|
|
|
File.rename = function (file1, file2, callback) {
|
|
|
|
this._addAction("rename", [file1, file2], callback);
|
|
|
|
};
|
|
|
|
|
|
|
|
File.stat = function (path, callback) {
|
|
|
|
this._addAction("stat", [path], callback);
|
|
|
|
};
|
|
|
|
|
|
|
|
File.exists = function (path, callback) {
|
|
|
|
this._addAction("stat", [path], function (status) {
|
|
|
|
callback(status == 0);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
File.cat = function (path, encoding, callback) {
|
|
|
|
var file = new File();
|
|
|
|
file.encoding = encoding;
|
|
|
|
|
|
|
|
var content = "";
|
|
|
|
if (file.encoding == "raw") content = [];
|
|
|
|
|
|
|
|
var pos = 0;
|
|
|
|
var chunkSize = 10*1024;
|
|
|
|
|
|
|
|
function readChunk () {
|
|
|
|
file.read(chunkSize, pos, function (status, chunk) {
|
|
|
|
if (chunk) {
|
|
|
|
|
|
|
|
if (chunk.constructor == String)
|
|
|
|
content += chunk;
|
|
|
|
else
|
|
|
|
content = content.concat(chunk);
|
|
|
|
|
|
|
|
pos += chunk.length;
|
|
|
|
readChunk();
|
|
|
|
} else {
|
|
|
|
callback(0, content);
|
|
|
|
file.close();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
file.open(path, "r", function (status) {
|
|
|
|
if (status == 0)
|
|
|
|
readChunk();
|
|
|
|
else
|
|
|
|
callback (status);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
File.prototype.puts = function (data, callback) {
|
|
|
|
this.write(data + "\n", -1, callback);
|
|
|
|
};
|
|
|
|
|
|
|
|
File.prototype.print = function (data, callback) {
|
|
|
|
this.write(data, -1, callback);
|
|
|
|
};
|
|
|
|
|
|
|
|
File.prototype.open = function (path, mode, callback) {
|
|
|
|
this._addAction("open", [path, mode], callback);
|
|
|
|
};
|
|
|
|
|
|
|
|
File.prototype.close = function (callback) {
|
|
|
|
this._addAction("close", [], callback);
|
|
|
|
};
|
|
|
|
|
|
|
|
File.prototype.write = function (buf, pos, callback) {
|
|
|
|
this._addAction("write", [buf, pos], callback);
|
|
|
|
};
|
|
|
|
|
|
|
|
File.prototype.read = function (length, pos, callback) {
|
|
|
|
this._addAction("read", [length, pos], callback);
|
|
|
|
};
|
|
|
|
|
|
|
|
// Some explanation of the File binding.
|
|
|
|
//
|
|
|
|
// All file operations are blocking. To get around this they are executed
|
|
|
|
// in a thread pool in C++ (libeio).
|
|
|
|
//
|
|
|
|
// The ordering of method calls to a file should be preserved, so they are
|
|
|
|
// only executed one at a time. A queue, called _actionQueue is employed.
|
|
|
|
//
|
|
|
|
// The constructor File() is implemented in C++. It initlizes
|
|
|
|
// the member _actionQueue = []
|
|
|
|
//
|
|
|
|
// Any of the methods called on a file are put into this queue. When they
|
|
|
|
// reach the head of the queue they will be executed. C++ calles the
|
|
|
|
// method _pollActions each time it becomes idle. If there is no action
|
|
|
|
// currently being executed then _pollActions will not be called. Thus when
|
|
|
|
// actions are added to an empty _actionQueue, they should be immediately
|
|
|
|
// executed.
|
|
|
|
//
|
|
|
|
// When an action has completed, the C++ side is going to look at the first
|
|
|
|
// element of _actionQueue in order to get a handle on the callback
|
|
|
|
// function. Only after that completion callback has been made can the
|
|
|
|
// action be shifted out of the queue.
|
|
|
|
//
|
|
|
|
// See File::CallTopCallback() in file.cc to see the other side of the
|
|
|
|
// binding.
|
|
|
|
File._addAction = File.prototype._addAction = function (method, args, callback) {
|
|
|
|
this._actionQueue.push({ method: method
|
|
|
|
, callback: callback
|
|
|
|
, args: args
|
|
|
|
});
|
|
|
|
if (this._actionQueue.length == 1) this._act();
|
|
|
|
}
|
|
|
|
|
|
|
|
File._act = File.prototype._act = function () {
|
|
|
|
var action = this._actionQueue[0];
|
|
|
|
if (action)
|
|
|
|
// TODO FIXME what if the action throws an error?
|
|
|
|
this["_ffi_" + action.method].apply(this, action.args);
|
|
|
|
};
|
|
|
|
|
|
|
|
// called from C++ after each action finishes
|
|
|
|
// (i.e. when it returns from the thread pool)
|
|
|
|
File._pollActions = File.prototype._pollActions = function () {
|
|
|
|
this._actionQueue.shift();
|
|
|
|
this._act();
|
|
|
|
};
|
|
|
|
|
|
|
|
var stdout = new File();
|
|
|
|
stdout.fd = File.STDOUT_FILENO;
|
|
|
|
|
|
|
|
var stderr = new File();
|
|
|
|
stderr.fd = File.STDERR_FILENO;
|
|
|
|
|
|
|
|
var stdin = new File();
|
|
|
|
stdin.fd = File.STDIN_FILENO;
|
|
|
|
|
|
|
|
this.puts = function (data, callback) {
|
|
|
|
stdout.puts(data, callback);
|
|
|
|
}
|