Merge pull request #137 from humphd/issue2
Update atime, ctime, mtime on fs operations. Fixes #2
This commit is contained in:
commit
27262cdb67
|
@ -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);
|
||||
```
|
||||
|
|
|
@ -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,
|
||||
|
|
243
src/fs.js
243
src/fs.js
|
@ -52,6 +52,8 @@ define(function(require) {
|
|||
var O_FLAGS = require('src/constants').O_FLAGS;
|
||||
var XATTR_CREATE = require('src/constants').XATTR_CREATE;
|
||||
var XATTR_REPLACE = require('src/constants').XATTR_REPLACE;
|
||||
var FS_NOMTIME = require('src/constants').FS_NOMTIME;
|
||||
var FS_NOCTIME = require('src/constants').FS_NOCTIME;
|
||||
|
||||
var providers = require('src/providers/providers');
|
||||
var adapters = require('src/adapters/adapters');
|
||||
|
@ -70,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;
|
||||
|
@ -101,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
|
||||
|
@ -128,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
|
||||
*/
|
||||
|
@ -231,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);
|
||||
}
|
||||
|
@ -245,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 {
|
||||
|
@ -356,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -429,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) {
|
||||
|
@ -567,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -596,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -615,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);
|
||||
|
@ -637,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -663,7 +762,6 @@ define(function(require) {
|
|||
}
|
||||
|
||||
fileNode.size = newSize;
|
||||
fileNode.mtime = Date.now();
|
||||
fileNode.version += 1;
|
||||
|
||||
context.put(fileNode.data, newData, update_file_node);
|
||||
|
@ -702,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);
|
||||
|
@ -801,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -881,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -902,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1006,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1089,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1133,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1154,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1181,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1296,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);
|
||||
}
|
||||
|
@ -1304,7 +1449,7 @@ define(function(require) {
|
|||
}
|
||||
else {
|
||||
delete node.xattrs[name];
|
||||
context.put(node.id, node, callback);
|
||||
context.put(node.id, node, update_time);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1322,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);
|
||||
}
|
||||
|
@ -1330,7 +1483,7 @@ define(function(require) {
|
|||
}
|
||||
else {
|
||||
delete node.xattrs[name];
|
||||
context.put(node.id, node, callback);
|
||||
context.put(node.id, node, update_time);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1471,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 {
|
||||
|
@ -1520,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);
|
||||
}
|
||||
|
@ -1671,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) {
|
||||
|
@ -1748,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) {
|
||||
|
@ -1783,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) {
|
||||
|
@ -2284,7 +2451,7 @@ define(function(require) {
|
|||
var fs = this;
|
||||
var error = fs.queueOrRun(
|
||||
function() {
|
||||
var context = fs.provider.getReadOnlyContext();
|
||||
var context = fs.provider.getReadWriteContext();
|
||||
_exists(context, fs.name, path, callback);
|
||||
}
|
||||
);
|
||||
|
|
|
@ -131,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;
|
||||
|
|
|
@ -11,9 +11,9 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
|
||||
it('should return false if path does not exist', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.exists('/tmp', function(result) {
|
||||
expect(result).to.exist;
|
||||
expect(result).equals(false);
|
||||
expect(result).to.be.false;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -22,30 +22,33 @@ define(["Filer", "util"], function(Filer, util) {
|
|||
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.close(fd, function(err) {
|
||||
if(err) throw err;
|
||||
fs.exists('/myfile', function(result) {
|
||||
expect(result).to.exist;
|
||||
expect(result).equals(true);
|
||||
done();
|
||||
});
|
||||
|
||||
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.exist;
|
||||
expect(result).equals(true);
|
||||
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();
|
||||
});
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
|
@ -32,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