Refactor Node to support layout changes with backwad compatibility
This commit is contained in:
parent
f738cbc17d
commit
d0178539f5
|
@ -201,7 +201,7 @@ function find_node(context, path, callback) {
|
||||||
} else if(!rootDirectoryNode) {
|
} else if(!rootDirectoryNode) {
|
||||||
callback(new Errors.ENOENT());
|
callback(new Errors.ENOENT());
|
||||||
} else {
|
} else {
|
||||||
callback(null, rootDirectoryNode);
|
Node.create(rootDirectoryNode, callback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,11 +227,18 @@ function find_node(context, path, callback) {
|
||||||
callback(new Errors.ENOENT(null, path));
|
callback(new Errors.ENOENT(null, path));
|
||||||
} else {
|
} else {
|
||||||
var nodeId = parentDirectoryData[name].id;
|
var nodeId = parentDirectoryData[name].id;
|
||||||
context.getObject(nodeId, is_symbolic_link);
|
context.getObject(nodeId, create_node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function create_node(error, data) {
|
||||||
|
if(error) {
|
||||||
|
return callback(error);
|
||||||
|
}
|
||||||
|
Node.create(data, is_symbolic_link);
|
||||||
|
}
|
||||||
|
|
||||||
function is_symbolic_link(error, node) {
|
function is_symbolic_link(error, node) {
|
||||||
if(error) {
|
if(error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
|
@ -664,7 +671,7 @@ function open_file(context, path, flags, mode, callback) {
|
||||||
fileNode = result;
|
fileNode = result;
|
||||||
fileNode.nlinks += 1;
|
fileNode.nlinks += 1;
|
||||||
if(mode){
|
if(mode){
|
||||||
Node.setMode(mode, fileNode);
|
fileNode.mode = mode;
|
||||||
}
|
}
|
||||||
context.putObject(fileNode.id, fileNode, write_file_data);
|
context.putObject(fileNode.id, fileNode, write_file_data);
|
||||||
});
|
});
|
||||||
|
@ -2006,7 +2013,7 @@ function chmod_file(context, path, mode, callback) {
|
||||||
if (error) {
|
if (error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
} else {
|
} else {
|
||||||
Node.setMode(mode, node);
|
node.mode = mode;
|
||||||
update_node_times(context, path, node, { mtime: Date.now() }, callback);
|
update_node_times(context, path, node, { mtime: Date.now() }, callback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
136
src/node.js
136
src/node.js
|
@ -1,34 +1,60 @@
|
||||||
var Constants = require('./constants.js');
|
const {
|
||||||
var NODE_TYPE_FILE = Constants.NODE_TYPE_FILE;
|
NODE_TYPE_FILE,
|
||||||
var NODE_TYPE_DIRECTORY = Constants.NODE_TYPE_DIRECTORY;
|
NODE_TYPE_DIRECTORY,
|
||||||
var NODE_TYPE_SYMBOLIC_LINK = Constants.NODE_TYPE_SYMBOLIC_LINK;
|
NODE_TYPE_SYMBOLIC_LINK,
|
||||||
|
DEFAULT_FILE_PERMISSIONS,
|
||||||
|
DEFAULT_DIR_PERMISSIONS
|
||||||
|
} = require('./constants');
|
||||||
|
const {
|
||||||
|
S_IFREG,
|
||||||
|
S_IFDIR,
|
||||||
|
S_IFLNK
|
||||||
|
} = require('./constants').fsConstants;
|
||||||
|
|
||||||
var S_IFREG = Constants.fsConstants.S_IFREG;
|
/**
|
||||||
var S_IFDIR = Constants.fsConstants.S_IFDIR;
|
* Make sure the options object has an id on property,
|
||||||
var S_IFLNK = Constants.fsConstants.S_IFLNK;
|
* either from caller or one we generate using supplied guid fn.
|
||||||
|
*/
|
||||||
|
function ensureID(options, prop, callback) {
|
||||||
|
if(options[prop]) {
|
||||||
|
return callback();
|
||||||
|
}
|
||||||
|
|
||||||
var DEFAULT_FILE_PERMISSIONS = Constants.DEFAULT_FILE_PERMISSIONS;
|
options.guid(function(err, id) {
|
||||||
var DEFAULT_DIR_PERMISSIONS = Constants.DEFAULT_DIR_PERMISSIONS;
|
if(err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
options[prop] = id;
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function getMode(type, mode) {
|
/**
|
||||||
switch(type) {
|
* Generate a POSIX mode (integer) for the node type and permissions.
|
||||||
|
* Use default permissions if we aren't passed any.
|
||||||
|
*/
|
||||||
|
function generateMode(nodeType, modePermissions) {
|
||||||
|
switch(nodeType) {
|
||||||
case NODE_TYPE_DIRECTORY:
|
case NODE_TYPE_DIRECTORY:
|
||||||
return (mode || DEFAULT_DIR_PERMISSIONS) | S_IFDIR;
|
return (modePermissions || DEFAULT_DIR_PERMISSIONS) | S_IFDIR;
|
||||||
case NODE_TYPE_SYMBOLIC_LINK:
|
case NODE_TYPE_SYMBOLIC_LINK:
|
||||||
return (mode || DEFAULT_FILE_PERMISSIONS) | S_IFLNK;
|
return (modePermissions || DEFAULT_FILE_PERMISSIONS) | S_IFLNK;
|
||||||
/* jshint -W086 */
|
|
||||||
case NODE_TYPE_FILE:
|
case NODE_TYPE_FILE:
|
||||||
// falls through
|
// falls through
|
||||||
default:
|
default:
|
||||||
return (mode || DEFAULT_FILE_PERMISSIONS) | S_IFREG;
|
return (modePermissions || DEFAULT_FILE_PERMISSIONS) | S_IFREG;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Node(options) {
|
/**
|
||||||
|
* Common properties for the layout of a Node
|
||||||
|
*/
|
||||||
|
class Node {
|
||||||
|
constructor(options) {
|
||||||
var now = Date.now();
|
var now = Date.now();
|
||||||
|
|
||||||
this.id = options.id;
|
this.id = options.id;
|
||||||
this.type = options.type || NODE_TYPE_FILE; // node type (file, directory, etc)
|
this.data = options.data; // id for data object
|
||||||
this.size = options.size || 0; // size (bytes for files, entries for directories)
|
this.size = options.size || 0; // size (bytes for files, entries for directories)
|
||||||
this.atime = options.atime || now; // access time (will mirror ctime after creation)
|
this.atime = options.atime || now; // access time (will mirror ctime after creation)
|
||||||
this.ctime = options.ctime || now; // creation/change time
|
this.ctime = options.ctime || now; // creation/change time
|
||||||
|
@ -36,50 +62,74 @@ function Node(options) {
|
||||||
this.flags = options.flags || []; // file flags
|
this.flags = options.flags || []; // file flags
|
||||||
this.xattrs = options.xattrs || {}; // extended attributes
|
this.xattrs = options.xattrs || {}; // extended attributes
|
||||||
this.nlinks = options.nlinks || 0; // links count
|
this.nlinks = options.nlinks || 0; // links count
|
||||||
this.data = options.data; // id for data object
|
|
||||||
this.version = options.version || 1;
|
|
||||||
|
|
||||||
// permissions and flags
|
// Historically, Filer's node layout has referred to the
|
||||||
this.mode = options.mode || (getMode(this.type));
|
// node type as `mode`, and done so using a String. In
|
||||||
|
// a POSIX filesystem, the mode is a number that combines
|
||||||
|
// both node type and permission bits. Internal we use `type`,
|
||||||
|
// but store it in the database as `mode` for backward
|
||||||
|
// compatibility.
|
||||||
|
if(typeof options.type === 'string') {
|
||||||
|
this.type = options.type;
|
||||||
|
} else if(typeof options.mode === 'string') {
|
||||||
|
this.type = options.mode;
|
||||||
|
} else {
|
||||||
|
this.type = NODE_TYPE_FILE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extra mode permissions and ownership info
|
||||||
|
this.permissions = options.permissions || generateMode(this.type);
|
||||||
this.uid = options.uid || 0x0; // owner name
|
this.uid = options.uid || 0x0; // owner name
|
||||||
this.gid = options.gid || 0x0; // group name
|
this.gid = options.gid || 0x0; // group name
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the options object has an id on property,
|
/**
|
||||||
// either from caller or one we generate using supplied guid fn.
|
* Serialize a Node to JSON. Everything is as expected except
|
||||||
function ensureID(options, prop, callback) {
|
* that we use `mode` for `type` to maintain backward compatibility.
|
||||||
if(options[prop]) {
|
*/
|
||||||
callback(null);
|
toJSON() {
|
||||||
} else {
|
return {
|
||||||
options.guid(function(err, id) {
|
id: this.id,
|
||||||
options[prop] = id;
|
data: this.data,
|
||||||
callback(err);
|
size: this.size,
|
||||||
});
|
atime: this.atime,
|
||||||
|
ctime: this.ctime,
|
||||||
|
mtime: this.ctime,
|
||||||
|
flags: this.flags,
|
||||||
|
xattrs: this.xattrs,
|
||||||
|
nlinks: this.nlinks,
|
||||||
|
// Use `mode` for `type` to keep backward compatibility
|
||||||
|
mode: this.type,
|
||||||
|
permissions: this.permissions,
|
||||||
|
uid: this.uid,
|
||||||
|
gid: this.gid
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return complete POSIX `mode` for node type + permissions. See:
|
||||||
|
// http://man7.org/linux/man-pages/man2/chmod.2.html
|
||||||
|
get mode() {
|
||||||
|
return generateMode(this.type, this.permissions);
|
||||||
|
}
|
||||||
|
// When setting the `mode` we assume permissions bits only (not changing type)
|
||||||
|
set mode(value) {
|
||||||
|
this.permissions = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Node.create = function(options, callback) {
|
module.exports.create = function create(options, callback) {
|
||||||
// We expect both options.id and options.data to be provided/generated.
|
// We expect both options.id and options.data to be provided/generated.
|
||||||
ensureID(options, 'id', function(err) {
|
ensureID(options, 'id', function(err) {
|
||||||
if(err) {
|
if(err) {
|
||||||
callback(err);
|
return callback(err);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ensureID(options, 'data', function(err) {
|
ensureID(options, 'data', function(err) {
|
||||||
if(err) {
|
if(err) {
|
||||||
callback(err);
|
return callback(err);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(null, new Node(options));
|
callback(null, new Node(options));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update the node's mode (permissions), taking file type bits into account.
|
|
||||||
Node.setMode = function(mode, node) {
|
|
||||||
node.mode = getMode(node.type, mode);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = Node;
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
var Errors = require('./errors.js');
|
const Errors = require('./errors.js');
|
||||||
|
const Node = require('./node');
|
||||||
|
|
||||||
function OpenFileDescription(path, id, flags, position) {
|
function OpenFileDescription(path, id, flags, position) {
|
||||||
this.path = path;
|
this.path = path;
|
||||||
|
@ -22,7 +23,7 @@ OpenFileDescription.prototype.getNode = function(context, callback) {
|
||||||
return callback(new Errors.EBADF('file descriptor refers to unknown node', path));
|
return callback(new Errors.EBADF('file descriptor refers to unknown node', path));
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(null, node);
|
Node.create(node, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.getObject(id, check_if_node_exists);
|
context.getObject(id, check_if_node_exists);
|
||||||
|
|
Loading…
Reference in New Issue