Skip to content

Commit

Permalink
Use 'r+' with truncation when saving existing files on Windows (#42899)
Browse files Browse the repository at this point in the history
* 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: #6363

* adopt truncate for saving as admin
  • Loading branch information
seishun authored and bpasero committed Aug 20, 2018
1 parent ff8009d commit aaa778b
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 21 deletions.
21 changes: 10 additions & 11 deletions src/vs/code/node/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,18 +87,17 @@ export async function main(argv: string[]): Promise<any> {

// 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
Expand Down
21 changes: 11 additions & 10 deletions src/vs/workbench/services/files/electron-browser/fileService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 => {
Expand Down

0 comments on commit aaa778b

Please sign in to comment.