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 Readable = Stream.Readable;
38 var Writable = Stream.Writable;
40 var kMinPoolSpace = 128;
42 var O_APPEND = constants.O_APPEND || 0;
43 var O_CREAT = constants.O_CREAT || 0;
44 var O_DIRECTORY = constants.O_DIRECTORY || 0;
45 var O_EXCL = constants.O_EXCL || 0;
46 var O_NOCTTY = constants.O_NOCTTY || 0;
47 var O_NOFOLLOW = constants.O_NOFOLLOW || 0;
48 var O_RDONLY = constants.O_RDONLY || 0;
49 var O_RDWR = constants.O_RDWR || 0;
50 var O_SYMLINK = constants.O_SYMLINK || 0;
51 var O_SYNC = constants.O_SYNC || 0;
52 var O_TRUNC = constants.O_TRUNC || 0;
53 var O_WRONLY = constants.O_WRONLY || 0;
55 var isWindows = process.platform === 'win32';
57 var DEBUG = process.env.NODE_DEBUG && /fs/.test(process.env.NODE_DEBUG);
60 // Only enable in debug mode. A backtrace uses ~1000 bytes of heap space and
61 // is fairly slow to generate.
63 var backtrace = new Error;
64 return function(err) {
66 backtrace.stack = err.name + ': ' + err.message +
67 backtrace.stack.substr(backtrace.name.length);
74 return function(err) {
76 throw err; // Forgot a callback but don't know where? Use NODE_DEBUG=fs
81 function maybeCallback(cb) {
82 return typeof cb === 'function' ? cb : rethrow();
85 // Ensure that callbacks run in the global context. Only use this function
86 // for callbacks that are passed to the binding layer, callbacks that are
87 // invoked from JS already run in the proper scope.
88 function makeCallback(cb) {
89 if (typeof cb !== 'function') {
94 return cb.apply(null, arguments);
98 function assertEncoding(encoding) {
99 if (encoding && !Buffer.isEncoding(encoding)) {
100 throw new Error('Unknown encoding: ' + encoding);
104 function nullCheck(path, callback) {
105 if (('' + path).indexOf('\u0000') !== -1) {
106 var er = new Error('Path must be a string without null bytes.');
109 process.nextTick(function() {
117 fs.Stats = binding.Stats;
119 fs.Stats.prototype._checkModeProperty = function(property) {
120 return ((this.mode & constants.S_IFMT) === property);
123 fs.Stats.prototype.isDirectory = function() {
124 return this._checkModeProperty(constants.S_IFDIR);
127 fs.Stats.prototype.isFile = function() {
128 return this._checkModeProperty(constants.S_IFREG);
131 fs.Stats.prototype.isBlockDevice = function() {
132 return this._checkModeProperty(constants.S_IFBLK);
135 fs.Stats.prototype.isCharacterDevice = function() {
136 return this._checkModeProperty(constants.S_IFCHR);
139 fs.Stats.prototype.isSymbolicLink = function() {
140 return this._checkModeProperty(constants.S_IFLNK);
143 fs.Stats.prototype.isFIFO = function() {
144 return this._checkModeProperty(constants.S_IFIFO);
147 fs.Stats.prototype.isSocket = function() {
148 return this._checkModeProperty(constants.S_IFSOCK);
151 fs.exists = function(path, callback) {
152 if (!nullCheck(path, cb)) return;
153 binding.stat(pathModule._makeLong(path), cb);
154 function cb(err, stats) {
155 if (callback) callback(err ? false : true);
159 fs.existsSync = function(path) {
162 binding.stat(pathModule._makeLong(path));
169 fs.readFile = function(path, options, callback_) {
170 var callback = maybeCallback(arguments[arguments.length - 1]);
172 if (typeof options === 'function' || !options) {
173 options = { encoding: null, flag: 'r' };
174 } else if (typeof options === 'string') {
175 options = { encoding: options, flag: 'r' };
176 } else if (!options) {
177 options = { encoding: null, flag: 'r' };
178 } else if (typeof options !== 'object') {
179 throw new TypeError('Bad arguments');
182 var encoding = options.encoding;
183 assertEncoding(encoding);
185 // first, stat the file, so we know the size.
187 var buffer; // single buffer with file data
188 var buffers; // list for when size is unknown
192 var flag = options.flag || 'r';
193 fs.open(path, flag, 438 /*=0666*/, function(er, fd_) {
194 if (er) return callback(er);
197 fs.fstat(fd, function(er, st) {
198 if (er) return callback(er);
201 // the kernel lies about many files.
202 // Go ahead and try to read some bytes.
207 buffer = new Buffer(size);
214 buffer = new Buffer(8192);
215 fs.read(fd, buffer, 0, 8192, -1, afterRead);
217 fs.read(fd, buffer, pos, size - pos, -1, afterRead);
221 function afterRead(er, bytesRead) {
223 return fs.close(fd, function(er2) {
228 if (bytesRead === 0) {
234 if (pos === size) close();
237 // unknown size, just read until we don't get bytes.
238 buffers.push(buffer.slice(0, bytesRead));
244 fs.close(fd, function(er) {
246 // collected the data into the buffers list.
247 buffer = Buffer.concat(buffers, pos);
248 } else if (pos < size) {
249 buffer = buffer.slice(0, pos);
252 if (encoding) buffer = buffer.toString(encoding);
253 return callback(er, buffer);
258 fs.readFileSync = function(path, options) {
260 options = { encoding: null, flag: 'r' };
261 } else if (typeof options === 'string') {
262 options = { encoding: options, flag: 'r' };
263 } else if (typeof options !== 'object') {
264 throw new TypeError('Bad arguments');
267 var encoding = options.encoding;
268 assertEncoding(encoding);
270 var flag = options.flag || 'r';
271 var fd = fs.openSync(path, flag, 438 /*=0666*/);
276 size = fs.fstatSync(fd).size;
279 if (threw) fs.closeSync(fd);
283 var buffer; // single buffer with file data
284 var buffers; // list for when size is unknown
289 buffer = new Buffer(size);
297 var bytesRead = fs.readSync(fd, buffer, pos, size - pos);
299 // the kernel lies about many files.
300 // Go ahead and try to read some bytes.
301 buffer = new Buffer(8192);
302 var bytesRead = fs.readSync(fd, buffer, 0, 8192);
304 buffers.push(buffer.slice(0, bytesRead));
309 if (threw) fs.closeSync(fd);
313 done = (bytesRead === 0) || (size !== 0 && pos >= size);
319 // data was collected into the buffers list.
320 buffer = Buffer.concat(buffers, pos);
321 } else if (pos < size) {
322 buffer = buffer.slice(0, pos);
325 if (encoding) buffer = buffer.toString(encoding);
330 // Used by binding.open and friends
331 function stringToFlags(flag) {
332 // Only mess with strings
333 if (typeof flag !== 'string') {
337 // O_EXCL is mandated by POSIX, Windows supports it too.
338 // Let's add a check anyway, just in case.
339 if (!O_EXCL && ~flag.indexOf('x')) {
340 throw errnoException('ENOSYS', 'fs.open(O_EXCL)');
344 case 'r' : return O_RDONLY;
345 case 'rs' : return O_RDONLY | O_SYNC;
346 case 'r+' : return O_RDWR;
347 case 'rs+' : return O_RDWR | O_SYNC;
349 case 'w' : return O_TRUNC | O_CREAT | O_WRONLY;
350 case 'wx' : // fall through
351 case 'xw' : return O_TRUNC | O_CREAT | O_WRONLY | O_EXCL;
353 case 'w+' : return O_TRUNC | O_CREAT | O_RDWR;
354 case 'wx+': // fall through
355 case 'xw+': return O_TRUNC | O_CREAT | O_RDWR | O_EXCL;
357 case 'a' : return O_APPEND | O_CREAT | O_WRONLY;
358 case 'ax' : // fall through
359 case 'xa' : return O_APPEND | O_CREAT | O_WRONLY | O_EXCL;
361 case 'a+' : return O_APPEND | O_CREAT | O_RDWR;
362 case 'ax+': // fall through
363 case 'xa+': return O_APPEND | O_CREAT | O_RDWR | O_EXCL;
366 throw new Error('Unknown file open flag: ' + flag);
369 // exported but hidden, only used by test/simple/test-fs-open-flags.js
370 Object.defineProperty(exports, '_stringToFlags', {
376 // Yes, the follow could be easily DRYed up but I provide the explicit
377 // list to make the arguments clear.
379 fs.close = function(fd, callback) {
380 binding.close(fd, makeCallback(callback));
383 fs.closeSync = function(fd) {
384 return binding.close(fd);
387 function modeNum(m, def) {
389 case 'number': return m;
390 case 'string': return parseInt(m, 8);
400 fs.open = function(path, flags, mode, callback) {
401 callback = makeCallback(arguments[arguments.length - 1]);
402 mode = modeNum(mode, 438 /*=0666*/);
404 if (!nullCheck(path, callback)) return;
405 binding.open(pathModule._makeLong(path),
406 stringToFlags(flags),
411 fs.openSync = function(path, flags, mode) {
412 mode = modeNum(mode, 438 /*=0666*/);
414 return binding.open(pathModule._makeLong(path), stringToFlags(flags), mode);
417 fs.read = function(fd, buffer, offset, length, position, callback) {
418 if (!Buffer.isBuffer(buffer)) {
419 // legacy string interface (fd, length, position, encoding, callback)
420 var cb = arguments[4],
421 encoding = arguments[3];
423 assertEncoding(encoding);
425 position = arguments[2];
426 length = arguments[1];
427 buffer = new Buffer(length);
430 callback = function(err, bytesRead) {
433 var str = (bytesRead > 0) ? buffer.toString(encoding, 0, bytesRead) : '';
435 (cb)(err, str, bytesRead);
439 function wrapper(err, bytesRead) {
440 // Retain a reference to buffer so that it can't be GC'ed too soon.
441 callback && callback(err, bytesRead || 0, buffer);
444 binding.read(fd, buffer, offset, length, position, wrapper);
447 fs.readSync = function(fd, buffer, offset, length, position) {
449 if (!Buffer.isBuffer(buffer)) {
450 // legacy string interface (fd, length, position, encoding, callback)
452 var encoding = arguments[3];
454 assertEncoding(encoding);
456 position = arguments[2];
457 length = arguments[1];
458 buffer = new Buffer(length);
463 var r = binding.read(fd, buffer, offset, length, position);
468 var str = (r > 0) ? buffer.toString(encoding, 0, r) : '';
472 fs.write = function(fd, buffer, offset, length, position, callback) {
473 if (!Buffer.isBuffer(buffer)) {
474 // legacy string interface (fd, data, position, encoding, callback)
475 callback = arguments[4];
476 position = arguments[2];
477 assertEncoding(arguments[3]);
479 buffer = new Buffer('' + arguments[1], arguments[3]);
481 length = buffer.length;
485 if (typeof callback == 'function') {
486 process.nextTick(function() {
487 callback(undefined, 0);
493 callback = maybeCallback(callback);
495 function wrapper(err, written) {
496 // Retain a reference to buffer so that it can't be GC'ed too soon.
497 callback(err, written || 0, buffer);
500 binding.write(fd, buffer, offset, length, position, wrapper);
503 fs.writeSync = function(fd, buffer, offset, length, position) {
504 if (!Buffer.isBuffer(buffer)) {
505 // legacy string interface (fd, data, position, encoding)
506 position = arguments[2];
507 assertEncoding(arguments[3]);
509 buffer = new Buffer('' + arguments[1], arguments[3]);
511 length = buffer.length;
513 if (!length) return 0;
515 return binding.write(fd, buffer, offset, length, position);
518 fs.rename = function(oldPath, newPath, callback) {
519 callback = makeCallback(callback);
520 if (!nullCheck(oldPath, callback)) return;
521 if (!nullCheck(newPath, callback)) return;
522 binding.rename(pathModule._makeLong(oldPath),
523 pathModule._makeLong(newPath),
527 fs.renameSync = function(oldPath, newPath) {
530 return binding.rename(pathModule._makeLong(oldPath),
531 pathModule._makeLong(newPath));
534 fs.truncate = function(path, len, callback) {
535 if (typeof path === 'number') {
537 return fs.ftruncate(path, len, callback);
539 if (typeof len === 'function') {
542 } else if (typeof len === 'undefined') {
545 callback = maybeCallback(callback);
546 fs.open(path, 'w', function(er, fd) {
547 if (er) return callback(er);
548 binding.ftruncate(fd, len, function(er) {
549 fs.close(fd, function(er2) {
556 fs.truncateSync = function(path, len) {
557 if (typeof path === 'number') {
559 return fs.ftruncateSync(path, len);
561 if (typeof len === 'undefined') {
564 // allow error to be thrown, but still close fd.
565 var fd = fs.openSync(path, 'w');
567 var ret = fs.ftruncateSync(fd, len);
574 fs.ftruncate = function(fd, len, callback) {
575 if (typeof len === 'function') {
578 } else if (typeof len === 'undefined') {
581 binding.ftruncate(fd, len, makeCallback(callback));
584 fs.ftruncateSync = function(fd, len) {
585 if (typeof len === 'undefined') {
588 return binding.ftruncate(fd, len);
591 fs.rmdir = function(path, callback) {
592 callback = makeCallback(callback);
593 if (!nullCheck(path, callback)) return;
594 binding.rmdir(pathModule._makeLong(path), callback);
597 fs.rmdirSync = function(path) {
599 return binding.rmdir(pathModule._makeLong(path));
602 fs.fdatasync = function(fd, callback) {
603 binding.fdatasync(fd, makeCallback(callback));
606 fs.fdatasyncSync = function(fd) {
607 return binding.fdatasync(fd);
610 fs.fsync = function(fd, callback) {
611 binding.fsync(fd, makeCallback(callback));
614 fs.fsyncSync = function(fd) {
615 return binding.fsync(fd);
618 fs.mkdir = function(path, mode, callback) {
619 if (typeof mode === 'function') callback = mode;
620 callback = makeCallback(callback);
621 if (!nullCheck(path, callback)) return;
622 binding.mkdir(pathModule._makeLong(path),
623 modeNum(mode, 511 /*=0777*/),
627 fs.mkdirSync = function(path, mode) {
629 return binding.mkdir(pathModule._makeLong(path),
630 modeNum(mode, 511 /*=0777*/));
633 fs.readdir = function(path, callback) {
634 callback = makeCallback(callback);
635 if (!nullCheck(path, callback)) return;
636 binding.readdir(pathModule._makeLong(path), callback);
639 fs.readdirSync = function(path) {
641 return binding.readdir(pathModule._makeLong(path));
644 fs.fstat = function(fd, callback) {
645 binding.fstat(fd, makeCallback(callback));
648 fs.lstat = function(path, callback) {
649 callback = makeCallback(callback);
650 if (!nullCheck(path, callback)) return;
651 binding.lstat(pathModule._makeLong(path), callback);
654 fs.stat = function(path, callback) {
655 callback = makeCallback(callback);
656 if (!nullCheck(path, callback)) return;
657 binding.stat(pathModule._makeLong(path), callback);
660 fs.fstatSync = function(fd) {
661 return binding.fstat(fd);
664 fs.lstatSync = function(path) {
666 return binding.lstat(pathModule._makeLong(path));
669 fs.statSync = function(path) {
671 return binding.stat(pathModule._makeLong(path));
674 fs.readlink = function(path, callback) {
675 callback = makeCallback(callback);
676 if (!nullCheck(path, callback)) return;
677 binding.readlink(pathModule._makeLong(path), callback);
680 fs.readlinkSync = function(path) {
682 return binding.readlink(pathModule._makeLong(path));
685 function preprocessSymlinkDestination(path, type) {
687 // No preprocessing is needed on Unix.
689 } else if (type === 'junction') {
690 // Junctions paths need to be absolute and \\?\-prefixed.
691 return pathModule._makeLong(path);
693 // Windows symlinks don't tolerate forward slashes.
694 return ('' + path).replace(/\//g, '\\');
698 fs.symlink = function(destination, path, type_, callback) {
699 var type = (typeof type_ === 'string' ? type_ : null);
700 var callback = makeCallback(arguments[arguments.length - 1]);
702 if (!nullCheck(destination, callback)) return;
703 if (!nullCheck(path, callback)) return;
705 binding.symlink(preprocessSymlinkDestination(destination, type),
706 pathModule._makeLong(path),
711 fs.symlinkSync = function(destination, path, type) {
712 type = (typeof type === 'string' ? type : null);
714 nullCheck(destination);
717 return binding.symlink(preprocessSymlinkDestination(destination, type),
718 pathModule._makeLong(path),
722 fs.link = function(srcpath, dstpath, callback) {
723 callback = makeCallback(callback);
724 if (!nullCheck(srcpath, callback)) return;
725 if (!nullCheck(dstpath, callback)) return;
727 binding.link(pathModule._makeLong(srcpath),
728 pathModule._makeLong(dstpath),
732 fs.linkSync = function(srcpath, dstpath) {
735 return binding.link(pathModule._makeLong(srcpath),
736 pathModule._makeLong(dstpath));
739 fs.unlink = function(path, callback) {
740 callback = makeCallback(callback);
741 if (!nullCheck(path, callback)) return;
742 binding.unlink(pathModule._makeLong(path), callback);
745 fs.unlinkSync = function(path) {
747 return binding.unlink(pathModule._makeLong(path));
750 fs.fchmod = function(fd, mode, callback) {
751 binding.fchmod(fd, modeNum(mode), makeCallback(callback));
754 fs.fchmodSync = function(fd, mode) {
755 return binding.fchmod(fd, modeNum(mode));
758 if (constants.hasOwnProperty('O_SYMLINK')) {
759 fs.lchmod = function(path, mode, callback) {
760 callback = maybeCallback(callback);
761 fs.open(path, constants.O_WRONLY | constants.O_SYMLINK, function(err, fd) {
766 // prefer to return the chmod error, if one occurs,
767 // but still try to close, and report closing errors if they occur.
768 fs.fchmod(fd, mode, function(err) {
769 fs.close(fd, function(err2) {
770 callback(err || err2);
776 fs.lchmodSync = function(path, mode) {
777 var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK);
779 // prefer to return the chmod error, if one occurs,
780 // but still try to close, and report closing errors if they occur.
783 var ret = fs.fchmodSync(fd, mode);
792 if (err || err2) throw (err || err2);
798 fs.chmod = function(path, mode, callback) {
799 callback = makeCallback(callback);
800 if (!nullCheck(path, callback)) return;
801 binding.chmod(pathModule._makeLong(path),
806 fs.chmodSync = function(path, mode) {
808 return binding.chmod(pathModule._makeLong(path), modeNum(mode));
811 if (constants.hasOwnProperty('O_SYMLINK')) {
812 fs.lchown = function(path, uid, gid, callback) {
813 callback = maybeCallback(callback);
814 fs.open(path, constants.O_WRONLY | constants.O_SYMLINK, function(err, fd) {
819 fs.fchown(fd, uid, gid, callback);
823 fs.lchownSync = function(path, uid, gid) {
824 var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK);
825 return fs.fchownSync(fd, uid, gid);
829 fs.fchown = function(fd, uid, gid, callback) {
830 binding.fchown(fd, uid, gid, makeCallback(callback));
833 fs.fchownSync = function(fd, uid, gid) {
834 return binding.fchown(fd, uid, gid);
837 fs.chown = function(path, uid, gid, callback) {
838 callback = makeCallback(callback);
839 if (!nullCheck(path, callback)) return;
840 binding.chown(pathModule._makeLong(path), uid, gid, callback);
843 fs.chownSync = function(path, uid, gid) {
845 return binding.chown(pathModule._makeLong(path), uid, gid);
848 // converts Date or number to a fractional UNIX timestamp
849 function toUnixTimestamp(time) {
850 if (typeof time == 'number') {
853 if (time instanceof Date) {
854 // convert to 123.456 UNIX timestamp
855 return time.getTime() / 1000;
857 throw new Error('Cannot parse time: ' + time);
860 // exported for unit tests, not for public consumption
861 fs._toUnixTimestamp = toUnixTimestamp;
863 fs.utimes = function(path, atime, mtime, callback) {
864 callback = makeCallback(callback);
865 if (!nullCheck(path, callback)) return;
866 binding.utimes(pathModule._makeLong(path),
867 toUnixTimestamp(atime),
868 toUnixTimestamp(mtime),
872 fs.utimesSync = function(path, atime, mtime) {
874 atime = toUnixTimestamp(atime);
875 mtime = toUnixTimestamp(mtime);
876 binding.utimes(pathModule._makeLong(path), atime, mtime);
879 fs.futimes = function(fd, atime, mtime, callback) {
880 atime = toUnixTimestamp(atime);
881 mtime = toUnixTimestamp(mtime);
882 binding.futimes(fd, atime, mtime, makeCallback(callback));
885 fs.futimesSync = function(fd, atime, mtime) {
886 atime = toUnixTimestamp(atime);
887 mtime = toUnixTimestamp(mtime);
888 binding.futimes(fd, atime, mtime);
891 function writeAll(fd, buffer, offset, length, position, callback) {
892 callback = maybeCallback(arguments[arguments.length - 1]);
894 // write(fd, buffer, offset, length, position, callback)
895 fs.write(fd, buffer, offset, length, position, function(writeErr, written) {
897 fs.close(fd, function() {
898 if (callback) callback(writeErr);
901 if (written === length) {
902 fs.close(fd, callback);
907 writeAll(fd, buffer, offset, length, position, callback);
913 fs.writeFile = function(path, data, options, callback) {
914 var callback = maybeCallback(arguments[arguments.length - 1]);
916 if (typeof options === 'function' || !options) {
917 options = { encoding: 'utf8', mode: 438 /*=0666*/, flag: 'w' };
918 } else if (typeof options === 'string') {
919 options = { encoding: options, mode: 438, flag: 'w' };
920 } else if (!options) {
921 options = { encoding: 'utf8', mode: 438 /*=0666*/, flag: 'w' };
922 } else if (typeof options !== 'object') {
923 throw new TypeError('Bad arguments');
926 assertEncoding(options.encoding);
928 var flag = options.flag || 'w';
929 fs.open(path, options.flag || 'w', options.mode, function(openErr, fd) {
931 if (callback) callback(openErr);
933 var buffer = Buffer.isBuffer(data) ? data : new Buffer('' + data,
934 options.encoding || 'utf8');
935 var position = /a/.test(flag) ? null : 0;
936 writeAll(fd, buffer, 0, buffer.length, position, callback);
941 fs.writeFileSync = function(path, data, options) {
943 options = { encoding: 'utf8', mode: 438 /*=0666*/, flag: 'w' };
944 } else if (typeof options === 'string') {
945 options = { encoding: options, mode: 438, flag: 'w' };
946 } else if (typeof options !== 'object') {
947 throw new TypeError('Bad arguments');
950 assertEncoding(options.encoding);
952 var flag = options.flag || 'w';
953 var fd = fs.openSync(path, flag, options.mode);
954 if (!Buffer.isBuffer(data)) {
955 data = new Buffer('' + data, options.encoding || 'utf8');
958 var length = data.length;
959 var position = /a/.test(flag) ? null : 0;
961 while (written < length) {
962 written += fs.writeSync(fd, data, written, length - written, position);
970 fs.appendFile = function(path, data, options, callback_) {
971 var callback = maybeCallback(arguments[arguments.length - 1]);
973 if (typeof options === 'function' || !options) {
974 options = { encoding: 'utf8', mode: 438 /*=0666*/, flag: 'a' };
975 } else if (typeof options === 'string') {
976 options = { encoding: options, mode: 438, flag: 'a' };
977 } else if (!options) {
978 options = { encoding: 'utf8', mode: 438 /*=0666*/, flag: 'a' };
979 } else if (typeof options !== 'object') {
980 throw new TypeError('Bad arguments');
984 options = util._extend({ flag: 'a' }, options);
985 fs.writeFile(path, data, options, callback);
988 fs.appendFileSync = function(path, data, options) {
990 options = { encoding: 'utf8', mode: 438 /*=0666*/, flag: 'a' };
991 } else if (typeof options === 'string') {
992 options = { encoding: options, mode: 438, flag: 'a' };
993 } else if (typeof options !== 'object') {
994 throw new TypeError('Bad arguments');
997 options = util._extend({ flag: 'a' }, options);
999 fs.writeFileSync(path, data, options);
1002 function errnoException(errorno, syscall) {
1003 // TODO make this more compatible with ErrnoException from src/node.cc
1004 // Once all of Node is using this function the ErrnoException from
1005 // src/node.cc should be removed.
1006 var e = new Error(syscall + ' ' + errorno);
1007 e.errno = e.code = errorno;
1008 e.syscall = syscall;
1013 function FSWatcher() {
1014 EventEmitter.call(this);
1017 var FSEvent = process.binding('fs_event_wrap').FSEvent;
1018 this._handle = new FSEvent();
1019 this._handle.owner = this;
1021 this._handle.onchange = function(status, event, filename) {
1023 self._handle.close();
1024 self.emit('error', errnoException(process._errno, 'watch'));
1026 self.emit('change', event, filename);
1030 util.inherits(FSWatcher, EventEmitter);
1032 FSWatcher.prototype.start = function(filename, persistent) {
1033 nullCheck(filename);
1034 var r = this._handle.start(pathModule._makeLong(filename), persistent);
1037 this._handle.close();
1038 throw errnoException(process._errno, 'watch');
1042 FSWatcher.prototype.close = function() {
1043 this._handle.close();
1046 fs.watch = function(filename) {
1047 nullCheck(filename);
1052 if ('object' == typeof arguments[1]) {
1053 options = arguments[1];
1054 listener = arguments[2];
1057 listener = arguments[1];
1060 if (options.persistent === undefined) options.persistent = true;
1062 watcher = new FSWatcher();
1063 watcher.start(filename, options.persistent);
1066 watcher.addListener('change', listener);
1073 // Stat Change Watchers
1075 function StatWatcher() {
1076 EventEmitter.call(this);
1079 this._handle = new binding.StatWatcher();
1081 // uv_fs_poll is a little more powerful than ev_stat but we curb it for
1082 // the sake of backwards compatibility
1085 this._handle.onchange = function(current, previous, newStatus) {
1086 if (oldStatus === -1 &&
1088 current.nlink === previous.nlink) return;
1090 oldStatus = newStatus;
1091 self.emit('change', current, previous);
1094 this._handle.onstop = function() {
1098 util.inherits(StatWatcher, EventEmitter);
1101 StatWatcher.prototype.start = function(filename, persistent, interval) {
1102 nullCheck(filename);
1103 this._handle.start(pathModule._makeLong(filename), persistent, interval);
1107 StatWatcher.prototype.stop = function() {
1108 this._handle.stop();
1112 var statWatchers = {};
1113 function inStatWatchers(filename) {
1114 return Object.prototype.hasOwnProperty.call(statWatchers, filename) &&
1115 statWatchers[filename];
1119 fs.watchFile = function(filename) {
1120 nullCheck(filename);
1125 // Poll interval in milliseconds. 5007 is what libev used to use. It's
1126 // a little on the slow side but let's stick with it for now to keep
1127 // behavioral changes to a minimum.
1132 if ('object' == typeof arguments[1]) {
1133 options = util._extend(options, arguments[1]);
1134 listener = arguments[2];
1136 listener = arguments[1];
1140 throw new Error('watchFile requires a listener function');
1143 if (inStatWatchers(filename)) {
1144 stat = statWatchers[filename];
1146 stat = statWatchers[filename] = new StatWatcher();
1147 stat.start(filename, options.persistent, options.interval);
1149 stat.addListener('change', listener);
1153 fs.unwatchFile = function(filename, listener) {
1154 nullCheck(filename);
1155 if (!inStatWatchers(filename)) return;
1157 var stat = statWatchers[filename];
1159 if (typeof listener === 'function') {
1160 stat.removeListener('change', listener);
1162 stat.removeAllListeners('change');
1165 if (EventEmitter.listenerCount(stat, 'change') === 0) {
1167 statWatchers[filename] = undefined;
1172 // Not using realpath(2) because it's bad.
1173 // See: http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html
1175 var normalize = pathModule.normalize;
1177 // Regexp that finds the next partion of a (partial) path
1178 // result is [base_with_slash, base], e.g. ['somedir/', 'somedir']
1180 var nextPartRe = /(.*?)(?:[\/\\]+|$)/g;
1182 var nextPartRe = /(.*?)(?:[\/]+|$)/g;
1185 // Regex to find the device root, including trailing slash. E.g. 'c:\\'.
1187 var splitRootRe = /^(?:[a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?[\\\/]*/;
1189 var splitRootRe = /^[\/]*/;
1192 fs.realpathSync = function realpathSync(p, cache) {
1193 // make p is absolute
1194 p = pathModule.resolve(p);
1196 if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
1204 // current character position in p
1206 // the partial path so far, including a trailing slash if any
1208 // the partial path without a trailing slash (except when pointing at a root)
1210 // the partial path scanned in the previous round, with slash
1217 var m = splitRootRe.exec(p);
1223 // On windows, check that the root exists. On unix there is no need.
1224 if (isWindows && !knownHard[base]) {
1226 knownHard[base] = true;
1230 // walk down the path, swapping out linked pathparts for their real
1232 // NB: p.length changes.
1233 while (pos < p.length) {
1234 // find the next part
1235 nextPartRe.lastIndex = pos;
1236 var result = nextPartRe.exec(p);
1238 current += result[0];
1239 base = previous + result[1];
1240 pos = nextPartRe.lastIndex;
1242 // continue if not a symlink
1243 if (knownHard[base] || (cache && cache[base] === base)) {
1248 if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
1249 // some known symbolic link. no need to stat again.
1250 resolvedLink = cache[base];
1252 var stat = fs.lstatSync(base);
1253 if (!stat.isSymbolicLink()) {
1254 knownHard[base] = true;
1255 if (cache) cache[base] = base;
1259 // read the link if it wasn't read before
1260 // dev/ino always return 0 on windows, so skip the check.
1261 var linkTarget = null;
1263 var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
1264 if (seenLinks.hasOwnProperty(id)) {
1265 linkTarget = seenLinks[id];
1268 if (linkTarget === null) {
1270 linkTarget = fs.readlinkSync(base);
1272 resolvedLink = pathModule.resolve(previous, linkTarget);
1273 // track this, if given a cache.
1274 if (cache) cache[base] = resolvedLink;
1275 if (!isWindows) seenLinks[id] = linkTarget;
1278 // resolve the link, then start over
1279 p = pathModule.resolve(resolvedLink, p.slice(pos));
1283 if (cache) cache[original] = p;
1289 fs.realpath = function realpath(p, cache, cb) {
1290 if (typeof cb !== 'function') {
1291 cb = maybeCallback(cache);
1295 // make p is absolute
1296 p = pathModule.resolve(p);
1298 if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
1299 return process.nextTick(cb.bind(null, null, cache[p]));
1306 // current character position in p
1308 // the partial path so far, including a trailing slash if any
1310 // the partial path without a trailing slash (except when pointing at a root)
1312 // the partial path scanned in the previous round, with slash
1319 var m = splitRootRe.exec(p);
1325 // On windows, check that the root exists. On unix there is no need.
1326 if (isWindows && !knownHard[base]) {
1327 fs.lstat(base, function(err) {
1328 if (err) return cb(err);
1329 knownHard[base] = true;
1333 process.nextTick(LOOP);
1337 // walk down the path, swapping out linked pathparts for their real
1340 // stop if scanned past end of path
1341 if (pos >= p.length) {
1342 if (cache) cache[original] = p;
1346 // find the next part
1347 nextPartRe.lastIndex = pos;
1348 var result = nextPartRe.exec(p);
1350 current += result[0];
1351 base = previous + result[1];
1352 pos = nextPartRe.lastIndex;
1354 // continue if not a symlink
1355 if (knownHard[base] || (cache && cache[base] === base)) {
1356 return process.nextTick(LOOP);
1359 if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
1360 // known symbolic link. no need to stat again.
1361 return gotResolvedLink(cache[base]);
1364 return fs.lstat(base, gotStat);
1367 function gotStat(err, stat) {
1368 if (err) return cb(err);
1370 // if not a symlink, skip to the next path part
1371 if (!stat.isSymbolicLink()) {
1372 knownHard[base] = true;
1373 if (cache) cache[base] = base;
1374 return process.nextTick(LOOP);
1377 // stat & read the link if not read before
1378 // call gotTarget as soon as the link target is known
1379 // dev/ino always return 0 on windows, so skip the check.
1381 var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
1382 if (seenLinks.hasOwnProperty(id)) {
1383 return gotTarget(null, seenLinks[id], base);
1386 fs.stat(base, function(err) {
1387 if (err) return cb(err);
1389 fs.readlink(base, function(err, target) {
1390 if (!isWindows) seenLinks[id] = target;
1391 gotTarget(err, target);
1396 function gotTarget(err, target, base) {
1397 if (err) return cb(err);
1399 var resolvedLink = pathModule.resolve(previous, target);
1400 if (cache) cache[base] = resolvedLink;
1401 gotResolvedLink(resolvedLink);
1404 function gotResolvedLink(resolvedLink) {
1405 // resolve the link, then start over
1406 p = pathModule.resolve(resolvedLink, p.slice(pos));
1415 function allocNewPool(poolSize) {
1416 pool = new Buffer(poolSize);
1422 fs.createReadStream = function(path, options) {
1423 return new ReadStream(path, options);
1426 util.inherits(ReadStream, Readable);
1427 fs.ReadStream = ReadStream;
1429 function ReadStream(path, options) {
1430 if (!(this instanceof ReadStream))
1431 return new ReadStream(path, options);
1433 // a little bit bigger buffer and water marks by default
1434 options = util._extend({
1435 highWaterMark: 64 * 1024
1438 Readable.call(this, options);
1441 this.fd = options.hasOwnProperty('fd') ? options.fd : null;
1442 this.flags = options.hasOwnProperty('flags') ? options.flags : 'r';
1443 this.mode = options.hasOwnProperty('mode') ? options.mode : 438; /*=0666*/
1445 this.start = options.hasOwnProperty('start') ? options.start : undefined;
1446 this.end = options.hasOwnProperty('end') ? options.end : undefined;
1447 this.autoClose = options.hasOwnProperty('autoClose') ?
1448 options.autoClose : true;
1449 this.pos = undefined;
1451 if (this.start !== undefined) {
1452 if ('number' !== typeof this.start) {
1453 throw TypeError('start must be a Number');
1455 if (this.end === undefined) {
1456 this.end = Infinity;
1457 } else if ('number' !== typeof this.end) {
1458 throw TypeError('end must be a Number');
1461 if (this.start > this.end) {
1462 throw new Error('start must be <= end');
1465 this.pos = this.start;
1468 if (typeof this.fd !== 'number')
1471 this.on('end', function() {
1472 if (this.autoClose) {
1478 fs.FileReadStream = fs.ReadStream; // support the legacy name
1480 ReadStream.prototype.open = function() {
1482 fs.open(this.path, this.flags, this.mode, function(er, fd) {
1484 if (this.autoClose) {
1487 self.emit('error', er);
1492 self.emit('open', fd);
1493 // start the flow of data.
1498 ReadStream.prototype._read = function(n) {
1499 if (typeof this.fd !== 'number')
1500 return this.once('open', function() {
1507 if (!pool || pool.length - pool.used < kMinPoolSpace) {
1508 // discard the old pool.
1510 allocNewPool(this._readableState.highWaterMark);
1513 // Grab another reference to the pool in the case that while we're
1514 // in the thread pool another read() finishes up the pool, and
1515 // allocates a new one.
1516 var thisPool = pool;
1517 var toRead = Math.min(pool.length - pool.used, n);
1518 var start = pool.used;
1520 if (this.pos !== undefined)
1521 toRead = Math.min(this.end - this.pos + 1, toRead);
1523 // already read everything we were supposed to read!
1526 return this.push(null);
1530 fs.read(this.fd, pool, pool.used, toRead, this.pos, onread);
1532 // move the pool positions, and internal position for reading.
1533 if (this.pos !== undefined)
1535 pool.used += toRead;
1537 function onread(er, bytesRead) {
1539 if (self.autoClose) {
1542 self.emit('error', er);
1546 b = thisPool.slice(start, start + bytesRead);
1554 ReadStream.prototype.destroy = function() {
1557 this.destroyed = true;
1559 if ('number' === typeof this.fd)
1564 ReadStream.prototype.close = function(cb) {
1567 this.once('close', cb);
1568 if (this.closed || 'number' !== typeof this.fd) {
1569 if ('number' !== typeof this.fd) {
1570 this.once('open', close);
1573 return process.nextTick(this.emit.bind(this, 'close'));
1578 function close(fd) {
1579 fs.close(fd || self.fd, function(er) {
1581 self.emit('error', er);
1592 fs.createWriteStream = function(path, options) {
1593 return new WriteStream(path, options);
1596 util.inherits(WriteStream, Writable);
1597 fs.WriteStream = WriteStream;
1598 function WriteStream(path, options) {
1599 if (!(this instanceof WriteStream))
1600 return new WriteStream(path, options);
1602 options = options || {};
1604 Writable.call(this, options);
1609 this.fd = options.hasOwnProperty('fd') ? options.fd : null;
1610 this.flags = options.hasOwnProperty('flags') ? options.flags : 'w';
1611 this.mode = options.hasOwnProperty('mode') ? options.mode : 438; /*=0666*/
1613 this.start = options.hasOwnProperty('start') ? options.start : undefined;
1614 this.pos = undefined;
1615 this.bytesWritten = 0;
1617 if (this.start !== undefined) {
1618 if ('number' !== typeof this.start) {
1619 throw TypeError('start must be a Number');
1621 if (this.start < 0) {
1622 throw new Error('start must be >= zero');
1625 this.pos = this.start;
1628 if ('number' !== typeof this.fd)
1631 // dispose on finish.
1632 this.once('finish', this.close);
1635 fs.FileWriteStream = fs.WriteStream; // support the legacy name
1638 WriteStream.prototype.open = function() {
1639 fs.open(this.path, this.flags, this.mode, function(er, fd) {
1642 this.emit('error', er);
1647 this.emit('open', fd);
1652 WriteStream.prototype._write = function(data, encoding, cb) {
1653 if (!Buffer.isBuffer(data))
1654 return this.emit('error', new Error('Invalid data'));
1656 if (typeof this.fd !== 'number')
1657 return this.once('open', function() {
1658 this._write(data, encoding, cb);
1662 fs.write(this.fd, data, 0, data.length, this.pos, function(er, bytes) {
1667 self.bytesWritten += bytes;
1671 if (this.pos !== undefined)
1672 this.pos += data.length;
1676 WriteStream.prototype.destroy = ReadStream.prototype.destroy;
1677 WriteStream.prototype.close = ReadStream.prototype.close;
1679 // There is no shutdown() for files.
1680 WriteStream.prototype.destroySoon = WriteStream.prototype.end;
1683 // SyncWriteStream is internal. DO NOT USE.
1684 // Temporary hack for process.stdout and process.stderr when piped to files.
1685 function SyncWriteStream(fd) {
1689 this.writable = true;
1690 this.readable = false;
1693 util.inherits(SyncWriteStream, Stream);
1697 fs.SyncWriteStream = SyncWriteStream;
1700 SyncWriteStream.prototype.write = function(data, arg1, arg2) {
1705 if (typeof arg1 === 'string') {
1708 } else if (typeof arg1 === 'function') {
1711 throw new Error('bad arg');
1714 assertEncoding(encoding);
1716 // Change strings to buffers. SLOW
1717 if (typeof data == 'string') {
1718 data = new Buffer(data, encoding);
1721 fs.writeSync(this.fd, data, 0, data.length);
1724 process.nextTick(cb);
1731 SyncWriteStream.prototype.end = function(data, arg1, arg2) {
1733 this.write(data, arg1, arg2);
1739 SyncWriteStream.prototype.destroy = function() {
1740 fs.closeSync(this.fd);
1746 SyncWriteStream.prototype.destroySoon = SyncWriteStream.prototype.destroy;