Skip to content

Commit 0ba78d5

Browse files
committed
Close nodejs#2166 Close the fd in lchmod
1 parent 6e1e9e2 commit 0ba78d5

2 files changed

Lines changed: 86 additions & 3 deletions

File tree

lib/fs.js

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -459,13 +459,34 @@ if (constants.hasOwnProperty('O_SYMLINK')) {
459459
callback(err);
460460
return;
461461
}
462-
fs.fchmod(fd, mode, callback);
462+
// prefer to return the chmod error, if one occurs,
463+
// but still try to close, and report closing errors if they occur.
464+
fs.fchmod(fd, mode, function(err) {
465+
fs.close(fd, function(err2) {
466+
callback(err || err2);
467+
});
468+
});
463469
});
464470
};
465471

466472
fs.lchmodSync = function(path, mode) {
467473
var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK);
468-
return fs.fchmodSync(fd, mode);
474+
475+
// prefer to return the chmod error, if one occurs,
476+
// but still try to close, and report closing errors if they occur.
477+
var err, err2;
478+
try {
479+
var ret = fs.fchmodSync(fd, mode);
480+
} catch (er) {
481+
err = er;
482+
}
483+
try {
484+
fs.closeSync(fd);
485+
} catch (er) {
486+
err2 = er;
487+
}
488+
if (err || err2) throw (err || err2);
489+
return ret;
469490
};
470491
}
471492

test/simple/test-fs-chmod.js

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,40 @@ var mode_async;
2929
var mode_sync;
3030
var is_windows = process.platform === 'win32';
3131

32+
// Need to hijack fs.open/close to make sure that things
33+
// get closed once they're opened.
34+
fs._open = fs.open;
35+
fs._openSync = fs.openSync;
36+
fs.open = open;
37+
fs.openSync = openSync;
38+
fs._close = fs.close;
39+
fs._closeSync = fs.closeSync;
40+
fs.close = close;
41+
fs.closeSync = closeSync;
42+
43+
var openCount = 0;
44+
45+
function open() {
46+
openCount++;
47+
return fs._open.apply(fs, arguments);
48+
}
49+
50+
function openSync() {
51+
openCount++;
52+
return fs._openSync.apply(fs, arguments);
53+
}
54+
55+
function close() {
56+
openCount--;
57+
return fs._close.apply(fs, arguments);
58+
}
59+
60+
function closeSync() {
61+
openCount--;
62+
return fs._closeSync.apply(fs, arguments);
63+
}
64+
65+
3266
// On Windows chmod is only able to manipulate read-only bit
3367
if (is_windows) {
3468
mode_async = 0600; // read-write
@@ -87,12 +121,40 @@ fs.open(file, 'a', function(err, fd) {
87121
assert.equal(mode_sync, fs.fstatSync(fd).mode & 0777);
88122
}
89123
success_count++;
124+
fs.close(fd);
90125
}
91126
});
92127
});
93128

129+
// lchmod
130+
if (!is_windows) {
131+
var link = path.join(common.tmpDir, 'symbolic-link');
132+
133+
try {
134+
fs.unlinkSync(link);
135+
} catch (er) {}
136+
fs.symlinkSync(file, link);
137+
138+
fs.lchmod(link, mode_async, function(err) {
139+
if (err) {
140+
got_error = true;
141+
} else {
142+
console.log(fs.lstatSync(link).mode);
143+
assert.equal(mode_async, fs.lstatSync(link).mode & 0777);
144+
145+
fs.lchmodSync(link, mode_sync);
146+
assert.equal(mode_sync, fs.lstatSync(link).mode & 0777);
147+
success_count++;
148+
}
149+
});
150+
} else {
151+
success_count++;
152+
}
153+
154+
94155
process.on('exit', function() {
95-
assert.equal(2, success_count);
156+
assert.equal(3, success_count);
157+
assert.equal(0, openCount);
96158
assert.equal(false, got_error);
97159
});
98160

0 commit comments

Comments
 (0)