diff --git a/examples/refactoring-test.html b/examples/refactoring-test.html index 2a72c71..7a1148d 100644 --- a/examples/refactoring-test.html +++ b/examples/refactoring-test.html @@ -36,13 +36,13 @@ function remove_tmp_directory() { }; function create_tmp_file() { - return fs.open('/tmp/1', 'CREATE'); + return fs.open('/tmp/1', 'w+'); }; fs.promise.then(make_tmp_directory) .then(create_tmp_file) .then(function() { console.log('done'); }) - .otherwise(function(error) { console.error(error, error.stack); }); + .otherwise(function(error) { console.error(error, error.message); }); }); diff --git a/src/constants.js b/src/constants.js index a2f9512..6946629 100644 --- a/src/constants.js +++ b/src/constants.js @@ -1,5 +1,12 @@ define(function(require) { + var O_READ = 'READ'; + var O_WRITE = 'WRITE'; + var O_CREATE = 'CREATE'; + var O_EXCLUSIVE = 'EXCLUSIVE'; + var O_TRUNCATE = 'TRUNCATE'; + var O_APPEND = 'APPEND'; + return { METADATA_STORE_NAME: 'metadata', FILE_STORE_NAME: 'files', @@ -17,17 +24,28 @@ define(function(require) { ROOT_DIRECTORY_NAME: '/', // basename(normalize(path)) ROOT_NODE_ID: '8a5edab282632443219e051e4ade2d1d5bbc671c781051bf1437897cbdfea0f1', // sha256(ROOT_DIRECTORY_NAME) - // FileSystem flags FS_FORMAT: 'FORMAT', - // Open flags - O_READONLY: 'READONLY', - O_READWRITE: 'READWRITE', - O_APPEND: 'APPEND', - O_CREATE: 'CREATE', - O_TRUNCATE: 'TRUNCATE', + O_READ: O_READ, + O_WRITE: O_WRITE, + O_CREATE: O_CREATE, + O_EXCLUSIVE: O_EXCLUSIVE, + O_TRUNCATE: O_TRUNCATE, + O_APPEND: O_APPEND, + + O_FLAGS: { + 'r': [O_READ], + 'r+': [O_READ, O_WRITE], + 'w': [O_WRITE, O_CREATE, O_TRUNCATE], + 'w+': [O_WRITE, O_READ, O_CREATE, O_TRUNCATE], + 'wx': [O_WRITE, O_CREATE, O_EXCLUSIVE, O_TRUNCATE], + 'wx+': [O_WRITE, O_READ, O_CREATE, O_EXCLUSIVE, O_TRUNCATE], + 'a': [O_WRITE, O_CREATE, O_APPEND], + 'a+': [O_WRITE, O_READ, O_CREATE, O_APPEND], + 'ax': [O_WRITE, O_CREATE, O_EXCLUSIVE, O_APPEND], + 'ax+': [O_WRITE, O_READ, O_CREATE, O_EXCLUSIVE, O_APPEND], + }, - // FileSystem readyState FS_READY: 'READY', FS_PENDING: 'PENDING', FS_ERROR: 'ERROR', diff --git a/src/descriptor.js b/src/descriptor.js index e4ee30b..50e8de5 100644 --- a/src/descriptor.js +++ b/src/descriptor.js @@ -1,10 +1,16 @@ define(function(require) { - function Descriptor() { + function Descriptor(db, id, flags, mode, size) { + this.db = db; + this.id = id; + this.flags = flags; + this.mode = mode; + this.size = size || 0; + this.position = 0; }; return { - Descriptor: Descriptor, - }; + Descriptor: Descriptor + } }); \ No newline at end of file diff --git a/src/directory.js b/src/directory.js index 164be9d..5db0b7e 100644 --- a/src/directory.js +++ b/src/directory.js @@ -7,7 +7,7 @@ define(function(require) { var ENoEntry = require('src/error').ENoEntry; var ENotDirectory = require('src/error').ENotDirectory; - var EPathExists = require('src/error').EPathExists; + var EExists = require('src/error').EExists; var MODE_FILE = require('src/constants').MODE_FILE; var MODE_DIRECTORY = require('src/constants').MODE_DIRECTORY; @@ -28,7 +28,7 @@ define(function(require) { function write_directory_node(error, existingNode) { if(!error && existingNode) { - callback(new EPathExists()); + callback(new EExists()); } else if(error && !error instanceof ENoEntry) { callback(error); } else { @@ -62,7 +62,7 @@ define(function(require) { function check_if_directory_exists(error, result) { if(!error && result) { - callback(new EPathExists()); + callback(new EExists()); } else if(error && !error instanceof ENoEntry) { callback(error); } else { diff --git a/src/error.js b/src/error.js index 29fec28..26ffaf9 100644 --- a/src/error.js +++ b/src/error.js @@ -14,58 +14,85 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND define(function(require) { // 'use strict'; - function EPathExists(){ Error.apply(this, arguments); } - EPathExists.prototype = new Error(); - EPathExists.prototype.name = "EPathExists"; - EPathExists.prototype.constructor = EPathExists; + function EExists(message){ + this.message = message || ''; + }; + EExists.prototype = new Error(); + EExists.prototype.name = "EExists"; + EExists.prototype.constructor = EExists; - function EIsDirectory(){ Error.apply(this, arguments); } + function EIsDirectory(message){ + this.message = message || ''; + }; EIsDirectory.prototype = new Error(); EIsDirectory.prototype.name = "EIsDirectory"; EIsDirectory.prototype.constructor = EIsDirectory; - function ENoEntry(){ Error.apply(this, arguments); } + function ENoEntry(message){ + this.message = message || ''; + }; ENoEntry.prototype = new Error(); ENoEntry.prototype.name = "ENoEntry"; ENoEntry.prototype.constructor = ENoEntry; - function EBusy(){ Error.apply(this, arguments); } + function EBusy(message){ + this.message = message || ''; + }; EBusy.prototype = new Error(); EBusy.prototype.name = "EBusy"; EBusy.prototype.constructor = EBusy; - function ENotEmpty(){ Error.apply(this, arguments); } + function ENotEmpty(message){ + this.message = message || ''; + }; ENotEmpty.prototype = new Error(); ENotEmpty.prototype.name = "ENotEmpty"; ENotEmpty.prototype.constructor = ENotEmpty; - function ENotDirectory(){ Error.apply(this, arguments); } + function ENotDirectory(message){ + this.message = message || ''; + }; ENotDirectory.prototype = new Error(); - ENotDirectory.prototype.name = "NotADirectoryError"; + ENotDirectory.prototype.name = "ENotDirectory"; ENotDirectory.prototype.constructor = ENotDirectory; - function EBadFileDescriptor(){ Error.apply(this, arguments); } + function EBadFileDescriptor(message){ + this.message = message || ''; + }; EBadFileDescriptor.prototype = new Error(); EBadFileDescriptor.prototype.name = "EBadFileDescriptor"; EBadFileDescriptor.prototype.constructor = EBadFileDescriptor; - function ENotImplemented(){ Error.apply(this, arguments); } + function ENotImplemented(message){ + this.message = message || ''; + }; ENotImplemented.prototype = new Error(); ENotImplemented.prototype.name = "ENotImplemented"; ENotImplemented.prototype.constructor = ENotImplemented; - function ENotMounted(){ Error.apply(this, arguments); } + function ENotMounted(message){ + this.message = message || ''; + }; ENotMounted.prototype = new Error(); ENotMounted.prototype.name = "ENotMounted"; ENotMounted.prototype.constructor = ENotMounted; - function EFileExists(){ Error.apply(this, arguments); } - EFileExists.prototype = new Error(); - EFileExists.prototype.name = "EFileExists"; - EFileExists.prototype.constructor = EFileExists; + function EInvalid(message){ + this.message = message || ''; + }; + EInvalid.prototype = new Error(); + EInvalid.prototype.name = "EInvalid"; + EInvalid.prototype.constructor = EInvalid; + + function EIO(message){ + this.message = message || ''; + }; + EIO.prototype = new Error(); + EIO.prototype.name = "EIO"; + EIO.prototype.constructor = EIO; return { - EPathExists: EPathExists, + EExists: EExists, EIsDirectory: EIsDirectory, ENoEntry: ENoEntry, EBusy: EBusy, @@ -74,7 +101,8 @@ define(function(require) { EBadFileDescriptor: EBadFileDescriptor, ENotImplemented: ENotImplemented, ENotMounted: ENotMounted, - EFileExists: EFileExists + EInvalid: EInvalid, + EIO: EIO, }; }); \ No newline at end of file diff --git a/src/file-system.js b/src/file-system.js index f3cc63b..c3b0943 100644 --- a/src/file-system.js +++ b/src/file-system.js @@ -9,7 +9,7 @@ define(function(require) { var hash = require('src/shared').hash; var nop = require('src/shared').nop; - var EPathExists = require('src/error').EPathExists; + var EExists = require('src/error').EExists; var EIsDirectory = require('src/error').EIsDirectory; var ENoEntry = require('src/error').ENoEntry; var EBusy = require('src/error').EBusy; @@ -18,7 +18,7 @@ define(function(require) { var EBadFileDescriptor = require('src/error').EBadFileDescriptor; var ENotImplemented = require('src/error').ENotImplemented; var ENotMounted = require('src/error').ENotMounted; - var EFileExists = require('src/error').EFileExists; + var EInvalid = require('src/error').EInvalid; var FS_FORMAT = require('src/constants').FS_FORMAT; @@ -100,21 +100,21 @@ define(function(require) { this.readyState = FS_PENDING; this.db = null; }; - FileSystem.prototype.open = function open(path, flags, mode) { + FileSystem.prototype.open = function open(path, flags) { var deferred = when.defer(); var transaction = this.db.transaction([FILE_STORE_NAME], IDB_RW); var files = transaction.objectStore(FILE_STORE_NAME); function check_result(error, fd) { if(error) { - if(transaction.error) transaction.abort(); + // if(transaction.error) transaction.abort(); deferred.reject(error); } else { deferred.resolve(); } }; - open_file(files, path, flags, mode, check_result); + open_file(files, path, flags, check_result); return deferred.promise; }; diff --git a/src/file.js b/src/file.js index 803027c..bb0df9b 100644 --- a/src/file.js +++ b/src/file.js @@ -16,7 +16,15 @@ define(function(require) { var delete_object = require('src/object-store').delete_object; var find_node = require('src/object-store').find_node; + var O_READ = require('src/constants').O_READ; + var O_WRITE = require('src/constants').O_WRITE; var O_CREATE = require('src/constants').O_CREATE; + var O_EXCLUSIVE = require('src/constants').O_EXCLUSIVE; + 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 EInvalid = require('src/error').EInvalid; function DirectoryEntry(id, type) { this.id = id; @@ -39,15 +47,24 @@ define(function(require) { this.data = hash(this.id) // id for data object }; - function open_file(objectStore, path, flags, mode, callback) { + function open_file(objectStore, path, flags, callback) { path = normalize(path); var name = basename(path); + var parentPath = dirname(path); var directoryNode; var directoryData; var fileNode; var fileData; + if(!_(O_FLAGS).has(flags)) { + return callback(new EInvalid('flags is not valid')); + } else { + flags = O_FLAGS[flags]; + } + + find_node(objectStore, parentPath, read_directory_data); + function read_directory_data(error, result) { if(error) { callback(error); @@ -63,12 +80,14 @@ define(function(require) { } else { directoryData = result; if(_(directoryData).has(name)) { - // file exists + if(_(flags).contains(O_EXCLUSIVE)) { + callback(new ENoEntry('O_CREATE and O_EXCLUSIVE are set, and the named file exists')) + } } else { - if(_(flags).contains(O_CREATE)) { - write_file_node(); + if(!_(flags).contains(O_CREATE)) { + callback(new ENoEntry('O_CREATE is not set and the named file does not exist')); } else { - callback(error); + write_file_node(); } } } @@ -105,9 +124,6 @@ define(function(require) { callback(undefined, '!'); } }; - - var parentPath = dirname(path); - find_node(objectStore, parentPath, read_directory_data); }; return { diff --git a/src/object-store.js b/src/object-store.js index 1022377..8e6e944 100644 --- a/src/object-store.js +++ b/src/object-store.js @@ -2,7 +2,7 @@ define(function(require) { var ENoEntry = require('src/error').ENoEntry; var ENotDirectory = require('src/error').ENotDirectory; - var EPathExists = require('src/error').EPathExists; + var EExists = require('src/error').EExists; var normalize = require('src/path').normalize; var dirname = require('src/path').dirname; @@ -17,6 +17,9 @@ define(function(require) { // out: node structure, or error function find_node(objectStore, path, callback) { path = normalize(path); + if(!path) { + return callback(new ENoEntry('path is an empty string')); + } var name = basename(path); if(ROOT_DIRECTORY_NAME == name) { @@ -24,7 +27,7 @@ define(function(require) { if(error) { callback(error); } else if(!rootDirectoryNode) { - callback(new ENoEntry()); + callback(new ENoEntry('path does not exist')); } else { callback(undefined, rootDirectoryNode); } @@ -38,7 +41,7 @@ define(function(require) { if(error) { callback(error); } else if(!_(parentDirectoryNode).has('data') || !parentDirectoryNode.type == MODE_DIRECTORY) { - callback(new ENotDirectory()); + callback(new ENotDirectory('a component of the path prefix is not a directory')); } else { read_object(objectStore, parentDirectoryNode.data, get_node_id_from_parent_directory_data); } @@ -51,7 +54,7 @@ define(function(require) { callback(error); } else { if(!_(parentDirectoryData).has(name)) { - callback(new ENoEntry()); + callback(new ENoEntry('path does not exist')); } else { var nodeId = parentDirectoryData[name].id; read_object(objectStore, nodeId, callback);