@@ -101,6 +101,10 @@ function nullCheck(path, callback) {
101101 return true ;
102102}
103103
104+ function isFd ( path ) {
105+ return ( path >>> 0 ) === path ;
106+ }
107+
104108// Static method to set the stats properties on a Stats object.
105109fs . Stats = function (
106110 dev ,
@@ -243,10 +247,18 @@ fs.readFile = function(path, options, callback_) {
243247 return ;
244248
245249 var context = new ReadFileContext ( callback , encoding ) ;
250+ context . isUserFd = isFd ( path ) ; // file descriptor ownership
246251 var req = new FSReqWrap ( ) ;
247252 req . context = context ;
248253 req . oncomplete = readFileAfterOpen ;
249254
255+ if ( context . isUserFd ) {
256+ process . nextTick ( function ( ) {
257+ req . oncomplete ( null , path ) ;
258+ } ) ;
259+ return ;
260+ }
261+
250262 binding . open ( pathModule . _makeLong ( path ) ,
251263 stringToFlags ( flag ) ,
252264 0o666 ,
@@ -257,6 +269,7 @@ const kReadFileBufferLength = 8 * 1024;
257269
258270function ReadFileContext ( callback , encoding ) {
259271 this . fd = undefined ;
272+ this . isUserFd = undefined ;
260273 this . size = undefined ;
261274 this . callback = callback ;
262275 this . buffers = null ;
@@ -293,6 +306,14 @@ ReadFileContext.prototype.close = function(err) {
293306 req . oncomplete = readFileAfterClose ;
294307 req . context = this ;
295308 this . err = err ;
309+
310+ if ( this . isUserFd ) {
311+ process . nextTick ( function ( ) {
312+ req . oncomplete ( null ) ;
313+ } ) ;
314+ return ;
315+ }
316+
296317 binding . close ( this . fd , req ) ;
297318} ;
298319
@@ -394,7 +415,8 @@ fs.readFileSync = function(path, options) {
394415 assertEncoding ( encoding ) ;
395416
396417 var flag = options . flag || 'r' ;
397- var fd = fs . openSync ( path , flag , 0o666 ) ;
418+ var isUserFd = isFd ( path ) ; // file descriptor ownership
419+ var fd = isUserFd ? path : fs . openSync ( path , flag , 0o666 ) ;
398420
399421 var st ;
400422 var size ;
@@ -404,7 +426,7 @@ fs.readFileSync = function(path, options) {
404426 size = st . isFile ( ) ? st . size : 0 ;
405427 threw = false ;
406428 } finally {
407- if ( threw ) fs . closeSync ( fd ) ;
429+ if ( threw && ! isUserFd ) fs . closeSync ( fd ) ;
408430 }
409431
410432 var pos = 0 ;
@@ -419,7 +441,7 @@ fs.readFileSync = function(path, options) {
419441 buffer = new Buffer ( size ) ;
420442 threw = false ;
421443 } finally {
422- if ( threw ) fs . closeSync ( fd ) ;
444+ if ( threw && ! isUserFd ) fs . closeSync ( fd ) ;
423445 }
424446 }
425447
@@ -442,14 +464,15 @@ fs.readFileSync = function(path, options) {
442464 }
443465 threw = false ;
444466 } finally {
445- if ( threw ) fs . closeSync ( fd ) ;
467+ if ( threw && ! isUserFd ) fs . closeSync ( fd ) ;
446468 }
447469
448470 pos += bytesRead ;
449471 done = ( bytesRead === 0 ) || ( size !== 0 && pos >= size ) ;
450472 }
451473
452- fs . closeSync ( fd ) ;
474+ if ( ! isUserFd )
475+ fs . closeSync ( fd ) ;
453476
454477 if ( size === 0 ) {
455478 // data was collected into the buffers list.
@@ -1096,25 +1119,33 @@ fs.futimesSync = function(fd, atime, mtime) {
10961119 binding . futimes ( fd , atime , mtime ) ;
10971120} ;
10981121
1099- function writeAll ( fd , buffer , offset , length , position , callback_ ) {
1122+ function writeAll ( fd , isUserFd , buffer , offset , length , position , callback_ ) {
11001123 var callback = maybeCallback ( arguments [ arguments . length - 1 ] ) ;
11011124
11021125 // write(fd, buffer, offset, length, position, callback)
11031126 fs . write ( fd , buffer , offset , length , position , function ( writeErr , written ) {
11041127 if ( writeErr ) {
1105- fs . close ( fd , function ( ) {
1128+ if ( isUserFd ) {
11061129 if ( callback ) callback ( writeErr ) ;
1107- } ) ;
1130+ } else {
1131+ fs . close ( fd , function ( ) {
1132+ if ( callback ) callback ( writeErr ) ;
1133+ } ) ;
1134+ }
11081135 } else {
11091136 if ( written === length ) {
1110- fs . close ( fd , callback ) ;
1137+ if ( isUserFd ) {
1138+ if ( callback ) callback ( null ) ;
1139+ } else {
1140+ fs . close ( fd , callback ) ;
1141+ }
11111142 } else {
11121143 offset += written ;
11131144 length -= written ;
11141145 if ( position !== null ) {
11151146 position += written ;
11161147 }
1117- writeAll ( fd , buffer , offset , length , position , callback ) ;
1148+ writeAll ( fd , isUserFd , buffer , offset , length , position , callback ) ;
11181149 }
11191150 }
11201151 } ) ;
@@ -1134,16 +1165,27 @@ fs.writeFile = function(path, data, options, callback_) {
11341165 assertEncoding ( options . encoding ) ;
11351166
11361167 var flag = options . flag || 'w' ;
1168+
1169+ if ( isFd ( path ) ) {
1170+ writeFd ( path , true ) ;
1171+ return ;
1172+ }
1173+
11371174 fs . open ( path , flag , options . mode , function ( openErr , fd ) {
11381175 if ( openErr ) {
11391176 if ( callback ) callback ( openErr ) ;
11401177 } else {
1141- var buffer = ( data instanceof Buffer ) ? data : new Buffer ( '' + data ,
1142- options . encoding || 'utf8' ) ;
1143- var position = / a / . test ( flag ) ? null : 0 ;
1144- writeAll ( fd , buffer , 0 , buffer . length , position , callback ) ;
1178+ writeFd ( fd , false ) ;
11451179 }
11461180 } ) ;
1181+
1182+ function writeFd ( fd , isUserFd ) {
1183+ var buffer = ( data instanceof Buffer ) ? data : new Buffer ( '' + data ,
1184+ options . encoding || 'utf8' ) ;
1185+ var position = / a / . test ( flag ) ? null : 0 ;
1186+
1187+ writeAll ( fd , isUserFd , buffer , 0 , buffer . length , position , callback ) ;
1188+ }
11471189} ;
11481190
11491191fs . writeFileSync = function ( path , data , options ) {
@@ -1158,7 +1200,9 @@ fs.writeFileSync = function(path, data, options) {
11581200 assertEncoding ( options . encoding ) ;
11591201
11601202 var flag = options . flag || 'w' ;
1161- var fd = fs . openSync ( path , flag , options . mode ) ;
1203+ var isUserFd = isFd ( path ) ; // file descriptor ownership
1204+ var fd = isUserFd ? path : fs . openSync ( path , flag , options . mode ) ;
1205+
11621206 if ( ! ( data instanceof Buffer ) ) {
11631207 data = new Buffer ( '' + data , options . encoding || 'utf8' ) ;
11641208 }
@@ -1175,7 +1219,7 @@ fs.writeFileSync = function(path, data, options) {
11751219 }
11761220 }
11771221 } finally {
1178- fs . closeSync ( fd ) ;
1222+ if ( ! isUserFd ) fs . closeSync ( fd ) ;
11791223 }
11801224} ;
11811225
@@ -1192,6 +1236,11 @@ fs.appendFile = function(path, data, options, callback_) {
11921236
11931237 if ( ! options . flag )
11941238 options = util . _extend ( { flag : 'a' } , options ) ;
1239+
1240+ // force append behavior when using a supplied file descriptor
1241+ if ( isFd ( path ) )
1242+ options . flag = 'a' ;
1243+
11951244 fs . writeFile ( path , data , options , callback ) ;
11961245} ;
11971246
@@ -1203,9 +1252,14 @@ fs.appendFileSync = function(path, data, options) {
12031252 } else if ( typeof options !== 'object' ) {
12041253 throwOptionsError ( options ) ;
12051254 }
1255+
12061256 if ( ! options . flag )
12071257 options = util . _extend ( { flag : 'a' } , options ) ;
12081258
1259+ // force append behavior when using a supplied file descriptor
1260+ if ( isFd ( path ) )
1261+ options . flag = 'a' ;
1262+
12091263 fs . writeFileSync ( path , data , options ) ;
12101264} ;
12111265
0 commit comments