Allow relpaths for symlink targets (needed by P9vfs), get rid of path info in Node

This commit is contained in:
David Humphrey 2018-05-29 10:48:18 -04:00
parent 9508833b37
commit 4e73ef8d9b
3 changed files with 37 additions and 24 deletions

View File

@ -136,7 +136,6 @@ function make_node(context, path, type, callback) {
} else { } else {
parentNodeData = result; parentNodeData = result;
Node.create({ Node.create({
path: path,
guid: context.guid, guid: context.guid,
type: type type: type
}, function(error, result) { }, function(error, result) {
@ -335,8 +334,7 @@ function ensure_root_directory(context, callback) {
Node.create({ Node.create({
guid: context.guid, guid: context.guid,
id: superNode.rnode, id: superNode.rnode,
type: NODE_TYPE_DIRECTORY, type: NODE_TYPE_DIRECTORY
path: ROOT_DIRECTORY_NAME
}, function(error, result) { }, function(error, result) {
if(error) { if(error) {
callback(error); callback(error);
@ -400,8 +398,7 @@ function make_directory(context, path, callback) {
parentDirectoryData = result; parentDirectoryData = result;
Node.create({ Node.create({
guid: context.guid, guid: context.guid,
type: NODE_TYPE_DIRECTORY, type: NODE_TYPE_DIRECTORY
path: path
}, function(error, result) { }, function(error, result) {
if(error) { if(error) {
callback(error); callback(error);
@ -641,8 +638,7 @@ function open_file(context, path, flags, callback) {
function write_file_node() { function write_file_node() {
Node.create({ Node.create({
guid: context.guid, guid: context.guid,
type: NODE_TYPE_FILE, type: NODE_TYPE_FILE
path: path
}, function(error, result) { }, function(error, result) {
if(error) { if(error) {
callback(error); callback(error);
@ -1135,8 +1131,7 @@ function make_symbolic_link(context, srcpath, dstpath, callback) {
function write_file_node() { function write_file_node() {
Node.create({ Node.create({
guid: context.guid, guid: context.guid,
type: NODE_TYPE_SYMBOLIC_LINK, type: NODE_TYPE_SYMBOLIC_LINK
path: dstpath
}, function(error, result) { }, function(error, result) {
if(error) { if(error) {
callback(error); callback(error);
@ -1144,8 +1139,17 @@ function make_symbolic_link(context, srcpath, dstpath, callback) {
} }
fileNode = result; fileNode = result;
fileNode.nlinks += 1; fileNode.nlinks += 1;
// If the srcpath isn't absolute, resolve it relative to the dstpath
// but store both versions, since we'll use the relative one in readlink().
if(!isAbsolutePath(srcpath)) {
fileNode.symlink_relpath = srcpath;
srcpath = Path.resolve(parentPath, srcpath);
}
fileNode.size = srcpath.length; fileNode.size = srcpath.length;
fileNode.data = srcpath; fileNode.data = srcpath;
context.putObject(fileNode.id, fileNode, update_directory_data); context.putObject(fileNode.id, fileNode, update_directory_data);
}); });
} }
@ -1201,14 +1205,17 @@ function read_link(context, path, callback) {
} }
} }
function check_if_symbolic(error, result) { function check_if_symbolic(error, fileNode) {
if(error) { if(error) {
callback(error); callback(error);
} else { } else {
if(result.type != NODE_TYPE_SYMBOLIC_LINK) { if(fileNode.type != NODE_TYPE_SYMBOLIC_LINK) {
callback(new Errors.EINVAL('path not a symbolic link', path)); callback(new Errors.EINVAL('path not a symbolic link', path));
} else { } else {
callback(null, result.data); // If we were originally given a relative path, return that now vs. the
// absolute path we've generated and use elsewhere internally.
var target = fileNode.symlink_relpath ? fileNode.symlink_relpath : fileNode.data;
callback(null, target);
} }
} }
} }
@ -1571,14 +1578,19 @@ function validate_file_options(options, enc, fileMode){
return options; return options;
} }
function pathCheck(path, callback) { function pathCheck(path, allowRelative, callback) {
var err; var err;
if(typeof allowRelative === 'function') {
callback = allowRelative;
allowRelative = false;
}
if(!path) { if(!path) {
err = new Errors.EINVAL('Path must be a string', path); err = new Errors.EINVAL('Path must be a string', path);
} else if(isNullPath(path)) { } else if(isNullPath(path)) {
err = new Errors.EINVAL('Path must be a string without null bytes.', path); err = new Errors.EINVAL('Path must be a string without null bytes.', path);
} else if(!isAbsolutePath(path)) { } else if(!allowRelative && !isAbsolutePath(path)) {
err = new Errors.EINVAL('Path must be absolute.', path); err = new Errors.EINVAL('Path must be absolute.', path);
} }
@ -2303,8 +2315,13 @@ function rename(fs, context, oldpath, newpath, callback) {
function symlink(fs, context, srcpath, dstpath, type, callback) { function symlink(fs, context, srcpath, dstpath, type, callback) {
// NOTE: we support passing the `type` arg, but ignore it. // NOTE: we support passing the `type` arg, but ignore it.
callback = arguments[arguments.length - 1]; callback = arguments[arguments.length - 1];
if(!pathCheck(srcpath, callback)) return;
// Special Case: allow srcpath to be relative, which we normally don't permit.
// If the srcpath is relative, we assume it's relative to the dirpath of
// dstpath.
if(!pathCheck(srcpath, true, callback)) return;
if(!pathCheck(dstpath, callback)) return; if(!pathCheck(dstpath, callback)) return;
make_symbolic_link(context, srcpath, dstpath, callback); make_symbolic_link(context, srcpath, dstpath, callback);
} }

View File

@ -1,6 +1,3 @@
var path = require('./path.js');
var hash32 = require('./encoding.js').hash32;
var NODE_TYPE_FILE = require('./constants.js').NODE_TYPE_FILE; var NODE_TYPE_FILE = require('./constants.js').NODE_TYPE_FILE;
var NODE_TYPE_DIRECTORY = require('./constants.js').NODE_TYPE_DIRECTORY; var NODE_TYPE_DIRECTORY = require('./constants.js').NODE_TYPE_DIRECTORY;
var NODE_TYPE_SYMBOLIC_LINK = require('./constants.js').NODE_TYPE_SYMBOLIC_LINK; var NODE_TYPE_SYMBOLIC_LINK = require('./constants.js').NODE_TYPE_SYMBOLIC_LINK;

View File

@ -26,7 +26,7 @@ describe("node.js tests: https://github.com/joyent/node/blob/master/test/simple/
done(); done();
} }
}); });
console.log('fn', fn);
fn.apply(fs, args); fn.apply(fs, args);
} }
@ -49,11 +49,10 @@ describe("node.js tests: https://github.com/joyent/node/blob/master/test/simple/
check(fs.appendFile, '/foo\u0000bar'); check(fs.appendFile, '/foo\u0000bar');
check(fs.truncate, '/foo\u0000bar'); check(fs.truncate, '/foo\u0000bar');
check(fs.utimes, '/foo\u0000bar', 0, 0); check(fs.utimes, '/foo\u0000bar', 0, 0);
// TODO - need to be implemented still... // Not implemented
// check(fs.realpath, '/foo\u0000bar'); // check(fs.realpath, '/foo\u0000bar');
// check(fs.chmod, '/foo\u0000bar', '0644'); check(fs.chmod, '/foo\u0000bar', '0644');
// check(fs.chown, '/foo\u0000bar', 12, 34); check(fs.chown, '/foo\u0000bar', 12, 34);
// check(fs.realpath, '/foo\u0000bar');
checks.forEach(function(fn){ checks.forEach(function(fn){
fn(); fn();