Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F7538030
fs.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
20 KB
Referenced Files
None
Subscribers
None
fs.c
View Options
#include
<uv.h>
#include
<stdio.h>
#include
<stdlib.h>
#include
<string.h>
#include
<sys/stat.h>
#include
<fcntl.h>
#include
<uthash.h>
#include
<utarray.h>
#include
<unistd.h>
#include
<errno.h>
#include
"modules/fs.h"
#include
"runtime.h"
typedef
enum
{
FS_OP_READ
,
FS_OP_WRITE
,
FS_OP_UNLINK
,
FS_OP_MKDIR
,
FS_OP_RMDIR
,
FS_OP_STAT
}
fs_op_type_t
;
typedef
struct
fs_request_s
{
struct
js
*
js
;
jsval_t
promise
;
uv_fs_t
uv_req
;
fs_op_type_t
op_type
;
char
*
path
;
char
*
data
;
size_t
data_len
;
uv_file
fd
;
int
completed
;
int
failed
;
char
*
error_msg
;
}
fs_request_t
;
static
uv_loop_t
*
fs_loop
=
NULL
;
static
UT_array
*
pending_requests
=
NULL
;
static
void
free_fs_request
(
fs_request_t
*
req
)
{
if
(
!
req
)
return
;
if
(
req
->
path
)
free
(
req
->
path
);
if
(
req
->
data
)
free
(
req
->
data
);
if
(
req
->
error_msg
)
free
(
req
->
error_msg
);
uv_fs_req_cleanup
(
&
req
->
uv_req
);
free
(
req
);
}
static
void
remove_pending_request
(
fs_request_t
*
req
)
{
if
(
!
req
||
!
pending_requests
)
return
;
fs_request_t
**
p
=
NULL
;
unsigned
int
i
=
0
;
while
((
p
=
(
fs_request_t
**
)
utarray_next
(
pending_requests
,
p
)))
{
if
(
*
p
==
req
)
{
utarray_erase
(
pending_requests
,
i
,
1
);
break
;
}
i
++
;
}
}
static
void
complete_request
(
fs_request_t
*
req
)
{
if
(
req
->
failed
)
{
const
char
*
err_msg
=
req
->
error_msg
?
req
->
error_msg
:
"Unknown error"
;
jsval_t
err
=
js_mkstr
(
req
->
js
,
err_msg
,
strlen
(
err_msg
));
js_reject_promise
(
req
->
js
,
req
->
promise
,
err
);
}
else
{
jsval_t
result
;
if
(
req
->
op_type
==
FS_OP_READ
&&
req
->
data
)
{
result
=
js_mkstr
(
req
->
js
,
req
->
data
,
req
->
data_len
);
}
else
if
(
req
->
op_type
==
FS_OP_STAT
)
{
result
=
js_mkundef
();
}
else
{
result
=
js_mkundef
();
}
js_resolve_promise
(
req
->
js
,
req
->
promise
,
result
);
}
remove_pending_request
(
req
);
free_fs_request
(
req
);
}
static
void
on_read_complete
(
uv_fs_t
*
uv_req
)
{
fs_request_t
*
req
=
(
fs_request_t
*
)
uv_req
->
data
;
if
(
uv_req
->
result
<
0
)
{
req
->
failed
=
1
;
req
->
error_msg
=
strdup
(
uv_strerror
(
uv_req
->
result
));
req
->
completed
=
1
;
complete_request
(
req
);
return
;
}
req
->
data_len
=
uv_req
->
result
;
uv_fs_t
close_req
;
uv_fs_close
(
fs_loop
,
&
close_req
,
req
->
fd
,
NULL
);
uv_fs_req_cleanup
(
&
close_req
);
req
->
completed
=
1
;
complete_request
(
req
);
}
static
void
on_open_for_read
(
uv_fs_t
*
uv_req
)
{
fs_request_t
*
req
=
(
fs_request_t
*
)
uv_req
->
data
;
if
(
uv_req
->
result
<
0
)
{
req
->
failed
=
1
;
req
->
error_msg
=
strdup
(
uv_strerror
(
uv_req
->
result
));
req
->
completed
=
1
;
complete_request
(
req
);
return
;
}
req
->
fd
=
uv_req
->
result
;
uv_fs_req_cleanup
(
uv_req
);
uv_fs_t
stat_req
;
int
stat_result
=
uv_fs_fstat
(
fs_loop
,
&
stat_req
,
req
->
fd
,
NULL
);
if
(
stat_result
<
0
)
{
req
->
failed
=
1
;
req
->
error_msg
=
strdup
(
uv_strerror
(
stat_result
));
req
->
completed
=
1
;
uv_fs_t
close_req
;
uv_fs_close
(
fs_loop
,
&
close_req
,
req
->
fd
,
NULL
);
uv_fs_req_cleanup
(
&
close_req
);
complete_request
(
req
);
return
;
}
size_t
file_size
=
stat_req
.
statbuf
.
st_size
;
uv_fs_req_cleanup
(
&
stat_req
);
req
->
data
=
malloc
(
file_size
+
1
);
if
(
!
req
->
data
)
{
req
->
failed
=
1
;
req
->
error_msg
=
strdup
(
"Out of memory"
);
req
->
completed
=
1
;
uv_fs_t
close_req
;
uv_fs_close
(
fs_loop
,
&
close_req
,
req
->
fd
,
NULL
);
uv_fs_req_cleanup
(
&
close_req
);
complete_request
(
req
);
return
;
}
uv_buf_t
buf
=
uv_buf_init
(
req
->
data
,
file_size
);
int
read_result
=
uv_fs_read
(
fs_loop
,
uv_req
,
req
->
fd
,
&
buf
,
1
,
0
,
on_read_complete
);
if
(
read_result
<
0
)
{
req
->
failed
=
1
;
req
->
error_msg
=
strdup
(
uv_strerror
(
read_result
));
req
->
completed
=
1
;
uv_fs_t
close_req
;
uv_fs_close
(
fs_loop
,
&
close_req
,
req
->
fd
,
NULL
);
uv_fs_req_cleanup
(
&
close_req
);
complete_request
(
req
);
return
;
}
}
static
void
on_write_complete
(
uv_fs_t
*
uv_req
)
{
fs_request_t
*
req
=
(
fs_request_t
*
)
uv_req
->
data
;
if
(
uv_req
->
result
<
0
)
{
req
->
failed
=
1
;
req
->
error_msg
=
strdup
(
uv_strerror
(
uv_req
->
result
));
}
uv_fs_t
close_req
;
uv_fs_close
(
fs_loop
,
&
close_req
,
req
->
fd
,
NULL
);
uv_fs_req_cleanup
(
&
close_req
);
req
->
completed
=
1
;
complete_request
(
req
);
}
static
void
on_open_for_write
(
uv_fs_t
*
uv_req
)
{
fs_request_t
*
req
=
(
fs_request_t
*
)
uv_req
->
data
;
if
(
uv_req
->
result
<
0
)
{
req
->
failed
=
1
;
req
->
error_msg
=
strdup
(
uv_strerror
(
uv_req
->
result
));
req
->
completed
=
1
;
complete_request
(
req
);
return
;
}
req
->
fd
=
uv_req
->
result
;
uv_fs_req_cleanup
(
uv_req
);
uv_buf_t
buf
=
uv_buf_init
(
req
->
data
,
req
->
data_len
);
int
write_result
=
uv_fs_write
(
fs_loop
,
uv_req
,
req
->
fd
,
&
buf
,
1
,
0
,
on_write_complete
);
if
(
write_result
<
0
)
{
req
->
failed
=
1
;
req
->
error_msg
=
strdup
(
uv_strerror
(
write_result
));
req
->
completed
=
1
;
uv_fs_t
close_req
;
uv_fs_close
(
fs_loop
,
&
close_req
,
req
->
fd
,
NULL
);
uv_fs_req_cleanup
(
&
close_req
);
complete_request
(
req
);
return
;
}
}
static
void
on_unlink_complete
(
uv_fs_t
*
uv_req
)
{
fs_request_t
*
req
=
(
fs_request_t
*
)
uv_req
->
data
;
if
(
uv_req
->
result
<
0
)
{
req
->
failed
=
1
;
req
->
error_msg
=
strdup
(
uv_strerror
(
uv_req
->
result
));
}
uv_fs_req_cleanup
(
uv_req
);
req
->
completed
=
1
;
complete_request
(
req
);
}
static
void
on_mkdir_complete
(
uv_fs_t
*
uv_req
)
{
fs_request_t
*
req
=
(
fs_request_t
*
)
uv_req
->
data
;
if
(
uv_req
->
result
<
0
)
{
req
->
failed
=
1
;
req
->
error_msg
=
strdup
(
uv_strerror
(
uv_req
->
result
));
}
uv_fs_req_cleanup
(
uv_req
);
req
->
completed
=
1
;
complete_request
(
req
);
}
static
void
on_rmdir_complete
(
uv_fs_t
*
uv_req
)
{
fs_request_t
*
req
=
(
fs_request_t
*
)
uv_req
->
data
;
if
(
uv_req
->
result
<
0
)
{
req
->
failed
=
1
;
req
->
error_msg
=
strdup
(
uv_strerror
(
uv_req
->
result
));
}
uv_fs_req_cleanup
(
uv_req
);
req
->
completed
=
1
;
complete_request
(
req
);
}
static
void
on_stat_complete
(
uv_fs_t
*
uv_req
)
{
fs_request_t
*
req
=
(
fs_request_t
*
)
uv_req
->
data
;
if
(
uv_req
->
result
<
0
)
{
req
->
failed
=
1
;
req
->
error_msg
=
strdup
(
uv_strerror
(
uv_req
->
result
));
req
->
completed
=
1
;
complete_request
(
req
);
return
;
}
jsval_t
stat_obj
=
js_mkobj
(
req
->
js
);
js_set
(
req
->
js
,
stat_obj
,
"size"
,
js_mknum
((
double
)
uv_req
->
statbuf
.
st_size
));
js_set
(
req
->
js
,
stat_obj
,
"mode"
,
js_mknum
((
double
)
uv_req
->
statbuf
.
st_mode
));
js_set
(
req
->
js
,
stat_obj
,
"isFile"
,
S_ISREG
(
uv_req
->
statbuf
.
st_mode
)
?
js_mktrue
()
:
js_mkfalse
());
js_set
(
req
->
js
,
stat_obj
,
"isDirectory"
,
S_ISDIR
(
uv_req
->
statbuf
.
st_mode
)
?
js_mktrue
()
:
js_mkfalse
());
req
->
completed
=
1
;
js_resolve_promise
(
req
->
js
,
req
->
promise
,
stat_obj
);
remove_pending_request
(
req
);
free_fs_request
(
req
);
}
static
void
ensure_fs_loop
(
void
)
{
if
(
!
fs_loop
)
{
if
(
rt
->
external_event_loop_active
)
{
fs_loop
=
uv_default_loop
();
}
else
{
fs_loop
=
malloc
(
sizeof
(
uv_loop_t
));
uv_loop_init
(
fs_loop
);
}
}
if
(
!
pending_requests
)
{
utarray_new
(
pending_requests
,
&
ut_ptr_icd
);
}
}
static
jsval_t
builtin_fs_readFileSync
(
struct
js
*
js
,
jsval_t
*
args
,
int
nargs
)
{
if
(
nargs
<
1
)
return
js_mkerr
(
js
,
"readFileSync() requires a path argument"
);
if
(
js_type
(
args
[
0
])
!=
JS_STR
)
return
js_mkerr
(
js
,
"readFileSync() path must be a string"
);
size_t
path_len
;
char
*
path
=
js_getstr
(
js
,
args
[
0
],
&
path_len
);
if
(
!
path
)
return
js_mkerr
(
js
,
"Failed to get path string"
);
char
*
path_cstr
=
strndup
(
path
,
path_len
);
if
(
!
path_cstr
)
return
js_mkerr
(
js
,
"Out of memory"
);
FILE
*
file
=
fopen
(
path_cstr
,
"rb"
);
if
(
!
file
)
{
char
err_msg
[
256
];
snprintf
(
err_msg
,
sizeof
(
err_msg
),
"Failed to open file: %s"
,
strerror
(
errno
));
free
(
path_cstr
);
return
js_mkerr
(
js
,
err_msg
);
}
fseek
(
file
,
0
,
SEEK_END
);
long
file_size
=
ftell
(
file
);
fseek
(
file
,
0
,
SEEK_SET
);
if
(
file_size
<
0
)
{
fclose
(
file
);
free
(
path_cstr
);
return
js_mkerr
(
js
,
"Failed to get file size"
);
}
char
*
data
=
malloc
(
file_size
+
1
);
if
(
!
data
)
{
fclose
(
file
);
free
(
path_cstr
);
return
js_mkerr
(
js
,
"Out of memory"
);
}
size_t
bytes_read
=
fread
(
data
,
1
,
file_size
,
file
);
fclose
(
file
);
free
(
path_cstr
);
if
(
bytes_read
!=
(
size_t
)
file_size
)
{
free
(
data
);
return
js_mkerr
(
js
,
"Failed to read entire file"
);
}
data
[
file_size
]
=
'\0'
;
jsval_t
result
=
js_mkstr
(
js
,
data
,
file_size
);
free
(
data
);
return
result
;
}
static
jsval_t
builtin_fs_readFile
(
struct
js
*
js
,
jsval_t
*
args
,
int
nargs
)
{
if
(
nargs
<
1
)
return
js_mkerr
(
js
,
"readFile() requires a path argument"
);
if
(
js_type
(
args
[
0
])
!=
JS_STR
)
return
js_mkerr
(
js
,
"readFile() path must be a string"
);
size_t
path_len
;
char
*
path
=
js_getstr
(
js
,
args
[
0
],
&
path_len
);
if
(
!
path
)
return
js_mkerr
(
js
,
"Failed to get path string"
);
ensure_fs_loop
();
fs_request_t
*
req
=
calloc
(
1
,
sizeof
(
fs_request_t
));
if
(
!
req
)
return
js_mkerr
(
js
,
"Out of memory"
);
req
->
js
=
js
;
req
->
op_type
=
FS_OP_READ
;
req
->
promise
=
js_mkpromise
(
js
);
req
->
path
=
strndup
(
path
,
path_len
);
req
->
uv_req
.
data
=
req
;
utarray_push_back
(
pending_requests
,
&
req
);
int
result
=
uv_fs_open
(
fs_loop
,
&
req
->
uv_req
,
req
->
path
,
O_RDONLY
,
0
,
on_open_for_read
);
if
(
result
<
0
)
{
req
->
failed
=
1
;
req
->
error_msg
=
strdup
(
uv_strerror
(
result
));
req
->
completed
=
1
;
complete_request
(
req
);
}
return
req
->
promise
;
}
static
jsval_t
builtin_fs_writeFileSync
(
struct
js
*
js
,
jsval_t
*
args
,
int
nargs
)
{
if
(
nargs
<
2
)
return
js_mkerr
(
js
,
"writeFileSync() requires path and data arguments"
);
if
(
js_type
(
args
[
0
])
!=
JS_STR
)
return
js_mkerr
(
js
,
"writeFileSync() path must be a string"
);
if
(
js_type
(
args
[
1
])
!=
JS_STR
)
return
js_mkerr
(
js
,
"writeFileSync() data must be a string"
);
size_t
path_len
,
data_len
;
char
*
path
=
js_getstr
(
js
,
args
[
0
],
&
path_len
);
char
*
data
=
js_getstr
(
js
,
args
[
1
],
&
data_len
);
if
(
!
path
||
!
data
)
return
js_mkerr
(
js
,
"Failed to get arguments"
);
char
*
path_cstr
=
strndup
(
path
,
path_len
);
if
(
!
path_cstr
)
return
js_mkerr
(
js
,
"Out of memory"
);
FILE
*
file
=
fopen
(
path_cstr
,
"wb"
);
if
(
!
file
)
{
char
err_msg
[
256
];
snprintf
(
err_msg
,
sizeof
(
err_msg
),
"Failed to open file: %s"
,
strerror
(
errno
));
free
(
path_cstr
);
return
js_mkerr
(
js
,
err_msg
);
}
size_t
bytes_written
=
fwrite
(
data
,
1
,
data_len
,
file
);
fclose
(
file
);
free
(
path_cstr
);
if
(
bytes_written
!=
data_len
)
{
return
js_mkerr
(
js
,
"Failed to write entire file"
);
}
return
js_mkundef
();
}
static
jsval_t
builtin_fs_writeFile
(
struct
js
*
js
,
jsval_t
*
args
,
int
nargs
)
{
if
(
nargs
<
2
)
return
js_mkerr
(
js
,
"writeFile() requires path and data arguments"
);
if
(
js_type
(
args
[
0
])
!=
JS_STR
)
return
js_mkerr
(
js
,
"writeFile() path must be a string"
);
if
(
js_type
(
args
[
1
])
!=
JS_STR
)
return
js_mkerr
(
js
,
"writeFile() data must be a string"
);
size_t
path_len
,
data_len
;
char
*
path
=
js_getstr
(
js
,
args
[
0
],
&
path_len
);
char
*
data
=
js_getstr
(
js
,
args
[
1
],
&
data_len
);
if
(
!
path
||
!
data
)
return
js_mkerr
(
js
,
"Failed to get arguments"
);
ensure_fs_loop
();
fs_request_t
*
req
=
calloc
(
1
,
sizeof
(
fs_request_t
));
if
(
!
req
)
return
js_mkerr
(
js
,
"Out of memory"
);
req
->
js
=
js
;
req
->
op_type
=
FS_OP_WRITE
;
req
->
promise
=
js_mkpromise
(
js
);
req
->
path
=
strndup
(
path
,
path_len
);
req
->
data
=
malloc
(
data_len
);
if
(
!
req
->
data
)
{
free
(
req
->
path
);
free
(
req
);
return
js_mkerr
(
js
,
"Out of memory"
);
}
memcpy
(
req
->
data
,
data
,
data_len
);
req
->
data_len
=
data_len
;
req
->
uv_req
.
data
=
req
;
utarray_push_back
(
pending_requests
,
&
req
);
int
result
=
uv_fs_open
(
fs_loop
,
&
req
->
uv_req
,
req
->
path
,
O_WRONLY
|
O_CREAT
|
O_TRUNC
,
0644
,
on_open_for_write
);
if
(
result
<
0
)
{
req
->
failed
=
1
;
req
->
error_msg
=
strdup
(
uv_strerror
(
result
));
req
->
completed
=
1
;
complete_request
(
req
);
}
return
req
->
promise
;
}
static
jsval_t
builtin_fs_unlinkSync
(
struct
js
*
js
,
jsval_t
*
args
,
int
nargs
)
{
if
(
nargs
<
1
)
return
js_mkerr
(
js
,
"unlinkSync() requires a path argument"
);
if
(
js_type
(
args
[
0
])
!=
JS_STR
)
return
js_mkerr
(
js
,
"unlinkSync() path must be a string"
);
size_t
path_len
;
char
*
path
=
js_getstr
(
js
,
args
[
0
],
&
path_len
);
if
(
!
path
)
return
js_mkerr
(
js
,
"Failed to get path string"
);
char
*
path_cstr
=
strndup
(
path
,
path_len
);
if
(
!
path_cstr
)
return
js_mkerr
(
js
,
"Out of memory"
);
int
result
=
unlink
(
path_cstr
);
free
(
path_cstr
);
if
(
result
!=
0
)
{
char
err_msg
[
256
];
snprintf
(
err_msg
,
sizeof
(
err_msg
),
"Failed to unlink file: %s"
,
strerror
(
errno
));
return
js_mkerr
(
js
,
err_msg
);
}
return
js_mkundef
();
}
static
jsval_t
builtin_fs_unlink
(
struct
js
*
js
,
jsval_t
*
args
,
int
nargs
)
{
if
(
nargs
<
1
)
return
js_mkerr
(
js
,
"unlink() requires a path argument"
);
if
(
js_type
(
args
[
0
])
!=
JS_STR
)
return
js_mkerr
(
js
,
"unlink() path must be a string"
);
size_t
path_len
;
char
*
path
=
js_getstr
(
js
,
args
[
0
],
&
path_len
);
if
(
!
path
)
return
js_mkerr
(
js
,
"Failed to get path string"
);
ensure_fs_loop
();
fs_request_t
*
req
=
calloc
(
1
,
sizeof
(
fs_request_t
));
if
(
!
req
)
return
js_mkerr
(
js
,
"Out of memory"
);
req
->
js
=
js
;
req
->
op_type
=
FS_OP_UNLINK
;
req
->
promise
=
js_mkpromise
(
js
);
req
->
path
=
strndup
(
path
,
path_len
);
req
->
uv_req
.
data
=
req
;
utarray_push_back
(
pending_requests
,
&
req
);
int
result
=
uv_fs_unlink
(
fs_loop
,
&
req
->
uv_req
,
req
->
path
,
on_unlink_complete
);
if
(
result
<
0
)
{
req
->
failed
=
1
;
req
->
error_msg
=
strdup
(
uv_strerror
(
result
));
req
->
completed
=
1
;
complete_request
(
req
);
}
return
req
->
promise
;
}
static
jsval_t
builtin_fs_mkdirSync
(
struct
js
*
js
,
jsval_t
*
args
,
int
nargs
)
{
if
(
nargs
<
1
)
return
js_mkerr
(
js
,
"mkdirSync() requires a path argument"
);
if
(
js_type
(
args
[
0
])
!=
JS_STR
)
return
js_mkerr
(
js
,
"mkdirSync() path must be a string"
);
size_t
path_len
;
char
*
path
=
js_getstr
(
js
,
args
[
0
],
&
path_len
);
if
(
!
path
)
return
js_mkerr
(
js
,
"Failed to get path string"
);
int
mode
=
0755
;
if
(
nargs
>=
2
&&
js_type
(
args
[
1
])
==
JS_NUM
)
{
mode
=
(
int
)
js_getnum
(
args
[
1
]);
}
char
*
path_cstr
=
strndup
(
path
,
path_len
);
if
(
!
path_cstr
)
return
js_mkerr
(
js
,
"Out of memory"
);
#ifdef _WIN32
int
result
=
_mkdir
(
path_cstr
);
#else
int
result
=
mkdir
(
path_cstr
,
mode
);
#endif
free
(
path_cstr
);
if
(
result
!=
0
)
{
char
err_msg
[
256
];
snprintf
(
err_msg
,
sizeof
(
err_msg
),
"Failed to create directory: %s"
,
strerror
(
errno
));
return
js_mkerr
(
js
,
err_msg
);
}
return
js_mkundef
();
}
static
jsval_t
builtin_fs_mkdir
(
struct
js
*
js
,
jsval_t
*
args
,
int
nargs
)
{
if
(
nargs
<
1
)
return
js_mkerr
(
js
,
"mkdir() requires a path argument"
);
if
(
js_type
(
args
[
0
])
!=
JS_STR
)
return
js_mkerr
(
js
,
"mkdir() path must be a string"
);
size_t
path_len
;
char
*
path
=
js_getstr
(
js
,
args
[
0
],
&
path_len
);
if
(
!
path
)
return
js_mkerr
(
js
,
"Failed to get path string"
);
int
mode
=
0755
;
if
(
nargs
>=
2
&&
js_type
(
args
[
1
])
==
JS_NUM
)
{
mode
=
(
int
)
js_getnum
(
args
[
1
]);
}
ensure_fs_loop
();
fs_request_t
*
req
=
calloc
(
1
,
sizeof
(
fs_request_t
));
if
(
!
req
)
return
js_mkerr
(
js
,
"Out of memory"
);
req
->
js
=
js
;
req
->
op_type
=
FS_OP_MKDIR
;
req
->
promise
=
js_mkpromise
(
js
);
req
->
path
=
strndup
(
path
,
path_len
);
req
->
uv_req
.
data
=
req
;
utarray_push_back
(
pending_requests
,
&
req
);
int
result
=
uv_fs_mkdir
(
fs_loop
,
&
req
->
uv_req
,
req
->
path
,
mode
,
on_mkdir_complete
);
if
(
result
<
0
)
{
req
->
failed
=
1
;
req
->
error_msg
=
strdup
(
uv_strerror
(
result
));
req
->
completed
=
1
;
complete_request
(
req
);
}
return
req
->
promise
;
}
static
jsval_t
builtin_fs_rmdirSync
(
struct
js
*
js
,
jsval_t
*
args
,
int
nargs
)
{
if
(
nargs
<
1
)
return
js_mkerr
(
js
,
"rmdirSync() requires a path argument"
);
if
(
js_type
(
args
[
0
])
!=
JS_STR
)
return
js_mkerr
(
js
,
"rmdirSync() path must be a string"
);
size_t
path_len
;
char
*
path
=
js_getstr
(
js
,
args
[
0
],
&
path_len
);
if
(
!
path
)
return
js_mkerr
(
js
,
"Failed to get path string"
);
char
*
path_cstr
=
strndup
(
path
,
path_len
);
if
(
!
path_cstr
)
return
js_mkerr
(
js
,
"Out of memory"
);
#ifdef _WIN32
int
result
=
_rmdir
(
path_cstr
);
#else
int
result
=
rmdir
(
path_cstr
);
#endif
free
(
path_cstr
);
if
(
result
!=
0
)
{
char
err_msg
[
256
];
snprintf
(
err_msg
,
sizeof
(
err_msg
),
"Failed to remove directory: %s"
,
strerror
(
errno
));
return
js_mkerr
(
js
,
err_msg
);
}
return
js_mkundef
();
}
static
jsval_t
builtin_fs_rmdir
(
struct
js
*
js
,
jsval_t
*
args
,
int
nargs
)
{
if
(
nargs
<
1
)
return
js_mkerr
(
js
,
"rmdir() requires a path argument"
);
if
(
js_type
(
args
[
0
])
!=
JS_STR
)
return
js_mkerr
(
js
,
"rmdir() path must be a string"
);
size_t
path_len
;
char
*
path
=
js_getstr
(
js
,
args
[
0
],
&
path_len
);
if
(
!
path
)
return
js_mkerr
(
js
,
"Failed to get path string"
);
ensure_fs_loop
();
fs_request_t
*
req
=
calloc
(
1
,
sizeof
(
fs_request_t
));
if
(
!
req
)
return
js_mkerr
(
js
,
"Out of memory"
);
req
->
js
=
js
;
req
->
op_type
=
FS_OP_RMDIR
;
req
->
promise
=
js_mkpromise
(
js
);
req
->
path
=
strndup
(
path
,
path_len
);
req
->
uv_req
.
data
=
req
;
utarray_push_back
(
pending_requests
,
&
req
);
int
result
=
uv_fs_rmdir
(
fs_loop
,
&
req
->
uv_req
,
req
->
path
,
on_rmdir_complete
);
if
(
result
<
0
)
{
req
->
failed
=
1
;
req
->
error_msg
=
strdup
(
uv_strerror
(
result
));
req
->
completed
=
1
;
complete_request
(
req
);
}
return
req
->
promise
;
}
static
jsval_t
builtin_fs_statSync
(
struct
js
*
js
,
jsval_t
*
args
,
int
nargs
)
{
if
(
nargs
<
1
)
return
js_mkerr
(
js
,
"statSync() requires a path argument"
);
if
(
js_type
(
args
[
0
])
!=
JS_STR
)
return
js_mkerr
(
js
,
"statSync() path must be a string"
);
size_t
path_len
;
char
*
path
=
js_getstr
(
js
,
args
[
0
],
&
path_len
);
if
(
!
path
)
return
js_mkerr
(
js
,
"Failed to get path string"
);
char
*
path_cstr
=
strndup
(
path
,
path_len
);
if
(
!
path_cstr
)
return
js_mkerr
(
js
,
"Out of memory"
);
struct
stat
st
;
int
result
=
stat
(
path_cstr
,
&
st
);
free
(
path_cstr
);
if
(
result
!=
0
)
{
char
err_msg
[
256
];
snprintf
(
err_msg
,
sizeof
(
err_msg
),
"Failed to stat file: %s"
,
strerror
(
errno
));
return
js_mkerr
(
js
,
err_msg
);
}
jsval_t
stat_obj
=
js_mkobj
(
js
);
js_set
(
js
,
stat_obj
,
"size"
,
js_mknum
((
double
)
st
.
st_size
));
js_set
(
js
,
stat_obj
,
"mode"
,
js_mknum
((
double
)
st
.
st_mode
));
js_set
(
js
,
stat_obj
,
"isFile"
,
S_ISREG
(
st
.
st_mode
)
?
js_mktrue
()
:
js_mkfalse
());
js_set
(
js
,
stat_obj
,
"isDirectory"
,
S_ISDIR
(
st
.
st_mode
)
?
js_mktrue
()
:
js_mkfalse
());
return
stat_obj
;
}
static
jsval_t
builtin_fs_stat
(
struct
js
*
js
,
jsval_t
*
args
,
int
nargs
)
{
if
(
nargs
<
1
)
return
js_mkerr
(
js
,
"stat() requires a path argument"
);
if
(
js_type
(
args
[
0
])
!=
JS_STR
)
return
js_mkerr
(
js
,
"stat() path must be a string"
);
size_t
path_len
;
char
*
path
=
js_getstr
(
js
,
args
[
0
],
&
path_len
);
if
(
!
path
)
return
js_mkerr
(
js
,
"Failed to get path string"
);
ensure_fs_loop
();
fs_request_t
*
req
=
calloc
(
1
,
sizeof
(
fs_request_t
));
if
(
!
req
)
return
js_mkerr
(
js
,
"Out of memory"
);
req
->
js
=
js
;
req
->
op_type
=
FS_OP_STAT
;
req
->
promise
=
js_mkpromise
(
js
);
req
->
path
=
strndup
(
path
,
path_len
);
req
->
uv_req
.
data
=
req
;
utarray_push_back
(
pending_requests
,
&
req
);
int
result
=
uv_fs_stat
(
fs_loop
,
&
req
->
uv_req
,
req
->
path
,
on_stat_complete
);
if
(
result
<
0
)
{
req
->
failed
=
1
;
req
->
error_msg
=
strdup
(
uv_strerror
(
result
));
req
->
completed
=
1
;
complete_request
(
req
);
}
return
req
->
promise
;
}
jsval_t
fs_library
(
struct
js
*
js
)
{
jsval_t
lib
=
js_mkobj
(
js
);
js_set
(
js
,
lib
,
"readFile"
,
js_mkfun
(
builtin_fs_readFile
));
js_set
(
js
,
lib
,
"readFileSync"
,
js_mkfun
(
builtin_fs_readFileSync
));
js_set
(
js
,
lib
,
"writeFile"
,
js_mkfun
(
builtin_fs_writeFile
));
js_set
(
js
,
lib
,
"writeFileSync"
,
js_mkfun
(
builtin_fs_writeFileSync
));
js_set
(
js
,
lib
,
"unlink"
,
js_mkfun
(
builtin_fs_unlink
));
js_set
(
js
,
lib
,
"unlinkSync"
,
js_mkfun
(
builtin_fs_unlinkSync
));
js_set
(
js
,
lib
,
"mkdir"
,
js_mkfun
(
builtin_fs_mkdir
));
js_set
(
js
,
lib
,
"mkdirSync"
,
js_mkfun
(
builtin_fs_mkdirSync
));
js_set
(
js
,
lib
,
"rmdir"
,
js_mkfun
(
builtin_fs_rmdir
));
js_set
(
js
,
lib
,
"rmdirSync"
,
js_mkfun
(
builtin_fs_rmdirSync
));
js_set
(
js
,
lib
,
"stat"
,
js_mkfun
(
builtin_fs_stat
));
js_set
(
js
,
lib
,
"statSync"
,
js_mkfun
(
builtin_fs_statSync
));
js_set
(
js
,
lib
,
"@@toStringTag"
,
js_mkstr
(
js
,
"fs"
,
2
));
return
lib
;
}
int
has_pending_fs_ops
(
void
)
{
return
(
pending_requests
&&
utarray_len
(
pending_requests
)
>
0
)
||
(
fs_loop
&&
uv_loop_alive
(
fs_loop
));
}
void
fs_poll_events
(
void
)
{
if
(
fs_loop
&&
fs_loop
==
uv_default_loop
()
&&
rt
->
external_event_loop_active
)
return
;
if
(
fs_loop
&&
uv_loop_alive
(
fs_loop
))
{
uv_run
(
fs_loop
,
UV_RUN_ONCE
);
if
(
pending_requests
&&
utarray_len
(
pending_requests
)
>
0
)
usleep
(
1000
);
}
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Wed, Jun 17, 12:49 PM (1 d, 1 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
533339
Default Alt Text
fs.c (20 KB)
Attached To
Mode
rANT Ant
Attached
Detach File
Event Timeline
Log In to Comment