Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 98 additions & 5 deletions quickjs-libc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1034,6 +1034,15 @@ typedef struct {
bool is_popen;
} JSSTDFile;

#if defined(__MINGW64__)
enum JSSTDFileKind { STDFile, STDPipe, TMPFile };
typedef struct {
FILE *f;
enum JSSTDFileKind kind;
char *filename;
} JSTMPFile;
#endif

static bool is_stdio(FILE *f)
{
return f == stdin || f == stdout || f == stderr;
Expand All @@ -1044,13 +1053,23 @@ static void js_std_file_finalizer(JSRuntime *rt, JSValueConst val)
JSThreadState *ts = js_get_thread_state(rt);
JSSTDFile *s = JS_GetOpaque(val, ts->std_file_class_id);
if (s) {
#if defined(__MINGW64__)
JSTMPFile *ss = (JSTMPFile*) s;
if (ss->kind == TMPFile) {
if (ss->f) fclose(ss->f);
if (ss->filename != 0) remove(ss->filename);
js_free_rt(rt, ss->filename);
return;
};
#endif
if (s->f && !is_stdio(s->f)) {
#if !defined(__wasi__)
if (s->is_popen)
pclose(s->f);
else
#endif
fclose(s->f);

}
js_free_rt(rt, s);
}
Expand Down Expand Up @@ -1207,6 +1226,67 @@ static JSValue js_std_fdopen(JSContext *ctx, JSValueConst this_val,
}

#if !defined(__wasi__)
#if defined(__MINGW64__)
static JSValue js_std_tmpfile(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
JSRuntime *rt = JS_GetRuntime(ctx);
JSThreadState *ts = js_get_thread_state(rt);
JSTMPFile *s;
JSValue obj;
char *env_tmp, *fn_buff;
int mk_fd, path_len, fn_template_len, fn_total_len;

obj = JS_NewObjectClass(ctx, ts->std_file_class_id);
if (JS_IsException(obj))
return JS_EXCEPTION;
s = js_mallocz(ctx, sizeof(*s));
if (!s) {
JS_FreeValue(ctx, obj);
return JS_EXCEPTION;
}
static char* fn_template = "qXXXXXXX";
fn_template_len = strlen(fn_template) + 1;
fn_total_len = fn_template_len;
path_len = 0;
env_tmp = getenv("TMP");
if (!env_tmp)
env_tmp = getenv("TEMP");
if (env_tmp) {
path_len = strlen(env_tmp);
fn_total_len = path_len + 1 + fn_template_len;
}
fn_buff = js_malloc(ctx, path_len + fn_total_len);
if (env_tmp) {
memcpy(fn_buff, env_tmp, path_len);
fn_buff[path_len] = '\\';
path_len++;
}
memcpy(fn_buff + path_len, fn_template, fn_template_len);
mk_fd = mkstemp(fn_buff);
if (mk_fd == -1) {
JS_ThrowInternalError(ctx, "tmpfile failed to create file with error: %d.", errno);
goto file_failure;
};
s->f = fdopen( mk_fd, "a+");
if (!s->f) {
JS_ThrowInternalError(ctx, "tmpfile failed to open file with error: %d.", errno);
close(mk_fd);
goto file_failure;
};
s->filename = fn_buff;
s->kind = TMPFile;
if (argc >= 1)
js_set_error_object(ctx, argv[0], s->f ? 0 : errno);
JS_SetOpaque(obj, s);
return obj;
file_failure:
JS_FreeValue(ctx, obj);
js_free(ctx, s);
js_free(ctx, fn_buff);
return JS_EXCEPTION;
}
#else // MINGW
static JSValue js_std_tmpfile(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
Expand All @@ -1218,7 +1298,8 @@ static JSValue js_std_tmpfile(JSContext *ctx, JSValueConst this_val,
return JS_NULL;
return js_new_std_file(ctx, f, false);
}
#endif
#endif // !MINGW
#endif // WASI

static JSValue js_std_sprintf(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
Expand Down Expand Up @@ -3055,9 +3136,8 @@ static JSValue js_os_realpath(JSContext *ctx, JSValueConst this_val,
}
return make_string_error(ctx, buf, err);
}
#endif

#if !defined(_WIN32) && !defined(__wasi__)
/* in WIN32: (0 | err) os.symlink(target, linkpath, bool isDirectory)
@ msdn: linkpath and target have reversed meaning than symlink! */
static JSValue js_os_symlink(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
Expand All @@ -3072,12 +3152,25 @@ static JSValue js_os_symlink(JSContext *ctx, JSValueConst this_val,
JS_FreeCString(ctx, target);
return JS_EXCEPTION;
}
#if defined(_WIN32)
int isdirflag = 0;
if (argc > 2) {
if (JS_ToInt32(ctx, &isdirflag, argv[2])) return JS_EXCEPTION;
}
err = CreateSymbolicLinkA(linkpath, target, ( isdirflag |
SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE ) ) ;
if (!err) err = GetLastError();
else err = 0;
#else
err = js_get_errno(symlink(target, linkpath));
#endif
JS_FreeCString(ctx, target);
JS_FreeCString(ctx, linkpath);
return JS_NewInt32(ctx, err);
}
#endif

#if !defined(_WIN32) && !defined(__wasi__)
/* return [path, errorcode] */
static JSValue js_os_readlink(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
Expand Down Expand Up @@ -4113,10 +4206,10 @@ static const JSCFunctionListEntry js_os_funcs[] = {
JS_CFUNC_DEF("sleep", 1, js_os_sleep ),
#if !defined(__wasi__)
JS_CFUNC_DEF("realpath", 1, js_os_realpath ),
JS_CFUNC_DEF("symlink", 2, js_os_symlink ),
#endif
#if !defined(_WIN32) && !defined(__wasi__)
JS_CFUNC_MAGIC_DEF("lstat", 1, js_os_stat, 1 ),
JS_CFUNC_DEF("symlink", 2, js_os_symlink ),
JS_CFUNC_DEF("readlink", 1, js_os_readlink ),
JS_CFUNC_DEF("exec", 1, js_os_exec ),
JS_CFUNC_DEF("getpid", 0, js_os_getpid ),
Expand Down
10 changes: 7 additions & 3 deletions tests/test_std.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { assert } from "./assert.js";
const isWin = os.platform === 'win32';
const isCygwin = os.platform === 'cygwin';


function test_printf()
{
assert(std.sprintf("a=%d s=%s", 123, "abc"), "a=123 s=abc");
Expand Down Expand Up @@ -160,7 +159,7 @@ function test_os()
assert(err, 0);
assert(files.indexOf(fname) >= 0);

fdate = 10000;
fdate = 86400000;

err = os.utimes(fpath, fdate, fdate);
assert(err, 0);
Expand All @@ -170,8 +169,9 @@ function test_os()
assert(st.mode & os.S_IFMT, os.S_IFREG);
assert(st.mtime, fdate);

err = os.symlink(fname, link_path);

if (!isWin) {
err = os.symlink(fname, link_path);
assert(err, 0);

[st, err] = os.lstat(link_path);
Expand All @@ -183,6 +183,10 @@ function test_os()
assert(buf, fname);

assert(os.remove(link_path) === 0);

} else if (err != 1314) {
assert(err, 0);
assert(os.remove(link_path) === 0);
}

[buf, err] = os.getcwd();
Expand Down