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.mustCall((err) => { 84 assert.ifError(err); 85 86 if (common.isWindows) { 87 assert.ok((fs.statSync(file1).mode & 0o777) & mode_async); 88 } else { 89 assert.strictEqual(fs.statSync(file1).mode & 0o777, mode_async); 90 } 91 92 fs.chmodSync(file1, mode_sync); 93 if (common.isWindows) { 94 assert.ok((fs.statSync(file1).mode & 0o777) & mode_sync); 95 } else { 96 assert.strictEqual(fs.statSync(file1).mode & 0o777, mode_sync); 97 } 98})); 99 100fs.open(file2, 'w', common.mustCall((err, fd) => { 101 assert.ifError(err); 102 103 fs.fchmod(fd, mode_async.toString(8), common.mustCall((err) => { 104 assert.ifError(err); 105 106 if (common.isWindows) { 107 assert.ok((fs.fstatSync(fd).mode & 0o777) & mode_async); 108 } else { 109 assert.strictEqual(fs.fstatSync(fd).mode & 0o777, mode_async); 110 } 111 112 assert.throws( 113 () => fs.fchmod(fd, {}), 114 { 115 code: 'ERR_INVALID_ARG_VALUE', 116 name: 'TypeError', 117 message: 'The argument \'mode\' must be a 32-bit unsigned integer ' + 118 'or an octal string. Received {}' 119 } 120 ); 121 122 fs.fchmodSync(fd, mode_sync); 123 if (common.isWindows) { 124 assert.ok((fs.fstatSync(fd).mode & 0o777) & mode_sync); 125 } else { 126 assert.strictEqual(fs.fstatSync(fd).mode & 0o777, mode_sync); 127 } 128 129 fs.close(fd, assert.ifError); 130 })); 131})); 132 133// lchmod 134if (fs.lchmod) { 135 const link = path.join(tmpdir.path, 'symbolic-link'); 136 137 fs.symlinkSync(file2, link); 138 139 fs.lchmod(link, mode_async, common.mustCall((err) => { 140 assert.ifError(err); 141 142 assert.strictEqual(fs.lstatSync(link).mode & 0o777, mode_async); 143 144 fs.lchmodSync(link, mode_sync); 145 assert.strictEqual(fs.lstatSync(link).mode & 0o777, mode_sync); 146 147 })); 148} 149 150[false, 1, {}, [], null, undefined].forEach((input) => { 151 const errObj = { 152 code: 'ERR_INVALID_ARG_TYPE', 153 name: 'TypeError', 154 message: 'The "path" argument must be of type string or an instance ' + 155 'of Buffer or URL.' + 156 common.invalidArgTypeHelper(input) 157 }; 158 assert.throws(() => fs.chmod(input, 1, common.mustNotCall()), errObj); 159 assert.throws(() => fs.chmodSync(input, 1), errObj); 160}); 161 162process.on('exit', function() { 163 assert.strictEqual(openCount, 0); 164}); 165