Update sh.ls and stats to remove bits I don't need, add what I do.

This commit is contained in:
David Humphrey 2018-05-24 15:41:54 -04:00
parent ee412d4abe
commit 0aaaeacd1a
8 changed files with 50 additions and 160 deletions

View File

@ -397,14 +397,19 @@ Callback gets `(error, stats)`, where `stats` is an object with the following pr
```
{
node: <string> // internal node id (unique)
dev: <string> // file system name
size: <number> // file size in bytes
nlinks: <number> // number of links
atime: <number> // last access time
mtime: <number> // last modified time
ctime: <number> // creation time
type: <string> // file type (FILE, DIRECTORY, SYMLINK)
node: <string> // internal node id (unique)
dev: <string> // file system name
name: <string> // the entry's name (basename)
size: <number> // file size in bytes
nlinks: <number> // number of links
atime: <number> // last access time
mtime: <number> // last modified time
ctime: <number> // creation time
type: <string> // file type (FILE, DIRECTORY, SYMLINK),
gid: <number> // group name
uid: <number> // owner name
mode: <number> // permissions
version: <number> // version of the node
}
```
@ -1263,17 +1268,8 @@ sh.find('/app/user', {
#### sh.ls(dir, [options], callback)<a name="ls"></a>
Get the listing of a directory, returning an array of directory entries
in the following form:
```
{
path: <String> the basename of the directory entry
links: <Number> the number of links to the entry
size: <Number> the size in bytes of the entry
modified: <Number> the last modified date/time
type: <String> the type of the entry
contents: <Array> an optional array of child entries, if this entry is itself a directory
}
```
in the same form as [fs.stat()](#stat), with the exception that a new Array named
`contents` is added for directory entries, containing child entries.
By default `sh.ls()` gives a shallow listing. If you want to follow
directories as they are encountered, use the `recursive=true` option. NOTE:

View File

@ -76,43 +76,5 @@ module.exports = {
ENVIRONMENT: {
TMP: '/tmp',
PATH: ''
},
/**
* Plan 9 related
* - https://github.com/chaos/diod/blob/master/libnpfs/9p.h
* - https://en.wikibooks.org/wiki/C_Programming/POSIX_Reference/sys/stat.h
*/
P9: {
/**
* QID types
*
* @P9_QTDIR: directory
* @P9_QTAPPEND: append-only
* @P9_QTEXCL: excluse use (only one open handle allowed)
* @P9_QTMOUNT: mount points
* @P9_QTAUTH: authentication file
* @P9_QTTMP: non-backed-up files
* @P9_QTSYMLINK: symbolic links (9P2000.u)
* @P9_QTLINK: hard-link (9P2000.u)
* @P9_QTFILE: normal files
*/
QTDIR: 0x80,
QTAPPEND: 0x40,
QTEXCL: 0x20,
QTMOUNT: 0x10,
QTAUTH: 0x08,
QTTMP: 0x04,
QTSYMLINK: 0x02,
QTLINK: 0x01,
QTFILE: 0x00,
/**
* POSIX System Values
*/
S_IFMT: 0xF000, // mask for file type
S_IFLNK: 0xA000, // symbolic link
S_IFDIR: 0x4000, // directory
S_IFREG: 0x8000 // regular file
}
};

View File

@ -7,23 +7,7 @@ function encode(string) {
return new Buffer(string, 'utf8');
}
// https://github.com/darkskyapp/string-hash
function hash32(string) {
var hash = 5381;
var i = string.length;
while(i) {
hash = (hash * 33) ^ string.charCodeAt(--i);
}
/* JavaScript does bitwise operations (like XOR, above) on 32-bit signed
* integers. Since we want the results to be always positive, convert the
* signed int to an unsigned by doing an unsigned bitshift. */
return hash >>> 0;
}
module.exports = {
encode: encode,
decode: decode,
hash32: hash32
decode: decode
};

View File

@ -12,9 +12,6 @@ var NODE_TYPE_FILE = Constants.NODE_TYPE_FILE;
var NODE_TYPE_DIRECTORY = Constants.NODE_TYPE_DIRECTORY;
var NODE_TYPE_SYMBOLIC_LINK = Constants.NODE_TYPE_SYMBOLIC_LINK;
var NODE_TYPE_META = Constants.NODE_TYPE_META;
var P9_QTDIR = Constants.P9.QTDIR;
var P9_QTFILE = Constants.P9.QTFILE;
var P9_QTSYMLINK = Constants.P9.QTSYMLINK;
var ROOT_DIRECTORY_NAME = Constants.ROOT_DIRECTORY_NAME;
var SUPER_NODE_ID = Constants.SUPER_NODE_ID;
@ -729,7 +726,7 @@ function replace_data(context, ofd, buffer, offset, length, callback) {
ofd.position = length;
fileNode.size = length;
fileNode.qid_version += 1;
fileNode.version += 1;
context.putBuffer(fileNode.data, newData, update_file_node);
}
@ -788,7 +785,7 @@ function write_data(context, ofd, buffer, offset, length, position, callback) {
}
fileNode.size = newSize;
fileNode.qid_version += 1;
fileNode.version += 1;
context.putBuffer(fileNode.data, newData, update_file_node);
}
@ -1258,7 +1255,7 @@ function truncate_file(context, path, length, callback) {
callback(error);
} else {
fileNode.size = length;
fileNode.qid_version += 1;
fileNode.version += 1;
context.putObject(fileNode.id, fileNode, update_time);
}
}
@ -1316,7 +1313,7 @@ function ftruncate_file(context, ofd, length, callback) {
callback(error);
} else {
fileNode.size = length;
fileNode.qid_version += 1;
fileNode.version += 1;
context.putObject(fileNode.id, fileNode, update_time);
}
}

