From aaa778b5e24c1af3aac43e840dce39ed861423f0 Mon Sep 17 00:00:00 2001 From: Nikolai Vavilov Date: Mon, 20 Aug 2018 19:55:12 +0300 Subject: [PATCH] Use 'r+' with truncation when saving existing files on Windows (#42899) * Use 'r+' with truncation when saving existing files on Windows Opening a file with 'w' flag removes its alternate data streams. To prevent this, extend the logic used for hidden files to all existing files. Fixes: https://github.com/Microsoft/vscode/issues/6363 * adopt truncate for saving as admin --- src/vs/code/node/cli.ts | 21 +++++++++---------- .../files/electron-browser/fileService.ts | 21 ++++++++++--------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/vs/code/node/cli.ts b/src/vs/code/node/cli.ts index 3ca3fd9ec94..a5f35fb14c1 100644 --- a/src/vs/code/node/cli.ts +++ b/src/vs/code/node/cli.ts @@ -87,18 +87,17 @@ export async function main(argv: string[]): Promise { // Write source to target const data = fs.readFileSync(source); - try { + if (isWindows) { + // On Windows we use a different strategy of saving the file + // by first truncating the file and then writing with r+ mode. + // This helps to save hidden files on Windows + // (see https://github.com/Microsoft/vscode/issues/931) and + // prevent removing alternate data streams + // (see https://github.com/Microsoft/vscode/issues/6363) + fs.truncateSync(target, 0); + writeFileAndFlushSync(target, data, { flag: 'r+' }); + } else { writeFileAndFlushSync(target, data); - } catch (error) { - // On Windows and if the file exists with an EPERM error, we try a different strategy of saving the file - // by first truncating the file and then writing with r+ mode. This helps to save hidden files on Windows - // (see https://github.com/Microsoft/vscode/issues/931) - if (isWindows && error.code === 'EPERM') { - fs.truncateSync(target, 0); - writeFileAndFlushSync(target, data, { flag: 'r+' }); - } else { - throw error; - } } // Restore previous mode as needed diff --git a/src/vs/workbench/services/files/electron-browser/fileService.ts b/src/vs/workbench/services/files/electron-browser/fileService.ts index b91d4371d27..44a594f32b3 100644 --- a/src/vs/workbench/services/files/electron-browser/fileService.ts +++ b/src/vs/workbench/services/files/electron-browser/fileService.ts @@ -607,22 +607,23 @@ export class FileService extends Disposable implements IFileService { return addBomPromise.then(addBom => { // 4.) set contents and resolve - return this.doSetContentsAndResolve(resource, absolutePath, value, addBom, encodingToWrite).then(void 0, error => { - if (!exists || error.code !== 'EPERM' || !isWindows) { - return TPromise.wrapError(error); - } + if (!exists || !isWindows) { + return this.doSetContentsAndResolve(resource, absolutePath, value, addBom, encodingToWrite); + } - // On Windows and if the file exists with an EPERM error, we try a different strategy of saving the file - // by first truncating the file and then writing with r+ mode. This helps to save hidden files on Windows - // (see https://github.com/Microsoft/vscode/issues/931) + // On Windows and if the file exists, we use a different strategy of saving the file + // by first truncating the file and then writing with r+ mode. This helps to save hidden files on Windows + // (see https://github.com/Microsoft/vscode/issues/931) and prevent removing alternate data streams + // (see https://github.com/Microsoft/vscode/issues/6363) + else { - // 5.) truncate + // 4.) truncate return pfs.truncate(absolutePath, 0).then(() => { - // 6.) set contents (this time with r+ mode) and resolve again + // 5.) set contents (with r+ mode) and resolve return this.doSetContentsAndResolve(resource, absolutePath, value, addBom, encodingToWrite, { flag: 'r+' }); }); - }); + } }); }); }).then(null, error => {