1// Copyright Joyent, Inc. and other Node contributors. 2// 3// Permission is hereby granted, free of charge, to any person obtaining a 4// copy of this software and associated documentation files (the 5// "Software"), to deal in the Software without restriction, including 6// without limitation the rights to use, copy, modify, merge, publish, 7// distribute, sublicense, and/or sell copies of the Software, and to permit 8// persons to whom the Software is furnished to do so, subject to the 9// following conditions: 10// 11// The above copyright notice and this permission notice shall be included 12// in all copies or substantial portions of the Software. 13// 14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20// USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22'use strict'; 23const common = require('../common'); 24const assert = require('assert'); 25const path = require('path'); 26const fs = require('fs'); 27 28let mode_async; 29let mode_sync; 30 31// Need to hijack fs.open/close to make sure that things 32// get closed once they're opened. 33fs._open = fs.open; 34fs._openSync = fs.openSync; 35fs.open = open; 36fs.openSync = openSync; 37fs._close = fs.close; 38fs._closeSync = fs.closeSync; 39fs.close = close; 40fs.closeSync = closeSync; 41 42let openCount = 0; 43 44function open() { 45 openCount++; 46 return fs._open.apply(fs, arguments); 47} 48 49function openSync() { 50 openCount++; 51 return fs._openSync.apply(fs, arguments); 52} 53 54function close() { 55 openCount--; 56 return fs._close.apply(fs, arguments); 57} 58 59function closeSync() { 60 openCount--; 61 return fs._closeSync.apply(fs, arguments); 62} 63 64 65// On Windows chmod is only able to manipulate write permission 66if (common.isWindows) { 67 mode_async = 0o400; // read-only 68 mode_sync = 0o600; // read-write 69} else { 70 mode_async = 0o777; 71 mode_sync = 0o644; 72} 73 74const tmpdir = require('../common/tmpdir'); 75tmpdir.refresh(); 76 77const file1 = path.join(tmpdir.path, 'a.js'); 78const file2 = path.join(tmpdir.path, 'a1.js'); 79 80// Create file1. 81fs.closeSync(fs.openSync(file1, 'w')); 82 83fs.chmod(file1, mode_async.toString(8), common.mustSucceed(() => { 84 if (common.isWindows) { 85 assert.ok((fs.statSync(file1).mode & 0o777) & mode_async); 86 } else { 87 assert.strictEqual(fs.statSync(file1).mode & 0o777, mode_async); 88 } 89 90 fs.chmodSync(file1, mode_sync); 91 if (common.isWindows) { 92 assert.ok((fs.statSync(file1).mode & 0o777) & mode_sync); 93 } else { 94 assert.strictEqual(fs.statSync(file1).mode & 0o777, mode_sync); 95 } 96})); 97 98fs.open(file2, 'w', common.mustSucceed((fd) => { 99 fs.fchmod(fd, mode_async.toString(8), common.mustSucceed(() => { 100 if (common.isWindows) { 101 assert.ok((fs.fstatSync(fd).mode & 0o777) & mode_async); 102 } else { 103 assert.strictEqual(fs.fstatSync(fd).mode & 0o777, mode_async); 104 } 105 106 assert.throws( 107 () => fs.fchmod(fd, {}), 108 { 109 code: 'ERR_INVALID_ARG_VALUE', 110 name: 'TypeError', 111 message: 'The argument \'mode\' must be a 32-bit unsigned integer ' + 112 'or an octal string. Received {}' 113 } 114 ); 115 116 fs.fchmodSync(fd, mode_sync); 117 if (common.isWindows) { 118 assert.ok((fs.fstatSync(fd).mode & 0o777) & mode_sync); 119 } else { 120 assert.strictEqual(fs.fstatSync(fd).mode & 0o777, mode_sync); 121 } 122 123 fs.close(fd, assert.ifError); 124 })); 125})); 126 127// lchmod 128if (fs.lchmod) { 129 const link = path.join(tmpdir.path, 'symbolic-link'); 130 131 fs.symlinkSync(file2, link); 132 133 fs.lchmod(link, mode_async, common.mustSucceed(() => { 134 assert.strictEqual(fs.lstatSync(link).mode & 0o777, mode_async); 135 136 fs.lchmodSync(link, mode_sync); 137 assert.strictEqual(fs.lstatSync(link).mode & 0o777, mode_sync); 138 139 })); 140} 141 142[false, 1, {}, [], null, undefined].forEach((input) => { 143 const errObj = { 144 code: 'ERR_INVALID_ARG_TYPE', 145 name: 'TypeError', 146 message: 'The "path" argument must be of type string or an instance ' + 147 'of Buffer or URL.' + 148 common.invalidArgTypeHelper(input) 149 }; 150 assert.throws(() => fs.chmod(input, 1, common.mustNotCall()), errObj); 151 assert.throws(() => fs.chmodSync(input, 1), errObj); 152}); 153 154process.on('exit', function() { 155 assert.strictEqual(openCount, 0); 156}); 157