~james-page/ubuntu/precise/nodejs/0.6.x-merge

« back to all changes in this revision

Viewing changes to lib/fs.js

  • Committer: James Page
  • Date: 2012-03-30 12:09:16 UTC
  • mfrom: (7.1.23 sid)
  • Revision ID: james.page@canonical.com-20120330120916-40hfu9o00qr5t87b
* Merge from Debian unstable:
  - New upstream release (LP: #892034).
  - This package is x86/arm only. Update control to match
  - d/patches/2009_increase_test_timeout.patch: Increased default test
    timeout from 60 to 120 seconds to support reliable execution of all
    tests on armhf/armel architectures.
  - d/patches/2005_expected_failing_tests.patch: 
    - Allow racey tests to fail: test-cluster-kill-workers,
      test-child-process-fork2 
    - Allow test-fs-watch to fail as LP buildd's don't support
      inotify.
    - Revert all other Ubuntu changes as no longer required.
* Update Standards-Version to 3.9.3.
* Patch wscript to enable build on mipsel arch, libv8 being available.
  Upstream does not support that arch, failure expected.
* test-cluster-kill-workers is expected to fail on armhf,
  Bug#660802 will be closed when test pass.
* test-buffer is expected to fail on armel,
  Bug#660800 will be closed when test pass.
* Add epoch to dependency on libev >= 1:4.11. Closes: bug#658441.
* Remove tools/doc because node-doc-generator has no license for now.
* Add copyright for doc/sh* files (shjs).
* source.lintian-overrides : source-contains-waf-binary tools/node-waf
  it is simply not the case here.
* test-stream-pipe-multi expected to timeout sometimes on busy builds. 
* New upstream release.
* Remove upstream patches.
* test-dgram-pingpong expected to timeout, the test itself is buggy.
* test-buffer expected to fail on armel, allow building package to make
  it easier to find the cause of the failure.
  Closes: bug#639636.
* Expect tests dgram-multicast and broadcast to fail.
  debian/patches/2005_expected_failing_tests.patch
* Drop dpkg-source local-options: Defaults since dpkg-source 1.16.1.
* New upstream release.
* Depend on libev-dev 4.11, see bug#657080.
* Bump dependency on openssl to 1.0.0g.
* Remove useless uv_loop_refcount from libuv,
  refreshed 2009_fix_shared_ev.patch.
* Apply to upstream patches landed after 0.6.10 release,
  to fix debugger repl and http client.
* New upstream release. Closes:bug#650661
* Repackage to remove non-dfsg font files ./deps/npm/html/*/*.ttf
* Remove unneeded bundled dependencies: lighter tarball,
  debian/copyright is easier to maintain.
* Drop unneeded build-dependency on scons.
* Depend on zlib1g, libc-ares, libev.
  Patches done to support building with those shared libs.
* Fix DEB_UPSTREAM_URL in debian/rules, and debian/watch.
* nodejs.pc file for pkgconfig is no more available.
* Build-depend on procps package, a test is using /bin/ps.
* Refreshed debian/patches/2005_expected_failing_tests.patch,
  only for tests that need networking.

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20
20
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21
21
 
 
22
// Maintainers, keep in mind that octal literals are not allowed
 
23
// in strict mode. Use the decimal value and add a comment with
 
24
// the octal value. Example:
 
25
//
 
26
//   var mode = 438; /* mode=0666 */
 
27
 
22
28
var util = require('util');
 
29
var pathModule = require('path');
23
30
 
24
31
var binding = process.binding('fs');
25
32
var constants = process.binding('constants');
26
33
var fs = exports;
27
34
var Stream = require('stream').Stream;
 
35
var EventEmitter = require('events').EventEmitter;
28
36
 
29
37
var kMinPoolSpace = 128;
30
38
var kPoolSize = 40 * 1024;
109
117
};
110
118
 
111
119
fs.readFileSync = function(path, encoding) {
112
 
  var fd = fs.openSync(path, constants.O_RDONLY, 0666);
 
120
  var fd = fs.openSync(path, constants.O_RDONLY, 438 /*=0666*/);
113
121
  var buffer = new Buffer(4048);
114
122
  var buffers = [];
115
123
  var nread = 0;
193
201
};
194
202
 
