UNPKG

42.1 kBJavaScriptView Raw
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// Maintainers, keep in mind that octal literals are not allowed
23// in strict mode. Use the decimal value and add a comment with
24// the octal value. Example:
25//
26// var mode = 438; /* mode=0666 */
27
28var util = require('util');
29var pathModule = require('path');
30
31var binding = process.binding('fs');
32var constants = process.binding('constants');
33var fs = exports;
34var Stream = require('stream').Stream;
35var EventEmitter = require('events').EventEmitter;
36
37var kMinPoolSpace = 128;
38var kPoolSize = 40 * 1024;
39
40var O_APPEND = constants.O_APPEND || 0;
41var O_CREAT = constants.O_CREAT || 0;
42var O_DIRECTORY = constants.O_DIRECTORY || 0;
43var O_EXCL = constants.O_EXCL || 0;
44var O_NOCTTY = constants.O_NOCTTY || 0;
45var O_NOFOLLOW = constants.O_NOFOLLOW || 0;
46var O_RDONLY = constants.O_RDONLY || 0;
47var O_RDWR = constants.O_RDWR || 0;
48var O_SYMLINK = constants.O_SYMLINK || 0;
49var O_SYNC = constants.O_SYNC || 0;
50var O_TRUNC = constants.O_TRUNC || 0;
51var O_WRONLY = constants.O_WRONLY || 0;
52
53var isWindows = process.platform === 'win32';
54
55fs.Stats = binding.Stats;
56
57fs.Stats.prototype._checkModeProperty = function(property) {
58 return ((this.mode & constants.S_IFMT) === property);
59};
60
61fs.Stats.prototype.isDirectory = function() {
62 return this._checkModeProperty(constants.S_IFDIR);
63};
64
65fs.Stats.prototype.isFile = function() {
66 return this._checkModeProperty(constants.S_IFREG);
67};
68
69fs.Stats.prototype.isBlockDevice = function() {
70 return this._checkModeProperty(constants.S_IFBLK);
71};
72
73fs.Stats.prototype.isCharacterDevice = function() {
74 return this._checkModeProperty(constants.S_IFCHR);
75};
76
77fs.Stats.prototype.isSymbolicLink = function() {
78 return this._checkModeProperty(constants.S_IFLNK);
79};
80
81fs.Stats.prototype.isFIFO = function() {
82 return this._checkModeProperty(constants.S_IFIFO);
83};
84
85fs.Stats.prototype.isSocket = function() {
86 return this._checkModeProperty(constants.S_IFSOCK);
87};
88
89fs.exists = function(path, callback) {
90 binding.stat(pathModule._makeLong(path), function(err, stats) {
91 if (callback) callback(err ? false : true);
92 });
93};
94
95fs.existsSync = function(path) {
96 try {
97 binding.stat(pathModule._makeLong(path));
98 return true;
99 } catch (e) {
100 return false;
101 }
102};
103
104fs.readFile = function(path, encoding_) {
105 var encoding = typeof(encoding_) === 'string' ? encoding_ : null;
106 var callback = arguments[arguments.length - 1];
107 if (typeof(callback) !== 'function') callback = function() {};
108
109 // first, stat the file, so we know the size.
110 var size;
111 var buffer; // single buffer with file data
112 var buffers; // list for when size is unknown
113 var pos = 0;
114 var fd;
115
116 fs.open(path, constants.O_RDONLY, 438 /*=0666*/, function(er, fd_) {
117 if (er) return callback(er);
118 fd = fd_;
119
120 fs.fstat(fd, function(er, st) {
121 if (er) return callback(er);
122 size = st.size;
123 if (size === 0) {
124 // the kernel lies about many files.
125 // Go ahead and try to read some bytes.
126 buffers = [];
127 return read();
128 }
129
130 buffer = new Buffer(size);
131 read();
132 });
133 });
134
135 function read() {
136 if (size === 0) {
137 buffer = new Buffer(8192);
138 fs.read(fd, buffer, 0, 8192, -1, afterRead);
139 } else {
140 fs.read(fd, buffer, pos, size - pos, -1, afterRead);
141 }
142 }
143
144 function afterRead(er, bytesRead) {
145 if (er) {
146 return fs.close(fd, function(er2) {
147 return callback(er);
148 });
149 }
150
151 if (bytesRead === 0) {
152 return close();
153 }
154
155 pos += bytesRead;
156 if (size !== 0) {
157 if (pos === size) close();
158 else read();
159 } else {
160 // unknown size, just read until we don't get bytes.
161 buffers.push(buffer.slice(0, bytesRead));
162 read();
163 }
164 }
165
166 function close() {
167 fs.close(fd, function(er) {
168 if (size === 0) {
169 // collected the data into the buffers list.
170 buffer = Buffer.concat(buffers, pos);
171 } else if (pos < size) {
172 buffer = buffer.slice(0, pos);
173 }
174
175 if (encoding) buffer = buffer.toString(encoding);
176 return callback(er, buffer);
177 });
178 }
179};
180
181fs.readFileSync = function(path, encoding) {
182 var fd = fs.openSync(path, constants.O_RDONLY, 438 /*=0666*/);
183
184 var size;
185 var threw = true;
186 try {
187 size = fs.fstatSync(fd).size;
188 threw = false;
189 } finally {
190 if (threw) fs.closeSync(fd);
191 }
192
193 var pos = 0;
194 var buffer; // single buffer with file data
195 var buffers; // list for when size is unknown
196
197 if (size === 0) {
198 buffers = [];
199 } else {
200 buffer = new Buffer(size);
201 }
202
203 var done = false;
204 while (!done) {
205 var threw = true;
206 try {
207 if (size !== 0) {
208 var bytesRead = fs.readSync(fd, buffer, pos, size - pos);
209 } else {
210 // the kernel lies about many files.
211 // Go ahead and try to read some bytes.
212 buffer = new Buffer(8192);
213 var bytesRead = fs.readSync(fd, buffer, 0, 8192);
214 if (bytesRead) {
215 buffers.push(buffer.slice(0, bytesRead));
216 }
217 }
218 threw = false;
219 } finally {
220 if (threw) fs.closeSync(fd);
221 }
222
223 pos += bytesRead;
224 done = (bytesRead === 0) || (size !== 0 && pos >= size);
225 }
226
227 fs.closeSync(fd);
228
229 if (size === 0) {
230 // data was collected into the buffers list.
231 buffer = Buffer.concat(buffers, pos);
232 } else if (pos < size) {
233 buffer = buffer.slice(0, pos);
234 }
235
236 if (encoding) buffer = buffer.toString(encoding);
237 return buffer;
238};
239
240
241// Used by binding.open and friends
242function stringToFlags(flag) {
243 // Only mess with strings
244 if (typeof flag !== 'string') {
245 return flag;
246 }
247
248 // O_EXCL is mandated by POSIX, Windows supports it too.
249 // Let's add a check anyway, just in case.
250 if (!O_EXCL && ~flag.indexOf('x')) {
251 throw errnoException('ENOSYS', 'fs.open(O_EXCL)');
252 }
253
254 switch (flag) {
255 case 'r' : return O_RDONLY;
256 case 'rs' : return O_RDONLY | O_SYNC;
257 case 'r+' : return O_RDWR;
258 case 'rs+' : return O_RDWR | O_SYNC;
259
260 case 'w' : return O_TRUNC | O_CREAT | O_WRONLY;
261 case 'wx' : // fall through
262 case 'xw' : return O_TRUNC | O_CREAT | O_WRONLY | O_EXCL;
263
264 case 'w+' : return O_TRUNC | O_CREAT | O_RDWR;
265 case 'wx+': // fall through
266 case 'xw+': return O_TRUNC | O_CREAT | O_RDWR | O_EXCL;
267
268 case 'a' : return O_APPEND | O_CREAT | O_WRONLY;
269 case 'ax' : // fall through
270 case 'xa' : return O_APPEND | O_CREAT | O_WRONLY | O_EXCL;
271
272 case 'a+' : return O_APPEND | O_CREAT | O_RDWR;
273 case 'ax+': // fall through
274 case 'xa+': return O_APPEND | O_CREAT | O_RDWR | O_EXCL;
275 }
276
277 throw new Error('Unknown file open flag: ' + flag);
278}
279
280// exported but hidden, only used by test/simple/test-fs-open-flags.js
281Object.defineProperty(exports, '_stringToFlags', {
282 enumerable: false,
283 value: stringToFlags
284});
285
286
287// Ensure that callbacks run in the global context. Only use this function
288// for callbacks that are passed to the binding layer, callbacks that are
289// invoked from JS already run in the proper scope.
290function makeCallback(cb) {
291 if (typeof cb !== 'function') {
292 // faster than returning a ref to a global no-op function
293 return function() {};
294 }
295
296 return function() {
297 return cb.apply(null, arguments);
298 };
299}
300
301
302// Yes, the follow could be easily DRYed up but I provide the explicit
303// list to make the arguments clear.
304
305fs.close = function(fd, callback) {
306 binding.close(fd, makeCallback(callback));
307};
308
309fs.closeSync = function(fd) {
310 return binding.close(fd);
311};
312
313function modeNum(m, def) {
314 switch (typeof m) {
315 case 'number': return m;
316 case 'string': return parseInt(m, 8);
317 default:
318 if (def) {
319 return modeNum(def);
320 } else {
321 return undefined;
322 }
323 }
324}
325
326fs.open = function(path, flags, mode, callback) {
327 callback = makeCallback(arguments[arguments.length - 1]);
328 mode = modeNum(mode, 438 /*=0666*/);
329
330 binding.open(pathModule._makeLong(path),
331 stringToFlags(flags),
332 mode,
333 callback);
334};
335
336fs.openSync = function(path, flags, mode) {
337 mode = modeNum(mode, 438 /*=0666*/);
338 return binding.open(pathModule._makeLong(path), stringToFlags(flags), mode);
339};
340
341fs.read = function(fd, buffer, offset, length, position, callback) {
342 if (!Buffer.isBuffer(buffer)) {
343 // legacy string interface (fd, length, position, encoding, callback)
344 var cb = arguments[4],
345 encoding = arguments[3];
346 position = arguments[2];
347 length = arguments[1];
348 buffer = new Buffer(length);
349 offset = 0;
350
351 callback = function(err, bytesRead) {
352 if (!cb) return;
353
354 var str = (bytesRead > 0) ? buffer.toString(encoding, 0, bytesRead) : '';
355
356 (cb)(err, str, bytesRead);
357 };
358 }
359
360 function wrapper(err, bytesRead) {
361 // Retain a reference to buffer so that it can't be GC'ed too soon.
362 callback && callback(err, bytesRead || 0, buffer);
363 }
364
365 binding.read(fd, buffer, offset, length, position, wrapper);
366};
367
368fs.readSync = function(fd, buffer, offset, length, position) {
369 var legacy = false;
370 if (!Buffer.isBuffer(buffer)) {
371 // legacy string interface (fd, length, position, encoding, callback)
372 legacy = true;
373 var encoding = arguments[3];
374 position = arguments[2];
375 length = arguments[1];
376 buffer = new Buffer(length);
377
378 offset = 0;
379 }
380
381 var r = binding.read(fd, buffer, offset, length, position);
382 if (!legacy) {
383 return r;
384 }
385
386 var str = (r > 0) ? buffer.toString(encoding, 0, r) : '';
387 return [str, r];
388};
389
390fs.write = function(fd, buffer, offset, length, position, callback) {
391 if (!Buffer.isBuffer(buffer)) {
392 // legacy string interface (fd, data, position, encoding, callback)
393 callback = arguments[4];
394 position = arguments[2];
395
396 buffer = new Buffer('' + arguments[1], arguments[3]);
397 offset = 0;
398 length = buffer.length;
399 }
400
401 if (!length) {
402 if (typeof callback == 'function') {
403 process.nextTick(function() {
404 callback(undefined, 0);
405 });
406 }
407 return;
408 }
409
410 function wrapper(err, written) {
411 // Retain a reference to buffer so that it can't be GC'ed too soon.
412 callback && callback(err, written || 0, buffer);
413 }
414
415 binding.write(fd, buffer, offset, length, position, wrapper);
416};
417
418fs.writeSync = function(fd, buffer, offset, length, position) {
419 if (!Buffer.isBuffer(buffer)) {
420 // legacy string interface (fd, data, position, encoding)
421 position = arguments[2];
422
423 buffer = new Buffer('' + arguments[1], arguments[3]);
424 offset = 0;
425 length = buffer.length;
426 }
427 if (!length) return 0;
428
429 return binding.write(fd, buffer, offset, length, position);
430};
431
432fs.rename = function(oldPath, newPath, callback) {
433 binding.rename(pathModule._makeLong(oldPath),
434 pathModule._makeLong(newPath),
435 makeCallback(callback));
436};
437
438fs.renameSync = function(oldPath, newPath) {
439 return binding.rename(pathModule._makeLong(oldPath),
440 pathModule._makeLong(newPath));
441};
442
443fs.truncate = function(fd, len, callback) {
444 binding.truncate(fd, len, makeCallback(callback));
445};
446
447fs.truncateSync = function(fd, len) {
448 return binding.truncate(fd, len);
449};
450
451fs.rmdir = function(path, callback) {
452 binding.rmdir(pathModule._makeLong(path), makeCallback(callback));
453};
454
455fs.rmdirSync = function(path) {
456 return binding.rmdir(pathModule._makeLong(path));
457};
458
459fs.fdatasync = function(fd, callback) {
460 binding.fdatasync(fd, makeCallback(callback));
461};
462
463fs.fdatasyncSync = function(fd) {
464 return binding.fdatasync(fd);
465};
466
467fs.fsync = function(fd, callback) {
468 binding.fsync(fd, makeCallback(callback));
469};
470
471fs.fsyncSync = function(fd) {
472 return binding.fsync(fd);
473};
474
475fs.mkdir = function(path, mode, callback) {
476 if (typeof mode === 'function') callback = mode;
477 binding.mkdir(pathModule._makeLong(path),
478 modeNum(mode, 511 /*=0777*/),
479 makeCallback(callback));
480};
481
482fs.mkdirSync = function(path, mode) {
483 return binding.mkdir(pathModule._makeLong(path),
484 modeNum(mode, 511 /*=0777*/));
485};
486
487fs.sendfile = function(outFd, inFd, inOffset, length, callback) {
488 binding.sendfile(outFd, inFd, inOffset, length, makeCallback(callback));
489};
490
491fs.sendfileSync = function(outFd, inFd, inOffset, length) {
492 return binding.sendfile(outFd, inFd, inOffset, length);
493};
494
495fs.readdir = function(path, callback) {
496 binding.readdir(pathModule._makeLong(path), makeCallback(callback));
497};
498
499fs.readdirSync = function(path) {
500 return binding.readdir(pathModule._makeLong(path));
501};
502
503fs.fstat = function(fd, callback) {
504 binding.fstat(fd, makeCallback(callback));
505};
506
507fs.lstat = function(path, callback) {
508 binding.lstat(pathModule._makeLong(path), makeCallback(callback));
509};
510
511fs.stat = function(path, callback) {
512 binding.stat(pathModule._makeLong(path), makeCallback(callback));
513};
514
515fs.fstatSync = function(fd) {
516 return binding.fstat(fd);
517};
518
519fs.lstatSync = function(path) {
520 return binding.lstat(pathModule._makeLong(path));
521};
522
523fs.statSync = function(path) {
524 return binding.stat(pathModule._makeLong(path));
525};
526
527fs.readlink = function(path, callback) {
528 binding.readlink(pathModule._makeLong(path), makeCallback(callback));
529};
530
531fs.readlinkSync = function(path) {
532 return binding.readlink(pathModule._makeLong(path));
533};
534
535function preprocessSymlinkDestination(path, type) {
536 if (!isWindows) {
537 // No preprocessing is needed on Unix.
538 return path;
539 } else if (type === 'junction') {
540 // Junctions paths need to be absolute and \\?\-prefixed.
541 return pathModule._makeLong(path);
542 } else {
543 // Windows symlinks don't tolerate forward slashes.
544 return ('' + path).replace(/\//g, '\\');
545 }
546}
547
548fs.symlink = function(destination, path, type_, callback) {
549 var type = (typeof type_ === 'string' ? type_ : null);
550 var callback = makeCallback(arguments[arguments.length - 1]);
551
552 binding.symlink(preprocessSymlinkDestination(destination, type),
553 pathModule._makeLong(path),
554 type,
555 callback);
556};
557
558fs.symlinkSync = function(destination, path, type) {
559 type = (typeof type === 'string' ? type : null);
560
561 return binding.symlink(preprocessSymlinkDestination(destination, type),
562 pathModule._makeLong(path),
563 type);
564};
565
566fs.link = function(srcpath, dstpath, callback) {
567 binding.link(pathModule._makeLong(srcpath),
568 pathModule._makeLong(dstpath),
569 makeCallback(callback));
570};
571
572fs.linkSync = function(srcpath, dstpath) {
573 return binding.link(pathModule._makeLong(srcpath),
574 pathModule._makeLong(dstpath));
575};
576
577fs.unlink = function(path, callback) {
578 binding.unlink(pathModule._makeLong(path), makeCallback(callback));
579};
580
581fs.unlinkSync = function(path) {
582 return binding.unlink(pathModule._makeLong(path));
583};
584
585fs.fchmod = function(fd, mode, callback) {
586 binding.fchmod(fd, modeNum(mode), makeCallback(callback));
587};
588
589fs.fchmodSync = function(fd, mode) {
590 return binding.fchmod(fd, modeNum(mode));
591};
592
593if (constants.hasOwnProperty('O_SYMLINK')) {
594 fs.lchmod = function(path, mode, callback) {
595 callback = callback || (function() {});
596 fs.open(path, constants.O_WRONLY | constants.O_SYMLINK, function(err, fd) {
597 if (err) {
598 callback(err);
599 return;
600 }
601 // prefer to return the chmod error, if one occurs,
602 // but still try to close, and report closing errors if they occur.
603 fs.fchmod(fd, mode, function(err) {
604 fs.close(fd, function(err2) {
605 callback(err || err2);
606 });
607 });
608 });
609 };
610
611 fs.lchmodSync = function(path, mode) {
612 var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK);
613
614 // prefer to return the chmod error, if one occurs,
615 // but still try to close, and report closing errors if they occur.
616 var err, err2;
617 try {
618 var ret = fs.fchmodSync(fd, mode);
619 } catch (er) {
620 err = er;
621 }
622 try {
623 fs.closeSync(fd);
624 } catch (er) {
625 err2 = er;
626 }
627 if (err || err2) throw (err || err2);
628 return ret;
629 };
630}
631
632
633fs.chmod = function(path, mode, callback) {
634 binding.chmod(pathModule._makeLong(path),
635 modeNum(mode),
636 makeCallback(callback));
637};
638
639fs.chmodSync = function(path, mode) {
640 return binding.chmod(pathModule._makeLong(path), modeNum(mode));
641};
642
643if (constants.hasOwnProperty('O_SYMLINK')) {
644 fs.lchown = function(path, uid, gid, callback) {
645 callback = callback || (function() {});
646 fs.open(path, constants.O_WRONLY | constants.O_SYMLINK, function(err, fd) {
647 if (err) {
648 callback(err);
649 return;
650 }
651 fs.fchown(fd, uid, gid, callback);
652 });
653 };
654
655 fs.lchownSync = function(path, uid, gid) {
656 var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK);
657 return fs.fchownSync(fd, uid, gid);
658 };
659}
660
661fs.fchown = function(fd, uid, gid, callback) {
662 binding.fchown(fd, uid, gid, makeCallback(callback));
663};
664
665fs.fchownSync = function(fd, uid, gid) {
666 return binding.fchown(fd, uid, gid);
667};
668
669fs.chown = function(path, uid, gid, callback) {
670 binding.chown(pathModule._makeLong(path), uid, gid, makeCallback(callback));
671};
672
673fs.chownSync = function(path, uid, gid) {
674 return binding.chown(pathModule._makeLong(path), uid, gid);
675};
676
677// converts Date or number to a fractional UNIX timestamp
678function toUnixTimestamp(time) {
679 if (typeof time == 'number') {
680 return time;
681 }
682 if (time instanceof Date) {
683 // convert to 123.456 UNIX timestamp
684 return time.getTime() / 1000;
685 }
686 throw new Error('Cannot parse time: ' + time);
687}
688
689// exported for unit tests, not for public consumption
690fs._toUnixTimestamp = toUnixTimestamp;
691
692fs.utimes = function(path, atime, mtime, callback) {
693 binding.utimes(pathModule._makeLong(path),
694 toUnixTimestamp(atime),
695 toUnixTimestamp(mtime),
696 makeCallback(callback));
697};
698
699fs.utimesSync = function(path, atime, mtime) {
700 atime = toUnixTimestamp(atime);
701 mtime = toUnixTimestamp(mtime);
702 binding.utimes(pathModule._makeLong(path), atime, mtime);
703};
704
705fs.futimes = function(fd, atime, mtime, callback) {
706 atime = toUnixTimestamp(atime);
707 mtime = toUnixTimestamp(mtime);
708 binding.futimes(fd, atime, mtime, makeCallback(callback));
709};
710
711fs.futimesSync = function(fd, atime, mtime) {
712 atime = toUnixTimestamp(atime);
713 mtime = toUnixTimestamp(mtime);
714 binding.futimes(fd, atime, mtime);
715};
716
717function writeAll(fd, buffer, offset, length, position, callback) {
718 var callback_ = arguments[arguments.length - 1];
719 callback = (typeof(callback_) == 'function' ? callback_ : null);
720
721 // write(fd, buffer, offset, length, position, callback)
722 fs.write(fd, buffer, offset, length, position, function(writeErr, written) {
723 if (writeErr) {
724 fs.close(fd, function() {
725 if (callback) callback(writeErr);
726 });
727 } else {
728 if (written === length) {
729 fs.close(fd, callback);
730 } else {
731 offset += written;
732 length -= written;
733 position += written;
734 writeAll(fd, buffer, offset, length, position, callback);
735 }
736 }
737 });
738}
739
740fs.writeFile = function(path, data, encoding_, callback) {
741 var encoding = (typeof(encoding_) == 'string' ? encoding_ : 'utf8');
742 var callback_ = arguments[arguments.length - 1];
743 callback = (typeof(callback_) == 'function' ? callback_ : null);
744 fs.open(path, 'w', 438 /*=0666*/, function(openErr, fd) {
745 if (openErr) {
746 if (callback) callback(openErr);
747 } else {
748 var buffer = Buffer.isBuffer(data) ? data : new Buffer('' + data,
749 encoding);
750 writeAll(fd, buffer, 0, buffer.length, 0, callback);
751 }
752 });
753};
754
755fs.writeFileSync = function(path, data, encoding) {
756 var fd = fs.openSync(path, 'w');
757 if (!Buffer.isBuffer(data)) {
758 data = new Buffer('' + data, encoding || 'utf8');
759 }
760 var written = 0;
761 var length = data.length;
762 try {
763 while (written < length) {
764 written += fs.writeSync(fd, data, written, length - written, written);
765 }
766 } finally {
767 fs.closeSync(fd);
768 }
769};
770
771fs.appendFile = function(path, data, encoding_, callback) {
772 var encoding = (typeof(encoding_) == 'string' ? encoding_ : 'utf8');
773 var callback_ = arguments[arguments.length - 1];
774 callback = (typeof(callback_) == 'function' ? callback_ : null);
775
776 fs.open(path, 'a', 438 /*=0666*/, function(err, fd) {
777 if (err) return callback(err);
778 var buffer = Buffer.isBuffer(data) ? data : new Buffer('' + data, encoding);
779 writeAll(fd, buffer, 0, buffer.length, null, callback);
780 });
781};
782
783fs.appendFileSync = function(path, data, encoding) {
784 var fd = fs.openSync(path, 'a');
785 if (!Buffer.isBuffer(data)) {
786 data = new Buffer('' + data, encoding || 'utf8');
787 }
788 var written = 0;
789 var position = null;
790 var length = data.length;
791
792 try {
793 while (written < length) {
794 written += fs.writeSync(fd, data, written, length - written, position);
795 position += written; // XXX not safe with multiple concurrent writers?
796 }
797 } finally {
798 fs.closeSync(fd);
799 }
800};
801
802function errnoException(errorno, syscall) {
803 // TODO make this more compatible with ErrnoException from src/node.cc
804 // Once all of Node is using this function the ErrnoException from
805 // src/node.cc should be removed.
806 var e = new Error(syscall + ' ' + errorno);
807 e.errno = e.code = errorno;
808 e.syscall = syscall;
809 return e;
810}
811
812
813function FSWatcher() {
814 EventEmitter.call(this);
815
816 var self = this;
817 var FSEvent = process.binding('fs_event_wrap').FSEvent;
818 this._handle = new FSEvent();
819 this._handle.owner = this;
820
821 this._handle.onchange = function(status, event, filename) {
822 if (status) {
823 self._handle.close();
824 self.emit('error', errnoException(errno, 'watch'));
825 } else {
826 self.emit('change', event, filename);
827 }
828 };
829}
830util.inherits(FSWatcher, EventEmitter);
831
832FSWatcher.prototype.start = function(filename, persistent) {
833 var r = this._handle.start(pathModule._makeLong(filename), persistent);
834
835 if (r) {
836 this._handle.close();
837 throw errnoException(errno, 'watch');
838 }
839};
840
841FSWatcher.prototype.close = function() {
842 this._handle.close();
843};
844
845fs.watch = function(filename) {
846 var watcher;
847 var options;
848 var listener;
849
850 if ('object' == typeof arguments[1]) {
851 options = arguments[1];
852 listener = arguments[2];
853 } else {
854 options = {};
855 listener = arguments[1];
856 }
857
858 if (options.persistent === undefined) options.persistent = true;
859
860 watcher = new FSWatcher();
861 watcher.start(filename, options.persistent);
862
863 if (listener) {
864 watcher.addListener('change', listener);
865 }
866
867 return watcher;
868};
869
870
871// Stat Change Watchers
872
873function StatWatcher() {
874 EventEmitter.call(this);
875
876 var self = this;
877 this._handle = new binding.StatWatcher();
878
879 // uv_fs_poll is a little more powerful than ev_stat but we curb it for
880 // the sake of backwards compatibility
881 var oldStatus = -1;
882
883 this._handle.onchange = function(current, previous, newStatus) {
884 if (oldStatus === -1 &&
885 newStatus === -1 &&
886 current.nlink === previous.nlink) return;
887
888 oldStatus = newStatus;
889 self.emit('change', current, previous);
890 };
891
892 this._handle.onstop = function() {
893 self.emit('stop');
894 };
895}
896util.inherits(StatWatcher, EventEmitter);
897
898
899StatWatcher.prototype.start = function(filename, persistent, interval) {
900 this._handle.start(pathModule._makeLong(filename), persistent, interval);
901};
902
903
904StatWatcher.prototype.stop = function() {
905 this._handle.stop();
906};
907
908
909var statWatchers = {};
910function inStatWatchers(filename) {
911 return Object.prototype.hasOwnProperty.call(statWatchers, filename) &&
912 statWatchers[filename];
913}
914
915
916fs.watchFile = function(filename) {
917 var stat;
918 var listener;
919
920 var options = {
921 // Poll interval in milliseconds. 5007 is what libev used to use. It's
922 // a little on the slow side but let's stick with it for now to keep
923 // behavioral changes to a minimum.
924 interval: 5007,
925 persistent: true
926 };
927
928 if ('object' == typeof arguments[1]) {
929 options = util._extend(options, arguments[1]);
930 listener = arguments[2];
931 } else {
932 listener = arguments[1];
933 }
934
935 if (!listener) {
936 throw new Error('watchFile requires a listener function');
937 }
938
939 if (inStatWatchers(filename)) {
940 stat = statWatchers[filename];
941 } else {
942 stat = statWatchers[filename] = new StatWatcher();
943 stat.start(filename, options.persistent, options.interval);
944 }
945 stat.addListener('change', listener);
946 return stat;
947};
948
949fs.unwatchFile = function(filename, listener) {
950 if (!inStatWatchers(filename)) return;
951
952 var stat = statWatchers[filename];
953
954 if (typeof listener === 'function') {
955 stat.removeListener('change', listener);
956 } else {
957 stat.removeAllListeners('change');
958 }
959
960 if (stat.listeners('change').length === 0) {
961 stat.stop();
962 statWatchers[filename] = undefined;
963 }
964};
965
966// Realpath
967// Not using realpath(2) because it's bad.
968// See: http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html
969
970var normalize = pathModule.normalize;
971
972// Regexp that finds the next partion of a (partial) path
973// result is [base_with_slash, base], e.g. ['somedir/', 'somedir']
974if (isWindows) {
975 var nextPartRe = /(.*?)(?:[\/\\]+|$)/g;
976} else {
977 var nextPartRe = /(.*?)(?:[\/]+|$)/g;
978}
979
980// Regex to find the device root, including trailing slash. E.g. 'c:\\'.
981if (isWindows) {
982 var splitRootRe = /^(?:[a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?[\\\/]*/;
983} else {
984 var splitRootRe = /^[\/]*/;
985}
986
987fs.realpathSync = function realpathSync(p, cache) {
988 // make p is absolute
989 p = pathModule.resolve(p);
990
991 if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
992 return cache[p];
993 }
994
995 var original = p,
996 seenLinks = {},
997 knownHard = {};
998
999 // current character position in p
1000 var pos;
1001 // the partial path so far, including a trailing slash if any
1002 var current;
1003 // the partial path without a trailing slash (except when pointing at a root)
1004 var base;
1005 // the partial path scanned in the previous round, with slash
1006 var previous;
1007
1008 start();
1009
1010 function start() {
1011 // Skip over roots
1012 var m = splitRootRe.exec(p);
1013 pos = m[0].length;
1014 current = m[0];
1015 base = m[0];
1016 previous = '';
1017
1018 // On windows, check that the root exists. On unix there is no need.
1019 if (isWindows && !knownHard[base]) {
1020 fs.lstatSync(base);
1021 knownHard[base] = true;
1022 }
1023 }
1024
1025 // walk down the path, swapping out linked pathparts for their real
1026 // values
1027 // NB: p.length changes.
1028 while (pos < p.length) {
1029 // find the next part
1030 nextPartRe.lastIndex = pos;
1031 var result = nextPartRe.exec(p);
1032 previous = current;
1033 current += result[0];
1034 base = previous + result[1];
1035 pos = nextPartRe.lastIndex;
1036
1037 // continue if not a symlink
1038 if (knownHard[base] || (cache && cache[base] === base)) {
1039 continue;
1040 }
1041
1042 var resolvedLink;
1043 if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
1044 // some known symbolic link. no need to stat again.
1045 resolvedLink = cache[base];
1046 } else {
1047 var stat = fs.lstatSync(base);
1048 if (!stat.isSymbolicLink()) {
1049 knownHard[base] = true;
1050 if (cache) cache[base] = base;
1051 continue;
1052 }
1053
1054 // read the link if it wasn't read before
1055 // dev/ino always return 0 on windows, so skip the check.
1056 var linkTarget = null;
1057 if (!isWindows) {
1058 var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
1059 if (seenLinks.hasOwnProperty(id)) {
1060 linkTarget = seenLinks[id];
1061 }
1062 }
1063 if (linkTarget === null) {
1064 fs.statSync(base);
1065 linkTarget = fs.readlinkSync(base);
1066 }
1067 resolvedLink = pathModule.resolve(previous, linkTarget);
1068 // track this, if given a cache.
1069 if (cache) cache[base] = resolvedLink;
1070 if (!isWindows) seenLinks[id] = linkTarget;
1071 }
1072
1073 // resolve the link, then start over
1074 p = pathModule.resolve(resolvedLink, p.slice(pos));
1075 start();
1076 }
1077
1078 if (cache) cache[original] = p;
1079
1080 return p;
1081};
1082
1083
1084fs.realpath = function realpath(p, cache, cb) {
1085 if (typeof cb !== 'function') {
1086 cb = cache;
1087 cache = null;
1088 }
1089
1090 // make p is absolute
1091 p = pathModule.resolve(p);
1092
1093 if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
1094 return process.nextTick(cb.bind(null, null, cache[p]));
1095 }
1096
1097 var original = p,
1098 seenLinks = {},
1099 knownHard = {};
1100
1101 // current character position in p
1102 var pos;
1103 // the partial path so far, including a trailing slash if any
1104 var current;
1105 // the partial path without a trailing slash (except when pointing at a root)
1106 var base;
1107 // the partial path scanned in the previous round, with slash
1108 var previous;
1109
1110 start();
1111
1112 function start() {
1113 // Skip over roots
1114 var m = splitRootRe.exec(p);
1115 pos = m[0].length;
1116 current = m[0];
1117 base = m[0];
1118 previous = '';
1119
1120 // On windows, check that the root exists. On unix there is no need.
1121 if (isWindows && !knownHard[base]) {
1122 fs.lstat(base, function(err) {
1123 if (err) return cb(err);
1124 knownHard[base] = true;
1125 LOOP();
1126 });
1127 } else {
1128 process.nextTick(LOOP);
1129 }
1130 }
1131
1132 // walk down the path, swapping out linked pathparts for their real
1133 // values
1134 function LOOP() {
1135 // stop if scanned past end of path
1136 if (pos >= p.length) {
1137 if (cache) cache[original] = p;
1138 return cb(null, p);
1139 }
1140
1141 // find the next part
1142 nextPartRe.lastIndex = pos;
1143 var result = nextPartRe.exec(p);
1144 previous = current;
1145 current += result[0];
1146 base = previous + result[1];
1147 pos = nextPartRe.lastIndex;
1148
1149 // continue if not a symlink
1150 if (knownHard[base] || (cache && cache[base] === base)) {
1151 return process.nextTick(LOOP);
1152 }
1153
1154 if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
1155 // known symbolic link. no need to stat again.
1156 return gotResolvedLink(cache[base]);
1157 }
1158
1159 return fs.lstat(base, gotStat);
1160 }
1161
1162 function gotStat(err, stat) {
1163 if (err) return cb(err);
1164
1165 // if not a symlink, skip to the next path part
1166 if (!stat.isSymbolicLink()) {
1167 knownHard[base] = true;
1168 if (cache) cache[base] = base;
1169 return process.nextTick(LOOP);
1170 }
1171
1172 // stat & read the link if not read before
1173 // call gotTarget as soon as the link target is known
1174 // dev/ino always return 0 on windows, so skip the check.
1175 if (!isWindows) {
1176 var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
1177 if (seenLinks.hasOwnProperty(id)) {
1178 return gotTarget(null, seenLinks[id], base);
1179 }
1180 }
1181 fs.stat(base, function(err) {
1182 if (err) return cb(err);
1183
1184 fs.readlink(base, function(err, target) {
1185 if (!isWindows) seenLinks[id] = target;
1186 gotTarget(err, target);
1187 });
1188 });
1189 }
1190
1191 function gotTarget(err, target, base) {
1192 if (err) return cb(err);
1193
1194 var resolvedLink = pathModule.resolve(previous, target);
1195 if (cache) cache[base] = resolvedLink;
1196 gotResolvedLink(resolvedLink);
1197 }
1198
1199 function gotResolvedLink(resolvedLink) {
1200 // resolve the link, then start over
1201 p = pathModule.resolve(resolvedLink, p.slice(pos));
1202 start();
1203 }
1204};
1205
1206
1207
1208var pool;
1209
1210function allocNewPool() {
1211 pool = new Buffer(kPoolSize);
1212 pool.used = 0;
1213}
1214
1215
1216
1217fs.createReadStream = function(path, options) {
1218 return new ReadStream(path, options);
1219};
1220
1221var ReadStream = fs.ReadStream = function(path, options) {
1222 if (!(this instanceof ReadStream)) return new ReadStream(path, options);
1223
1224 Stream.call(this);
1225
1226 var self = this;
1227
1228 this.path = path;
1229 this.fd = null;
1230 this.readable = true;
1231 this.paused = false;
1232
1233 this.flags = 'r';
1234 this.mode = 438; /*=0666*/
1235 this.bufferSize = 64 * 1024;
1236
1237 options = options || {};
1238
1239 // Mixin options into this
1240 var keys = Object.keys(options);
1241 for (var index = 0, length = keys.length; index < length; index++) {
1242 var key = keys[index];
1243 this[key] = options[key];
1244 }
1245
1246 if (this.encoding) this.setEncoding(this.encoding);
1247
1248 if (this.start !== undefined) {
1249 if ('number' !== typeof this.start) {
1250 throw TypeError('start must be a Number');
1251 }
1252 if (this.end === undefined) {
1253 this.end = Infinity;
1254 } else if ('number' !== typeof this.end) {
1255 throw TypeError('end must be a Number');
1256 }
1257
1258 if (this.start > this.end) {
1259 throw new Error('start must be <= end');
1260 }
1261
1262 this.pos = this.start;
1263 }
1264
1265 if (this.fd !== null) {
1266 process.nextTick(function() {
1267 self._read();
1268 });
1269 return;
1270 }
1271
1272 fs.open(this.path, this.flags, this.mode, function(err, fd) {
1273 if (err) {
1274 self.emit('error', err);
1275 self.readable = false;
1276 return;
1277 }
1278
1279 self.fd = fd;
1280 self.emit('open', fd);
1281 self._read();
1282 });
1283};
1284util.inherits(ReadStream, Stream);
1285
1286fs.FileReadStream = fs.ReadStream; // support the legacy name
1287
1288ReadStream.prototype.setEncoding = function(encoding) {
1289 var StringDecoder = require('string_decoder').StringDecoder; // lazy load
1290 this._decoder = new StringDecoder(encoding);
1291};
1292
1293
1294ReadStream.prototype._read = function() {
1295 var self = this;
1296 if (!this.readable || this.paused || this.reading) return;
1297
1298 this.reading = true;
1299
1300 if (!pool || pool.length - pool.used < kMinPoolSpace) {
1301 // discard the old pool. Can't add to the free list because
1302 // users might have refernces to slices on it.
1303 pool = null;
1304 allocNewPool();
1305 }
1306
1307 // Grab another reference to the pool in the case that while we're in the
1308 // thread pool another read() finishes up the pool, and allocates a new
1309 // one.
1310 var thisPool = pool;
1311 var toRead = Math.min(pool.length - pool.used, ~~this.bufferSize);
1312 var start = pool.used;
1313
1314 if (this.pos !== undefined) {
1315 toRead = Math.min(this.end - this.pos + 1, toRead);
1316 }
1317
1318 function afterRead(err, bytesRead) {
1319 self.reading = false;
1320 if (err) {
1321 fs.close(self.fd, function() {
1322 self.fd = null;
1323 self.emit('error', err);
1324 self.readable = false;
1325 });
1326 return;
1327 }
1328
1329 if (bytesRead === 0) {
1330 self.emit('end');
1331 self.destroy();
1332 return;
1333 }
1334
1335 var b = thisPool.slice(start, start + bytesRead);
1336
1337 // Possible optimizition here?
1338 // Reclaim some bytes if bytesRead < toRead?
1339 // Would need to ensure that pool === thisPool.
1340
1341 // do not emit events if the stream is paused
1342 if (self.paused) {
1343 self.buffer = b;
1344 return;
1345 }
1346
1347 // do not emit events anymore after we declared the stream unreadable
1348 if (!self.readable) return;
1349
1350 self._emitData(b);
1351 self._read();
1352 }
1353
1354 fs.read(this.fd, pool, pool.used, toRead, this.pos, afterRead);
1355
1356 if (this.pos !== undefined) {
1357 this.pos += toRead;
1358 }
1359 pool.used += toRead;
1360};
1361
1362
1363ReadStream.prototype._emitData = function(d) {
1364 if (this._decoder) {
1365 var string = this._decoder.write(d);
1366 if (string.length) this.emit('data', string);
1367 } else {
1368 this.emit('data', d);
1369 }
1370};
1371
1372
1373ReadStream.prototype.destroy = function(cb) {
1374 var self = this;
1375
1376 if (!this.readable) {
1377 if (cb) process.nextTick(function() { cb(null); });
1378 return;
1379 }
1380 this.readable = false;
1381
1382 function close() {
1383 fs.close(self.fd, function(err) {
1384 if (err) {
1385 if (cb) cb(err);
1386 self.emit('error', err);
1387 return;
1388 }
1389
1390 if (cb) cb(null);
1391 self.emit('close');
1392 });
1393 }
1394
1395 if (this.fd === null) {
1396 this.addListener('open', close);
1397 } else {
1398 close();
1399 }
1400};
1401
1402
1403ReadStream.prototype.pause = function() {
1404 this.paused = true;
1405};
1406
1407
1408ReadStream.prototype.resume = function() {
1409 this.paused = false;
1410
1411 if (this.buffer) {
1412 var buffer = this.buffer;
1413 this.buffer = null;
1414 this._emitData(buffer);
1415 }
1416
1417 // hasn't opened yet.
1418 if (null == this.fd) return;
1419
1420 this._read();
1421};
1422
1423
1424
1425fs.createWriteStream = function(path, options) {
1426 return new WriteStream(path, options);
1427};
1428
1429var WriteStream = fs.WriteStream = function(path, options) {
1430 if (!(this instanceof WriteStream)) return new WriteStream(path, options);
1431
1432 Stream.call(this);
1433
1434 this.path = path;
1435 this.fd = null;
1436 this.writable = true;
1437
1438 this.flags = 'w';
1439 this.encoding = 'binary';
1440 this.mode = 438; /*=0666*/
1441 this.bytesWritten = 0;
1442
1443 options = options || {};
1444
1445 // Mixin options into this
1446 var keys = Object.keys(options);
1447 for (var index = 0, length = keys.length; index < length; index++) {
1448 var key = keys[index];
1449 this[key] = options[key];
1450 }
1451
1452 if (this.start !== undefined) {
1453 if ('number' !== typeof this.start) {
1454 throw TypeError('start must be a Number');
1455 }
1456 if (this.start < 0) {
1457 throw new Error('start must be >= zero');
1458 }
1459
1460 this.pos = this.start;
1461 }
1462
1463 this.busy = false;
1464 this._queue = [];
1465
1466 if (this.fd === null) {
1467 this._open = fs.open;
1468 this._queue.push([this._open, this.path, this.flags, this.mode, undefined]);
1469 this.flush();
1470 }
1471};
1472util.inherits(WriteStream, Stream);
1473
1474fs.FileWriteStream = fs.WriteStream; // support the legacy name
1475
1476WriteStream.prototype.flush = function() {
1477 if (this.busy) return;
1478 var self = this;
1479
1480 var args = this._queue.shift();
1481 if (!args) {
1482 if (this.drainable) { this.emit('drain'); }
1483 return;
1484 }
1485
1486 this.busy = true;
1487
1488 var method = args.shift(),
1489 cb = args.pop();
1490
1491 args.push(function(err) {
1492 self.busy = false;
1493
1494 if (err) {
1495 self.writable = false;
1496
1497 function emit() {
1498 self.fd = null;
1499 if (cb) cb(err);
1500 self.emit('error', err);
1501 }
1502
1503 if (self.fd === null) {
1504 emit();
1505 } else {
1506 fs.close(self.fd, emit);
1507 }
1508
1509 return;
1510 }
1511
1512 if (method == fs.write) {
1513 self.bytesWritten += arguments[1];
1514 if (cb) {
1515 // write callback
1516 cb(null, arguments[1]);
1517 }
1518
1519 } else if (method === self._open) {
1520 // save reference for file pointer
1521 self.fd = arguments[1];
1522 self.emit('open', self.fd);
1523
1524 } else if (method === fs.close) {
1525 // stop flushing after close
1526 if (cb) {
1527 cb(null);
1528 }
1529 self.emit('close');
1530 return;
1531 }
1532
1533 self.flush();
1534 });
1535
1536 // Inject the file pointer
1537 if (method !== self._open) {
1538 args.unshift(this.fd);
1539 }
1540
1541 method.apply(this, args);
1542};
1543
1544WriteStream.prototype.write = function(data) {
1545 if (!this.writable) {
1546 this.emit('error', new Error('stream not writable'));
1547 return false;
1548 }
1549
1550 this.drainable = true;
1551
1552 var cb;
1553 if (typeof(arguments[arguments.length - 1]) == 'function') {
1554 cb = arguments[arguments.length - 1];
1555 }
1556
1557 if (!Buffer.isBuffer(data)) {
1558 var encoding = 'utf8';
1559 if (typeof(arguments[1]) == 'string') encoding = arguments[1];
1560 data = new Buffer('' + data, encoding);
1561 }
1562
1563 this._queue.push([fs.write, data, 0, data.length, this.pos, cb]);
1564
1565 if (this.pos !== undefined) {
1566 this.pos += data.length;
1567 }
1568
1569 this.flush();
1570
1571 return false;
1572};
1573
1574WriteStream.prototype.end = function(data, encoding, cb) {
1575 if (typeof(data) === 'function') {
1576 cb = data;
1577 } else if (typeof(encoding) === 'function') {
1578 cb = encoding;
1579 this.write(data);
1580 } else if (arguments.length > 0) {
1581 this.write(data, encoding);
1582 }
1583 this.writable = false;
1584 this._queue.push([fs.close, cb]);
1585 this.flush();
1586};
1587
1588WriteStream.prototype.destroy = function(cb) {
1589 var self = this;
1590
1591 if (!this.writable) {
1592 if (cb) process.nextTick(function() { cb(null); });
1593 return;
1594 }
1595 this.writable = false;
1596
1597 function close() {
1598 fs.close(self.fd, function(err) {
1599 if (err) {
1600 if (cb) { cb(err); }
1601 self.emit('error', err);
1602 return;
1603 }
1604
1605 if (cb) { cb(null); }
1606 self.emit('close');
1607 });
1608 }
1609
1610 if (this.fd === null) {
1611 this.addListener('open', close);
1612 } else {
1613 close();
1614 }
1615};
1616
1617// There is no shutdown() for files.
1618WriteStream.prototype.destroySoon = WriteStream.prototype.end;
1619
1620
1621// SyncWriteStream is internal. DO NOT USE.
1622// Temporary hack for process.stdout and process.stderr when piped to files.
1623function SyncWriteStream(fd) {
1624 Stream.call(this);
1625
1626 this.fd = fd;
1627 this.writable = true;
1628 this.readable = false;
1629}
1630
1631util.inherits(SyncWriteStream, Stream);
1632
1633
1634// Export
1635fs.SyncWriteStream = SyncWriteStream;
1636
1637
1638SyncWriteStream.prototype.write = function(data, arg1, arg2) {
1639 var encoding, cb;
1640
1641 // parse arguments
1642 if (arg1) {
1643 if (typeof arg1 === 'string') {
1644 encoding = arg1;
1645 cb = arg2;
1646 } else if (typeof arg1 === 'function') {
1647 cb = arg1;
1648 } else {
1649 throw new Error('bad arg');
1650 }
1651 }
1652
1653 // Change strings to buffers. SLOW
1654 if (typeof data == 'string') {
1655 data = new Buffer(data, encoding);
1656 }
1657
1658 fs.writeSync(this.fd, data, 0, data.length);
1659
1660 if (cb) {
1661 process.nextTick(cb);
1662 }
1663
1664 return true;
1665};
1666
1667
1668SyncWriteStream.prototype.end = function(data, arg1, arg2) {
1669 if (data) {
1670 this.write(data, arg1, arg2);
1671 }
1672 this.destroy();
1673};
1674
1675
1676SyncWriteStream.prototype.destroy = function() {
1677 fs.closeSync(this.fd);
1678 this.fd = null;
1679 this.emit('close');
1680 return true;
1681};
1682
1683SyncWriteStream.prototype.destroySoon = SyncWriteStream.prototype.destroy;