From 5cbebd135cb770f1159f6f99c04873c636148327 Mon Sep 17 00:00:00 2001 From: Abir Viqar Date: Sat, 23 Nov 2013 13:34:57 -0500 Subject: [PATCH] add lstat --- README.md | 4 ++ src/fs.js | 71 ++++++++++++++++++++++++++++++++- tests/spec/idbfs.spec.js | 86 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b0e9a49..4fbc28c 100644 --- a/README.md +++ b/README.md @@ -170,3 +170,7 @@ Unlike node.js, IDBFS does not accept the optional `type` parameter. #### fs.readlink(path, callback) Asynchronous readlink(2). Callback gets `(error, linkContents)`, where `linkContents` is a string containing the path to which the symbolic link links to. + +#### fs.lstat(path, callback) + +Asynchronous lstat(2). Callback gets `(error, stats)`, See `fs.stat`. diff --git a/src/fs.js b/src/fs.js index 665ecfd..817866a 100644 --- a/src/fs.js +++ b/src/fs.js @@ -609,6 +609,51 @@ define(function(require) { } } + function lstat_file(objectStore, path, callback) { + path = normalize(path); + var name = basename(path); + var parentPath = dirname(path); + + var directoryNode; + var directoryData; + + if(ROOT_DIRECTORY_NAME == name) { + read_object(objectStore, ROOT_NODE_ID, check_file); + } else { + find_node(objectStore, parentPath, read_directory_data); + } + + function read_directory_data(error, result) { + if(error) { + callback(error); + } else { + directoryNode = result; + read_object(objectStore, directoryNode.data, check_if_file_exists); + } + } + + function check_if_file_exists(error, result) { + if(error) { + callback(error); + } else { + directoryData = result; + if(!_(directoryData).has(name)) { + callback(new ENoEntry('a component of the path does not name an existing file')); + } else { + read_object(objectStore, directoryData[name].id, check_file); + } + } + } + + function check_file(error, result) { + if(error) { + callback(error); + } else { + callback(undefined, result); + } + } + } + function link_node(objectStore, oldpath, newpath, callback) { oldpath = normalize(oldpath); var oldname = basename(oldpath); @@ -1329,8 +1374,20 @@ define(function(require) { FileSystem.prototype._realpath = function _realpath(fd, length, callback) { }; - FileSystem.prototype._lstat = function _lstat(fd, length, callback) { + FileSystem.prototype._lstat = function _lstat(context, path, callback) { + var that = this; + function check_result(error, result) { + if(error) { + // if(transaction.error) transaction.abort(); + callback(error); + } else { + var stats = new Stats(result, that.name); + callback(undefined, stats); + } + } + + lstat_file(context, path, check_result); }; function IndexedDBContext(objectStore) { @@ -1636,6 +1693,18 @@ define(function(require) { ); if(error) callback(error); }; + IndexedDBFileSystem.prototype.lstat = function lstat(path, callback) { + var fs = this; + var error = this._queueOrRun( + function() { + var transaction = fs.db.transaction([FILE_STORE_NAME], IDB_RW); + var files = transaction.objectStore(FILE_STORE_NAME); + var context = new IndexedDBContext(files); + fs._lstat(context, path, callback); + } + ); + if(error) callback(error); + }; // FIXME: WebSQL stuff, this needs implementation function WebSQLContext(transaction) { diff --git a/tests/spec/idbfs.spec.js b/tests/spec/idbfs.spec.js index 70634f6..e2d7257 100644 --- a/tests/spec/idbfs.spec.js +++ b/tests/spec/idbfs.spec.js @@ -201,6 +201,92 @@ describe('fs.fstat', function() { }); }); +describe('fs.lstat', function() { + beforeEach(function() { + this.db_name = mk_db_name(); + this.fs = new IDBFS.FileSystem(this.db_name, 'FORMAT'); + }); + + afterEach(function() { + indexedDB.deleteDatabase(this.db_name); + delete this.fs; + }); + + it('should be a function', function() { + expect(typeof this.fs.lstat).toEqual('function'); + }); + + it('should return an error if path does not exist', function() { + var complete = false; + var _error, _result; + + this.fs.lstat('/tmp', function(error, result) { + _error = error; + _result = result; + + complete = true; + }); + + waitsFor(function() { + return complete; + }, 'test to complete', DEFAULT_TIMEOUT); + + runs(function() { + expect(_error).toBeDefined(); + expect(_result).not.toBeDefined(); + }); + }); + + it('should return a stat object if path is not a symbolic link', function() { + var complete = false; + var _error, _result; + var that = this; + + that.fs.lstat('/', function(error, result) { + _error = error; + _result = result; + + complete = true; + }); + + waitsFor(function() { + return complete; + }, 'test to complete', DEFAULT_TIMEOUT); + + runs(function() { + expect(_error).not.toBeDefined(); + expect(_result).toBeDefined(); + }); + }); + + + it('should return a stat object if path is a symbolic link', function() { + var complete = false; + var _error, _result; + var that = this; + + that.fs.symlink('/', '/mylink', function(error) { + if(error) throw error; + + that.fs.lstat('/mylink', function(error, result) { + _error = error; + _result = result; + + complete = true; + }); + }); + + waitsFor(function() { + return complete; + }, 'test to complete', DEFAULT_TIMEOUT); + + runs(function() { + expect(_error).not.toBeDefined(); + expect(_result).toBeDefined(); + }); + }); +}); + describe('fs.mkdir', function() { beforeEach(function() { this.db_name = mk_db_name();