195
203
function modeNum(m, def) {
196
 
  switch(typeof m) {
 
204
  switch (typeof m) {
197
205
    case 'number': return m;
198
206
    case 'string': return parseInt(m, 8);
199
207
    default:
211
219
    callback = noop;
212
220
  }
213
221
 
214
 
  mode = modeNum(mode, '0666');
 
222
  mode = modeNum(mode, 438 /*=0666*/);
215
223
 
216
 
  binding.open(path, stringToFlags(flags), mode, callback);
 
224
  binding.open(pathModule._makeLong(path), stringToFlags(flags), mode,
 
225
    callback);
217
226
};
218
227
 
219
228
fs.openSync = function(path, flags, mode) {
220
 
  mode = modeNum(mode, '0666');
221
 
  return binding.open(path, stringToFlags(flags), mode);
 
229
  mode = modeNum(mode, 438 /*=0666*/);
 
230
  return binding.open(pathModule._makeLong(path), stringToFlags(flags), mode);
222
231
};
223
232
 
224
233
fs.read = function(fd, buffer, offset, length, position, callback) {
313
322
};
314
323
 
315
324
fs.rename = function(oldPath, newPath, callback) {
316
 
  binding.rename(oldPath, newPath, callback || noop);
 
325
  binding.rename(pathModule._makeLong(oldPath), pathModule._makeLong(newPath),
 
326
    callback || noop);
317
327
};
318
328
 
319
329
fs.renameSync = function(oldPath, newPath) {
320
 
  return binding.rename(oldPath, newPath);
 
330
  return binding.rename(pathModule._makeLong(oldPath),
 
331
    pathModule._makeLong(newPath));
321
332
};
322
333
 
323
334
fs.truncate = function(fd, len, callback) {
329
340
};
330
341
 
331
342
fs.rmdir = function(path, callback) {
332
 
  binding.rmdir(path, callback || noop);
 
343
  binding.rmdir(pathModule._makeLong(path), callback || noop);
333
344
};
334
345
 
335
346
fs.rmdirSync = function(path) {
336
 
  return binding.rmdir(path);
 
347
  return binding.rmdir(pathModule._makeLong(path));
337
348
};
338
349
 
339
350
fs.fdatasync = function(fd, callback) {
353
364
};
354
365
 
355
366
fs.mkdir = function(path, mode, callback) {
356
 
  binding.mkdir(path, modeNum(mode), callback || noop);
 
367
  if (typeof mode === 'function') callback = mode;
 
368
  binding.mkdir(pathModule._makeLong(path), modeNum(mode, 511 /*=0777*/),
 
369
    callback || noop);
357
370
};
358
371
 
359
372
fs.mkdirSync = function(path, mode) {
360
 
  return binding.mkdir(path, modeNum(mode));
 
373
  return binding.mkdir(pathModule._makeLong(path),
 
374
    modeNum(mode, 511 /*=0777*/));
361
375
};
362
376
 
363
377
fs.sendfile = function(outFd, inFd, inOffset, length, callback) {
369
383
};
370
384
 
371
385
fs.readdir = function(path, callback) {
372
 
  binding.readdir(path, callback || noop);
 
386
  binding.readdir(pathModule._makeLong(path), callback || noop);
373
387
};
374
388
 
375
389
fs.readdirSync = function(path) {
376
 
  return binding.readdir(path);
 
390
  return binding.readdir(pathModule._makeLong(path));
377
391
};
378
392
 
379
393
fs.fstat = function(fd, callback) {
381
395
};
382
396
 
383
397
fs.lstat = function(path, callback) {
384
 
  binding.lstat(path, callback || noop);
 
398
  binding.lstat(pathModule._makeLong(path), callback || noop);
385
399
};
386
400
 
387
401
fs.stat = function(path, callback) {
388
 
  binding.stat(path, callback || noop);
 
402
  binding.stat(pathModule._makeLong(path), callback || noop);
389
403
};
390
404
 
391
405
fs.fstatSync = function(fd) {
393
407
};
394
408
 
395
409
fs.lstatSync = function(path) {
396
 
  return binding.lstat(path);
 
410
  return binding.lstat(pathModule._makeLong(path));
397
411
};
398
412
 
399
413
fs.statSync = function(path) {
400
 
  return binding.stat(path);
 
414
  return binding.stat(pathModule._makeLong(path));
401
415
};
402
416
 
403
417
fs.readlink = function(path, callback) {
404
 
  binding.readlink(path, callback || noop);
 
418
  binding.readlink(pathModule._makeLong(path), callback || noop);
405
419
};
406
420
 
407
421
fs.readlinkSync = function(path) {
408
 
  return binding.readlink(path);
409
 
};
410
 
 
411
 
fs.symlink = function(destination, path, callback) {
412
 
  binding.symlink(destination, path, callback || noop);
413
 
};
414
 
 
415
 
fs.symlinkSync = function(destination, path) {
416
 
  return binding.symlink(destination, path);
 
422
  return binding.readlink(pathModule._makeLong(path));
 
423
};
 
424
 
 
425
fs.symlink = function(destination, path, type_, callback) {
 
426
  var type = (typeof(type_) == 'string' ? type_ : null);
 
427
  var callback_ = arguments[arguments.length - 1];
 
428
  callback = (typeof(callback_) == 'function' ? callback_ : null);
 
429
  binding.symlink(pathModule._makeLong(destination),
 
430
    pathModule._makeLong(path), type, callback);
 
431
};
 
432
 
 
433
fs.symlinkSync = function(destination, path, type) {
 
434
  return binding.symlink(pathModule._makeLong(destination),
 
435
    pathModule._makeLong(path), type);
417
436
};
418
437
 
419
438
fs.link = function(srcpath, dstpath, callback) {
420
 
  binding.link(srcpath, dstpath, callback || noop);
 
439
  binding.link(pathModule._makeLong(srcpath), pathModule._makeLong(dstpath),
 
440
    callback || noop);
421
441
};
422
442
 
423
443
fs.linkSync = function(srcpath, dstpath) {
424
 
  return binding.link(srcpath, dstpath);
 
444
  return binding.link(pathModule._makeLong(srcpath),
 
445
    pathModule._makeLong(dstpath));
425
446
};
426
447
 
427
448
fs.unlink = function(path, callback) {
428
 
  binding.unlink(path, callback || noop);
 
449
  binding.unlink(pathModule._makeLong(path), callback || noop);
429
450
};
430
451
 
431
452
fs.unlinkSync = function(path) {
432
 
  return binding.unlink(path);
433
 
};
 
453
  return binding.unlink(pathModule._makeLong(path));
 
454
};
 