View File

@ -6,29 +6,8 @@ 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_META = require('./constants.js').NODE_TYPE_META;
var P9_QTFILE = require('./constants.js').P9.QTFILE;
var P9_QTDIR = require('./constants.js').P9.QTDIR;
var P9_QTSYMLINK = require('./constants.js').P9.QTSYMLINK;
var S_IFLNK = require('./constants.js').P9.S_IFLNK;
var S_IFDIR = require('./constants.js').P9.S_IFDIR;
var S_IFREG = require('./constants.js').P9.S_IFREG;
var ROOT_DIRECTORY_NAME = require('./constants.js').ROOT_DIRECTORY_NAME;
function getQType(type) {
switch(type) {
case NODE_TYPE_FILE:
return P9_QTFILE;
case NODE_TYPE_DIRECTORY:
return P9_QTDIR;
case NODE_TYPE_SYMBOLIC_LINK:
return P9_QTSYMLINK;
default:
return P9_QTFILE;
}
}
// 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);
@ -48,26 +27,7 @@ function Node(options) {
this.xattrs = options.xattrs || {}; // extended attributes
this.nlinks = options.nlinks || 0; // links count
this.data = options.data; // id for data object
/**
* Plan 9 related metadata:
* https://web.archive.org/web/20170601072902/http://plan9.bell-labs.com/magic/man2html/5/0intro
*
* "The qid represents the server's unique identification for the file being
* accessed: two files on the same server hierarchy are the same if and only
* if their qids are the same. (The client may have multiple fids pointing to
* a single file on a server and hence having a single qid.) The thirteenbyte
* qid fields hold a onebyte type, specifying whether the file is a directory,
* appendonly file, etc., and two unsigned integers: first the fourbyte qid
* version, then the eightbyte qid path. The path is an integer unique among
* all files in the hierarchy. If a file is deleted and recreated with the same
* name in the same directory, the old and new path components of the qids
* should be different. The version is a version number for a file; typically,
* it is incremented every time the file is modified."
*/
this.qid_type = options.qid_type || (getQType(this.type));
this.qid_version = options.qid_version || 1;
this.qid_path = options.qid_path || hash32(options.path + this.qid_version);
this.version = options.version || 1;
// permissions and flags
this.mode = options.mode || (this.type === NODE_TYPE_DIRECTORY ? /* 755 */ 493 : /* 644 */ 420);
@ -77,8 +37,6 @@ function Node(options) {
// When the node's path changes, update info that relates to it.
Node.prototype.updatePathInfo = function(newPath) {
// XXX: need to confirm that qid's path actually changes on rename.
this.qid_path = hash32(newPath + this.qid_version);
this.name = pathToName(newPath);
};
@ -130,9 +88,7 @@ Node.fromObject = function(object) {
mode: object.mode,
uid: object.uid,
gid: object.gid,
qid_type: object.qid_type,
qid_version: object.qid_version,
qid_path: object.qid_path
version: object.version
});
};

View File

