Permalink
Browse files

Enable long paths on windows

  • Loading branch information...
1 parent 3195809 commit 1f16a7b6e541694067178a022b9f7a082a6ce7f1 Author: Igor Zinkovsky committed with piscisaureus Nov 25, 2011
Showing with 173 additions and 42 deletions.
  1. +49 −40 lib/fs.js
  2. +21 −0 lib/path.js
  3. +16 −2 src/node_file.cc
  4. +49 −0 test/simple/test-fs-long-path.js
  5. +38 −0 test/simple/test-path-makelong.js
View
@@ -26,6 +26,7 @@
// var mode = 438; /* mode=0666 */
var util = require('util');
+var pathModule = require('path');
var binding = process.binding('fs');
var constants = process.binding('constants');
@@ -220,12 +221,13 @@ fs.open = function(path, flags, mode, callback) {
mode = modeNum(mode, 438 /*=0666*/);
- binding.open(path, stringToFlags(flags), mode, callback);
+ binding.open(pathModule._makeLong(path), stringToFlags(flags), mode,
+ callback);
};
fs.openSync = function(path, flags, mode) {
mode = modeNum(mode, 438 /*=0666*/);
- return binding.open(path, stringToFlags(flags), mode);
+ return binding.open(pathModule._makeLong(path), stringToFlags(flags), mode);
};
fs.read = function(fd, buffer, offset, length, position, callback) {
@@ -320,11 +322,13 @@ fs.writeSync = function(fd, buffer, offset, length, position) {
};
fs.rename = function(oldPath, newPath, callback) {
- binding.rename(oldPath, newPath, callback || noop);
+ binding.rename(pathModule._makeLong(oldPath), pathModule._makeLong(newPath),
+ callback || noop);
};
fs.renameSync = function(oldPath, newPath) {
- return binding.rename(oldPath, newPath);
+ return binding.rename(pathModule._makeLong(oldPath),
+ pathModule._makeLong(newPath));
};
fs.truncate = function(fd, len, callback) {
@@ -336,11 +340,11 @@ fs.truncateSync = function(fd, len) {
};
fs.rmdir = function(path, callback) {
- binding.rmdir(path, callback || noop);
+ binding.rmdir(pathModule._makeLong(path), callback || noop);
};
fs.rmdirSync = function(path) {
- return binding.rmdir(path);
+ return binding.rmdir(pathModule._makeLong(path));
};
fs.fdatasync = function(fd, callback) {
@@ -361,11 +365,13 @@ fs.fsyncSync = function(fd) {
fs.mkdir = function(path, mode, callback) {
if (typeof mode === 'function') callback = mode;
- binding.mkdir(path, modeNum(mode, 511 /*=0777*/), callback || noop);
+ binding.mkdir(pathModule._makeLong(path), modeNum(mode, 511 /*=0777*/),
+ callback || noop);
};
fs.mkdirSync = function(path, mode) {
- return binding.mkdir(path, modeNum(mode, 511 /*=0777*/));
+ return binding.mkdir(pathModule._makeLong(path),
+ modeNum(mode, 511 /*=0777*/));
};
fs.sendfile = function(outFd, inFd, inOffset, length, callback) {
@@ -377,70 +383,74 @@ fs.sendfileSync = function(outFd, inFd, inOffset, length) {
};
fs.readdir = function(path, callback) {
- binding.readdir(path, callback || noop);
+ binding.readdir(pathModule._makeLong(path), callback || noop);
};
fs.readdirSync = function(path) {
- return binding.readdir(path);
+ return binding.readdir(pathModule._makeLong(path));
};
fs.fstat = function(fd, callback) {
binding.fstat(fd, callback || noop);
};
fs.lstat = function(path, callback) {
- binding.lstat(path, callback || noop);
+ binding.lstat(pathModule._makeLong(path), callback || noop);
};
fs.stat = function(path, callback) {
- binding.stat(path, callback || noop);
+ binding.stat(pathModule._makeLong(path), callback || noop);
};
fs.fstatSync = function(fd) {
return binding.fstat(fd);
};
fs.lstatSync = function(path) {
- return binding.lstat(path);
+ return binding.lstat(pathModule._makeLong(path));
};
fs.statSync = function(path) {
- return binding.stat(path);
+ return binding.stat(pathModule._makeLong(path));
};
fs.readlink = function(path, callback) {
- binding.readlink(path, callback || noop);
+ binding.readlink(pathModule._makeLong(path), callback || noop);
};
fs.readlinkSync = function(path) {
- return binding.readlink(path);
+ return binding.readlink(pathModule._makeLong(path));
};
fs.symlink = function(destination, path, mode_, callback) {
var mode = (typeof(mode_) == 'string' ? mode_ : null);
var callback_ = arguments[arguments.length - 1];
callback = (typeof(callback_) == 'function' ? callback_ : null);
- binding.symlink(destination, path, mode, callback);
+ binding.symlink(pathModule._makeLong(destination),
+ pathModule._makeLong(path), mode, callback);
};
fs.symlinkSync = function(destination, path, mode) {
- return binding.symlink(destination, path, mode);
+ return binding.symlink(pathModule._makeLong(destination),
+ pathModule._makeLong(path), mode);
};
fs.link = function(srcpath, dstpath, callback) {
- binding.link(srcpath, dstpath, callback || noop);
+ binding.link(pathModule._makeLong(srcpath), pathModule._makeLong(dstpath),
+ callback || noop);
};
fs.linkSync = function(srcpath, dstpath) {
- return binding.link(srcpath, dstpath);
+ return binding.link(pathModule._makeLong(srcpath),
+ pathModule._makeLong(dstpath));
};
fs.unlink = function(path, callback) {
- binding.unlink(path, callback || noop);
+ binding.unlink(pathModule._makeLong(path), callback || noop);
};
fs.unlinkSync = function(path) {
- return binding.unlink(path);
+ return binding.unlink(pathModule._makeLong(path));
};
fs.fchmod = function(fd, mode, callback) {
@@ -492,11 +502,11 @@ if (constants.hasOwnProperty('O_SYMLINK')) {
fs.chmod = function(path, mode, callback) {
- binding.chmod(path, modeNum(mode), callback || noop);
+ binding.chmod(pathModule._makeLong(path), modeNum(mode), callback || noop);
};
fs.chmodSync = function(path, mode) {
- return binding.chmod(path, modeNum(mode));
+ return binding.chmod(pathModule._makeLong(path), modeNum(mode));
};
if (constants.hasOwnProperty('O_SYMLINK')) {
@@ -526,11 +536,11 @@ fs.fchownSync = function(fd, uid, gid) {
};
fs.chown = function(path, uid, gid, callback) {
- binding.chown(path, uid, gid, callback || noop);
+ binding.chown(pathModule._makeLong(path), uid, gid, callback || noop);
};
fs.chownSync = function(path, uid, gid) {
- return binding.chown(path, uid, gid);
+ return binding.chown(pathModule._makeLong(path), uid, gid);
};
// converts Date or number to a fractional UNIX timestamp
@@ -551,13 +561,13 @@ fs._toUnixTimestamp = toUnixTimestamp;
fs.utimes = function(path, atime, mtime, callback) {
atime = toUnixTimestamp(atime);
mtime = toUnixTimestamp(mtime);
- binding.utimes(path, atime, mtime, callback || noop);
+ binding.utimes(pathModule._makeLong(path), atime, mtime, callback || noop);
};
fs.utimesSync = function(path, atime, mtime) {
atime = toUnixTimestamp(atime);
mtime = toUnixTimestamp(mtime);
- binding.utimes(path, atime, mtime);
+ binding.utimes(pathModule._makeLong(path), atime, mtime);
};
fs.futimes = function(fd, atime, mtime, callback) {
@@ -646,7 +656,7 @@ function FSWatcher() {
util.inherits(FSWatcher, EventEmitter);
FSWatcher.prototype.start = function(filename, persistent) {
- var r = this._handle.start(filename, persistent);
+ var r = this._handle.start(pathModule._makeLong(filename), persistent);
if (r) {
this._handle.close();
@@ -703,7 +713,7 @@ util.inherits(StatWatcher, EventEmitter);
StatWatcher.prototype.start = function(filename, persistent, interval) {
- this._handle.start(filename, persistent, interval);
+ this._handle.start(pathModule._makeLong(filename), persistent, interval);
};
@@ -766,8 +776,7 @@ fs.unwatchFile = function(filename) {
// Not using realpath(2) because it's bad.
// See: http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html
-var path = require('path'),
- normalize = path.normalize,
+var normalize = pathModule.normalize,
isWindows = process.platform === 'win32';
if (isWindows) {
@@ -776,7 +785,7 @@ if (isWindows) {
// windows version
fs.realpathSync = function realpathSync(p, cache) {
- p = path.resolve(p);
+ p = pathModule.resolve(p);
if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
return cache[p];
}
@@ -791,7 +800,7 @@ if (isWindows) {
cb = cache;
cache = null;
}
- p = path.resolve(p);
+ p = pathModule.resolve(p);
if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
return cb(null, cache[p]);
}
@@ -812,7 +821,7 @@ if (isWindows) {
// posix version
fs.realpathSync = function realpathSync(p, cache) {
// make p is absolute
- p = path.resolve(p);
+ p = pathModule.resolve(p);
if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
return cache[p];
@@ -865,14 +874,14 @@ if (isWindows) {
if (!seenLinks[id]) {
fs.statSync(base);
seenLinks[id] = fs.readlinkSync(base);
- resolvedLink = path.resolve(previous, seenLinks[id]);
+ resolvedLink = pathModule.resolve(previous, seenLinks[id]);
// track this, if given a cache.
if (cache) cache[base] = resolvedLink;
}
}
// resolve the link, then start over
- p = path.resolve(resolvedLink, p.slice(pos));
+ p = pathModule.resolve(resolvedLink, p.slice(pos));
pos = 0;
previous = base = current = '';
}
@@ -891,7 +900,7 @@ if (isWindows) {
}
// make p is absolute
- p = path.resolve(p);
+ p = pathModule.resolve(p);
if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
return cb(null, cache[p]);
@@ -969,15 +978,15 @@ if (isWindows) {
function gotTarget(err, target, base) {
if (err) return cb(err);
- var resolvedLink = path.resolve(previous, target);
+ var resolvedLink = pathModule.resolve(previous, target);
if (cache) cache[base] = resolvedLink;
gotResolvedLink(resolvedLink);
}
function gotResolvedLink(resolvedLink) {
// resolve the link, then start over
- p = path.resolve(resolvedLink, p.slice(pos));
+ p = pathModule.resolve(resolvedLink, p.slice(pos));
pos = 0;
previous = base = current = '';
View
@@ -417,3 +417,24 @@ exports.existsSync = function(path) {
return false;
}
};
+
+
+exports._makeLong = isWindows ?
+ function(path) {
+ var resolvedPath = exports.resolve(path);
+
+ if (resolvedPath.match(/^[a-zA-Z]\:\\/)) {
+ // path is local filesystem path, which needs to be converted
+ // to long UNC path.
+ return '\\\\?\\' + resolvedPath;
+ } else if (resolvedPath.match(/^\\\\[^?.]/)) {
+ // path is network UNC path, which needs to be converted
+ // to long UNC path.
+ return '\\\\?\\UNC\\' + resolvedPath.substring(2);
+ }
+
+ return path;
+ } :
+ function(path) {
+ return path;
+ };
View
@@ -252,9 +252,23 @@ Local<Value> FSError(int errorno,
Local<Value> e;
+ Local<String> path_str;
+
if (path) {
+#ifdef _WIN32
+ if (memcmp(path, "\\\\?\\UNC\\", 8) == 0) {
+ path_str = String::Concat(String::New("\\\\"), String::New(path + 8));
+ } else if (memcmp(path, "\\\\?\\", 4) == 0) {
+ path_str = String::New(path + 4);
+ } else {
+ path_str = String::New(path);
+ }
+#else
+ path_str = String::New(path);
+#endif
+
Local<String> cons3 = String::Concat(cons2, String::NewSymbol(" '"));
- Local<String> cons4 = String::Concat(cons3, String::New(path));
+ Local<String> cons4 = String::Concat(cons3, path_str);
Local<String> cons5 = String::Concat(cons4, String::NewSymbol("'"));
e = Exception::Error(cons5);
} else {
@@ -266,7 +280,7 @@ Local<Value> FSError(int errorno,
// TODO errno should probably go
obj->Set(errno_symbol, Integer::New(errorno));
obj->Set(code_symbol, estring);
- if (path) obj->Set(errpath_symbol, String::New(path));
+ if (path) obj->Set(errpath_symbol, path_str);
if (syscall) obj->Set(syscall_symbol, String::NewSymbol(syscall));
return e;
}
Oops, something went wrong.

0 comments on commit 1f16a7b

Please sign in to comment.