455
 
 
456
fs.fchmod = function(fd, mode, callback) {
 
457
  binding.fchmod(fd, modeNum(mode), callback || noop);
 
458
};
 
459
 
 
460
fs.fchmodSync = function(fd, mode) {
 
461
  return binding.fchmod(fd, modeNum(mode));
 
462
};
 
463
 
 
464
if (constants.hasOwnProperty('O_SYMLINK')) {
 
465
  fs.lchmod = function(path, mode, callback) {
 
466
    callback = callback || noop;
 
467
    fs.open(path, constants.O_WRONLY | constants.O_SYMLINK, function(err, fd) {
 
468
      if (err) {
 
469
        callback(err);
 
470
        return;
 
471
      }
 
472
      // prefer to return the chmod error, if one occurs,
 
473
      // but still try to close, and report closing errors if they occur.
 
474
      fs.fchmod(fd, mode, function(err) {
 
475
        fs.close(fd, function(err2) {
 
476
          callback(err || err2);
 
477
        });
 
478
      });
 
479
    });
 
480
  };
 
481
 
 
482
  fs.lchmodSync = function(path, mode) {
 
483
    var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK);
 
484
 
 
485
    // prefer to return the chmod error, if one occurs,
 
486
    // but still try to close, and report closing errors if they occur.
 
487
    var err, err2;
 
488
    try {
 
489
      var ret = fs.fchmodSync(fd, mode);
 
490
    } catch (er) {
 
491
      err = er;
 
492
    }
 
493
    try {
 
494
      fs.closeSync(fd);
 
495
    } catch (er) {
 
496
      err2 = er;
 
497
    }
 
498
    if (err || err2) throw (err || err2);
 
499
    return ret;
 
500
  };
 
501
}
 
502
 
434
503
 
435
504
fs.chmod = function(path, mode, callback) {
436
 
  binding.chmod(path, modeNum(mode), callback || noop);
 
505
  binding.chmod(pathModule._makeLong(path), modeNum(mode), callback || noop);
437
506
};
438
507
 
439
508
fs.chmodSync = function(path, mode) {
440
 
  return binding.chmod(path, modeNum(mode));
 
509
  return binding.chmod(pathModule._makeLong(path), modeNum(mode));
 
510
};
 