@ -233,18 +233,10 @@ Shell.prototype.ls = function(dir, options, callback) {
callback(error);
return;
}
var entry = {
path: Path.basename(name),
links: stats.nlinks,
size: stats.size,
modified: stats.mtime,
type: stats.type,
// Also expose the Plan 9 bits
p9: stats.p9
};
var entry = stats;
if(options.recursive && stats.type === 'DIRECTORY') {
list(Path.join(pathname, entry.path), function(error, items) {
list(Path.join(pathname, entry.name), function(error, items) {
if(error) {
callback(error);
return;

View File

@ -1,16 +1,19 @@
var Constants = require('./constants.js');
function Stats(fileNode, devName) {
this.node = fileNode.id;
this.dev = devName;
this.node = fileNode.id;
this.type = fileNode.type;
this.name = fileNode.name;
this.size = fileNode.size;
this.nlinks = fileNode.nlinks;
this.atime = fileNode.atime;
this.mtime = fileNode.mtime;
this.ctime = fileNode.ctime;
this.type = fileNode.type;
// Expose extra Plan 9 bits too
this.p9 = fileNode.p9;
this.version = fileNode.version;
this.mode = fileNode.mode;
this.uid = fileNode.uid;
this.gid = fileNode.gid;
}
Stats.prototype.isFile = function() {

View File

@ -40,18 +40,18 @@ describe('FileSystemShell.ls', function() {
expect(list.length).to.equal(2);
var item0 = list[0];
expect(item0.path).to.equal('file');
expect(item0.links).to.equal(1);
expect(item0.name).to.equal('file');
expect(item0.nlinks).to.equal(1);
expect(item0.size).to.equal(1);
expect(item0.modified).to.be.a('number');
expect(item0.mtime).to.be.a('number');
expect(item0.type).to.equal('FILE');
expect(item0.contents).not.to.exist;
var item1 = list[1];
expect(item1.path).to.equal('file2');
expect(item1.links).to.equal(1);
expect(item1.name).to.equal('file2');
expect(item1.nlinks).to.equal(1);
expect(item1.size).to.equal(2);
expect(item1.modified).to.be.a('number');
expect(item1.mtime).to.be.a('number');
expect(item1.type).to.equal('FILE');
expect(item0.contents).not.to.exist;
@ -84,19 +84,19 @@ describe('FileSystemShell.ls', function() {
// We shouldn't rely on the order we'll get the listing
list.forEach(function(item, i, arr) {
switch(item.path) {
switch(item.name) {
case 'dir2':
expect(item.links).to.equal(1);
expect(item.nlinks).to.equal(1);
expect(item.size).to.be.a('number');
expect(item.modified).to.be.a('number');
expect(item.mtime).to.be.a('number');
expect(item.type).to.equal('DIRECTORY');
expect(item.contents).not.to.exist;
break;
case 'file':
case 'file2':
expect(item.links).to.equal(1);
expect(item.nlinks).to.equal(1);
expect(item.size).to.equal(1);
expect(item.modified).to.be.a('number');
expect(item.mtime).to.be.a('number');
expect(item.type).to.equal('FILE');
expect(item.contents).not.to.exist;
break;
@ -143,27 +143,27 @@ describe('FileSystemShell.ls', function() {
// We shouldn't rely on the order we'll get the listing
list.forEach(function(item, i, arr) {
switch(item.path) {
switch(item.name) {
case 'dir2':
expect(item.links).to.equal(1);
expect(item.nlinks).to.equal(1);
expect(item.size).to.be.a('number');
expect(item.modified).to.be.a('number');
expect(item.mtime).to.be.a('number');
expect(item.type).to.equal('DIRECTORY');
expect(item.contents).to.exist;
expect(item.contents.length).to.equal(1);
var contents0 = item.contents[0];
expect(contents0.path).to.equal('file');
expect(contents0.links).to.equal(1);
expect(contents0.name).to.equal('file');
expect(contents0.nlinks).to.equal(1);
expect(contents0.size).to.equal(1);
expect(contents0.modified).to.be.a('number');
expect(contents0.mtime).to.be.a('number');
expect(contents0.type).to.equal('FILE');
expect(contents0.contents).not.to.exist;
break;
case 'file':
case 'file2':
expect(item.links).to.equal(1);
expect(item.nlinks).to.equal(1);
expect(item.size).to.equal(1);
expect(item.modified).to.be.a('number');
expect(item.mtime).to.be.a('number');
expect(item.type).to.equal('FILE');
expect(item.contents).not.to.exist;
break;