mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-28 08:12:28 +00:00
Make improvements
- Invent openatemp() API - Invent O_UNLINK open flag - Introduce getenv_secure() API - Remove `git pull` from cosmocc - Fix utimes() when path is NULL - Fix mktemp() to never return NULL - Fix utimensat() UTIME_OMIT on XNU - Improve utimensat() code for RHEL5 - Turn `argv[0]` C:/ to /C/ on Windows - Introduce tmpnam() and tmpnam_r() APIs - Fix more const issues with internal APIs - Permit utimes() on WIN32 in O_RDONLY mode - Fix fdopendir() to check fd is a directory - Fix recent crash regression in landlock make - Fix futimens(AT_FDCWD, NULL) to return EBADF - Use workaround so `make -j` doesn't fork bomb - Rename dontdiscard to __wur (just like glibc) - Fix st_size for WIN32 symlinks containing UTF-8 - Introduce stdio ext APIs needed by GNU coreutils - Fix lstat() on WIN32 for symlinks to directories - Move some constants from normalize.inc to limits.h - Fix segv with memchr() and memcmp() overlapping page - Implement POSIX fflush() behavior for reader streams - Implement AT_SYMLINK_NOFOLLOW for utimensat() on WIN32 - Don't change read-only status of existing files on WIN32 - Correctly handle `0x[^[:xdigit:]]` case in strtol() functions
This commit is contained in:
parent
8596e83cce
commit
f531acc8f9
297 changed files with 1920 additions and 1681 deletions
|
@ -1,7 +1,7 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
|
@ -16,8 +16,9 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/stdio/temp.h"
|
||||
#include "libc/stdio/internal.h"
|
||||
#include "libc/stdio/stdio_ext.h"
|
||||
|
||||
int mkstemps(char *template, int suffixlen) {
|
||||
return mkostempsm(template, suffixlen, 0, 0600);
|
||||
size_t __freadahead(FILE *f) {
|
||||
return f->beg <= f->end ? f->end - f->beg : 0;
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
|
@ -16,11 +16,11 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/stdio/temp.h"
|
||||
#include "libc/stdio/internal.h"
|
||||
#include "libc/stdio/stdio_ext.h"
|
||||
|
||||
/**
|
||||
* Delegates to mkotempsm() w/ owner-only non-execute access.
|
||||
*/
|
||||
dontdiscard int mkostemps(char *template, int suffixlen, unsigned flags) {
|
||||
return mkostempsm(template, suffixlen, flags, 0600);
|
||||
const char *__freadptr(FILE *f, size_t *sizep) {
|
||||
if (f->beg == f->end) return 0;
|
||||
*sizep = f->end - f->beg;
|
||||
return (const char *)f->buf + f->beg;
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
|
@ -16,8 +16,9 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/stdio/temp.h"
|
||||
#include "libc/stdio/internal.h"
|
||||
#include "libc/stdio/stdio_ext.h"
|
||||
|
||||
int mkostemp(char *template, unsigned flags) {
|
||||
return mkostempsm(template, 0, flags, 0600);
|
||||
void __freadptrinc(FILE *f, size_t inc) {
|
||||
f->beg += inc;
|
||||
}
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/dirent.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
|
@ -42,6 +43,7 @@
|
|||
#include "libc/runtime/zipos.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/dt.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/s.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
@ -262,6 +264,20 @@ GiveUpOnGettingInode:
|
|||
*/
|
||||
DIR *fdopendir(int fd) {
|
||||
|
||||
// sanity check file descriptor
|
||||
struct stat st;
|
||||
if (fstat(fd, &st) == -1) {
|
||||
return 0;
|
||||
}
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
enotdir();
|
||||
return 0;
|
||||
}
|
||||
if (IsLinux() && (__sys_fcntl(fd, F_GETFL) & O_PATH)) {
|
||||
ebadf();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// allocate directory iterator object
|
||||
DIR *dir;
|
||||
if (!(dir = calloc(1, sizeof(*dir)))) {
|
||||
|
|
|
@ -34,14 +34,23 @@ int __fflush_impl(FILE *f) {
|
|||
}
|
||||
f->getln = 0;
|
||||
}
|
||||
if (f->beg && !f->end && (f->iomode & O_ACCMODE) != O_RDONLY) {
|
||||
for (i = 0; i < f->beg; i += rc) {
|
||||
if ((rc = write(f->fd, f->buf + i, f->beg - i)) == -1) {
|
||||
if (f->fd != -1) {
|
||||
if (f->beg && !f->end && (f->iomode & O_ACCMODE) != O_RDONLY) {
|
||||
for (i = 0; i < f->beg; i += rc) {
|
||||
if ((rc = write(f->fd, f->buf + i, f->beg - i)) == -1) {
|
||||
f->state = errno;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
f->beg = 0;
|
||||
}
|
||||
if (f->beg < f->end && (f->iomode & O_ACCMODE) != O_WRONLY) {
|
||||
if (lseek(f->fd, -(int)(f->end - f->beg), SEEK_CUR) == -1) {
|
||||
f->state = errno;
|
||||
return -1;
|
||||
}
|
||||
f->end = f->beg;
|
||||
}
|
||||
f->beg = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ size_t fwrite_unlocked(const void *data, size_t stride, size_t count, FILE *f) {
|
|||
}
|
||||
m = f->size - f->beg;
|
||||
if (n <= m && f->bufmode != _IONBF) {
|
||||
// this isn't a fully buffered stream, and
|
||||
// this isn't an unbuffered stream, and
|
||||
// there's enough room in the buffer for the request
|
||||
memcpy(f->buf + f->beg, data, n);
|
||||
f->beg += n;
|
||||
|
|
|
@ -10,7 +10,7 @@ COSMOPOLITAN_C_START_
|
|||
|
||||
struct FILE {
|
||||
uint8_t bufmode; /* 0x00 _IOFBF, etc. (ignored if fd=-1) */
|
||||
bool noclose; /* 0x01 for fake dup() todo delete! */
|
||||
char noclose; /* 0x01 for fake dup() todo delete! */
|
||||
uint32_t iomode; /* 0x04 O_RDONLY, etc. (ignored if fd=-1) */
|
||||
int32_t state; /* 0x08 0=OK, -1=EOF, >0=errno */
|
||||
int fd; /* 0x0c ≥0=fd, -1=closed|buffer */
|
||||
|
|
|
@ -1,85 +0,0 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/lcg.internal.h"
|
||||
#include "libc/stdio/rand.h"
|
||||
#include "libc/stdio/temp.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
#define RESEED 1024
|
||||
#define ATTEMPTS 10
|
||||
#define WILDCARD "XXXXXX"
|
||||
|
||||
int mkostempsmi(char *tpl, int slen, unsigned flags, uint64_t *rando, int mode,
|
||||
int openit(const char *file, int flags, ...)) {
|
||||
size_t len = strlen(tpl);
|
||||
size_t wildlen = strlen(WILDCARD);
|
||||
if (len < wildlen || slen > len - wildlen) return einval();
|
||||
char *ss = tpl + len - wildlen - slen;
|
||||
npassert(memcmp(ss, WILDCARD, wildlen) == 0);
|
||||
flags = (flags & ~(flags & O_ACCMODE)) | O_RDWR | O_CREAT | O_EXCL;
|
||||
unsigned attempts = ATTEMPTS;
|
||||
do {
|
||||
char *p = ss;
|
||||
uint32_t num = KnuthLinearCongruentialGenerator(rando) >> 32;
|
||||
for (unsigned i = 0; i < wildlen; ++i) {
|
||||
p[i] = "0123456789abcdefghijklmnopqrstuvwxyz"[num & 31];
|
||||
num >>= 5;
|
||||
}
|
||||
int fd;
|
||||
if ((fd = openit(tpl, flags, 0600)) != -1) return fd;
|
||||
} while (--attempts && errno == EEXIST);
|
||||
memcpy(ss, WILDCARD, wildlen);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static uint64_t g_mkostemps_rand;
|
||||
static uint64_t g_mkostemps_reseed;
|
||||
|
||||
/**
|
||||
* Opens unique temporary file.
|
||||
*
|
||||
* The substring XXXXXX is replaced with a pseudorandom number that's
|
||||
* seeded automatically and grants 30 bits of randomness to each value.
|
||||
* Retries are made in the unlikely event of collisions.
|
||||
*
|
||||
* @param template is a pathname relative to current directory by default,
|
||||
* that needs to have "XXXXXX" at the end of the string
|
||||
* @param suffixlen may be nonzero to permit characters after the XXXXXX
|
||||
* @param flags can have O_APPEND, O_CLOEXEC, etc.
|
||||
* @param mode is conventionally 0600, for owner-only non-exec access
|
||||
* @return exclusive open file descriptor for generated pathname,
|
||||
* or -1 w/ errno
|
||||
* @see kTmpPath
|
||||
*/
|
||||
int mkostempsm(char *template, int suffixlen, unsigned flags, int mode) {
|
||||
int fd;
|
||||
if (g_mkostemps_reseed++ % RESEED == 0) g_mkostemps_rand = _rand64();
|
||||
fd = mkostempsmi(template, suffixlen, flags, &g_mkostemps_rand, mode, open);
|
||||
STRACE("mkostempsm([%#s], %'d, %#x, %#o) → %d% m", template, suffixlen, flags,
|
||||
mode, fd);
|
||||
return fd;
|
||||
}
|
|
@ -17,12 +17,13 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
/**
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/stdio/posix_spawn.h"
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,10 +1,19 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_STDIO_H_
|
||||
#define COSMOPOLITAN_LIBC_STDIO_H_
|
||||
|
||||
#define EOF -1 /* end of file */
|
||||
#define WEOF -1u /* end of file (multibyte) */
|
||||
#define _IOFBF 0 /* fully buffered */
|
||||
#define _IOLBF 1 /* line buffered */
|
||||
#define _IONBF 2 /* no buffering */
|
||||
|
||||
#define L_tmpnam 20
|
||||
#define L_ctermid 20
|
||||
#define FILENAME_MAX PATH_MAX
|
||||
#define P_tmpdir "/tmp"
|
||||
#define FILENAME_MAX 1024
|
||||
#define FOPEN_MAX 1000
|
||||
#define TMP_MAX 10000
|
||||
#define BUFSIZ 4096
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
@ -51,9 +60,9 @@ int putchar(int);
|
|||
int puts(const char *);
|
||||
ssize_t getline(char **, size_t *, FILE *) paramsnonnull();
|
||||
ssize_t getdelim(char **, size_t *, int, FILE *) paramsnonnull();
|
||||
FILE *fopen(const char *, const char *) paramsnonnull((2)) dontdiscard;
|
||||
FILE *fdopen(int, const char *) paramsnonnull() dontdiscard;
|
||||
FILE *fmemopen(void *, size_t, const char *) paramsnonnull((3)) dontdiscard;
|
||||
FILE *fopen(const char *, const char *) paramsnonnull((2)) __wur;
|
||||
FILE *fdopen(int, const char *) paramsnonnull() __wur;
|
||||
FILE *fmemopen(void *, size_t, const char *) paramsnonnull((3)) __wur;
|
||||
FILE *freopen(const char *, const char *, FILE *) paramsnonnull((2, 3));
|
||||
size_t fread(void *, size_t, size_t, FILE *) paramsnonnull((4));
|
||||
size_t fwrite(const void *, size_t, size_t, FILE *) paramsnonnull((4));
|
||||
|
@ -77,6 +86,9 @@ char *gets(char *) paramsnonnull();
|
|||
int fgetpos(FILE *, fpos_t *) paramsnonnull();
|
||||
int fsetpos(FILE *, const fpos_t *) paramsnonnull();
|
||||
|
||||
FILE *tmpfile(void) __wur;
|
||||
char *tmpnam(char *) __wur;
|
||||
char *tmpnam_r(char *) __wur;
|
||||
int system(const char *);
|
||||
FILE *popen(const char *, const char *);
|
||||
|
||||
|
|
|
@ -20,6 +20,9 @@ int __fsetlocking(FILE *, int);
|
|||
void _flushlbf(void);
|
||||
void __fpurge(FILE *);
|
||||
void __fseterr(FILE *);
|
||||
const char *__freadptr(FILE *, size_t *);
|
||||
size_t __freadahead(FILE *);
|
||||
void __freadptrinc(FILE *, size_t);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_STDIO_TEMP_H_
|
||||
#define COSMOPOLITAN_LIBC_STDIO_TEMP_H_
|
||||
#include "libc/stdio/stdio.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
FILE *tmpfile(void);
|
||||
char *mkdtemp(char *);
|
||||
char *mktemp(char *);
|
||||
char *tmpnam(char *);
|
||||
int mkostemp(char *, unsigned);
|
||||
int mkostemps(char *, int, unsigned);
|
||||
int mkostempsm(char *, int, unsigned, int);
|
||||
int mkstemp(char *);
|
||||
int mkstemps(char *, int);
|
||||
|
||||
int mkostempsmi(char *, int, unsigned, uint64_t *, int,
|
||||
int (*)(const char *, int, ...)) dontdiscard;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_STDIO_TEMP_H_ */
|
|
@ -18,7 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/stdio/temp.h"
|
||||
#include "libc/temp.h"
|
||||
|
||||
/**
|
||||
* Opens stream backed by anonymous file, e.g.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
|
@ -17,48 +17,36 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/stdio/rand.h"
|
||||
#include "libc/stdio/temp.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static char g_tmpnam[L_tmpnam];
|
||||
|
||||
/**
|
||||
* Creates temporary directory, e.g.
|
||||
* Generates temporary file name.
|
||||
*
|
||||
* char path[PATH_MAX];
|
||||
* snprintf(path, sizeof(path), "%s%s.XXXXXX",
|
||||
* kTmpPath, program_invocation_short_name);
|
||||
* printf("%s\n", mkdtemp(path));
|
||||
* rmdir(path);
|
||||
*
|
||||
* @param template must end with XXXXXX which is replaced with
|
||||
* nondeterministic base36 random data
|
||||
* @return pointer to template on success, or NULL w/ errno
|
||||
* @raise EINVAL if template didn't end with XXXXXX
|
||||
* @param buf may be null to generate `/tmp/tmpnam_XXXXXX` to a static
|
||||
* buffer (it works on Windows) that is not thread safe; otherwise
|
||||
* the caller must supply a buffer with `L_tmpnam` bytes available
|
||||
* @return unique generated filename, or null on failure; `buf` memory
|
||||
* is only mutated on success
|
||||
*/
|
||||
char *mkdtemp(char *template) {
|
||||
unsigned x;
|
||||
int i, j, n;
|
||||
if ((n = strlen(template)) >= 6 && !memcmp(template + n - 6, "XXXXXX", 6)) {
|
||||
for (i = 0; i < 10; ++i) {
|
||||
x = _rand64();
|
||||
for (j = 0; j < 6; ++j) {
|
||||
template[n - 6 + j] = "0123456789abcdefghijklmnopqrstuvwxyz"[x % 36];
|
||||
x /= 36;
|
||||
}
|
||||
if (!mkdir(template, 0700)) {
|
||||
return template;
|
||||
}
|
||||
if (errno != EEXIST) {
|
||||
break;
|
||||
}
|
||||
char *tmpnam(char *buf) {
|
||||
if (IsAsan()) __asan_verify(buf, L_tmpnam);
|
||||
char path[] = P_tmpdir "/tmpnam_XXXXXX";
|
||||
for (int t = 0; t < 100; ++t) {
|
||||
int w = _rand64();
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
path[sizeof(path) - 1 - 6 + i] =
|
||||
"0123456789abcdefghikmnpqrstvwxyz"[w & 31];
|
||||
w >>= 5;
|
||||
}
|
||||
for (j = 0; j < 6; ++j) {
|
||||
template[n - 6 + j] = 'X';
|
||||
if (!fileexists(path)) {
|
||||
return strcpy(buf ? buf : g_tmpnam, path);
|
||||
}
|
||||
} else {
|
||||
einval();
|
||||
}
|
||||
return 0;
|
||||
}
|
39
libc/stdio/tmpnam_r.c
Normal file
39
libc/stdio/tmpnam_r.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Generates temporary file name, reentrantly.
|
||||
*
|
||||
* This function is the same as tmpnam() except `buf` can't be NULL.
|
||||
*
|
||||
* @param buf must have `L_tmpnam` bytes available
|
||||
* @return pointer to `buf` which is populated with a unique generated
|
||||
* filename, or null w/ errno on failure; buffer content will only
|
||||
* be mutated on success
|
||||
*/
|
||||
char *tmpnam_r(char *buf) {
|
||||
if (buf) {
|
||||
return tmpnam(buf);
|
||||
} else {
|
||||
einval();
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/fmt/conv.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue