Merge branch 'develop' of github.com:js-platform/filer into develop
Conflicts: dist/filer.js dist/filer.min.js src/fs.js src/providers/websql.js This deals exclusively with requirejs path issues.
This commit is contained in:
commit
03aae05a33
29
README.md
29
README.md
|
@ -80,7 +80,10 @@ Accepts two arguments: an `options` object, and an optional `callback`. The `opt
|
|||
object can specify a number of optional arguments, including:
|
||||
|
||||
* `name`: the name of the file system, defaults to `'"local'`
|
||||
* `flags`: one or more flags to use when creating/opening the file system. Use `'FORMAT'` to force Filer to format (i.e., erase) the file system
|
||||
* `flags`: an Array of one or more flags to use when creating/opening the file system:
|
||||
*`'FORMAT'` to force Filer to format (i.e., erase) the file system
|
||||
*`'NOCTIME'` to force Filer to not update `ctime` on nodes when metadata changes (i.e., for better performance)
|
||||
*`'NOMTIME'` to force Filer to not update `mtime` on nodes when data changes (i.e., for better performance)
|
||||
* `provider`: an explicit storage provider to use for the file system's database context provider. See the section on [Storage Providers](#providers).
|
||||
|
||||
The `callback` function indicates when the file system is ready for use. Depending on the storage provider used, this might
|
||||
|
@ -98,7 +101,7 @@ function fsReady(err, fs) {
|
|||
|
||||
fs = new Filer.FileSystem({
|
||||
name: "my-filesystem",
|
||||
flags: 'FORMAT',
|
||||
flags: [ 'FORMAT' ],
|
||||
provider: new Filer.FileSystem.providers.Memory()
|
||||
}, fsReady);
|
||||
```
|
||||
|
@ -175,7 +178,6 @@ interface as providers. See the code in `src/providers` and `src/adapters` for
|
|||
|
||||
The node.js [path module](http://nodejs.org/api/path.html) is available via the `Filer.Path` object. It is
|
||||
identical to the node.js version with the following differences:
|
||||
* No support for `exits()` or `existsSync()`. Use `fs.stat()` instead.
|
||||
* No notion of a current working directory in `resolve` (the root dir is used instead)
|
||||
|
||||
```javascript
|
||||
|
@ -219,6 +221,7 @@ var fs = new Filer.FileSystem();
|
|||
* [fs.stat(path, callback)](#stat)
|
||||
* [fs.fstat(fd, callback)](#fstat)
|
||||
* [fs.lstat(path, callback)](#lstat)
|
||||
* [fs.exists(path, callback)](#exists)
|
||||
* [fs.link(srcpath, dstpath, callback)](#link)
|
||||
* [fs.symlink(srcpath, dstpath, [type], callback)](#symlink)
|
||||
* [fs.readlink(path, callback)](#readlink)
|
||||
|
@ -417,7 +420,25 @@ fs.link("/data/logs/august", "/data/logs/current", function(err) {
|
|||
var size = stats.size;
|
||||
});
|
||||
});
|
||||
````
|
||||
```
|
||||
|
||||
#### fs.exists(path, callback)<a name="exists"></a>
|
||||
|
||||
Test whether or not the given path exists by checking with the file system.
|
||||
Then call the callback argument with either true or false.
|
||||
|
||||
Example:
|
||||
|
||||
```javascript
|
||||
//Test if the file exists
|
||||
fs.exists('/myfile', function (exists) {
|
||||
console.log(exists ? "file exists" : "file not found");
|
||||
});
|
||||
```
|
||||
|
||||
fs.exists() is an anachronism and exists only for historical reasons. There should almost never be a reason to use it in your own code.
|
||||
|
||||
In particular, checking if a file exists before opening it is an anti-pattern that leaves you vulnerable to race conditions: another process may remove the file between the calls to fs.exists() and fs.open(). Just open the file and handle the error when it's not there.
|
||||
|
||||
#### fs.link(srcPath, dstPath, callback)<a name="link"></a>
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -19,9 +19,9 @@ var fs = new Filer.FileSystem({
|
|||
//var data = new Uint8Array(buffer.length);
|
||||
|
||||
try {
|
||||
fs.stat('/', function(error, stats) {
|
||||
fs.readdir('\u0000', function(error, files) {
|
||||
if(error) throw error;
|
||||
console.log('stats:', stats);
|
||||
console.log('contents:', files);
|
||||
});
|
||||
} catch(e) {
|
||||
console.error(e);
|
||||
|
|
|
@ -33,8 +33,12 @@ define(function(require) {
|
|||
|
||||
ROOT_DIRECTORY_NAME: '/', // basename(normalize(path))
|
||||
|
||||
// FS Mount Flags
|
||||
FS_FORMAT: 'FORMAT',
|
||||
FS_NOCTIME: 'NOCTIME',
|
||||
FS_NOMTIME: 'NOMTIME',
|
||||
|
||||
// FS File Open Flags
|
||||
O_READ: O_READ,
|
||||
O_WRITE: O_WRITE,
|
||||
O_CREATE: O_CREATE,
|
||||
|
|
586
src/error.js
586
src/error.js
|
@ -9,122 +9,570 @@ Redistribution and use in source and binary forms, with or without modification,
|
|||
Neither the name of the Mozilla Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Errors based off Node.js custom errors (https://github.com/rvagg/node-errno) made available under the MIT license
|
||||
*/
|
||||
|
||||
define(function(require) {
|
||||
// 'use strict';
|
||||
|
||||
function EExists(message){
|
||||
this.message = message || '';
|
||||
|
||||
function Unknown(message){
|
||||
this.message = message || 'unknown error';
|
||||
}
|
||||
EExists.prototype = new Error();
|
||||
EExists.prototype.name = "EExists";
|
||||
EExists.prototype.constructor = EExists;
|
||||
Unknown.prototype = new Error();
|
||||
Unknown.prototype.errno = -1;
|
||||
Unknown.prototype.code = "UNKNOWN";
|
||||
Unknown.prototype.constructor = Unknown;
|
||||
|
||||
function EIsDirectory(message){
|
||||
this.message = message || '';
|
||||
function OK(message){
|
||||
this.message = message || 'success';
|
||||
}
|
||||
EIsDirectory.prototype = new Error();
|
||||
EIsDirectory.prototype.name = "EIsDirectory";
|
||||
EIsDirectory.prototype.constructor = EIsDirectory;
|
||||
OK.prototype = new Error();
|
||||
OK.prototype.errno = 0;
|
||||
OK.prototype.code = "OK";
|
||||
OK.prototype.constructor = OK;
|
||||
|
||||
function ENoEntry(message){
|
||||
this.message = message || '';
|
||||
function EOF(message){
|
||||
this.message = message || 'end of file';
|
||||
}
|
||||
ENoEntry.prototype = new Error();
|
||||
ENoEntry.prototype.name = "ENoEntry";
|
||||
ENoEntry.prototype.constructor = ENoEntry;
|
||||
EOF.prototype = new Error();
|
||||
EOF.prototype.errno = 1;
|
||||
EOF.prototype.code = "EOF";
|
||||
EOF.prototype.constructor = EOF;
|
||||
|
||||
function EAddrInfo(message){
|
||||
this.message = message || 'getaddrinfo error';
|
||||
}
|
||||
EAddrInfo.prototype = new Error();
|
||||
EAddrInfo.prototype.errno = 2;
|
||||
EAddrInfo.prototype.code = "EADDRINFO";
|
||||
EAddrInfo.prototype.constructor = EAddrInfo;
|
||||
|
||||
function EAcces(message){
|
||||
this.message = message || 'permission denied';
|
||||
}
|
||||
EAcces.prototype = new Error();
|
||||
EAcces.prototype.errno = 3;
|
||||
EAcces.prototype.code = "EACCES";
|
||||
EAcces.prototype.constructor = EAcces;
|
||||
|
||||
function EAgain(message){
|
||||
this.message = message || 'resource temporarily unavailable';
|
||||
}
|
||||
EAgain.prototype = new Error();
|
||||
EAgain.prototype.errno = 4;
|
||||
EAgain.prototype.code = "EAGAIN";
|
||||
EAgain.prototype.constructor = EAgain;
|
||||
|
||||
function EAddrInUse(message){
|
||||
this.message = message || 'address already in use';
|
||||
}
|
||||
EAddrInUse.prototype = new Error();
|
||||
EAddrInUse.prototype.errno = 5;
|
||||
EAddrInUse.prototype.code = "EADDRINUSE";
|
||||
EAddrInUse.prototype.constructor = EAddrInUse;
|
||||
|
||||
function EAddrNotAvail(message){
|
||||
this.message = message || 'address not available';
|
||||
}
|
||||
EAddrNotAvail.prototype = new Error();
|
||||
EAddrNotAvail.prototype.errno = 6;
|
||||
EAddrNotAvail.prototype.code = "EADDRNOTAVAIL";
|
||||
EAddrNotAvail.prototype.constructor = EAddrNotAvail;
|
||||
|
||||
function EAFNoSupport(message){
|
||||
this.message = message || 'address family not supported';
|
||||
}
|
||||
EAFNoSupport.prototype = new Error();
|
||||
EAFNoSupport.prototype.errno = 7;
|
||||
EAFNoSupport.prototype.code = "EAFNOSUPPORT";
|
||||
EAFNoSupport.prototype.constructor = EAFNoSupport;
|
||||
|
||||
function EBusy(message){
|
||||
this.message = message || '';
|
||||
function EAlready(message){
|
||||
this.message = message || 'connection already in progress';
|
||||
}
|
||||
EBusy.prototype = new Error();
|
||||
EBusy.prototype.name = "EBusy";
|
||||
EBusy.prototype.constructor = EBusy;
|
||||
|
||||
function ENotEmpty(message){
|
||||
this.message = message || '';
|
||||
}
|
||||
ENotEmpty.prototype = new Error();
|
||||
ENotEmpty.prototype.name = "ENotEmpty";
|
||||
ENotEmpty.prototype.constructor = ENotEmpty;
|
||||
|
||||
function ENotDirectory(message){
|
||||
this.message = message || '';
|
||||
}
|
||||
ENotDirectory.prototype = new Error();
|
||||
ENotDirectory.prototype.name = "ENotDirectory";
|
||||
ENotDirectory.prototype.constructor = ENotDirectory;
|
||||
EAlready.prototype = new Error();
|
||||
EAlready.prototype.errno = 8;
|
||||
EAlready.prototype.code = "EALREADY";
|
||||
EAlready.prototype.constructor = EAlready;
|
||||
|
||||
function EBadFileDescriptor(message){
|
||||
this.message = message || '';
|
||||
this.message = message || 'bad file descriptor';
|
||||
}
|
||||
EBadFileDescriptor.prototype = new Error();
|
||||
EBadFileDescriptor.prototype.name = "EBadFileDescriptor";
|
||||
EBadFileDescriptor.prototype.errno = 9;
|
||||
EBadFileDescriptor.prototype.code = "EBADF";
|
||||
EBadFileDescriptor.prototype.constructor = EBadFileDescriptor;
|
||||
|
||||
function ENotImplemented(message){
|
||||
this.message = message || '';
|
||||
function EBusy(message){
|
||||
this.message = message || 'resource busy or locked';
|
||||
}
|
||||
ENotImplemented.prototype = new Error();
|
||||
ENotImplemented.prototype.name = "ENotImplemented";
|
||||
ENotImplemented.prototype.constructor = ENotImplemented;
|
||||
EBusy.prototype = new Error();
|
||||
EBusy.prototype.errno = 10;
|
||||
EBusy.prototype.code = "EBUSY";
|
||||
EBusy.prototype.constructor = EBusy;
|
||||
|
||||
function ENotMounted(message){
|
||||
this.message = message || '';
|
||||
function EConnAborted(message){
|
||||
this.message = message || 'software caused connection abort';
|
||||
}
|
||||
ENotMounted.prototype = new Error();
|
||||
ENotMounted.prototype.name = "ENotMounted";
|
||||
ENotMounted.prototype.constructor = ENotMounted;
|
||||
EConnAborted.prototype = new Error();
|
||||
EConnAborted.prototype.errno = 11;
|
||||
EConnAborted.prototype.code = "ECONNABORTED";
|
||||
EConnAborted.prototype.constructor = EConnAborted;
|
||||
|
||||
function EConnRefused(message){
|
||||
this.message = message || 'connection refused';
|
||||
}
|
||||
EConnRefused.prototype = new Error();
|
||||
EConnRefused.prototype.errno = 12;
|
||||
EConnRefused.prototype.code = "ECONNREFUSED";
|
||||
EConnRefused.prototype.constructor = EConnRefused;
|
||||
|
||||
function EConnReset(message){
|
||||
this.message = message || 'connection reset by peer';
|
||||
}
|
||||
EConnReset.prototype = new Error();
|
||||
EConnReset.prototype.errno = 13;
|
||||
EConnReset.prototype.code = "ECONNRESET";
|
||||
EConnReset.prototype.constructor = EConnReset;
|
||||
|
||||
function EDestAddrReq(message){
|
||||
this.message = message || 'destination address required';
|
||||
}
|
||||
EDestAddrReq.prototype = new Error();
|
||||
EDestAddrReq.prototype.errno = 14;
|
||||
EDestAddrReq.prototype.code = "EDESTADDRREQ";
|
||||
EDestAddrReq.prototype.constructor = EDestAddrReq;
|
||||
|
||||
function EFault(message){
|
||||
this.message = message || 'bad address in system call argument';
|
||||
}
|
||||
EFault.prototype = new Error();
|
||||
EFault.prototype.errno = 15;
|
||||
EFault.prototype.code = "EFAULT";
|
||||
EFault.prototype.constructor = EFault;
|
||||
|
||||
function EHostUnreach(message){
|
||||
this.message = message || 'host is unreachable';
|
||||
}
|
||||
EHostUnreach.prototype = new Error();
|
||||
EHostUnreach.prototype.errno = 16;
|
||||
EHostUnreach.prototype.code = "EHOSTUNREACH";
|
||||
EHostUnreach.prototype.constructor = EHostUnreach;
|
||||
|
||||
function EIntr(message){
|
||||
this.message = message || 'interrupted system call';
|
||||
}
|
||||
EIntr.prototype = new Error();
|
||||
EIntr.prototype.errno = 17;
|
||||
EIntr.prototype.code = "EINTR";
|
||||
EIntr.prototype.constructor = EIntr;
|
||||
|
||||
function EInvalid(message){
|
||||
this.message = message || '';
|
||||
this.message = message || 'invalid argument';
|
||||
}
|
||||
EInvalid.prototype = new Error();
|
||||
EInvalid.prototype.name = "EInvalid";
|
||||
EInvalid.prototype.errno = 18;
|
||||
EInvalid.prototype.code = "EINVAL";
|
||||
EInvalid.prototype.constructor = EInvalid;
|
||||
|
||||
function EIO(message){
|
||||
this.message = message || '';
|
||||
function EIsConn(message){
|
||||
this.message = message || 'socket is already connected';
|
||||
}
|
||||
EIO.prototype = new Error();
|
||||
EIO.prototype.name = "EIO";
|
||||
EIO.prototype.constructor = EIO;
|
||||
EIsConn.prototype = new Error();
|
||||
EIsConn.prototype.errno = 19;
|
||||
EIsConn.prototype.code = "EISCONN";
|
||||
EIsConn.prototype.constructor = EIsConn;
|
||||
|
||||
function EMFile(message){
|
||||
this.message = message || 'too many open files';
|
||||
}
|
||||
EMFile.prototype = new Error();
|
||||
EMFile.prototype.errno = 20;
|
||||
EMFile.prototype.code = "EMFILE";
|
||||
EMFile.prototype.constructor = EMFile;
|
||||
|
||||
function EMsgSize(message){
|
||||
this.message = message || 'message too long';
|
||||
}
|
||||
EMsgSize.prototype = new Error();
|
||||
EMsgSize.prototype.errno = 21;
|
||||
EMsgSize.prototype.code = "EMSGSIZE";
|
||||
EMsgSize.prototype.constructor = EMsgSize;
|
||||
|
||||
function ENetDown(message){
|
||||
this.message = message || 'network is down';
|
||||
}
|
||||
ENetDown.prototype = new Error();
|
||||
ENetDown.prototype.errno = 22;
|
||||
ENetDown.prototype.code = "ENETDOWN";
|
||||
ENetDown.prototype.constructor = ENetDown;
|
||||
|
||||
function ENetUnreach(message){
|
||||
this.message = message || 'network is unreachable';
|
||||
}
|
||||
ENetUnreach.prototype = new Error();
|
||||
ENetUnreach.prototype.errno = 23;
|
||||
ENetUnreach.prototype.code = "ENETUNREACH";
|
||||
ENetUnreach.prototype.constructor = ENetUnreach;
|
||||
|
||||
function ENFile(message){
|
||||
this.message = message || 'file table overflow';
|
||||
}
|
||||
ENFile.prototype = new Error();
|
||||
ENFile.prototype.errno = 24;
|
||||
ENFile.prototype.code = "ENFILE";
|
||||
ENFile.prototype.constructor = ENFile;
|
||||
|
||||
function ENoBufS(message){
|
||||
this.message = message || 'no buffer space available';
|
||||
}
|
||||
ENoBufS.prototype = new Error();
|
||||
ENoBufS.prototype.errno = 25;
|
||||
ENoBufS.prototype.code = "ENOBUFS";
|
||||
ENoBufS.prototype.constructor = ENoBufS;
|
||||
|
||||
function ENoMem(message){
|
||||
this.message = message || 'not enough memory';
|
||||
}
|
||||
ENoMem.prototype = new Error();
|
||||
ENoMem.prototype.errno = 26;
|
||||
ENoMem.prototype.code = "ENOMEM";
|
||||
ENoMem.prototype.constructor = ENoMem;
|
||||
|
||||
function ENotDirectory(message){
|
||||
this.message = message || 'not a directory';
|
||||
}
|
||||
ENotDirectory.prototype = new Error();
|
||||
ENotDirectory.prototype.errno = 27;
|
||||
ENotDirectory.prototype.code = "ENOTDIR";
|
||||
ENotDirectory.prototype.constructor = ENotDirectory;
|
||||
|
||||
function EIsDirectory(message){
|
||||
this.message = message || 'illegal operation on a directory';
|
||||
}
|
||||
EIsDirectory.prototype = new Error();
|
||||
EIsDirectory.prototype.errno = 28;
|
||||
EIsDirectory.prototype.code = "EISDIR";
|
||||
EIsDirectory.prototype.constructor = EIsDirectory;
|
||||
|
||||
function ENoNet(message){
|
||||
this.message = message || 'machine is not on the network';
|
||||
}
|
||||
ENoNet.prototype = new Error();
|
||||
ENoNet.prototype.errno = 29;
|
||||
ENoNet.prototype.code = "ENONET";
|
||||
ENoNet.prototype.constructor = ENoNet;
|
||||
|
||||
function ENotConn(message){
|
||||
this.message = message || 'socket is not connected';
|
||||
}
|
||||
ENotConn.prototype = new Error();
|
||||
ENotConn.prototype.errno = 31;
|
||||
ENotConn.prototype.code = "ENOTCONN";
|
||||
ENotConn.prototype.constructor = ENotConn;
|
||||
|
||||
function ENotSock(message){
|
||||
this.message = message || 'socket operation on non-socket';
|
||||
}
|
||||
ENotSock.prototype = new Error();
|
||||
ENotSock.prototype.errno = 32;
|
||||
ENotSock.prototype.code = "ENOTSOCK";
|
||||
ENotSock.prototype.constructor = ENotSock;
|
||||
|
||||
function ENotSup(message){
|
||||
this.message = message || 'operation not supported on socket';
|
||||
}
|
||||
ENotSup.prototype = new Error();
|
||||
ENotSup.prototype.errno = 33;
|
||||
ENotSup.prototype.code = "ENOTSUP";
|
||||
ENotSup.prototype.constructor = ENotSup;
|
||||
|
||||
function ENoEntry(message){
|
||||
this.message = message || 'no such file or directory';
|
||||
}
|
||||
ENoEntry.prototype = new Error();
|
||||
ENoEntry.prototype.errno = 34;
|
||||
ENoEntry.prototype.code = "ENOENT";
|
||||
ENoEntry.prototype.constructor = ENoEntry;
|
||||
|
||||
function ENotImplemented(message){
|
||||
this.message = message || 'function not implemented';
|
||||
}
|
||||
ENotImplemented.prototype = new Error();
|
||||
ENotImplemented.prototype.errno = 35;
|
||||
ENotImplemented.prototype.code = "ENOSYS";
|
||||
ENotImplemented.prototype.constructor = ENotImplemented;
|
||||
|
||||
function EPipe(message){
|
||||
this.message = message || 'broken pipe';
|
||||
}
|
||||
EPipe.prototype = new Error();
|
||||
EPipe.prototype.errno = 36;
|
||||
EPipe.prototype.code = "EPIPE";
|
||||
EPipe.prototype.constructor = EPipe;
|
||||
|
||||
function EProto(message){
|
||||
this.message = message || 'protocol error';
|
||||
}
|
||||
EProto.prototype = new Error();
|
||||
EProto.prototype.errno = 37;
|
||||
EProto.prototype.code = "EPROTO";
|
||||
EProto.prototype.constructor = EProto;
|
||||
|
||||
function EProtoNoSupport(message){
|
||||
this.message = message || 'protocol not supported';
|
||||
}
|
||||
EProtoNoSupport.prototype = new Error();
|
||||
EProtoNoSupport.prototype.errno = 38;
|
||||
EProtoNoSupport.prototype.code = "EPROTONOSUPPORT";
|
||||
EProtoNoSupport.prototype.constructor = EProtoNoSupport;
|
||||
|
||||
function EPrototype(message){
|
||||
this.message = message || 'protocol wrong type for socket';
|
||||
}
|
||||
EPrototype.prototype = new Error();
|
||||
EPrototype.prototype.errno = 39;
|
||||
EPrototype.prototype.code = "EPROTOTYPE";
|
||||
EPrototype.prototype.constructor = EPrototype;
|
||||
|
||||
function ETimedOut(message){
|
||||
this.message = message || 'connection timed out';
|
||||
}
|
||||
ETimedOut.prototype = new Error();
|
||||
ETimedOut.prototype.errno = 40;
|
||||
ETimedOut.prototype.code = "ETIMEDOUT";
|
||||
ETimedOut.prototype.constructor = ETimedOut;
|
||||
|
||||
function ECharset(message){
|
||||
this.message = message || 'invalid Unicode character';
|
||||
}
|
||||
ECharset.prototype = new Error();
|
||||
ECharset.prototype.errno = 41;
|
||||
ECharset.prototype.code = "ECHARSET";
|
||||
ECharset.prototype.constructor = ECharset;
|
||||
|
||||
function EAIFamNoSupport(message){
|
||||
this.message = message || 'address family for hostname not supported';
|
||||
}
|
||||
EAIFamNoSupport.prototype = new Error();
|
||||
EAIFamNoSupport.prototype.errno = 42;
|
||||
EAIFamNoSupport.prototype.code = "EAIFAMNOSUPPORT";
|
||||
EAIFamNoSupport.prototype.constructor = EAIFamNoSupport;
|
||||
|
||||
function EAIService(message){
|
||||
this.message = message || 'servname not supported for ai_socktype';
|
||||
}
|
||||
EAIService.prototype = new Error();
|
||||
EAIService.prototype.errno = 44;
|
||||
EAIService.prototype.code = "EAISERVICE";
|
||||
EAIService.prototype.constructor = EAIService;
|
||||
|
||||
function EAISockType(message){
|
||||
this.message = message || 'ai_socktype not supported';
|
||||
}
|
||||
EAISockType.prototype = new Error();
|
||||
EAISockType.prototype.errno = 45;
|
||||
EAISockType.prototype.code = "EAISOCKTYPE";
|
||||
EAISockType.prototype.constructor = EAISockType;
|
||||
|
||||
function EShutdown(message){
|
||||
this.message = message || 'cannot send after transport endpoint shutdown';
|
||||
}
|
||||
EShutdown.prototype = new Error();
|
||||
EShutdown.prototype.errno = 46;
|
||||
EShutdown.prototype.code = "ESHUTDOWN";
|
||||
EShutdown.prototype.constructor = EShutdown;
|
||||
|
||||
function EExists(message){
|
||||
this.message = message || 'file already exists';
|
||||
}
|
||||
EExists.prototype = new Error();
|
||||
EExists.prototype.errno = 47;
|
||||
EExists.prototype.code = "EEXIST";
|
||||
EExists.prototype.constructor = EExists;
|
||||
|
||||
function ESrch(message){
|
||||
this.message = message || 'no such process';
|
||||
}
|
||||
ESrch.prototype = new Error();
|
||||
ESrch.prototype.errno = 48;
|
||||
ESrch.prototype.code = "ESRCH";
|
||||
ESrch.prototype.constructor = ESrch;
|
||||
|
||||
function ENameTooLong(message){
|
||||
this.message = message || 'name too long';
|
||||
}
|
||||
ENameTooLong.prototype = new Error();
|
||||
ENameTooLong.prototype.errno = 49;
|
||||
ENameTooLong.prototype.code = "ENAMETOOLONG";
|
||||
ENameTooLong.prototype.constructor = ENameTooLong;
|
||||
|
||||
function EPerm(message){
|
||||
this.message = message || 'operation not permitted';
|
||||
}
|
||||
EPerm.prototype = new Error();
|
||||
EPerm.prototype.errno = 50;
|
||||
EPerm.prototype.code = "EPERM";
|
||||
EPerm.prototype.constructor = EPerm;
|
||||
|
||||
function ELoop(message){
|
||||
this.message = message || '';
|
||||
this.message = message || 'too many symbolic links encountered';
|
||||
}
|
||||
ELoop.prototype = new Error();
|
||||
ELoop.prototype.name = "ELoop";
|
||||
ELoop.prototype.errno = 51;
|
||||
ELoop.prototype.code = "ELOOP";
|
||||
ELoop.prototype.constructor = ELoop;
|
||||
|
||||
function EXDev(message){
|
||||
this.message = message || 'cross-device link not permitted';
|
||||
}
|
||||
EXDev.prototype = new Error();
|
||||
EXDev.prototype.errno = 52;
|
||||
EXDev.prototype.code = "EXDEV";
|
||||
EXDev.prototype.constructor = EXDev;
|
||||
|
||||
function ENotEmpty(message){
|
||||
this.message = message || 'directory not empty';
|
||||
}
|
||||
ENotEmpty.prototype = new Error();
|
||||
ENotEmpty.prototype.errno = 53;
|
||||
ENotEmpty.prototype.code = "ENOTEMPTY";
|
||||
ENotEmpty.prototype.constructor = ENotEmpty;
|
||||
|
||||
function ENoSpc(message){
|
||||
this.message = message || 'no space left on device';
|
||||
}
|
||||
ENoSpc.prototype = new Error();
|
||||
ENoSpc.prototype.errno = 54;
|
||||
ENoSpc.prototype.code = "ENOSPC";
|
||||
ENoSpc.prototype.constructor = ENoSpc;
|
||||
|
||||
function EIO(message){
|
||||
this.message = message || 'i/o error';
|
||||
}
|
||||
EIO.prototype = new Error();
|
||||
EIO.prototype.errno = 55;
|
||||
EIO.prototype.code = "EIO";
|
||||
EIO.prototype.constructor = EIO;
|
||||
|
||||
function EROFS(message){
|
||||
this.message = message || 'read-only file system';
|
||||
}
|
||||
EROFS.prototype = new Error();
|
||||
EROFS.prototype.errno = 56;
|
||||
EROFS.prototype.code = "EROFS";
|
||||
EROFS.prototype.constructor = EROFS;
|
||||
|
||||
function ENoDev(message){
|
||||
this.message = message || 'no such device';
|
||||
}
|
||||
ENoDev.prototype = new Error();
|
||||
ENoDev.prototype.errno = 57;
|
||||
ENoDev.prototype.code = "ENODEV";
|
||||
ENoDev.prototype.constructor = ENoDev;
|
||||
|
||||
function ESPipe(message){
|
||||
this.message = message || 'invalid seek';
|
||||
}
|
||||
ESPipe.prototype = new Error();
|
||||
ESPipe.prototype.errno = 58;
|
||||
ESPipe.prototype.code = "ESPIPE";
|
||||
ESPipe.prototype.constructor = ESPipe;
|
||||
|
||||
function ECanceled(message){
|
||||
this.message = message || 'operation canceled';
|
||||
}
|
||||
ECanceled.prototype = new Error();
|
||||
ECanceled.prototype.errno = 59;
|
||||
ECanceled.prototype.code = "ECANCELED";
|
||||
ECanceled.prototype.constructor = ECanceled;
|
||||
|
||||
function ENotMounted(message){
|
||||
this.message = message || 'not mounted';
|
||||
}
|
||||
ENotMounted.prototype = new Error();
|
||||
ENotMounted.prototype.errno = 60;
|
||||
ENotMounted.prototype.code = "ENotMounted";
|
||||
ENotMounted.prototype.constructor = ENotMounted;
|
||||
|
||||
function EFileSystemError(message){
|
||||
this.message = message || '';
|
||||
this.message = message || 'missing super node';
|
||||
}
|
||||
EFileSystemError.prototype = new Error();
|
||||
EFileSystemError.prototype.name = "EFileSystemError";
|
||||
EFileSystemError.prototype.errno = 61;
|
||||
EFileSystemError.prototype.code = "EFileSystemError";
|
||||
EFileSystemError.prototype.constructor = EFileSystemError;
|
||||
|
||||
function ENoAttr(message) {
|
||||
this.message = message || '';
|
||||
this.message = message || 'attribute does not exist';
|
||||
}
|
||||
ENoAttr.prototype = new Error();
|
||||
ENoAttr.prototype.name = 'ENoAttr';
|
||||
ENoAttr.prototype.errno = 62;
|
||||
ENoAttr.prototype.code = 'ENoAttr';
|
||||
ENoAttr.prototype.constructor = ENoAttr;
|
||||
|
||||
return {
|
||||
EExists: EExists,
|
||||
EIsDirectory: EIsDirectory,
|
||||
ENoEntry: ENoEntry,
|
||||
EBusy: EBusy,
|
||||
ENotEmpty: ENotEmpty,
|
||||
ENotDirectory: ENotDirectory,
|
||||
Unknown: Unknown,
|
||||
OK: OK,
|
||||
EOF: EOF,
|
||||
EAddrInfo: EAddrInfo,
|
||||
EAcces: EAcces,
|
||||
EAgain: EAgain,
|
||||
EAddrInUse: EAddrInUse,
|
||||
EAddrNotAvail: EAddrNotAvail,
|
||||
EAFNoSupport: EAFNoSupport,
|
||||
EAlready: EAlready,
|
||||
EBadFileDescriptor: EBadFileDescriptor,
|
||||
ENotImplemented: ENotImplemented,
|
||||
ENotMounted: ENotMounted,
|
||||
EBusy: EBusy,
|
||||
EConnAborted: EConnAborted,
|
||||
EConnRefused: EConnRefused,
|
||||
EConnReset: EConnReset,
|
||||
EDestAddrReq: EDestAddrReq,
|
||||
EFault: EFault,
|
||||
EHostUnreach: EHostUnreach,
|
||||
EIntr: EIntr,
|
||||
EInvalid: EInvalid,
|
||||
EIO: EIO,
|
||||
EIsConn: EIsConn,
|
||||
EMFile: EMFile,
|
||||
EMsgSize: EMsgSize,
|
||||
ENetDown: ENetDown,
|
||||
ENetUnreach: ENetUnreach,
|
||||
ENFile: ENFile,
|
||||
ENoBufS: ENoBufS,
|
||||
ENoMem: ENoMem,
|
||||
ENotDirectory: ENotDirectory,
|
||||
EIsDirectory: EIsDirectory,
|
||||
ENoNet: ENoNet,
|
||||
ENotConn: ENotConn,
|
||||
ENotSock: ENotSock,
|
||||
ENotSup: ENotSup,
|
||||
ENoEntry: ENoEntry,
|
||||
ENotImplemented: ENotImplemented,
|
||||
EPipe: EPipe,
|
||||
EProto: EProto,
|
||||
EProtoNoSupport: EProtoNoSupport,
|
||||
EPrototype: EPrototype,
|
||||
ETimedOut: ETimedOut,
|
||||
ECharset: ECharset,
|
||||
EAIFamNoSupport: EAIFamNoSupport,
|
||||
EAIService: EAIService,
|
||||
EAISockType: EAISockType,
|
||||
EShutdown: EShutdown,
|
||||
EExists: EExists,
|
||||
ESrch: ESrch,
|
||||
ENameTooLong: ENameTooLong,
|
||||
EPerm: EPerm,
|
||||
ELoop: ELoop,
|
||||
EXDev: EXDev,
|
||||
ENotEmpty: ENotEmpty,
|
||||
ENoSpc: ENoSpc,
|
||||
EIO: EIO,
|
||||
EROFS: EROFS,
|
||||
ENoDev: ENoDev,
|
||||
ESPipe: ESPipe,
|
||||
ECanceled: ECanceled,
|
||||
ENotMounted: ENotMounted,
|
||||
EFileSystemError: EFileSystemError,
|
||||
ENoAttr: ENoAttr
|
||||
};
|
||||
|
|
320
src/fs.js
320
src/fs.js
|
@ -9,6 +9,8 @@ define(function(require) {
|
|||
var normalize = require('./path').normalize;
|
||||
var dirname = require('./path').dirname;
|
||||
var basename = require('./path').basename;
|
||||
var isAbsolutePath = require('./path').isAbsolute;
|
||||
var isNullPath = require('./path').isNull;
|
||||
|
||||
var guid = require('./shared').guid;
|
||||
var hash = require('./shared').hash;
|
||||
|
@ -50,6 +52,8 @@ define(function(require) {
|
|||
var O_FLAGS = require('./constants').O_FLAGS;
|
||||
var XATTR_CREATE = require('./constants').XATTR_CREATE;
|
||||
var XATTR_REPLACE = require('./constants').XATTR_REPLACE;
|
||||
var FS_NOMTIME = require('./constants').FS_NOMTIME;
|
||||
var FS_NOCTIME = require('./constants').FS_NOCTIME;
|
||||
|
||||
var providers = require('./providers/providers');
|
||||
var adapters = require('./adapters/adapters');
|
||||
|
@ -68,7 +72,8 @@ define(function(require) {
|
|||
* OpenFileDescription
|
||||
*/
|
||||
|
||||
function OpenFileDescription(id, flags, position) {
|
||||
function OpenFileDescription(path, id, flags, position) {
|
||||
this.path = path;
|
||||
this.id = id;
|
||||
this.flags = flags;
|
||||
this.position = position;
|
||||
|
@ -99,8 +104,8 @@ define(function(require) {
|
|||
this.id = id || guid();
|
||||
this.mode = mode || MODE_FILE; // node type (file, directory, etc)
|
||||
this.size = size || 0; // size (bytes for files, entries for directories)
|
||||
this.atime = atime || now; // access time
|
||||
this.ctime = ctime || now; // creation time
|
||||
this.atime = atime || now; // access time (will mirror ctime after creation)
|
||||
this.ctime = ctime || now; // creation/change time
|
||||
this.mtime = mtime || now; // modified time
|
||||
this.flags = flags || []; // file flags
|
||||
this.xattrs = xattrs || {}; // extended attributes
|
||||
|
@ -126,6 +131,46 @@ define(function(require) {
|
|||
this.type = fileNode.mode;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update node times. Only passed times are modified (undefined times are ignored)
|
||||
* and filesystem flags are examined in order to override update logic.
|
||||
*/
|
||||
function update_node_times(context, path, node, times, callback) {
|
||||
// Honour mount flags for how we update times
|
||||
var flags = context.flags;
|
||||
if(_(flags).contains(FS_NOCTIME)) {
|
||||
delete times.ctime;
|
||||
}
|
||||
if(_(flags).contains(FS_NOMTIME)) {
|
||||
delete times.mtime;
|
||||
}
|
||||
|
||||
// Only do the update if required (i.e., times are still present)
|
||||
var update = false;
|
||||
if(times.ctime) {
|
||||
node.ctime = times.ctime;
|
||||
// We don't do atime tracking for perf reasons, but do mirror ctime
|
||||
node.atime = times.ctime;
|
||||
update = true;
|
||||
}
|
||||
if(times.atime) {
|
||||
// The only time we explicitly pass atime is when utimes(), futimes() is called.
|
||||
// Override ctime mirror here if so
|
||||
node.atime = times.atime;
|
||||
update = true;
|
||||
}
|
||||
if(times.mtime) {
|
||||
node.mtime = times.mtime;
|
||||
update = true;
|
||||
}
|
||||
|
||||
if(update) {
|
||||
context.put(node.id, node, callback);
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* find_node
|
||||
*/
|
||||
|
@ -229,9 +274,19 @@ define(function(require) {
|
|||
*/
|
||||
|
||||
function set_extended_attribute (context, path_or_fd, name, value, flag, callback) {
|
||||
var path;
|
||||
|
||||
function set_xattr (error, node) {
|
||||
var xattr = (node ? node.xattrs[name] : null);
|
||||
|
||||
function update_time(error) {
|
||||
if(error) {
|
||||
callback(error);
|
||||
} else {
|
||||
update_node_times(context, path, node, { ctime: Date.now() }, callback);
|
||||
}
|
||||
}
|
||||
|
||||
if (error) {
|
||||
callback(error);
|
||||
}
|
||||
|
@ -243,14 +298,16 @@ define(function(require) {
|
|||
}
|
||||
else {
|
||||
node.xattrs[name] = value;
|
||||
context.put(node.id, node, callback);
|
||||
context.put(node.id, node, update_time);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof path_or_fd == 'string') {
|
||||
path = path_or_fd;
|
||||
find_node(context, path_or_fd, set_xattr);
|
||||
}
|
||||
else if (typeof path_or_fd == 'object' && typeof path_or_fd.id == 'string') {
|
||||
path = path_or_fd.path;
|
||||
context.get(path_or_fd.id, set_xattr);
|
||||
}
|
||||
else {
|
||||
|
@ -354,12 +411,21 @@ define(function(require) {
|
|||
}
|
||||
}
|
||||
|
||||
function update_time(error) {
|
||||
if(error) {
|
||||
callback(error);
|
||||
} else {
|
||||
var now = Date.now();
|
||||
update_node_times(context, parentPath, parentDirectoryNode, { mtime: now, ctime: now }, callback);
|
||||
}
|
||||
}
|
||||
|
||||
function update_parent_directory_data(error) {
|
||||
if(error) {
|
||||
callback(error);
|
||||
} else {
|
||||
parentDirectoryData[name] = new DirectoryEntry(directoryNode.id, MODE_DIRECTORY);
|
||||
context.put(parentDirectoryNode.data, parentDirectoryData, callback);
|
||||
context.put(parentDirectoryNode.data, parentDirectoryData, update_time);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -427,9 +493,18 @@ define(function(require) {
|
|||
}
|
||||
}
|
||||
|
||||
function update_time(error) {
|
||||
if(error) {
|
||||
callback(error);
|
||||
} else {
|
||||
var now = Date.now();
|
||||
update_node_times(context, parentPath, parentDirectoryNode, { mtime: now, ctime: now }, remove_directory_node);
|
||||
}
|
||||
}
|
||||
|
||||
function remove_directory_entry_from_parent_directory_node() {
|
||||
delete parentDirectoryData[name];
|
||||
context.put(parentDirectoryNode.data, parentDirectoryData, remove_directory_node);
|
||||
context.put(parentDirectoryNode.data, parentDirectoryData, update_time);
|
||||
}
|
||||
|
||||
function remove_directory_node(error) {
|
||||
|
@ -565,12 +640,21 @@ define(function(require) {
|
|||
}
|
||||
}
|
||||
|
||||
function update_time(error) {
|
||||
if(error) {
|
||||
callback(error);
|
||||
} else {
|
||||
var now = Date.now();
|
||||
update_node_times(context, parentPath, directoryNode, { mtime: now, ctime: now }, handle_update_result);
|
||||
}
|
||||
}
|
||||
|
||||
function update_directory_data(error) {
|
||||
if(error) {
|
||||
callback(error);
|
||||
} else {
|
||||
directoryData[name] = new DirectoryEntry(fileNode.id, MODE_FILE);
|
||||
context.put(directoryNode.data, directoryData, handle_update_result);
|
||||
context.put(directoryNode.data, directoryData, update_time);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -594,11 +678,20 @@ define(function(require) {
|
|||
}
|
||||
}
|
||||
|
||||
function update_time(error) {
|
||||
if(error) {
|
||||
callback(error);
|
||||
} else {
|
||||
var now = Date.now();
|
||||
update_node_times(context, ofd.path, fileNode, { mtime: now, ctime: now }, return_nbytes);
|
||||
}
|
||||
}
|
||||
|
||||
function update_file_node(error) {
|
||||
if(error) {
|
||||
callback(error);
|
||||
} else {
|
||||
context.put(fileNode.id, fileNode, return_nbytes);
|
||||
context.put(fileNode.id, fileNode, update_time);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -613,7 +706,6 @@ define(function(require) {
|
|||
ofd.position = length;
|
||||
|
||||
fileNode.size = length;
|
||||
fileNode.mtime = Date.now();
|
||||
fileNode.version += 1;
|
||||
|
||||
context.put(fileNode.data, newData, update_file_node);
|
||||
|
@ -635,11 +727,20 @@ define(function(require) {
|
|||
}
|
||||
}
|
||||
|
||||
function update_time(error) {
|
||||
if(error) {
|
||||
callback(error);
|
||||
} else {
|
||||
var now = Date.now();
|
||||
update_node_times(context, ofd.path, fileNode, { mtime: now, ctime: now }, return_nbytes);
|
||||
}
|
||||
}
|
||||
|
||||
function update_file_node(error) {
|
||||
if(error) {
|
||||
callback(error);
|
||||
} else {
|
||||
context.put(fileNode.id, fileNode, return_nbytes);
|
||||
context.put(fileNode.id, fileNode, update_time);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -661,7 +762,6 @@ define(function(require) {
|
|||
}
|
||||
|
||||
fileNode.size = newSize;
|
||||
fileNode.mtime = Date.now();
|
||||
fileNode.version += 1;
|
||||
|
||||
context.put(fileNode.data, newData, update_file_node);
|
||||
|
@ -700,6 +800,14 @@ define(function(require) {
|
|||
}
|
||||
}
|
||||
|
||||
function update_time(error) {
|
||||
if(error) {
|
||||
callback(error);
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function read_file_data(error, result) {
|
||||
if(error) {
|
||||
callback(error);
|
||||
|
@ -799,13 +907,21 @@ define(function(require) {
|
|||
var newDirectoryData;
|
||||
var fileNode;
|
||||
|
||||
function update_time(error) {
|
||||
if(error) {
|
||||
callback(error);
|
||||
} else {
|
||||
update_node_times(context, newpath, fileNode, { ctime: Date.now() }, callback);
|
||||
}
|
||||
}
|
||||
|
||||
function update_file_node(error, result) {
|
||||
if(error) {
|
||||
callback(error);
|
||||
} else {
|
||||
fileNode = result;
|
||||
fileNode.nlinks += 1;
|
||||
context.put(fileNode.id, fileNode, callback);
|
||||
context.put(fileNode.id, fileNode, update_time);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -879,7 +995,10 @@ define(function(require) {
|
|||
callback(error);
|
||||
} else {
|
||||
delete directoryData[name];
|
||||
context.put(directoryNode.data, directoryData, callback);
|
||||
context.put(directoryNode.data, directoryData, function(error) {
|
||||
var now = Date.now();
|
||||
update_node_times(context, parentPath, directoryNode, { mtime: now, ctime: now }, callback);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -900,7 +1019,9 @@ define(function(require) {
|
|||
if(fileNode.nlinks < 1) {
|
||||
context.delete(fileNode.id, delete_file_data);
|
||||
} else {
|
||||
context.put(fileNode.id, fileNode, update_directory_data);
|
||||
context.put(fileNode.id, fileNode, function(error) {
|
||||
update_node_times(context, path, fileNode, { ctime: Date.now() }, update_directory_data);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1004,12 +1125,21 @@ define(function(require) {
|
|||
context.put(fileNode.id, fileNode, update_directory_data);
|
||||
}
|
||||
|
||||
function update_time(error) {
|
||||
if(error) {
|
||||
callback(error);
|
||||
} else {
|
||||
var now = Date.now();
|
||||
update_node_times(context, parentPath, directoryNode, { mtime: now, ctime: now }, callback);
|
||||
}
|
||||
}
|
||||
|
||||
function update_directory_data(error) {
|
||||
if(error) {
|
||||
callback(error);
|
||||
} else {
|
||||
directoryData[name] = new DirectoryEntry(fileNode.id, MODE_SYMBOLIC_LINK);
|
||||
context.put(directoryNode.data, directoryData, callback);
|
||||
context.put(directoryNode.data, directoryData, update_time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1087,14 +1217,22 @@ define(function(require) {
|
|||
}
|
||||
}
|
||||
|
||||
function update_time(error) {
|
||||
if(error) {
|
||||
callback(error);
|
||||
} else {
|
||||
var now = Date.now();
|
||||
update_node_times(context, path, fileNode, { mtime: now, ctime: now }, callback);
|
||||
}
|
||||
}
|
||||
|
||||
function update_file_node (error) {
|
||||
if(error) {
|
||||
callback(error);
|
||||
} else {
|
||||
fileNode.size = length;
|
||||
fileNode.mtime = Date.now();
|
||||
fileNode.version += 1;
|
||||
context.put(fileNode.id, fileNode, callback);
|
||||
context.put(fileNode.id, fileNode, update_time);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1131,14 +1269,21 @@ define(function(require) {
|
|||
}
|
||||
}
|
||||
|
||||
function update_time(error) {
|
||||
if(error) {
|
||||
callback(error);
|
||||
} else {
|
||||
var now = Date.now();
|
||||
update_node_times(context, ofd.path, fileNode, { mtime: now, ctime: now }, callback);
|
||||
}
|
||||
}
|
||||
function update_file_node (error) {
|
||||
if(error) {
|
||||
callback(error);
|
||||
} else {
|
||||
fileNode.size = length;
|
||||
fileNode.mtime = Date.now();
|
||||
fileNode.version += 1;
|
||||
context.put(fileNode.id, fileNode, callback);
|
||||
context.put(fileNode.id, fileNode, update_time);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1152,14 +1297,11 @@ define(function(require) {
|
|||
function utimes_file(context, path, atime, mtime, callback) {
|
||||
path = normalize(path);
|
||||
|
||||
function update_times (error, node) {
|
||||
function update_times(error, node) {
|
||||
if (error) {
|
||||
callback(error);
|
||||
}
|
||||
else {
|
||||
node.atime = atime;
|
||||
node.mtime = mtime;
|
||||
context.put(node.id, node, callback);
|
||||
} else {
|
||||
update_node_times(context, path, node, { atime: atime, ctime: mtime, mtime: mtime }, callback);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1179,11 +1321,8 @@ define(function(require) {
|
|||
function update_times (error, node) {
|
||||
if (error) {
|
||||
callback(error);
|
||||
}
|
||||
else {
|
||||
node.atime = atime;
|
||||
node.mtime = mtime;
|
||||
context.put(node.id, node, callback);
|
||||
} else {
|
||||
update_node_times(context, ofd.path, node, { atime: atime, ctime: mtime, mtime: mtime }, callback);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1294,6 +1433,14 @@ define(function(require) {
|
|||
function remove_xattr (error, node) {
|
||||
var xattr = (node ? node.xattrs : null);
|
||||
|
||||
function update_time(error) {
|
||||
if(error) {
|
||||
callback(error);
|
||||
} else {
|
||||
update_node_times(context, path, node, { ctime: Date.now() }, callback);
|
||||
}
|
||||
}
|
||||
|
||||
if (error) {
|
||||
callback(error);
|
||||
}
|
||||
|
@ -1302,7 +1449,7 @@ define(function(require) {
|
|||
}
|
||||
else {
|
||||
delete node.xattrs[name];
|
||||
context.put(node.id, node, callback);
|
||||
context.put(node.id, node, update_time);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1320,6 +1467,14 @@ define(function(require) {
|
|||
function fremovexattr_file (context, ofd, name, callback) {
|
||||
|
||||
function remove_xattr (error, node) {
|
||||
function update_time(error) {
|
||||
if(error) {
|
||||
callback(error);
|
||||
} else {
|
||||
update_node_times(context, ofd.path, node, { ctime: Date.now() }, callback);
|
||||
}
|
||||
}
|
||||
|
||||
if (error) {
|
||||
callback(error);
|
||||
}
|
||||
|
@ -1328,7 +1483,7 @@ define(function(require) {
|
|||
}
|
||||
else {
|
||||
delete node.xattrs[name];
|
||||
context.put(node.id, node, callback);
|
||||
context.put(node.id, node, update_time);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1361,11 +1516,16 @@ define(function(require) {
|
|||
return options;
|
||||
}
|
||||
|
||||
// nullCheck from https://github.com/joyent/node/blob/master/lib/fs.js
|
||||
function nullCheck(path, callback) {
|
||||
if (('' + path).indexOf('\u0000') !== -1) {
|
||||
var er = new Error('Path must be a string without null bytes.');
|
||||
callback(er);
|
||||
function pathCheck(path, callback) {
|
||||
var err;
|
||||
if(isNullPath(path)) {
|
||||
err = new Error('Path must be a string without null bytes.');
|
||||
} else if(!isAbsolutePath(path)) {
|
||||
err = new Error('Path must be absolute.');
|
||||
}
|
||||
|
||||
if(err) {
|
||||
callback(err);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -1464,7 +1624,21 @@ define(function(require) {
|
|||
// Open file system storage provider
|
||||
provider.open(function(err, needsFormatting) {
|
||||
function complete(error) {
|
||||
fs.provider = provider;
|
||||
// Wrap the provider so we can extend the context with fs flags.
|
||||
// From this point forward we won't call open again, so drop it.
|
||||
fs.provider = {
|
||||
getReadWriteContext: function() {
|
||||
var context = provider.getReadWriteContext();
|
||||
context.flags = flags;
|
||||
return context;
|
||||
},
|
||||
getReadOnlyContext: function() {
|
||||
var context = provider.getReadOnlyContext();
|
||||
context.flags = flags;
|
||||
return context;
|
||||
}
|
||||
};
|
||||
|
||||
if(error) {
|
||||
fs.readyState = FS_ERROR;
|
||||
} else {
|
||||
|
@ -1501,7 +1675,7 @@ define(function(require) {
|
|||
FileSystem.adapters = adapters;
|
||||
|
||||
function _open(fs, context, path, flags, callback) {
|
||||
if(!nullCheck(path, callback)) return;
|
||||
if(!pathCheck(path, callback)) return;
|
||||
|
||||
function check_result(error, fileNode) {
|
||||
if(error) {
|
||||
|
@ -1513,7 +1687,7 @@ define(function(require) {
|
|||
} else {
|
||||
position = 0;
|
||||
}
|
||||
var openFileDescription = new OpenFileDescription(fileNode.id, flags, position);
|
||||
var openFileDescription = new OpenFileDescription(path, fileNode.id, flags, position);
|
||||
var fd = fs.allocDescriptor(openFileDescription);
|
||||
callback(null, fd);
|
||||
}
|
||||
|
@ -1537,7 +1711,7 @@ define(function(require) {
|
|||
}
|
||||
|
||||
function _mkdir(context, path, callback) {
|
||||
if(!nullCheck(path, callback)) return;
|
||||
if(!pathCheck(path, callback)) return;
|
||||
|
||||
function check_result(error) {
|
||||
if(error) {
|
||||
|
@ -1551,7 +1725,7 @@ define(function(require) {
|
|||
}
|
||||
|
||||
function _rmdir(context, path, callback) {
|
||||
if(!nullCheck(path, callback)) return;
|
||||
if(!pathCheck(path, callback)) return;
|
||||
|
||||
function check_result(error) {
|
||||
if(error) {
|
||||
|
@ -1565,7 +1739,7 @@ define(function(require) {
|
|||
}
|
||||
|
||||
function _stat(context, name, path, callback) {
|
||||
if(!nullCheck(path, callback)) return;
|
||||
if(!pathCheck(path, callback)) return;
|
||||
|
||||
function check_result(error, result) {
|
||||
if(error) {
|
||||
|
@ -1599,8 +1773,8 @@ define(function(require) {
|
|||
}
|
||||
|
||||
function _link(context, oldpath, newpath, callback) {
|
||||
if(!nullCheck(oldpath, callback)) return;
|
||||
if(!nullCheck(newpath, callback)) return;
|
||||
if(!pathCheck(oldpath, callback)) return;
|
||||
if(!pathCheck(newpath, callback)) return;
|
||||
|
||||
function check_result(error) {
|
||||
if(error) {
|
||||
|
@ -1614,7 +1788,7 @@ define(function(require) {
|
|||
}
|
||||
|
||||
function _unlink(context, path, callback) {
|
||||
if(!nullCheck(path, callback)) return;
|
||||
if(!pathCheck(path, callback)) return;
|
||||
|
||||
function check_result(error) {
|
||||
if(error) {
|
||||
|
@ -1653,7 +1827,7 @@ define(function(require) {
|
|||
function _readFile(fs, context, path, options, callback) {
|
||||
options = validate_file_options(options, null, 'r');
|
||||
|
||||
if(!nullCheck(path, callback)) return;
|
||||
if(!pathCheck(path, callback)) return;
|
||||
|
||||
var flags = validate_flags(options.flag || 'r');
|
||||
if(!flags) {
|
||||
|
@ -1664,7 +1838,7 @@ define(function(require) {
|
|||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
var ofd = new OpenFileDescription(fileNode.id, flags, 0);
|
||||
var ofd = new OpenFileDescription(path, fileNode.id, flags, 0);
|
||||
var fd = fs.allocDescriptor(ofd);
|
||||
|
||||
fstat_file(context, ofd, function(err2, fstatResult) {
|
||||
|
@ -1722,7 +1896,7 @@ define(function(require) {
|
|||
function _writeFile(fs, context, path, data, options, callback) {
|
||||
options = validate_file_options(options, 'utf8', 'w');
|
||||
|
||||
if(!nullCheck(path, callback)) return;
|
||||
if(!pathCheck(path, callback)) return;
|
||||
|
||||
var flags = validate_flags(options.flag || 'w');
|
||||
if(!flags) {
|
||||
|
@ -1741,7 +1915,7 @@ define(function(require) {
|
|||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
var ofd = new OpenFileDescription(fileNode.id, flags, 0);
|
||||
var ofd = new OpenFileDescription(path, fileNode.id, flags, 0);
|
||||
var fd = fs.allocDescriptor(ofd);
|
||||
|
||||
replace_data(context, ofd, data, 0, data.length, function(err2, nbytes) {
|
||||
|
@ -1757,7 +1931,7 @@ define(function(require) {
|
|||
function _appendFile(fs, context, path, data, options, callback) {
|
||||
options = validate_file_options(options, 'utf8', 'a');
|
||||
|
||||
if(!nullCheck(path, callback)) return;
|
||||
if(!pathCheck(path, callback)) return;
|
||||
|
||||
var flags = validate_flags(options.flag || 'a');
|
||||
if(!flags) {
|
||||
|
@ -1776,7 +1950,7 @@ define(function(require) {
|
|||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
var ofd = new OpenFileDescription(fileNode.id, flags, fileNode.size);
|
||||
var ofd = new OpenFileDescription(path, fileNode.id, flags, fileNode.size);
|
||||
var fd = fs.allocDescriptor(ofd);
|
||||
|
||||
write_data(context, ofd, data, 0, data.length, ofd.position, function(err2, nbytes) {
|
||||
|
@ -1789,8 +1963,15 @@ define(function(require) {
|
|||
});
|
||||
}
|
||||
|
||||
function _exists (context, name, path, callback) {
|
||||
function cb(err, stats) {
|
||||
callback(err ? false : true);
|
||||
}
|
||||
_stat(context, name, path, cb);
|
||||
}
|
||||
|
||||
function _getxattr (context, path, name, callback) {
|
||||
if (!nullCheck(path, callback)) return;
|
||||
if (!pathCheck(path, callback)) return;
|
||||
|
||||
function fetch_value (error, value) {
|
||||
if (error) {
|
||||
|
@ -1826,7 +2007,7 @@ define(function(require) {
|
|||
}
|
||||
|
||||
function _setxattr (context, path, name, value, flag, callback) {
|
||||
if (!nullCheck(path, callback)) return;
|
||||
if (!pathCheck(path, callback)) return;
|
||||
|
||||
function check_result (error) {
|
||||
if (error) {
|
||||
|
@ -1864,7 +2045,7 @@ define(function(require) {
|
|||
}
|
||||
|
||||
function _removexattr (context, path, name, callback) {
|
||||
if (!nullCheck(path, callback)) return;
|
||||
if (!pathCheck(path, callback)) return;
|
||||
|
||||
function remove_xattr (error) {
|
||||
if (error) {
|
||||
|
@ -1952,7 +2133,7 @@ define(function(require) {
|
|||
}
|
||||
|
||||
function _readdir(context, path, callback) {
|
||||
if(!nullCheck(path, callback)) return;
|
||||
if(!pathCheck(path, callback)) return;
|
||||
|
||||
function check_result(error, files) {
|
||||
if(error) {
|
||||
|
@ -1966,7 +2147,7 @@ define(function(require) {
|
|||
}
|
||||
|
||||
function _utimes(context, path, atime, mtime, callback) {
|
||||
if(!nullCheck(path, callback)) return;
|
||||
if(!pathCheck(path, callback)) return;
|
||||
|
||||
var currentTime = Date.now();
|
||||
atime = (atime) ? atime : currentTime;
|
||||
|
@ -2009,8 +2190,8 @@ define(function(require) {
|
|||
}
|
||||
|
||||
function _rename(context, oldpath, newpath, callback) {
|
||||
if(!nullCheck(oldpath, callback)) return;
|
||||
if(!nullCheck(newpath, callback)) return;
|
||||
if(!pathCheck(oldpath, callback)) return;
|
||||
if(!pathCheck(newpath, callback)) return;
|
||||
|
||||
function check_result(error) {
|
||||
if(error) {
|
||||
|
@ -2032,8 +2213,8 @@ define(function(require) {
|
|||
}
|
||||
|
||||
function _symlink(context, srcpath, dstpath, callback) {
|
||||
if(!nullCheck(srcpath, callback)) return;
|
||||
if(!nullCheck(dstpath, callback)) return;
|
||||
if(!pathCheck(srcpath, callback)) return;
|
||||
if(!pathCheck(dstpath, callback)) return;
|
||||
|
||||
function check_result(error) {
|
||||
if(error) {
|
||||
|
@ -2047,7 +2228,7 @@ define(function(require) {
|
|||
}
|
||||
|
||||
function _readlink(context, path, callback) {
|
||||
if(!nullCheck(path, callback)) return;
|
||||
if(!pathCheck(path, callback)) return;
|
||||
|
||||
function check_result(error, result) {
|
||||
if(error) {
|
||||
|
@ -2065,7 +2246,7 @@ define(function(require) {
|
|||
}
|
||||
|
||||
function _lstat(fs, context, path, callback) {
|
||||
if(!nullCheck(path, callback)) return;
|
||||
if(!pathCheck(path, callback)) return;
|
||||
|
||||
function check_result(error, result) {
|
||||
if(error) {
|
||||
|
@ -2080,7 +2261,7 @@ define(function(require) {
|
|||
}
|
||||
|
||||
function _truncate(context, path, length, callback) {
|
||||
if(!nullCheck(path, callback)) return;
|
||||
if(!pathCheck(path, callback)) return;
|
||||
|
||||
function check_result(error) {
|
||||
if(error) {
|
||||
|
@ -2265,6 +2446,17 @@ define(function(require) {
|
|||
);
|
||||
if(error) callback(error);
|
||||
};
|
||||
FileSystem.prototype.exists = function(path, callback_) {
|
||||
var callback = maybeCallback(arguments[arguments.length - 1]);
|
||||
var fs = this;
|
||||
var error = fs.queueOrRun(
|
||||
function() {
|
||||
var context = fs.provider.getReadWriteContext();
|
||||
_exists(context, fs.name, path, callback);
|
||||
}
|
||||
);
|
||||
if(error) callback(error);
|
||||
};
|
||||
FileSystem.prototype.lseek = function(fd, offset, whence, callback) {
|
||||
callback = maybeCallback(callback);
|
||||
var fs = this;
|
||||
|
|
18
src/path.js
18
src/path.js
|
@ -193,6 +193,20 @@ define(function() {
|
|||
return splitPath(path)[3];
|
||||
}
|
||||
|
||||
function isAbsolute(path) {
|
||||
if(path.charAt(0) === '/') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isNull(path) {
|
||||
if (('' + path).indexOf('\u0000') !== -1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// XXXidbfs: we don't support path.exists() or path.existsSync(), which
|
||||
// are deprecated, and need a FileSystem instance to work. Use fs.stat().
|
||||
|
||||
|
@ -205,7 +219,9 @@ define(function() {
|
|||
delimiter: ':',
|
||||
dirname: dirname,
|
||||
basename: basename,
|
||||
extname: extname
|
||||
extname: extname,
|
||||
isAbsolute: isAbsolute,
|
||||
isNull: isNull
|
||||
};
|
||||
|
||||
});
|
||||
|
|
|
@ -116,7 +116,10 @@ define(function(require) {
|
|||
};
|
||||
};
|
||||
IndexedDB.prototype.getReadOnlyContext = function() {
|
||||
return new IndexedDBContext(this.db, IDB_RO);
|
||||
// Due to timing issues in Chrome with readwrite vs. readonly indexeddb transactions
|
||||
// always use readwrite so we can make sure pending commits finish before callbacks.
|
||||
// See https://github.com/js-platform/filer/issues/128
|
||||
return new IndexedDBContext(this.db, IDB_RW);
|
||||
};
|
||||
IndexedDB.prototype.getReadWriteContext = function() {
|
||||
return new IndexedDBContext(this.db, IDB_RW);
|
||||
|
|
|
@ -4,6 +4,7 @@ define(function(require) {
|
|||
var WSQL_VERSION = require('../constants').WSQL_VERSION;
|
||||
var WSQL_SIZE = require('../constants').WSQL_SIZE;
|
||||
var WSQL_DESC = require('../constants').WSQL_DESC;
|
||||
var u8toArray = require('../shared').u8toArray;
|
||||
|
||||
function WebSQLContext(db, isReadOnly) {
|
||||
var that = this;
|
||||
|
@ -27,7 +28,7 @@ define(function(require) {
|
|||
callback(null);
|
||||
}
|
||||
this.getTransaction(function(transaction) {
|
||||
transaction.executeSql("DELETE FROM " + FILE_STORE_NAME,
|
||||
transaction.executeSql("DELETE FROM " + FILE_STORE_NAME + ";",
|
||||
[], onSuccess, onError);
|
||||
});
|
||||
};
|
||||
|
@ -35,17 +36,37 @@ define(function(require) {
|
|||
function onSuccess(transaction, result) {
|
||||
// If the key isn't found, return null
|
||||
var value = result.rows.length === 0 ? null : result.rows.item(0).data;
|
||||
callback(null, value);
|
||||
try {
|
||||
if(value) {
|
||||
value = JSON.parse(value);
|
||||
// Deal with special-cased flattened typed arrays in WebSQL (see put() below)
|
||||
if(value.__isUint8Array) {
|
||||
value = new Uint8Array(value.__array);
|
||||
}
|
||||
}
|
||||
callback(null, value);
|
||||
} catch(e) {
|
||||
callback(e);
|
||||
}
|
||||
}
|
||||
function onError(transaction, error) {
|
||||
callback(error);
|
||||
}
|
||||
this.getTransaction(function(transaction) {
|
||||
transaction.executeSql("SELECT data FROM " + FILE_STORE_NAME + " WHERE id = ?",
|
||||
transaction.executeSql("SELECT data FROM " + FILE_STORE_NAME + " WHERE id = ?;",
|
||||
[key], onSuccess, onError);
|
||||
});
|
||||
};
|
||||
WebSQLContext.prototype.put = function(key, value, callback) {
|
||||
// We do extra work to make sure typed arrays survive
|
||||
// being stored in the db and still get the right prototype later.
|
||||
if(Object.prototype.toString.call(value) === "[object Uint8Array]") {
|
||||
value = {
|
||||
__isUint8Array: true,
|
||||
__array: u8toArray(value)
|
||||
};
|
||||
}
|
||||
value = JSON.stringify(value);
|
||||
function onSuccess(transaction, result) {
|
||||
callback(null);
|
||||
}
|
||||
|
@ -53,7 +74,7 @@ define(function(require) {
|
|||
callback(error);
|
||||
}
|
||||
this.getTransaction(function(transaction) {
|
||||
transaction.executeSql("INSERT OR REPLACE INTO " + FILE_STORE_NAME + " (id, data) VALUES (?, ?)",
|
||||
transaction.executeSql("INSERT OR REPLACE INTO " + FILE_STORE_NAME + " (id, data) VALUES (?, ?);",
|
||||
[key, value], onSuccess, onError);
|
||||
});
|
||||
};
|
||||
|
@ -65,7 +86,7 @@ define(function(require) {
|
|||
callback(error);
|
||||
}
|
||||
this.getTransaction(function(transaction) {
|
||||
transaction.executeSql("DELETE FROM " + FILE_STORE_NAME + " WHERE id = ?",
|
||||
transaction.executeSql("DELETE FROM " + FILE_STORE_NAME + " WHERE id = ?;",
|
||||
[key], onSuccess, onError);
|
||||
});
|
||||
};
|
||||
|
@ -113,9 +134,15 @@ define(function(require) {
|
|||
[], gotCount, onError);
|
||||
}
|
||||
|
||||
// Create the table and index we'll need to store the fs data.
|
||||
db.transaction(function(transaction) {
|
||||
transaction.executeSql("CREATE TABLE IF NOT EXISTS " + FILE_STORE_NAME + " (id unique, data)",
|
||||
[], onSuccess, onError);
|
||||
function createIndex(transaction) {
|
||||
transaction.executeSql("CREATE INDEX IF NOT EXISTS idx_" + FILE_STORE_NAME + "_id" +
|
||||
" on " + FILE_STORE_NAME + " (id);",
|
||||
[], onSuccess, onError);
|
||||
}
|
||||
transaction.executeSql("CREATE TABLE IF NOT EXISTS " + FILE_STORE_NAME + " (id unique, data TEXT);",
|
||||
[], createIndex, onError);
|
||||
});
|
||||
};
|
||||
WebSQL.prototype.getReadOnlyContext = function() {
|
||||
|
|
|
@ -15,9 +15,22 @@ define(function(require) {
|
|||
|
||||
function nop() {}
|
||||
|
||||
/**
|
||||
* Convert a Uint8Array to a regular array
|
||||
*/
|
||||
function u8toArray(u8) {
|
||||
var array = [];
|
||||
var len = u8.length;
|
||||
for(var i = 0; i < len; i++) {
|
||||
array[i] = u8[i];
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
return {
|
||||
guid: guid,
|
||||
hash: hash,
|
||||
u8toArray: u8toArray,
|
||||
nop: nop
|
||||
};
|
||||
|
||||
|
|
|
@ -78,8 +78,9 @@ require.config(config);
|
|||
assert = chai.assert;
|
||||
expect = chai.expect;
|
||||
|
||||
// We need to setup describe() support before loading tests
|
||||
mocha.setup("bdd");
|
||||
// We need to setup describe() support before loading tests.
|
||||
// Use a test timeout of 5s and a slow-test warning of 250ms
|
||||
mocha.setup("bdd").timeout(5000).slow(250);
|
||||
|
||||
require(["tests/test-manifest"], function() {
|
||||
window.onload = function() {
|
||||
|
|
|
@ -3,7 +3,7 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
// We reuse the same set of tests for all adapters.
|
||||
// buildTestsFor() creates a set of tests bound to an
|
||||
// adapter, and uses the provider set on the query string
|
||||
// (defaults to Memory, see test-utils.js).
|
||||
// (defaults to best available/supported provider, see test-utils.js).
|
||||
function buildTestsFor(adapterName, buildAdapter) {
|
||||
function encode(str) {
|
||||
// TextEncoder is either native, or shimmed by Filer
|
||||
|
@ -38,7 +38,7 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
});
|
||||
});
|
||||
|
||||
describe("open a Memory provider with an " + adapterName + " adapter", function() {
|
||||
describe("open a provider with an " + adapterName + " adapter", function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
|
@ -46,13 +46,17 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
var provider = createProvider();
|
||||
provider.open(function(error, firstAccess) {
|
||||
expect(error).not.to.exist;
|
||||
expect(firstAccess).to.be.true;
|
||||
// NOTE: we test firstAccess logic in the individual provider tests
|
||||
// (see tests/spec/providers/*) but can't easily/actually test it here,
|
||||
// since the provider-agnostic code in test-utils pre-creates a
|
||||
// FileSystem object, thus eating the first access info.
|
||||
// See https://github.com/js-platform/filer/issues/127
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("Read/Write operations on a Memory provider with an " + adapterName + " adapter", function() {
|
||||
describe("Read/Write operations on a provider with an " + adapterName + " adapter", function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
|
@ -127,7 +131,13 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
});
|
||||
});
|
||||
|
||||
it("should fail when trying to write on ReadOnlyContext", function(done) {
|
||||
/**
|
||||
* With issue 123 (see https://github.com/js-platform/filer/issues/128) we had to
|
||||
* start using readwrite contexts everywhere with IndexedDB. As such, we can't
|
||||
* easily test this here, without knowing which provider we have. We test this
|
||||
* in the actual providers, so this isn't really needed. Skipping for now.
|
||||
*/
|
||||
it.skip("should fail when trying to write on ReadOnlyContext", function(done) {
|
||||
var provider = createProvider();
|
||||
provider.open(function(error, firstAccess) {
|
||||
if(error) throw error;
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
define(["Filer", "util"], function(Filer, util) {
|
||||
|
||||
describe('fs.exists', function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('should be a function', function() {
|
||||
var fs = util.fs();
|
||||
expect(typeof fs.exists).to.equal('function');
|
||||
});
|
||||
|
||||
it('should return false if path does not exist', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.exists('/tmp', function(result) {
|
||||
expect(result).to.be.false;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return true if path exists', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.open('/myfile', 'w', function(err, fd) {
|
||||
if(err) throw err;
|
||||
|
||||
fs.close(fd, function(err) {
|
||||
if(err) throw err;
|
||||
|
||||
fs.exists('/myfile', function(result) {
|
||||
expect(result).to.be.true;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should follow symbolic links and return true for the resulting path', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.open('/myfile', 'w', function(error, fd) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.close(fd, function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.symlink('/myfile', '/myfilelink', function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.exists('/myfilelink', function(result) {
|
||||
expect(result).to.be.true;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -28,7 +28,10 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
fs.stat('/myotherfile', function(error, result) {
|
||||
expect(error).not.to.exist;
|
||||
expect(result.nlinks).to.equal(2);
|
||||
expect(result).to.deep.equal(_oldstats);
|
||||
expect(result.dev).to.equal(_oldstats.dev);
|
||||
expect(result.node).to.equal(_oldstats.node);
|
||||
expect(result.size).to.equal(_oldstats.size);
|
||||
expect(result.type).to.equal(_oldstats.type);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -52,7 +55,10 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
var _linkstats = result;
|
||||
fs.lstat('/myotherfile', function (error, result) {
|
||||
expect(error).not.to.exist;
|
||||
expect(result).to.deep.equal(_linkstats);
|
||||
expect(result.dev).to.equal(_linkstats.dev);
|
||||
expect(result.node).to.equal(_linkstats.node);
|
||||
expect(result.size).to.equal(_linkstats.size);
|
||||
expect(result.type).to.equal(_linkstats.type);
|
||||
expect(result.nlinks).to.equal(2);
|
||||
done();
|
||||
});
|
||||
|
|
|
@ -17,7 +17,7 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
|
||||
fs.utimes('/testfile', -1, Date.now(), function (error) {
|
||||
expect(error).to.exist;
|
||||
expect(error.name).to.equal('EInvalid');
|
||||
expect(error.code).to.equal('EINVAL');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -31,7 +31,7 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
|
||||
fs.utimes('/testfile', Date.now(), -1, function (error) {
|
||||
expect(error).to.exist;
|
||||
expect(error.name).to.equal('EInvalid');
|
||||
expect(error.code).to.equal('EINVAL');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -45,7 +45,7 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
|
||||
fs.utimes('/testfile', 'invalid datetime', Date.now(), function (error) {
|
||||
expect(error).to.exist;
|
||||
expect(error.name).to.equal('EInvalid');
|
||||
expect(error.code).to.equal('EINVAL');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -58,7 +58,7 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
|
||||
fs.utimes('/pathdoesnotexist', atime, mtime, function (error) {
|
||||
expect(error).to.exist;
|
||||
expect(error.name).to.equal('ENoEntry');
|
||||
expect(error.code).to.equal('ENOENT');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -71,7 +71,7 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
|
||||
fs.utimes('/testfile', Date.now(), 'invalid datetime', function (error) {
|
||||
expect(error).to.exist;
|
||||
expect(error.name).to.equal('EInvalid');
|
||||
expect(error.code).to.equal('EINVAL');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -84,7 +84,7 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
|
||||
fs.futimes(1, atime, mtime, function (error) {
|
||||
expect(error).to.exist;
|
||||
expect(error.name).to.equal('EBadFileDescriptor');
|
||||
expect(error.code).to.equal('EBADF');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -102,7 +102,6 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
|
||||
fs.stat('/testfile', function (error, stat) {
|
||||
expect(error).not.to.exist;
|
||||
expect(stat.atime).to.equal(atime);
|
||||
expect(stat.mtime).to.equal(mtime);
|
||||
done();
|
||||
});
|
||||
|
@ -125,7 +124,6 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
|
||||
fs.fstat(ofd, function (error, stat) {
|
||||
expect(error).not.to.exist;
|
||||
expect(stat.atime).to.equal(atime);
|
||||
expect(stat.mtime).to.equal(mtime);
|
||||
done();
|
||||
});
|
||||
|
@ -146,7 +144,6 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
|
||||
fs.stat('/testdir', function (error, stat) {
|
||||
expect(error).not.to.exist;
|
||||
expect(stat.atime).to.equal(atime);
|
||||
expect(stat.mtime).to.equal(mtime);
|
||||
done();
|
||||
});
|
||||
|
@ -158,22 +155,21 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
var fs = util.fs();
|
||||
var atimeEst;
|
||||
var mtimeEst;
|
||||
var now;
|
||||
|
||||
fs.writeFile('/myfile', '', function (error) {
|
||||
if (error) throw error;
|
||||
|
||||
var then = Date.now();
|
||||
fs.utimes('/myfile', null, null, function (error) {
|
||||
expect(error).not.to.exist;
|
||||
|
||||
now = Date.now();
|
||||
|
||||
fs.stat('/myfile', function (error, stat) {
|
||||
expect(error).not.to.exist;
|
||||
// Note: testing estimation as time may differ by a couple of milliseconds
|
||||
// This number should be increased if tests are on slow systems
|
||||
expect(now - stat.atime).to.be.below(75);
|
||||
expect(now - stat.mtime).to.be.below(75);
|
||||
var delta = Date.now() - then;
|
||||
expect(then - stat.atime).to.be.below(delta);
|
||||
expect(then - stat.mtime).to.be.below(delta);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -21,7 +21,7 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
|
||||
fs.setxattr('/testfile', 89, 'testvalue', function (error) {
|
||||
expect(error).to.exist;
|
||||
expect(error.name).to.equal('EInvalid');
|
||||
expect(error.code).to.equal('EINVAL');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -35,7 +35,7 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
|
||||
fs.setxattr('/testfile', null, 'testvalue', function (error) {
|
||||
expect(error).to.exist;
|
||||
expect(error.name).to.equal('EInvalid');
|
||||
expect(error.code).to.equal('EINVAL');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -49,7 +49,7 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
|
||||
fs.setxattr('/testfile', 'test', 'value', 'InvalidFlag', function (error) {
|
||||
expect(error).to.exist;
|
||||
expect(error.name).to.equal('EInvalid');
|
||||
expect(error.code).to.equal('EINVAL');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -66,7 +66,7 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
|
||||
fs.setxattr('/testfile', 'test', 'othervalue', 'CREATE', function(error) {
|
||||
expect(error).to.exist;
|
||||
expect(error.name).to.equal('EExists');
|
||||
expect(error.code).to.equal('EEXIST');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -81,7 +81,7 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
|
||||
fs.setxattr('/testfile', 'test', 'value', 'REPLACE', function(error) {
|
||||
expect(error).to.exist;
|
||||
expect(error.name).to.equal('ENoAttr');
|
||||
expect(error.code).to.equal('ENoAttr');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -95,7 +95,7 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
|
||||
fs.getxattr('/testfile', '', function(error, value) {
|
||||
expect(error).to.exist;
|
||||
expect(error.name).to.equal('EInvalid');
|
||||
expect(error.code).to.equal('EINVAL');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -109,7 +109,7 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
|
||||
fs.getxattr('/testfile', 89, function(error, value) {
|
||||
expect(error).to.exist;
|
||||
expect(error.name).to.equal('EInvalid');
|
||||
expect(error.code).to.equal('EINVAL');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -123,7 +123,7 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
|
||||
fs.getxattr('/testfile', 'test', function(error, value) {
|
||||
expect(error).to.exist;
|
||||
expect(error.name).to.equal('ENoAttr');
|
||||
expect(error.code).to.equal('ENoAttr');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -144,14 +144,14 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
|
||||
fs.fsetxattr(1, 'test', 'value', function(error) {
|
||||
expect(error).to.exist;
|
||||
expect(error.name).to.equal('EBadFileDescriptor');
|
||||
expect(error.code).to.equal('EBADF');
|
||||
completeSet = true;
|
||||
maybeDone();
|
||||
});
|
||||
|
||||
fs.fgetxattr(1, 'test', function(error, value) {
|
||||
expect(error).to.exist;
|
||||
expect(error.name).to.equal('EBadFileDescriptor');
|
||||
expect(error.code).to.equal('EBADF');
|
||||
expect(value).not.to.exist;
|
||||
completeGet = true;
|
||||
maybeDone();
|
||||
|
@ -159,7 +159,7 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
|
||||
fs.fremovexattr(1, 'test', function(error, value) {
|
||||
expect(error).to.exist;
|
||||
expect(error.name).to.equal('EBadFileDescriptor');
|
||||
expect(error.code).to.equal('EBADF');
|
||||
completeRemove = true;
|
||||
maybeDone();
|
||||
});
|
||||
|
@ -195,7 +195,7 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
|
||||
fs.removexattr('/testfile', 'testenoattr', function (error) {
|
||||
expect(error).to.exist;
|
||||
expect(error.name).to.equal('ENoAttr');
|
||||
expect(error.code).to.equal('ENoAttr');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -336,7 +336,7 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
|
||||
fs.getxattr('/testfile', 'test', function (error) {
|
||||
expect(error).to.exist;
|
||||
expect(error.name).to.equal('ENoAttr');
|
||||
expect(error.code).to.equal('ENoAttr');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -363,7 +363,7 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
|
||||
fs.fgetxattr(ofd, 'test', function (error) {
|
||||
expect(error).to.exist;
|
||||
expect(error.name).to.equal('ENoAttr');
|
||||
expect(error.code).to.equal('ENoAttr');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -29,30 +29,30 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
fn.apply(fs, args);
|
||||
}
|
||||
|
||||
check(fs.link, 'foo\u0000bar', 'foobar');
|
||||
check(fs.link, 'foobar', 'foo\u0000bar');
|
||||
check(fs.lstat, 'foo\u0000bar');
|
||||
check(fs.mkdir, 'foo\u0000bar', '0755');
|
||||
check(fs.open, 'foo\u0000bar', 'r');
|
||||
check(fs.readFile, 'foo\u0000bar');
|
||||
check(fs.readdir, 'foo\u0000bar');
|
||||
check(fs.readlink, 'foo\u0000bar');
|
||||
check(fs.rename, 'foo\u0000bar', 'foobar');
|
||||
check(fs.rename, 'foobar', 'foo\u0000bar');
|
||||
check(fs.rmdir, 'foo\u0000bar');
|
||||
check(fs.stat, 'foo\u0000bar');
|
||||
check(fs.symlink, 'foo\u0000bar', 'foobar');
|
||||
check(fs.symlink, 'foobar', 'foo\u0000bar');
|
||||
check(fs.unlink, 'foo\u0000bar');
|
||||
check(fs.writeFile, 'foo\u0000bar');
|
||||
check(fs.appendFile, 'foo\u0000bar');
|
||||
check(fs.truncate, 'foo\u0000bar');
|
||||
check(fs.utimes, 'foo\u0000bar', 0, 0);
|
||||
check(fs.link, '/foo\u0000bar', 'foobar');
|
||||
check(fs.link, '/foobar', 'foo\u0000bar');
|
||||
check(fs.lstat, '/foo\u0000bar');
|
||||
check(fs.mkdir, '/foo\u0000bar', '0755');
|
||||
check(fs.open, '/foo\u0000bar', 'r');
|
||||
check(fs.readFile, '/foo\u0000bar');
|
||||
check(fs.readdir, '/foo\u0000bar');
|
||||
check(fs.readlink, '/foo\u0000bar');
|
||||
check(fs.rename, '/foo\u0000bar', 'foobar');
|
||||
check(fs.rename, '/foobar', 'foo\u0000bar');
|
||||
check(fs.rmdir, '/foo\u0000bar');
|
||||
check(fs.stat, '/foo\u0000bar');
|
||||
check(fs.symlink, '/foo\u0000bar', 'foobar');
|
||||
check(fs.symlink, '/foobar', 'foo\u0000bar');
|
||||
check(fs.unlink, '/foo\u0000bar');
|
||||
check(fs.writeFile, '/foo\u0000bar');
|
||||
check(fs.appendFile, '/foo\u0000bar');
|
||||
check(fs.truncate, '/foo\u0000bar');
|
||||
check(fs.utimes, '/foo\u0000bar', 0, 0);
|
||||
// TODO - need to be implemented still...
|
||||
// check(fs.realpath, 'foo\u0000bar');
|
||||
// check(fs.chmod, 'foo\u0000bar', '0644');
|
||||
// check(fs.chown, 'foo\u0000bar', 12, 34);
|
||||
// check(fs.realpath, 'foo\u0000bar');
|
||||
// check(fs.realpath, '/foo\u0000bar');
|
||||
// check(fs.chmod, '/foo\u0000bar', '0644');
|
||||
// check(fs.chown, '/foo\u0000bar', 12, 34);
|
||||
// check(fs.realpath, '/foo\u0000bar');
|
||||
|
||||
checks.forEach(function(fn){
|
||||
fn();
|
||||
|
|
|
@ -149,7 +149,7 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
createSymlinkChain(1, function() {
|
||||
fs.stat('/myfile11', function(error, result) {
|
||||
expect(error).to.exist;
|
||||
expect(error.name).to.equal('ELoop');
|
||||
expect(error.code).to.equal('ELOOP');
|
||||
expect(result).not.to.exist;
|
||||
done();
|
||||
});
|
||||
|
|
|
@ -129,7 +129,11 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
});
|
||||
});
|
||||
|
||||
it("should fail when trying to write on ReadOnlyContext", function(done) {
|
||||
/**
|
||||
* With issue 123 (see https://github.com/js-platform/filer/issues/128) we had to
|
||||
* start using readwrite contexts everywhere with IndexedDB. Skipping for now.
|
||||
*/
|
||||
it.skip("should fail when trying to write on ReadOnlyContext", function(done) {
|
||||
var provider = _provider.provider;
|
||||
provider.open(function(error, firstAccess) {
|
||||
if(error) throw error;
|
||||
|
|
|
@ -40,7 +40,7 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
expect(shell.pwd()).to.equal('/');
|
||||
shell.cd('/nodir', function(err) {
|
||||
expect(err).to.exist;
|
||||
expect(err.name).to.equal('ENotDirectory');
|
||||
expect(err.code).to.equal('ENOTDIR');
|
||||
expect(shell.pwd()).to.equal('/');
|
||||
done();
|
||||
});
|
||||
|
@ -57,7 +57,7 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
expect(shell.pwd()).to.equal('/');
|
||||
shell.cd('/file', function(err) {
|
||||
expect(err).to.exist;
|
||||
expect(err.name).to.equal('ENotDirectory');
|
||||
expect(err.code).to.equal('ENOTDIR');
|
||||
expect(shell.pwd()).to.equal('/');
|
||||
done();
|
||||
});
|
||||
|
|
|
@ -71,7 +71,7 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
|
||||
shell.rm('/dir', function(err) {
|
||||
expect(err).to.exist;
|
||||
expect(err.name).to.equal('ENotEmpty');
|
||||
expect(err.code).to.equal('ENOTEMPTY');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -92,7 +92,6 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
|
||||
getTimes(fs, '/newfile', function(times) {
|
||||
expect(times.mtime).to.equal(date);
|
||||
expect(times.atime).to.equal(date);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
define(["Filer", "util"], function(Filer, util) {
|
||||
|
||||
describe('node times (atime, mtime, ctime) with mount flags', function() {
|
||||
|
||||
var dirname = "/dir";
|
||||
var filename = "/dir/file";
|
||||
|
||||
function memoryFS(flags, callback) {
|
||||
var name = util.uniqueName();
|
||||
var fs = new Filer.FileSystem({
|
||||
name: name,
|
||||
flags: flags || [],
|
||||
provider: new Filer.FileSystem.providers.Memory(name)
|
||||
}, callback);
|
||||
}
|
||||
|
||||
function createTree(fs, callback) {
|
||||
fs.mkdir(dirname, function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.open(filename, 'w', function(error, fd) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.close(fd, callback);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function stat(fs, path, callback) {
|
||||
fs.stat(path, function(error, stats) {
|
||||
if(error) throw error;
|
||||
|
||||
callback(stats);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* We test the actual time updates in times.spec.js, whereas these just test
|
||||
* the overrides with the mount flags. The particular fs methods called
|
||||
* are unimportant, but are known to affect the particular times being suppressed.
|
||||
*/
|
||||
|
||||
it('should not update ctime when calling fs.rename() with NOCTIME', function(done) {
|
||||
memoryFS(['NOCTIME'], function(error, fs) {
|
||||
var newfilename = filename + '1';
|
||||
|
||||
createTree(fs, function() {
|
||||
stat(fs, filename, function(stats1) {
|
||||
|
||||
fs.rename(filename, newfilename, function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
stat(fs, newfilename, function(stats2) {
|
||||
expect(stats2.ctime).to.equal(stats1.ctime);
|
||||
expect(stats2.mtime).to.equal(stats1.mtime);
|
||||
expect(stats2.atime).to.equal(stats1.atime);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should not update ctime, mtime, atime when calling fs.truncate() with NOCTIME, NOMTIME', function(done) {
|
||||
memoryFS(['NOCTIME', 'NOMTIME'], function(error, fs) {
|
||||
createTree(fs, function() {
|
||||
stat(fs, filename, function(stats1) {
|
||||
|
||||
fs.truncate(filename, 5, function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
stat(fs, filename, function(stats2) {
|
||||
expect(stats2.ctime).to.equal(stats1.ctime);
|
||||
expect(stats2.mtime).to.equal(stats1.mtime);
|
||||
expect(stats2.atime).to.equal(stats1.atime);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should not update mtime when calling fs.truncate() with NOMTIME', function(done) {
|
||||
memoryFS(['NOMTIME'], function(error, fs) {
|
||||
createTree(fs, function() {
|
||||
stat(fs, filename, function(stats1) {
|
||||
|
||||
fs.truncate(filename, 5, function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
stat(fs, filename, function(stats2) {
|
||||
expect(stats2.ctime).to.be.above(stats1.ctime);
|
||||
expect(stats2.mtime).to.equal(stats1.mtime);
|
||||
expect(stats2.atime).to.be.above(stats1.atime);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
|
@ -0,0 +1,622 @@
|
|||
define(["Filer", "util"], function(Filer, util) {
|
||||
|
||||
describe('node times (atime, mtime, ctime)', function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
var dirname = "/dir";
|
||||
var filename = "/dir/file";
|
||||
|
||||
function createTree(callback) {
|
||||
var fs = util.fs();
|
||||
fs.mkdir(dirname, function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.open(filename, 'w', function(error, fd) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.close(fd, callback);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function stat(path, callback) {
|
||||
var fs = util.fs();
|
||||
fs.stat(path, function(error, stats) {
|
||||
if(error) throw error;
|
||||
|
||||
callback(stats);
|
||||
});
|
||||
}
|
||||
|
||||
it('should update ctime when calling fs.rename()', function(done) {
|
||||
var fs = util.fs();
|
||||
var newfilename = filename + '1';
|
||||
|
||||
createTree(function() {
|
||||
stat(filename, function(stats1) {
|
||||
|
||||
fs.rename(filename, newfilename, function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
stat(newfilename, function(stats2) {
|
||||
expect(stats2.ctime).to.be.above(stats1.ctime);
|
||||
expect(stats2.mtime).to.equal(stats1.mtime);
|
||||
expect(stats2.atime).to.be.above(stats1.atime);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should update ctime, mtime, atime when calling fs.truncate()', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
stat(filename, function(stats1) {
|
||||
|
||||
fs.truncate(filename, 5, function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
stat(filename, function(stats2) {
|
||||
expect(stats2.ctime).to.be.above(stats1.ctime);
|
||||
expect(stats2.mtime).to.be.above(stats1.mtime);
|
||||
expect(stats2.atime).to.be.above(stats1.atime);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should update ctime, mtime, atime when calling fs.ftruncate()', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
stat(filename, function(stats1) {
|
||||
|
||||
fs.open(filename, 'w', function(error, fd) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.ftruncate(fd, 5, function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
stat(filename, function(stats2) {
|
||||
expect(stats2.ctime).to.be.above(stats1.ctime);
|
||||
expect(stats2.mtime).to.be.above(stats1.mtime);
|
||||
expect(stats2.atime).to.be.above(stats1.atime);
|
||||
|
||||
fs.close(fd, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should make no change when calling fs.stat()', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
stat(filename, function(stats1) {
|
||||
|
||||
fs.stat(filename, function(error, stats2) {
|
||||
if(error) throw error;
|
||||
|
||||
expect(stats2.ctime).to.equal(stats1.ctime);
|
||||
expect(stats2.mtime).to.equal(stats1.mtime);
|
||||
expect(stats2.atime).to.equal(stats1.atime);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should make no change when calling fs.fstat()', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
stat(filename, function(stats1) {
|
||||
|
||||
fs.open(filename, 'w', function(error, fd) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.fstat(fd, function(error, stats2) {
|
||||
if(error) throw error;
|
||||
|
||||
expect(stats2.ctime).to.equal(stats1.ctime);
|
||||
expect(stats2.mtime).to.equal(stats1.mtime);
|
||||
expect(stats2.atime).to.equal(stats1.atime);
|
||||
|
||||
fs.close(fd, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should make no change when calling fs.lstat()', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
fs.link(filename, '/link', function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
stat(filename, function(stats1) {
|
||||
fs.lstat('/link', function(error, stats2) {
|
||||
if(error) throw error;
|
||||
|
||||
expect(stats2.ctime).to.equal(stats1.ctime);
|
||||
expect(stats2.mtime).to.equal(stats1.mtime);
|
||||
expect(stats2.atime).to.equal(stats1.atime);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should make no change when calling fs.exists()', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
stat(filename, function(stats1) {
|
||||
|
||||
fs.exists(filename, function(exists) {
|
||||
expect(exists).to.be.true;
|
||||
|
||||
fs.stat(filename, function(error, stats2) {
|
||||
if(error) throw error;
|
||||
|
||||
expect(stats2.ctime).to.equal(stats1.ctime);
|
||||
expect(stats2.mtime).to.equal(stats1.mtime);
|
||||
expect(stats2.atime).to.equal(stats1.atime);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should update ctime, atime when calling fs.link()', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
stat(filename, function(stats1) {
|
||||
fs.link(filename, '/link', function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
stat(filename, function(stats2) {
|
||||
expect(stats2.ctime).to.be.above(stats1.ctime);
|
||||
expect(stats2.mtime).to.equal(stats1.mtime);
|
||||
expect(stats2.atime).to.be.above(stats1.atime);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should make no change when calling fs.symlink()', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
stat(filename, function(stats1) {
|
||||
fs.symlink(filename, '/link', function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
stat(filename, function(stats2) {
|
||||
expect(stats2.ctime).to.equal(stats1.ctime);
|
||||
expect(stats2.mtime).to.equal(stats1.mtime);
|
||||
expect(stats2.atime).to.equal(stats1.atime);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should make no change when calling fs.readlink()', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
fs.symlink(filename, '/link', function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
stat('/link', function(stats1) {
|
||||
fs.readlink('/link', function(error, contents) {
|
||||
if(error) throw error;
|
||||
expect(contents).to.equal(filename);
|
||||
|
||||
stat('/link', function(stats2) {
|
||||
expect(stats2.ctime).to.equal(stats1.ctime);
|
||||
expect(stats2.mtime).to.equal(stats1.mtime);
|
||||
expect(stats2.atime).to.equal(stats1.atime);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should update ctime, atime, mtime of parent dir when calling fs.unlink()', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
stat(dirname, function(stats1) {
|
||||
fs.unlink(filename, function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
stat(dirname, function(stats2) {
|
||||
expect(stats2.ctime).to.be.above(stats1.ctime);
|
||||
expect(stats2.mtime).to.be.above(stats1.mtime);
|
||||
expect(stats2.atime).to.be.above(stats1.atime);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should update ctime, atime, mtime of parent dir when calling fs.rmdir()', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
stat('/', function(stats1) {
|
||||
|
||||
fs.unlink(filename, function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.rmdir(dirname, function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
stat('/', function(stats2) {
|
||||
expect(stats2.ctime).to.be.above(stats1.ctime);
|
||||
expect(stats2.mtime).to.be.above(stats1.mtime);
|
||||
expect(stats2.atime).to.be.above(stats1.atime);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should update ctime, atime, mtime of parent dir when calling fs.mkdir()', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
stat('/', function(stats1) {
|
||||
|
||||
fs.mkdir('/a', function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
stat('/', function(stats2) {
|
||||
expect(stats2.ctime).to.be.above(stats1.ctime);
|
||||
expect(stats2.mtime).to.be.above(stats1.mtime);
|
||||
expect(stats2.atime).to.be.above(stats1.atime);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should make no change when calling fs.close()', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
fs.open(filename, 'w', function(error, fd) {
|
||||
if(error) throw error;
|
||||
|
||||
stat(filename, function(stats1) {
|
||||
fs.close(fd, function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
stat(filename, function(stats2) {
|
||||
expect(stats2.ctime).to.equal(stats1.ctime);
|
||||
expect(stats2.mtime).to.equal(stats1.mtime);
|
||||
expect(stats2.atime).to.equal(stats1.atime);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should make no change when calling fs.open()', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
stat(filename, function(stats1) {
|
||||
fs.open(filename, 'w', function(error, fd) {
|
||||
if(error) throw error;
|
||||
|
||||
stat(filename, function(stats2) {
|
||||
expect(stats2.ctime).to.equal(stats1.ctime);
|
||||
expect(stats2.mtime).to.equal(stats1.mtime);
|
||||
expect(stats2.atime).to.equal(stats1.atime);
|
||||
|
||||
fs.close(fd, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* fs.utimes and fs.futimes are tested elsewhere already, skipping
|
||||
*/
|
||||
|
||||
it('should update atime, ctime, mtime when calling fs.write()', function(done) {
|
||||
var fs = util.fs();
|
||||
var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
|
||||
createTree(function() {
|
||||
fs.open('/myfile', 'w', function(err, fd) {
|
||||
if(err) throw error;
|
||||
|
||||
stat('/myfile', function(stats1) {
|
||||
fs.write(fd, buffer, 0, buffer.length, 0, function(err, nbytes) {
|
||||
if(err) throw error;
|
||||
|
||||
fs.close(fd, function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
stat('/myfile', function(stats2) {
|
||||
expect(stats2.ctime).to.be.above(stats1.ctime);
|
||||
expect(stats2.mtime).to.be.above(stats1.mtime);
|
||||
expect(stats2.atime).to.be.above(stats1.atime);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should make no change when calling fs.read()', function(done) {
|
||||
var fs = util.fs();
|
||||
var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
|
||||
createTree(function() {
|
||||
fs.open('/myfile', 'w', function(err, fd) {
|
||||
if(err) throw err;
|
||||
|
||||
fs.write(fd, buffer, 0, buffer.length, 0, function(err, nbytes) {
|
||||
if(err) throw err;
|
||||
|
||||
fs.close(fd, function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.open('/myfile', 'r', function(error, fd) {
|
||||
if(error) throw error;
|
||||
|
||||
stat('/myfile', function(stats1) {
|
||||
var buffer2 = new Uint8Array(buffer.length);
|
||||
fs.read(fd, buffer2, 0, buffer2.length, 0, function(err, nbytes) {
|
||||
|
||||
fs.close(fd, function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
stat('/myfile', function(stats2) {
|
||||
expect(stats2.ctime).to.equal(stats1.ctime);
|
||||
expect(stats2.mtime).to.equal(stats1.mtime);
|
||||
expect(stats2.atime).to.equal(stats1.atime);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should make no change when calling fs.readFile()', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
stat(filename, function(stats1) {
|
||||
fs.readFile(filename, function(error, data) {
|
||||
if(error) throw error;
|
||||
|
||||
stat(filename, function(stats2) {
|
||||
expect(stats2.ctime).to.equal(stats1.ctime);
|
||||
expect(stats2.mtime).to.equal(stats1.mtime);
|
||||
expect(stats2.atime).to.equal(stats1.atime);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should update atime, ctime, mtime when calling fs.writeFile()', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
stat(filename, function(stats1) {
|
||||
fs.writeFile(filename, 'data', function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
stat(filename, function(stats2) {
|
||||
expect(stats2.ctime).to.be.above(stats1.ctime);
|
||||
expect(stats2.mtime).to.be.above(stats1.mtime);
|
||||
expect(stats2.atime).to.be.above(stats1.atime);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should update atime, ctime, mtime when calling fs.appendFile()', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
stat(filename, function(stats1) {
|
||||
fs.appendFile(filename, '...more data', function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
stat(filename, function(stats2) {
|
||||
expect(stats2.ctime).to.be.above(stats1.ctime);
|
||||
expect(stats2.mtime).to.be.above(stats1.mtime);
|
||||
expect(stats2.atime).to.be.above(stats1.atime);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should update ctime, atime when calling fs.setxattr()', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
stat(filename, function(stats1) {
|
||||
fs.setxattr(filename, 'extra', 'data', function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
stat(filename, function(stats2) {
|
||||
expect(stats2.ctime).to.be.above(stats1.ctime);
|
||||
expect(stats2.mtime).to.equal(stats1.mtime);
|
||||
expect(stats2.atime).to.be.above(stats1.atime);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should update ctime, atime when calling fs.fsetxattr()', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
fs.open(filename, 'w', function(error, fd) {
|
||||
if(error) throw error;
|
||||
|
||||
stat(filename, function(stats1) {
|
||||
fs.fsetxattr(fd, 'extra', 'data', function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
stat(filename, function(stats2) {
|
||||
expect(stats2.ctime).to.be.above(stats1.ctime);
|
||||
expect(stats2.mtime).to.equal(stats1.mtime);
|
||||
expect(stats2.atime).to.be.above(stats1.atime);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should make no change when calling fs.getxattr()', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
fs.setxattr(filename, 'extra', 'data', function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
stat(filename, function(stats1) {
|
||||
fs.getxattr(filename, 'extra', function(error, value) {
|
||||
if(error) throw error;
|
||||
|
||||
stat(filename, function(stats2) {
|
||||
expect(stats2.ctime).to.equal(stats1.ctime);
|
||||
expect(stats2.mtime).to.equal(stats1.mtime);
|
||||
expect(stats2.atime).to.equal(stats1.atime);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should make no change when calling fs.fgetxattr()', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
fs.open(filename, 'w', function(error, fd) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.fsetxattr(fd, 'extra', 'data', function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
stat(filename, function(stats1) {
|
||||
fs.fgetxattr(fd, 'extra', function(error, value) {
|
||||
if(error) throw error;
|
||||
|
||||
stat(filename, function(stats2) {
|
||||
expect(stats2.ctime).to.equal(stats1.ctime);
|
||||
expect(stats2.mtime).to.equal(stats1.mtime);
|
||||
expect(stats2.atime).to.equal(stats1.atime);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should update ctime, atime when calling fs.removexattr()', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
fs.setxattr(filename, 'extra', 'data', function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
stat(filename, function(stats1) {
|
||||
fs.removexattr(filename, 'extra', function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
stat(filename, function(stats2) {
|
||||
expect(stats2.ctime).to.be.above(stats1.ctime);
|
||||
expect(stats2.mtime).to.equal(stats1.mtime);
|
||||
expect(stats2.atime).to.be.above(stats1.atime);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should update ctime, atime when calling fs.fremovexattr()', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
fs.open(filename, 'w', function(error, fd) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.fsetxattr(fd, 'extra', 'data', function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
stat(filename, function(stats1) {
|
||||
fs.fremovexattr(fd, 'extra', function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
stat(filename, function(stats2) {
|
||||
expect(stats2.ctime).to.be.above(stats1.ctime);
|
||||
expect(stats2.mtime).to.equal(stats1.mtime);
|
||||
expect(stats2.atime).to.be.above(stats1.atime);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
|
@ -12,6 +12,7 @@ define([
|
|||
"spec/fs.spec",
|
||||
"spec/fs.stat.spec",
|
||||
"spec/fs.lstat.spec",
|
||||
"spec/fs.exists.spec",
|
||||
"spec/fs.mkdir.spec",
|
||||
"spec/fs.readdir.spec",
|
||||
"spec/fs.rmdir.spec",
|
||||
|
@ -31,6 +32,8 @@ define([
|
|||
"spec/fs.utimes.spec",
|
||||
"spec/fs.xattr.spec",
|
||||
"spec/path-resolution.spec",
|
||||
"spec/times.spec",
|
||||
"spec/time-flags.spec",
|
||||
|
||||
// Filer.FileSystem.providers.*
|
||||
"spec/providers/providers.spec",
|
||||
|
|
Loading…
Reference in New Issue