mirror of
https://github.com/nodejs/node.git
synced 2024-11-29 15:06:33 +01:00
add file open/close
This commit is contained in:
parent
63a9cd3897
commit
e8ce6ef790
218
src/file.cc
218
src/file.cc
@ -1,6 +1,11 @@
|
||||
#include "node.h"
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
using namespace v8;
|
||||
|
||||
class Callback {
|
||||
@ -9,33 +14,32 @@ class Callback {
|
||||
~Callback();
|
||||
Local<Value> Call(Handle<Object> recv, int argc, Handle<Value> argv[]);
|
||||
private:
|
||||
Persistent<Function> handle;
|
||||
Persistent<Function> handle_;
|
||||
};
|
||||
|
||||
|
||||
Callback::Callback (Handle<Value> v)
|
||||
{
|
||||
HandleScope scope;
|
||||
Handle<Function> f = Handle<Function>::Cast(v);
|
||||
handle = Persistent<Function>::New(f);
|
||||
handle_ = Persistent<Function>::New(f);
|
||||
}
|
||||
|
||||
Callback::~Callback ()
|
||||
{
|
||||
handle.Dispose();
|
||||
handle.Clear(); // necessary?
|
||||
handle_.Dispose();
|
||||
handle_.Clear(); // necessary?
|
||||
}
|
||||
|
||||
Local<Value>
|
||||
Callback::Call (Handle<Object> recv, int argc, Handle<Value> argv[])
|
||||
{
|
||||
HandleScope scope;
|
||||
Local<Value> r = handle->Call(recv, argc, argv);
|
||||
Local<Value> r = handle_->Call(recv, argc, argv);
|
||||
return scope.Close(r);
|
||||
}
|
||||
|
||||
static int
|
||||
after_rename (eio_req *req)
|
||||
AfterRename (eio_req *req)
|
||||
{
|
||||
Callback *callback = static_cast<Callback*>(req->data);
|
||||
if (callback != NULL) {
|
||||
@ -65,14 +69,14 @@ JS_METHOD(rename)
|
||||
Callback *callback = NULL;
|
||||
if (!args[2]->IsUndefined()) callback = new Callback(args[2]);
|
||||
|
||||
eio_req *req = eio_rename(*path, *new_path, EIO_PRI_DEFAULT, after_rename, callback);
|
||||
eio_req *req = eio_rename(*path, *new_path, EIO_PRI_DEFAULT, AfterRename, callback);
|
||||
node_eio_submit(req);
|
||||
|
||||
return Undefined();
|
||||
}
|
||||
|
||||
static int
|
||||
after_stat (eio_req *req)
|
||||
AfterStat (eio_req *req)
|
||||
{
|
||||
Callback *callback = static_cast<Callback*>(req->data);
|
||||
if (callback != NULL) {
|
||||
@ -134,12 +138,199 @@ JS_METHOD(stat)
|
||||
Callback *callback = NULL;
|
||||
if (!args[1]->IsUndefined()) callback = new Callback(args[1]);
|
||||
|
||||
eio_req *req = eio_stat(*path, EIO_PRI_DEFAULT, after_stat, callback);
|
||||
eio_req *req = eio_stat(*path, EIO_PRI_DEFAULT, AfterStat, callback);
|
||||
node_eio_submit(req);
|
||||
|
||||
return Undefined();
|
||||
}
|
||||
|
||||
///////////////////// FILE /////////////////////
|
||||
|
||||
class File {
|
||||
public:
|
||||
File (Handle<Object> handle);
|
||||
~File ();
|
||||
|
||||
static File* Unwrap (Handle<Object> obj);
|
||||
|
||||
void Open (const char *path, const char *mode);
|
||||
static int AfterOpen (eio_req *req);
|
||||
|
||||
void Close ();
|
||||
static int AfterClose (eio_req *req);
|
||||
|
||||
|
||||
private:
|
||||
static void MakeWeak (Persistent<Value> _, void *data);
|
||||
int fd_;
|
||||
Persistent<Object> handle_;
|
||||
};
|
||||
|
||||
File::File (Handle<Object> handle)
|
||||
{
|
||||
HandleScope scope;
|
||||
fd_ = -1;
|
||||
handle_ = Persistent<Object>::New(handle);
|
||||
Handle<External> external = External::New(this);
|
||||
handle_->SetInternalField(0, external);
|
||||
handle_.MakeWeak(this, File::MakeWeak);
|
||||
}
|
||||
|
||||
File::~File ()
|
||||
{
|
||||
Close();
|
||||
handle_->SetInternalField(0, Undefined());
|
||||
handle_.Dispose();
|
||||
handle_.Clear();
|
||||
}
|
||||
|
||||
File*
|
||||
File::Unwrap (Handle<Object> obj)
|
||||
{
|
||||
HandleScope scope;
|
||||
Handle<External> field = Handle<External>::Cast(obj->GetInternalField(0));
|
||||
File* file = static_cast<File*>(field->Value());
|
||||
return file;
|
||||
}
|
||||
|
||||
void
|
||||
File::MakeWeak (Persistent<Value> _, void *data)
|
||||
{
|
||||
File *file = static_cast<File*> (data);
|
||||
delete file;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
File::AfterClose (eio_req *req)
|
||||
{
|
||||
File *file = static_cast<File*>(req->data);
|
||||
|
||||
// TODO
|
||||
printf("after close\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
File::Close ()
|
||||
{
|
||||
eio_req *req = eio_close (fd_, EIO_PRI_DEFAULT, File::AfterClose, this);
|
||||
node_eio_submit(req);
|
||||
}
|
||||
|
||||
int
|
||||
File::AfterOpen (eio_req *req)
|
||||
{
|
||||
File *file = static_cast<File*>(req->data);
|
||||
|
||||
HandleScope scope;
|
||||
TryCatch try_catch;
|
||||
|
||||
if(req->result < 0) {
|
||||
// TODO
|
||||
/*
|
||||
const int argc = 2;
|
||||
Local<Value> argv[argc];
|
||||
|
||||
argv[0] = Integer::New(errorno);
|
||||
argv[1] = String::New(strerror(errorno));
|
||||
*/
|
||||
printf("error opening file...handle me\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
file->fd_ = static_cast<int>(req->result);
|
||||
|
||||
file->handle_->Set(String::NewSymbol("fd"), Integer::New(req->result));
|
||||
Handle<Value> on_open_value = file->handle_->Get( String::NewSymbol("onOpen") );
|
||||
if (!on_open_value->IsFunction())
|
||||
return 0;
|
||||
Handle<Function> on_open = Handle<Function>::Cast(on_open_value);
|
||||
|
||||
on_open->Call(file->handle_, 0, NULL);
|
||||
|
||||
if(try_catch.HasCaught())
|
||||
node_fatal_exception(try_catch);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
File::Open (const char *path, const char *mode)
|
||||
{
|
||||
mode_t mask = umask(0x0700);
|
||||
umask(mask);
|
||||
|
||||
int flags = O_RDONLY; // default
|
||||
// XXX is this interpretation correct?
|
||||
// I don't want to to use fopen() because eio doesn't support it.
|
||||
switch(mode[0]) {
|
||||
case 'r':
|
||||
if (mode[1] == '+')
|
||||
flags = O_RDWR;
|
||||
else
|
||||
flags = O_RDONLY;
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
if (mode[1] == '+')
|
||||
flags = O_RDWR | O_CREAT | O_TRUNC;
|
||||
else
|
||||
flags = O_WRONLY | O_CREAT | O_TRUNC;
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
if (mode[1] == '+')
|
||||
flags = O_RDWR | O_APPEND | O_CREAT;
|
||||
else
|
||||
flags = O_WRONLY | O_APPEND | O_CREAT;
|
||||
break;
|
||||
}
|
||||
|
||||
eio_req *req = eio_open (path, flags, mask, EIO_PRI_DEFAULT, File::AfterOpen, this);
|
||||
node_eio_submit(req);
|
||||
}
|
||||
|
||||
static Handle<Value>
|
||||
NewFile (const Arguments& args)
|
||||
{
|
||||
HandleScope scope;
|
||||
File *file = new File(args.Holder());
|
||||
if(file == NULL)
|
||||
return Undefined(); // XXX raise error?
|
||||
|
||||
return args.This();
|
||||
}
|
||||
|
||||
JS_METHOD(file_open)
|
||||
{
|
||||
if (args.Length() < 1) return Undefined();
|
||||
if (!args[0]->IsString()) return Undefined();
|
||||
|
||||
HandleScope scope;
|
||||
|
||||
File *file = File::Unwrap(args.Holder());
|
||||
String::Utf8Value path(args[0]->ToString());
|
||||
if (args[1]->IsString()) {
|
||||
String::AsciiValue mode(args[1]->ToString());
|
||||
file->Open(*path, *mode);
|
||||
} else {
|
||||
file->Open(*path, "r");
|
||||
}
|
||||
|
||||
return Undefined();
|
||||
}
|
||||
|
||||
JS_METHOD(file_close)
|
||||
{
|
||||
HandleScope scope;
|
||||
|
||||
File *file = File::Unwrap(args.Holder());
|
||||
file->Close();
|
||||
|
||||
return Undefined();
|
||||
}
|
||||
|
||||
void
|
||||
NodeInit_file (Handle<Object> target)
|
||||
{
|
||||
@ -150,4 +341,11 @@ NodeInit_file (Handle<Object> target)
|
||||
|
||||
JS_SET_METHOD(fs, "rename", rename);
|
||||
JS_SET_METHOD(fs, "stat", stat);
|
||||
|
||||
Local<FunctionTemplate> file_template = FunctionTemplate::New(NewFile);
|
||||
file_template->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
target->Set(String::NewSymbol("File"), file_template->GetFunction());
|
||||
|
||||
JS_SET_METHOD(file_template->InstanceTemplate(), "open", file_open);
|
||||
JS_SET_METHOD(file_template->InstanceTemplate(), "close", file_close);
|
||||
}
|
||||
|
11
src/main.js
11
src/main.js
@ -42,7 +42,7 @@ function __require (path, loading_file) {
|
||||
// absolute path
|
||||
if (path.slice(0,1) === "/") {
|
||||
} else {
|
||||
filename = node.path.join(node.path.dirname(loading_file), path);
|
||||
//filename = node.path.join(node.path.dirname(loading_file), path);
|
||||
}
|
||||
node.blocking.print("require: " + filename);
|
||||
|
||||
@ -75,11 +75,16 @@ function __require (path, loading_file) {
|
||||
}
|
||||
|
||||
// main script execution.
|
||||
//__require(ARGV[1], ARGV[1]);
|
||||
//
|
||||
__require(ARGV[1], ".");
|
||||
|
||||
/*
|
||||
fs.stat("/tmp/world", function (stat, status, msg) {
|
||||
for ( var i in stat ) {
|
||||
node.blocking.print(i + ": " + stat[i]);
|
||||
}
|
||||
node.blocking.print("done: " + status.toString() + " " + msg.toString());
|
||||
|
||||
});
|
||||
*/
|
||||
|
||||
//var f = new File();
|
||||
|
@ -168,7 +168,7 @@ JS_METHOD(exec)
|
||||
static void
|
||||
OnFatalError (const char* location, const char* message)
|
||||
{
|
||||
fprintf(stderr, "Fatal error. %s %s\n", location, message);
|
||||
fprintf(stderr, "Fatal error: %s %s\n", location, message);
|
||||
ev_unloop(node_loop(), EVUNLOOP_ALL);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user