@ -12,490 +12,405 @@
using namespace v8 ;
using namespace node ;
# define FD_SYMBOL String::NewSymbol("fd")
# define ACTION_QUEUE_SYMBOL String::NewSymbol("_actionQueue")
# define ENCODING_SYMBOL String::NewSymbol("encoding")
# define CALLBACK_SYMBOL String::NewSymbol("callbaccallback")
# define POLL_ACTIONS_SYMBOL String::NewSymbol("_pollActions")
# define UTF8_SYMBOL String::NewSymbol("utf8")
# define RAW_SYMBOL String::NewSymbol("raw")
void
File : : Initialize ( Handle < Object > target )
{
HandleScope scope ;
// file system methods
NODE_SET_METHOD ( target , " rename " , FileSystem : : Rename ) ;
NODE_SET_METHOD ( target , " stat " , FileSystem : : Stat ) ;
NODE_SET_METHOD ( target , " strerror " , FileSystem : : StrError ) ;
target - > Set ( String : : NewSymbol ( " STDIN_FILENO " ) , Integer : : New ( STDIN_FILENO ) ) ;
target - > Set ( String : : NewSymbol ( " STDOUT_FILENO " ) , Integer : : New ( STDOUT_FILENO ) ) ;
target - > Set ( String : : NewSymbol ( " STDERR_FILENO " ) , Integer : : New ( STDERR_FILENO ) ) ;
Local < FunctionTemplate > file_template = FunctionTemplate : : New ( File : : New ) ;
file_template - > InstanceTemplate ( ) - > SetInternalFieldCount ( 1 ) ;
// file methods
NODE_SET_PROTOTYPE_METHOD ( file_template , " _ffi_open " , File : : Open ) ;
NODE_SET_PROTOTYPE_METHOD ( file_template , " _ffi_close " , File : : Close ) ;
NODE_SET_PROTOTYPE_METHOD ( file_template , " _ffi_write " , File : : Write ) ;
NODE_SET_PROTOTYPE_METHOD ( file_template , " _ffi_read " , File : : Read ) ;
file_template - > InstanceTemplate ( ) - > SetAccessor ( ENCODING_SYMBOL , File : : GetEncoding , File : : SetEncoding ) ;
target - > Set ( String : : NewSymbol ( " File " ) , file_template - > GetFunction ( ) ) ;
}
Handle < Value >
File : : GetEncoding ( Local < String > property , const AccessorInfo & info )
{
File * file = NODE_UNWRAP ( File , info . This ( ) ) ;
if ( file - > encoding_ = = UTF8 )
return UTF8_SYMBOL ;
else
return RAW_SYMBOL ;
}
void
File : : SetEncoding ( Local < String > property , Local < Value > value , const AccessorInfo & info )
{
File * file = NODE_UNWRAP ( File , info . This ( ) ) ;
if ( value - > IsString ( ) ) {
Local < String > encoding_string = value - > ToString ( ) ;
char buf [ 5 ] ; // need enough room for "utf8" or "raw"
encoding_string - > WriteAscii ( buf , 0 , 4 ) ;
buf [ 4 ] = ' \0 ' ;
file - > encoding_ = strcasecmp ( buf , " utf8 " ) = = 0 ? UTF8 : RAW ;
} else {
file - > encoding_ = RAW ;
}
}
static void
CallTopCallback ( Handle < Object > handle , const int argc , Handle < Value > argv [ ] )
# define DEV_SYMBOL String::NewSymbol("dev")
# define INO_SYMBOL String::NewSymbol("ino")
# define MODE_SYMBOL String::NewSymbol("mode")
# define NLINK_SYMBOL String::NewSymbol("nlink")
# define UID_SYMBOL String::NewSymbol("uid")
# define GID_SYMBOL String::NewSymbol("gid")
# define RDEV_SYMBOL String::NewSymbol("rdev")
# define SIZE_SYMBOL String::NewSymbol("size")
# define BLKSIZE_SYMBOL String::NewSymbol("blksize")
# define BLOCKS_SYMBOL String::NewSymbol("blocks")
# define ATIME_SYMBOL String::NewSymbol("atime")
# define MTIME_SYMBOL String::NewSymbol("mtime")
# define CTIME_SYMBOL String::NewSymbol("ctime")
# define BAD_ARGUMENTS String::New("Bad argument")
# define MAKE_CALLBACK_PTR \
Persistent < Function > * callback = NULL ; \
Local < Value > last_arg = args [ args . Length ( ) - 1 ] ; \
if ( last_arg - > IsFunction ( ) ) { \
Local < Function > l = Local < Function > : : Cast ( last_arg ) ; \
callback = new Persistent < Function > ( ) ; \
* callback = Persistent < Function > : : New ( l ) ; \
} \
node : : eio_warmup ( ) ; \
# define CALL_CALLBACK_PTR(req, argc, argv) \
do { \
if ( req - > data ) { \
Persistent < Function > * callback = \
reinterpret_cast < Persistent < Function > * > ( req - > data ) ; \
TryCatch try_catch ; \
( * callback ) - > Call ( Context : : GetCurrent ( ) - > Global ( ) , argc , argv ) ; \
if ( try_catch . HasCaught ( ) ) \
node : : fatal_exception ( try_catch ) ; \
free ( callback ) ; \
} \
} while ( 0 )
# define DEFINE_SIMPLE_CB(name) \
static int After # # name ( eio_req * req ) \
{ \
HandleScope scope ; \
Local < Value > argv [ ] = { Integer : : New ( req - > errorno ) } ; \
CALL_CALLBACK_PTR ( req , 1 , argv ) ; \
return 0 ; \
} \
DEFINE_SIMPLE_CB ( Close )
static Handle < Value > Close ( const Arguments & args )
{
if ( args . Length ( ) < 1 | | ! args [ 0 ] - > IsInt32 ( ) )
return ThrowException ( BAD_ARGUMENTS ) ;
HandleScope scope ;
// poll_actions
Local < Value > poll_actions_value = handle - > Get ( POLL_ACTIONS_SYMBOL ) ;
assert ( poll_actions_value - > IsFunction ( ) ) ;
Handle < Function > poll_actions = Handle < Function > : : Cast ( poll_actions_value ) ;
TryCatch try_catch ;
poll_actions - > Call ( handle , argc , argv ) ;
if ( try_catch . HasCaught ( ) )
node : : fatal_exception ( try_catch ) ;
int fd = args [ 0 ] - > Int32Value ( ) ;
MAKE_CALLBACK_PTR
eio_close ( fd , EIO_PRI_DEFAULT , AfterClose , callback ) ;
return Undefined ( ) ;
}
Handle < Value >
FileSystem : : Rename ( const Arguments & args )
DEFINE_SIMPLE_CB ( Rename )
static Handle < Value > Rename ( const Arguments & args )
{
if ( args . Length ( ) < 2 )
return Undefined ( ) ;
if ( args . Length ( ) < 2 | | ! args [ 0 ] - > IsString ( ) | | ! args [ 1 ] - > IsString ( ) )
return ThrowException ( BAD_ARGUMENTS ) ;
HandleScope scope ;
String : : Utf8Value path ( args [ 0 ] - > ToString ( ) ) ;
String : : Utf8Value new_path ( args [ 1 ] - > ToString ( ) ) ;
Persistent < Function > * callback = NULL ;
if ( args [ 2 ] - > IsFunction ( ) ) {
Local < Function > l = Local < Function > : : Cast ( args [ 2 ] ) ;
callback = new Persistent < Function > ( ) ;
* callback = Persistent < Function > : : New ( l ) ;
}
node : : eio_warmup ( ) ;
eio_rename ( * path , * new_path , EIO_PRI_DEFAULT , AfterRename , NULL ) ;
MAKE_CALLBACK_PTR
eio_rename ( * path , * new_path , EIO_PRI_DEFAULT , AfterRename , callback ) ;
return Undefined ( ) ;
}
int
FileSystem : : AfterRename ( eio_req * req )
static int
AfterOpen ( eio_req * req )
{
HandleScope scope ;
const int argc = 1 ;
const int argc = 2 ;
Local < Value > argv [ argc ] ;
argv [ 0 ] = Integer : : New ( req - > errorno ) ;
if ( req - > data ) {
Persistent < Function > * callback = reinterpret_cast < Persistent < Function > * > ( req - > data ) ;
TryCatch try_catch ;
( * callback ) - > Call ( Context : : GetCurrent ( ) - > Global ( ) , argc , argv ) ;
if ( try_catch . HasCaught ( ) )
node : : fatal_exception ( try_catch ) ;
free ( callback ) ;
}
argv [ 1 ] = Integer : : New ( req - > result ) ;
CALL_CALLBACK_PTR ( req , argc , argv ) ;
return 0 ;
}
Handle < Value >
FileSystem : : Stat ( const Arguments & args )
static Handle < Value >
Open ( const Arguments & args )
{
if ( args . Length ( ) < 1 )
return v8 : : Undefined ( ) ;
if ( args . Length ( ) < 3
| | ! args [ 0 ] - > IsString ( )
| | ! args [ 1 ] - > IsInt32 ( )
| | ! args [ 2 ] - > IsInt32 ( )
) return ThrowException ( BAD_ARGUMENTS ) ;
HandleScope scope ;
String : : Utf8Value path ( args [ 0 ] - > ToString ( ) ) ;
int flags = args [ 1 ] - > Int32Value ( ) ;
mode_t mode = static_cast < mode_t > ( args [ 2 ] - > Int32Value ( ) ) ;
Persistent < Function > * callback = NULL ;
if ( args [ 1 ] - > IsFunction ( ) ) {
Local < Function > l = Local < Function > : : Cast ( args [ 1 ] ) ;
callback = new Persistent < Function > ( ) ;
* callback = Persistent < Function > : : New ( l ) ;
}
node : : eio_warmup ( ) ;
eio_stat ( * path , EIO_PRI_DEFAULT , AfterStat , callback ) ;
MAKE_CALLBACK_PTR
eio_open ( * path , flags , mode , EIO_PRI_DEFAULT , AfterOpen , callback ) ;
return Undefined ( ) ;
}
int
FileSystem : : AfterStat ( eio_req * req )
static int
AfterWrite ( eio_req * req )
{
HandleScope scope ;
free ( req - > ptr2 ) ;
ssize_t written = req - > result ;
const int argc = 2 ;
Local < Value > argv [ argc ] ;
argv [ 0 ] = Integer : : New ( req - > errorno ) ;
argv [ 1 ] = written > = 0 ? Integer : : New ( written ) : Integer : : New ( 0 ) ;
Local < Object > stats = Object : : New ( ) ;
argv [ 1 ] = stats ;
if ( req - > result = = 0 ) {
struct stat * s = reinterpret_cast < struct stat * > ( req - > ptr2 ) ;
/* ID of device containing file */
stats - > Set ( NODE_SYMBOL ( " dev " ) , Integer : : New ( s - > st_dev ) ) ;
/* inode number */
stats - > Set ( NODE_SYMBOL ( " ino " ) , Integer : : New ( s - > st_ino ) ) ;
/* protection */
stats - > Set ( NODE_SYMBOL ( " mode " ) , Integer : : New ( s - > st_mode ) ) ;
/* number of hard links */
stats - > Set ( NODE_SYMBOL ( " nlink " ) , Integer : : New ( s - > st_nlink ) ) ;
/* user ID of owner */
stats - > Set ( NODE_SYMBOL ( " uid " ) , Integer : : New ( s - > st_uid ) ) ;
/* group ID of owner */
stats - > Set ( NODE_SYMBOL ( " gid " ) , Integer : : New ( s - > st_gid ) ) ;
/* device ID (if special file) */
stats - > Set ( NODE_SYMBOL ( " rdev " ) , Integer : : New ( s - > st_rdev ) ) ;
/* total size, in bytes */
stats - > Set ( NODE_SYMBOL ( " size " ) , Integer : : New ( s - > st_size ) ) ;
/* blocksize for filesystem I/O */
stats - > Set ( NODE_SYMBOL ( " blksize " ) , Integer : : New ( s - > st_blksize ) ) ;
/* number of blocks allocated */
stats - > Set ( NODE_SYMBOL ( " blocks " ) , Integer : : New ( s - > st_blocks ) ) ;
/* time of last access */
stats - > Set ( NODE_SYMBOL ( " atime " ) , Date : : New ( 1000 * static_cast < double > ( s - > st_atime ) ) ) ;
/* time of last modification */
stats - > Set ( NODE_SYMBOL ( " mtime " ) , Date : : New ( 1000 * static_cast < double > ( s - > st_mtime ) ) ) ;
/* time of last status change */
stats - > Set ( NODE_SYMBOL ( " ctime " ) , Date : : New ( 1000 * static_cast < double > ( s - > st_ctime ) ) ) ;
}
if ( req - > data ) {
Persistent < Function > * callback = reinterpret_cast < Persistent < Function > * > ( req - > data ) ;
TryCatch try_catch ;
( * callback ) - > Call ( Context : : GetCurrent ( ) - > Global ( ) , argc , argv ) ;
if ( try_catch . HasCaught ( ) )
node : : fatal_exception ( try_catch ) ;
free ( callback ) ;
}
CALL_CALLBACK_PTR ( req , argc , argv ) ;
return 0 ;
}
Handle < Value >
FileSystem : : StrError ( const Arguments & args )
/* node.fs.write(fd, data, position, callback)
* Wrapper for write ( 2 ) .
*
* 0 fd integer . file descriptor
* 1 data the data to write
* 2 position if integer , position to write at in the file .
* if null , write from the current position
*
* 3 callback ( errorno , written )
*/
static Handle < Value >
Write ( const Arguments & args )
{
if ( args . Length ( ) < 1 ) return v8 : : Undefined ( ) ;
if ( ! args [ 0 ] - > IsNumber ( ) ) return v8 : : Undefined ( ) ;
if ( args . Length ( ) < 3
| | ! args [ 0 ] - > IsInt32 ( )
) return ThrowException ( BAD_ARGUMENTS ) ;
HandleScope scope ;
int errorno = args [ 0 ] - > IntegerValue ( ) ;
Local < String > message = String : : New ( strerror ( errorno ) ) ;
int fd = args [ 0 ] - > Int32Value ( ) ;
off_t pos = args [ 2 ] - > IsNumber ( ) ? args [ 2 ] - > IntegerValue ( ) : - 1 ;
return scope . Close ( message ) ;
}
///////////////////// FILE /////////////////////
char * buf = NULL ;
size_t len = 0 ;
File : : File ( Handle < Object > handle )
: ObjectWrap ( handle )
{
HandleScope scope ;
encoding_ = RAW ;
handle - > Set ( ACTION_QUEUE_SYMBOL , Array : : New ( ) ) ;
}
if ( args [ 1 ] - > IsString ( ) ) {
// utf8 encoding
Local < String > string = args [ 1 ] - > ToString ( ) ;
len = string - > Utf8Length ( ) ;
buf = reinterpret_cast < char * > ( malloc ( len ) ) ;
string - > WriteUtf8 ( buf , len ) ;
File : : ~ File ( )
{
; // XXX call close?
} else if ( args [ 1 ] - > IsArray ( ) ) {
// raw encoding
Local < Array > array = Local < Array > : : Cast ( args [ 1 ] ) ;
len = array - > Length ( ) ;
buf = reinterpret_cast < char * > ( malloc ( len ) ) ;
for ( unsigned int i = 0 ; i < len ; i + + ) {
Local < Value > int_value = array - > Get ( Integer : : New ( i ) ) ;
buf [ i ] = int_value - > Int32Value ( ) ;
}
bool
File : : HasUtf8Encoding ( void )
{
return false ;
} else {
return ThrowException ( BAD_ARGUMENTS ) ;
}
int
File : : GetFD ( void )
{
Handle < Value > fd_value = handle_ - > Get ( FD_SYMBOL ) ;
int fd = fd_value - > IntegerValue ( ) ;
return fd ;
MAKE_CALLBACK_PTR
eio_write ( fd , buf , len , pos , EIO_PRI_DEFAULT , AfterWrite , callback ) ;
return Undefined ( ) ;
}
Handle < Value >
File : : Close ( const Arguments & args )
static int
AfterUtf8Read ( eio_req * req )
{
HandleScope scope ;
File * file = NODE_UNWRAP ( File , args . Holder ( ) ) ;
int fd = file - > GetFD ( ) ;
node : : eio_warmup ( ) ;
eio_close ( fd , EIO_PRI_DEFAULT , File : : AfterClose , file ) ;
file - > Attach ( ) ;
return Undefined ( ) ;
}
const int argc = 2 ;
Local < Value > argv [ argc ] ;
argv [ 0 ] = Integer : : New ( req - > errorno ) ;
int
File : : AfterClose ( eio_req * req )
{
File * file = reinterpret_cast < File * > ( req - > data ) ;
char * buf = reinterpret_cast < char * > ( req - > ptr2 ) ;
if ( req - > result = = 0 ) {
file - > handle_ - > Delete ( FD_SYMBOL ) ;
// eof
argv [ 1 ] = Local < Value > : : New ( Null ( ) ) ;
} else {
size_t len = req - > result ;
argv [ 1 ] = String : : New ( buf , len ) ;
}
const int argc = 1 ;
Local < Value > argv [ argc ] ;
argv [ 0 ] = Integer : : New ( req - > errorno ) ;
CallTopCallback ( file - > handle_ , argc , argv ) ;
file - > Detach ( ) ;
CALL_CALLBACK_PTR ( req , argc , argv ) ;
return 0 ;
}
Handle < Value >
File : : Open ( const Arguments & args )
static int
AfterRawRead ( eio_req * req )
{
/* check arguments */
if ( args . Length ( ) < 1 ) return Undefined ( ) ;
if ( ! args [ 0 ] - > IsString ( ) ) return Undefined ( ) ;
HandleScope scope ;
File * file = NODE_UNWRAP ( File , args . Holder ( ) ) ;
// make sure that we don't already have a pending open
if ( file - > handle_ - > Has ( FD_SYMBOL ) ) {
return ThrowException ( String : : New ( " File object is opened. " ) ) ;
}
String : : Utf8Value path ( args [ 0 ] - > ToString ( ) ) ;
const int argc = 2 ;
Local < Value > argv [ argc ] ;
argv [ 0 ] = Integer : : New ( req - > errorno ) ;
int flags = O_RDONLY ; // default
if ( args [ 1 ] - > IsString ( ) ) {
String : : AsciiValue mode_v ( args [ 1 ] - > ToString ( ) ) ;
char * mode = * mode_v ;
// XXX is this interpretation of the mode correct?
// I don't want to to use fopen() directly because eio doesn't support it.
switch ( mode [ 0 ] ) {
case ' r ' :
flags = ( mode [ 1 ] = = ' + ' ? O_RDWR : O_RDONLY ) ;
break ;
case ' w ' :
flags = O_CREAT | O_TRUNC | ( mode [ 1 ] = = ' + ' ? O_RDWR : O_WRONLY ) ;
break ;
case ' a ' :
flags = O_APPEND | O_CREAT | ( mode [ 1 ] = = ' + ' ? O_RDWR : O_WRONLY ) ;
break ;
}
}
char * buf = reinterpret_cast < char * > ( req - > ptr2 ) ;
// TODO how should the mode be set?
node : : eio_warmup ( ) ;
eio_open ( * path , flags , 0666 , EIO_PRI_DEFAULT , File : : AfterOpen , file ) ;
file - > Attach ( ) ;
return Undefined ( ) ;
if ( req - > result = = 0 ) {
// eof
argv [ 1 ] = Local < Value > : : New ( Null ( ) ) ;
} else {
// raw encoding
size_t len = req - > result ;
Local < Array > array = Array : : New ( len ) ;
for ( unsigned int i = 0 ; i < len ; i + + ) {
array - > Set ( Integer : : New ( i ) , Integer : : New ( buf [ i ] ) ) ;
}
int
File : : AfterOpen ( eio_req * req )
{
File * file = reinterpret_cast < File * > ( req - > data ) ;
HandleScope scope ;
if ( req - > result > = 0 ) {
file - > handle_ - > Set ( FD_SYMBOL , Integer : : New ( req - > result ) ) ;
argv [ 1 ] = array ;
}
const int argc = 1 ;
Handle < Value > argv [ argc ] ;
argv [ 0 ] = Integer : : New ( req - > errorno ) ;
CallTopCallback ( file - > handle_ , argc , argv ) ;
file - > Detach ( ) ;
CALL_CALLBACK_PTR ( req , argc , argv ) ;
return 0 ;
}
Handle < Value >
File : : Write ( const Arguments & args )
/* node.fs.read(fd, length, position, encoding, callback)
* Wrapper for read ( 2 ) .
*
* 0 fd integer . file descriptor
* 1 length integer . length to read
* 2 position if integer , position to read from in the file .
* if null , read from the current position
* 3 encoding either node . fs . UTF8 or node . fs . RAW
*
* 4 callback ( errorno , data )
*/
static Handle < Value >
Read ( const Arguments & args )
{
if ( args . Length ( ) < 2 ) return Undefined ( ) ;
if ( ! args [ 1 ] - > IsNumber ( ) ) return Undefined ( ) ;
if ( args . Length ( ) < 3
| | ! args [ 0 ] - > IsInt32 ( ) // fd
| | ! args [ 1 ] - > IsNumber ( ) // len
) return ThrowException ( BAD_ARGUMENTS ) ;
HandleScope scope ;
File * file = NODE_UNWRAP ( File , args . Holder ( ) ) ;
off_t pos = args [ 1 ] - > IntegerValue ( ) ;
char * buf = NULL ;
size_t length = 0 ;
if ( args [ 0 ] - > IsString ( ) ) {
// utf8 encoding
Local < String > string = args [ 0 ] - > ToString ( ) ;
length = string - > Utf8Length ( ) ;
buf = reinterpret_cast < char * > ( malloc ( length ) ) ;
string - > WriteUtf8 ( buf , length ) ;
} else if ( args [ 0 ] - > IsArray ( ) ) {
// raw encoding
Local < Array > array = Local < Array > : : Cast ( args [ 0 ] ) ;
length = array - > Length ( ) ;
buf = reinterpret_cast < char * > ( malloc ( length ) ) ;
for ( unsigned int i = 0 ; i < length ; i + + ) {
Local < Value > int_value = array - > Get ( Integer : : New ( i ) ) ;
buf [ i ] = int_value - > Int32Value ( ) ;
}
} else {
// bad arguments. raise error?
return Undefined ( ) ;
}
int fd = args [ 0 ] - > Int32Value ( ) ;
size_t len = args [ 1 ] - > IntegerValue ( ) ;
off_t pos = args [ 2 ] - > IsNumber ( ) ? args [ 2 ] - > IntegerValue ( ) : - 1 ;
if ( file - > handle_ - > Has ( FD_SYMBOL ) = = false ) {
printf ( " trying to write to a bad fd! \n " ) ;
return Undefined ( ) ;
enum encoding encoding = RAW ;
if ( args [ 3 ] - > IsInt32 ( ) ) {
encoding = static_cast < enum encoding > ( args [ 3 ] - > Int32Value ( ) ) ;
}
int fd = file - > GetFD ( ) ;
node : : eio_warmup ( ) ;
eio_write ( fd , buf , length , pos , EIO_PRI_DEFAULT , File : : AfterWrite , file ) ;
file - > Attach ( ) ;
MAKE_CALLBACK_PTR
// NOTE: 2nd param: NULL pointer tells eio to allocate it itself
eio_read ( fd , NULL , len , pos , EIO_PRI_DEFAULT ,
encoding = = UTF8 ? AfterUtf8Read : AfterRawRead , callback ) ;
return Undefined ( ) ;
}
int
File : : AfterWrite ( eio_req * req )
static int
AfterStat ( eio_req * req )
{
File * file = reinterpret_cast < File * > ( req - > data ) ;
//char *buf = reinterpret_cast<char*>(req->ptr2);
free ( req - > ptr2 ) ;
ssize_t written = req - > result ;
HandleScope scope ;
const int argc = 2 ;
Local < Value > argv [ argc ] ;
argv [ 0 ] = Integer : : New ( req - > errorno ) ;
argv [ 1 ] = written > = 0 ? Integer : : New ( written ) : Integer : : New ( 0 ) ;
CallTopCallback ( file - > handle_ , argc , argv ) ;
file - > Detach ( ) ;
Local < Object > stats = Object : : New ( ) ;
argv [ 1 ] = stats ;
if ( req - > result = = 0 ) {
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 ) ) ) ;
}
CALL_CALLBACK_PTR ( req , argc , argv ) ; \
return 0 ;
}
Handle < Value >
File : : Read ( const Arguments & args )
static Handle < Value >
Stat ( const Arguments & args )
{
HandleScope scope ;
if ( args . Length ( ) < 1 | | ! args [ 0 ] - > IsString ( ) )
return ThrowException ( BAD_ARGUMENTS ) ;
if ( args . Length ( ) < 1 | | ! args [ 0 ] - > IsNumber ( ) | | ! args [ 1 ] - > IsNumber ( ) ) {
return ThrowException ( String : : New ( " Bad parameter for _ffi_read() " )) ;
}
HandleScope scope ;
File * file = NODE_UNWRAP ( File , args . Holder ( ) ) ;
size_t len = args [ 0 ] - > IntegerValue ( ) ;
off_t pos = args [ 1 ] - > IntegerValue ( ) ;
String : : Utf8Value path ( args [ 0 ] - > ToString ( ) ) ;
int fd = file - > GetFD ( ) ;
assert ( fd > = 0 ) ;
MAKE_CALLBACK_PTR
// NOTE: 2nd param: NULL pointer tells eio to allocate it itself
node : : eio_warmup ( ) ;
eio_read ( fd , NULL , len , pos , EIO_PRI_DEFAULT , File : : AfterRead , file ) ;
eio_stat ( * path , EIO_PRI_DEFAULT , AfterStat , callback ) ;
file - > Attach ( ) ;
return Undefined ( ) ;
}
int
File : : AfterRead ( eio_req * req )
stat ic Handle < Value >
StrError ( const Arguments & args )
{
File * file = reinterpret_cast < File * > ( req - > data ) ;
HandleScope scope ;
const int argc = 2 ;
Local < Value > argv [ argc ] ;
argv [ 0 ] = Integer : : New ( req - > errorno ) ;
if ( args . Length ( ) < 1 ) return v8 : : Undefined ( ) ;
if ( ! args [ 0 ] - > IsNumber ( ) ) return v8 : : Undefined ( ) ;
char * buf = reinterpret_cast < char * > ( req - > ptr2 ) ;
HandleScope scope ;
if ( req - > result = = 0 ) {
// eof
argv [ 1 ] = Local < Value > : : New ( Null ( ) ) ;
} else {
size_t len = req - > result ;
if ( file - > encoding_ = = UTF8 ) {
// utf8 encoding
argv [ 1 ] = String : : New ( buf , req - > result ) ;
} else {
// raw encoding
Local < Array > array = Array : : New ( len ) ;
for ( unsigned int i = 0 ; i < len ; i + + ) {
array - > Set ( Integer : : New ( i ) , Integer : : New ( buf [ i ] ) ) ;
}
argv [ 1 ] = array ;
}
}
int errorno = args [ 0 ] - > IntegerValue ( ) ;
CallTopCallback ( file - > handle_ , argc , argv ) ;
Local < String > message = String : : New ( strerror ( errorno ) ) ;
file - > Detach ( ) ;
return 0 ;
return scope . Close ( message ) ;
}
Handle < Value >
File : : New ( const Arguments & args )
void
File : : Initialize ( Handle < Object > target )
{
HandleScope scope ;
File * f = new File ( args . Holder ( ) ) ;
ObjectWrap : : InformV8ofAllocation ( f ) ;
return args . This ( ) ;
// file system methods
NODE_SET_METHOD ( target , " rename " , Rename ) ;
NODE_SET_METHOD ( target , " stat " , Stat ) ;
NODE_SET_METHOD ( target , " close " , Close ) ;
NODE_SET_METHOD ( target , " open " , Open ) ;
NODE_SET_METHOD ( target , " write " , Write ) ;
NODE_SET_METHOD ( target , " read " , Read ) ;
NODE_SET_METHOD ( target , " strerror " , StrError ) ;
NODE_DEFINE_CONSTANT ( target , RAW ) ;
NODE_DEFINE_CONSTANT ( target , UTF8 ) ;
NODE_DEFINE_CONSTANT ( target , STDIN_FILENO ) ;
NODE_DEFINE_CONSTANT ( target , STDOUT_FILENO ) ;
NODE_DEFINE_CONSTANT ( target , STDERR_FILENO ) ;
// file access modes
NODE_DEFINE_CONSTANT ( target , O_RDONLY ) ;
NODE_DEFINE_CONSTANT ( target , O_WRONLY ) ;
NODE_DEFINE_CONSTANT ( target , O_RDWR ) ;
// file creation flags
NODE_DEFINE_CONSTANT ( target , O_CREAT ) ;
NODE_DEFINE_CONSTANT ( target , O_EXCL ) ;
NODE_DEFINE_CONSTANT ( target , O_NOCTTY ) ;
NODE_DEFINE_CONSTANT ( target , O_TRUNC ) ;
// file status flags
NODE_DEFINE_CONSTANT ( target , O_APPEND ) ;
// NODE_DEFINE_CONSTANT(target, O_ASYNC);
NODE_DEFINE_CONSTANT ( target , O_CLOEXEC ) ;
NODE_DEFINE_CONSTANT ( target , O_DIRECT ) ;
NODE_DEFINE_CONSTANT ( target , O_DIRECTORY ) ;
NODE_DEFINE_CONSTANT ( target , O_EXCL ) ;
NODE_DEFINE_CONSTANT ( target , O_LARGEFILE ) ;
NODE_DEFINE_CONSTANT ( target , O_NOATIME ) ;
NODE_DEFINE_CONSTANT ( target , O_NOFOLLOW ) ;
// NODE_DEFINE_CONSTANT(target, O_NONBLOCK);
// NODE_DEFINE_CONSTANT(target, O_SYNC);
NODE_DEFINE_CONSTANT ( target , O_SYNC ) ;
NODE_DEFINE_CONSTANT ( target , S_IRWXU ) ;
NODE_DEFINE_CONSTANT ( target , S_IRUSR ) ;
NODE_DEFINE_CONSTANT ( target , S_IWUSR ) ;
NODE_DEFINE_CONSTANT ( target , S_IXUSR ) ;
NODE_DEFINE_CONSTANT ( target , S_IRWXG ) ;
NODE_DEFINE_CONSTANT ( target , S_IRGRP ) ;
NODE_DEFINE_CONSTANT ( target , S_IWGRP ) ;
NODE_DEFINE_CONSTANT ( target , S_IXGRP ) ;
NODE_DEFINE_CONSTANT ( target , S_IRWXO ) ;
NODE_DEFINE_CONSTANT ( target , S_IROTH ) ;
NODE_DEFINE_CONSTANT ( target , S_IWOTH ) ;
NODE_DEFINE_CONSTANT ( target , S_IXOTH ) ;
}