2013-05-31 01:38:44 +00:00
|
|
|
define(function(require) {
|
|
|
|
|
|
|
|
var _ = require('lodash');
|
|
|
|
|
2013-11-08 20:33:44 +00:00
|
|
|
// TextEncoder and TextDecoder will either already be present, or use this shim.
|
|
|
|
// Because of the way the spec is defined, we need to get them off the global.
|
|
|
|
require('encoding-indexes');
|
|
|
|
require('encoding');
|
|
|
|
|
2013-06-22 15:33:08 +00:00
|
|
|
var normalize = require('src/path').normalize;
|
|
|
|
var dirname = require('src/path').dirname;
|
|
|
|
var basename = require('src/path').basename;
|
|
|
|
|
2013-05-31 01:38:44 +00:00
|
|
|
var guid = require('src/shared').guid;
|
|
|
|
var hash = require('src/shared').hash;
|
|
|
|
var nop = require('src/shared').nop;
|
|
|
|
|
2013-05-31 19:03:18 +00:00
|
|
|
var EExists = require('src/error').EExists;
|
2013-05-31 01:38:44 +00:00
|
|
|
var EIsDirectory = require('src/error').EIsDirectory;
|
|
|
|
var ENoEntry = require('src/error').ENoEntry;
|
|
|
|
var EBusy = require('src/error').EBusy;
|
|
|
|
var ENotEmpty = require('src/error').ENotEmpty;
|
|
|
|
var ENotDirectory = require('src/error').ENotDirectory;
|
|
|
|
var EBadFileDescriptor = require('src/error').EBadFileDescriptor;
|
|
|
|
var ENotImplemented = require('src/error').ENotImplemented;
|
|
|
|
var ENotMounted = require('src/error').ENotMounted;
|
2013-05-31 19:03:18 +00:00
|
|
|
var EInvalid = require('src/error').EInvalid;
|
2013-06-22 15:33:08 +00:00
|
|
|
var EIO = require('src/error').EIO;
|
2013-11-23 18:34:48 +00:00
|
|
|
var ELoop = require('src/error').ELoop;
|
2013-07-12 15:11:05 +00:00
|
|
|
var EFileSystemError = require('src/error').EFileSystemError;
|
2013-05-31 01:38:44 +00:00
|
|
|
|
|
|
|
var FS_FORMAT = require('src/constants').FS_FORMAT;
|
2013-06-22 15:33:08 +00:00
|
|
|
var MODE_FILE = require('src/constants').MODE_FILE;
|
|
|
|
var MODE_DIRECTORY = require('src/constants').MODE_DIRECTORY;
|
2013-11-23 18:34:32 +00:00
|
|
|
var MODE_SYMBOLIC_LINK = require('src/constants').MODE_SYMBOLIC_LINK;
|
2013-06-22 15:33:08 +00:00
|
|
|
var ROOT_DIRECTORY_NAME = require('src/constants').ROOT_DIRECTORY_NAME;
|
|
|
|
var ROOT_NODE_ID = require('src/constants').ROOT_NODE_ID;
|
2013-11-23 18:34:48 +00:00
|
|
|
var SYMLOOP_MAX = require('src/constants').SYMLOOP_MAX;
|
2013-07-12 15:11:05 +00:00
|
|
|
var FS_READY = require('src/constants').FS_READY;
|
2013-05-31 01:38:44 +00:00
|
|
|
var FS_PENDING = require('src/constants').FS_PENDING;
|
|
|
|
var FS_ERROR = require('src/constants').FS_ERROR;
|
2013-06-22 15:33:08 +00:00
|
|
|
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;
|
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
var Providers = require('src/providers/providers');
|
|
|
|
var FileSystemsManager = require('src/filesystems-manager');
|
|
|
|
|
2013-06-22 15:33:08 +00:00
|
|
|
/*
|
|
|
|
* DirectoryEntry
|
|
|
|
*/
|
|
|
|
|
|
|
|
function DirectoryEntry(id, type) {
|
|
|
|
this.id = id;
|
|
|
|
this.type = type || MODE_FILE;
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* OpenFileDescription
|
|
|
|
*/
|
|
|
|
|
|
|
|
function OpenFileDescription(id, flags, position) {
|
|
|
|
this.id = id;
|
|
|
|
this.flags = flags;
|
|
|
|
this.position = position;
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Node
|
|
|
|
*/
|
|
|
|
|
|
|
|
function Node(id, mode, size, atime, ctime, mtime, flags, xattrs, nlinks, version) {
|
|
|
|
var now = Date.now();
|
|
|
|
|
2013-11-08 20:33:44 +00:00
|
|
|
this.id = id || hash(guid());
|
2013-06-22 15:33:08 +00:00
|
|
|
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.mtime = mtime || now; // modified time
|
|
|
|
this.flags = flags || []; // file flags
|
|
|
|
this.xattrs = xattrs || {}; // extended attributes
|
|
|
|
this.nlinks = nlinks || 0; // links count
|
|
|
|
this.version = version || 0; // node version
|
2013-07-12 15:11:05 +00:00
|
|
|
this.blksize = undefined; // block size
|
|
|
|
this.nblocks = 1; // blocks count
|
|
|
|
this.data = hash(guid()); // id for data object
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
2013-07-29 20:30:24 +00:00
|
|
|
/*
|
|
|
|
* Stats
|
|
|
|
*/
|
|
|
|
|
|
|
|
function Stats(fileNode, devName) {
|
|
|
|
this.node = fileNode.id;
|
|
|
|
this.dev = devName;
|
|
|
|
this.size = fileNode.size;
|
|
|
|
this.nlinks = fileNode.nlinks;
|
|
|
|
this.atime = fileNode.atime;
|
|
|
|
this.mtime = fileNode.mtime;
|
|
|
|
this.ctime = fileNode.ctime;
|
|
|
|
this.type = fileNode.mode;
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-07-29 20:30:24 +00:00
|
|
|
|
2013-06-22 15:33:08 +00:00
|
|
|
/*
|
|
|
|
* find_node
|
|
|
|
*/
|
|
|
|
|
|
|
|
// in: file or directory path
|
|
|
|
// out: node structure, or error
|
2013-11-22 21:12:31 +00:00
|
|
|
function find_node(context, path, callback) {
|
2013-06-22 15:33:08 +00:00
|
|
|
path = normalize(path);
|
|
|
|
if(!path) {
|
|
|
|
return callback(new ENoEntry('path is an empty string'));
|
|
|
|
}
|
|
|
|
var name = basename(path);
|
2013-07-12 15:11:05 +00:00
|
|
|
var parentPath = dirname(path);
|
2013-11-23 18:34:48 +00:00
|
|
|
var followedCount = 0;
|
2013-06-22 15:33:08 +00:00
|
|
|
|
2013-11-12 18:14:23 +00:00
|
|
|
function check_root_directory_node(error, rootDirectoryNode) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else if(!rootDirectoryNode) {
|
|
|
|
callback(new ENoEntry('path does not exist'));
|
|
|
|
} else {
|
|
|
|
callback(undefined, rootDirectoryNode);
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-11-12 18:14:23 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
2013-11-12 18:14:23 +00:00
|
|
|
// in: parent directory node
|
|
|
|
// out: parent directory data
|
|
|
|
function read_parent_directory_data(error, parentDirectoryNode) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
2013-11-21 00:24:49 +00:00
|
|
|
} else if(parentDirectoryNode.mode !== MODE_DIRECTORY || !parentDirectoryNode.data) {
|
2013-11-12 18:14:23 +00:00
|
|
|
callback(new ENotDirectory('a component of the path prefix is not a directory'));
|
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
context.get(parentDirectoryNode.data, get_node_from_parent_directory_data);
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-11-12 18:14:23 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
2013-11-12 18:14:23 +00:00
|
|
|
// in: parent directory data
|
2013-11-23 18:34:48 +00:00
|
|
|
// out: searched node
|
|
|
|
function get_node_from_parent_directory_data(error, parentDirectoryData) {
|
2013-11-12 18:14:23 +00:00
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
if(!_(parentDirectoryData).has(name)) {
|
|
|
|
callback(new ENoEntry('path does not exist'));
|
2013-06-22 15:33:08 +00:00
|
|
|
} else {
|
2013-11-12 18:14:23 +00:00
|
|
|
var nodeId = parentDirectoryData[name].id;
|
2013-11-22 21:12:31 +00:00
|
|
|
context.get(nodeId, is_symbolic_link);
|
2013-06-22 15:33:08 +00:00
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-11-12 18:14:23 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
2013-11-23 18:34:48 +00:00
|
|
|
function is_symbolic_link(error, node) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
if(node.mode == MODE_SYMBOLIC_LINK) {
|
|
|
|
followedCount++;
|
|
|
|
if(followedCount > SYMLOOP_MAX){
|
|
|
|
callback(new ELoop('too many symbolic links were encountered'));
|
|
|
|
} else {
|
|
|
|
follow_symbolic_link(node.data);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
callback(undefined, node);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function follow_symbolic_link(data) {
|
|
|
|
data = normalize(data);
|
|
|
|
parentPath = dirname(data);
|
|
|
|
name = basename(data);
|
|
|
|
if(ROOT_DIRECTORY_NAME == name) {
|
2013-11-22 21:12:31 +00:00
|
|
|
context.get(ROOT_NODE_ID, check_root_directory_node);
|
2013-11-23 18:34:48 +00:00
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
find_node(context, parentPath, read_parent_directory_data);
|
2013-11-23 18:34:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-12 18:14:23 +00:00
|
|
|
if(ROOT_DIRECTORY_NAME == name) {
|
2013-11-22 21:12:31 +00:00
|
|
|
context.get(ROOT_NODE_ID, check_root_directory_node);
|
2013-11-12 18:14:23 +00:00
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
find_node(context, parentPath, read_parent_directory_data);
|
2013-06-22 15:33:08 +00:00
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* make_root_directory
|
|
|
|
*/
|
|
|
|
|
|
|
|
// Note: this should only be invoked when formatting a new file system
|
2013-11-22 21:12:31 +00:00
|
|
|
function make_root_directory(context, callback) {
|
2013-06-22 15:33:08 +00:00
|
|
|
var directoryNode;
|
|
|
|
var directoryData;
|
|
|
|
|
|
|
|
function write_directory_node(error, existingNode) {
|
|
|
|
if(!error && existingNode) {
|
|
|
|
callback(new EExists());
|
|
|
|
} else if(error && !error instanceof ENoEntry) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
directoryNode = new Node(ROOT_NODE_ID, MODE_DIRECTORY);
|
|
|
|
directoryNode.nlinks += 1;
|
2013-11-22 21:12:31 +00:00
|
|
|
context.put(directoryNode.id, directoryNode, write_directory_data);
|
2013-06-22 15:33:08 +00:00
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
|
|
|
function write_directory_data(error) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
directoryData = {};
|
2013-11-22 21:12:31 +00:00
|
|
|
context.put(directoryNode.data, directoryData, callback);
|
2013-06-22 15:33:08 +00:00
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
find_node(context, ROOT_DIRECTORY_NAME, write_directory_node);
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* make_directory
|
|
|
|
*/
|
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function make_directory(context, path, callback) {
|
2013-06-22 15:33:08 +00:00
|
|
|
path = normalize(path);
|
|
|
|
var name = basename(path);
|
|
|
|
var parentPath = dirname(path);
|
|
|
|
|
|
|
|
var directoryNode;
|
|
|
|
var directoryData;
|
|
|
|
var parentDirectoryNode;
|
|
|
|
var parentDirectoryData;
|
|
|
|
|
|
|
|
function check_if_directory_exists(error, result) {
|
|
|
|
if(!error && result) {
|
|
|
|
callback(new EExists());
|
|
|
|
} else if(error && !error instanceof ENoEntry) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
find_node(context, parentPath, read_parent_directory_data);
|
2013-06-22 15:33:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function read_parent_directory_data(error, result) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
parentDirectoryNode = result;
|
2013-11-22 21:12:31 +00:00
|
|
|
context.get(parentDirectoryNode.data, write_directory_node);
|
2013-06-22 15:33:08 +00:00
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
|
|
|
function write_directory_node(error, result) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
parentDirectoryData = result;
|
|
|
|
directoryNode = new Node(undefined, MODE_DIRECTORY);
|
|
|
|
directoryNode.nlinks += 1;
|
2013-11-22 21:12:31 +00:00
|
|
|
context.put(directoryNode.id, directoryNode, write_directory_data);
|
2013-06-22 15:33:08 +00:00
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
|
|
|
function write_directory_data(error) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
directoryData = {};
|
2013-11-22 21:12:31 +00:00
|
|
|
context.put(directoryNode.data, directoryData, update_parent_directory_data);
|
2013-06-22 15:33:08 +00:00
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
|
|
|
function update_parent_directory_data(error) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
parentDirectoryData[name] = new DirectoryEntry(directoryNode.id, MODE_DIRECTORY);
|
2013-11-22 21:12:31 +00:00
|
|
|
context.put(parentDirectoryNode.data, parentDirectoryData, callback);
|
2013-06-22 15:33:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
find_node(context, path, check_if_directory_exists);
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* remove_directory
|
|
|
|
*/
|
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function remove_directory(context, path, callback) {
|
2013-06-22 15:33:08 +00:00
|
|
|
path = normalize(path);
|
|
|
|
var name = basename(path);
|
|
|
|
var parentPath = dirname(path);
|
|
|
|
|
|
|
|
var directoryNode;
|
|
|
|
var directoryData;
|
|
|
|
var parentDirectoryNode;
|
|
|
|
var parentDirectoryData;
|
|
|
|
|
2013-11-23 18:35:10 +00:00
|
|
|
function read_parent_directory_data(error, result) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
parentDirectoryNode = result;
|
2013-11-22 21:12:31 +00:00
|
|
|
context.get(parentDirectoryNode.data, check_if_node_exists);
|
2013-11-23 18:35:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function check_if_node_exists(error, result) {
|
2013-06-22 15:33:08 +00:00
|
|
|
if(error) {
|
|
|
|
callback(error);
|
2013-07-15 15:52:41 +00:00
|
|
|
} else if(ROOT_DIRECTORY_NAME == name) {
|
|
|
|
callback(new EBusy());
|
2013-11-23 18:35:10 +00:00
|
|
|
} else if(!_(result).has(name)) {
|
2013-06-22 15:33:08 +00:00
|
|
|
callback(new ENoEntry());
|
2013-11-23 18:35:10 +00:00
|
|
|
} else {
|
|
|
|
parentDirectoryData = result;
|
|
|
|
directoryNode = parentDirectoryData[name].id;
|
2013-11-22 21:12:31 +00:00
|
|
|
context.get(directoryNode, check_if_node_is_directory);
|
2013-11-23 18:35:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function check_if_node_is_directory(error, result) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else if(result.mode != MODE_DIRECTORY) {
|
|
|
|
callback(new ENotDirectory());
|
2013-06-22 15:33:08 +00:00
|
|
|
} else {
|
|
|
|
directoryNode = result;
|
2013-11-22 21:12:31 +00:00
|
|
|
context.get(directoryNode.data, check_if_directory_is_empty);
|
2013-06-22 15:33:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function check_if_directory_is_empty(error, result) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
directoryData = result;
|
|
|
|
if(_(directoryData).size() > 0) {
|
|
|
|
callback(new ENotEmpty());
|
|
|
|
} else {
|
2013-11-23 18:35:10 +00:00
|
|
|
remove_directory_entry_from_parent_directory_node();
|
2013-06-22 15:33:08 +00:00
|
|
|
}
|
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
2013-11-23 18:35:10 +00:00
|
|
|
function remove_directory_entry_from_parent_directory_node() {
|
|
|
|
delete parentDirectoryData[name];
|
2013-11-22 21:12:31 +00:00
|
|
|
context.put(parentDirectoryNode.data, parentDirectoryData, remove_directory_node);
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
|
|
|
function remove_directory_node(error) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
context.delete(directoryNode.id, remove_directory_data);
|
2013-06-22 15:33:08 +00:00
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
|
|
|
function remove_directory_data(error) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
context.delete(directoryNode.data, callback);
|
2013-06-22 15:33:08 +00:00
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
find_node(context, parentPath, read_parent_directory_data);
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function open_file(context, path, flags, callback) {
|
2013-06-22 15:33:08 +00:00
|
|
|
path = normalize(path);
|
|
|
|
var name = basename(path);
|
|
|
|
var parentPath = dirname(path);
|
|
|
|
|
|
|
|
var directoryNode;
|
|
|
|
var directoryData;
|
|
|
|
var directoryEntry;
|
|
|
|
var fileNode;
|
|
|
|
var fileData;
|
|
|
|
|
2013-11-23 18:35:23 +00:00
|
|
|
var followedCount = 0;
|
|
|
|
|
2013-07-19 15:22:23 +00:00
|
|
|
if(ROOT_DIRECTORY_NAME == name) {
|
|
|
|
if(_(flags).contains(O_WRITE)) {
|
2013-11-08 20:33:44 +00:00
|
|
|
callback(new EIsDirectory('the named file is a directory and O_WRITE is set'));
|
2013-07-19 15:22:23 +00:00
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
find_node(context, path, set_file_node);
|
2013-07-19 15:22:23 +00:00
|
|
|
}
|
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
find_node(context, parentPath, read_directory_data);
|
2013-07-19 15:22:23 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
|
|
|
function read_directory_data(error, result) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
directoryNode = result;
|
2013-11-22 21:12:31 +00:00
|
|
|
context.get(directoryNode.data, check_if_file_exists);
|
2013-06-22 15:33:08 +00:00
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
|
|
|
function check_if_file_exists(error, result) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
directoryData = result;
|
|
|
|
if(_(directoryData).has(name)) {
|
|
|
|
if(_(flags).contains(O_EXCLUSIVE)) {
|
2013-11-08 20:33:44 +00:00
|
|
|
callback(new ENoEntry('O_CREATE and O_EXCLUSIVE are set, and the named file exists'));
|
2013-06-22 15:33:08 +00:00
|
|
|
} else {
|
|
|
|
directoryEntry = directoryData[name];
|
2013-07-19 15:22:23 +00:00
|
|
|
if(directoryEntry.type == MODE_DIRECTORY && _(flags).contains(O_WRITE)) {
|
2013-11-08 20:33:44 +00:00
|
|
|
callback(new EIsDirectory('the named file is a directory and O_WRITE is set'));
|
2013-06-22 15:33:08 +00:00
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
context.get(directoryEntry.id, check_if_symbolic_link);
|
2013-06-22 15:33:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if(!_(flags).contains(O_CREATE)) {
|
|
|
|
callback(new ENoEntry('O_CREATE is not set and the named file does not exist'));
|
|
|
|
} else {
|
|
|
|
write_file_node();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
2013-11-23 18:35:23 +00:00
|
|
|
function check_if_symbolic_link(error, result) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
var node = result;
|
|
|
|
if(node.mode == MODE_SYMBOLIC_LINK) {
|
|
|
|
followedCount++;
|
|
|
|
if(followedCount > SYMLOOP_MAX){
|
|
|
|
callback(new ELoop('too many symbolic links were encountered'));
|
|
|
|
} else {
|
|
|
|
follow_symbolic_link(node.data);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
set_file_node(undefined, node);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function follow_symbolic_link(data) {
|
|
|
|
data = normalize(data);
|
|
|
|
parentPath = dirname(data);
|
|
|
|
name = basename(data);
|
|
|
|
if(ROOT_DIRECTORY_NAME == name) {
|
|
|
|
if(_(flags).contains(O_WRITE)) {
|
|
|
|
callback(new EIsDirectory('the named file is a directory and O_WRITE is set'));
|
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
find_node(context, path, set_file_node);
|
2013-11-23 18:35:23 +00:00
|
|
|
}
|
|
|
|
}
|
2013-11-22 21:12:31 +00:00
|
|
|
find_node(context, parentPath, read_directory_data);
|
2013-11-23 18:35:23 +00:00
|
|
|
}
|
|
|
|
|
2013-06-22 15:33:08 +00:00
|
|
|
function set_file_node(error, result) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
fileNode = result;
|
|
|
|
callback(undefined, fileNode);
|
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
|
|
|
function write_file_node() {
|
|
|
|
fileNode = new Node(undefined, MODE_FILE);
|
|
|
|
fileNode.nlinks += 1;
|
2013-11-22 21:12:31 +00:00
|
|
|
context.put(fileNode.id, fileNode, write_file_data);
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
|
|
|
function write_file_data(error) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
2013-07-22 17:08:35 +00:00
|
|
|
fileData = new Uint8Array(0);
|
2013-11-22 21:12:31 +00:00
|
|
|
context.put(fileNode.data, fileData, update_directory_data);
|
2013-06-22 15:33:08 +00:00
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
|
|
|
function update_directory_data(error) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
directoryData[name] = new DirectoryEntry(fileNode.id, MODE_FILE);
|
2013-11-22 21:12:31 +00:00
|
|
|
context.put(directoryNode.data, directoryData, handle_update_result);
|
2013-06-22 15:33:08 +00:00
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
|
|
|
function handle_update_result(error) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
callback(undefined, fileNode);
|
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function write_data(context, ofd, buffer, offset, length, position, callback) {
|
2013-06-22 15:33:08 +00:00
|
|
|
var fileNode;
|
|
|
|
var fileData;
|
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function return_nbytes(error) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
callback(undefined, length);
|
|
|
|
}
|
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function update_file_node(error) {
|
2013-06-22 15:33:08 +00:00
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
context.put(fileNode.id, fileNode, return_nbytes);
|
2013-06-22 15:33:08 +00:00
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
|
|
|
function update_file_data(error, result) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
fileData = result;
|
2013-07-29 18:55:25 +00:00
|
|
|
var _position = (!(undefined === position || null === position)) ? position : ofd.position;
|
2013-06-22 15:33:08 +00:00
|
|
|
var newSize = Math.max(fileData.length, _position + length);
|
|
|
|
var newData = new Uint8Array(newSize);
|
|
|
|
if(fileData) {
|
|
|
|
newData.set(fileData);
|
|
|
|
}
|
|
|
|
newData.set(buffer, _position);
|
|
|
|
if(undefined === position) {
|
|
|
|
ofd.position += length;
|
|
|
|
}
|
|
|
|
|
|
|
|
fileNode.size = newSize;
|
|
|
|
fileNode.mtime = Date.now();
|
|
|
|
fileNode.version += 1;
|
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
context.put(fileNode.data, newData, update_file_node);
|
2013-06-22 15:33:08 +00:00
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function read_file_data(error, result) {
|
2013-06-22 15:33:08 +00:00
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
fileNode = result;
|
|
|
|
context.get(fileNode.data, update_file_data);
|
2013-06-22 15:33:08 +00:00
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
context.get(ofd.id, read_file_data);
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-05-31 01:38:44 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function read_data(context, ofd, buffer, offset, length, position, callback) {
|
2013-06-22 15:33:08 +00:00
|
|
|
var fileNode;
|
|
|
|
var fileData;
|
2013-05-31 01:38:44 +00:00
|
|
|
|
2013-06-22 15:33:08 +00:00
|
|
|
function handle_file_data(error, result) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
fileData = result;
|
2013-07-29 18:55:25 +00:00
|
|
|
var _position = (!(undefined === position || null === position)) ? position : ofd.position;
|
2013-06-22 15:33:08 +00:00
|
|
|
length = (_position + length > buffer.length) ? length - _position : length;
|
|
|
|
var dataView = fileData.subarray(_position, _position + length);
|
2013-07-22 17:08:35 +00:00
|
|
|
buffer.set(dataView, offset);
|
2013-06-22 15:33:08 +00:00
|
|
|
if(undefined === position) {
|
|
|
|
ofd.position += length;
|
|
|
|
}
|
|
|
|
callback(undefined, length);
|
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-11-22 21:12:31 +00:00
|
|
|
|
|
|
|
function read_file_data(error, result) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
fileNode = result;
|
|
|
|
context.get(fileNode.data, handle_file_data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
context.get(ofd.id, read_file_data);
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-05-31 07:52:04 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function stat_file(context, path, callback) {
|
2013-07-12 15:11:05 +00:00
|
|
|
path = normalize(path);
|
|
|
|
var name = basename(path);
|
|
|
|
|
|
|
|
function check_file(error, result) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
callback(undefined, result);
|
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-07-12 15:11:05 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
find_node(context, path, check_file);
|
|
|
|
}
|
2013-07-29 18:55:25 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function fstat_file(context, ofd, callback) {
|
2013-07-29 18:55:25 +00:00
|
|
|
function check_file(error, result) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
callback(undefined, result);
|
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-11-22 21:12:31 +00:00
|
|
|
|
|
|
|
context.get(ofd.id, check_file);
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-07-29 18:55:25 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function lstat_file(context, path, callback) {
|
2013-11-23 18:34:57 +00:00
|
|
|
path = normalize(path);
|
|
|
|
var name = basename(path);
|
|
|
|
var parentPath = dirname(path);
|
|
|
|
|
|
|
|
var directoryNode;
|
|
|
|
var directoryData;
|
|
|
|
|
|
|
|
if(ROOT_DIRECTORY_NAME == name) {
|
2013-11-22 21:12:31 +00:00
|
|
|
context.get(ROOT_NODE_ID, check_file);
|
2013-11-23 18:34:57 +00:00
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
find_node(context, parentPath, read_directory_data);
|
2013-11-23 18:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function read_directory_data(error, result) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
directoryNode = result;
|
2013-11-22 21:12:31 +00:00
|
|
|
context.get(directoryNode.data, check_if_file_exists);
|
2013-11-23 18:34:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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 {
|
2013-11-22 21:12:31 +00:00
|
|
|
context.get(directoryData[name].id, check_file);
|
2013-11-23 18:34:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function check_file(error, result) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
callback(undefined, result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function link_node(context, oldpath, newpath, callback) {
|
2013-07-26 02:49:53 +00:00
|
|
|
oldpath = normalize(oldpath);
|
|
|
|
var oldname = basename(oldpath);
|
|
|
|
var oldParentPath = dirname(oldpath);
|
|
|
|
|
|
|
|
newpath = normalize(newpath);
|
|
|
|
var newname = basename(newpath);
|
|
|
|
var newParentPath = dirname(newpath);
|
|
|
|
|
|
|
|
var oldDirectoryNode;
|
|
|
|
var oldDirectoryData;
|
|
|
|
var newDirectoryNode;
|
|
|
|
var newDirectoryData;
|
|
|
|
var fileNode;
|
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function update_file_node(error, result) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
fileNode = result;
|
|
|
|
fileNode.nlinks += 1;
|
|
|
|
context.put(fileNode.id, fileNode, callback);
|
|
|
|
}
|
|
|
|
}
|
2013-07-26 02:49:53 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function read_directory_entry(error, result) {
|
2013-07-26 02:49:53 +00:00
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
context.get(newDirectoryData[newname].id, update_file_node);
|
2013-07-26 02:49:53 +00:00
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-07-26 02:49:53 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function check_if_new_file_exists(error, result) {
|
2013-07-26 02:49:53 +00:00
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
newDirectoryData = result;
|
|
|
|
if(_(newDirectoryData).has(newname)) {
|
|
|
|
callback(new EExists('newpath resolves to an existing file'));
|
2013-07-26 02:49:53 +00:00
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
newDirectoryData[newname] = oldDirectoryData[oldname];
|
|
|
|
context.put(newDirectoryNode.data, newDirectoryData, read_directory_entry);
|
2013-07-26 02:49:53 +00:00
|
|
|
}
|
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-07-26 02:49:53 +00:00
|
|
|
|
|
|
|
function read_new_directory_data(error, result) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
newDirectoryNode = result;
|
2013-11-22 21:12:31 +00:00
|
|
|
context.get(newDirectoryNode.data, check_if_new_file_exists);
|
2013-07-26 02:49:53 +00:00
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-07-26 02:49:53 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function check_if_old_file_exists(error, result) {
|
2013-07-26 02:49:53 +00:00
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
oldDirectoryData = result;
|
|
|
|
if(!_(oldDirectoryData).has(oldname)) {
|
|
|
|
callback(new ENoEntry('a component of either path prefix does not exist'));
|
2013-07-26 02:49:53 +00:00
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
find_node(context, newParentPath, read_new_directory_data);
|
2013-07-26 02:49:53 +00:00
|
|
|
}
|
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-07-26 02:49:53 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function read_old_directory_data(error, result) {
|
2013-07-26 02:49:53 +00:00
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
oldDirectoryNode = result;
|
|
|
|
context.get(oldDirectoryNode.data, check_if_old_file_exists);
|
2013-07-26 02:49:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
find_node(context, oldParentPath, read_old_directory_data);
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-07-26 04:15:48 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function unlink_node(context, path, callback) {
|
2013-07-26 04:15:48 +00:00
|
|
|
path = normalize(path);
|
2013-11-23 18:35:31 +00:00
|
|
|
var name = basename(path);
|
|
|
|
var parentPath = dirname(path);
|
2013-07-26 04:15:48 +00:00
|
|
|
|
|
|
|
var directoryNode;
|
|
|
|
var directoryData;
|
|
|
|
var fileNode;
|
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function update_directory_data(error) {
|
2013-07-26 04:15:48 +00:00
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
delete directoryData[name];
|
|
|
|
context.put(directoryNode.data, directoryData, callback);
|
2013-07-26 04:15:48 +00:00
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-07-26 04:15:48 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function delete_file_data(error) {
|
2013-07-26 02:49:53 +00:00
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
context.delete(fileNode.data, update_directory_data);
|
2013-07-26 02:49:53 +00:00
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-07-26 02:49:53 +00:00
|
|
|
|
|
|
|
function update_file_node(error, result) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
fileNode = result;
|
2013-07-26 04:15:48 +00:00
|
|
|
fileNode.nlinks -= 1;
|
|
|
|
if(fileNode.nlinks < 1) {
|
2013-11-22 21:12:31 +00:00
|
|
|
context.delete(fileNode.id, delete_file_data);
|
2013-07-26 04:15:48 +00:00
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
context.put(fileNode.id, fileNode, update_directory_data);
|
2013-07-26 04:15:48 +00:00
|
|
|
}
|
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-07-26 04:15:48 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function check_if_file_exists(error, result) {
|
2013-07-26 04:15:48 +00:00
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
directoryData = result;
|
|
|
|
if(!_(directoryData).has(name)) {
|
|
|
|
callback(new ENoEntry('a component of the path does not name an existing file'));
|
|
|
|
} else {
|
|
|
|
context.get(directoryData[name].id, update_file_node);
|
|
|
|
}
|
2013-07-26 02:49:53 +00:00
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-07-26 04:15:48 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function read_directory_data(error, result) {
|
2013-07-26 04:15:48 +00:00
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
directoryNode = result;
|
|
|
|
context.get(directoryNode.data, check_if_file_exists);
|
2013-07-26 04:15:48 +00:00
|
|
|
}
|
|
|
|
}
|
2013-11-22 21:12:31 +00:00
|
|
|
|
|
|
|
find_node(context, parentPath, read_directory_data);
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-07-26 02:49:53 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function read_directory(context, path, callback) {
|
2013-11-07 20:55:14 +00:00
|
|
|
path = normalize(path);
|
|
|
|
var name = basename(path);
|
|
|
|
|
|
|
|
var directoryNode;
|
|
|
|
var directoryData;
|
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function handle_directory_data(error, result) {
|
2013-11-07 20:55:14 +00:00
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
directoryData = result;
|
|
|
|
var files = Object.keys(directoryData);
|
|
|
|
callback(undefined, files);
|
2013-11-07 20:55:14 +00:00
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-11-07 20:55:14 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function read_directory_data(error, result) {
|
2013-11-07 20:55:14 +00:00
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
directoryNode = result;
|
|
|
|
context.get(directoryNode.data, handle_directory_data);
|
2013-11-07 20:55:14 +00:00
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-11-22 21:12:31 +00:00
|
|
|
|
|
|
|
find_node(context, path, read_directory_data);
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-11-07 20:55:14 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function make_symbolic_link(context, srcpath, dstpath, callback) {
|
2013-11-23 18:34:40 +00:00
|
|
|
dstpath = normalize(dstpath);
|
|
|
|
var name = basename(dstpath);
|
|
|
|
var parentPath = dirname(dstpath);
|
|
|
|
|
|
|
|
var directoryNode;
|
|
|
|
var directoryData;
|
|
|
|
var fileNode;
|
|
|
|
|
|
|
|
if(ROOT_DIRECTORY_NAME == name) {
|
|
|
|
callback(new EExists('the destination path already exists'));
|
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
find_node(context, parentPath, read_directory_data);
|
2013-11-23 18:34:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function read_directory_data(error, result) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
directoryNode = result;
|
2013-11-22 21:12:31 +00:00
|
|
|
context.get(directoryNode.data, check_if_file_exists);
|
2013-11-23 18:34:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function check_if_file_exists(error, result) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
directoryData = result;
|
|
|
|
if(_(directoryData).has(name)) {
|
|
|
|
callback(new EExists('the destination path already exists'));
|
|
|
|
} else {
|
|
|
|
write_file_node();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function write_file_node() {
|
|
|
|
fileNode = new Node(undefined, MODE_SYMBOLIC_LINK);
|
|
|
|
fileNode.nlinks += 1;
|
|
|
|
fileNode.size = srcpath.length;
|
|
|
|
fileNode.data = srcpath;
|
2013-11-22 21:12:31 +00:00
|
|
|
context.put(fileNode.id, fileNode, update_directory_data);
|
2013-11-23 18:34:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function update_directory_data(error) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
directoryData[name] = new DirectoryEntry(fileNode.id, MODE_SYMBOLIC_LINK);
|
2013-11-22 21:12:31 +00:00
|
|
|
context.put(directoryNode.data, directoryData, callback);
|
2013-11-23 18:34:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function read_link(context, path, callback) {
|
2013-11-23 18:34:32 +00:00
|
|
|
path = normalize(path);
|
|
|
|
var name = basename(path);
|
|
|
|
var parentPath = dirname(path);
|
|
|
|
|
|
|
|
var directoryNode;
|
|
|
|
var directoryData;
|
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
find_node(context, parentPath, read_directory_data);
|
2013-11-23 18:34:32 +00:00
|
|
|
|
|
|
|
function read_directory_data(error, result) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
directoryNode = result;
|
2013-11-22 21:12:31 +00:00
|
|
|
context.get(directoryNode.data, check_if_file_exists);
|
2013-11-23 18:34:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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 {
|
2013-11-22 21:12:31 +00:00
|
|
|
context.get(directoryData[name].id, check_if_symbolic);
|
2013-11-23 18:34:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function check_if_symbolic(error, result) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
if(result.mode != MODE_SYMBOLIC_LINK) {
|
|
|
|
callback(new EInvalid("path not a symbolic link"));
|
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
callback(undefined, result.data);
|
2013-11-23 18:34:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-09 20:12:52 +00:00
|
|
|
function validate_flags(flags) {
|
|
|
|
if(!_(O_FLAGS).has(flags)) {
|
|
|
|
return null;
|
|
|
|
}
|
2013-11-22 21:12:31 +00:00
|
|
|
return O_FLAGS[flags];
|
2013-11-09 20:12:52 +00:00
|
|
|
}
|
|
|
|
|
2013-05-31 01:38:44 +00:00
|
|
|
/*
|
|
|
|
* FileSystem
|
2013-11-22 21:12:31 +00:00
|
|
|
*
|
|
|
|
* A FileSystem takes an `options` object, which can specify a number of,
|
|
|
|
* options. All options are optional, and include:
|
|
|
|
*
|
|
|
|
* name: the name of the file system, defaults to "local"
|
|
|
|
*
|
|
|
|
* flags: one or more flags to use when creating/opening the file system.
|
|
|
|
* For example: "FORMAT" will cause the file system to be formatted.
|
|
|
|
* No explicit flags are set by default.
|
|
|
|
*
|
|
|
|
* contextProvider: a explicit constructor function to use for the file
|
|
|
|
* system's database context provider. A number of context
|
|
|
|
* providers are provided, and users can write one of their
|
|
|
|
* own and pass it in to be used. By default an IndexedDB
|
|
|
|
* provider is used.
|
|
|
|
*
|
|
|
|
* onReady: a callback function to be executed when the file system becomes
|
|
|
|
* ready for use. Depending on the context provider used, this might
|
|
|
|
* be right away, or could take some time. The onReady callback should
|
|
|
|
* check the file system's `readyState` and `error` properties to
|
|
|
|
* make sure it is usable.
|
2013-05-31 01:38:44 +00:00
|
|
|
*/
|
2013-11-22 21:12:31 +00:00
|
|
|
function FileSystem(options) {
|
|
|
|
options = options || {};
|
2013-05-31 01:38:44 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
var fs = this;
|
|
|
|
FileSystemsManager.register(fs);
|
2013-11-22 01:44:57 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
var name = options.name || "local";
|
|
|
|
var flags = options.flags;
|
|
|
|
var provider = options.provider || new Providers.Default(name);
|
|
|
|
var onReady = options.onReady || nop;
|
|
|
|
var forceFormatting = _(flags).contains(FS_FORMAT);
|
2013-11-22 01:44:57 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
fs.readyState = FS_PENDING;
|
|
|
|
fs.name = name;
|
|
|
|
fs.error = null;
|
|
|
|
|
|
|
|
provider.open(function(err, needsFormatting) {
|
|
|
|
function complete(error) {
|
|
|
|
fs.provider = provider;
|
|
|
|
if(error) {
|
|
|
|
fs.readyState = FS_ERROR;
|
|
|
|
} else {
|
|
|
|
fs.readyState = FS_READY;
|
|
|
|
FileSystemsManager.get(fs).runQueued();
|
|
|
|
}
|
|
|
|
onReady();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(err) {
|
|
|
|
return complete(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we don't need or want formatting, we're done
|
|
|
|
if(!(forceFormatting || needsFormatting)) {
|
|
|
|
return complete();
|
|
|
|
}
|
|
|
|
// otherwise format the fs first
|
|
|
|
var context = provider.getReadWriteContext();
|
|
|
|
context.clear(function(err) {
|
|
|
|
if(err) {
|
|
|
|
return complete(err);
|
|
|
|
}
|
|
|
|
make_root_directory(context, complete);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
2013-05-31 01:38:44 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function _open(fs, context, path, flags, callback) {
|
2013-11-21 00:24:49 +00:00
|
|
|
function check_result(error, fileNode) {
|
|
|
|
if(error) {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(error);
|
2013-11-21 00:24:49 +00:00
|
|
|
} else {
|
|
|
|
var position;
|
|
|
|
if(_(flags).contains(O_APPEND)) {
|
|
|
|
position = fileNode.size;
|
|
|
|
} else {
|
|
|
|
position = 0;
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-11-22 21:12:31 +00:00
|
|
|
var openFileDescription = new OpenFileDescription(fileNode.id, flags, position);
|
|
|
|
var fd = FileSystemsManager.get(fs).allocDescriptor(openFileDescription);
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(undefined, fd);
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
}
|
2013-07-19 15:22:23 +00:00
|
|
|
|
2013-11-21 00:24:49 +00:00
|
|
|
flags = validate_flags(flags);
|
|
|
|
if(!flags) {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(new EInvalid('flags is not valid'));
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
2013-05-31 07:52:04 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
open_file(context, path, flags, check_result);
|
|
|
|
}
|
|
|
|
|
|
|
|
function _close(fs, fd, callback) {
|
|
|
|
var wrapped = FileSystemsManager.get(fs);
|
|
|
|
if(!_(wrapped.openFiles).has(fd)) {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(new EBadFileDescriptor('invalid file descriptor'));
|
2013-06-22 15:33:08 +00:00
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
wrapped.releaseDescriptor(fd);
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(undefined);
|
2013-06-22 15:33:08 +00:00
|
|
|
}
|
2013-11-22 21:12:31 +00:00
|
|
|
}
|
2013-05-31 01:38:44 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function _mkdir(context, path, callback) {
|
2013-11-21 00:24:49 +00:00
|
|
|
function check_result(error) {
|
|
|
|
if(error) {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(error);
|
2013-11-21 00:24:49 +00:00
|
|
|
} else {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(undefined);
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
}
|
2013-05-31 01:38:44 +00:00
|
|
|
|
2013-11-21 00:24:49 +00:00
|
|
|
make_directory(context, path, check_result);
|
2013-11-22 21:12:31 +00:00
|
|
|
}
|
2013-05-31 01:38:44 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function _rmdir(context, path, callback) {
|
2013-11-21 00:24:49 +00:00
|
|
|
function check_result(error) {
|
|
|
|
if(error) {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(error);
|
2013-11-21 00:24:49 +00:00
|
|
|
} else {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(undefined);
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
}
|
2013-05-31 01:38:44 +00:00
|
|
|
|
2013-11-21 00:24:49 +00:00
|
|
|
remove_directory(context, path, check_result);
|
2013-11-22 21:12:31 +00:00
|
|
|
}
|
2013-07-12 15:11:05 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function _stat(context, name, path, callback) {
|
2013-11-21 00:24:49 +00:00
|
|
|
function check_result(error, result) {
|
|
|
|
if(error) {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(error);
|
2013-11-21 00:24:49 +00:00
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
var stats = new Stats(result, name);
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(undefined, stats);
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
}
|
2013-05-31 01:38:44 +00:00
|
|
|
|
2013-11-21 00:24:49 +00:00
|
|
|
stat_file(context, path, check_result);
|
2013-11-22 21:12:31 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function _fstat(fs, context, fd, callback) {
|
2013-11-21 00:24:49 +00:00
|
|
|
function check_result(error, result) {
|
|
|
|
if(error) {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(error);
|
2013-11-21 00:24:49 +00:00
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
var stats = new Stats(result, fs.name);
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(undefined, stats);
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
}
|
2013-07-29 18:55:25 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
var ofd = FileSystemsManager.get(fs).openFiles[fd];
|
2013-07-29 18:55:25 +00:00
|
|
|
|
2013-11-21 00:24:49 +00:00
|
|
|
if(!ofd) {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(new EBadFileDescriptor('invalid file descriptor'));
|
2013-11-21 00:24:49 +00:00
|
|
|
} else {
|
|
|
|
fstat_file(context, ofd, check_result);
|
|
|
|
}
|
2013-11-22 21:12:31 +00:00
|
|
|
}
|
2013-05-31 01:38:44 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function _link(context, oldpath, newpath, callback) {
|
2013-11-21 00:24:49 +00:00
|
|
|
function check_result(error) {
|
|
|
|
if(error) {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(error);
|
2013-11-21 00:24:49 +00:00
|
|
|
} else {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(undefined);
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
}
|
2013-07-23 03:34:38 +00:00
|
|
|
|
2013-11-21 00:24:49 +00:00
|
|
|
link_node(context, oldpath, newpath, check_result);
|
2013-11-22 21:12:31 +00:00
|
|
|
}
|
2013-05-31 01:38:44 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function _unlink(context, path, callback) {
|
2013-11-21 00:24:49 +00:00
|
|
|
function check_result(error) {
|
|
|
|
if(error) {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(error);
|
2013-11-21 00:24:49 +00:00
|
|
|
} else {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(undefined);
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
}
|
2013-07-26 02:49:53 +00:00
|
|
|
|
2013-11-21 00:24:49 +00:00
|
|
|
unlink_node(context, path, check_result);
|
2013-11-22 21:12:31 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function _read(fs, context, fd, buffer, offset, length, position, callback) {
|
2013-11-21 00:24:49 +00:00
|
|
|
offset = (undefined === offset) ? 0 : offset;
|
|
|
|
length = (undefined === length) ? buffer.length - offset : length;
|
2013-06-22 15:33:08 +00:00
|
|
|
|
2013-11-21 00:24:49 +00:00
|
|
|
function check_result(error, nbytes) {
|
|
|
|
if(error) {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(error);
|
2013-11-21 00:24:49 +00:00
|
|
|
} else {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(undefined, nbytes);
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
var ofd = FileSystemsManager.get(fs).openFiles[fd];
|
2013-06-22 15:33:08 +00:00
|
|
|
|
2013-11-21 00:24:49 +00:00
|
|
|
if(!ofd) {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(new EBadFileDescriptor('invalid file descriptor'));
|
2013-11-21 00:24:49 +00:00
|
|
|
} else if(!_(ofd.flags).contains(O_READ)) {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(new EBadFileDescriptor('descriptor does not permit reading'));
|
2013-11-21 00:24:49 +00:00
|
|
|
} else {
|
|
|
|
read_data(context, ofd, buffer, offset, length, position, check_result);
|
|
|
|
}
|
2013-11-22 21:12:31 +00:00
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function _readFile(fs, context, path, options, callback) {
|
2013-11-21 00:24:49 +00:00
|
|
|
if(!options) {
|
|
|
|
options = { encoding: null, flag: 'r' };
|
|
|
|
} else if(typeof options === "function") {
|
|
|
|
callback = options;
|
|
|
|
options = { encoding: null, flag: 'r' };
|
|
|
|
} else if(typeof options === "string") {
|
|
|
|
options = { encoding: options, flag: 'r' };
|
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
|
2013-11-21 00:24:49 +00:00
|
|
|
var flags = validate_flags(options.flag || 'r');
|
|
|
|
if(!flags) {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(new EInvalid('flags is not valid'));
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
open_file(context, path, flags, function(err, fileNode) {
|
2013-11-21 00:24:49 +00:00
|
|
|
if(err) {
|
2013-11-21 21:15:30 +00:00
|
|
|
return callback(err);
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
var ofd = new OpenFileDescription(fileNode.id, flags, 0);
|
2013-11-22 21:12:31 +00:00
|
|
|
var fd = FileSystemsManager.get(fs).allocDescriptor(ofd);
|
2013-11-21 00:24:49 +00:00
|
|
|
|
|
|
|
fstat_file(context, ofd, function(err2, fstatResult) {
|
|
|
|
if(err2) {
|
2013-11-21 21:15:30 +00:00
|
|
|
return callback(err2);
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
var stats = new Stats(fstatResult, fs.name);
|
2013-11-21 00:24:49 +00:00
|
|
|
var size = stats.size;
|
|
|
|
var buffer = new Uint8Array(size);
|
|
|
|
|
|
|
|
read_data(context, ofd, buffer, 0, size, 0, function(err3, nbytes) {
|
|
|
|
if(err3) {
|
2013-11-21 21:15:30 +00:00
|
|
|
return callback(err3);
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-11-22 21:12:31 +00:00
|
|
|
FileSystemsManager.get(fs).releaseDescriptor(fd);
|
2013-11-08 20:33:44 +00:00
|
|
|
|
2013-11-21 00:24:49 +00:00
|
|
|
var data;
|
|
|
|
if(options.encoding === 'utf8') {
|
|
|
|
data = new TextDecoder('utf-8').decode(buffer);
|
|
|
|
} else {
|
|
|
|
data = buffer;
|
|
|
|
}
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(undefined, data);
|
2013-11-21 00:24:49 +00:00
|
|
|
});
|
|
|
|
});
|
2013-11-08 20:33:44 +00:00
|
|
|
|
2013-11-21 00:24:49 +00:00
|
|
|
});
|
2013-11-22 21:12:31 +00:00
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function _write(fs, context, fd, buffer, offset, length, position, callback) {
|
2013-11-21 00:24:49 +00:00
|
|
|
offset = (undefined === offset) ? 0 : offset;
|
|
|
|
length = (undefined === length) ? buffer.length - offset : length;
|
|
|
|
|
|
|
|
function check_result(error, nbytes) {
|
|
|
|
if(error) {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(error);
|
2013-11-21 00:24:49 +00:00
|
|
|
} else {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(undefined, nbytes);
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
var ofd = FileSystemsManager.get(fs).openFiles[fd];
|
2013-11-21 00:24:49 +00:00
|
|
|
|
|
|
|
if(!ofd) {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(new EBadFileDescriptor('invalid file descriptor'));
|
2013-11-21 00:24:49 +00:00
|
|
|
} else if(!_(ofd.flags).contains(O_WRITE)) {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(new EBadFileDescriptor('descriptor does not permit writing'));
|
2013-11-21 00:24:49 +00:00
|
|
|
} else if(buffer.length - offset < length) {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(new EIO('intput buffer is too small'));
|
2013-11-21 00:24:49 +00:00
|
|
|
} else {
|
|
|
|
write_data(context, ofd, buffer, offset, length, position, check_result);
|
|
|
|
}
|
2013-11-22 21:12:31 +00:00
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function _writeFile(fs, context, path, data, options, callback) {
|
2013-11-21 00:24:49 +00:00
|
|
|
if(!options) {
|
|
|
|
options = { encoding: 'utf8', flag: 'w' };
|
|
|
|
} else if(typeof options === "function") {
|
|
|
|
callback = options;
|
|
|
|
options = { encoding: 'utf8', flag: 'w' };
|
|
|
|
} else if(typeof options === "string") {
|
|
|
|
options = { encoding: options, flag: 'w' };
|
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
2013-11-21 00:24:49 +00:00
|
|
|
var flags = validate_flags(options.flag || 'w');
|
|
|
|
if(!flags) {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(new EInvalid('flags is not valid'));
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(typeof data === "string" && options.encoding === 'utf8') {
|
|
|
|
data = new TextEncoder('utf-8').encode(data);
|
|
|
|
}
|
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
open_file(context, path, flags, function(err, fileNode) {
|
2013-11-21 00:24:49 +00:00
|
|
|
if(err) {
|
2013-11-21 21:15:30 +00:00
|
|
|
return callback(err);
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
var ofd = new OpenFileDescription(fileNode.id, flags, 0);
|
2013-11-22 21:12:31 +00:00
|
|
|
var fd = FileSystemsManager.get(fs).allocDescriptor(ofd);
|
2013-11-21 00:24:49 +00:00
|
|
|
|
|
|
|
write_data(context, ofd, data, 0, data.length, 0, function(err2, nbytes) {
|
|
|
|
if(err2) {
|
2013-11-21 21:15:30 +00:00
|
|
|
return callback(err2);
|
2013-11-08 20:33:44 +00:00
|
|
|
}
|
2013-11-22 21:12:31 +00:00
|
|
|
FileSystemsManager.get(fs).releaseDescriptor(fd);
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(undefined);
|
2013-11-21 00:24:49 +00:00
|
|
|
});
|
|
|
|
});
|
2013-11-22 21:12:31 +00:00
|
|
|
}
|
2013-11-21 00:24:49 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function _getxattr(path, name, callback) {
|
|
|
|
// TODO
|
|
|
|
}
|
2013-11-21 00:24:49 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function _setxattr(path, name, value, callback) {
|
|
|
|
// TODO
|
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function _lseek(fs, context, fd, offset, whence, callback) {
|
2013-11-21 00:24:49 +00:00
|
|
|
function check_result(error, offset) {
|
|
|
|
if(error) {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(error);
|
2013-11-21 00:24:49 +00:00
|
|
|
} else {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(offset);
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
2013-11-21 00:24:49 +00:00
|
|
|
function update_descriptor_position(error, stats) {
|
|
|
|
if(error) {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(error);
|
2013-11-21 00:24:49 +00:00
|
|
|
} else {
|
|
|
|
if(stats.size + offset < 0) {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(new EInvalid('resulting file offset would be negative'));
|
2013-07-22 17:08:35 +00:00
|
|
|
} else {
|
2013-11-21 00:24:49 +00:00
|
|
|
ofd.position = stats.size + offset;
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(undefined, ofd.position);
|
2013-07-22 17:08:35 +00:00
|
|
|
}
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
}
|
2013-06-22 15:33:08 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
var ofd = FileSystemsManager.get(fs).openFiles[fd];
|
2013-11-21 00:24:49 +00:00
|
|
|
|
|
|
|
if(!ofd) {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(new EBadFileDescriptor('invalid file descriptor'));
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if('SET' === whence) {
|
|
|
|
if(offset < 0) {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(new EInvalid('resulting file offset would be negative'));
|
2013-11-21 00:24:49 +00:00
|
|
|
} else {
|
|
|
|
ofd.position = offset;
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(undefined, ofd.position);
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
} else if('CUR' === whence) {
|
|
|
|
if(ofd.position + offset < 0) {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(new EInvalid('resulting file offset would be negative'));
|
2013-11-21 00:24:49 +00:00
|
|
|
} else {
|
|
|
|
ofd.position += offset;
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(undefined, ofd.position);
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
} else if('END' === whence) {
|
|
|
|
fstat_file(context, ofd, update_descriptor_position);
|
|
|
|
} else {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(new EInvalid('whence argument is not a proper value'));
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
2013-11-22 21:12:31 +00:00
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function _readdir(context, path, callback) {
|
2013-11-21 00:24:49 +00:00
|
|
|
function check_result(error, files) {
|
|
|
|
if(error) {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(error);
|
2013-11-21 00:24:49 +00:00
|
|
|
} else {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(undefined, files);
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
|
2013-11-21 00:24:49 +00:00
|
|
|
read_directory(context, path, check_result);
|
2013-11-22 21:12:31 +00:00
|
|
|
}
|
2013-11-09 19:51:21 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function _utimes(path, atime, mtime, callback) {
|
|
|
|
// TODO
|
|
|
|
}
|
2013-11-08 20:33:44 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function _rename(context, oldpath, newpath, callback) {
|
|
|
|
function check_result(error) {
|
2013-11-21 00:24:49 +00:00
|
|
|
if(error) {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(error);
|
2013-11-21 00:24:49 +00:00
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
callback(undefined);
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function unlink_old_node(error) {
|
2013-11-21 00:24:49 +00:00
|
|
|
if(error) {
|
2013-11-21 21:15:30 +00:00
|
|
|
callback(error);
|
2013-11-21 00:24:49 +00:00
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
unlink_node(context, oldpath, check_result);
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
link_node(context, oldpath, newpath, unlink_old_node);
|
|
|
|
}
|
2013-11-21 00:24:49 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function _symlink(context, srcpath, dstpath, callback) {
|
2013-11-23 18:34:40 +00:00
|
|
|
function check_result(error) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
callback(undefined);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
make_symbolic_link(context, srcpath, dstpath, check_result);
|
2013-11-22 21:12:31 +00:00
|
|
|
}
|
2013-07-29 18:55:25 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function _readlink(context, path, callback) {
|
2013-11-23 18:34:32 +00:00
|
|
|
function check_result(error, result) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
|
|
|
callback(undefined, result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
read_link(context, path, check_result);
|
2013-11-22 21:12:31 +00:00
|
|
|
}
|
2013-07-29 18:55:25 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function _realpath(fd, length, callback) {
|
|
|
|
// TODO
|
|
|
|
}
|
2013-11-21 00:24:49 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function _lstat(fs, context, path, callback) {
|
2013-11-23 18:34:57 +00:00
|
|
|
function check_result(error, result) {
|
|
|
|
if(error) {
|
|
|
|
callback(error);
|
|
|
|
} else {
|
2013-11-22 21:12:31 +00:00
|
|
|
var stats = new Stats(result, fs.name);
|
2013-11-23 18:34:57 +00:00
|
|
|
callback(undefined, stats);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
lstat_file(context, path, check_result);
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
2013-07-29 18:55:25 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function _truncate(path, length, callback) {
|
|
|
|
// TODO
|
|
|
|
}
|
2013-07-29 18:55:25 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
function _ftruncate(fd, length, callback) {
|
|
|
|
// TODO
|
|
|
|
}
|
2013-07-29 18:55:25 +00:00
|
|
|
|
2013-07-29 19:59:17 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
/**
|
|
|
|
* Public API for FileSystem
|
|
|
|
*/
|
2013-07-29 18:55:25 +00:00
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
FileSystem.prototype.open = function(path, flags, callback) {
|
2013-11-21 00:24:49 +00:00
|
|
|
var fs = this;
|
2013-11-22 21:12:31 +00:00
|
|
|
var error = FileSystemsManager.get(fs).queueOrRun(
|
2013-11-21 00:24:49 +00:00
|
|
|
function() {
|
2013-11-22 21:12:31 +00:00
|
|
|
var context = fs.provider.getReadWriteContext();
|
|
|
|
_open(fs, context, path, flags, callback);
|
2013-07-29 18:55:25 +00:00
|
|
|
}
|
|
|
|
);
|
2013-11-22 01:44:57 +00:00
|
|
|
if(error) callback(error);
|
2013-07-23 03:34:38 +00:00
|
|
|
};
|
2013-11-22 21:12:31 +00:00
|
|
|
FileSystem.prototype.close = function(fd, callback) {
|
|
|
|
_close(this, fd, callback);
|
2013-11-21 00:24:49 +00:00
|
|
|
};
|
2013-11-22 21:12:31 +00:00
|
|
|
FileSystem.prototype.mkdir = function(path, callback) {
|
2013-11-21 00:24:49 +00:00
|
|
|
var fs = this;
|
2013-11-22 21:12:31 +00:00
|
|
|
var error = FileSystemsManager.get(fs).queueOrRun(
|
2013-11-07 20:55:14 +00:00
|
|
|
function() {
|
2013-11-22 21:12:31 +00:00
|
|
|
var context = fs.provider.getReadWriteContext();
|
|
|
|
_mkdir(context, path, callback);
|
2013-11-07 20:55:14 +00:00
|
|
|
}
|
|
|
|
);
|
2013-11-22 01:44:57 +00:00
|
|
|
if(error) callback(error);
|
2013-07-29 21:58:55 +00:00
|
|
|
};
|
2013-11-22 21:12:31 +00:00
|
|
|
FileSystem.prototype.rmdir = function(path, callback) {
|
2013-11-21 00:24:49 +00:00
|
|
|
var fs = this;
|
2013-11-22 21:12:31 +00:00
|
|
|
var error = FileSystemsManager.get(fs).queueOrRun(
|
2013-11-21 00:24:49 +00:00
|
|
|
function() {
|
2013-11-22 21:12:31 +00:00
|
|
|
var context = fs.provider.getReadWriteContext();
|
|
|
|
_rmdir(context, path, callback);
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
);
|
2013-11-22 01:44:57 +00:00
|
|
|
if(error) callback(error);
|
2013-07-27 01:53:25 +00:00
|
|
|
};
|
2013-11-22 21:12:31 +00:00
|
|
|
FileSystem.prototype.stat = function(path, callback) {
|
2013-11-21 00:24:49 +00:00
|
|
|
var fs = this;
|
2013-11-22 21:12:31 +00:00
|
|
|
var error = FileSystemsManager.get(fs).queueOrRun(
|
2013-11-12 18:39:11 +00:00
|
|
|
function() {
|
2013-11-22 21:12:31 +00:00
|
|
|
var context = fs.provider.getReadWriteContext();
|
|
|
|
_stat(context, fs.name, path, callback);
|
2013-11-12 18:39:11 +00:00
|
|
|
}
|
|
|
|
);
|
2013-11-22 01:44:57 +00:00
|
|
|
if(error) callback(error);
|
2013-07-27 01:53:25 +00:00
|
|
|
};
|
2013-11-22 21:12:31 +00:00
|
|
|
FileSystem.prototype.fstat = function(fd, callback) {
|
2013-11-21 00:24:49 +00:00
|
|
|
var fs = this;
|
2013-11-22 21:12:31 +00:00
|
|
|
var error = FileSystemsManager.get(fs).queueOrRun(
|
2013-11-21 00:24:49 +00:00
|
|
|
function() {
|
2013-11-22 21:12:31 +00:00
|
|
|
var context = fs.provider.getReadWriteContext();
|
|
|
|
_fstat(fs, context, fd, callback);
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
);
|
2013-11-22 01:44:57 +00:00
|
|
|
if(error) callback(error);
|
2013-07-27 01:53:25 +00:00
|
|
|
};
|
2013-11-22 21:12:31 +00:00
|
|
|
FileSystem.prototype.link = function(oldpath, newpath, callback) {
|
2013-11-21 00:24:49 +00:00
|
|
|
var fs = this;
|
2013-11-22 21:12:31 +00:00
|
|
|
var error = FileSystemsManager.get(fs).queueOrRun(
|
2013-11-21 00:24:49 +00:00
|
|
|
function() {
|
2013-11-22 21:12:31 +00:00
|
|
|
var context = fs.provider.getReadWriteContext();
|
|
|
|
_link(context, oldpath, newpath, callback);
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
);
|
2013-11-22 01:44:57 +00:00
|
|
|
if(error) callback(error);
|
2013-05-31 01:38:44 +00:00
|
|
|
};
|
2013-11-22 21:12:31 +00:00
|
|
|
FileSystem.prototype.unlink = function(path, callback) {
|
2013-11-21 00:24:49 +00:00
|
|
|
var fs = this;
|
2013-11-22 21:12:31 +00:00
|
|
|
var error = FileSystemsManager.get(fs).queueOrRun(
|
2013-11-21 00:24:49 +00:00
|
|
|
function() {
|
2013-11-22 21:12:31 +00:00
|
|
|
var context = fs.provider.getReadWriteContext();
|
|
|
|
_unlink(context, path, callback);
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
);
|
2013-11-22 01:44:57 +00:00
|
|
|
if(error) callback(error);
|
2013-11-21 00:24:49 +00:00
|
|
|
};
|
2013-11-22 21:12:31 +00:00
|
|
|
FileSystem.prototype.read = function(fd, buffer, offset, length, position, callback) {
|
2013-11-21 00:24:49 +00:00
|
|
|
var fs = this;
|
2013-11-22 21:12:31 +00:00
|
|
|
var error = FileSystemsManager.get(fs).queueOrRun(
|
2013-11-21 00:24:49 +00:00
|
|
|
function() {
|
2013-11-22 21:12:31 +00:00
|
|
|
var context = fs.provider.getReadWriteContext();
|
|
|
|
_read(fs, context, fd, buffer, offset, length, position, callback);
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
);
|
2013-11-22 01:44:57 +00:00
|
|
|
if(error) callback(error);
|
2013-11-21 00:24:49 +00:00
|
|
|
};
|
2013-11-22 21:12:31 +00:00
|
|
|
FileSystem.prototype.readFile = function(path, options, callback) {
|
2013-11-21 00:24:49 +00:00
|
|
|
var fs = this;
|
2013-11-22 21:12:31 +00:00
|
|
|
var error = FileSystemsManager.get(fs).queueOrRun(
|
2013-11-21 00:24:49 +00:00
|
|
|
function() {
|
2013-11-22 21:12:31 +00:00
|
|
|
var context = fs.provider.getReadWriteContext();
|
|
|
|
_readFile(fs, context, path, options, callback);
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
);
|
2013-11-22 01:44:57 +00:00
|
|
|
if(error) callback(error);
|
2013-11-21 00:24:49 +00:00
|
|
|
};
|
2013-11-22 21:12:31 +00:00
|
|
|
FileSystem.prototype.write = function(fd, buffer, offset, length, position, callback) {
|
2013-11-21 00:24:49 +00:00
|
|
|
var fs = this;
|
2013-11-22 21:12:31 +00:00
|
|
|
var error = FileSystemsManager.get(fs).queueOrRun(
|
2013-11-21 00:24:49 +00:00
|
|
|
function() {
|
2013-11-22 21:12:31 +00:00
|
|
|
var context = fs.provider.getReadWriteContext();
|
|
|
|
_write(fs, context, fd, buffer, offset, length, position, callback);
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
);
|
2013-11-22 21:12:31 +00:00
|
|
|
|
2013-11-22 01:44:57 +00:00
|
|
|
if(error) callback(error);
|
2013-11-21 00:24:49 +00:00
|
|
|
};
|
2013-11-22 21:12:31 +00:00
|
|
|
FileSystem.prototype.writeFile = function(path, data, options, callback) {
|
2013-11-21 00:24:49 +00:00
|
|
|
var fs = this;
|
2013-11-22 21:12:31 +00:00
|
|
|
var error = FileSystemsManager.get(fs).queueOrRun(
|
2013-11-21 00:24:49 +00:00
|
|
|
function() {
|
2013-11-22 21:12:31 +00:00
|
|
|
var context = fs.provider.getReadWriteContext();
|
|
|
|
_writeFile(fs, context, path, data, options, callback);
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
);
|
2013-11-22 01:44:57 +00:00
|
|
|
if(error) callback(error);
|
2013-11-21 00:24:49 +00:00
|
|
|
};
|
2013-11-22 21:12:31 +00:00
|
|
|
FileSystem.prototype.lseek = function(fd, offset, whence, callback) {
|
2013-11-21 00:24:49 +00:00
|
|
|
var fs = this;
|
2013-11-22 21:12:31 +00:00
|
|
|
var error = FileSystemsManager.get(fs).queueOrRun(
|
2013-11-21 00:24:49 +00:00
|
|
|
function() {
|
2013-11-22 21:12:31 +00:00
|
|
|
var context = fs.provider.getReadWriteContext();
|
|
|
|
_lseek(fs, context, fd, offset, whence, callback);
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
);
|
2013-11-22 01:44:57 +00:00
|
|
|
if(error) callback(error);
|
2013-11-21 00:24:49 +00:00
|
|
|
};
|
2013-11-22 21:12:31 +00:00
|
|
|
FileSystem.prototype.readdir = function(path, callback) {
|
2013-11-21 00:24:49 +00:00
|
|
|
var fs = this;
|
2013-11-22 21:12:31 +00:00
|
|
|
var error = FileSystemsManager.get(fs).queueOrRun(
|
2013-11-21 00:24:49 +00:00
|
|
|
function() {
|
2013-11-22 21:12:31 +00:00
|
|
|
var context = fs.provider.getReadWriteContext();
|
|
|
|
_readdir(context, path, callback);
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
);
|
2013-11-22 01:44:57 +00:00
|
|
|
if(error) callback(error);
|
2013-11-21 00:24:49 +00:00
|
|
|
};
|
2013-11-22 21:12:31 +00:00
|
|
|
FileSystem.prototype.rename = function(oldpath, newpath, callback) {
|
2013-11-21 00:24:49 +00:00
|
|
|
var fs = this;
|
2013-11-22 21:12:31 +00:00
|
|
|
var error = FileSystemsManager.get(fs).queueOrRun(
|
2013-11-21 00:24:49 +00:00
|
|
|
function() {
|
2013-11-22 21:12:31 +00:00
|
|
|
var context = fs.provider.getReadWriteContext();
|
|
|
|
_rename(context, oldpath, newpath, callback);
|
2013-11-21 00:24:49 +00:00
|
|
|
}
|
|
|
|
);
|
2013-11-22 01:44:57 +00:00
|
|
|
if(error) callback(error);
|
2013-07-29 21:58:55 +00:00
|
|
|
};
|
2013-11-22 21:12:31 +00:00
|
|
|
FileSystem.prototype.readlink = function(path, callback) {
|
2013-11-23 18:34:32 +00:00
|
|
|
var fs = this;
|
2013-11-22 21:12:31 +00:00
|
|
|
var error = FileSystemsManager.get(fs).queueOrRun(
|
2013-11-23 18:34:32 +00:00
|
|
|
function() {
|
2013-11-22 21:12:31 +00:00
|
|
|
var context = fs.provider.getReadWriteContext();
|
|
|
|
_readlink(context, path, callback);
|
2013-11-23 18:34:32 +00:00
|
|
|
}
|
|
|
|
);
|
|
|
|
if(error) callback(error);
|
|
|
|
};
|
2013-11-22 21:12:31 +00:00
|
|
|
FileSystem.prototype.symlink = function(srcpath, dstpath, callback) {
|
2013-11-23 18:34:40 +00:00
|
|
|
var fs = this;
|
2013-11-22 21:12:31 +00:00
|
|
|
var error = FileSystemsManager.get(fs).queueOrRun(
|
2013-11-23 18:34:40 +00:00
|
|
|
function() {
|
2013-11-22 21:12:31 +00:00
|
|
|
var context = fs.provider.getReadWriteContext();
|
|
|
|
_symlink(context, srcpath, dstpath, callback);
|
2013-11-23 18:34:40 +00:00
|
|
|
}
|
|
|
|
);
|
|
|
|
if(error) callback(error);
|
|
|
|
};
|
2013-11-22 21:12:31 +00:00
|
|
|
FileSystem.prototype.lstat = function(path, callback) {
|
2013-11-23 18:34:57 +00:00
|
|
|
var fs = this;
|
2013-11-22 21:12:31 +00:00
|
|
|
var error = FileSystemsManager.get(fs).queueOrRun(
|
2013-11-23 18:34:57 +00:00
|
|
|
function() {
|
2013-11-22 21:12:31 +00:00
|
|
|
var context = fs.provider.getReadWriteContext();
|
|
|
|
_lstat(fs, context, path, callback);
|
2013-11-23 18:34:57 +00:00
|
|
|
}
|
|
|
|
);
|
|
|
|
if(error) callback(error);
|
|
|
|
};
|
2013-07-29 21:58:55 +00:00
|
|
|
|
2013-05-31 01:38:44 +00:00
|
|
|
return {
|
2013-11-22 21:12:31 +00:00
|
|
|
FileSystem: FileSystem,
|
|
|
|
Providers: Providers
|
2013-05-31 01:38:44 +00:00
|
|
|
};
|
|
|
|
|
2013-11-22 21:12:31 +00:00
|
|
|
});
|