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

Commit

Permalink
Enable long paths on windows
Browse files Browse the repository at this point in the history
  • Loading branch information
Author: Igor Zinkovsky authored and piscisaureus committed Nov 25, 2011
1 parent 3195809 commit 1f16a7b
Show file tree
Hide file tree
Showing 5 changed files with 173 additions and 42 deletions.
89 changes: 49 additions & 40 deletions lib/fs.js
Expand Up @@ -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');
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand All @@ -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) {
Expand All @@ -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) {
Expand All @@ -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) {
Expand Down Expand Up @@ -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')) {
Expand Down Expand Up @@ -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
Expand All @@ -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) {
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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);
};


Expand Down Expand Up @@ -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) {
Expand All @@ -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];
}
Expand All @@ -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]);
}
Expand All @@ -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];
Expand Down Expand Up @@ -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 = '';
}
Expand All @@ -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]);
Expand Down Expand Up @@ -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 = '';

Expand Down
21 changes: 21 additions & 0 deletions lib/path.js
Expand Up @@ -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;
};
18 changes: 16 additions & 2 deletions src/node_file.cc
Expand Up @@ -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 {
Expand All @@ -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;
}
Expand Down

0 comments on commit 1f16a7b

Please sign in to comment.