511
 
 
512
if (constants.hasOwnProperty('O_SYMLINK')) {
 
513
  fs.lchown = function(path, uid, gid, callback) {
 
514
    callback = callback || noop;
 
515
    fs.open(path, constants.O_WRONLY | constants.O_SYMLINK, function(err, fd) {
 
516
      if (err) {
 
517
        callback(err);
 
518
        return;
 
519
      }
 
520
      fs.fchown(fd, uid, gid, callback);
 
521
    });
 
522
  };
 
523
 
 
524
  fs.lchownSync = function(path, uid, gid) {
 
525
    var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK);
 
526
    return fs.fchownSync(fd, uid, gid);
 
527
  };
 
528
}
 
529
 
 
530
fs.fchown = function(fd, uid, gid, callback) {
 
531
  binding.fchown(fd, uid, gid, callback || noop);
 
532
};
 
533
 
 
534
fs.fchownSync = function(fd, uid, gid) {
 
535
  return binding.fchown(fd, uid, gid);
441
536
};
442
537
 
443
538
fs.chown = function(path, uid, gid, callback) {
444
 
  binding.chown(path, uid, gid, callback || noop);
 
539
  binding.chown(pathModule._makeLong(path), uid, gid, callback || noop);
445
540
};
446
541
 
447
542
fs.chownSync = function(path, uid, gid) {
448
 
  return binding.chown(path, uid, gid);
 
543
  return binding.chown(pathModule._makeLong(path), uid, gid);
 
544
};
 
545
 
 
546
// converts Date or number to a fractional UNIX timestamp
 
547
function toUnixTimestamp(time) {
 
548
  if (typeof time == 'number') {
 
549
    return time;
 
550
  }
 
551
  if (time instanceof Date) {
 
552
    // convert to 123.456 UNIX timestamp
 
553
    return time.getTime() / 1000;
 
554
  }
 
555
  throw new Error('Cannot parse time: ' + time);
 
556
}
 
557
 
 
558
// exported for unit tests, not for public consumption
 
559
fs._toUnixTimestamp = toUnixTimestamp;
 
560
 
 
561
fs.utimes = function(path, atime, mtime, callback) {
 
562
  atime = toUnixTimestamp(atime);
 
563
  mtime = toUnixTimestamp(mtime);
 
564
  binding.utimes(pathModule._makeLong(path), atime, mtime, callback || noop);
 
565
};
 
566
 
 
567
fs.utimesSync = function(path, atime, mtime) {
 
568
  atime = toUnixTimestamp(atime);
 
569
  mtime = toUnixTimestamp(mtime);
 
570
  binding.utimes(pathModule._makeLong(path), atime, mtime);
 
571
};
 
572
 
 
573
fs.futimes = function(fd, atime, mtime, callback) {
 
574
  atime = toUnixTimestamp(atime);
 
575
  mtime = toUnixTimestamp(mtime);
 
576
  binding.futimes(fd, atime, mtime, callback || noop);
 
577
};
 
578
 
 
579
fs.futimesSync = function(fd, atime, mtime) {
 
580
  atime = toUnixTimestamp(atime);
 
581
  mtime = toUnixTimestamp(mtime);
 
582
  binding.futimes(fd, atime, mtime);
449
583
};
450
584
 
451
585
function writeAll(fd, buffer, offset, length, callback) {
468
602
fs.writeFile = function(path, data, encoding_, callback) {
469
603
  var encoding = (typeof(encoding_) == 'string' ? encoding_ : 'utf8');
470
604
  var callback_ = arguments[arguments.length - 1];
471
 
  var callback = (typeof(callback_) == 'function' ? callback_ : null);
472
 
  fs.open(path, 'w', 0666, function(openErr, fd) {
 
605
  callback = (typeof(callback_) == 'function' ? callback_ : null);
 
606
  fs.open(path, 'w', 438 /*=0666*/, function(openErr, fd) {
473
607
    if (openErr) {
474
608
      if (callback) callback(openErr);
475
609
    } else {
476
 
      var buffer = Buffer.isBuffer(data) ? data : new Buffer(data, encoding);
 
610
      var buffer = Buffer.isBuffer(data) ? data : new Buffer('' + data,
 
611
          encoding);
477
612
      writeAll(fd, buffer, 0, buffer.length, callback);
478
613
    }
479
614
  });
482
617
fs.writeFileSync = function(path, data, encoding) {
483
618
  var fd = fs.openSync(path, 'w');
484
619
  if (!Buffer.isBuffer(data)) {
485
 
    data = new Buffer(data, encoding || 'utf8');
 
620
    data = new Buffer('' + data, encoding || 'utf8');
486
621
  }
487
622
  var written = 0;
488
623
  var length = data.length;
493
628
  fs.closeSync(fd);
494
629
};
495
630
 
 
631
 
 
632
function errnoException(errorno, syscall) {
 
633
  // TODO make this more compatible with ErrnoException from src/node.cc
 
634
  // Once all of Node is using this function the ErrnoException from
 
635
  // src/node.cc should be removed.
 
636
  var e = new Error(syscall + ' ' + errorno);
 
637
  e.errno = e.code = errorno;
 
638
  e.syscall = syscall;
 
639
  return e;
 
640
}
 
641
 
 
642
 
 
643
function FSWatcher() {
 
644
  var self = this;
 
645
  var FSEvent = process.binding('fs_event_wrap').FSEvent;
 
646
  this._handle = new FSEvent();
 
647
 
 
648
  this._handle.onchange = function(status, event, filename) {
 
649
    if (status) {
 
650
      self.emit('error', errnoException(errno, 'watch'));
 
651
    } else {
 
652
      self.emit('change', event, filename);
 
653
    }
 
654
  };
 
655
}
 
656
util.inherits(FSWatcher, EventEmitter);
 
657
 
 
658
FSWatcher.prototype.start = function(filename, persistent) {
 
659
  var r = this._handle.start(pathModule._makeLong(filename), persistent);
 
660
 
 
661
  if (r) {
 
662
    this._handle.close();
 
663
    throw errnoException(errno, 'watch');
 
664
  }
 
665
};
 
666
 
 
667
FSWatcher.prototype.close = function() {
 
668
  this._handle.close();
 
669
};
 
670
 
 
671
fs.watch = function(filename) {
 
672
  var watcher;
 
673
  var options;
 
674
  var listener;
 
675
 
 
676
  if ('object' == typeof arguments[1]) {
 
677
    options = arguments[1];
 
678
    listener = arguments[2];
 
679
  } else {
 
680
    options = {};
 
681
    listener = arguments[1];
 
682
  }
 
683
 
 
684
  if (!listener) {
 
685
    throw new Error('watch requires a listener function');
 
686
  }
 
687
 
 
688
  if (options.persistent === undefined) options.persistent = true;
 
689
 
 
690
  watcher = new FSWatcher();
 
691
  watcher.start(filename, options.persistent);
 
692
 
 
693
  watcher.addListener('change', listener);
 
694
  return watcher;
 
695
};
 
696
 
 
697
 
496
698
// Stat Change Watchers
497
699
 
 
700
function StatWatcher() {
 
701
  var self = this;
 
702
  this._handle = new binding.StatWatcher();
 
703
 
 
704
  this._handle.onchange = function(current, previous) {
 
705
    self.emit('change', current, previous);
 
706
  };
 
707
 
 
708
  this._handle.onstop = function() {
 
709
    self.emit('stop');
 
710
  };
 
711
}
 
712
util.inherits(StatWatcher, EventEmitter);
 
713
 
 
714
 
 
715
StatWatcher.prototype.start = function(filename, persistent, interval) {
 
716
  this._handle.start(pathModule._makeLong(filename), persistent, interval);
 
717
};
 
718
 
 
719
 
 
720
StatWatcher.prototype.stop = function() {
 
721
  this._handle.stop();
 
722
};
 
723
 
 
724
 
498
725
var statWatchers = {};
 
726
function inStatWatchers(filename) {
 
727
  return Object.prototype.hasOwnProperty.call(statWatchers, filename) &&
 
728
      statWatchers[filename];
 
729
}
 
730
 
499
731
 
500
732
fs.watchFile = function(filename) {
 
733
  if (isWindows) {
 
734
    throw new Error('use fs.watch api instead');
 
735
  }
 
736
 
501
737
  var stat;
502
738
  var options;
503
739
  var listener;
510
746
    listener = arguments[1];
511
747
  }
512
748
 
 
749
  if (!listener) {
 
750
    throw new Error('watchFile requires a listener function');
 
751
  }
 
752
 
513
753
  if (options.persistent === undefined) options.persistent = true;
514
754
  if (options.interval === undefined) options.interval = 0;
515
755
 
516
 
  if (statWatchers[filename]) {
 
756
  if (inStatWatchers(filename)) {
517
757
    stat = statWatchers[filename];
518
758
  } else {
519
 
    statWatchers[filename] = new binding.StatWatcher();
520
 
    stat = statWatchers[filename];
 
759
    stat = statWatchers[filename] = new StatWatcher();
521
760
    stat.start(filename, options.persistent, options.interval);
522
761
  }
523
762
  stat.addListener('change', listener);
526
765
 
527
766
fs.unwatchFile = function(filename) {
528
767
  var stat;
529
 
  if (statWatchers[filename]) {
 
768
  if (inStatWatchers(filename)) {
530
769
    stat = statWatchers[filename];
531
770
    stat.stop();
532
771
    statWatchers[filename] = undefined;
537
776
// Not using realpath(2) because it's bad.
538
777
// See: http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html
539
778
 
540
 
var path = require('path'),
541
 
    normalize = path.normalize,
 
779
var normalize = pathModule.normalize,
542
780
    isWindows = process.platform === 'win32';
543
781
 
544
782
if (isWindows) {
547
785
 
548
786
  // windows version
549
787
  fs.realpathSync = function realpathSync(p, cache) {
550
 
    var p = path.resolve(p);
 
788
    p = pathModule.resolve(p);
551
789
    if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
552
790
      return cache[p];
553
791
    }
562
800
      cb = cache;
563
801
      cache = null;
564
802
    }
565
 
    var p = path.resolve(p);
 
803
    p = pathModule.resolve(p);
566
804
    if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
567
805
      return cb(null, cache[p]);
568
806
    }
569
807
    fs.stat(p, function(err) {
570
 
      if (err) cb(err);
 
808
      if (err) return cb(err);
571
809
      if (cache) cache[p] = p;
572
810
      cb(null, p);
573
811
    });
583
821
  // posix version
584
822
  fs.realpathSync = function realpathSync(p, cache) {
585
823
    // make p is absolute
586
 
    p = path.resolve(p);
 
824
    p = pathModule.resolve(p);
587
825
 
588
826
    if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
589
827
      return cache[p];
636
874
        if (!seenLinks[id]) {
637
875
          fs.statSync(base);
638
876
          seenLinks[id] = fs.readlinkSync(base);
639
 
          resolvedLink = path.resolve(previous, seenLinks[id]);
 
877
          resolvedLink = pathModule.resolve(previous, seenLinks[id]);
640
878
          // track this, if given a cache.
641
879
          if (cache) cache[base] = resolvedLink;
642
880
        }
643
881
      }
644
882
 
645
883
      // resolve the link, then start over
646
 
      p = path.resolve(resolvedLink, p.slice(pos));
 
884
      p = pathModule.resolve(resolvedLink, p.slice(pos));
647
885
      pos = 0;
648
886
      previous = base = current = '';
649
887
    }
662
900
    }
663
901
 
664
902
    // make p is absolute
665
 
    p = path.resolve(p);
 
903
    p = pathModule.resolve(p);
666
904
 
667
905
    if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
668
906
      return cb(null, cache[p]);
740
978
    function gotTarget(err, target, base) {
741
979
      if (err) return cb(err);
742
980
 
743
 
      var resolvedLink = path.resolve(previous, target);
 
981
      var resolvedLink = pathModule.resolve(previous, target);
744
982
      if (cache) cache[base] = resolvedLink;
745
983
      gotResolvedLink(resolvedLink);
746
984
    }
748
986
    function gotResolvedLink(resolvedLink) {
749
987
 
750
988
      // resolve the link, then start over
751
 
      p = path.resolve(resolvedLink, p.slice(pos));
 
989
      p = pathModule.resolve(resolvedLink, p.slice(pos));
752
990
      pos = 0;
753
991
      previous = base = current = '';
754
992
 
785
1023
  this.paused = false;
786
1024
 
787
1025
  this.flags = 'r';
788
 
  this.mode = parseInt('0666', 8);
 
1026
  this.mode = 438; /*=0666*/
789
1027
  this.bufferSize = 64 * 1024;
790
1028
 
791
1029
  options = options || {};
800
1038
  if (this.encoding) this.setEncoding(this.encoding);
801
1039
 
802
1040
  if (this.start !== undefined) {
 
1041
    if ('number' !== typeof this.start) {
 
1042
      throw TypeError('start must be a Number');
 
1043
    }
803
1044
    if (this.end === undefined) {
804
1045
      this.end = Infinity;
 
1046
    } else if ('number' !== typeof this.end) {
 
1047
      throw TypeError('end must be a Number');
805
1048
    }
806
1049
 
807
1050
    if (this.start > this.end) {
808
 
      this.emit('error', new Error('start must be <= end'));
809
 
    } else {
810
 
      this._firstRead = true;
 
1051
      throw new Error('start must be <= end');
811
1052
    }
 
1053
 
 
1054
    this.pos = this.start;
812
1055
  }
813
1056
 
814
1057
  if (this.fd !== null) {
 
1058
    this._read();
815
1059
    return;
816
1060
  }
817
1061
 
839
1083
 
840
1084
ReadStream.prototype._read = function() {
841
1085
  var self = this;
842
 
  if (!self.readable || self.paused || self.reading) return;
 
1086
  if (!this.readable || this.paused || this.reading) return;
843
1087
 
844
 
  self.reading = true;
 
1088
  this.reading = true;
845
1089
 
846
1090
  if (!pool || pool.length - pool.used < kMinPoolSpace) {
847
1091
    // discard the old pool. Can't add to the free list because
850
1094
    allocNewPool();
851
1095
  }
852
1096
 
853
 
  if (self.start !== undefined && self._firstRead) {
854
 
    self.pos = self.start;
855
 
    self._firstRead = false;
856
 
  }
857
 
 
858
1097
  // Grab another reference to the pool in the case that while we're in the
859
1098
  // thread pool another read() finishes up the pool, and allocates a new
860
1099
  // one.
861
1100
  var thisPool = pool;
862
 
  var toRead = Math.min(pool.length - pool.used, this.bufferSize);
 
1101
  var toRead = Math.min(pool.length - pool.used, ~~this.bufferSize);
863
1102
  var start = pool.used;
864
1103
 
865
1104
  if (this.pos !== undefined) {
899
1138
    self._read();
900
1139
  }
901
1140
 
902
 
  fs.read(self.fd, pool, pool.used, toRead, self.pos, afterRead);
 
1141
  fs.read(this.fd, pool, pool.used, toRead, this.pos, afterRead);
903
1142
 
904
 
  if (self.pos !== undefined) {
905
 
    self.pos += toRead;
 
1143
  if (this.pos !== undefined) {
 
1144
    this.pos += toRead;
906
1145
  }
907
1146
  pool.used += toRead;
908
1147
};
979
1218
 
980
1219
  this.flags = 'w';
981
1220
  this.encoding = 'binary';
982
 
  this.mode = parseInt('0666', 8);
 
1221
  this.mode = 438; /*=0666*/
 
1222
  this.bytesWritten = 0;
983
1223
 
984
1224
  options = options || {};
985
1225
 
990
1230
    this[key] = options[key];
991
1231
  }
992
1232
 
 
1233
  if (this.start !== undefined) {
 
1234
    if ('number' !== typeof this.start) {
 
1235
      throw TypeError('start must be a Number');
 
1236
    }
 
1237
    if (this.start < 0) {
 
1238
      throw new Error('start must be >= zero');
 
1239
    }
 
1240
 
 
1241
    this.pos = this.start;
 
1242
  }
 
1243
 
993
1244
  this.busy = false;
994
1245
  this._queue = [];
995
1246
 
1008
1259
 
1009
1260
  var args = this._queue.shift();
1010
1261
  if (!args) {
1011
 
    if (this.drainable) { self.emit('drain'); }
 
1262
    if (this.drainable) { this.emit('drain'); }
1012
1263
    return;
1013
1264
  }
1014
1265
 
1017
1268
  var method = args.shift(),
1018
1269
      cb = args.pop();
1019
1270
 
1020
 
  var self = this;
1021
 
 
1022
1271
  args.push(function(err) {
1023
1272
    self.busy = false;
1024
1273
 
1031
1280
      return;
1032
1281
    }
1033
1282
 
1034
 
    // stop flushing after close
1035
 
    if (method === fs.close) {
 
1283
    if (method == fs.write) {
 
1284
      self.bytesWritten += arguments[1];
1036
1285
      if (cb) {
1037
 
        cb(null);
 
1286
        // write callback
 
1287
        cb(null, arguments[1]);
1038
1288
      }
1039
 
      self.emit('close');
1040
 
      return;
1041
 
    }
1042
1289
 
1043
 
    // save reference for file pointer
1044
 
    if (method === fs.open) {
 
1290
    } else if (method === fs.open) {
 
1291
      // save reference for file pointer
1045
1292
      self.fd = arguments[1];
1046
1293
      self.emit('open', self.fd);
1047
 
    } else if (cb) {
1048
 
      // write callback
1049
 
      cb(null, arguments[1]);
 
1294
 
 
1295
    } else if (method === fs.close) {
 
1296
      // stop flushing after close
 
1297
      if (cb) {
 
1298
        cb(null);
 
1299
      }
 
1300
      self.emit('close');
 
1301
      return;
1050
1302
    }
1051
1303
 
1052
1304
    self.flush();
1054
1306
 
1055
1307
  // Inject the file pointer
1056
1308
  if (method !== fs.open) {
1057
 
    args.unshift(self.fd);
 
1309
    args.unshift(this.fd);
1058
1310
  }
1059
1311
 
1060
1312
  method.apply(this, args);
1062
1314
 
1063
1315
WriteStream.prototype.write = function(data) {
1064
1316
  if (!this.writable) {
1065
 
    throw new Error('stream not writable');
 
1317
    this.emit('error', new Error('stream not writable'));
 
1318
    return false;
1066
1319
  }
1067
1320
 
1068
1321
  this.drainable = true;
1072
1325
    cb = arguments[arguments.length - 1];
1073
1326
  }
1074
1327
 
1075
 
  if (Buffer.isBuffer(data)) {
1076
 
    this._queue.push([fs.write, data, 0, data.length, null, cb]);
1077
 
  } else {
 
1328
  if (!Buffer.isBuffer(data)) {
1078
1329
    var encoding = 'utf8';
1079
1330
    if (typeof(arguments[1]) == 'string') encoding = arguments[1];
1080
 
    this._queue.push([fs.write, data, undefined, encoding, cb]);
1081
 
  }
1082
 
 
 
1331
    data = new Buffer('' + data, encoding);
 
1332
  }
 
1333
 
 
1334
  this._queue.push([fs.write, data, 0, data.length, this.pos, cb]);
 
1335
 
 
1336
  if (this.pos !== undefined) {
 
1337
    this.pos += data.length;
 
1338
  }
1083
1339
 
1084
1340
  this.flush();
1085
1341
 
1127
1383
// There is no shutdown() for files.
1128
1384
WriteStream.prototype.destroySoon = WriteStream.prototype.end;
1129
1385
 
 
1386
 
 
1387
// SyncWriteStream is internal. DO NOT USE.
 
1388
// Temporary hack for process.stdout and process.stderr when piped to files.
 
1389
function SyncWriteStream(fd) {
 
1390
  this.fd = fd;
 
1391
  this.writable = true;
 
1392
  this.readable = false;
 
1393
};
 
1394
util.inherits(SyncWriteStream, Stream);
 
1395
 
 
1396
 
 
1397
// Export
 
1398
fs.SyncWriteStream = SyncWriteStream;
 
1399
 
 
1400
 
 
1401
SyncWriteStream.prototype.write = function(data, arg1, arg2) {
 
1402
  var encoding, cb;
 
1403
 
 
1404
  // parse arguments
 
1405
  if (arg1) {
 
1406
    if (typeof arg1 === 'string') {
 
1407
      encoding = arg1;
 
1408
      cb = arg2;
 
1409
    } else if (typeof arg1 === 'function') {
 
1410
      cb = arg1;
 
1411
    } else {
 
1412
      throw new Error("bad arg");
 
1413
    }
 
1414
  }
 
1415
 
 
1416
  // Change strings to buffers. SLOW
 
1417
  if (typeof data == 'string') {
 
1418
    data = new Buffer(data, encoding);
 
1419
  }
 
1420
 
 
1421
  fs.writeSync(this.fd, data, 0, data.length);
 
1422
 
 
1423
  if (cb) {
 
1424
    process.nextTick(cb);
 
1425
  }
 
1426
 
 
1427
  return true;
 
1428
};
 
1429
 
 
1430
 
 
1431
SyncWriteStream.prototype.end = function(data, arg1, arg2) {
 
1432
  if (data) {
 
1433
    this.write(data, arg1, arg2);
 
1434
  }
 
1435
  this.destroy();
 
1436
};
 
1437
 
 
1438
 
 
1439
SyncWriteStream.prototype.destroy = function() {
 
1440
  fs.closeSync(this.fd);
 
1441
  this.fd = null;
 
1442
  this.emit('close');
 
1443
  return true;
 
1444
};
 
1445
 
 
1446
SyncWriteStream.prototype.destroySoon = SyncWriteStream.prototype.destroy;