Skip to content
This repository was archived by the owner on Apr 22, 2023. It is now read-only.

Commit 1f16a7b

Browse files
Author: Igor Zinkovskypiscisaureus
Author: Igor Zinkovsky
authored andcommitted
Enable long paths on windows
1 parent 3195809 commit 1f16a7b

File tree

5 files changed

+173
-42
lines changed

5 files changed

+173
-42
lines changed

lib/fs.js

+49-40
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
// var mode = 438; /* mode=0666 */
2727

2828
var util = require('util');
29+
var pathModule = require('path');
2930

3031
var binding = process.binding('fs');
3132
var constants = process.binding('constants');
@@ -220,12 +221,13 @@ fs.open = function(path, flags, mode, callback) {
220221

221222
mode = modeNum(mode, 438 /*=0666*/);
222223

223-
binding.open(path, stringToFlags(flags), mode, callback);
224+
binding.open(pathModule._makeLong(path), stringToFlags(flags), mode,
225+
callback);
224226
};
225227

226228
fs.openSync = function(path, flags, mode) {
227229
mode = modeNum(mode, 438 /*=0666*/);
228-
return binding.open(path, stringToFlags(flags), mode);
230+
return binding.open(pathModule._makeLong(path), stringToFlags(flags), mode);
229231
};
230232

