1 // Copyright Joyent, Inc. and other Node contributors.
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:
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
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.
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:
26 // var mode = 438; /* mode=0666 */
28 var util = require('util');
29 var pathModule = require('path');
31 var binding = process.binding('fs');
32 var constants = process.binding('constants');
34 var Stream = require('stream').Stream;
35 var EventEmitter = require('events').EventEmitter;
37 var kMinPoolSpace = 128;
38 var kPoolSize = 40 * 1024;
40 var O_APPEND = constants.O_APPEND || 0;
41 var O_CREAT = constants.O_CREAT || 0;
42 var O_DIRECTORY = constants.O_DIRECTORY || 0;
43 var O_EXCL = constants.O_EXCL || 0;
44 var O_NOCTTY = constants.O_NOCTTY || 0;
45 var O_NOFOLLOW = constants.O_NOFOLLOW || 0;
46 var O_RDONLY = constants.O_RDONLY || 0;
47 var O_RDWR = constants.O_RDWR || 0;
48 var O_SYMLINK = constants.O_SYMLINK || 0;
49 var O_SYNC = constants.O_SYNC || 0;
50 var O_TRUNC = constants.O_TRUNC || 0;
51 var O_WRONLY = constants.O_WRONLY || 0;
53 var isWindows = process.platform === 'win32';
55 function rethrow(err) {
59 function maybeCallback(cb) {
60 return typeof cb === 'function' ? cb : rethrow;
63 // Ensure that callbacks run in the global context. Only use this function
64 // for callbacks that are passed to the binding layer, callbacks that are
65 // invoked from JS already run in the proper scope.
66 function makeCallback(cb) {
67 if (typeof cb !== 'function') {
72 return cb.apply(null, arguments);
76 function assertEncoding(encoding) {
77 if (encoding && !Buffer.isEncoding(encoding)) {
78 throw new Error('Unknown encoding: ' + encoding);
83 fs.Stats = binding.Stats;
85 fs.Stats.prototype._checkModeProperty = function(property) {
86 return ((this.mode & constants.S_IFMT) === property);
89 fs.Stats.prototype.isDirectory = function() {
90 return this._checkModeProperty(constants.S_IFDIR);
93 fs.Stats.prototype.isFile = function() {
94 return this._checkModeProperty(constants.S_IFREG);
97 fs.Stats.prototype.isBlockDevice = function() {
98 return this._checkModeProperty(constants.S_IFBLK);
101 fs.Stats.prototype.isCharacterDevice = function() {
102 return this._checkModeProperty(constants.S_IFCHR);
105 fs.Stats.prototype.isSymbolicLink = function() {
106 return this._checkModeProperty(constants.S_IFLNK);
109 fs.Stats.prototype.isFIFO = function() {
110 return this._checkModeProperty(constants.S_IFIFO);
113 fs.Stats.prototype.isSocket = function() {
114 return this._checkModeProperty(constants.S_IFSOCK);
117 fs.exists = function(path, callback) {
118 binding.stat(pathModule._makeLong(path), function(err, stats) {
119 if (callback) callback(err ? false : true);
123 fs.existsSync = function(path) {
125 binding.stat(pathModule._makeLong(path));
132 fs.readFile = function(path, encoding_) {
133 var encoding = typeof(encoding_) === 'string' ? encoding_ : null;
134 var callback = maybeCallback(arguments[arguments.length - 1]);
136 assertEncoding(encoding);
138 // first, stat the file, so we know the size.
140 var buffer; // single buffer with file data
141 var buffers; // list for when size is unknown
145 fs.open(path, constants.O_RDONLY, 438 /*=0666*/, function(er, fd_) {
146 if (er) return callback(er);
149 fs.fstat(fd, function(er, st) {
150 if (er) return callback(er);
153 // the kernel lies about many files.
154 // Go ahead and try to read some bytes.
159 buffer = new Buffer(size);
166 buffer = new Buffer(8192);
167 fs.read(fd, buffer, 0, 8192, -1, afterRead);
169 fs.read(fd, buffer, pos, size - pos, -1, afterRead);
173 function afterRead(er, bytesRead) {
175 return fs.close(fd, function(er2) {
180 if (bytesRead === 0) {
186 if (pos === size) close();
189 // unknown size, just read until we don't get bytes.
190 buffers.push(buffer.slice(0, bytesRead));
196 fs.close(fd, function(er) {
198 // collected the data into the buffers list.
199 buffer = Buffer.concat(buffers, pos);
200 } else if (pos < size) {
201 buffer = buffer.slice(0, pos);
204 if (encoding) buffer = buffer.toString(encoding);
205 return callback(er, buffer);
210 fs.readFileSync = function(path, encoding) {
211 assertEncoding(encoding);
213 var fd = fs.openSync(path, constants.O_RDONLY, 438 /*=0666*/);
218 size = fs.fstatSync(fd).size;
221 if (threw) fs.closeSync(fd);
225 var buffer; // single buffer with file data
226 var buffers; // list for when size is unknown
231 buffer = new Buffer(size);
239 var bytesRead = fs.readSync(fd, buffer, pos, size - pos);
241 // the kernel lies about many files.
242 // Go ahead and try to read some bytes.
243 buffer = new Buffer(8192);
244 var bytesRead = fs.readSync(fd, buffer, 0, 8192);
246 buffers.push(buffer.slice(0, bytesRead));
251 if (threw) fs.closeSync(fd);
255 done = (bytesRead === 0) || (size !== 0 && pos >= size);
261 // data was collected into the buffers list.
262 buffer = Buffer.concat(buffers, pos);
263 } else if (pos < size) {
264 buffer = buffer.slice(0, pos);
267 if (encoding) buffer = buffer.toString(encoding);
272 // Used by binding.open and friends
273 function stringToFlags(flag) {
274 // Only mess with strings
275 if (typeof flag !== 'string') {
279 // O_EXCL is mandated by POSIX, Windows supports it too.
280 // Let's add a check anyway, just in case.
281 if (!O_EXCL && ~flag.indexOf('x')) {
282 throw errnoException('ENOSYS', 'fs.open(O_EXCL)');
286 case 'r' : return O_RDONLY;
287 case 'rs' : return O_RDONLY | O_SYNC;
288 case 'r+' : return O_RDWR;
289 case 'rs+' : return O_RDWR | O_SYNC;
291 case 'w' : return O_TRUNC | O_CREAT | O_WRONLY;
292 case 'wx' : // fall through
293 case 'xw' : return O_TRUNC | O_CREAT | O_WRONLY | O_EXCL;
295 case 'w+' : return O_TRUNC | O_CREAT | O_RDWR;
296 case 'wx+': // fall through
297 case 'xw+': return O_TRUNC | O_CREAT | O_RDWR | O_EXCL;
299 case 'a' : return O_APPEND | O_CREAT | O_WRONLY;
300 case 'ax' : // fall through
301 case 'xa' : return O_APPEND | O_CREAT | O_WRONLY | O_EXCL;
303 case 'a+' : return O_APPEND | O_CREAT | O_RDWR;
304 case 'ax+': // fall through
305 case 'xa+': return O_APPEND | O_CREAT | O_RDWR | O_EXCL;
308 throw new Error('Unknown file open flag: ' + flag);
311 // exported but hidden, only used by test/simple/test-fs-open-flags.js
312 Object.defineProperty(exports, '_stringToFlags', {
318 // Yes, the follow could be easily DRYed up but I provide the explicit
319 // list to make the arguments clear.
321 fs.close = function(fd, callback) {
322 binding.close(fd, makeCallback(callback));
325 fs.closeSync = function(fd) {
326 return binding.close(fd);
329 function modeNum(m, def) {
331 case 'number': return m;
332 case 'string': return parseInt(m, 8);
342 fs.open = function(path, flags, mode, callback) {
343 callback = makeCallback(arguments[arguments.length - 1]);
344 mode = modeNum(mode, 438 /*=0666*/);
346 binding.open(pathModule._makeLong(path),
347 stringToFlags(flags),
352 fs.openSync = function(path, flags, mode) {
353 mode = modeNum(mode, 438 /*=0666*/);
354 return binding.open(pathModule._makeLong(path), stringToFlags(flags), mode);
357 fs.read = function(fd, buffer, offset, length, position, callback) {
358 if (!Buffer.isBuffer(buffer)) {
359 // legacy string interface (fd, length, position, encoding, callback)
360 var cb = arguments[4],
361 encoding = arguments[3];
363 assertEncoding(encoding);
365 position = arguments[2];
366 length = arguments[1];
367 buffer = new Buffer(length);
370 callback = function(err, bytesRead) {
373 var str = (bytesRead > 0) ? buffer.toString(encoding, 0, bytesRead) : '';
375 (cb)(err, str, bytesRead);
379 function wrapper(err, bytesRead) {
380 // Retain a reference to buffer so that it can't be GC'ed too soon.
381 callback && callback(err, bytesRead || 0, buffer);
384 binding.read(fd, buffer, offset, length, position, wrapper);
387 fs.readSync = function(fd, buffer, offset, length, position) {
389 if (!Buffer.isBuffer(buffer)) {
390 // legacy string interface (fd, length, position, encoding, callback)
392 var encoding = arguments[3];
394 assertEncoding(encoding);
396 position = arguments[2];
397 length = arguments[1];
398 buffer = new Buffer(length);
403 var r = binding.read(fd, buffer, offset, length, position);
408 var str = (r > 0) ? buffer.toString(encoding, 0, r) : '';
412 fs.write = function(fd, buffer, offset, length, position, callback) {
413 if (!Buffer.isBuffer(buffer)) {
414 // legacy string interface (fd, data, position, encoding, callback)
415 callback = arguments[4];
416 position = arguments[2];
417 assertEncoding(arguments[3]);
419 buffer = new Buffer('' + arguments[1], arguments[3]);
421 length = buffer.length;
425 if (typeof callback == 'function') {
426 process.nextTick(function() {
427 callback(undefined, 0);
433 callback = maybeCallback(callback);
435 function wrapper(err, written) {
436 // Retain a reference to buffer so that it can't be GC'ed too soon.
437 callback(err, written || 0, buffer);
440 binding.write(fd, buffer, offset, length, position, wrapper);
443 fs.writeSync = function(fd, buffer, offset, length, position) {
444 if (!Buffer.isBuffer(buffer)) {
445 // legacy string interface (fd, data, position, encoding)
446 position = arguments[2];
447 assertEncoding(arguments[3]);
449 buffer = new Buffer('' + arguments[1], arguments[3]);
451 length = buffer.length;
453 if (!length) return 0;
455 return binding.write(fd, buffer, offset, length, position);
458 fs.rename = function(oldPath, newPath, callback) {
459 binding.rename(pathModule._makeLong(oldPath),
460 pathModule._makeLong(newPath),
461 makeCallback(callback));
464 fs.renameSync = function(oldPath, newPath) {
465 return binding.rename(pathModule._makeLong(oldPath),
466 pathModule._makeLong(newPath));
469 fs.truncate = function(path, len, callback) {
470 if (typeof path === 'number') {
472 return fs.ftruncate(path, len, callback);
474 if (typeof len === 'function') {
477 } else if (typeof len === 'undefined') {
480 callback = maybeCallback(callback);
481 fs.open(path, 'w', function(er, fd) {
482 if (er) return callback(er);
483 binding.ftruncate(fd, len, function(er) {
484 fs.close(fd, function(er2) {
491 fs.truncateSync = function(path, len) {
492 if (typeof path === 'number') {
494 return fs.ftruncateSync(path, len);
496 if (typeof len === 'undefined') {
499 // allow error to be thrown, but still close fd.
500 var fd = fs.openSync(path, 'w');
502 var ret = fs.ftruncateSync(fd, len);
509 fs.ftruncate = function(fd, len, callback) {
510 if (typeof len === 'function') {
513 } else if (typeof len === 'undefined') {
516 binding.ftruncate(fd, len, makeCallback(callback));
519 fs.ftruncateSync = function(fd, len) {
520 if (typeof len === 'undefined') {
523 return binding.ftruncate(fd, len);
526 fs.rmdir = function(path, callback) {
527 binding.rmdir(pathModule._makeLong(path), makeCallback(callback));
530 fs.rmdirSync = function(path) {
531 return binding.rmdir(pathModule._makeLong(path));
534 fs.fdatasync = function(fd, callback) {
535 binding.fdatasync(fd, makeCallback(callback));
538 fs.fdatasyncSync = function(fd) {
539 return binding.fdatasync(fd);
542 fs.fsync = function(fd, callback) {
543 binding.fsync(fd, makeCallback(callback));
546 fs.fsyncSync = function(fd) {
547 return binding.fsync(fd);
550 fs.mkdir = function(path, mode, callback) {
551 if (typeof mode === 'function') callback = mode;
552 binding.mkdir(pathModule._makeLong(path),
553 modeNum(mode, 511 /*=0777*/),
554 makeCallback(callback));
557 fs.mkdirSync = function(path, mode) {
558 return binding.mkdir(pathModule._makeLong(path),
559 modeNum(mode, 511 /*=0777*/));
562 fs.sendfile = function(outFd, inFd, inOffset, length, callback) {
563 binding.sendfile(outFd, inFd, inOffset, length, makeCallback(callback));
566 fs.sendfileSync = function(outFd, inFd, inOffset, length) {
567 return binding.sendfile(outFd, inFd, inOffset, length);
570 fs.readdir = function(path, callback) {
571 binding.readdir(pathModule._makeLong(path), makeCallback(callback));
574 fs.readdirSync = function(path) {
575 return binding.readdir(pathModule._makeLong(path));
578 fs.fstat = function(fd, callback) {
579 binding.fstat(fd, makeCallback(callback));
582 fs.lstat = function(path, callback) {
583 binding.lstat(pathModule._makeLong(path), makeCallback(callback));
586 fs.stat = function(path, callback) {
587 binding.stat(pathModule._makeLong(path), makeCallback(callback));
590 fs.fstatSync = function(fd) {
591 return binding.fstat(fd);
594 fs.lstatSync = function(path) {
595 return binding.lstat(pathModule._makeLong(path));
598 fs.statSync = function(path) {
599 return binding.stat(pathModule._makeLong(path));
602 fs.readlink = function(path, callback) {
603 binding.readlink(pathModule._makeLong(path), makeCallback(callback));
606 fs.readlinkSync = function(path) {
607 return binding.readlink(pathModule._makeLong(path));
610 function preprocessSymlinkDestination(path, type) {
612 // No preprocessing is needed on Unix.
614 } else if (type === 'junction') {
615 // Junctions paths need to be absolute and \\?\-prefixed.
616 return pathModule._makeLong(path);
618 // Windows symlinks don't tolerate forward slashes.
619 return ('' + path).replace(/\//g, '\\');
623 fs.symlink = function(destination, path, type_, callback) {
624 var type = (typeof type_ === 'string' ? type_ : null);
625 var callback = makeCallback(arguments[arguments.length - 1]);
627 binding.symlink(preprocessSymlinkDestination(destination, type),
628 pathModule._makeLong(path),
633 fs.symlinkSync = function(destination, path, type) {
634 type = (typeof type === 'string' ? type : null);
636 return binding.symlink(preprocessSymlinkDestination(destination, type),
637 pathModule._makeLong(path),
641 fs.link = function(srcpath, dstpath, callback) {
642 binding.link(pathModule._makeLong(srcpath),
643 pathModule._makeLong(dstpath),
644 makeCallback(callback));
647 fs.linkSync = function(srcpath, dstpath) {
648 return binding.link(pathModule._makeLong(srcpath),
649 pathModule._makeLong(dstpath));
652 fs.unlink = function(path, callback) {
653 binding.unlink(pathModule._makeLong(path), makeCallback(callback));
656 fs.unlinkSync = function(path) {
657 return binding.unlink(pathModule._makeLong(path));
660 fs.fchmod = function(fd, mode, callback) {
661 binding.fchmod(fd, modeNum(mode), makeCallback(callback));
664 fs.fchmodSync = function(fd, mode) {
665 return binding.fchmod(fd, modeNum(mode));
668 if (constants.hasOwnProperty('O_SYMLINK')) {
669 fs.lchmod = function(path, mode, callback) {
670 callback = maybeCallback(callback);
671 fs.open(path, constants.O_WRONLY | constants.O_SYMLINK, function(err, fd) {
676 // prefer to return the chmod error, if one occurs,
677 // but still try to close, and report closing errors if they occur.
678 fs.fchmod(fd, mode, function(err) {
679 fs.close(fd, function(err2) {
680 callback(err || err2);
686 fs.lchmodSync = function(path, mode) {
687 var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK);
689 // prefer to return the chmod error, if one occurs,
690 // but still try to close, and report closing errors if they occur.
693 var ret = fs.fchmodSync(fd, mode);
702 if (err || err2) throw (err || err2);
708 fs.chmod = function(path, mode, callback) {
709 binding.chmod(pathModule._makeLong(path),
711 makeCallback(callback));
714 fs.chmodSync = function(path, mode) {
715 return binding.chmod(pathModule._makeLong(path), modeNum(mode));
718 if (constants.hasOwnProperty('O_SYMLINK')) {
719 fs.lchown = function(path, uid, gid, callback) {
720 callback = maybeCallback(callback);
721 fs.open(path, constants.O_WRONLY | constants.O_SYMLINK, function(err, fd) {
726 fs.fchown(fd, uid, gid, callback);
730 fs.lchownSync = function(path, uid, gid) {
731 var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK);
732 return fs.fchownSync(fd, uid, gid);
736 fs.fchown = function(fd, uid, gid, callback) {
737 binding.fchown(fd, uid, gid, makeCallback(callback));
740 fs.fchownSync = function(fd, uid, gid) {
741 return binding.fchown(fd, uid, gid);
744 fs.chown = function(path, uid, gid, callback) {
745 binding.chown(pathModule._makeLong(path), uid, gid, makeCallback(callback));
748 fs.chownSync = function(path, uid, gid) {
749 return binding.chown(pathModule._makeLong(path), uid, gid);
752 // converts Date or number to a fractional UNIX timestamp
753 function toUnixTimestamp(time) {
754 if (typeof time == 'number') {
757 if (time instanceof Date) {
758 // convert to 123.456 UNIX timestamp
759 return time.getTime() / 1000;
761 throw new Error('Cannot parse time: ' + time);
764 // exported for unit tests, not for public consumption
765 fs._toUnixTimestamp = toUnixTimestamp;
767 fs.utimes = function(path, atime, mtime, callback) {
768 binding.utimes(pathModule._makeLong(path),
769 toUnixTimestamp(atime),
770 toUnixTimestamp(mtime),
771 makeCallback(callback));
774 fs.utimesSync = function(path, atime, mtime) {
775 atime = toUnixTimestamp(atime);
776 mtime = toUnixTimestamp(mtime);
777 binding.utimes(pathModule._makeLong(path), atime, mtime);
780 fs.futimes = function(fd, atime, mtime, callback) {
781 atime = toUnixTimestamp(atime);
782 mtime = toUnixTimestamp(mtime);
783 binding.futimes(fd, atime, mtime, makeCallback(callback));
786 fs.futimesSync = function(fd, atime, mtime) {
787 atime = toUnixTimestamp(atime);
788 mtime = toUnixTimestamp(mtime);
789 binding.futimes(fd, atime, mtime);
792 function writeAll(fd, buffer, offset, length, position, callback) {
793 callback = maybeCallback(arguments[arguments.length - 1]);
795 // write(fd, buffer, offset, length, position, callback)
796 fs.write(fd, buffer, offset, length, position, function(writeErr, written) {
798 fs.close(fd, function() {
799 if (callback) callback(writeErr);
802 if (written === length) {
803 fs.close(fd, callback);
808 writeAll(fd, buffer, offset, length, position, callback);
814 fs.writeFile = function(path, data, encoding_, callback) {
815 var encoding = (typeof(encoding_) == 'string' ? encoding_ : 'utf8');
816 assertEncoding(encoding);
818 callback = maybeCallback(arguments[arguments.length - 1]);
819 fs.open(path, 'w', 438 /*=0666*/, function(openErr, fd) {
821 if (callback) callback(openErr);
823 var buffer = Buffer.isBuffer(data) ? data : new Buffer('' + data,
825 writeAll(fd, buffer, 0, buffer.length, 0, callback);
830 fs.writeFileSync = function(path, data, encoding) {
831 assertEncoding(encoding);
833 var fd = fs.openSync(path, 'w');
834 if (!Buffer.isBuffer(data)) {
835 data = new Buffer('' + data, encoding || 'utf8');
838 var length = data.length;
840 while (written < length) {
841 written += fs.writeSync(fd, data, written, length - written, written);
848 fs.appendFile = function(path, data, encoding_, callback) {
849 var encoding = (typeof(encoding_) == 'string' ? encoding_ : 'utf8');
850 assertEncoding(encoding);
852 callback = maybeCallback(arguments[arguments.length - 1]);
854 fs.open(path, 'a', 438 /*=0666*/, function(err, fd) {
855 if (err) return callback(err);
856 var buffer = Buffer.isBuffer(data) ? data : new Buffer('' + data, encoding);
857 writeAll(fd, buffer, 0, buffer.length, null, callback);
861 fs.appendFileSync = function(path, data, encoding) {
862 assertEncoding(encoding);
864 var fd = fs.openSync(path, 'a');
865 if (!Buffer.isBuffer(data)) {
866 data = new Buffer('' + data, encoding || 'utf8');
870 var length = data.length;
873 while (written < length) {
874 written += fs.writeSync(fd, data, written, length - written, position);
875 position += written; // XXX not safe with multiple concurrent writers?
882 function errnoException(errorno, syscall) {
883 // TODO make this more compatible with ErrnoException from src/node.cc
884 // Once all of Node is using this function the ErrnoException from
885 // src/node.cc should be removed.
886 var e = new Error(syscall + ' ' + errorno);
887 e.errno = e.code = errorno;
893 function FSWatcher() {
894 EventEmitter.call(this);
897 var FSEvent = process.binding('fs_event_wrap').FSEvent;
898 this._handle = new FSEvent();
899 this._handle.owner = this;
901 this._handle.onchange = function(status, event, filename) {
903 self._handle.close();
904 self.emit('error', errnoException(errno, 'watch'));
906 self.emit('change', event, filename);
910 util.inherits(FSWatcher, EventEmitter);
912 FSWatcher.prototype.start = function(filename, persistent) {
913 var r = this._handle.start(pathModule._makeLong(filename), persistent);
916 this._handle.close();
917 throw errnoException(errno, 'watch');
921 FSWatcher.prototype.close = function() {
922 this._handle.close();
925 fs.watch = function(filename) {
930 if ('object' == typeof arguments[1]) {
931 options = arguments[1];
932 listener = arguments[2];
935 listener = arguments[1];
938 if (options.persistent === undefined) options.persistent = true;
940 watcher = new FSWatcher();
941 watcher.start(filename, options.persistent);
944 watcher.addListener('change', listener);
951 // Stat Change Watchers
953 function StatWatcher() {
954 EventEmitter.call(this);
957 this._handle = new binding.StatWatcher();
959 // uv_fs_poll is a little more powerful than ev_stat but we curb it for
960 // the sake of backwards compatibility
963 this._handle.onchange = function(current, previous, newStatus) {
964 if (oldStatus === -1 &&
966 current.nlink === previous.nlink) return;
968 oldStatus = newStatus;
969 self.emit('change', current, previous);
972 this._handle.onstop = function() {
976 util.inherits(StatWatcher, EventEmitter);
979 StatWatcher.prototype.start = function(filename, persistent, interval) {
980 this._handle.start(pathModule._makeLong(filename), persistent, interval);
984 StatWatcher.prototype.stop = function() {
989 var statWatchers = {};
990 function inStatWatchers(filename) {
991 return Object.prototype.hasOwnProperty.call(statWatchers, filename) &&
992 statWatchers[filename];
996 fs.watchFile = function(filename) {
1001 // Poll interval in milliseconds. 5007 is what libev used to use. It's
1002 // a little on the slow side but let's stick with it for now to keep
1003 // behavioral changes to a minimum.
1008 if ('object' == typeof arguments[1]) {
1009 options = util._extend(options, arguments[1]);
1010 listener = arguments[2];
1012 listener = arguments[1];
1016 throw new Error('watchFile requires a listener function');
1019 if (inStatWatchers(filename)) {
1020 stat = statWatchers[filename];
1022 stat = statWatchers[filename] = new StatWatcher();
1023 stat.start(filename, options.persistent, options.interval);
1025 stat.addListener('change', listener);
1029 fs.unwatchFile = function(filename, listener) {
1030 if (!inStatWatchers(filename)) return;
1032 var stat = statWatchers[filename];
1034 if (typeof listener === 'function') {
1035 stat.removeListener('change', listener);
1037 stat.removeAllListeners('change');
1040 if (stat.listeners('change').length === 0) {
1042 statWatchers[filename] = undefined;
1047 // Not using realpath(2) because it's bad.
1048 // See: http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html
1050 var normalize = pathModule.normalize;
1052 // Regexp that finds the next partion of a (partial) path
1053 // result is [base_with_slash, base], e.g. ['somedir/', 'somedir']
1055 var nextPartRe = /(.*?)(?:[\/\\]+|$)/g;
1057 var nextPartRe = /(.*?)(?:[\/]+|$)/g;
1060 // Regex to find the device root, including trailing slash. E.g. 'c:\\'.
1062 var splitRootRe = /^(?:[a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?[\\\/]*/;
1064 var splitRootRe = /^[\/]*/;
1067 fs.realpathSync = function realpathSync(p, cache) {
1068 // make p is absolute
1069 p = pathModule.resolve(p);
1071 if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
1079 // current character position in p
1081 // the partial path so far, including a trailing slash if any
1083 // the partial path without a trailing slash (except when pointing at a root)
1085 // the partial path scanned in the previous round, with slash
1092 var m = splitRootRe.exec(p);
1098 // On windows, check that the root exists. On unix there is no need.
1099 if (isWindows && !knownHard[base]) {
1101 knownHard[base] = true;
1105 // walk down the path, swapping out linked pathparts for their real
1107 // NB: p.length changes.
1108 while (pos < p.length) {
1109 // find the next part
1110 nextPartRe.lastIndex = pos;
1111 var result = nextPartRe.exec(p);
1113 current += result[0];
1114 base = previous + result[1];
1115 pos = nextPartRe.lastIndex;
1117 // continue if not a symlink
1118 if (knownHard[base] || (cache && cache[base] === base)) {
1123 if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
1124 // some known symbolic link. no need to stat again.
1125 resolvedLink = cache[base];
1127 var stat = fs.lstatSync(base);
1128 if (!stat.isSymbolicLink()) {
1129 knownHard[base] = true;
1130 if (cache) cache[base] = base;
1134 // read the link if it wasn't read before
1135 // dev/ino always return 0 on windows, so skip the check.
1136 var linkTarget = null;
1138 var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
1139 if (seenLinks.hasOwnProperty(id)) {
1140 linkTarget = seenLinks[id];
1143 if (linkTarget === null) {
1145 linkTarget = fs.readlinkSync(base);
1147 resolvedLink = pathModule.resolve(previous, linkTarget);
1148 // track this, if given a cache.
1149 if (cache) cache[base] = resolvedLink;
1150 if (!isWindows) seenLinks[id] = linkTarget;
1153 // resolve the link, then start over
1154 p = pathModule.resolve(resolvedLink, p.slice(pos));
1158 if (cache) cache[original] = p;
1164 fs.realpath = function realpath(p, cache, cb) {
1165 if (typeof cb !== 'function') {
1166 cb = maybeCallback(cache);
1170 // make p is absolute
1171 p = pathModule.resolve(p);
1173 if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
1174 return process.nextTick(cb.bind(null, null, cache[p]));
1181 // current character position in p
1183 // the partial path so far, including a trailing slash if any
1185 // the partial path without a trailing slash (except when pointing at a root)
1187 // the partial path scanned in the previous round, with slash
1194 var m = splitRootRe.exec(p);
1200 // On windows, check that the root exists. On unix there is no need.
1201 if (isWindows && !knownHard[base]) {
1202 fs.lstat(base, function(err) {
1203 if (err) return cb(err);
1204 knownHard[base] = true;
1208 process.nextTick(LOOP);
1212 // walk down the path, swapping out linked pathparts for their real
1215 // stop if scanned past end of path
1216 if (pos >= p.length) {
1217 if (cache) cache[original] = p;
1221 // find the next part
1222 nextPartRe.lastIndex = pos;
1223 var result = nextPartRe.exec(p);
1225 current += result[0];
1226 base = previous + result[1];
1227 pos = nextPartRe.lastIndex;
1229 // continue if not a symlink
1230 if (knownHard[base] || (cache && cache[base] === base)) {
1231 return process.nextTick(LOOP);
1234 if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
1235 // known symbolic link. no need to stat again.
1236 return gotResolvedLink(cache[base]);
1239 return fs.lstat(base, gotStat);
1242 function gotStat(err, stat) {
1243 if (err) return cb(err);
1245 // if not a symlink, skip to the next path part
1246 if (!stat.isSymbolicLink()) {
1247 knownHard[base] = true;
1248 if (cache) cache[base] = base;
1249 return process.nextTick(LOOP);
1252 // stat & read the link if not read before
1253 // call gotTarget as soon as the link target is known
1254 // dev/ino always return 0 on windows, so skip the check.
1256 var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
1257 if (seenLinks.hasOwnProperty(id)) {
1258 return gotTarget(null, seenLinks[id], base);
1261 fs.stat(base, function(err) {
1262 if (err) return cb(err);
1264 fs.readlink(base, function(err, target) {
1265 if (!isWindows) seenLinks[id] = target;
1266 gotTarget(err, target);
1271 function gotTarget(err, target, base) {
1272 if (err) return cb(err);
1274 var resolvedLink = pathModule.resolve(previous, target);
1275 if (cache) cache[base] = resolvedLink;
1276 gotResolvedLink(resolvedLink);
1279 function gotResolvedLink(resolvedLink) {
1280 // resolve the link, then start over
1281 p = pathModule.resolve(resolvedLink, p.slice(pos));
1290 function allocNewPool() {
1291 pool = new Buffer(kPoolSize);
1297 fs.createReadStream = function(path, options) {
1298 return new ReadStream(path, options);
1301 var ReadStream = fs.ReadStream = function(path, options) {
1302 if (!(this instanceof ReadStream)) return new ReadStream(path, options);
1310 this.readable = true;
1311 this.paused = false;
1314 this.mode = 438; /*=0666*/
1315 this.bufferSize = 64 * 1024;
1317 options = options || {};
1319 // Mixin options into this
1320 var keys = Object.keys(options);
1321 for (var index = 0, length = keys.length; index < length; index++) {
1322 var key = keys[index];
1323 this[key] = options[key];
1326 assertEncoding(this.encoding);
1328 if (this.encoding) this.setEncoding(this.encoding);
1330 if (this.start !== undefined) {
1331 if ('number' !== typeof this.start) {
1332 throw TypeError('start must be a Number');
1334 if (this.end === undefined) {
1335 this.end = Infinity;
1336 } else if ('number' !== typeof this.end) {
1337 throw TypeError('end must be a Number');
1340 if (this.start > this.end) {
1341 throw new Error('start must be <= end');
1344 this.pos = this.start;
1347 if (this.fd !== null) {
1348 process.nextTick(function() {
1354 fs.open(this.path, this.flags, this.mode, function(err, fd) {
1356 self.emit('error', err);
1357 self.readable = false;
1362 self.emit('open', fd);
1366 util.inherits(ReadStream, Stream);
1368 fs.FileReadStream = fs.ReadStream; // support the legacy name
1370 ReadStream.prototype.setEncoding = function(encoding) {
1371 assertEncoding(encoding);
1372 var StringDecoder = require('string_decoder').StringDecoder; // lazy load
1373 this._decoder = new StringDecoder(encoding);
1377 ReadStream.prototype._read = function() {
1379 if (!this.readable || this.paused || this.reading) return;
1381 this.reading = true;
1383 if (!pool || pool.length - pool.used < kMinPoolSpace) {
1384 // discard the old pool. Can't add to the free list because
1385 // users might have refernces to slices on it.
1390 // Grab another reference to the pool in the case that while we're in the
1391 // thread pool another read() finishes up the pool, and allocates a new
1393 var thisPool = pool;
1394 var toRead = Math.min(pool.length - pool.used, ~~this.bufferSize);
1395 var start = pool.used;
1397 if (this.pos !== undefined) {
1398 toRead = Math.min(this.end - this.pos + 1, toRead);
1401 function afterRead(err, bytesRead) {
1402 self.reading = false;
1404 self.emit('error', err);
1405 self.readable = false;
1409 if (bytesRead === 0) {
1410 if (this._decoder) {
1411 var ret = this._decoder.end();
1413 this.emit('data', ret);
1420 var b = thisPool.slice(start, start + bytesRead);
1422 // Possible optimizition here?
1423 // Reclaim some bytes if bytesRead < toRead?
1424 // Would need to ensure that pool === thisPool.
1426 // do not emit events if the stream is paused
1432 // do not emit events anymore after we declared the stream unreadable
1433 if (!self.readable) return;
1439 fs.read(this.fd, pool, pool.used, toRead, this.pos, afterRead);
1441 if (this.pos !== undefined) {
1444 pool.used += toRead;
1448 ReadStream.prototype._emitData = function(d) {
1449 if (this._decoder) {
1450 var string = this._decoder.write(d);
1451 if (string.length) this.emit('data', string);
1453 this.emit('data', d);
1458 ReadStream.prototype.destroy = function() {
1461 if (!this.readable) return;
1462 this.readable = false;
1465 fs.close(self.fd, function(err) {
1467 self.emit('error', err);
1474 if (this.fd === null) {
1475 this.addListener('open', close);
1482 ReadStream.prototype.pause = function() {
1487 ReadStream.prototype.resume = function() {
1488 this.paused = false;
1491 var buffer = this.buffer;
1493 this._emitData(buffer);
1496 // hasn't opened yet.
1497 if (null == this.fd) return;
1504 fs.createWriteStream = function(path, options) {
1505 return new WriteStream(path, options);
1508 var WriteStream = fs.WriteStream = function(path, options) {
1509 if (!(this instanceof WriteStream)) return new WriteStream(path, options);
1515 this.writable = true;
1518 this.encoding = 'binary';
1519 this.mode = 438; /*=0666*/
1520 this.bytesWritten = 0;
1522 options = options || {};
1524 // Mixin options into this
1525 var keys = Object.keys(options);
1526 for (var index = 0, length = keys.length; index < length; index++) {
1527 var key = keys[index];
1528 this[key] = options[key];
1531 if (this.start !== undefined) {
1532 if ('number' !== typeof this.start) {
1533 throw TypeError('start must be a Number');
1535 if (this.start < 0) {
1536 throw new Error('start must be >= zero');
1539 this.pos = this.start;
1545 if (this.fd === null) {
1546 this._open = fs.open;
1547 this._queue.push([this._open, this.path, this.flags, this.mode, undefined]);
1551 util.inherits(WriteStream, Stream);
1553 fs.FileWriteStream = fs.WriteStream; // support the legacy name
1555 WriteStream.prototype.flush = function() {
1556 if (this.busy) return;
1559 var args = this._queue.shift();
1561 if (this.drainable) { this.emit('drain'); }
1567 var method = args.shift(),
1570 args.push(function(err) {
1574 self.writable = false;
1578 self.emit('error', err);
1582 if (method == fs.write) {
1583 self.bytesWritten += arguments[1];
1586 cb(null, arguments[1]);
1589 } else if (method === self._open) {
1590 // save reference for file pointer
1591 self.fd = arguments[1];
1592 self.emit('open', self.fd);
1594 } else if (method === fs.close) {
1595 // stop flushing after close
1606 // Inject the file pointer
1607 if (method !== self._open) {
1608 args.unshift(this.fd);
1611 method.apply(this, args);
1614 WriteStream.prototype.write = function(data) {
1615 if (!this.writable) {
1616 this.emit('error', new Error('stream not writable'));
1620 this.drainable = true;
1623 if (typeof(arguments[arguments.length - 1]) == 'function') {
1624 cb = arguments[arguments.length - 1];
1627 if (!Buffer.isBuffer(data)) {
1628 var encoding = 'utf8';
1629 if (typeof(arguments[1]) == 'string') encoding = arguments[1];
1630 assertEncoding(encoding);
1631 data = new Buffer('' + data, encoding);
1634 this._queue.push([fs.write, data, 0, data.length, this.pos, cb]);
1636 if (this.pos !== undefined) {
1637 this.pos += data.length;
1645 WriteStream.prototype.end = function(data, encoding, cb) {
1646 if (typeof(data) === 'function') {
1648 } else if (typeof(encoding) === 'function') {
1651 } else if (arguments.length > 0) {
1652 this.write(data, encoding);
1654 this.writable = false;
1655 this._queue.push([fs.close, cb]);
1659 WriteStream.prototype.destroy = function() {
1662 if (!this.writable) return;
1663 this.writable = false;
1666 fs.close(self.fd, function(err) {
1668 self.emit('error', err);
1675 if (this.fd === null) {
1676 this.addListener('open', close);
1682 // There is no shutdown() for files.
1683 WriteStream.prototype.destroySoon = WriteStream.prototype.end;
1686 // SyncWriteStream is internal. DO NOT USE.
1687 // Temporary hack for process.stdout and process.stderr when piped to files.
1688 function SyncWriteStream(fd) {
1692 this.writable = true;
1693 this.readable = false;
1696 util.inherits(SyncWriteStream, Stream);
1700 fs.SyncWriteStream = SyncWriteStream;
1703 SyncWriteStream.prototype.write = function(data, arg1, arg2) {
1708 if (typeof arg1 === 'string') {
1711 } else if (typeof arg1 === 'function') {
1714 throw new Error('bad arg');
1717 assertEncoding(encoding);
1719 // Change strings to buffers. SLOW
1720 if (typeof data == 'string') {
1721 data = new Buffer(data, encoding);
1724 fs.writeSync(this.fd, data, 0, data.length);
1727 process.nextTick(cb);
1734 SyncWriteStream.prototype.end = function(data, arg1, arg2) {
1736 this.write(data, arg1, arg2);
1742 SyncWriteStream.prototype.destroy = function() {
1743 fs.closeSync(this.fd);
1749 SyncWriteStream.prototype.destroySoon = SyncWriteStream.prototype.destroy;