diff --git a/src/errors.js b/src/errors.js index fbb5e96..9e151d3 100644 --- a/src/errors.js +++ b/src/errors.js @@ -1,69 +1,69 @@ var errors = {}; [ /** - * node.js errors + * node.js errors - we only use some of these, add as needed. */ - '-1:UNKNOWN:unknown error', - '0:OK:success', - '1:EOF:end of file', - '2:EADDRINFO:getaddrinfo error', - '3:EACCES:permission denied', - '4:EAGAIN:resource temporarily unavailable', - '5:EADDRINUSE:address already in use', - '6:EADDRNOTAVAIL:address not available', - '7:EAFNOSUPPORT:address family not supported', - '8:EALREADY:connection already in progress', + //'-1:UNKNOWN:unknown error', + //'0:OK:success', + //'1:EOF:end of file', + //'2:EADDRINFO:getaddrinfo error', + //'3:EACCES:permission denied', + //'4:EAGAIN:resource temporarily unavailable', + //'5:EADDRINUSE:address already in use', + //'6:EADDRNOTAVAIL:address not available', + //'7:EAFNOSUPPORT:address family not supported', + //'8:EALREADY:connection already in progress', '9:EBADF:bad file descriptor', '10:EBUSY:resource busy or locked', - '11:ECONNABORTED:software caused connection abort', - '12:ECONNREFUSED:connection refused', - '13:ECONNRESET:connection reset by peer', - '14:EDESTADDRREQ:destination address required', - '15:EFAULT:bad address in system call argument', - '16:EHOSTUNREACH:host is unreachable', - '17:EINTR:interrupted system call', + //'11:ECONNABORTED:software caused connection abort', + //'12:ECONNREFUSED:connection refused', + //'13:ECONNRESET:connection reset by peer', + //'14:EDESTADDRREQ:destination address required', + //'15:EFAULT:bad address in system call argument', + //'16:EHOSTUNREACH:host is unreachable', + //'17:EINTR:interrupted system call', '18:EINVAL:invalid argument', - '19:EISCONN:socket is already connected', - '20:EMFILE:too many open files', - '21:EMSGSIZE:message too long', - '22:ENETDOWN:network is down', - '23:ENETUNREACH:network is unreachable', - '24:ENFILE:file table overflow', - '25:ENOBUFS:no buffer space available', - '26:ENOMEM:not enough memory', + //'19:EISCONN:socket is already connected', + //'20:EMFILE:too many open files', + //'21:EMSGSIZE:message too long', + //'22:ENETDOWN:network is down', + //'23:ENETUNREACH:network is unreachable', + //'24:ENFILE:file table overflow', + //'25:ENOBUFS:no buffer space available', + //'26:ENOMEM:not enough memory', '27:ENOTDIR:not a directory', '28:EISDIR:illegal operation on a directory', - '29:ENONET:machine is not on the network', + //'29:ENONET:machine is not on the network', // errno 30 skipped, as per https://github.com/rvagg/node-errno/blob/master/errno.js - '31:ENOTCONN:socket is not connected', - '32:ENOTSOCK:socket operation on non-socket', - '33:ENOTSUP:operation not supported on socket', + //'31:ENOTCONN:socket is not connected', + //'32:ENOTSOCK:socket operation on non-socket', + //'33:ENOTSUP:operation not supported on socket', '34:ENOENT:no such file or directory', - '35:ENOSYS:function not implemented', - '36:EPIPE:broken pipe', - '37:EPROTO:protocol error', - '38:EPROTONOSUPPORT:protocol not supported', - '39:EPROTOTYPE:protocol wrong type for socket', - '40:ETIMEDOUT:connection timed out', - '41:ECHARSET:invalid Unicode character', - '42:EAIFAMNOSUPPORT:address family for hostname not supported', + //'35:ENOSYS:function not implemented', + //'36:EPIPE:broken pipe', + //'37:EPROTO:protocol error', + //'38:EPROTONOSUPPORT:protocol not supported', + //'39:EPROTOTYPE:protocol wrong type for socket', + //'40:ETIMEDOUT:connection timed out', + //'41:ECHARSET:invalid Unicode character', + //'42:EAIFAMNOSUPPORT:address family for hostname not supported', // errno 43 skipped, as per https://github.com/rvagg/node-errno/blob/master/errno.js - '44:EAISERVICE:servname not supported for ai_socktype', - '45:EAISOCKTYPE:ai_socktype not supported', - '46:ESHUTDOWN:cannot send after transport endpoint shutdown', + //'44:EAISERVICE:servname not supported for ai_socktype', + //'45:EAISOCKTYPE:ai_socktype not supported', + //'46:ESHUTDOWN:cannot send after transport endpoint shutdown', '47:EEXIST:file already exists', - '48:ESRCH:no such process', - '49:ENAMETOOLONG:name too long', - '50:EPERM:operation not permitted', + //'48:ESRCH:no such process', + //'49:ENAMETOOLONG:name too long', + //'50:EPERM:operation not permitted', '51:ELOOP:too many symbolic links encountered', - '52:EXDEV:cross-device link not permitted', + //'52:EXDEV:cross-device link not permitted', '53:ENOTEMPTY:directory not empty', - '54:ENOSPC:no space left on device', + //'54:ENOSPC:no space left on device', '55:EIO:i/o error', - '56:EROFS:read-only file system', - '57:ENODEV:no such device', - '58:ESPIPE:invalid seek', - '59:ECANCELED:operation canceled', + //'56:EROFS:read-only file system', + //'57:ENODEV:no such device', + //'58:ESPIPE:invalid seek', + //'59:ECANCELED:operation canceled', /** * Filer specific errors @@ -71,23 +71,34 @@ var errors = {}; '1000:ENOTMOUNTED:not mounted', '1001:EFILESYSTEMERROR:missing super node, use \'FORMAT\' flag to format filesystem.', '1002:ENOATTR:attribute does not exist' + ].forEach(function(e) { e = e.split(':'); - var errno = e[0], - err = e[1], - message = e[2]; + var errno = +e[0]; + var errName = e[1]; + var defaultMessage = e[2]; - function FilerError(m) { - this.name = err; - this.code = err; + function FilerError(msg, path) { + Error.call(this); + + this.name = errName; + this.code = errName; this.errno = errno; - this.message = m || message; + this.message = msg || defaultMessage; + if(path) { + this.path = path; + } + this.stack = (new Error(this.message)).stack; } FilerError.prototype = Object.create(Error.prototype); FilerError.prototype.constructor = FilerError; + FilerError.prototype.toString = function() { + var pathInfo = this.path ? (', \'' + this.path + '\'') : ''; + return this.name + ': ' + this.message + pathInfo; + }; // We expose the error as both Errors.EINVAL and Errors[18] - errors[err] = errors[errno] = FilerError; + errors[errName] = errors[errno] = FilerError; }); module.exports = errors; diff --git a/src/filesystem/implementation.js b/src/filesystem/implementation.js index 7b406ce..b8dd308 100644 --- a/src/filesystem/implementation.js +++ b/src/filesystem/implementation.js @@ -111,7 +111,7 @@ function update_node_times(context, path, node, times, callback) { // out: new node representing file/directory function make_node(context, path, mode, callback) { if(mode !== MODE_DIRECTORY && mode !== MODE_FILE) { - return callback(new Errors.EINVAL('mode must be a directory or file')); + return callback(new Errors.EINVAL('mode must be a directory or file', path)); } path = normalize(path); @@ -127,7 +127,7 @@ function make_node(context, path, mode, callback) { if(error) { callback(error); } else if(parentDirectoryNode.mode !== MODE_DIRECTORY) { - callback(new Errors.ENOTDIR('a component of the path prefix is not a directory')); + callback(new Errors.ENOTDIR('a component of the path prefix is not a directory', path)); } else { parentNode = parentDirectoryNode; find_node(context, path, check_if_node_exists); @@ -137,7 +137,7 @@ function make_node(context, path, mode, callback) { // Check if the node to be created already exists function check_if_node_exists(error, result) { if(!error && result) { - callback(new Errors.EEXIST('path name already exists')); + callback(new Errors.EEXIST('path name already exists', path)); } else if(error && !(error instanceof Errors.ENOENT)) { callback(error); } else { @@ -227,7 +227,7 @@ function find_node(context, path, callback) { if(error) { callback(error); } else if(parentDirectoryNode.mode !== MODE_DIRECTORY || !parentDirectoryNode.data) { - callback(new Errors.ENOTDIR('a component of the path prefix is not a directory')); + callback(new Errors.ENOTDIR('a component of the path prefix is not a directory', path)); } else { context.getObject(parentDirectoryNode.data, get_node_from_parent_directory_data); } @@ -240,7 +240,7 @@ function find_node(context, path, callback) { callback(error); } else { if(!_(parentDirectoryData).has(name)) { - callback(new Errors.ENOENT()); + callback(new Errors.ENOENT(null, path)); } else { var nodeId = parentDirectoryData[name].id; context.getObject(nodeId, is_symbolic_link); @@ -255,7 +255,7 @@ function find_node(context, path, callback) { if(node.mode == MODE_SYMBOLIC_LINK) { followedCount++; if(followedCount > SYMLOOP_MAX){ - callback(new Errors.ELOOP()); + callback(new Errors.ELOOP(null, path)); } else { follow_symbolic_link(node.data); } @@ -305,10 +305,10 @@ function set_extended_attribute (context, path_or_fd, name, value, flag, callbac callback(error); } else if (flag === XATTR_CREATE && node.xattrs.hasOwnProperty(name)) { - callback(new Errors.EEXIST('attribute already exists')); + callback(new Errors.EEXIST('attribute already exists', path_or_fd)); } else if (flag === XATTR_REPLACE && !node.xattrs.hasOwnProperty(name)) { - callback(new Errors.ENOATTR()); + callback(new Errors.ENOATTR(null, path_or_fd)); } else { node.xattrs[name] = value; @@ -325,7 +325,7 @@ function set_extended_attribute (context, path_or_fd, name, value, flag, callbac context.getObject(path_or_fd.id, set_xattr); } else { - callback(new Errors.EINVAL('path or file descriptor of wrong type')); + callback(new Errors.EINVAL('path or file descriptor of wrong type', path_or_fd)); } } @@ -402,7 +402,7 @@ function make_directory(context, path, callback) { function check_if_directory_exists(error, result) { if(!error && result) { - callback(new Errors.EEXIST()); + callback(new Errors.EEXIST(null, path)); } else if(error && !(error instanceof Errors.ENOENT)) { callback(error); } else { @@ -492,9 +492,9 @@ function remove_directory(context, path, callback) { if(error) { callback(error); } else if(ROOT_DIRECTORY_NAME == name) { - callback(new Errors.EBUSY()); + callback(new Errors.EBUSY(null, path)); } else if(!_(result).has(name)) { - callback(new Errors.ENOENT()); + callback(new Errors.ENOENT(null, path)); } else { parentDirectoryData = result; directoryNode = parentDirectoryData[name].id; @@ -506,7 +506,7 @@ function remove_directory(context, path, callback) { if(error) { callback(error); } else if(result.mode != MODE_DIRECTORY) { - callback(new Errors.ENOTDIR()); + callback(new Errors.ENOTDIR(null, path)); } else { directoryNode = result; context.getObject(directoryNode.data, check_if_directory_is_empty); @@ -519,7 +519,7 @@ function remove_directory(context, path, callback) { } else { directoryData = result; if(_(directoryData).size() > 0) { - callback(new Errors.ENOTEMPTY()); + callback(new Errors.ENOTEMPTY(null, path)); } else { remove_directory_entry_from_parent_directory_node(); } @@ -574,7 +574,7 @@ function open_file(context, path, flags, callback) { if(ROOT_DIRECTORY_NAME == name) { if(_(flags).contains(O_WRITE)) { - callback(new Errors.EISDIR('the named file is a directory and O_WRITE is set')); + callback(new Errors.EISDIR('the named file is a directory and O_WRITE is set', path)); } else { find_node(context, path, set_file_node); } @@ -586,7 +586,7 @@ function open_file(context, path, flags, callback) { if(error) { callback(error); } else if(result.mode !== MODE_DIRECTORY) { - callback(new Errors.ENOENT()); + callback(new Errors.ENOENT(null, path)); } else { directoryNode = result; context.getObject(directoryNode.data, check_if_file_exists); @@ -600,18 +600,18 @@ function open_file(context, path, flags, callback) { directoryData = result; if(_(directoryData).has(name)) { if(_(flags).contains(O_EXCLUSIVE)) { - callback(new Errors.ENOENT('O_CREATE and O_EXCLUSIVE are set, and the named file exists')); + callback(new Errors.ENOENT('O_CREATE and O_EXCLUSIVE are set, and the named file exists', path)); } else { directoryEntry = directoryData[name]; if(directoryEntry.type == MODE_DIRECTORY && _(flags).contains(O_WRITE)) { - callback(new Errors.EISDIR('the named file is a directory and O_WRITE is set')); + callback(new Errors.EISDIR('the named file is a directory and O_WRITE is set', path)); } else { context.getObject(directoryEntry.id, check_if_symbolic_link); } } } else { if(!_(flags).contains(O_CREATE)) { - callback(new Errors.ENOENT('O_CREATE is not set and the named file does not exist')); + callback(new Errors.ENOENT('O_CREATE is not set and the named file does not exist', path)); } else { write_file_node(); } @@ -627,7 +627,7 @@ function open_file(context, path, flags, callback) { if(node.mode == MODE_SYMBOLIC_LINK) { followedCount++; if(followedCount > SYMLOOP_MAX){ - callback(new Errors.ELOOP()); + callback(new Errors.ELOOP(null, path)); } else { follow_symbolic_link(node.data); } @@ -643,7 +643,7 @@ function open_file(context, path, flags, callback) { name = basename(data); if(ROOT_DIRECTORY_NAME == name) { if(_(flags).contains(O_WRITE)) { - callback(new Errors.EISDIR('the named file is a directory and O_WRITE is set')); + callback(new Errors.EISDIR('the named file is a directory and O_WRITE is set', path)); } else { find_node(context, path, set_file_node); } @@ -898,7 +898,7 @@ function lstat_file(context, path, callback) { } else { directoryData = result; if(!_(directoryData).has(name)) { - callback(new Errors.ENOENT('a component of the path does not name an existing file')); + callback(new Errors.ENOENT('a component of the path does not name an existing file', path)); } else { context.getObject(directoryData[name].id, standard_check_result_cb(callback)); } @@ -953,7 +953,7 @@ function link_node(context, oldpath, newpath, callback) { } else { newDirectoryData = result; if(_(newDirectoryData).has(newname)) { - callback(new Errors.EEXIST('newpath resolves to an existing file')); + callback(new Errors.EEXIST('newpath resolves to an existing file', newname)); } else { newDirectoryData[newname] = oldDirectoryData[oldname]; context.putObject(newDirectoryNode.data, newDirectoryData, read_directory_entry); @@ -976,7 +976,7 @@ function link_node(context, oldpath, newpath, callback) { } else { oldDirectoryData = result; if(!_(oldDirectoryData).has(oldname)) { - callback(new Errors.ENOENT('a component of either path prefix does not exist')); + callback(new Errors.ENOENT('a component of either path prefix does not exist', oldname)); } else { find_node(context, newParentPath, read_new_directory_data); } @@ -1046,7 +1046,7 @@ function unlink_node(context, path, callback) { } else { directoryData = result; if(!_(directoryData).has(name)) { - callback(new Errors.ENOENT('a component of the path does not name an existing file')); + callback(new Errors.ENOENT('a component of the path does not name an existing file', name)); } else { context.getObject(directoryData[name].id, update_file_node); } @@ -1104,7 +1104,7 @@ function make_symbolic_link(context, srcpath, dstpath, callback) { var fileNode; if(ROOT_DIRECTORY_NAME == name) { - callback(new Errors.EEXIST()); + callback(new Errors.EEXIST(null, name)); } else { find_node(context, parentPath, read_directory_data); } @@ -1124,7 +1124,7 @@ function make_symbolic_link(context, srcpath, dstpath, callback) { } else { directoryData = result; if(_(directoryData).has(name)) { - callback(new Errors.EEXIST()); + callback(new Errors.EEXIST(null, name)); } else { write_file_node(); } @@ -1189,7 +1189,7 @@ function read_link(context, path, callback) { } else { directoryData = result; if(!_(directoryData).has(name)) { - callback(new Errors.ENOENT('a component of the path does not name an existing file')); + callback(new Errors.ENOENT('a component of the path does not name an existing file', name)); } else { context.getObject(directoryData[name].id, check_if_symbolic); } @@ -1201,7 +1201,7 @@ function read_link(context, path, callback) { callback(error); } else { if(result.mode != MODE_SYMBOLIC_LINK) { - callback(new Errors.EINVAL("path not a symbolic link")); + callback(new Errors.EINVAL('path not a symbolic link', path)); } else { callback(null, result.data); } @@ -1218,7 +1218,7 @@ function truncate_file(context, path, length, callback) { if (error) { callback(error); } else if(node.mode == MODE_DIRECTORY ) { - callback(new Errors.EISDIR()); + callback(new Errors.EISDIR(null, path)); } else{ fileNode = node; context.getBuffer(fileNode.data, truncate_file_data); @@ -1337,10 +1337,10 @@ function utimes_file(context, path, atime, mtime, callback) { } if (typeof atime != 'number' || typeof mtime != 'number') { - callback(new Errors.EINVAL('atime and mtime must be number')); + callback(new Errors.EINVAL('atime and mtime must be number', path)); } else if (atime < 0 || mtime < 0) { - callback(new Errors.EINVAL('atime and mtime must be positive integers')); + callback(new Errors.EINVAL('atime and mtime must be positive integers', path)); } else { find_node(context, path, update_times); @@ -1372,14 +1372,14 @@ function setxattr_file(context, path, name, value, flag, callback) { path = normalize(path); if (typeof name != 'string') { - callback(new Errors.EINVAL('attribute name must be a string')); + callback(new Errors.EINVAL('attribute name must be a string', path)); } else if (!name) { - callback(new Errors.EINVAL('attribute name cannot be an empty string')); + callback(new Errors.EINVAL('attribute name cannot be an empty string', path)); } else if (flag !== null && flag !== XATTR_CREATE && flag !== XATTR_REPLACE) { - callback(new Errors.EINVAL('invalid flag, must be null, XATTR_CREATE or XATTR_REPLACE')); + callback(new Errors.EINVAL('invalid flag, must be null, XATTR_CREATE or XATTR_REPLACE', path)); } else { set_extended_attribute(context, path, name, value, flag, callback); @@ -1412,7 +1412,7 @@ function getxattr_file (context, path, name, callback) { callback (error); } else if (!node.xattrs.hasOwnProperty(name)) { - callback(new Errors.ENOATTR()); + callback(new Errors.ENOATTR(null, path)); } else { callback(null, node.xattrs[name]); @@ -1420,10 +1420,10 @@ function getxattr_file (context, path, name, callback) { } if (typeof name != 'string') { - callback(new Errors.EINVAL('attribute name must be a string')); + callback(new Errors.EINVAL('attribute name must be a string', path)); } else if (!name) { - callback(new Errors.EINVAL('attribute name cannot be an empty string')); + callback(new Errors.EINVAL('attribute name cannot be an empty string', path)); } else { find_node(context, path, get_xattr); @@ -1475,7 +1475,7 @@ function removexattr_file (context, path, name, callback) { callback(error); } else if (!xattr.hasOwnProperty(name)) { - callback(new Errors.ENOATTR()); + callback(new Errors.ENOATTR(null, path)); } else { delete node.xattrs[name]; @@ -1484,10 +1484,10 @@ function removexattr_file (context, path, name, callback) { } if (typeof name != 'string') { - callback(new Errors.EINVAL('attribute name must be a string')); + callback(new Errors.EINVAL('attribute name must be a string', path)); } else if (!name) { - callback(new Errors.EINVAL('attribute name cannot be an empty string')); + callback(new Errors.EINVAL('attribute name cannot be an empty string', path)); } else { find_node(context, path, remove_xattr); @@ -1549,9 +1549,9 @@ function validate_file_options(options, enc, fileMode){ function pathCheck(path, callback) { var err; if(isNullPath(path)) { - err = new Error('Path must be a string without null bytes.'); + err = new Errors.EINVAL('Path must be a string without null bytes.', path); } else if(!isAbsolutePath(path)) { - err = new Error('Path must be absolute.'); + err = new Errors.EINAVL('Path must be absolute.', path); } if(err) { @@ -1586,7 +1586,7 @@ function open(fs, context, path, flags, mode, callback) { flags = validate_flags(flags); if(!flags) { - callback(new Errors.EINVAL('flags is not valid')); + callback(new Errors.EINVAL('flags is not valid'), path); } open_file(context, path, flags, check_result); @@ -1691,7 +1691,7 @@ function readFile(fs, context, path, options, callback) { var flags = validate_flags(options.flag || 'r'); if(!flags) { - return callback(new Errors.EINVAL('flags is not valid')); + return callback(new Errors.EINVAL('flags is not valid', path)); } open_file(context, path, flags, function(err, fileNode) { @@ -1715,7 +1715,7 @@ function readFile(fs, context, path, options, callback) { if(stats.isDirectory()) { cleanup(); - return callback(new Errors.EISDIR('illegal operation on directory')); + return callback(new Errors.EISDIR('illegal operation on directory', path)); } var size = stats.size; @@ -1766,7 +1766,7 @@ function writeFile(fs, context, path, data, options, callback) { var flags = validate_flags(options.flag || 'w'); if(!flags) { - callback(new Errors.EINVAL('flags is not valid')); + return callback(new Errors.EINVAL('flags is not valid', path)); } data = data || ''; @@ -1803,7 +1803,7 @@ function appendFile(fs, context, path, data, options, callback) { var flags = validate_flags(options.flag || 'a'); if(!flags) { - callback(new Errors.EINVAL('flags is not valid')); + return callback(new Errors.EINVAL('flags is not valid', path)); } data = data || ''; diff --git a/src/shell/shell.js b/src/shell/shell.js index 7962993..fd9332e 100644 --- a/src/shell/shell.js +++ b/src/shell/shell.js @@ -40,14 +40,14 @@ function Shell(fs, options) { // Make sure the path actually exists, and is a dir fs.stat(path, function(err, stats) { if(err) { - callback(new Errors.ENOTDIR()); + callback(new Errors.ENOTDIR(null, path)); return; } if(stats.type === 'DIRECTORY') { cwd = path; callback(); } else { - callback(new Errors.ENOTDIR()); + callback(new Errors.ENOTDIR(null, path)); } }); }; @@ -158,7 +158,7 @@ Shell.prototype.cat = function(files, callback) { callback = callback || function(){}; if(!files) { - callback(new Errors.EINVAL("Missing files argument")); + callback(new Errors.EINVAL('Missing files argument')); return; } @@ -213,7 +213,7 @@ Shell.prototype.ls = function(dir, options, callback) { callback = callback || function(){}; if(!dir) { - callback(new Errors.EINVAL("Missing dir argument")); + callback(new Errors.EINVAL('Missing dir argument')); return; } @@ -286,7 +286,7 @@ Shell.prototype.rm = function(path, options, callback) { callback = callback || function(){}; if(!path) { - callback(new Errors.EINVAL("Missing path argument")); + callback(new Errors.EINVAL('Missing path argument')); return; } @@ -319,7 +319,7 @@ Shell.prototype.rm = function(path, options, callback) { // If not, see if we're allowed to delete recursively if(!options.recursive) { - callback(new Errors.ENOTEMPTY()); + callback(new Errors.ENOTEMPTY(null, pathname)); return; } @@ -373,7 +373,7 @@ Shell.prototype.mkdirp = function(path, callback) { callback = callback || function(){}; if(!path) { - callback(new Errors.EINVAL("Missing path argument")); + callback(new Errors.EINVAL('Missing path argument')); return; } else if (path === '/') { @@ -388,7 +388,7 @@ Shell.prototype.mkdirp = function(path, callback) { return; } else if (stat.isFile()) { - callback(new Errors.ENOTDIR()); + callback(new Errors.ENOTDIR(null, path)); return; } } @@ -445,7 +445,7 @@ Shell.prototype.wget = function(url, options, callback) { callback = callback || function(){}; if(!url) { - callback(new Errors.EINVAL('missing url argument')); + callback(new Errors.EINVAL('Missing url argument')); return; } @@ -487,7 +487,7 @@ Shell.prototype.unzip = function(zipfile, options, callback) { callback = callback || function(){}; if(!zipfile) { - callback(new Errors.EINVAL('missing zipfile argument')); + callback(new Errors.EINVAL('Missing zipfile argument')); return; } @@ -533,11 +533,11 @@ Shell.prototype.zip = function(zipfile, paths, options, callback) { callback = callback || function(){}; if(!zipfile) { - callback(new Errors.EINVAL('missing zipfile argument')); + callback(new Errors.EINVAL('Missing zipfile argument')); return; } if(!paths) { - callback(new Errors.EINVAL('missing paths argument')); + callback(new Errors.EINVAL('Missing paths argument')); return; } if(typeof paths === 'string') { @@ -591,9 +591,9 @@ Shell.prototype.zip = function(zipfile, paths, options, callback) { var zip = new JSZip(); // Make sure the zipfile doesn't already exist. - fs.stat(zipfile, function(err, stats) { - if(stats) { - return callback(new Errors.EEXIST('zipfile already exists')); + fs.exists(zipfile, function(exists) { + if(exists) { + return callback(new Errors.EEXIST('zipfile already exists', zipfile)); } async.eachSeries(paths, add, function(err) { diff --git a/tests/spec/errors.spec.js b/tests/spec/errors.spec.js index a35a088..4604812 100644 --- a/tests/spec/errors.spec.js +++ b/tests/spec/errors.spec.js @@ -5,132 +5,177 @@ describe("Filer.Errors", function() { it("has expected errors", function() { expect(Filer.Errors).to.exist; - // By ctor - expect(Filer.Errors.UNKNOWN).to.be.a('function'); - expect(Filer.Errors.OK).to.be.a('function'); - expect(Filer.Errors.EOF).to.be.a('function'); - expect(Filer.Errors.EADDRINFO).to.be.a('function'); - expect(Filer.Errors.EACCES).to.be.a('function'); - expect(Filer.Errors.EAGAIN).to.be.a('function'); - expect(Filer.Errors.EADDRINUSE).to.be.a('function'); - expect(Filer.Errors.EADDRNOTAVAIL).to.be.a('function'); - expect(Filer.Errors.EAFNOSUPPORT).to.be.a('function'); - expect(Filer.Errors.EALREADY).to.be.a('function'); + // By ctor -- if you add some to src/errors.js, also add here + //expect(Filer.Errors.UNKNOWN).to.be.a('function'); + //expect(Filer.Errors.OK).to.be.a('function'); + //expect(Filer.Errors.EOF).to.be.a('function'); + //expect(Filer.Errors.EADDRINFO).to.be.a('function'); + //expect(Filer.Errors.EACCES).to.be.a('function'); + //expect(Filer.Errors.EAGAIN).to.be.a('function'); + //expect(Filer.Errors.EADDRINUSE).to.be.a('function'); + //expect(Filer.Errors.EADDRNOTAVAIL).to.be.a('function'); + //expect(Filer.Errors.EAFNOSUPPORT).to.be.a('function'); + //expect(Filer.Errors.EALREADY).to.be.a('function'); expect(Filer.Errors.EBADF).to.be.a('function'); expect(Filer.Errors.EBUSY).to.be.a('function'); - expect(Filer.Errors.ECONNABORTED).to.be.a('function'); - expect(Filer.Errors.ECONNREFUSED).to.be.a('function'); - expect(Filer.Errors.ECONNRESET).to.be.a('function'); - expect(Filer.Errors.EDESTADDRREQ).to.be.a('function'); - expect(Filer.Errors.EFAULT).to.be.a('function'); - expect(Filer.Errors.EHOSTUNREACH).to.be.a('function'); - expect(Filer.Errors.EINTR).to.be.a('function'); + //expect(Filer.Errors.ECONNABORTED).to.be.a('function'); + //expect(Filer.Errors.ECONNREFUSED).to.be.a('function'); + //expect(Filer.Errors.ECONNRESET).to.be.a('function'); + //expect(Filer.Errors.EDESTADDRREQ).to.be.a('function'); + //expect(Filer.Errors.EFAULT).to.be.a('function'); + //expect(Filer.Errors.EHOSTUNREACH).to.be.a('function'); + //expect(Filer.Errors.EINTR).to.be.a('function'); expect(Filer.Errors.EINVAL).to.be.a('function'); - expect(Filer.Errors.EISCONN).to.be.a('function'); - expect(Filer.Errors.EMFILE).to.be.a('function'); - expect(Filer.Errors.EMSGSIZE).to.be.a('function'); - expect(Filer.Errors.ENETDOWN).to.be.a('function'); - expect(Filer.Errors.ENETUNREACH).to.be.a('function'); - expect(Filer.Errors.ENFILE).to.be.a('function'); - expect(Filer.Errors.ENOBUFS).to.be.a('function'); - expect(Filer.Errors.ENOMEM).to.be.a('function'); + //expect(Filer.Errors.EISCONN).to.be.a('function'); + //expect(Filer.Errors.EMFILE).to.be.a('function'); + //expect(Filer.Errors.EMSGSIZE).to.be.a('function'); + //expect(Filer.Errors.ENETDOWN).to.be.a('function'); + //expect(Filer.Errors.ENETUNREACH).to.be.a('function'); + //expect(Filer.Errors.ENFILE).to.be.a('function'); + //expect(Filer.Errors.ENOBUFS).to.be.a('function'); + //expect(Filer.Errors.ENOMEM).to.be.a('function'); expect(Filer.Errors.ENOTDIR).to.be.a('function'); expect(Filer.Errors.EISDIR).to.be.a('function'); - expect(Filer.Errors.ENONET).to.be.a('function'); - expect(Filer.Errors.ENOTCONN).to.be.a('function'); - expect(Filer.Errors.ENOTSOCK).to.be.a('function'); - expect(Filer.Errors.ENOTSUP).to.be.a('function'); + //expect(Filer.Errors.ENONET).to.be.a('function'); + //expect(Filer.Errors.ENOTCONN).to.be.a('function'); + //expect(Filer.Errors.ENOTSOCK).to.be.a('function'); + //expect(Filer.Errors.ENOTSUP).to.be.a('function'); expect(Filer.Errors.ENOENT).to.be.a('function'); - expect(Filer.Errors.ENOSYS).to.be.a('function'); - expect(Filer.Errors.EPIPE).to.be.a('function'); - expect(Filer.Errors.EPROTO).to.be.a('function'); - expect(Filer.Errors.EPROTONOSUPPORT).to.be.a('function'); - expect(Filer.Errors.EPROTOTYPE).to.be.a('function'); - expect(Filer.Errors.ETIMEDOUT).to.be.a('function'); - expect(Filer.Errors.ECHARSET).to.be.a('function'); - expect(Filer.Errors.EAIFAMNOSUPPORT).to.be.a('function'); - expect(Filer.Errors.EAISERVICE).to.be.a('function'); - expect(Filer.Errors.EAISOCKTYPE).to.be.a('function'); - expect(Filer.Errors.ESHUTDOWN).to.be.a('function'); + //expect(Filer.Errors.ENOSYS).to.be.a('function'); + //expect(Filer.Errors.EPIPE).to.be.a('function'); + //expect(Filer.Errors.EPROTO).to.be.a('function'); + //expect(Filer.Errors.EPROTONOSUPPORT).to.be.a('function'); + //expect(Filer.Errors.EPROTOTYPE).to.be.a('function'); + //expect(Filer.Errors.ETIMEDOUT).to.be.a('function'); + //expect(Filer.Errors.ECHARSET).to.be.a('function'); + //expect(Filer.Errors.EAIFAMNOSUPPORT).to.be.a('function'); + //expect(Filer.Errors.EAISERVICE).to.be.a('function'); + //expect(Filer.Errors.EAISOCKTYPE).to.be.a('function'); + //expect(Filer.Errors.ESHUTDOWN).to.be.a('function'); expect(Filer.Errors.EEXIST).to.be.a('function'); - expect(Filer.Errors.ESRCH).to.be.a('function'); - expect(Filer.Errors.ENAMETOOLONG).to.be.a('function'); - expect(Filer.Errors.EPERM).to.be.a('function'); + //expect(Filer.Errors.ESRCH).to.be.a('function'); + //expect(Filer.Errors.ENAMETOOLONG).to.be.a('function'); + //expect(Filer.Errors.EPERM).to.be.a('function'); expect(Filer.Errors.ELOOP).to.be.a('function'); - expect(Filer.Errors.EXDEV).to.be.a('function'); + //expect(Filer.Errors.EXDEV).to.be.a('function'); expect(Filer.Errors.ENOTEMPTY).to.be.a('function'); - expect(Filer.Errors.ENOSPC).to.be.a('function'); + //expect(Filer.Errors.ENOSPC).to.be.a('function'); expect(Filer.Errors.EIO).to.be.a('function'); - expect(Filer.Errors.EROFS).to.be.a('function'); - expect(Filer.Errors.ENODEV).to.be.a('function'); - expect(Filer.Errors.ESPIPE).to.be.a('function'); - expect(Filer.Errors.ECANCELED).to.be.a('function'); + //expect(Filer.Errors.EROFS).to.be.a('function'); + //expect(Filer.Errors.ENODEV).to.be.a('function'); + //expect(Filer.Errors.ESPIPE).to.be.a('function'); + //expect(Filer.Errors.ECANCELED).to.be.a('function'); expect(Filer.Errors.ENOTMOUNTED).to.be.a('function'); expect(Filer.Errors.EFILESYSTEMERROR).to.be.a('function'); expect(Filer.Errors.ENOATTR).to.be.a('function'); // By errno - expect(Filer.Errors[-1]).to.equal(Filer.Errors.UNKNOWN); - expect(Filer.Errors[0]).to.equal(Filer.Errors.OK); - expect(Filer.Errors[1]).to.equal(Filer.Errors.EOF); - expect(Filer.Errors[2]).to.equal(Filer.Errors.EADDRINFO); - expect(Filer.Errors[3]).to.equal(Filer.Errors.EACCES); - expect(Filer.Errors[4]).to.equal(Filer.Errors.EAGAIN); - expect(Filer.Errors[5]).to.equal(Filer.Errors.EADDRINUSE); - expect(Filer.Errors[6]).to.equal(Filer.Errors.EADDRNOTAVAIL); - expect(Filer.Errors[7]).to.equal(Filer.Errors.EAFNOSUPPORT); - expect(Filer.Errors[8]).to.equal(Filer.Errors.EALREADY); + //expect(Filer.Errors[-1]).to.equal(Filer.Errors.UNKNOWN); + //expect(Filer.Errors[0]).to.equal(Filer.Errors.OK); + //expect(Filer.Errors[1]).to.equal(Filer.Errors.EOF); + //expect(Filer.Errors[2]).to.equal(Filer.Errors.EADDRINFO); + //expect(Filer.Errors[3]).to.equal(Filer.Errors.EACCES); + //expect(Filer.Errors[4]).to.equal(Filer.Errors.EAGAIN); + //expect(Filer.Errors[5]).to.equal(Filer.Errors.EADDRINUSE); + //expect(Filer.Errors[6]).to.equal(Filer.Errors.EADDRNOTAVAIL); + //expect(Filer.Errors[7]).to.equal(Filer.Errors.EAFNOSUPPORT); + //expect(Filer.Errors[8]).to.equal(Filer.Errors.EALREADY); expect(Filer.Errors[9]).to.equal(Filer.Errors.EBADF); expect(Filer.Errors[10]).to.equal(Filer.Errors.EBUSY); - expect(Filer.Errors[11]).to.equal(Filer.Errors.ECONNABORTED); - expect(Filer.Errors[12]).to.equal(Filer.Errors.ECONNREFUSED); - expect(Filer.Errors[13]).to.equal(Filer.Errors.ECONNRESET); - expect(Filer.Errors[14]).to.equal(Filer.Errors.EDESTADDRREQ); - expect(Filer.Errors[15]).to.equal(Filer.Errors.EFAULT); - expect(Filer.Errors[16]).to.equal(Filer.Errors.EHOSTUNREACH); - expect(Filer.Errors[17]).to.equal(Filer.Errors.EINTR); + //expect(Filer.Errors[11]).to.equal(Filer.Errors.ECONNABORTED); + //expect(Filer.Errors[12]).to.equal(Filer.Errors.ECONNREFUSED); + //expect(Filer.Errors[13]).to.equal(Filer.Errors.ECONNRESET); + //expect(Filer.Errors[14]).to.equal(Filer.Errors.EDESTADDRREQ); + //expect(Filer.Errors[15]).to.equal(Filer.Errors.EFAULT); + //expect(Filer.Errors[16]).to.equal(Filer.Errors.EHOSTUNREACH); + //expect(Filer.Errors[17]).to.equal(Filer.Errors.EINTR); expect(Filer.Errors[18]).to.equal(Filer.Errors.EINVAL); - expect(Filer.Errors[19]).to.equal(Filer.Errors.EISCONN); - expect(Filer.Errors[20]).to.equal(Filer.Errors.EMFILE); - expect(Filer.Errors[21]).to.equal(Filer.Errors.EMSGSIZE); - expect(Filer.Errors[22]).to.equal(Filer.Errors.ENETDOWN); - expect(Filer.Errors[23]).to.equal(Filer.Errors.ENETUNREACH); - expect(Filer.Errors[24]).to.equal(Filer.Errors.ENFILE); - expect(Filer.Errors[25]).to.equal(Filer.Errors.ENOBUFS); - expect(Filer.Errors[26]).to.equal(Filer.Errors.ENOMEM); + //expect(Filer.Errors[19]).to.equal(Filer.Errors.EISCONN); + //expect(Filer.Errors[20]).to.equal(Filer.Errors.EMFILE); + //expect(Filer.Errors[21]).to.equal(Filer.Errors.EMSGSIZE); + //expect(Filer.Errors[22]).to.equal(Filer.Errors.ENETDOWN); + //expect(Filer.Errors[23]).to.equal(Filer.Errors.ENETUNREACH); + //expect(Filer.Errors[24]).to.equal(Filer.Errors.ENFILE); + //expect(Filer.Errors[25]).to.equal(Filer.Errors.ENOBUFS); + //expect(Filer.Errors[26]).to.equal(Filer.Errors.ENOMEM); expect(Filer.Errors[27]).to.equal(Filer.Errors.ENOTDIR); expect(Filer.Errors[28]).to.equal(Filer.Errors.EISDIR); - expect(Filer.Errors[29]).to.equal(Filer.Errors.ENONET); - expect(Filer.Errors[31]).to.equal(Filer.Errors.ENOTCONN); - expect(Filer.Errors[32]).to.equal(Filer.Errors.ENOTSOCK); - expect(Filer.Errors[33]).to.equal(Filer.Errors.ENOTSUP); + //expect(Filer.Errors[29]).to.equal(Filer.Errors.ENONET); + //expect(Filer.Errors[31]).to.equal(Filer.Errors.ENOTCONN); + //expect(Filer.Errors[32]).to.equal(Filer.Errors.ENOTSOCK); + //expect(Filer.Errors[33]).to.equal(Filer.Errors.ENOTSUP); expect(Filer.Errors[34]).to.equal(Filer.Errors.ENOENT); - expect(Filer.Errors[35]).to.equal(Filer.Errors.ENOSYS); - expect(Filer.Errors[36]).to.equal(Filer.Errors.EPIPE); - expect(Filer.Errors[37]).to.equal(Filer.Errors.EPROTO); - expect(Filer.Errors[38]).to.equal(Filer.Errors.EPROTONOSUPPORT); - expect(Filer.Errors[39]).to.equal(Filer.Errors.EPROTOTYPE); - expect(Filer.Errors[40]).to.equal(Filer.Errors.ETIMEDOUT); - expect(Filer.Errors[41]).to.equal(Filer.Errors.ECHARSET); - expect(Filer.Errors[42]).to.equal(Filer.Errors.EAIFAMNOSUPPORT); - expect(Filer.Errors[44]).to.equal(Filer.Errors.EAISERVICE); - expect(Filer.Errors[45]).to.equal(Filer.Errors.EAISOCKTYPE); - expect(Filer.Errors[46]).to.equal(Filer.Errors.ESHUTDOWN); + //expect(Filer.Errors[35]).to.equal(Filer.Errors.ENOSYS); + //expect(Filer.Errors[36]).to.equal(Filer.Errors.EPIPE); + //expect(Filer.Errors[37]).to.equal(Filer.Errors.EPROTO); + //expect(Filer.Errors[38]).to.equal(Filer.Errors.EPROTONOSUPPORT); + //expect(Filer.Errors[39]).to.equal(Filer.Errors.EPROTOTYPE); + //expect(Filer.Errors[40]).to.equal(Filer.Errors.ETIMEDOUT); + //expect(Filer.Errors[41]).to.equal(Filer.Errors.ECHARSET); + //expect(Filer.Errors[42]).to.equal(Filer.Errors.EAIFAMNOSUPPORT); + //expect(Filer.Errors[44]).to.equal(Filer.Errors.EAISERVICE); + //expect(Filer.Errors[45]).to.equal(Filer.Errors.EAISOCKTYPE); + //expect(Filer.Errors[46]).to.equal(Filer.Errors.ESHUTDOWN); expect(Filer.Errors[47]).to.equal(Filer.Errors.EEXIST); - expect(Filer.Errors[48]).to.equal(Filer.Errors.ESRCH); - expect(Filer.Errors[49]).to.equal(Filer.Errors.ENAMETOOLONG); - expect(Filer.Errors[50]).to.equal(Filer.Errors.EPERM); + //expect(Filer.Errors[48]).to.equal(Filer.Errors.ESRCH); + //expect(Filer.Errors[49]).to.equal(Filer.Errors.ENAMETOOLONG); + //expect(Filer.Errors[50]).to.equal(Filer.Errors.EPERM); expect(Filer.Errors[51]).to.equal(Filer.Errors.ELOOP); - expect(Filer.Errors[52]).to.equal(Filer.Errors.EXDEV); + //expect(Filer.Errors[52]).to.equal(Filer.Errors.EXDEV); expect(Filer.Errors[53]).to.equal(Filer.Errors.ENOTEMPTY); - expect(Filer.Errors[54]).to.equal(Filer.Errors.ENOSPC); + //expect(Filer.Errors[54]).to.equal(Filer.Errors.ENOSPC); expect(Filer.Errors[55]).to.equal(Filer.Errors.EIO); - expect(Filer.Errors[56]).to.equal(Filer.Errors.EROFS); - expect(Filer.Errors[57]).to.equal(Filer.Errors.ENODEV); - expect(Filer.Errors[58]).to.equal(Filer.Errors.ESPIPE); - expect(Filer.Errors[59]).to.equal(Filer.Errors.ECANCELED); + //expect(Filer.Errors[56]).to.equal(Filer.Errors.EROFS); + //expect(Filer.Errors[57]).to.equal(Filer.Errors.ENODEV); + //expect(Filer.Errors[58]).to.equal(Filer.Errors.ESPIPE); + //expect(Filer.Errors[59]).to.equal(Filer.Errors.ECANCELED); expect(Filer.Errors[1000]).to.equal(Filer.Errors.ENOTMOUNTED); expect(Filer.Errors[1001]).to.equal(Filer.Errors.EFILESYSTEMERROR); expect(Filer.Errors[1002]).to.equal(Filer.Errors.ENOATTR); }); + + it('should include all expected properties by default', function() { + var err = new Filer.Errors.ENOENT(); + expect(err.name).to.equal('ENOENT'); + expect(err.code).to.equal('ENOENT'); + expect(err.errno).to.equal(34); + expect(err.message).to.equal('no such file or directory'); + }); + + it('should include extra properties when provided', function() { + var err = new Filer.Errors.ENOENT('This is the message', '/this/is/the/path'); + expect(err.name).to.equal('ENOENT'); + expect(err.code).to.equal('ENOENT'); + expect(err.errno).to.equal(34); + expect(err.message).to.equal('This is the message'); + expect(err.path).to.equal('/this/is/the/path'); + }); + + it('should include default message and path info when provided', function() { + var err = new Filer.Errors.ENOENT(null, '/this/is/the/path'); + expect(err.message).to.equal('no such file or directory'); + expect(err.path).to.equal('/this/is/the/path'); + }); + + it('should include just the message when no path provided', function() { + var err = new Filer.Errors.ENOENT(); + expect(err.message).to.equal('no such file or directory'); + expect(err.path).not.to.exist; + }); + + it('should not include path in toString() when not provided', function() { + var err = new Filer.Errors.ENOENT('This is the message'); + expect(err.toString()).to.equal("ENOENT: This is the message"); + }); + + it('should include path in toString() when provided', function() { + var err = new Filer.Errors.ENOENT(null, '/this/is/the/path'); + expect(err.toString()).to.equal("ENOENT: no such file or directory, '/this/is/the/path'"); + }); + + it('should include message and path info when provided', function() { + var err = new Filer.Errors.ENOENT('This is the message', '/this/is/the/path'); + expect(err.message).to.equal('This is the message'); + expect(err.path).to.equal('/this/is/the/path'); + }); });