Skip to content

Commit 3eb0605

Browse files
authored
Add os.mkdtemp() and os.mkstemp() (#1364)
1 parent 4f020b2 commit 3eb0605

3 files changed

Lines changed: 91 additions & 0 deletions

File tree

docs/docs/stdlib.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,31 @@ Change the current directory. Return 0 if OK or `-errno`.
154154

155155
Create a directory at `path`. Return 0 if OK or `-errno`.
156156

157+
### `mkdtemp(pattern = "tmpXXXXXX")`
158+
159+
Create a temporary directory. `XXXXXX` must be at the end of the pattern
160+
string and is replaced with a random name. The directory is created with
161+
file mode `0o700`.
162+
163+
Return `[path, err]` where `path` is a string and `err` is 0 or `-errno`.
164+
165+
Not available on Windows and WASI.
166+
167+
### `mkstemp(pattern = "tmpXXXXXX")`
168+
169+
Create a temporary file and open it. `XXXXXX` must be at the end of the
170+
pattern string and is replaced with a random name. The file is created with
171+
file mode `0o600` and opened in read/write mode.
172+
173+
Return `[path, fd]` where `path` is a string and `fd` is the file descriptor
174+
or `-errno`, i.e., the error code if less than zero.
175+
176+
Unlike `std.tmpfile()`, the file is not automatically deleted on close.
177+
178+
See also `std.fdopen()`.
179+
180+
Not available on Windows and WASI.
181+
157182
### `stat(path)` / `lstat(path)`
158183

159184
Return `[obj, err]` where `obj` is an object containing the

quickjs-libc.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3093,6 +3093,53 @@ static JSValue js_os_readdir(JSContext *ctx, JSValueConst this_val,
30933093
#endif
30943094
}
30953095

3096+
#if !defined(_WIN32) && !defined(__wasi__)
3097+
#define PAT "XXXXXX"
3098+
#define PSZ (sizeof(PAT)-1)
3099+
static JSValue js_os_mkdstemp(JSContext *ctx, JSValueConst this_val,
3100+
int argc, JSValueConst *argv, int magic)
3101+
{
3102+
char pat_s[32] = "tmp"PAT, *pat = pat_s;
3103+
const char *s;
3104+
size_t k, n;
3105+
JSValue val;
3106+
int err;
3107+
3108+
if (argc > 0) {
3109+
s = JS_ToCStringLen(ctx, &n, argv[0]);
3110+
if (!s)
3111+
return JS_EXCEPTION;
3112+
k = n;
3113+
if (n < PSZ || memcmp(&s[n-PSZ], PAT, PSZ))
3114+
k += PSZ;
3115+
if (k >= sizeof(pat_s))
3116+
pat = js_malloc(ctx, k+1);
3117+
if (pat) {
3118+
memcpy(pat, s, n);
3119+
if (n < k)
3120+
memcpy(&pat[n], PAT, PSZ);
3121+
pat[k] = '\0';
3122+
}
3123+
JS_FreeCString(ctx, s);
3124+
if (!pat)
3125+
return JS_EXCEPTION;
3126+
}
3127+
if (magic == 'd') {
3128+
err = 0;
3129+
if (!mkdtemp(pat))
3130+
err = -errno;
3131+
} else {
3132+
err = js_get_errno(mkstemp(pat));
3133+
}
3134+
val = JS_NewString(ctx, pat);
3135+
if (pat != pat_s)
3136+
js_free(ctx, pat);
3137+
return make_obj_error(ctx, val, err);
3138+
}
3139+
#undef PSZ
3140+
#undef PAT
3141+
#endif // !defined(_WIN32) && !defined(__wasi__)
3142+
30963143
#if !defined(_WIN32)
30973144
static int64_t timespec_to_ms(const struct timespec *tv)
30983145
{
@@ -4356,6 +4403,10 @@ static const JSCFunctionListEntry js_os_funcs[] = {
43564403
JS_CFUNC_DEF("chdir", 0, js_os_chdir ),
43574404
JS_CFUNC_DEF("mkdir", 1, js_os_mkdir ),
43584405
JS_CFUNC_DEF("readdir", 1, js_os_readdir ),
4406+
#if !defined(_WIN32) && !defined(__wasi__)
4407+
JS_CFUNC_MAGIC_DEF("mkdtemp", 0, js_os_mkdstemp, 'd' ),
4408+
JS_CFUNC_MAGIC_DEF("mkstemp", 0, js_os_mkdstemp, 's' ),
4409+
#endif
43594410
/* st_mode constants */
43604411
OS_FLAG(S_IFMT),
43614412
OS_FLAG(S_IFIFO),

tests/test_std.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,21 @@ function test_os()
213213
assert(fd < 0);
214214

215215
assert(os.remove(fdir) === 0);
216+
217+
if (!isWin) {
218+
[fdir, err] = os.mkdtemp();
219+
assert(err, 0);
220+
assert(fdir.startsWith("tmp"));
221+
assert(fdir.length, 9);
222+
223+
[fpath, fd] = os.mkstemp(`${fdir}/XXXXXX`);
224+
assert(fdir.startsWith(`${fdir}`));
225+
assert(fd >= 0);
226+
os.close(fd);
227+
228+
assert(os.remove(fpath), 0);
229+
assert(os.remove(fdir), 0);
230+
}
216231
}
217232

218233
function test_os_exec()

0 commit comments

Comments
 (0)