@@ -101,6 +101,10 @@ function nullCheck(path, callback) {
101
101
return true ;
102
102
}
103
103
104
+ function isFd ( path ) {
105
+ return ( path >>> 0 ) === path ;
106
+ }
107
+
104
108
// Static method to set the stats properties on a Stats object.
105
109
fs . Stats = function (
106
110
dev ,
@@ -243,10 +247,18 @@ fs.readFile = function(path, options, callback_) {
243
247
return ;
244
248
245
249
var context = new ReadFileContext ( callback , encoding ) ;
250
+ context . isUserFd = isFd ( path ) ; // file descriptor ownership
246
251
var req = new FSReqWrap ( ) ;
247
252
req . context = context ;
248
253
req . oncomplete = readFileAfterOpen ;
249
254
255
+ if ( context . isUserFd ) {
256
+ process . nextTick ( function ( ) {
257
+ req . oncomplete ( null , path ) ;
258
+ } ) ;
259
+ return ;
260
+ }
261
+
250
262
binding . open ( pathModule . _makeLong ( path ) ,
251
263
stringToFlags ( flag ) ,
252
264
0o666 ,
@@ -257,6 +269,7 @@ const kReadFileBufferLength = 8 * 1024;
257
269
258
270
function ReadFileContext ( callback , encoding ) {
259
271
this . fd = undefined ;
272
+ this . isUserFd = undefined ;
260
273
this . size = undefined ;
261
274
this . callback = callback ;
262
275
this . buffers = null ;
@@ -293,6 +306,14 @@ ReadFileContext.prototype.close = function(err) {
293
306
req . oncomplete = readFileAfterClose ;
294
307
req . context = this ;
295
308
this . err = err ;
309
+
310
+ if ( this . isUserFd ) {
311
+ process . nextTick ( function ( ) {
312
+ req . oncomplete ( null ) ;
313
+ } ) ;
314
+ return ;
315
+ }
316
+
296
317
binding . close ( this . fd , req ) ;
297
318
} ;
298
319
@@ -394,7 +415,8 @@ fs.readFileSync = function(path, options) {
394
415
assertEncoding ( encoding ) ;
395
416
396
417
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 ) ;
398
420
399
421
var st ;
400
422
var size ;
@@ -404,7 +426,7 @@ fs.readFileSync = function(path, options) {
404
426
size = st . isFile ( ) ? st . size : 0 ;
405
427
threw = false ;
406
428
} finally {
407
- if ( threw ) fs . closeSync ( fd ) ;
429
+ if ( threw && ! isUserFd ) fs . closeSync ( fd ) ;
408
430
}
409
431
410
432
var pos = 0 ;
@@ -419,7 +441,7 @@ fs.readFileSync = function(path, options) {
419
441
buffer = new Buffer ( size ) ;
420
442
threw = false ;
421
443
} finally {
422
- if ( threw ) fs . closeSync ( fd ) ;
444
+ if ( threw && ! isUserFd ) fs . closeSync ( fd ) ;
423
445
}
424
446
}
425
447
@@ -442,14 +464,15 @@ fs.readFileSync = function(path, options) {
442
464
}
443
465
threw = false ;
444
466
} finally {
445
- if ( threw ) fs . closeSync ( fd ) ;
467
+ if ( threw && ! isUserFd ) fs . closeSync ( fd ) ;
446
468
}
447
469
448
470
pos += bytesRead ;
449
471
done = ( bytesRead === 0 ) || ( size !== 0 && pos >= size ) ;
450
472
}
451
473
452
- fs . closeSync ( fd ) ;
474
+ if ( ! isUserFd )
475
+ fs . closeSync ( fd ) ;
453
476
454
477
if ( size === 0 ) {
455
478
// data was collected into the buffers list.
@@ -1096,25 +1119,33 @@ fs.futimesSync = function(fd, atime, mtime) {
1096
1119
binding . futimes ( fd , atime , mtime ) ;
1097
1120
} ;
1098
1121
1099
- function writeAll ( fd , buffer , offset , length , position , callback_ ) {
1122
+ function writeAll ( fd , isUserFd , buffer , offset , length , position , callback_ ) {
1100
1123
var callback = maybeCallback ( arguments [ arguments . length - 1 ] ) ;
1101
1124
1102
1125
// write(fd, buffer, offset, length, position, callback)
1103
1126
fs . write ( fd , buffer , offset , length , position , function ( writeErr , written ) {
1104
1127
if ( writeErr ) {
1105
- fs . close ( fd , function ( ) {
1128
+ if ( isUserFd ) {
1106
1129
if ( callback ) callback ( writeErr ) ;
1107
- } ) ;
1130
+ } else {
1131
+ fs . close ( fd , function ( ) {
1132
+ if ( callback ) callback ( writeErr ) ;
1133
+ } ) ;
1134
+ }
1108
1135
} else {
1109
1136
if ( written === length ) {
1110
- fs . close ( fd , callback ) ;
1137
+ if ( isUserFd ) {
1138
+ if ( callback ) callback ( null ) ;
1139
+ } else {
1140
+ fs . close ( fd , callback ) ;
1141
+ }
1111
1142
} else {
1112
1143
offset += written ;
1113
1144
length -= written ;
1114
1145
if ( position !== null ) {
1115
1146
position += written ;
1116
1147
}
1117
- writeAll ( fd , buffer , offset , length , position , callback ) ;
1148
+ writeAll ( fd , isUserFd , buffer , offset , length , position , callback ) ;
1118
1149
}
1119
1150
}
1120
1151
} ) ;
@@ -1134,16 +1165,27 @@ fs.writeFile = function(path, data, options, callback_) {
1134
1165
assertEncoding ( options . encoding ) ;
1135
1166
1136
1167
var flag = options . flag || 'w' ;
1168
+
1169
+ if ( isFd ( path ) ) {
1170
+ writeFd ( path , true ) ;
1171
+ return ;
1172
+ }
1173
+
1137
1174
fs . open ( path , flag , options . mode , function ( openErr , fd ) {
1138
1175
if ( openErr ) {
1139
1176
if ( callback ) callback ( openErr ) ;
1140
1177
} 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 ) ;
1145
1179
}
1146
1180
} ) ;
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
+ }
1147
1189
} ;
1148
1190
1149
1191
fs . writeFileSync = function ( path , data , options ) {
@@ -1158,7 +1200,9 @@ fs.writeFileSync = function(path, data, options) {
1158
1200
assertEncoding ( options . encoding ) ;
1159
1201
1160
1202
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
+
1162
1206
if ( ! ( data instanceof Buffer ) ) {
1163
1207
data = new Buffer ( '' + data , options . encoding || 'utf8' ) ;
1164
1208
}
@@ -1175,7 +1219,7 @@ fs.writeFileSync = function(path, data, options) {
1175
1219
}
1176
1220
}
1177
1221
} finally {
1178
- fs . closeSync ( fd ) ;
1222
+ if ( ! isUserFd ) fs . closeSync ( fd ) ;
1179
1223
}
1180
1224
} ;
1181
1225
@@ -1192,6 +1236,11 @@ fs.appendFile = function(path, data, options, callback_) {
1192
1236
1193
1237
if ( ! options . flag )
1194
1238
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
+
1195
1244
fs . writeFile ( path , data , options , callback ) ;
1196
1245
} ;
1197
1246
@@ -1203,9 +1252,14 @@ fs.appendFileSync = function(path, data, options) {
1203
1252
} else if ( typeof options !== 'object' ) {
1204
1253
throwOptionsError ( options ) ;
1205
1254
}
1255
+
1206
1256
if ( ! options . flag )
1207
1257
options = util . _extend ( { flag : 'a' } , options ) ;
1208
1258
1259
+ // force append behavior when using a supplied file descriptor
1260
+ if ( isFd ( path ) )
1261
+ options . flag = 'a' ;
1262
+
1209
1263
fs . writeFileSync ( path , data , options ) ;
1210
1264
} ;
1211
1265
0 commit comments