231233
fs.read = function(fd, buffer, offset, length, position, callback) {
@@ -320,11 +322,13 @@ fs.writeSync = function(fd, buffer, offset, length, position) {
320322
};
321323

322324
fs.rename = function(oldPath, newPath, callback) {
323-
binding.rename(oldPath, newPath, callback || noop);
325+
binding.rename(pathModule._makeLong(oldPath), pathModule._makeLong(newPath),
326+
callback || noop);
324327
};
325328

326329
fs.renameSync = function(oldPath, newPath) {
327-
return binding.rename(oldPath, newPath);
330+
return binding.rename(pathModule._makeLong(oldPath),
331+
pathModule._makeLong(newPath));
328332
};
329333

330334
fs.truncate = function(fd, len, callback) {
@@ -336,11 +340,11 @@ fs.truncateSync = function(fd, len) {
336340
};
337341

338342
fs.rmdir = function(path, callback) {
339-
binding.rmdir(path, callback || noop);
343+
binding.rmdir(pathModule._makeLong(path), callback || noop);
340344
};
341345

342346
fs.rmdirSync = function(path) {
343-
return binding.rmdir(path);
347+
return binding.rmdir(pathModule._makeLong(path));
344348
};
345349

346350
fs.fdatasync = function(fd, callback) {
@@ -361,11 +365,13 @@ fs.fsyncSync = function(fd) {
361365

362366
fs.mkdir = function(path, mode, callback) {
363367
if (typeof mode === 'function') callback = mode;
364-
binding.mkdir(path, modeNum(mode, 511 /*=0777*/), callback || noop);
368+
binding.mkdir(pathModule._makeLong(path), modeNum(mode, 511 /*=0777*/),
369+
callback || noop);
365370
};
366371

367372
fs.mkdirSync = function(path, mode) {
368-
return binding.mkdir(path, modeNum(mode, 511 /*=0777*/));
373+
return binding.mkdir(pathModule._makeLong(path),
374+
modeNum(mode, 511 /*=0777*/));
369375
};
370376

371377
fs.sendfile = function(outFd, inFd, inOffset, length, callback) {
@@ -377,70 +383,74 @@ fs.sendfileSync = function(outFd, inFd, inOffset, length) {
377383
};
378384

379385
fs.readdir = function(path, callback) {
380-
binding.readdir(path, callback || noop);
386+
binding.readdir(pathModule._makeLong(path), callback || noop);
381387
};
382388

383389
fs.readdirSync = function(path) {
384-
return binding.readdir(path);
390+
return binding.readdir(pathModule._makeLong(path));
385391
};
386392

387393
fs.fstat = function(fd, callback) {
388394
binding.fstat(fd, callback || noop);
389395
};
390396

391397
fs.lstat = function(path, callback) {
392-
binding.lstat(path, callback || noop);
398+
binding.lstat(pathModule._makeLong(path), callback || noop);
393399
};
394400

395401
fs.stat = function(path, callback) {
396-
binding.stat(path, callback || noop);
402+
binding.stat(pathModule._makeLong(path), callback || noop);
397403
};
398404

399405
fs.fstatSync = function(fd) {
400406
return binding.fstat(fd);
401407
};
402408

403409
fs.lstatSync = function(path) {
404-
return binding.lstat(path);
410+
return binding.lstat(pathModule._makeLong(path));
405411
};
406412

407413
fs.statSync = function(path) {
408-
return binding.stat(path);
414+
return binding.stat(pathModule._makeLong(path));
409415
};
410416

411417
fs.readlink = function(path, callback) {
412-
binding.readlink(path, callback || noop);
418+
binding.readlink(pathModule._makeLong(path), callback || noop);
413419
};
414420

415421
fs.readlinkSync = function(path) {
416-
return binding.readlink(path);
422+
return binding.readlink(pathModule._makeLong(path));
417423
};
418424

419425
fs.symlink = function(destination, path, mode_, callback) {
420426
var mode = (typeof(mode_) == 'string' ? mode_ : null);
421427
var callback_ = arguments[arguments.length - 1];
422428
callback = (typeof(callback_) == 'function' ? callback_ : null);
423-
binding.symlink(destination, path, mode, callback);
429+
binding.symlink(pathModule._makeLong(destination),
430+
pathModule._makeLong(path), mode, callback);
424431
};
425432

426433
fs.symlinkSync = function(destination, path, mode) {
427-
return binding.symlink(destination, path, mode);
434+
return binding.symlink(pathModule._makeLong(destination),
435+
pathModule._makeLong(path), mode);
428436
};
429437

430438
fs.link = function(srcpath, dstpath, callback) {
431-
binding.link(srcpath, dstpath, callback || noop);
439+
binding.link(pathModule._makeLong(srcpath), pathModule._makeLong(dstpath),
440+
callback || noop);
432441
};
433442

434443
fs.linkSync = function(srcpath, dstpath) {
435-
return binding.link(srcpath, dstpath);
444+
return binding.link(pathModule._makeLong(srcpath),
445+
pathModule._makeLong(dstpath));
436446
};
437447

438448
fs.unlink = function(path, callback) {
439-
binding.unlink(path, callback || noop);
449+
binding.unlink(pathModule._makeLong(path), callback || noop);
440450
};
441451

442452
fs.unlinkSync = function(path) {
443-
return binding.unlink(path);
453+
return binding.unlink(pathModule._makeLong(path));
444454
};
445455

446456
fs.fchmod = function(fd, mode, callback) {
@@ -492,11 +502,11 @@ if (constants.hasOwnProperty('O_SYMLINK')) {
492502

493503

494504
fs.chmod = function(path, mode, callback) {
495-
binding.chmod(path, modeNum(mode), callback || noop);
505+
binding.chmod(pathModule._makeLong(path), modeNum(mode), callback || noop);
496506
};
497507

498508
fs.chmodSync = function(path, mode) {
499-
return binding.chmod(path, modeNum(mode));
509+
return binding.chmod(pathModule._makeLong(path), modeNum(mode));
500510
};
501511

502512
if (constants.hasOwnProperty('O_SYMLINK')) {
@@ -526,11 +536,11 @@ fs.fchownSync = function(fd, uid, gid) {
526536
};
527537

528538
fs.chown = function(path, uid, gid, callback) {
529-
binding.chown(path, uid, gid, callback || noop);
539+
binding.chown(pathModule._makeLong(path), uid, gid, callback || noop);
530540
};
531541

532542
fs.chownSync = function(path, uid, gid) {
533-
return binding.chown(path, uid, gid);
543+
return binding.chown(pathModule._makeLong(path), uid, gid);
534544
};
535545

536546
// converts Date or number to a fractional UNIX timestamp
@@ -551,13 +561,13 @@ fs._toUnixTimestamp = toUnixTimestamp;
551561
fs.utimes = function(path, atime, mtime, callback) {
552562
atime = toUnixTimestamp(atime);
553563
mtime = toUnixTimestamp(mtime);
554-
binding.utimes(path, atime, mtime, callback || noop);
564+
binding.utimes(pathModule._makeLong(path), atime, mtime, callback || noop);
555565
};
556566

557567
fs.utimesSync = function(path, atime, mtime) {
558568
atime = toUnixTimestamp(atime);
559569
mtime = toUnixTimestamp(mtime);
560-
binding.utimes(path, atime, mtime);
570+
binding.utimes(pathModule._makeLong(path), atime, mtime);
561571
};
562572

563573
fs.futimes = function(fd, atime, mtime, callback) {
@@ -646,7 +656,7 @@ function FSWatcher() {
646656
util.inherits(FSWatcher, EventEmitter);
647657

648658
FSWatcher.prototype.start = function(filename, persistent) {
649-
var r = this._handle.start(filename, persistent);
659+
var r = this._handle.start(pathModule._makeLong(filename), persistent);
650660

651661
if (r) {
652662
this._handle.close();
@@ -703,7 +713,7 @@ util.inherits(StatWatcher, EventEmitter);
703713

704714

705715
StatWatcher.prototype.start = function(filename, persistent, interval) {
706-
this._handle.start(filename, persistent, interval);
716+
this._handle.start(pathModule._makeLong(filename), persistent, interval);
707717
};
708718

709719

@@ -766,8 +776,7 @@ fs.unwatchFile = function(filename) {
766776
// Not using realpath(2) because it's bad.
767777
// See: http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html
768778

769-
var path = require('path'),
770-
normalize = path.normalize,
779+
var normalize = pathModule.normalize,
771780
isWindows = process.platform === 'win32';
772781

773782
if (isWindows) {
@@ -776,7 +785,7 @@ if (isWindows) {
776785

777786
// windows version
778787
fs.realpathSync = function realpathSync(p, cache) {
779-
p = path.resolve(p);
788+
p = pathModule.resolve(p);
780789
if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
781790
return cache[p];
782791
}
@@ -791,7 +800,7 @@ if (isWindows) {
791800
cb = cache;
792801
cache = null;
793802
}
794-
p = path.resolve(p);
803+
p = pathModule.resolve(p);
795804
if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
796805
return cb(null, cache[p]);
797806
}
@@ -812,7 +821,7 @@ if (isWindows) {
812821
// posix version
813822
fs.realpathSync = function realpathSync(p, cache) {
814823
// make p is absolute
815-
p = path.resolve(p);
824+
p = pathModule.resolve(p);
816825

817826
if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
818827
return cache[p];
@@ -865,14 +874,14 @@ if (isWindows) {
865874
if (!seenLinks[id]) {
866875
fs.statSync(base);
867876
seenLinks[id] = fs.readlinkSync(base);
868-
resolvedLink = path.resolve(previous, seenLinks[id]);
877+
resolvedLink = pathModule.resolve(previous, seenLinks[id]);
869878
// track this, if given a cache.
870879
if (cache) cache[base] = resolvedLink;
871880
}
872881
}
873882

874883
// resolve the link, then start over
875-
p = path.resolve(resolvedLink, p.slice(pos));
884+
p = pathModule.resolve(resolvedLink, p.slice(pos));
876885
pos = 0;
877886
previous = base = current = '';
878887
}
@@ -891,7 +900,7 @@ if (isWindows) {
891900
}
892901

893902
// make p is absolute
894-
p = path.resolve(p);
903+
p = pathModule.resolve(p);
895904

896905
if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
897906
return cb(null, cache[p]);
@@ -969,15 +978,15 @@ if (isWindows) {
969978
function gotTarget(err, target, base) {
970979
if (err) return cb(err);
971980

972-
var resolvedLink = path.resolve(previous, target);
981+
var resolvedLink = pathModule.resolve(previous, target);
973982
if (cache) cache[base] = resolvedLink;
974983
gotResolvedLink(resolvedLink);
975984
}
976985

977986
function gotResolvedLink(resolvedLink) {
978987

979988
// resolve the link, then start over
980-
p = path.resolve(resolvedLink, p.slice(pos));
989+
p = pathModule.resolve(resolvedLink, p.slice(pos));
981990
pos = 0;
982991
previous = base = current = '';
983992

lib/path.js

+21
Original file line numberDiff line numberDiff line change
@@ -417,3 +417,24 @@ exports.existsSync = function(path) {
417417
return false;
418418
}
419419
};
420+
421+
422+
exports._makeLong = isWindows ?
423+
function(path) {
424+
var resolvedPath = exports.resolve(path);
425+
426+
if (resolvedPath.match(/^[a-zA-Z]\:\\/)) {
427+
// path is local filesystem path, which needs to be converted
428+
// to long UNC path.
429+
return '\\\\?\\' + resolvedPath;
430+
} else if (resolvedPath.match(/^\\\\[^?.]/)) {
431+
// path is network UNC path, which needs to be converted
432+
// to long UNC path.
433+
return '\\\\?\\UNC\\' + resolvedPath.substring(2);
434+
}
435+
436+
return path;
437+
} :
438+
function(path) {
439+
return path;
440+
};

src/node_file.cc

+16-2
Original file line numberDiff line numberDiff line change
@@ -252,9 +252,23 @@ Local<Value> FSError(int errorno,
252252

253253
Local<Value> e;
254254

255+
Local<String> path_str;
256+
255257
if (path) {
258+
#ifdef _WIN32
259+
if (memcmp(path, "\\\\?\\UNC\\", 8) == 0) {
260+
path_str = String::Concat(String::New("\\\\"), String::New(path + 8));
261+
} else if (memcmp(path, "\\\\?\\", 4) == 0) {
262+
path_str = String::New(path + 4);
263+
} else {
264+
path_str = String::New(path);
265+
}
266+
#else
267+
path_str = String::New(path);
268+
#endif
269+
256270
Local<String> cons3 = String::Concat(cons2, String::NewSymbol(" '"));
257-
Local<String> cons4 = String::Concat(cons3, String::New(path));
271+
Local<String> cons4 = String::Concat(cons3, path_str);
258272
Local<String> cons5 = String::Concat(cons4, String::NewSymbol("'"));
259273
e = Exception::Error(cons5);
260274
} else {
@@ -266,7 +280,7 @@ Local<Value> FSError(int errorno,
266280
// TODO errno should probably go
267281
obj->Set(errno_symbol, Integer::New(errorno));
268282
obj->Set(code_symbol, estring);
269-
if (path) obj->Set(errpath_symbol, String::New(path));
283+
if (path) obj->Set(errpath_symbol, path_str);
270284
if (syscall) obj->Set(syscall_symbol, String::NewSymbol(syscall));
271285
return e;
272286
}

0 commit comments

Comments
 (0)