1 // Maintainers, keep in mind that ES1-style octal literals (`0666`) are not
2 // allowed in strict mode. Use ES6-style octal literals instead (`0o666`).
6 const SlowBuffer = require('buffer').SlowBuffer;
7 const util = require('util');
8 const pathModule = require('path');
10 const binding = process.binding('fs');
11 const constants = require('constants');
13 const Buffer = require('buffer').Buffer;
14 const Stream = require('stream').Stream;
15 const EventEmitter = require('events');
16 const FSReqWrap = binding.FSReqWrap;
17 const FSEvent = process.binding('fs_event_wrap').FSEvent;
19 const Readable = Stream.Readable;
20 const Writable = Stream.Writable;
22 const kMinPoolSpace = 128;
23 const kMaxLength = require('buffer').kMaxLength;
25 const O_APPEND = constants.O_APPEND || 0;
26 const O_CREAT = constants.O_CREAT || 0;
27 const O_EXCL = constants.O_EXCL || 0;
28 const O_RDONLY = constants.O_RDONLY || 0;
29 const O_RDWR = constants.O_RDWR || 0;
30 const O_SYNC = constants.O_SYNC || 0;
31 const O_TRUNC = constants.O_TRUNC || 0;
32 const O_WRONLY = constants.O_WRONLY || 0;
34 const isWindows = process.platform === 'win32';
36 const DEBUG = process.env.NODE_DEBUG && /fs/.test(process.env.NODE_DEBUG);
37 const errnoException = util._errnoException;
39 function throwOptionsError(options) {
40 throw new TypeError('Expected options to be either an object or a string, ' +
41 'but got ' + typeof options + ' instead');
45 // Only enable in debug mode. A backtrace uses ~1000 bytes of heap space and
46 // is fairly slow to generate.
48 var backtrace = new Error();
49 return function(err) {
51 backtrace.stack = err.name + ': ' + err.message +
52 backtrace.stack.substr(backtrace.name.length);
58 return function(err) {
60 throw err; // Forgot a callback but don't know where? Use NODE_DEBUG=fs
65 function maybeCallback(cb) {
66 return typeof cb === 'function' ? cb : rethrow();
69 // Ensure that callbacks run in the global context. Only use this function
70 // for callbacks that are passed to the binding layer, callbacks that are
71 // invoked from JS already run in the proper scope.
72 function makeCallback(cb) {
73 if (cb === undefined) {
77 if (typeof cb !== 'function') {
78 throw new TypeError('callback must be a function');
82 return cb.apply(null, arguments);
86 function assertEncoding(encoding) {
87 if (encoding && !Buffer.isEncoding(encoding)) {
88 throw new Error('Unknown encoding: ' + encoding);
92 function nullCheck(path, callback) {
93 if (('' + path).indexOf('\u0000') !== -1) {
94 var er = new Error('Path must be a string without null bytes.');
96 if (typeof callback !== 'function')
98 process.nextTick(callback, er);
104 // Static method to set the stats properties on a Stats object.
126 this.blksize = blksize;
129 this.blocks = blocks;
130 this.atime = new Date(atim_msec);
131 this.mtime = new Date(mtim_msec);
132 this.ctime = new Date(ctim_msec);
133 this.birthtime = new Date(birthtim_msec);
136 // Create a C++ binding to the function which creates a Stats object.
137 binding.FSInitialize(fs.Stats);
139 fs.Stats.prototype._checkModeProperty = function(property) {
140 return ((this.mode & constants.S_IFMT) === property);
143 fs.Stats.prototype.isDirectory = function() {
144 return this._checkModeProperty(constants.S_IFDIR);
147 fs.Stats.prototype.isFile = function() {
148 return this._checkModeProperty(constants.S_IFREG);
151 fs.Stats.prototype.isBlockDevice = function() {
152 return this._checkModeProperty(constants.S_IFBLK);
155 fs.Stats.prototype.isCharacterDevice = function() {
156 return this._checkModeProperty(constants.S_IFCHR);
159 fs.Stats.prototype.isSymbolicLink = function() {
160 return this._checkModeProperty(constants.S_IFLNK);
163 fs.Stats.prototype.isFIFO = function() {
164 return this._checkModeProperty(constants.S_IFIFO);
167 fs.Stats.prototype.isSocket = function() {
168 return this._checkModeProperty(constants.S_IFSOCK);
171 // Don't allow mode to accidentally be overwritten.
172 ['F_OK', 'R_OK', 'W_OK', 'X_OK'].forEach(function(key) {
173 Object.defineProperty(fs, key, {
174 enumerable: true, value: constants[key] || 0, writable: false
178 fs.access = function(path, mode, callback) {
179 if (typeof mode === 'function') {
182 } else if (typeof callback !== 'function') {
183 throw new TypeError('callback must be a function');
186 if (!nullCheck(path, callback))
190 var req = new FSReqWrap();
191 req.oncomplete = makeCallback(callback);
192 binding.access(pathModule._makeLong(path), mode, req);
195 fs.accessSync = function(path, mode) {
198 if (mode === undefined)
203 binding.access(pathModule._makeLong(path), mode);
206 fs.exists = function(path, callback) {
207 if (!nullCheck(path, cb)) return;
208 var req = new FSReqWrap();
210 binding.stat(pathModule._makeLong(path), req);
211 function cb(err, stats) {
212 if (callback) callback(err ? false : true);
216 fs.existsSync = function(path) {
219 binding.stat(pathModule._makeLong(path));
226 fs.readFile = function(path, options, callback_) {
227 var callback = maybeCallback(arguments[arguments.length - 1]);
229 if (!options || typeof options === 'function') {
230 options = { encoding: null, flag: 'r' };
231 } else if (typeof options === 'string') {
232 options = { encoding: options, flag: 'r' };
233 } else if (typeof options !== 'object') {
234 throwOptionsError(options);
237 var encoding = options.encoding;
238 assertEncoding(encoding);
240 var flag = options.flag || 'r';
242 if (!nullCheck(path, callback))
245 var context = new ReadFileContext(callback, encoding);
246 var req = new FSReqWrap();
247 req.context = context;
248 req.oncomplete = readFileAfterOpen;
250 binding.open(pathModule._makeLong(path),
256 const kReadFileBufferLength = 8 * 1024;
258 function ReadFileContext(callback, encoding) {
260 this.size = undefined;
261 this.callback = callback;
265 this.encoding = encoding;
269 ReadFileContext.prototype.read = function() {
274 if (this.size === 0) {
275 buffer = this.buffer = new SlowBuffer(kReadFileBufferLength);
277 length = kReadFileBufferLength;
279 buffer = this.buffer;
281 length = this.size - this.pos;
284 var req = new FSReqWrap();
285 req.oncomplete = readFileAfterRead;
288 binding.read(this.fd, buffer, offset, length, -1, req);
291 ReadFileContext.prototype.close = function(err) {
292 var req = new FSReqWrap();
293 req.oncomplete = readFileAfterClose;
296 binding.close(this.fd, req);
299 function readFileAfterOpen(err, fd) {
300 var context = this.context;
303 context.callback(err);
309 var req = new FSReqWrap();
310 req.oncomplete = readFileAfterStat;
311 req.context = context;
312 binding.fstat(fd, req);
315 function readFileAfterStat(err, st) {
316 var context = this.context;
319 return context.close(err);
321 var size = context.size = st.isFile() ? st.size : 0;
324 context.buffers = [];
329 if (size > kMaxLength) {
330 err = new RangeError('File size is greater than possible Buffer: ' +
331 `0x${kMaxLength.toString(16)} bytes`);
332 return context.close(err);
335 context.buffer = new SlowBuffer(size);
339 function readFileAfterRead(err, bytesRead) {
340 var context = this.context;
343 return context.close(err);
346 return context.close();
348 context.pos += bytesRead;
350 if (context.size !== 0) {
351 if (context.pos === context.size)
356 // unknown size, just read until we don't get bytes.
357 context.buffers.push(context.buffer.slice(0, bytesRead));
362 function readFileAfterClose(err) {
363 var context = this.context;
365 var callback = context.callback;
368 return callback(context.err);
370 if (context.size === 0)
371 buffer = Buffer.concat(context.buffers, context.pos);
372 else if (context.pos < context.size)
373 buffer = context.buffer.slice(0, context.pos);
375 buffer = context.buffer;
377 if (context.encoding)
378 buffer = buffer.toString(context.encoding);
380 callback(err, buffer);
384 fs.readFileSync = function(path, options) {
386 options = { encoding: null, flag: 'r' };
387 } else if (typeof options === 'string') {
388 options = { encoding: options, flag: 'r' };
389 } else if (typeof options !== 'object') {
390 throwOptionsError(options);
393 var encoding = options.encoding;
394 assertEncoding(encoding);
396 var flag = options.flag || 'r';
397 var fd = fs.openSync(path, flag, 0o666);
403 st = fs.fstatSync(fd);
404 size = st.isFile() ? st.size : 0;
407 if (threw) fs.closeSync(fd);
411 var buffer; // single buffer with file data
412 var buffers; // list for when size is unknown
419 buffer = new Buffer(size);
422 if (threw) fs.closeSync(fd);
433 bytesRead = fs.readSync(fd, buffer, pos, size - pos);
435 // the kernel lies about many files.
436 // Go ahead and try to read some bytes.
437 buffer = new Buffer(8192);
438 bytesRead = fs.readSync(fd, buffer, 0, 8192);
440 buffers.push(buffer.slice(0, bytesRead));
445 if (threw) fs.closeSync(fd);
449 done = (bytesRead === 0) || (size !== 0 && pos >= size);
455 // data was collected into the buffers list.
456 buffer = Buffer.concat(buffers, pos);
457 } else if (pos < size) {
458 buffer = buffer.slice(0, pos);
461 if (encoding) buffer = buffer.toString(encoding);
466 // Used by binding.open and friends
467 function stringToFlags(flag) {
468 // Only mess with strings
469 if (typeof flag !== 'string') {
474 case 'r' : return O_RDONLY;
475 case 'rs' : // fall through
476 case 'sr' : return O_RDONLY | O_SYNC;
477 case 'r+' : return O_RDWR;
478 case 'rs+' : // fall through
479 case 'sr+' : return O_RDWR | O_SYNC;
481 case 'w' : return O_TRUNC | O_CREAT | O_WRONLY;
482 case 'wx' : // fall through
483 case 'xw' : return O_TRUNC | O_CREAT | O_WRONLY | O_EXCL;
485 case 'w+' : return O_TRUNC | O_CREAT | O_RDWR;
486 case 'wx+': // fall through
487 case 'xw+': return O_TRUNC | O_CREAT | O_RDWR | O_EXCL;
489 case 'a' : return O_APPEND | O_CREAT | O_WRONLY;
490 case 'ax' : // fall through
491 case 'xa' : return O_APPEND | O_CREAT | O_WRONLY | O_EXCL;
493 case 'a+' : return O_APPEND | O_CREAT | O_RDWR;
494 case 'ax+': // fall through
495 case 'xa+': return O_APPEND | O_CREAT | O_RDWR | O_EXCL;
498 throw new Error('Unknown file open flag: ' + flag);
501 // exported but hidden, only used by test/simple/test-fs-open-flags.js
502 Object.defineProperty(exports, '_stringToFlags', {
508 // Yes, the follow could be easily DRYed up but I provide the explicit
509 // list to make the arguments clear.
511 fs.close = function(fd, callback) {
512 var req = new FSReqWrap();
513 req.oncomplete = makeCallback(callback);
514 binding.close(fd, req);
517 fs.closeSync = function(fd) {
518 return binding.close(fd);
521 function modeNum(m, def) {
522 if (typeof m === 'number')
524 if (typeof m === 'string')
525 return parseInt(m, 8);
531 fs.open = function(path, flags, mode, callback_) {
532 var callback = makeCallback(arguments[arguments.length - 1]);
533 mode = modeNum(mode, 0o666);
535 if (!nullCheck(path, callback)) return;
537 var req = new FSReqWrap();
538 req.oncomplete = callback;
540 binding.open(pathModule._makeLong(path),
541 stringToFlags(flags),
546 fs.openSync = function(path, flags, mode) {
547 mode = modeNum(mode, 0o666);
549 return binding.open(pathModule._makeLong(path), stringToFlags(flags), mode);
552 fs.read = function(fd, buffer, offset, length, position, callback) {
553 if (!(buffer instanceof Buffer)) {
554 // legacy string interface (fd, length, position, encoding, callback)
555 var cb = arguments[4],
556 encoding = arguments[3];
558 assertEncoding(encoding);
560 position = arguments[2];
561 length = arguments[1];
562 buffer = new Buffer(length);
565 callback = function(err, bytesRead) {
568 var str = (bytesRead > 0) ? buffer.toString(encoding, 0, bytesRead) : '';
570 (cb)(err, str, bytesRead);
574 function wrapper(err, bytesRead) {
575 // Retain a reference to buffer so that it can't be GC'ed too soon.
576 callback && callback(err, bytesRead || 0, buffer);
579 var req = new FSReqWrap();
580 req.oncomplete = wrapper;
582 binding.read(fd, buffer, offset, length, position, req);
585 fs.readSync = function(fd, buffer, offset, length, position) {
589 if (!(buffer instanceof Buffer)) {
590 // legacy string interface (fd, length, position, encoding, callback)
592 encoding = arguments[3];
594 assertEncoding(encoding);
596 position = arguments[2];
597 length = arguments[1];
598 buffer = new Buffer(length);
603 var r = binding.read(fd, buffer, offset, length, position);
608 var str = (r > 0) ? buffer.toString(encoding, 0, r) : '';
613 // fs.write(fd, buffer, offset, length[, position], callback);
615 // fs.write(fd, string[, position[, encoding]], callback);
616 fs.write = function(fd, buffer, offset, length, position, callback) {
617 function wrapper(err, written) {
618 // Retain a reference to buffer so that it can't be GC'ed too soon.
619 callback(err, written || 0, buffer);
622 var req = new FSReqWrap();
623 req.oncomplete = wrapper;
625 if (buffer instanceof Buffer) {
626 // if no position is passed then assume null
627 if (typeof position === 'function') {
631 callback = maybeCallback(callback);
632 return binding.writeBuffer(fd, buffer, offset, length, position, req);
635 if (typeof buffer !== 'string')
637 if (typeof position !== 'function') {
638 if (typeof offset === 'function') {
646 callback = maybeCallback(position);
647 return binding.writeString(fd, buffer, offset, length, req);
651 // fs.writeSync(fd, buffer, offset, length[, position]);
653 // fs.writeSync(fd, string[, position[, encoding]]);
654 fs.writeSync = function(fd, buffer, offset, length, position) {
655 if (buffer instanceof Buffer) {
656 if (position === undefined)
658 return binding.writeBuffer(fd, buffer, offset, length, position);
660 if (typeof buffer !== 'string')
662 if (offset === undefined)
664 return binding.writeString(fd, buffer, offset, length, position);
667 fs.rename = function(oldPath, newPath, callback) {
668 callback = makeCallback(callback);
669 if (!nullCheck(oldPath, callback)) return;
670 if (!nullCheck(newPath, callback)) return;
671 var req = new FSReqWrap();
672 req.oncomplete = callback;
673 binding.rename(pathModule._makeLong(oldPath),
674 pathModule._makeLong(newPath),
678 fs.renameSync = function(oldPath, newPath) {
681 return binding.rename(pathModule._makeLong(oldPath),
682 pathModule._makeLong(newPath));
685 fs.truncate = function(path, len, callback) {
686 if (typeof path === 'number') {
687 return fs.ftruncate(path, len, callback);
689 if (typeof len === 'function') {
692 } else if (len === undefined) {
696 callback = maybeCallback(callback);
697 fs.open(path, 'r+', function(er, fd) {
698 if (er) return callback(er);
699 var req = new FSReqWrap();
700 req.oncomplete = function ftruncateCb(er) {
701 fs.close(fd, function(er2) {
705 binding.ftruncate(fd, len, req);
709 fs.truncateSync = function(path, len) {
710 if (typeof path === 'number') {
712 return fs.ftruncateSync(path, len);
714 if (len === undefined) {
717 // allow error to be thrown, but still close fd.
718 var fd = fs.openSync(path, 'r+');
722 ret = fs.ftruncateSync(fd, len);
729 fs.ftruncate = function(fd, len, callback) {
730 if (typeof len === 'function') {
733 } else if (len === undefined) {
736 var req = new FSReqWrap();
737 req.oncomplete = makeCallback(callback);
738 binding.ftruncate(fd, len, req);
741 fs.ftruncateSync = function(fd, len) {
742 if (len === undefined) {
745 return binding.ftruncate(fd, len);
748 fs.rmdir = function(path, callback) {
749 callback = maybeCallback(callback);
750 if (!nullCheck(path, callback)) return;
751 var req = new FSReqWrap();
752 req.oncomplete = callback;
753 binding.rmdir(pathModule._makeLong(path), req);
756 fs.rmdirSync = function(path) {
758 return binding.rmdir(pathModule._makeLong(path));
761 fs.fdatasync = function(fd, callback) {
762 var req = new FSReqWrap();
763 req.oncomplete = makeCallback(callback);
764 binding.fdatasync(fd, req);
767 fs.fdatasyncSync = function(fd) {
768 return binding.fdatasync(fd);
771 fs.fsync = function(fd, callback) {
772 var req = new FSReqWrap();
773 req.oncomplete = makeCallback(callback);
774 binding.fsync(fd, req);
777 fs.fsyncSync = function(fd) {
778 return binding.fsync(fd);
781 fs.mkdir = function(path, mode, callback) {
782 if (typeof mode === 'function') callback = mode;
783 callback = makeCallback(callback);
784 if (!nullCheck(path, callback)) return;
785 var req = new FSReqWrap();
786 req.oncomplete = callback;
787 binding.mkdir(pathModule._makeLong(path),
788 modeNum(mode, 0o777),
792 fs.mkdirSync = function(path, mode) {
794 return binding.mkdir(pathModule._makeLong(path),
795 modeNum(mode, 0o777));
798 fs.readdir = function(path, callback) {
799 callback = makeCallback(callback);
800 if (!nullCheck(path, callback)) return;
801 var req = new FSReqWrap();
802 req.oncomplete = callback;
803 binding.readdir(pathModule._makeLong(path), req);
806 fs.readdirSync = function(path) {
808 return binding.readdir(pathModule._makeLong(path));
811 fs.fstat = function(fd, callback) {
812 var req = new FSReqWrap();
813 req.oncomplete = makeCallback(callback);
814 binding.fstat(fd, req);
817 fs.lstat = function(path, callback) {
818 callback = makeCallback(callback);
819 if (!nullCheck(path, callback)) return;
820 var req = new FSReqWrap();
821 req.oncomplete = callback;
822 binding.lstat(pathModule._makeLong(path), req);
825 fs.stat = function(path, callback) {
826 callback = makeCallback(callback);
827 if (!nullCheck(path, callback)) return;
828 var req = new FSReqWrap();
829 req.oncomplete = callback;
830 binding.stat(pathModule._makeLong(path), req);
833 fs.fstatSync = function(fd) {
834 return binding.fstat(fd);
837 fs.lstatSync = function(path) {
839 return binding.lstat(pathModule._makeLong(path));
842 fs.statSync = function(path) {
844 return binding.stat(pathModule._makeLong(path));
847 fs.readlink = function(path, callback) {
848 callback = makeCallback(callback);
849 if (!nullCheck(path, callback)) return;
850 var req = new FSReqWrap();
851 req.oncomplete = callback;
852 binding.readlink(pathModule._makeLong(path), req);
855 fs.readlinkSync = function(path) {
857 return binding.readlink(pathModule._makeLong(path));
860 function preprocessSymlinkDestination(path, type, linkPath) {
862 // No preprocessing is needed on Unix.
864 } else if (type === 'junction') {
865 // Junctions paths need to be absolute and \\?\-prefixed.
866 // A relative target is relative to the link's parent directory.
867 path = pathModule.resolve(linkPath, '..', path);
868 return pathModule._makeLong(path);
870 // Windows symlinks don't tolerate forward slashes.
871 return ('' + path).replace(/\//g, '\\');
875 fs.symlink = function(target, path, type_, callback_) {
876 var type = (typeof type_ === 'string' ? type_ : null);
877 var callback = makeCallback(arguments[arguments.length - 1]);
879 if (!nullCheck(target, callback)) return;
880 if (!nullCheck(path, callback)) return;
882 var req = new FSReqWrap();
883 req.oncomplete = callback;
885 binding.symlink(preprocessSymlinkDestination(target, type, path),
886 pathModule._makeLong(path),
891 fs.symlinkSync = function(target, path, type) {
892 type = (typeof type === 'string' ? type : null);
897 return binding.symlink(preprocessSymlinkDestination(target, type, path),
898 pathModule._makeLong(path),
902 fs.link = function(srcpath, dstpath, callback) {
903 callback = makeCallback(callback);
904 if (!nullCheck(srcpath, callback)) return;
905 if (!nullCheck(dstpath, callback)) return;
907 var req = new FSReqWrap();
908 req.oncomplete = callback;
910 binding.link(pathModule._makeLong(srcpath),
911 pathModule._makeLong(dstpath),
915 fs.linkSync = function(srcpath, dstpath) {
918 return binding.link(pathModule._makeLong(srcpath),
919 pathModule._makeLong(dstpath));
922 fs.unlink = function(path, callback) {
923 callback = makeCallback(callback);
924 if (!nullCheck(path, callback)) return;
925 var req = new FSReqWrap();
926 req.oncomplete = callback;
927 binding.unlink(pathModule._makeLong(path), req);
930 fs.unlinkSync = function(path) {
932 return binding.unlink(pathModule._makeLong(path));
935 fs.fchmod = function(fd, mode, callback) {
936 var req = new FSReqWrap();
937 req.oncomplete = makeCallback(callback);
938 binding.fchmod(fd, modeNum(mode), req);
941 fs.fchmodSync = function(fd, mode) {
942 return binding.fchmod(fd, modeNum(mode));
945 if (constants.hasOwnProperty('O_SYMLINK')) {
946 fs.lchmod = function(path, mode, callback) {
947 callback = maybeCallback(callback);
948 fs.open(path, constants.O_WRONLY | constants.O_SYMLINK, function(err, fd) {
953 // prefer to return the chmod error, if one occurs,
954 // but still try to close, and report closing errors if they occur.
955 fs.fchmod(fd, mode, function(err) {
956 fs.close(fd, function(err2) {
957 callback(err || err2);
963 fs.lchmodSync = function(path, mode) {
964 var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK);
966 // prefer to return the chmod error, if one occurs,
967 // but still try to close, and report closing errors if they occur.
970 ret = fs.fchmodSync(fd, mode);
979 if (err || err2) throw (err || err2);
985 fs.chmod = function(path, mode, callback) {
986 callback = makeCallback(callback);
987 if (!nullCheck(path, callback)) return;
988 var req = new FSReqWrap();
989 req.oncomplete = callback;
990 binding.chmod(pathModule._makeLong(path),
995 fs.chmodSync = function(path, mode) {
997 return binding.chmod(pathModule._makeLong(path), modeNum(mode));
1000 if (constants.hasOwnProperty('O_SYMLINK')) {
1001 fs.lchown = function(path, uid, gid, callback) {
1002 callback = maybeCallback(callback);
1003 fs.open(path, constants.O_WRONLY | constants.O_SYMLINK, function(err, fd) {
1008 fs.fchown(fd, uid, gid, callback);
1012 fs.lchownSync = function(path, uid, gid) {
1013 var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK);
1014 return fs.fchownSync(fd, uid, gid);
1018 fs.fchown = function(fd, uid, gid, callback) {
1019 var req = new FSReqWrap();
1020 req.oncomplete = makeCallback(callback);
1021 binding.fchown(fd, uid, gid, req);
1024 fs.fchownSync = function(fd, uid, gid) {
1025 return binding.fchown(fd, uid, gid);
1028 fs.chown = function(path, uid, gid, callback) {
1029 callback = makeCallback(callback);
1030 if (!nullCheck(path, callback)) return;
1031 var req = new FSReqWrap();
1032 req.oncomplete = callback;
1033 binding.chown(pathModule._makeLong(path), uid, gid, req);
1036 fs.chownSync = function(path, uid, gid) {
1038 return binding.chown(pathModule._makeLong(path), uid, gid);
1041 // converts Date or number to a fractional UNIX timestamp
1042 function toUnixTimestamp(time) {
1043 if (typeof time === 'string' && +time == time) {
1046 if (typeof time === 'number') {
1047 if (!Number.isFinite(time) || time < 0) {
1048 return Date.now() / 1000;
1052 if (util.isDate(time)) {
1053 // convert to 123.456 UNIX timestamp
1054 return time.getTime() / 1000;
1056 throw new Error('Cannot parse time: ' + time);
1059 // exported for unit tests, not for public consumption
1060 fs._toUnixTimestamp = toUnixTimestamp;
1062 fs.utimes = function(path, atime, mtime, callback) {
1063 callback = makeCallback(callback);
1064 if (!nullCheck(path, callback)) return;
1065 var req = new FSReqWrap();
1066 req.oncomplete = callback;
1067 binding.utimes(pathModule._makeLong(path),
1068 toUnixTimestamp(atime),
1069 toUnixTimestamp(mtime),
1073 fs.utimesSync = function(path, atime, mtime) {
1075 atime = toUnixTimestamp(atime);
1076 mtime = toUnixTimestamp(mtime);
1077 binding.utimes(pathModule._makeLong(path), atime, mtime);
1080 fs.futimes = function(fd, atime, mtime, callback) {
1081 atime = toUnixTimestamp(atime);
1082 mtime = toUnixTimestamp(mtime);
1083 var req = new FSReqWrap();
1084 req.oncomplete = makeCallback(callback);
1085 binding.futimes(fd, atime, mtime, req);
1088 fs.futimesSync = function(fd, atime, mtime) {
1089 atime = toUnixTimestamp(atime);
1090 mtime = toUnixTimestamp(mtime);
1091 binding.futimes(fd, atime, mtime);
1094 function writeAll(fd, buffer, offset, length, position, callback_) {
1095 var callback = maybeCallback(arguments[arguments.length - 1]);
1097 // write(fd, buffer, offset, length, position, callback)
1098 fs.write(fd, buffer, offset, length, position, function(writeErr, written) {
1100 fs.close(fd, function() {
1101 if (callback) callback(writeErr);
1104 if (written === length) {
1105 fs.close(fd, callback);
1109 if (position !== null) {
1110 position += written;
1112 writeAll(fd, buffer, offset, length, position, callback);
1118 fs.writeFile = function(path, data, options, callback_) {
1119 var callback = maybeCallback(arguments[arguments.length - 1]);
1121 if (!options || typeof options === 'function') {
1122 options = { encoding: 'utf8', mode: 0o666, flag: 'w' };
1123 } else if (typeof options === 'string') {
1124 options = { encoding: options, mode: 0o666, flag: 'w' };
1125 } else if (typeof options !== 'object') {
1126 throwOptionsError(options);
1129 assertEncoding(options.encoding);
1131 var flag = options.flag || 'w';
1132 fs.open(path, flag, options.mode, function(openErr, fd) {
1134 if (callback) callback(openErr);
1136 var buffer = (data instanceof Buffer) ? data : new Buffer('' + data,
1137 options.encoding || 'utf8');
1138 var position = /a/.test(flag) ? null : 0;
1139 writeAll(fd, buffer, 0, buffer.length, position, callback);
1144 fs.writeFileSync = function(path, data, options) {
1146 options = { encoding: 'utf8', mode: 0o666, flag: 'w' };
1147 } else if (typeof options === 'string') {
1148 options = { encoding: options, mode: 0o666, flag: 'w' };
1149 } else if (typeof options !== 'object') {
1150 throwOptionsError(options);
1153 assertEncoding(options.encoding);
1155 var flag = options.flag || 'w';
1156 var fd = fs.openSync(path, flag, options.mode);
1157 if (!(data instanceof Buffer)) {
1158 data = new Buffer('' + data, options.encoding || 'utf8');
1161 var length = data.length;
1162 var position = /a/.test(flag) ? null : 0;
1164 while (length > 0) {
1165 var written = fs.writeSync(fd, data, offset, length, position);
1168 if (position !== null) {
1169 position += written;
1177 fs.appendFile = function(path, data, options, callback_) {
1178 var callback = maybeCallback(arguments[arguments.length - 1]);
1180 if (!options || typeof options === 'function') {
1181 options = { encoding: 'utf8', mode: 0o666, flag: 'a' };
1182 } else if (typeof options === 'string') {
1183 options = { encoding: options, mode: 0o666, flag: 'a' };
1184 } else if (typeof options !== 'object') {
1185 throwOptionsError(options);
1189 options = util._extend({ flag: 'a' }, options);
1190 fs.writeFile(path, data, options, callback);
1193 fs.appendFileSync = function(path, data, options) {
1195 options = { encoding: 'utf8', mode: 0o666, flag: 'a' };
1196 } else if (typeof options === 'string') {
1197 options = { encoding: options, mode: 0o666, flag: 'a' };
1198 } else if (typeof options !== 'object') {
1199 throwOptionsError(options);
1202 options = util._extend({ flag: 'a' }, options);
1204 fs.writeFileSync(path, data, options);
1207 function FSWatcher() {
1208 EventEmitter.call(this);
1211 this._handle = new FSEvent();
1212 this._handle.owner = this;
1214 this._handle.onchange = function(status, event, filename) {
1216 self._handle.close();
1217 const error = errnoException(status, `watch ${filename}`);
1218 error.filename = filename;
1219 self.emit('error', error);
1221 self.emit('change', event, filename);
1225 util.inherits(FSWatcher, EventEmitter);
1227 FSWatcher.prototype.start = function(filename, persistent, recursive) {
1228 nullCheck(filename);
1229 var err = this._handle.start(pathModule._makeLong(filename),
1233 this._handle.close();
1234 const error = errnoException(err, `watch ${filename}`);
1235 error.filename = filename;
1240 FSWatcher.prototype.close = function() {
1241 this._handle.close();
1244 fs.watch = function(filename) {
1245 nullCheck(filename);
1250 if (arguments[1] !== null && typeof arguments[1] === 'object') {
1251 options = arguments[1];
1252 listener = arguments[2];
1255 listener = arguments[1];
1258 if (options.persistent === undefined) options.persistent = true;
1259 if (options.recursive === undefined) options.recursive = false;
1261 watcher = new FSWatcher();
1262 watcher.start(filename, options.persistent, options.recursive);
1265 watcher.addListener('change', listener);
1272 // Stat Change Watchers
1274 function StatWatcher() {
1275 EventEmitter.call(this);
1278 this._handle = new binding.StatWatcher();
1280 // uv_fs_poll is a little more powerful than ev_stat but we curb it for
1281 // the sake of backwards compatibility
1284 this._handle.onchange = function(current, previous, newStatus) {
1285 if (oldStatus === -1 &&
1287 current.nlink === previous.nlink) return;
1289 oldStatus = newStatus;
1290 self.emit('change', current, previous);
1293 this._handle.onstop = function() {
1297 util.inherits(StatWatcher, EventEmitter);
1300 StatWatcher.prototype.start = function(filename, persistent, interval) {
1301 nullCheck(filename);
1302 this._handle.start(pathModule._makeLong(filename), persistent, interval);
1306 StatWatcher.prototype.stop = function() {
1307 this._handle.stop();
1311 const statWatchers = new Map();
1313 fs.watchFile = function(filename, options, listener) {
1314 nullCheck(filename);
1315 filename = pathModule.resolve(filename);
1319 // Poll interval in milliseconds. 5007 is what libev used to use. It's
1320 // a little on the slow side but let's stick with it for now to keep
1321 // behavioral changes to a minimum.
1326 if (options !== null && typeof options === 'object') {
1327 options = util._extend(defaults, options);
1333 if (typeof listener !== 'function') {
1334 throw new Error('watchFile requires a listener function');
1337 stat = statWatchers.get(filename);
1339 if (stat === undefined) {
1340 stat = new StatWatcher();
1341 stat.start(filename, options.persistent, options.interval);
1342 statWatchers.set(filename, stat);
1345 stat.addListener('change', listener);
1349 fs.unwatchFile = function(filename, listener) {
1350 nullCheck(filename);
1351 filename = pathModule.resolve(filename);
1352 var stat = statWatchers.get(filename);
1354 if (stat === undefined) return;
1356 if (typeof listener === 'function') {
1357 stat.removeListener('change', listener);
1359 stat.removeAllListeners('change');
1362 if (stat.listenerCount('change') === 0) {
1364 statWatchers.delete(filename);
1368 // Regexp that finds the next partion of a (partial) path
1369 // result is [base_with_slash, base], e.g. ['somedir/', 'somedir']
1371 var nextPartRe = /(.*?)(?:[\/\\]+|$)/g;
1373 var nextPartRe = /(.*?)(?:[\/]+|$)/g;
1376 // Regex to find the device root, including trailing slash. E.g. 'c:\\'.
1378 var splitRootRe = /^(?:[a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?[\\\/]*/;
1380 var splitRootRe = /^[\/]*/;
1383 fs.realpathSync = function realpathSync(p, cache) {
1384 // make p is absolute
1385 p = pathModule.resolve(p);
1387 if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
1395 // current character position in p
1397 // the partial path so far, including a trailing slash if any
1399 // the partial path without a trailing slash (except when pointing at a root)
1401 // the partial path scanned in the previous round, with slash
1408 var m = splitRootRe.exec(p);
1414 // On windows, check that the root exists. On unix there is no need.
1415 if (isWindows && !knownHard[base]) {
1417 knownHard[base] = true;
1421 // walk down the path, swapping out linked pathparts for their real
1423 // NB: p.length changes.
1424 while (pos < p.length) {
1425 // find the next part
1426 nextPartRe.lastIndex = pos;
1427 var result = nextPartRe.exec(p);
1429 current += result[0];
1430 base = previous + result[1];
1431 pos = nextPartRe.lastIndex;
1433 // continue if not a symlink
1434 if (knownHard[base] || (cache && cache[base] === base)) {
1439 if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
1440 // some known symbolic link. no need to stat again.
1441 resolvedLink = cache[base];
1443 var stat = fs.lstatSync(base);
1444 if (!stat.isSymbolicLink()) {
1445 knownHard[base] = true;
1446 if (cache) cache[base] = base;
1450 // read the link if it wasn't read before
1451 // dev/ino always return 0 on windows, so skip the check.
1452 var linkTarget = null;
1454 var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
1455 if (seenLinks.hasOwnProperty(id)) {
1456 linkTarget = seenLinks[id];
1459 if (linkTarget === null) {
1461 linkTarget = fs.readlinkSync(base);
1463 resolvedLink = pathModule.resolve(previous, linkTarget);
1464 // track this, if given a cache.
1465 if (cache) cache[base] = resolvedLink;
1466 if (!isWindows) seenLinks[id] = linkTarget;
1469 // resolve the link, then start over
1470 p = pathModule.resolve(resolvedLink, p.slice(pos));
1474 if (cache) cache[original] = p;
1480 fs.realpath = function realpath(p, cache, cb) {
1481 if (typeof cb !== 'function') {
1482 cb = maybeCallback(cache);
1486 // make p is absolute
1487 p = pathModule.resolve(p);
1489 if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
1490 return process.nextTick(cb.bind(null, null, cache[p]));
1497 // current character position in p
1499 // the partial path so far, including a trailing slash if any
1501 // the partial path without a trailing slash (except when pointing at a root)
1503 // the partial path scanned in the previous round, with slash
1510 var m = splitRootRe.exec(p);
1516 // On windows, check that the root exists. On unix there is no need.
1517 if (isWindows && !knownHard[base]) {
1518 fs.lstat(base, function(err) {
1519 if (err) return cb(err);
1520 knownHard[base] = true;
1524 process.nextTick(LOOP);
1528 // walk down the path, swapping out linked pathparts for their real
1531 // stop if scanned past end of path
1532 if (pos >= p.length) {
1533 if (cache) cache[original] = p;
1537 // find the next part
1538 nextPartRe.lastIndex = pos;
1539 var result = nextPartRe.exec(p);
1541 current += result[0];
1542 base = previous + result[1];
1543 pos = nextPartRe.lastIndex;
1545 // continue if not a symlink
1546 if (knownHard[base] || (cache && cache[base] === base)) {
1547 return process.nextTick(LOOP);
1550 if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
1551 // known symbolic link. no need to stat again.
1552 return gotResolvedLink(cache[base]);
1555 return fs.lstat(base, gotStat);
1558 function gotStat(err, stat) {
1559 if (err) return cb(err);
1561 // if not a symlink, skip to the next path part
1562 if (!stat.isSymbolicLink()) {
1563 knownHard[base] = true;
1564 if (cache) cache[base] = base;
1565 return process.nextTick(LOOP);
1568 // stat & read the link if not read before
1569 // call gotTarget as soon as the link target is known
1570 // dev/ino always return 0 on windows, so skip the check.
1572 var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
1573 if (seenLinks.hasOwnProperty(id)) {
1574 return gotTarget(null, seenLinks[id], base);
1577 fs.stat(base, function(err) {
1578 if (err) return cb(err);
1580 fs.readlink(base, function(err, target) {
1581 if (!isWindows) seenLinks[id] = target;
1582 gotTarget(err, target);
1587 function gotTarget(err, target, base) {
1588 if (err) return cb(err);
1590 var resolvedLink = pathModule.resolve(previous, target);
1591 if (cache) cache[base] = resolvedLink;
1592 gotResolvedLink(resolvedLink);
1595 function gotResolvedLink(resolvedLink) {
1596 // resolve the link, then start over
1597 p = pathModule.resolve(resolvedLink, p.slice(pos));
1605 function allocNewPool(poolSize) {
1606 pool = new Buffer(poolSize);
1611 fs.createReadStream = function(path, options) {
1612 return new ReadStream(path, options);
1615 util.inherits(ReadStream, Readable);
1616 fs.ReadStream = ReadStream;
1618 function ReadStream(path, options) {
1619 if (!(this instanceof ReadStream))
1620 return new ReadStream(path, options);
1622 if (options === undefined)
1624 else if (typeof options === 'string')
1625 options = { encoding: options };
1626 else if (options === null || typeof options !== 'object')
1627 throw new TypeError('options must be a string or an object');
1629 // a little bit bigger buffer and water marks by default
1630 options = Object.create(options);
1631 if (options.highWaterMark === undefined)
1632 options.highWaterMark = 64 * 1024;
1634 Readable.call(this, options);
1637 this.fd = options.fd === undefined ? null : options.fd;
1638 this.flags = options.flags === undefined ? 'r' : options.flags;
1639 this.mode = options.mode === undefined ? 0o666 : options.mode;
1641 this.start = options.start;
1642 this.end = options.end;
1643 this.autoClose = options.autoClose === undefined ? true : options.autoClose;
1644 this.pos = undefined;
1646 if (this.start !== undefined) {
1647 if (typeof this.start !== 'number') {
1648 throw new TypeError('start must be a Number');
1650 if (this.end === undefined) {
1651 this.end = Infinity;
1652 } else if (typeof this.end !== 'number') {
1653 throw new TypeError('end must be a Number');
1656 if (this.start > this.end) {
1657 throw new Error('start must be <= end');
1660 this.pos = this.start;
1663 if (typeof this.fd !== 'number')
1666 this.on('end', function() {
1667 if (this.autoClose) {
1673 fs.FileReadStream = fs.ReadStream; // support the legacy name
1675 ReadStream.prototype.open = function() {
1677 fs.open(this.path, this.flags, this.mode, function(er, fd) {
1679 if (self.autoClose) {
1682 self.emit('error', er);
1687 self.emit('open', fd);
1688 // start the flow of data.
1693 ReadStream.prototype._read = function(n) {
1694 if (typeof this.fd !== 'number')
1695 return this.once('open', function() {
1702 if (!pool || pool.length - pool.used < kMinPoolSpace) {
1703 // discard the old pool.
1705 allocNewPool(this._readableState.highWaterMark);
1708 // Grab another reference to the pool in the case that while we're
1709 // in the thread pool another read() finishes up the pool, and
1710 // allocates a new one.
1711 var thisPool = pool;
1712 var toRead = Math.min(pool.length - pool.used, n);
1713 var start = pool.used;
1715 if (this.pos !== undefined)
1716 toRead = Math.min(this.end - this.pos + 1, toRead);
1718 // already read everything we were supposed to read!
1721 return this.push(null);
1725 fs.read(this.fd, pool, pool.used, toRead, this.pos, onread);
1727 // move the pool positions, and internal position for reading.
1728 if (this.pos !== undefined)
1730 pool.used += toRead;
1732 function onread(er, bytesRead) {
1734 if (self.autoClose) {
1737 self.emit('error', er);
1741 b = thisPool.slice(start, start + bytesRead);
1749 ReadStream.prototype.destroy = function() {
1752 this.destroyed = true;
1757 ReadStream.prototype.close = function(cb) {
1760 this.once('close', cb);
1761 if (this.closed || typeof this.fd !== 'number') {
1762 if (typeof this.fd !== 'number') {
1763 this.once('open', close);
1766 return process.nextTick(this.emit.bind(this, 'close'));
1771 function close(fd) {
1772 fs.close(fd || self.fd, function(er) {
1774 self.emit('error', er);
1783 fs.createWriteStream = function(path, options) {
1784 return new WriteStream(path, options);
1787 util.inherits(WriteStream, Writable);
1788 fs.WriteStream = WriteStream;
1789 function WriteStream(path, options) {
1790 if (!(this instanceof WriteStream))
1791 return new WriteStream(path, options);
1793 if (options === undefined)
1795 else if (typeof options === 'string')
1796 options = { encoding: options };
1797 else if (options === null || typeof options !== 'object')
1798 throw new TypeError('options must be a string or an object');
1800 options = Object.create(options);
1802 Writable.call(this, options);
1805 this.fd = options.fd === undefined ? null : options.fd;
1806 this.flags = options.flags === undefined ? 'w' : options.flags;
1807 this.mode = options.mode === undefined ? 0o666 : options.mode;
1809 this.start = options.start;
1810 this.pos = undefined;
1811 this.bytesWritten = 0;
1813 if (this.start !== undefined) {
1814 if (typeof this.start !== 'number') {
1815 throw new TypeError('start must be a Number');
1817 if (this.start < 0) {
1818 throw new Error('start must be >= zero');
1821 this.pos = this.start;
1824 if (options.encoding)
1825 this.setDefaultEncoding(options.encoding);
1827 if (typeof this.fd !== 'number')
1830 // dispose on finish.
1831 this.once('finish', this.close);
1834 fs.FileWriteStream = fs.WriteStream; // support the legacy name
1837 WriteStream.prototype.open = function() {
1838 fs.open(this.path, this.flags, this.mode, function(er, fd) {
1841 this.emit('error', er);
1846 this.emit('open', fd);
1851 WriteStream.prototype._write = function(data, encoding, cb) {
1852 if (!(data instanceof Buffer))
1853 return this.emit('error', new Error('Invalid data'));
1855 if (typeof this.fd !== 'number')
1856 return this.once('open', function() {
1857 this._write(data, encoding, cb);
1861 fs.write(this.fd, data, 0, data.length, this.pos, function(er, bytes) {
1866 self.bytesWritten += bytes;
1870 if (this.pos !== undefined)
1871 this.pos += data.length;
1875 function writev(fd, chunks, position, callback) {
1876 function wrapper(err, written) {
1877 // Retain a reference to chunks so that they can't be GC'ed too soon.
1878 callback(err, written || 0, chunks);
1881 const req = new FSReqWrap();
1882 req.oncomplete = wrapper;
1883 binding.writeBuffers(fd, chunks, position, req);
1887 WriteStream.prototype._writev = function(data, cb) {
1888 if (typeof this.fd !== 'number')
1889 return this.once('open', function() {
1890 this._writev(data, cb);
1894 const len = data.length;
1895 const chunks = new Array(len);
1898 for (var i = 0; i < len; i++) {
1899 var chunk = data[i].chunk;
1902 size += chunk.length;
1905 writev(this.fd, chunks, this.pos, function(er, bytes) {
1910 self.bytesWritten += bytes;
1914 if (this.pos !== undefined)
1919 WriteStream.prototype.destroy = ReadStream.prototype.destroy;
1920 WriteStream.prototype.close = ReadStream.prototype.close;
1922 // There is no shutdown() for files.
1923 WriteStream.prototype.destroySoon = WriteStream.prototype.end;
1926 // SyncWriteStream is internal. DO NOT USE.
1927 // Temporary hack for process.stdout and process.stderr when piped to files.
1928 function SyncWriteStream(fd, options) {
1931 options = options || {};
1934 this.writable = true;
1935 this.readable = false;
1936 this.autoClose = options.autoClose === undefined ? true : options.autoClose;
1939 util.inherits(SyncWriteStream, Stream);
1943 Object.defineProperty(fs, 'SyncWriteStream', {
1946 value: SyncWriteStream
1949 SyncWriteStream.prototype.write = function(data, arg1, arg2) {
1954 if (typeof arg1 === 'string') {
1957 } else if (typeof arg1 === 'function') {
1960 throw new Error('bad arg');
1963 assertEncoding(encoding);
1965 // Change strings to buffers. SLOW
1966 if (typeof data === 'string') {
1967 data = new Buffer(data, encoding);
1970 fs.writeSync(this.fd, data, 0, data.length);
1973 process.nextTick(cb);
1980 SyncWriteStream.prototype.end = function(data, arg1, arg2) {
1982 this.write(data, arg1, arg2);
1988 SyncWriteStream.prototype.destroy = function() {
1990 fs.closeSync(this.fd);
1996 SyncWriteStream.prototype.destroySoon = SyncWriteStream.prototype.destroy;