|
@ -28,184 +28,242 @@ using namespace node; |
|
|
#define CTIME_SYMBOL String::NewSymbol("ctime") |
|
|
#define CTIME_SYMBOL String::NewSymbol("ctime") |
|
|
#define BAD_ARGUMENTS Exception::TypeError(String::New("Bad argument")) |
|
|
#define BAD_ARGUMENTS Exception::TypeError(String::New("Bad argument")) |
|
|
|
|
|
|
|
|
static int |
|
|
void |
|
|
AfterClose (eio_req *req) |
|
|
EIOPromise::Attach (void) |
|
|
{ |
|
|
{ |
|
|
Promise *promise = reinterpret_cast<Promise*>(req->data); |
|
|
ev_ref(EV_DEFAULT_UC); |
|
|
if (req->result == 0) { |
|
|
Promise::Attach(); |
|
|
promise->EmitSuccess(0, NULL); |
|
|
|
|
|
} else { |
|
|
|
|
|
promise->EmitError(0, NULL); |
|
|
|
|
|
} |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static Handle<Value> |
|
|
void |
|
|
Close (const Arguments& args) |
|
|
EIOPromise::Detach (void) |
|
|
|
|
|
{ |
|
|
|
|
|
Promise::Detach(); |
|
|
|
|
|
ev_unref(EV_DEFAULT_UC); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
EIOPromise* |
|
|
|
|
|
EIOPromise::Create (void) |
|
|
{ |
|
|
{ |
|
|
if (args.Length() < 1 || !args[0]->IsInt32()) |
|
|
|
|
|
return ThrowException(BAD_ARGUMENTS); |
|
|
|
|
|
HandleScope scope; |
|
|
HandleScope scope; |
|
|
int fd = args[0]->Int32Value(); |
|
|
|
|
|
|
|
|
|
|
|
Promise *promise = Promise::Create(true); |
|
|
Local<Object> handle = |
|
|
|
|
|
Promise::constructor_template->GetFunction()->NewInstance(); |
|
|
|
|
|
|
|
|
eio_close(fd, EIO_PRI_DEFAULT, AfterClose, promise); |
|
|
EIOPromise *promise = new EIOPromise(); |
|
|
return scope.Close(promise->Handle()); |
|
|
promise->Wrap(handle); |
|
|
|
|
|
|
|
|
|
|
|
promise->Attach(); |
|
|
|
|
|
|
|
|
|
|
|
return promise; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static int |
|
|
#define NODE_UNIXTIME(t) v8::Date::New(1000*static_cast<double>(t)) |
|
|
AfterRename (eio_req *req) |
|
|
int |
|
|
|
|
|
EIOPromise::After (eio_req *req) |
|
|
{ |
|
|
{ |
|
|
Promise *promise = reinterpret_cast<Promise*>(req->data); |
|
|
HandleScope scope; |
|
|
if (req->result == 0) { |
|
|
|
|
|
promise->EmitSuccess(0, NULL); |
|
|
EIOPromise *promise = reinterpret_cast<EIOPromise*>(req->data); |
|
|
} else { |
|
|
assert(req == promise->req_); |
|
|
promise->EmitError(0, NULL); |
|
|
|
|
|
|
|
|
if (req->errorno != 0) { |
|
|
|
|
|
Local<Value> exception = Exception::Error( |
|
|
|
|
|
String::NewSymbol(strerror(req->errorno))); |
|
|
|
|
|
promise->EmitError(1, &exception); |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int argc = 0; |
|
|
|
|
|
Local<Value> argv[5]; // 5 is the maximum number of args
|
|
|
|
|
|
|
|
|
|
|
|
switch (req->type) { |
|
|
|
|
|
case EIO_CLOSE: |
|
|
|
|
|
case EIO_RENAME: |
|
|
|
|
|
case EIO_UNLINK: |
|
|
|
|
|
case EIO_RMDIR: |
|
|
|
|
|
argc = 0; |
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case EIO_OPEN: |
|
|
|
|
|
case EIO_WRITE: |
|
|
|
|
|
argc = 1; |
|
|
|
|
|
argv[0] = Integer::New(req->result); |
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case EIO_STAT: |
|
|
|
|
|
{ |
|
|
|
|
|
Local<Object> stats = Object::New(); |
|
|
|
|
|
struct stat *s = reinterpret_cast<struct stat*>(req->ptr2); |
|
|
|
|
|
stats->Set(DEV_SYMBOL, Integer::New(s->st_dev)); /* ID of device containing file */ |
|
|
|
|
|
stats->Set(INO_SYMBOL, Integer::New(s->st_ino)); /* inode number */ |
|
|
|
|
|
stats->Set(MODE_SYMBOL, Integer::New(s->st_mode)); /* protection */ |
|
|
|
|
|
stats->Set(NLINK_SYMBOL, Integer::New(s->st_nlink)); /* number of hard links */ |
|
|
|
|
|
stats->Set(UID_SYMBOL, Integer::New(s->st_uid)); /* user ID of owner */ |
|
|
|
|
|
stats->Set(GID_SYMBOL, Integer::New(s->st_gid)); /* group ID of owner */ |
|
|
|
|
|
stats->Set(RDEV_SYMBOL, Integer::New(s->st_rdev)); /* device ID (if special file) */ |
|
|
|
|
|
stats->Set(SIZE_SYMBOL, Integer::New(s->st_size)); /* total size, in bytes */ |
|
|
|
|
|
stats->Set(BLKSIZE_SYMBOL, Integer::New(s->st_blksize)); /* blocksize for filesystem I/O */ |
|
|
|
|
|
stats->Set(BLOCKS_SYMBOL, Integer::New(s->st_blocks)); /* number of blocks allocated */ |
|
|
|
|
|
stats->Set(ATIME_SYMBOL, NODE_UNIXTIME(s->st_atime)); /* time of last access */ |
|
|
|
|
|
stats->Set(MTIME_SYMBOL, NODE_UNIXTIME(s->st_mtime)); /* time of last modification */ |
|
|
|
|
|
stats->Set(CTIME_SYMBOL, NODE_UNIXTIME(s->st_ctime)); /* time of last status change */ |
|
|
|
|
|
argc = 1; |
|
|
|
|
|
argv[0] = stats; |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
case EIO_READ: |
|
|
|
|
|
{ |
|
|
|
|
|
argc = 2; |
|
|
|
|
|
// FIXME the following is really ugly!
|
|
|
|
|
|
if (promise->encoding_ == RAW) { |
|
|
|
|
|
if (req->result == 0) { |
|
|
|
|
|
argv[0] = Local<Value>::New(Null()); |
|
|
|
|
|
argv[1] = Integer::New(0); |
|
|
|
|
|
} else { |
|
|
|
|
|
char *buf = reinterpret_cast<char*>(req->ptr2); |
|
|
|
|
|
size_t len = req->result; |
|
|
|
|
|
Local<Array> array = Array::New(len); |
|
|
|
|
|
for (unsigned int i = 0; i < len; i++) { |
|
|
|
|
|
unsigned char val = reinterpret_cast<const unsigned char*>(buf)[i]; |
|
|
|
|
|
array->Set(Integer::New(i), Integer::New(val)); |
|
|
|
|
|
} |
|
|
|
|
|
argv[0] = array; |
|
|
|
|
|
argv[1] = Integer::New(req->result); |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
// UTF8
|
|
|
|
|
|
if (req->result == 0) { |
|
|
|
|
|
// eof
|
|
|
|
|
|
argv[0] = Local<Value>::New(Null()); |
|
|
|
|
|
argv[1] = Integer::New(0); |
|
|
|
|
|
} else { |
|
|
|
|
|
char *buf = reinterpret_cast<char*>(req->ptr2); |
|
|
|
|
|
argv[0] = String::New(buf, req->result); |
|
|
|
|
|
argv[1] = Integer::New(req->result); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
|
assert(0 && "Unhandled eio response"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
promise->EmitSuccess(argc, argv); |
|
|
|
|
|
|
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static Handle<Value> Rename (const Arguments& args) |
|
|
static Handle<Value> |
|
|
|
|
|
Close (const Arguments& args) |
|
|
{ |
|
|
{ |
|
|
if (args.Length() < 2 || !args[0]->IsString() || !args[1]->IsString()) |
|
|
|
|
|
return ThrowException(BAD_ARGUMENTS); |
|
|
|
|
|
HandleScope scope; |
|
|
HandleScope scope; |
|
|
String::Utf8Value path(args[0]->ToString()); |
|
|
|
|
|
String::Utf8Value new_path(args[1]->ToString()); |
|
|
|
|
|
|
|
|
|
|
|
Promise *promise = Promise::Create(true); |
|
|
if (args.Length() < 1 || !args[0]->IsInt32()) { |
|
|
|
|
|
return ThrowException(BAD_ARGUMENTS); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
eio_rename(*path, *new_path, EIO_PRI_DEFAULT, AfterRename, promise); |
|
|
int fd = args[0]->Int32Value(); |
|
|
return scope.Close(promise->Handle()); |
|
|
|
|
|
|
|
|
return scope.Close(EIOPromise::Close(fd)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static int |
|
|
static Handle<Value> |
|
|
AfterUnlink (eio_req *req) |
|
|
Stat (const Arguments& args) |
|
|
{ |
|
|
{ |
|
|
Promise *promise = reinterpret_cast<Promise*>(req->data); |
|
|
HandleScope scope; |
|
|
if (req->result == 0) { |
|
|
|
|
|
promise->EmitSuccess(0, NULL); |
|
|
if (args.Length() < 1 || !args[0]->IsString()) { |
|
|
} else { |
|
|
return ThrowException(BAD_ARGUMENTS); |
|
|
promise->EmitError(0, NULL); |
|
|
|
|
|
} |
|
|
} |
|
|
return 0; |
|
|
|
|
|
|
|
|
String::Utf8Value path(args[0]->ToString()); |
|
|
|
|
|
|
|
|
|
|
|
return scope.Close(EIOPromise::Stat(*path)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static Handle<Value> Unlink (const Arguments& args) |
|
|
static Handle<Value> |
|
|
|
|
|
Rename (const Arguments& args) |
|
|
{ |
|
|
{ |
|
|
if (args.Length() < 1 || !args[0]->IsString()) |
|
|
|
|
|
return ThrowException(BAD_ARGUMENTS); |
|
|
|
|
|
HandleScope scope; |
|
|
HandleScope scope; |
|
|
|
|
|
|
|
|
|
|
|
if (args.Length() < 2 || !args[0]->IsString() || !args[1]->IsString()) { |
|
|
|
|
|
return ThrowException(BAD_ARGUMENTS); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
String::Utf8Value path(args[0]->ToString()); |
|
|
String::Utf8Value path(args[0]->ToString()); |
|
|
Promise *promise = Promise::Create(true); |
|
|
String::Utf8Value new_path(args[1]->ToString()); |
|
|
eio_unlink(*path, EIO_PRI_DEFAULT, AfterUnlink, promise); |
|
|
|
|
|
|
|
|
return scope.Close(EIOPromise::Rename(*path, *new_path)); |
|
|
|
|
|
Promise *promise = EIOPromise::Create(); |
|
|
|
|
|
|
|
|
return scope.Close(promise->Handle()); |
|
|
return scope.Close(promise->Handle()); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static int |
|
|
static Handle<Value> Unlink (const Arguments& args) |
|
|
AfterRMDir (eio_req *req) |
|
|
|
|
|
{ |
|
|
{ |
|
|
Promise *promise = reinterpret_cast<Promise*>(req->data); |
|
|
HandleScope scope; |
|
|
if (req->result == 0) { |
|
|
|
|
|
promise->EmitSuccess(0, NULL); |
|
|
|
|
|
} else { |
|
|
|
|
|
promise->EmitError(0, NULL); |
|
|
|
|
|
} |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static Handle<Value> RMDir (const Arguments& args) |
|
|
if (args.Length() < 1 || !args[0]->IsString()) { |
|
|
{ |
|
|
|
|
|
if (args.Length() < 1 || !args[0]->IsString()) |
|
|
|
|
|
return ThrowException(BAD_ARGUMENTS); |
|
|
return ThrowException(BAD_ARGUMENTS); |
|
|
HandleScope scope; |
|
|
} |
|
|
|
|
|
|
|
|
String::Utf8Value path(args[0]->ToString()); |
|
|
String::Utf8Value path(args[0]->ToString()); |
|
|
Promise *promise = Promise::Create(true); |
|
|
return scope.Close(EIOPromise::Unlink(*path)); |
|
|
eio_rmdir(*path, EIO_PRI_DEFAULT, AfterRMDir, promise); |
|
|
|
|
|
return scope.Close(promise->Handle()); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static int |
|
|
static Handle<Value> |
|
|
AfterOpen (eio_req *req) |
|
|
RMDir (const Arguments& args) |
|
|
{ |
|
|
{ |
|
|
Promise *promise = reinterpret_cast<Promise*>(req->data); |
|
|
HandleScope scope; |
|
|
|
|
|
|
|
|
if (req->result < 0) { |
|
|
if (args.Length() < 1 || !args[0]->IsString()) { |
|
|
promise->EmitError(0, NULL); |
|
|
return ThrowException(BAD_ARGUMENTS); |
|
|
return 0; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
HandleScope scope; |
|
|
String::Utf8Value path(args[0]->ToString()); |
|
|
Local<Value> argv[1] = { Integer::New(req->result) }; |
|
|
return scope.Close(EIOPromise::RMDir(*path)); |
|
|
promise->EmitSuccess(1, argv); |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static Handle<Value> |
|
|
static Handle<Value> |
|
|
Open (const Arguments& args) |
|
|
Open (const Arguments& args) |
|
|
{ |
|
|
{ |
|
|
|
|
|
HandleScope scope; |
|
|
|
|
|
|
|
|
if ( args.Length() < 3 |
|
|
if ( args.Length() < 3 |
|
|
|| !args[0]->IsString() |
|
|
|| !args[0]->IsString() |
|
|
|| !args[1]->IsInt32() |
|
|
|| !args[1]->IsInt32() |
|
|
|| !args[2]->IsInt32() |
|
|
|| !args[2]->IsInt32() |
|
|
) return ThrowException(BAD_ARGUMENTS); |
|
|
) return ThrowException(BAD_ARGUMENTS); |
|
|
|
|
|
|
|
|
HandleScope scope; |
|
|
|
|
|
String::Utf8Value path(args[0]->ToString()); |
|
|
String::Utf8Value path(args[0]->ToString()); |
|
|
int flags = args[1]->Int32Value(); |
|
|
int flags = args[1]->Int32Value(); |
|
|
mode_t mode = static_cast<mode_t>(args[2]->Int32Value()); |
|
|
mode_t mode = static_cast<mode_t>(args[2]->Int32Value()); |
|
|
|
|
|
|
|
|
Promise *promise = Promise::Create(true); |
|
|
return scope.Close(EIOPromise::Open(*path, flags, mode)); |
|
|
|
|
|
|
|
|
eio_open(*path, flags, mode, EIO_PRI_DEFAULT, AfterOpen, promise); |
|
|
|
|
|
return scope.Close(promise->Handle()); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int |
|
|
|
|
|
AfterWrite (eio_req *req) |
|
|
|
|
|
{ |
|
|
|
|
|
Promise *promise = reinterpret_cast<Promise*>(req->data); |
|
|
|
|
|
|
|
|
|
|
|
if (req->result < 0) { |
|
|
|
|
|
promise->EmitError(0, NULL); |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
HandleScope scope; |
|
|
|
|
|
|
|
|
|
|
|
free(req->ptr2); |
|
|
|
|
|
|
|
|
|
|
|
ssize_t written = req->result; |
|
|
|
|
|
Local<Value> argv[1]; |
|
|
|
|
|
argv[0] = written >= 0 ? Integer::New(written) : Integer::New(0); |
|
|
|
|
|
|
|
|
|
|
|
promise->EmitSuccess(1, argv); |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* node.fs.write(fd, data, position=null)
|
|
|
/* node.fs.write(fd, data, position, callback)
|
|
|
|
|
|
* Wrapper for write(2). |
|
|
* Wrapper for write(2). |
|
|
* |
|
|
* |
|
|
* 0 fd integer. file descriptor |
|
|
* 0 fd integer. file descriptor |
|
|
* 1 data the data to write (string = utf8, array = raw) |
|
|
* 1 data the data to write (string = utf8, array = raw) |
|
|
* 2 position if integer, position to write at in the file. |
|
|
* 2 position if integer, position to write at in the file. |
|
|
* if null, write from the current position |
|
|
* if null, write from the current position |
|
|
* |
|
|
|
|
|
* 3 callback(errorno, written) |
|
|
|
|
|
*/ |
|
|
*/ |
|
|
static Handle<Value> |
|
|
static Handle<Value> |
|
|
Write (const Arguments& args) |
|
|
Write (const Arguments& args) |
|
|
{ |
|
|
{ |
|
|
if ( args.Length() < 3 |
|
|
|
|
|
|| !args[0]->IsInt32() |
|
|
|
|
|
) return ThrowException(BAD_ARGUMENTS); |
|
|
|
|
|
|
|
|
|
|
|
HandleScope scope; |
|
|
HandleScope scope; |
|
|
|
|
|
|
|
|
|
|
|
if (args.Length() < 2 || !args[0]->IsInt32()) { |
|
|
|
|
|
return ThrowException(BAD_ARGUMENTS); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
int fd = args[0]->Int32Value(); |
|
|
int fd = args[0]->Int32Value(); |
|
|
off_t pos = args[2]->IsNumber() ? args[2]->IntegerValue() : -1; |
|
|
off_t offset = args[2]->IsNumber() ? args[2]->IntegerValue() : -1; |
|
|
|
|
|
|
|
|
char *buf = NULL; |
|
|
char *buf = NULL; |
|
|
size_t len = 0; |
|
|
size_t len = 0; |
|
@ -231,92 +289,27 @@ Write (const Arguments& args) |
|
|
return ThrowException(BAD_ARGUMENTS); |
|
|
return ThrowException(BAD_ARGUMENTS); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Promise *promise = Promise::Create(true); |
|
|
return scope.Close(EIOPromise::Write(fd, buf, len, offset)); |
|
|
eio_write(fd, buf, len, pos, EIO_PRI_DEFAULT, AfterWrite, promise); |
|
|
|
|
|
return scope.Close(promise->Handle()); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int |
|
|
|
|
|
AfterUtf8Read (eio_req *req) |
|
|
|
|
|
{ |
|
|
|
|
|
Promise *promise = reinterpret_cast<Promise*>(req->data); |
|
|
|
|
|
|
|
|
|
|
|
if (req->result < 0) { |
|
|
|
|
|
promise->EmitError(0, NULL); |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
HandleScope scope; |
|
|
|
|
|
|
|
|
|
|
|
Local<Value> argv[2]; |
|
|
|
|
|
|
|
|
|
|
|
if (req->result == 0) { |
|
|
|
|
|
// eof
|
|
|
|
|
|
argv[0] = Local<Value>::New(Null()); |
|
|
|
|
|
argv[1] = Integer::New(0); |
|
|
|
|
|
} else { |
|
|
|
|
|
char *buf = reinterpret_cast<char*>(req->ptr2); |
|
|
|
|
|
argv[0] = String::New(buf, req->result); |
|
|
|
|
|
argv[1] = Integer::New(req->result); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
promise->EmitSuccess(2, argv); |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int |
|
|
|
|
|
AfterRawRead(eio_req *req) |
|
|
|
|
|
{ |
|
|
|
|
|
Promise *promise = reinterpret_cast<Promise*>(req->data); |
|
|
|
|
|
|
|
|
|
|
|
if (req->result < 0) { |
|
|
|
|
|
promise->EmitError(0, NULL); |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
HandleScope scope; |
|
|
|
|
|
Local<Value> argv[2]; |
|
|
|
|
|
|
|
|
|
|
|
if (req->result == 0) { |
|
|
|
|
|
argv[0] = Local<Value>::New(Null()); |
|
|
|
|
|
argv[1] = Integer::New(0); |
|
|
|
|
|
} else { |
|
|
|
|
|
char *buf = reinterpret_cast<char*>(req->ptr2); |
|
|
|
|
|
size_t len = req->result; |
|
|
|
|
|
Local<Array> array = Array::New(len); |
|
|
|
|
|
for (unsigned int i = 0; i < len; i++) { |
|
|
|
|
|
unsigned char val = reinterpret_cast<const unsigned char*>(buf)[i]; |
|
|
|
|
|
array->Set(Integer::New(i), Integer::New(val)); |
|
|
|
|
|
} |
|
|
|
|
|
argv[0] = array; |
|
|
|
|
|
argv[1] = Integer::New(req->result); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
promise->EmitSuccess(2, argv); |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* node.fs.read(fd, length, position, encoding, callback)
|
|
|
/* node.fs.read(fd, length, position, encoding)
|
|
|
* Wrapper for read(2). |
|
|
* Wrapper for read(2). |
|
|
* |
|
|
* |
|
|
* 0 fd integer. file descriptor |
|
|
* 0 fd integer. file descriptor |
|
|
* 1 length integer. length to read |
|
|
* 1 length integer. length to read |
|
|
* 2 position if integer, position to read from in the file. |
|
|
* 2 position if integer, position to read from in the file. |
|
|
* if null, read from the current position |
|
|
* if null, read from the current position |
|
|
* 3 encoding either node.fs.UTF8 or node.fs.RAW |
|
|
* 3 encoding either node.UTF8 or node.RAW |
|
|
* |
|
|
|
|
|
* 4 callback(errorno, data) |
|
|
|
|
|
*/ |
|
|
*/ |
|
|
static Handle<Value> |
|
|
static Handle<Value> |
|
|
Read (const Arguments& args) |
|
|
Read (const Arguments& args) |
|
|
{ |
|
|
{ |
|
|
if ( args.Length() < 2 |
|
|
|
|
|
|| !args[0]->IsInt32() // fd
|
|
|
|
|
|
|| !args[1]->IsNumber() // len
|
|
|
|
|
|
) return ThrowException(BAD_ARGUMENTS); |
|
|
|
|
|
|
|
|
|
|
|
HandleScope scope; |
|
|
HandleScope scope; |
|
|
|
|
|
|
|
|
|
|
|
if (args.Length() < 2 || !args[0]->IsInt32() || !args[1]->IsNumber()) { |
|
|
|
|
|
return ThrowException(BAD_ARGUMENTS); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
int fd = args[0]->Int32Value(); |
|
|
int fd = args[0]->Int32Value(); |
|
|
size_t len = args[1]->IntegerValue(); |
|
|
size_t len = args[1]->IntegerValue(); |
|
|
off_t pos = args[2]->IsNumber() ? args[2]->IntegerValue() : -1; |
|
|
off_t pos = args[2]->IsNumber() ? args[2]->IntegerValue() : -1; |
|
@ -326,94 +319,7 @@ Read (const Arguments& args) |
|
|
encoding = static_cast<enum encoding>(args[3]->Int32Value()); |
|
|
encoding = static_cast<enum encoding>(args[3]->Int32Value()); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Promise *promise = Promise::Create(true); |
|
|
return scope.Close(EIOPromise::Read(fd, len, pos, encoding)); |
|
|
|
|
|
|
|
|
// NOTE: 2nd param: NULL pointer tells eio to allocate it itself
|
|
|
|
|
|
eio_read(fd, NULL, len, pos, EIO_PRI_DEFAULT, |
|
|
|
|
|
encoding == UTF8 ? AfterUtf8Read : AfterRawRead, promise); |
|
|
|
|
|
|
|
|
|
|
|
return scope.Close(promise->Handle()); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int |
|
|
|
|
|
AfterStat (eio_req *req) |
|
|
|
|
|
{ |
|
|
|
|
|
Promise *promise = reinterpret_cast<Promise*>(req->data); |
|
|
|
|
|
|
|
|
|
|
|
if (req->result < 0) { |
|
|
|
|
|
promise->EmitError(0, NULL); |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
HandleScope scope; |
|
|
|
|
|
|
|
|
|
|
|
Local<Object> stats = Object::New(); |
|
|
|
|
|
|
|
|
|
|
|
struct stat *s = reinterpret_cast<struct stat*>(req->ptr2); |
|
|
|
|
|
|
|
|
|
|
|
/* ID of device containing file */ |
|
|
|
|
|
stats->Set(DEV_SYMBOL, Integer::New(s->st_dev)); |
|
|
|
|
|
/* inode number */ |
|
|
|
|
|
stats->Set(INO_SYMBOL, Integer::New(s->st_ino)); |
|
|
|
|
|
/* protection */ |
|
|
|
|
|
stats->Set(MODE_SYMBOL, Integer::New(s->st_mode)); |
|
|
|
|
|
/* number of hard links */ |
|
|
|
|
|
stats->Set(NLINK_SYMBOL, Integer::New(s->st_nlink)); |
|
|
|
|
|
/* user ID of owner */ |
|
|
|
|
|
stats->Set(UID_SYMBOL, Integer::New(s->st_uid)); |
|
|
|
|
|
/* group ID of owner */ |
|
|
|
|
|
stats->Set(GID_SYMBOL, Integer::New(s->st_gid)); |
|
|
|
|
|
/* device ID (if special file) */ |
|
|
|
|
|
stats->Set(RDEV_SYMBOL, Integer::New(s->st_rdev)); |
|
|
|
|
|
/* total size, in bytes */ |
|
|
|
|
|
stats->Set(SIZE_SYMBOL, Integer::New(s->st_size)); |
|
|
|
|
|
/* blocksize for filesystem I/O */ |
|
|
|
|
|
stats->Set(BLKSIZE_SYMBOL, Integer::New(s->st_blksize)); |
|
|
|
|
|
/* number of blocks allocated */ |
|
|
|
|
|
stats->Set(BLOCKS_SYMBOL, Integer::New(s->st_blocks)); |
|
|
|
|
|
/* time of last access */ |
|
|
|
|
|
stats->Set(ATIME_SYMBOL, Date::New(1000*static_cast<double>(s->st_atime))); |
|
|
|
|
|
/* time of last modification */ |
|
|
|
|
|
stats->Set(MTIME_SYMBOL, Date::New(1000*static_cast<double>(s->st_mtime))); |
|
|
|
|
|
/* time of last status change */ |
|
|
|
|
|
stats->Set(CTIME_SYMBOL, Date::New(1000*static_cast<double>(s->st_ctime))); |
|
|
|
|
|
|
|
|
|
|
|
Local<Value> argv[1] = { stats }; |
|
|
|
|
|
promise->EmitSuccess(1, argv); |
|
|
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static Handle<Value> |
|
|
|
|
|
Stat (const Arguments& args) |
|
|
|
|
|
{ |
|
|
|
|
|
if (args.Length() < 1 || !args[0]->IsString()) |
|
|
|
|
|
return ThrowException(BAD_ARGUMENTS); |
|
|
|
|
|
|
|
|
|
|
|
HandleScope scope; |
|
|
|
|
|
|
|
|
|
|
|
String::Utf8Value path(args[0]->ToString()); |
|
|
|
|
|
|
|
|
|
|
|
Promise *promise = Promise::Create(true); |
|
|
|
|
|
|
|
|
|
|
|
eio_stat(*path, EIO_PRI_DEFAULT, AfterStat, promise); |
|
|
|
|
|
|
|
|
|
|
|
return scope.Close(promise->Handle()); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static Handle<Value> |
|
|
|
|
|
StrError (const Arguments& args) |
|
|
|
|
|
{ |
|
|
|
|
|
if (args.Length() < 1) return v8::Undefined(); |
|
|
|
|
|
if (!args[0]->IsNumber()) return v8::Undefined(); |
|
|
|
|
|
|
|
|
|
|
|
HandleScope scope; |
|
|
|
|
|
|
|
|
|
|
|
int errorno = args[0]->IntegerValue(); |
|
|
|
|
|
|
|
|
|
|
|
Local<String> message = String::New(strerror(errorno)); |
|
|
|
|
|
|
|
|
|
|
|
return scope.Close(message); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void |
|
|
void |
|
@ -421,7 +327,6 @@ File::Initialize (Handle<Object> target) |
|
|
{ |
|
|
{ |
|
|
HandleScope scope; |
|
|
HandleScope scope; |
|
|
|
|
|
|
|
|
// POSIX Wrappers
|
|
|
|
|
|
NODE_SET_METHOD(target, "close", Close); |
|
|
NODE_SET_METHOD(target, "close", Close); |
|
|
NODE_SET_METHOD(target, "open", Open); |
|
|
NODE_SET_METHOD(target, "open", Open); |
|
|
NODE_SET_METHOD(target, "read", Read); |
|
|
NODE_SET_METHOD(target, "read", Read); |
|
@ -430,6 +335,4 @@ File::Initialize (Handle<Object> target) |
|
|
NODE_SET_METHOD(target, "stat", Stat); |
|
|
NODE_SET_METHOD(target, "stat", Stat); |
|
|
NODE_SET_METHOD(target, "unlink", Unlink); |
|
|
NODE_SET_METHOD(target, "unlink", Unlink); |
|
|
NODE_SET_METHOD(target, "write", Write); |
|
|
NODE_SET_METHOD(target, "write", Write); |
|
|
|
|
|
|
|
|
NODE_SET_METHOD(target, "strerror", StrError); |
|
|
|
|
|
} |
|
|
} |
|
|