From 8fc9e3eb2a76e80daa58c219f49c8b6fc1f6efaa Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 11 Apr 2019 12:47:06 +0200 Subject: [PATCH] files2 - fix permission denied issues --- .../files2/node/diskFileSystemProvider.ts | 2 +- .../services/textfile/node/textFileService.ts | 45 ++++++++++++++----- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/vs/workbench/services/files2/node/diskFileSystemProvider.ts b/src/vs/workbench/services/files2/node/diskFileSystemProvider.ts index 56ea34c31cb..c0b013d37e0 100644 --- a/src/vs/workbench/services/files2/node/diskFileSystemProvider.ts +++ b/src/vs/workbench/services/files2/node/diskFileSystemProvider.ts @@ -487,7 +487,7 @@ export class DiskFileSystemProvider extends Disposable implements IFileSystemPro code = FileSystemProviderErrorCode.FileExists; break; case 'EPERM': - case 'EACCESS': + case 'EACCES': code = FileSystemProviderErrorCode.NoPermissions; break; default: diff --git a/src/vs/workbench/services/textfile/node/textFileService.ts b/src/vs/workbench/services/textfile/node/textFileService.ts index fe7d072486e..a56679c4009 100644 --- a/src/vs/workbench/services/textfile/node/textFileService.ts +++ b/src/vs/workbench/services/textfile/node/textFileService.ts @@ -4,11 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import { tmpdir } from 'os'; +import { localize } from 'vs/nls'; import { TextFileService } from 'vs/workbench/services/textfile/common/textFileService'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { URI } from 'vs/base/common/uri'; -import { ITextSnapshot, IWriteTextFileOptions, IFileStatWithMetadata, IResourceEncoding, IResolveContentOptions, IFileService, stringToSnapshot, ICreateFileOptions } from 'vs/platform/files/common/files'; +import { ITextSnapshot, IWriteTextFileOptions, IFileStatWithMetadata, IResourceEncoding, IResolveContentOptions, IFileService, stringToSnapshot, ICreateFileOptions, FileOperationError, FileOperationResult } from 'vs/platform/files/common/files'; import { Schemas } from 'vs/base/common/network'; import { exists, stat, chmod, rimraf } from 'vs/base/node/pfs'; import { join, dirname } from 'vs/base/common/path'; @@ -69,16 +70,41 @@ export class NodeTextFileService extends TextFileService { return this.writeElevated(resource, value, options); } - // check for encoding - const { encoding, addBOM } = await this.encoding.getWriteEncoding(resource, options); + try { - // return to parent when encoding is standard - if (encoding === UTF8 && !addBOM) { - return super.write(resource, value, options); + // check for encoding + const { encoding, addBOM } = await this.encoding.getWriteEncoding(resource, options); + + // return to parent when encoding is standard + if (encoding === UTF8 && !addBOM) { + return await super.write(resource, value, options); + } + + // otherwise save with encoding + else { + return await this.fileService.writeFile(resource, this.getEncodedReadable(value, encoding, addBOM), options); + } + } catch (error) { + + // In case of permission denied, we need to check for readonly + if ((error).fileOperationResult === FileOperationResult.FILE_PERMISSION_DENIED) { + let isReadonly = false; + try { + const fileStat = await stat(resource.fsPath); + if (!(fileStat.mode & 128)) { + isReadonly = true; + } + } catch (error) { + // ignore - rethrow original error + } + + if (isReadonly) { + throw new FileOperationError(localize('fileReadOnlyError', "File is Read Only"), FileOperationResult.FILE_READ_ONLY, options); + } + } + + throw error; } - - // otherwise save with encoding - return this.fileService.writeFile(resource, this.getEncodedReadable(value, encoding, addBOM), options); } private getEncodedReadable(value: string | ITextSnapshot, encoding: string, addBOM: boolean): VSBufferReadable { @@ -165,7 +191,6 @@ export class NodeTextFileService extends TextFileService { bytesRead += res.byteLength; return VSBuffer.wrap(res); } - } }; }