Fix mode, fs.link, fix other bugs and cleanup
This commit is contained in:
parent
0aaaeacd1a
commit
c526445a43
|
@ -24,6 +24,13 @@ module.exports = {
|
|||
NODE_TYPE_SYMBOLIC_LINK: 'SYMLINK',
|
||||
NODE_TYPE_META: 'META',
|
||||
|
||||
S_IFREG: 0x8000,
|
||||
S_IFDIR: 0x4000,
|
||||
S_IFLNK: 0xA000,
|
||||
|
||||
DEFAULT_DIR_PERMISSIONS: 0x1ED, // 755
|
||||
DEFAULT_FILE_PERMISSIONS: 0x1A4, // 644
|
||||
|
||||
SYMLOOP_MAX: 10,
|
||||
|
||||
BINARY_MIME_TYPE: 'application/octet-stream',
|
||||
|
|
|
@ -900,6 +900,7 @@ function link_node(context, oldpath, newpath, callback) {
|
|||
var oldDirectoryData;
|
||||
var newDirectoryNode;
|
||||
var newDirectoryData;
|
||||
var fileNodeID;
|
||||
var fileNode;
|
||||
|
||||
function update_time(error) {
|
||||
|
@ -914,18 +915,17 @@ function link_node(context, oldpath, newpath, callback) {
|
|||
if(error) {
|
||||
callback(error);
|
||||
} else {
|
||||
fileNode = Node.fromObject(result);
|
||||
fileNode = result;
|
||||
fileNode.nlinks += 1;
|
||||
fileNode.updatePathInfo(newpath);
|
||||
context.putObject(fileNode.id, fileNode, update_time);
|
||||
}
|
||||
}
|
||||
|
||||
function read_directory_entry(error, result) {
|
||||
function read_file_node(error, result) {
|
||||
if(error) {
|
||||
callback(error);
|
||||
} else {
|
||||
context.getObject(newDirectoryData[newname].id, update_file_node);
|
||||
context.getObject(fileNodeID, update_file_node);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -938,7 +938,8 @@ function link_node(context, oldpath, newpath, callback) {
|
|||
callback(new Errors.EEXIST('newpath resolves to an existing file', newname));
|
||||
} else {
|
||||
newDirectoryData[newname] = oldDirectoryData[oldname];
|
||||
context.putObject(newDirectoryNode.data, newDirectoryData, read_directory_entry);
|
||||
fileNodeID = newDirectoryData[newname].id;
|
||||
context.putObject(newDirectoryNode.data, newDirectoryData, read_file_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1648,7 +1649,7 @@ function stat(fs, context, path, callback) {
|
|||
if(error) {
|
||||
callback(error);
|
||||
} else {
|
||||
var stats = new Stats(result, fs.name);
|
||||
var stats = new Stats(path, result, fs.name);
|
||||
callback(null, stats);
|
||||
}
|
||||
}
|
||||
|
@ -1661,7 +1662,7 @@ function fstat(fs, context, fd, callback) {
|
|||
if(error) {
|
||||
callback(error);
|
||||
} else {
|
||||
var stats = new Stats(result, fs.name);
|
||||
var stats = new Stats(fd.path, result, fs.name);
|
||||
callback(null, stats);
|
||||
}
|
||||
}
|
||||
|
@ -1734,7 +1735,7 @@ function readFile(fs, context, path, options, callback) {
|
|||
return callback(err);
|
||||
}
|
||||
|
||||
var stats = new Stats(fstatResult, fs.name);
|
||||
var stats = new Stats(ofd.path, fstatResult, fs.name);
|
||||
|
||||
if(stats.isDirectory()) {
|
||||
cleanup();
|
||||
|
@ -2009,31 +2010,20 @@ function rename(fs, context, oldpath, newpath, callback) {
|
|||
var ctime = Date.now();
|
||||
var fileNode;
|
||||
|
||||
function update_times(error) {
|
||||
function update_times(error, result) {
|
||||
if(error) {
|
||||
callback(error);
|
||||
} else {
|
||||
fileNode = result;
|
||||
update_node_times(context, newpath, fileNode, { ctime: ctime }, callback);
|
||||
}
|
||||
}
|
||||
|
||||
function update_file_node(error, result) {
|
||||
if(error) {
|
||||
callback(error);
|
||||
} else {
|
||||
fileNode = Node.fromObject(result);
|
||||
// Don't think I need this here...
|
||||
// fileNode.nlinks += 1;
|
||||
fileNode.updatePathInfo(newpath);
|
||||
context.putObject(fileNode.id, fileNode, update_times);
|
||||
}
|
||||
}
|
||||
|
||||
function read_new_directory(error) {
|
||||
if(error) {
|
||||
callback(error);
|
||||
} else {
|
||||
context.getObject(newParentData[newName].id, update_file_node);
|
||||
context.getObject(newParentData[newName].id, update_times);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2139,7 +2129,7 @@ function lstat(fs, context, path, callback) {
|
|||
if(error) {
|
||||
callback(error);
|
||||
} else {
|
||||
var stats = new Stats(result, fs.name);
|
||||
var stats = new Stats(path, result, fs.name);
|
||||
callback(null, stats);
|
||||
}
|
||||
}
|
||||
|
|
50
src/node.js
50
src/node.js
|
@ -8,9 +8,25 @@ var NODE_TYPE_META = require('./constants.js').NODE_TYPE_META;
|
|||
|
||||
var ROOT_DIRECTORY_NAME = require('./constants.js').ROOT_DIRECTORY_NAME;
|
||||
|
||||
// Name of file/dir. Must be '/' if the file is the root directory of the server
|
||||
function pathToName(pathName) {
|
||||
return pathName === ROOT_DIRECTORY_NAME ? ROOT_DIRECTORY_NAME : path.basename(pathName);
|
||||
var S_IFREG = require('./constants.js').S_IFREG;
|
||||
var S_IFDIR = require('./constants.js').S_IFDIR;
|
||||
var S_IFLNK = require('./constants.js').S_IFLNK;
|
||||
|
||||
var DEFAULT_FILE_PERMISSIONS = require('./constants.js').DEFAULT_FILE_PERMISSIONS;
|
||||
var DEFAULT_DIR_PERMISSIONS = require('./constants.js').DEFAULT_DIR_PERMISSIONS;
|
||||
|
||||
function getMode(type) {
|
||||
switch(type) {
|
||||
case NODE_TYPE_DIRECTORY:
|
||||
return DEFAULT_DIR_PERMISSIONS | S_IFDIR;
|
||||
case NODE_TYPE_SYMBOLIC_LINK:
|
||||
return DEFAULT_FILE_PERMISSIONS | S_IFLNK;
|
||||
/* jshint -W086 */
|
||||
case NODE_TYPE_FILE:
|
||||
// falls through
|
||||
default:
|
||||
return DEFAULT_FILE_PERMISSIONS | S_IFREG;
|
||||
}
|
||||
}
|
||||
|
||||
function Node(options) {
|
||||
|
@ -18,7 +34,6 @@ function Node(options) {
|
|||
|
||||
this.id = options.id;
|
||||
this.type = options.type || NODE_TYPE_FILE; // node type (file, directory, etc)
|
||||
this.name = options.name || (pathToName(options.path));
|
||||
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.ctime = options.ctime || now; // creation/change time
|
||||
|
@ -30,16 +45,11 @@ function Node(options) {
|
|||
this.version = options.version || 1;
|
||||
|
||||
// permissions and flags
|
||||
this.mode = options.mode || (this.type === NODE_TYPE_DIRECTORY ? /* 755 */ 493 : /* 644 */ 420);
|
||||
this.mode = options.mode || (getMode(this.type));
|
||||
this.uid = options.uid || 0x0; // owner name
|
||||
this.gid = options.gid || 0x0; // group name
|
||||
}
|
||||
|
||||
// When the node's path changes, update info that relates to it.
|
||||
Node.prototype.updatePathInfo = function(newPath) {
|
||||
this.name = pathToName(newPath);
|
||||
};
|
||||
|
||||
// Make sure the options object has an id on property,
|
||||
// either from caller or one we generate using supplied guid fn.
|
||||
function ensureID(options, prop, callback) {
|
||||
|
@ -72,24 +82,4 @@ Node.create = function(options, callback) {
|
|||
});
|
||||
};
|
||||
|
||||
Node.fromObject = function(object) {
|
||||
return new Node({
|
||||
id: object.id,
|
||||
type: object.type,
|
||||
name: object.name,
|
||||
size: object.size,
|
||||
atime: object.atime,
|
||||
ctime: object.ctime,
|
||||
mtime: object.mtime,
|
||||
flags: object.flags,
|
||||
xattrs: object.xattrs,
|
||||
nlinks: object.nlinks,
|
||||
data: object.data,
|
||||
mode: object.mode,
|
||||
uid: object.uid,
|
||||
gid: object.gid,
|
||||
version: object.version
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = Node;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
var Constants = require('./constants.js');
|
||||
var Path = require('./path.js');
|
||||
|
||||
function Stats(fileNode, devName) {
|
||||
function Stats(path, fileNode, devName) {
|
||||
this.dev = devName;
|
||||
this.node = fileNode.id;
|
||||
this.type = fileNode.type;
|
||||
|
@ -14,6 +15,7 @@ function Stats(fileNode, devName) {
|
|||
this.mode = fileNode.mode;
|
||||
this.uid = fileNode.uid;
|
||||
this.gid = fileNode.gid;
|
||||
this.name = Path.basename(path);
|
||||
}
|
||||
|
||||
Stats.prototype.isFile = function() {
|
||||
|
|
|
@ -42,6 +42,30 @@ describe('fs.link', function() {
|
|||
});
|
||||
});
|
||||
|
||||
it('should create hard link to identical data node', function(done) {
|
||||
var fs = util.fs();
|
||||
var contents = "Hello World!";
|
||||
|
||||
fs.writeFile('/file', contents, function(err) {
|
||||
if(err) throw err;
|
||||
|
||||
fs.link('/file', '/hlink', function(err) {
|
||||
if(err) throw err;
|
||||
|
||||
fs.readFile('/file', 'utf8', function(err, fileData) {
|
||||
if(err) throw err;
|
||||
|
||||
fs.readFile('/hlink', 'utf8', function(err, hlinkData) {
|
||||
if(err) throw err;
|
||||
|
||||
expect(fileData).to.equal(hlinkData);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should not follow symbolic links', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
|
|
Loading…
Reference in New Issue