This commit is contained in:
Alan Kligman 2013-05-31 15:03:18 -04:00
parent 5bef87490c
commit 2d195ff6d6
8 changed files with 123 additions and 52 deletions

View File

@ -36,13 +36,13 @@ function remove_tmp_directory() {
}; };
function create_tmp_file() { function create_tmp_file() {
return fs.open('/tmp/1', 'CREATE'); return fs.open('/tmp/1', 'w+');
}; };
fs.promise.then(make_tmp_directory) fs.promise.then(make_tmp_directory)
.then(create_tmp_file) .then(create_tmp_file)
.then(function() { console.log('done'); }) .then(function() { console.log('done'); })
.otherwise(function(error) { console.error(error, error.stack); }); .otherwise(function(error) { console.error(error, error.message); });
}); });
</script> </script>

View File

@ -1,5 +1,12 @@
define(function(require) { 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 { return {
METADATA_STORE_NAME: 'metadata', METADATA_STORE_NAME: 'metadata',
FILE_STORE_NAME: 'files', FILE_STORE_NAME: 'files',
@ -17,17 +24,28 @@ define(function(require) {
ROOT_DIRECTORY_NAME: '/', // basename(normalize(path)) ROOT_DIRECTORY_NAME: '/', // basename(normalize(path))
ROOT_NODE_ID: '8a5edab282632443219e051e4ade2d1d5bbc671c781051bf1437897cbdfea0f1', // sha256(ROOT_DIRECTORY_NAME) ROOT_NODE_ID: '8a5edab282632443219e051e4ade2d1d5bbc671c781051bf1437897cbdfea0f1', // sha256(ROOT_DIRECTORY_NAME)
// FileSystem flags
FS_FORMAT: 'FORMAT', FS_FORMAT: 'FORMAT',
// Open flags O_READ: O_READ,
O_READONLY: 'READONLY', O_WRITE: O_WRITE,
O_READWRITE: 'READWRITE', O_CREATE: O_CREATE,
O_APPEND: 'APPEND', O_EXCLUSIVE: O_EXCLUSIVE,
O_CREATE: 'CREATE', O_TRUNCATE: O_TRUNCATE,
O_TRUNCATE: '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_READY: 'READY',
FS_PENDING: 'PENDING', FS_PENDING: 'PENDING',
FS_ERROR: 'ERROR', FS_ERROR: 'ERROR',

View File

@ -1,10 +1,16 @@
define(function(require) { 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 { return {
Descriptor: Descriptor, Descriptor: Descriptor
}; }
}); });

View File

@ -7,7 +7,7 @@ define(function(require) {
var ENoEntry = require('src/error').ENoEntry; var ENoEntry = require('src/error').ENoEntry;
var ENotDirectory = require('src/error').ENotDirectory; 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_FILE = require('src/constants').MODE_FILE;
var MODE_DIRECTORY = require('src/constants').MODE_DIRECTORY; var MODE_DIRECTORY = require('src/constants').MODE_DIRECTORY;
@ -28,7 +28,7 @@ define(function(require) {
function write_directory_node(error, existingNode) { function write_directory_node(error, existingNode) {
if(!error && existingNode) { if(!error && existingNode) {
callback(new EPathExists()); callback(new EExists());
} else if(error && !error instanceof ENoEntry) { } else if(error && !error instanceof ENoEntry) {
callback(error); callback(error);
} else { } else {
@ -62,7 +62,7 @@ define(function(require) {
function check_if_directory_exists(error, result) { function check_if_directory_exists(error, result) {
if(!error && result) { if(!error && result) {
callback(new EPathExists()); callback(new EExists());
} else if(error && !error instanceof ENoEntry) { } else if(error && !error instanceof ENoEntry) {
callback(error); callback(error);
} else { } else {

View File

@ -14,58 +14,85 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
define(function(require) { define(function(require) {
// 'use strict'; // 'use strict';
function EPathExists(){ Error.apply(this, arguments); } function EExists(message){
EPathExists.prototype = new Error(); this.message = message || '';
EPathExists.prototype.name = "EPathExists"; };
EPathExists.prototype.constructor = EPathExists; 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 = new Error();
EIsDirectory.prototype.name = "EIsDirectory"; EIsDirectory.prototype.name = "EIsDirectory";
EIsDirectory.prototype.constructor = EIsDirectory; EIsDirectory.prototype.constructor = EIsDirectory;
function ENoEntry(){ Error.apply(this, arguments); } function ENoEntry(message){
this.message = message || '';
};
ENoEntry.prototype = new Error(); ENoEntry.prototype = new Error();
ENoEntry.prototype.name = "ENoEntry"; ENoEntry.prototype.name = "ENoEntry";
ENoEntry.prototype.constructor = ENoEntry; ENoEntry.prototype.constructor = ENoEntry;
function EBusy(){ Error.apply(this, arguments); } function EBusy(message){
this.message = message || '';
};
EBusy.prototype = new Error(); EBusy.prototype = new Error();
EBusy.prototype.name = "EBusy"; EBusy.prototype.name = "EBusy";
EBusy.prototype.constructor = EBusy; EBusy.prototype.constructor = EBusy;
function ENotEmpty(){ Error.apply(this, arguments); } function ENotEmpty(message){
this.message = message || '';
};
ENotEmpty.prototype = new Error(); ENotEmpty.prototype = new Error();
ENotEmpty.prototype.name = "ENotEmpty"; ENotEmpty.prototype.name = "ENotEmpty";
ENotEmpty.prototype.constructor = ENotEmpty; ENotEmpty.prototype.constructor = ENotEmpty;
function ENotDirectory(){ Error.apply(this, arguments); } function ENotDirectory(message){
this.message = message || '';
};
ENotDirectory.prototype = new Error(); ENotDirectory.prototype = new Error();
ENotDirectory.prototype.name = "NotADirectoryError"; ENotDirectory.prototype.name = "ENotDirectory";
ENotDirectory.prototype.constructor = ENotDirectory; ENotDirectory.prototype.constructor = ENotDirectory;
function EBadFileDescriptor(){ Error.apply(this, arguments); } function EBadFileDescriptor(message){
this.message = message || '';
};
EBadFileDescriptor.prototype = new Error(); EBadFileDescriptor.prototype = new Error();
EBadFileDescriptor.prototype.name = "EBadFileDescriptor"; EBadFileDescriptor.prototype.name = "EBadFileDescriptor";
EBadFileDescriptor.prototype.constructor = EBadFileDescriptor; EBadFileDescriptor.prototype.constructor = EBadFileDescriptor;
function ENotImplemented(){ Error.apply(this, arguments); } function ENotImplemented(message){
this.message = message || '';
};
ENotImplemented.prototype = new Error(); ENotImplemented.prototype = new Error();
ENotImplemented.prototype.name = "ENotImplemented"; ENotImplemented.prototype.name = "ENotImplemented";
ENotImplemented.prototype.constructor = ENotImplemented; ENotImplemented.prototype.constructor = ENotImplemented;
function ENotMounted(){ Error.apply(this, arguments); } function ENotMounted(message){
this.message = message || '';
};
ENotMounted.prototype = new Error(); ENotMounted.prototype = new Error();
ENotMounted.prototype.name = "ENotMounted"; ENotMounted.prototype.name = "ENotMounted";
ENotMounted.prototype.constructor = ENotMounted; ENotMounted.prototype.constructor = ENotMounted;
function EFileExists(){ Error.apply(this, arguments); } function EInvalid(message){
EFileExists.prototype = new Error(); this.message = message || '';
EFileExists.prototype.name = "EFileExists"; };
EFileExists.prototype.constructor = EFileExists; 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 { return {
EPathExists: EPathExists, EExists: EExists,
EIsDirectory: EIsDirectory, EIsDirectory: EIsDirectory,
ENoEntry: ENoEntry, ENoEntry: ENoEntry,
EBusy: EBusy, EBusy: EBusy,
@ -74,7 +101,8 @@ define(function(require) {
EBadFileDescriptor: EBadFileDescriptor, EBadFileDescriptor: EBadFileDescriptor,
ENotImplemented: ENotImplemented, ENotImplemented: ENotImplemented,
ENotMounted: ENotMounted, ENotMounted: ENotMounted,
EFileExists: EFileExists EInvalid: EInvalid,
EIO: EIO,
}; };
}); });

View File

@ -9,7 +9,7 @@ define(function(require) {
var hash = require('src/shared').hash; var hash = require('src/shared').hash;
var nop = require('src/shared').nop; 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 EIsDirectory = require('src/error').EIsDirectory;
var ENoEntry = require('src/error').ENoEntry; var ENoEntry = require('src/error').ENoEntry;
var EBusy = require('src/error').EBusy; var EBusy = require('src/error').EBusy;
@ -18,7 +18,7 @@ define(function(require) {
var EBadFileDescriptor = require('src/error').EBadFileDescriptor; var EBadFileDescriptor = require('src/error').EBadFileDescriptor;
var ENotImplemented = require('src/error').ENotImplemented; var ENotImplemented = require('src/error').ENotImplemented;
var ENotMounted = require('src/error').ENotMounted; 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; var FS_FORMAT = require('src/constants').FS_FORMAT;
@ -100,21 +100,21 @@ define(function(require) {
this.readyState = FS_PENDING; this.readyState = FS_PENDING;
this.db = null; this.db = null;
}; };
FileSystem.prototype.open = function open(path, flags, mode) { FileSystem.prototype.open = function open(path, flags) {
var deferred = when.defer(); var deferred = when.defer();
var transaction = this.db.transaction([FILE_STORE_NAME], IDB_RW); var transaction = this.db.transaction([FILE_STORE_NAME], IDB_RW);
var files = transaction.objectStore(FILE_STORE_NAME); var files = transaction.objectStore(FILE_STORE_NAME);
function check_result(error, fd) { function check_result(error, fd) {
if(error) { if(error) {
if(transaction.error) transaction.abort(); // if(transaction.error) transaction.abort();
deferred.reject(error); deferred.reject(error);
} else { } else {
deferred.resolve(); deferred.resolve();
} }
}; };
open_file(files, path, flags, mode, check_result); open_file(files, path, flags, check_result);
return deferred.promise; return deferred.promise;
}; };

View File

@ -16,7 +16,15 @@ define(function(require) {
var delete_object = require('src/object-store').delete_object; var delete_object = require('src/object-store').delete_object;
var find_node = require('src/object-store').find_node; 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_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) { function DirectoryEntry(id, type) {
this.id = id; this.id = id;
@ -39,15 +47,24 @@ define(function(require) {
this.data = hash(this.id) // id for data object 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); path = normalize(path);
var name = basename(path); var name = basename(path);
var parentPath = dirname(path);
var directoryNode; var directoryNode;
var directoryData; var directoryData;
var fileNode; var fileNode;
var fileData; 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) { function read_directory_data(error, result) {
if(error) { if(error) {
callback(error); callback(error);
@ -63,12 +80,14 @@ define(function(require) {
} else { } else {
directoryData = result; directoryData = result;
if(_(directoryData).has(name)) { 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 { } else {
if(_(flags).contains(O_CREATE)) { if(!_(flags).contains(O_CREATE)) {
write_file_node(); callback(new ENoEntry('O_CREATE is not set and the named file does not exist'));
} else { } else {
callback(error); write_file_node();
} }
} }
} }
@ -105,9 +124,6 @@ define(function(require) {
callback(undefined, '!'); callback(undefined, '!');
} }
}; };
var parentPath = dirname(path);
find_node(objectStore, parentPath, read_directory_data);
}; };
return { return {

View File

@ -2,7 +2,7 @@ define(function(require) {
var ENoEntry = require('src/error').ENoEntry; var ENoEntry = require('src/error').ENoEntry;
var ENotDirectory = require('src/error').ENotDirectory; 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 normalize = require('src/path').normalize;
var dirname = require('src/path').dirname; var dirname = require('src/path').dirname;
@ -17,6 +17,9 @@ define(function(require) {
// out: node structure, or error // out: node structure, or error
function find_node(objectStore, path, callback) { function find_node(objectStore, path, callback) {
path = normalize(path); path = normalize(path);
if(!path) {
return callback(new ENoEntry('path is an empty string'));
}
var name = basename(path); var name = basename(path);
if(ROOT_DIRECTORY_NAME == name) { if(ROOT_DIRECTORY_NAME == name) {
@ -24,7 +27,7 @@ define(function(require) {
if(error) { if(error) {
callback(error); callback(error);
} else if(!rootDirectoryNode) { } else if(!rootDirectoryNode) {
callback(new ENoEntry()); callback(new ENoEntry('path does not exist'));
} else { } else {
callback(undefined, rootDirectoryNode); callback(undefined, rootDirectoryNode);
} }
@ -38,7 +41,7 @@ define(function(require) {
if(error) { if(error) {
callback(error); callback(error);
} else if(!_(parentDirectoryNode).has('data') || !parentDirectoryNode.type == MODE_DIRECTORY) { } 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 { } else {
read_object(objectStore, parentDirectoryNode.data, get_node_id_from_parent_directory_data); read_object(objectStore, parentDirectoryNode.data, get_node_id_from_parent_directory_data);
} }
@ -51,7 +54,7 @@ define(function(require) {
callback(error); callback(error);
} else { } else {
if(!_(parentDirectoryData).has(name)) { if(!_(parentDirectoryData).has(name)) {
callback(new ENoEntry()); callback(new ENoEntry('path does not exist'));
} else { } else {
var nodeId = parentDirectoryData[name].id; var nodeId = parentDirectoryData[name].id;
read_object(objectStore, nodeId, callback); read_object(objectStore, nodeId, callback);