Merge pull request #84 from btulchinsky/xattr

Implement setxattr, getxattr
This commit is contained in:
Alan K 2014-01-13 21:59:20 -08:00
commit fc03bb72d3
8 changed files with 1035 additions and 5986 deletions

View File

@ -344,3 +344,27 @@ Asynchronous utimes(3). Callback gets no additional arguments.
#### fs.futimes(fd, atime, mtime, callback)
Asynchronous futimes(3). Callback gets no additional arguments.
#### fs.setxattr(path, name, value, [flag], callback)
Asynchronous setxattr(2). Sets an extended attribute of a file or directory.
The optional flag parameter can be set to the following:
XATTR_CREATE: ensures that the extended attribute with the given name will be new and not previously set. If an attribute with the given name already exists, it will return EExists error to the callback.
XATTR_REPLACE: ensures that an extended attribute with the given name already exists. If an attribute with the given name does not exist, it will return an ENoAttr error to the callback.
Callback gets no additional arguments.
#### fs.getxattr(path, name, callback)
Asynchronous getxattr(2). Gets an extended attribute value for a file or directory.
Callback gets `(error, value)`, where value is the value for the extended attribute.
#### fs.fsetxattr(fd, name, value, [flag], callback)
Asynchronous fsetxattr(2). See `fs.setxattr` for flag options. Callback gets no additional arguments.
#### fs.fgetxattr(fs, name, callback)
Asynchronous fgetxattr(2). Callback gets `(error, value)`, See `fs.getxattr`.

5974
dist/idbfs.js vendored

File diff suppressed because it is too large Load Diff

5
dist/idbfs.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -6,6 +6,8 @@ define(function(require) {
var O_EXCLUSIVE = 'EXCLUSIVE';
var O_TRUNCATE = 'TRUNCATE';
var O_APPEND = 'APPEND';
var XATTR_CREATE = 'CREATE';
var XATTR_REPLACE = 'REPLACE';
return {
FILE_SYSTEM_NAME: 'local',
@ -53,6 +55,9 @@ define(function(require) {
'ax+': [O_WRITE, O_READ, O_CREATE, O_EXCLUSIVE, O_APPEND]
},
XATTR_CREATE: XATTR_CREATE,
XATTR_REPLACE: XATTR_REPLACE,
FS_READY: 'READY',
FS_PENDING: 'PENDING',
FS_ERROR: 'ERROR',

View File

@ -105,6 +105,13 @@ define(function(require) {
EFileSystemError.prototype.name = "EFileSystemError";
EFileSystemError.prototype.constructor = EFileSystemError;
function ENoAttr(message) {
this.message = message || '';
}
ENoAttr.prototype = new Error();
ENoAttr.prototype.name = 'ENoAttr';
ENoAttr.prototype.constructor = ENoAttr;
return {
EExists: EExists,
EIsDirectory: EIsDirectory,
@ -118,7 +125,8 @@ define(function(require) {
EInvalid: EInvalid,
EIO: EIO,
ELoop: ELoop,
EFileSystemError: EFileSystemError
EFileSystemError: EFileSystemError,
ENoAttr: ENoAttr
};
});

383
src/fs.js
View File

@ -27,6 +27,7 @@ define(function(require) {
var EIO = require('src/error').EIO;
var ELoop = require('src/error').ELoop;
var EFileSystemError = require('src/error').EFileSystemError;
var ENoAttr = require('src/error').ENoAttr;
var FILE_SYSTEM_NAME = require('src/constants').FILE_SYSTEM_NAME;
var FS_FORMAT = require('src/constants').FS_FORMAT;
@ -47,6 +48,8 @@ define(function(require) {
var O_TRUNCATE = require('src/constants').O_TRUNCATE;
var O_APPEND = require('src/constants').O_APPEND;
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 providers = require('src/providers/providers');
var adapters = require('src/adapters/adapters');
@ -219,6 +222,41 @@ define(function(require) {
}
}
/*
* set extended attribute (refactor)
*/
function set_extended_attribute (context, path_or_fd, name, value, flag, callback) {
function set_xattr (error, node) {
var xattr = (node ? node.xattrs[name] : null);
if (error) {
callback(error);
}
else if (flag === XATTR_CREATE && node.xattrs.hasOwnProperty(name)) {
callback(new EExists('attribute already exists'));
}
else if (flag === XATTR_REPLACE && !node.xattrs.hasOwnProperty(name)) {
callback(new ENoAttr('attribute does not exist'));
}
else {
node.xattrs[name] = value;
context.put(node.id, node, callback);
}
}
if (typeof path_or_fd == 'string') {
find_node(context, path_or_fd, set_xattr);
}
else if (typeof path_or_fd == 'object' && typeof path_or_fd.id == 'string') {
context.get(path_or_fd.id, set_xattr);
}
else {
callback(new EInvalid('path or file descriptor of wrong type'));
}
}
/*
* make_root_directory
*/
@ -1118,6 +1156,151 @@ define(function(require) {
}
}
function setxattr_file (context, path, name, value, flag, callback) {
path = normalize(path);
if (typeof name != 'string') {
callback(new EInvalid('attribute name must be a string'));
}
else if (!name) {
callback(new EInvalid('attribute name cannot be an empty string'));
}
else if (flag != null &&
flag !== XATTR_CREATE && flag !== XATTR_REPLACE) {
callback(new EInvalid('invalid flag, must be null, XATTR_CREATE or XATTR_REPLACE'));
}
else {
set_extended_attribute(context, path, name, value, flag, callback);
}
}
function fsetxattr_file (context, ofd, name, value, flag, callback) {
if (typeof name != 'string') {
callback(new EInvalid('attribute name must be a string'));
}
else if (!name) {
callback(new EInvalid('attribute name cannot be an empty string'));
}
else if (flag != null &&
flag !== XATTR_CREATE && flag !== XATTR_REPLACE) {
callback(new EInvalid('invalid flag, must be null, XATTR_CREATE or XATTR_REPLACE'));
}
else {
set_extended_attribute(context, ofd, name, value, flag, callback);
}
}
function getxattr_file (context, path, name, callback) {
path = normalize(path);
function get_xattr(error, node) {
var xattr = (node ? node.xattrs[name] : null);
if (error) {
callback (error);
}
else if (!node.xattrs.hasOwnProperty(name)) {
callback(new ENoAttr('attribute does not exist'));
}
else {
callback(null, node.xattrs[name]);
}
}
if (typeof name != 'string') {
callback(new EInvalid('attribute name must be a string'));
}
else if (!name) {
callback(new EInvalid('attribute name cannot be an empty string'));
}
else {
find_node(context, path, get_xattr);
}
}
function fgetxattr_file (context, ofd, name, callback) {
function get_xattr (error, node) {
var xattr = (node ? node.xattrs[name] : null);
if (error) {
callback(error);
}
else if (!node.xattrs.hasOwnProperty(name)) {
callback(new ENoAttr('attribute does not exist'));
}
else {
callback(null, node.xattrs[name]);
}
}
if (typeof name != 'string') {
callback(new EInvalid('attribute name must be a string'));
}
else if (!name) {
callback(new EInvalid('attribute name cannot be an empty string'));
}
else {
context.get(ofd.id, get_xattr);
}
}
function removexattr_file (context, path, name, callback) {
path = normalize(path);
function remove_xattr (error, node) {
var xattr = (node ? node.xattrs : null);
if (error) {
callback(error);
}
else if (!xattr.hasOwnProperty(name)) {
callback(new ENoAttr('attribute does not exist'));
}
else {
delete node.xattrs[name];
context.put(node.id, node, callback);
}
}
if (typeof name != 'string') {
callback(new EInvalid('attribute name must be a string'));
}
else if (!name) {
callback(new EInvalid('attribute name cannot be an empty string'));
}
else {
find_node(context, path, remove_xattr);
}
}
function fremovexattr_file (context, ofd, name, callback) {
function remove_xattr (error, node) {
if (error) {
callback(error);
}
else if (!node.xattrs.hasOwnProperty(name)) {
callback(new ENoAttr('attribute does not exist'));
}
else {
delete node.xattrs[name];
context.put(node.id, node, callback);
}
}
if (typeof name != 'string') {
callback(new EInvalid('attribute name must be a string'));
}
else if (!name) {
callback(new EInvalid('attribute name cannot be an empty string'));
}
else {
context.get(ofd.id, remove_xattr);
}
}
function validate_flags(flags) {
if(!_(O_FLAGS).has(flags)) {
return null;
@ -1531,14 +1714,117 @@ define(function(require) {
});
}
function _getxattr(path, name, callback) {
// TODO
// if(!nullCheck(path, callback)) return;
function _getxattr (context, path, name, callback) {
if (!nullCheck(path, callback)) return;
function fetch_value (error, value) {
if (error) {
callback(error);
}
else {
callback(null, value);
}
}
getxattr_file(context, path, name, fetch_value);
}
function _setxattr(path, name, value, callback) {
// TODO
// if(!nullCheck(path, callback)) return;
function _fgetxattr (fs, context, fd, name, callback) {
function get_result (error, value) {
if (error) {
callback(error);
}
else {
callback(null, value);
}
}
var ofd = fs.openFiles[fd];
if (!ofd) {
callback(new EBadFileDescriptor('invalid file descriptor'));
}
else {
fgetxattr_file(context, ofd, name, get_result);
}
}
function _setxattr (context, path, name, value, flag, callback) {
if (!nullCheck(path, callback)) return;
function check_result (error) {
if (error) {
callback(error);
}
else {
callback(null);
}
};
setxattr_file(context, path, name, value, flag, check_result);
}
function _fsetxattr (fs, context, fd, name, value, flag, callback) {
function check_result (error) {
if (error) {
callback(error);
}
else {
callback(null);
}
}
var ofd = fs.openFiles[fd];
if (!ofd) {
callback(new EBadFileDescriptor('invalid file descriptor'));
}
else if (!_(ofd.flags).contains(O_WRITE)) {
callback(new EBadFileDescriptor('descriptor does not permit writing'));
}
else {
fsetxattr_file(context, ofd, name, value, flag, check_result);
}
}
function _removexattr (context, path, name, callback) {
if (!nullCheck(path, callback)) return;
function remove_xattr (error) {
if (error) {
callback(error);
}
else {
callback(null);
}
}
removexattr_file (context, path, name, remove_xattr);
}
function _fremovexattr (fs, context, fd, name, callback) {
function remove_xattr (error) {
if (error) {
callback(error);
}
else {
callback(null);
}
}
var ofd = fs.openFiles[fd];
if (!ofd) {
callback(new EBadFileDescriptor('invalid file descriptor'));
}
else if (!_(ofd.flags).contains(O_WRITE)) {
callback(new EBadFileDescriptor('descriptor does not permit writing'));
}
else {
fremovexattr_file(context, ofd, name, remove_xattr);
}
}
function _lseek(fs, context, fd, offset, whence, callback) {
@ -2010,7 +2296,92 @@ define(function(require) {
callback(error);
}
};
FileSystem.prototype.setxattr = function (path, name, value, flag, callback) {
var callback = maybeCallback(arguments[arguments.length - 1]);
var _flag = (typeof flag != 'function') ? flag : null;
var fs = this;
var error = fs.queueOrRun(
function () {
var context = fs.provider.getReadWriteContext();
_setxattr(context, path, name, value, _flag, callback);
}
);
if (error) {
callback(error);
}
};
FileSystem.prototype.getxattr = function (path, name, callback) {
callback = maybeCallback(callback);
var fs = this;
var error = fs.queueOrRun(
function () {
var context = fs.provider.getReadWriteContext();
_getxattr(context, path, name, callback);
}
);
if (error) {
callback(error);
}
};
FileSystem.prototype.fsetxattr = function (fd, name, value, flag, callback) {
var callback = maybeCallback(arguments[arguments.length - 1]);
var _flag = (typeof flag != 'function') ? flag : null;
var fs = this;
var error = fs.queueOrRun(
function () {
var context = fs.provider.getReadWriteContext();
_fsetxattr(fs, context, fd, name, value, _flag, callback);
}
);
if (error) {
callback(error);
}
};
FileSystem.prototype.fgetxattr = function (fd, name, callback) {
callback = maybeCallback(callback);
var fs = this;
var error = fs.queueOrRun(
function () {
var context = fs.provider.getReadWriteContext();
_fgetxattr(fs, context, fd, name, callback);
}
);
if (error) {
callback(error);
}
};
FileSystem.prototype.removexattr = function (path, name, callback) {
callback = maybeCallback(callback);
var fs = this;
var error = fs.queueOrRun(
function () {
var context = fs.provider.getReadWriteContext();
_removexattr(context, path, name, callback);
}
);
if (error) {
callback(error);
}
};
FileSystem.prototype.fremovexattr = function (fd, name, callback) {
callback = maybeCallback(callback);
var fs = this;
var error = fs.queueOrRun(
function () {
var context = fs.provider.getReadWriteContext();
_fremovexattr(fs, context, fd, name, callback);
}
);
if (error) {
callback(error);
}
};
return FileSystem;
});

619
tests/spec/fs.xattr.spec.js Normal file
View File

@ -0,0 +1,619 @@
define(["IDBFS"], function(IDBFS) {
describe('fs.xattr', function() {
beforeEach(function() {
this.db_name = mk_db_name();
this.fs = new IDBFS.FileSystem({
name: this.db_name,
flags: 'FORMAT'
});
});
afterEach(function() {
indexedDB.deleteDatabase(this.db_name);
delete this.fs;
});
it('should be a function', function () {
expect(typeof this.fs.setxattr).toEqual('function');
expect(typeof this.fs.getxattr).toEqual('function');
expect(typeof this.fs.removexattr).toEqual('function');
expect(typeof this.fs.fsetxattr).toEqual('function');
expect(typeof this.fs.fgetxattr).toEqual('function');
});
it('should error when setting with a name that is not a string', function () {
var complete = false;
var _error;
var that = this;
that.fs.writeFile('/testfile', '', function (error) {
if (error) throw error;
that.fs.setxattr('/testfile', 89, 'testvalue', function (error) {
_error = error;
complete = true;
});
});
waitsFor(function () {
return complete;
}, 'test to complete', DEFAULT_TIMEOUT);
runs(function () {
expect(_error).toBeDefined();
expect(_error.name).toEqual('EInvalid');
});
});
it('should error when setting with a name that is null', function () {
var complete = false;
var _error;
var that = this;
that.fs.writeFile('/testfile', '', function (error) {
if (error) throw error;
that.fs.setxattr('/testfile', null, 'testvalue', function (error) {
_error = error;
complete = true;
});
});
waitsFor(function () {
return complete;
}, 'test to complete', DEFAULT_TIMEOUT);
runs(function () {
expect(_error).toBeDefined();
expect(_error.name).toEqual('EInvalid');
});
});
it('should error when setting with an invalid flag', function () {
var complete = false;
var _error;
var that = this;
that.fs.writeFile('/testfile', '', function (error) {
if (error) throw error;
that.fs.setxattr('/testfile', 'test', 'value', 'InvalidFlag', function (error) {
_error = error;
complete = true;
});
});
waitsFor(function () {
return complete;
}, 'test to complete', DEFAULT_TIMEOUT);
runs(function () {
expect(_error).toBeDefined();
expect(_error.name).toEqual('EInvalid');
});
});
it('should error when when setting an extended attribute which exists with XATTR_CREATE flag', function (error) {
var complete = false;
var _error;
var that = this;
that.fs.writeFile('/testfile', '', function (error) {
if (error) throw error;
that.fs.setxattr('/testfile', 'test', 'value', function (error) {
if (error) throw error;
that.fs.setxattr('/testfile', 'test', 'othervalue', 'CREATE', function (error) {
_error = error;
complete = true;
});
});
});
waitsFor(function () {
return complete;
}, 'test to complete', DEFAULT_TIMEOUT);
runs(function () {
expect(_error).toBeDefined();
expect(_error.name).toEqual('EExists');
});
});
it('should error when setting an extended attribute which does not exist with XATTR_REPLACE flag', function (error) {
var complete = false;
var _error;
var that = this;
that.fs.writeFile('/testfile', '', function (error) {
if (error) throw error;
that.fs.setxattr('/testfile', 'test', 'value', 'REPLACE', function (error) {
_error = error;
complete = true;
});
});
waitsFor(function () {
return complete;
}, 'test to complete', DEFAULT_TIMEOUT);
runs(function () {
expect(_error).toBeDefined();
expect(_error.name).toEqual('ENoAttr');
});
});
it ('should error when getting an attribute with a name that is empty', function (error) {
var complete = false;
var _error;
var that = this;
that.fs.writeFile('/testfile', '', function (error) {
if (error) throw error;
that.fs.getxattr('/testfile', '', function (error, value) {
_error = error;
complete = true;
});
});
waitsFor(function () {
return complete;
}, 'test to complete', DEFAULT_TIMEOUT);
runs(function () {
expect(_error).toBeDefined();
expect(_error.name).toEqual('EInvalid');
});
});
it('should error when getting an attribute where the name is not a string', function (error) {
var complete = false;
var _error;
var that = this;
that.fs.writeFile('/testfile', '', function (error) {
if (error) throw error;
that.fs.getxattr('/testfile', 89, function (error, value) {
_error = error;
complete = true;
});
});
waitsFor(function () {
return complete;
}, 'test to complete', DEFAULT_TIMEOUT);
runs(function () {
expect(_error).toBeDefined();
expect(_error.name).toEqual('EInvalid');
});
});
it('should error when getting an attribute that does not exist', function (error) {
var complete = false;
var _error;
var that = this;
that.fs.writeFile('/testfile', '', function (error) {
if (error) throw error;
that.fs.getxattr('/testfile', 'test', function (error, value) {
_error = error;
complete = true;
});
});
waitsFor(function () {
return complete;
}, 'test to complete', DEFAULT_TIMEOUT);
runs(function () {
expect(_error).toBeDefined();
expect(_error.name).toEqual('ENoAttr');
});
});
it('should error when file descriptor is invalid', function (error) {
var completeSet, completeGet, completeRemove;
var _errorSet, _errorGet, _errorRemove;
var that = this;
var _value;
completeSet = completeGet = completeRemove = false;
that.fs.fsetxattr(1, 'test', 'value', function (error) {
_errorSet = error;
completeSet = true;
});
that.fs.fgetxattr(1, 'test', function (error, value) {
_errorGet = error;
_value = value;
completeGet = true;
});
that.fs.fremovexattr(1, 'test', function (error, value) {
_errorRemove = error;
completeRemove = true;
});
waitsFor(function () {
return completeSet && completeGet && completeRemove;
}, 'test to complete', DEFAULT_TIMEOUT);
runs(function () {
expect(_value).toEqual(null);
expect(_errorSet).toBeDefined();
expect(_errorSet.name).toEqual('EBadFileDescriptor');
expect(_errorGet).toBeDefined();
expect(_errorGet.name).toEqual('EBadFileDescriptor');
expect(_errorRemove).toBeDefined();
expect(_errorRemove.name).toEqual('EBadFileDescriptor');
});
});
it('should set and get an extended attribute of a path', function (error) {
var complete = false;
var _errorSet;
var that = this;
var name = 'test';
var _value;;
that.fs.writeFile('/testfile', '', function (error) {
if (error) throw error;
that.fs.setxattr('/testfile', name, 'somevalue', function (error) {
_errorSet = error;
that.fs.getxattr('/testfile', name, function (error, value) {
_errorGet = error;
_value = value;
complete = true;
});
});
});
waitsFor(function () {
return complete;
}, 'test to complete', DEFAULT_TIMEOUT);
runs(function () {
expect(_errorSet).toEqual(null);
expect(_errorGet).toEqual(null);
expect(_value).toEqual('somevalue');
});
});
it('should error when attempting to remove a non-existing attribute', function (error) {
var complete = false;
var _error;
var that = this;
that.fs.writeFile('/testfile', '', function (error) {
if (error) throw error;
that.fs.setxattr('/testfile', 'test', '', function (error) {
if (error) throw error;
that.fs.removexattr('/testfile', 'testenoattr', function (error) {
_error = error;
complete = true;
});
});
});
waitsFor(function () {
return complete;
}, 'test to complete', DEFAULT_TIMEOUT);
runs(function () {
expect(_error).toBeDefined();
expect(_error.name).toEqual('ENoAttr');
});
});
it('should set and get an empty string as a value', function (error) {
var complete = false;
var _error;
var _value;
var that = this;
that.fs.writeFile('/testfile', '', function (error) {
if (error) throw error;
that.fs.setxattr('/testfile', 'test', '', function (error) {
_error = error;
that.fs.getxattr('/testfile', 'test', function (error, value) {
_error = error;
_value = value;
complete = true;
});
});
});
waitsFor(function () {
return complete;
}, 'test to complete', DEFAULT_TIMEOUT);
runs(function () {
expect(_error).toEqual(null);
expect(_value).toBeDefined();
expect(_value).toEqual('');
});
});
it('should set and get an extended attribute for a valid file descriptor', function (error) {
var complete = false;
var _errorSet, _errorGet;
var _value;
var that = this;
var ofd;
that.fs.open('/testfile', 'w', function (error, result) {
if (error) throw error;
ofd = result;
that.fs.fsetxattr(ofd, 'test', 'value', function (error) {
_errorSet = error;
that.fs.fgetxattr(ofd, 'test', function (error, value) {
_errorGet = error;
_value = value;
complete = true;
});
});
});
waitsFor(function () {
return complete;
}, 'test to complete', DEFAULT_TIMEOUT);
runs(function () {
expect(_errorSet).toEqual(null);
expect(_errorGet).toEqual(null);
expect(_value).toBeDefined();
expect(_value).toEqual('value');
});
});
it('should set and get an object to an extended attribute', function (error) {
var complete = false;
var _error;
var that = this;
var value;
that.fs.writeFile('/testfile', '', function (error) {
if (error) throw error;
that.fs.setxattr('/testfile', 'test', { key1: 'test', key2: 'value', key3: 87 }, function (error) {
_error = error;
that.fs.getxattr('/testfile', 'test', function (error, value) {
_error = error;
_value = value;
complete = true;
});
});
});
waitsFor(function () {
return complete;
}, 'test to complete', DEFAULT_TIMEOUT);
runs(function () {
expect(_error).toEqual(null);
expect(_value).toEqual({ key1: 'test', key2: 'value', key3: 87 });
});
});
it('should update/overwrite an existing extended attribute', function (error) {
var complete = false;
var _error;
var that = this;
var _value1, _value2, _value3;
that.fs.writeFile('/testfile', '', function (error) {
if (error) throw error;
that.fs.setxattr('/testfile', 'test', 'value', function (error) {
_error = error;
that.fs.getxattr('/testfile', 'test', function (error, value) {
_error = error;
_value1 = value;
that.fs.setxattr('/testfile', 'test', { o: 'object', t: 'test' }, function (error) {
_error = error;
that.fs.getxattr('/testfile', 'test', function (error, value) {
_error = error;
_value2 = value;
that.fs.setxattr('/testfile', 'test', 100, 'REPLACE', function (error) {
_error = error;
that.fs.getxattr('/testfile', 'test', function (error, value) {
_error = error;
_value3 = value;
complete = true;
});
});
});
});
});
})
});
waitsFor(function () {
return complete;
}, 'test to complete' , DEFAULT_TIMEOUT);
runs(function () {
expect(_error).toEqual(null);
expect(_value1).toEqual('value');
expect(_value2).toEqual({ o: 'object', t: 'test' });
expect(_value3).toEqual(100);
});
});
it('should set multiple extended attributes for a path', function (error) {
var complete = false;
var _error;
var that = this;
var _value1, _value2;
that.fs.writeFile('/testfile', '', function (error) {
if (error) throw error;
that.fs.setxattr('/testfile', 'test', 89, function (error) {
_error = error;
that.fs.setxattr('/testfile', 'other', 'attribute', function (error) {
_error = error;
that.fs.getxattr('/testfile', 'test', function (error, value) {
_error = error;
_value1 = value;
that.fs.getxattr('/testfile', 'other', function (error, value) {
_error = error;
_value2 = value;
complete = true;
});
});
});
});
});
waitsFor(function () {
return complete;
}, 'test to complete', DEFAULT_TIMEOUT);
runs(function () {
expect(_error).toEqual(null);
expect(_value1).toEqual(89);
expect(_value2).toEqual('attribute');
});
});
it('should remove an extended attribute from a path', function (error) {
var complete = false;
var _error, _value;
var that = this;
that.fs.writeFile('/testfile', '', function (error) {
if (error) throw error;
that.fs.setxattr('/testfile', 'test', 'somevalue', function (error) {
if (error) throw error;
that.fs.getxattr('/testfile', 'test', function (error, value) {
if (error) throw error;
_value = value;
that.fs.removexattr('/testfile', 'test', function (error) {
if (error) throw error;
that.fs.getxattr('/testfile', 'test', function (error) {
_error = error;
complete = true;
});
});
});
});
});
waitsFor(function () {
return complete;
}, 'test to complete', DEFAULT_TIMEOUT);
runs(function () {
expect(_error).toBeDefined();
expect(_value).toBeDefined();
expect(_value).toEqual('somevalue');
expect(_error.name).toEqual('ENoAttr');
});
});
it('should remove an extended attribute from a valid file descriptor', function () {
var complete = false;
var _error, _value;
var that = this;
var ofd;
that.fs.open('/testfile', 'w', function (error, result) {
if (error) throw error;
var ofd = result;
that.fs.fsetxattr(ofd, 'test', 'somevalue', function (error) {
if (error) throw error;
that.fs.fgetxattr(ofd, 'test', function (error, value) {
if (error) throw error;
_value = value;
that.fs.fremovexattr(ofd, 'test', function (error) {
if (error) throw error;
that.fs.fgetxattr(ofd, 'test', function (error) {
_error = error;
complete = true;
});
});
});
});
});
waitsFor(function () {
return complete;
}, 'test to complete', DEFAULT_TIMEOUT);
runs(function () {
expect(_error).toBeDefined();
expect(_value).toBeDefined();
expect(_value).toEqual('somevalue');
expect(_error.name).toEqual('ENoAttr');
});
});
it('should allow setting with a null value', function () {
var complete = false;
var _error;
var _value;
var that = this;
that.fs.writeFile('/testfile', '', function (error) {
if (error) throw error;
that.fs.setxattr('/testfile', 'test', null, function (error) {
if (error) throw error;
that.fs.getxattr('/testfile', 'test', function (error, value) {
_error = error;
_value = value;
complete = true;
});
});
});
waitsFor(function () {
return complete;
}, 'test to complete', DEFAULT_TIMEOUT);
runs(function () {
expect(_error).toEqual(null);
expect(_value).toEqual(null);
});
});
});
});

View File

@ -28,6 +28,7 @@ define([
"spec/fs.readlink.spec",
"spec/fs.truncate.spec",
"spec/fs.utimes.spec",
"spec/fs.xattr.spec",
"spec/path-resolution.spec",
// IDBFS.FileSystem.providers.*