LibC: Implement/fix mk{,o}stemp{,s}

This commit is contained in:
2026-05-22 22:21:54 +03:00
parent fe533c2e62
commit 9ccdebcd96
2 changed files with 56 additions and 28 deletions

View File

@@ -75,8 +75,8 @@ int mblen(const char* s, size_t n);
size_t mbstowcs(wchar_t* __restrict pwcs, const char* __restrict s, size_t n); size_t mbstowcs(wchar_t* __restrict pwcs, const char* __restrict s, size_t n);
int mbtowc(wchar_t* __restrict pwc, const char* __restrict s, size_t n); int mbtowc(wchar_t* __restrict pwc, const char* __restrict s, size_t n);
char* mkdtemp(char* _template); char* mkdtemp(char* _template);
char* mktemp(char* _template);
int mkstemp(char* _template); int mkstemp(char* _template);
int mkostemp(char* _template, int flags);
long mrand48(void); long mrand48(void);
long nrand48(unsigned short xsubi[3]); long nrand48(unsigned short xsubi[3]);
int posix_memalign(void** memptr, size_t alignment, size_t size); int posix_memalign(void** memptr, size_t alignment, size_t size);
@@ -109,6 +109,10 @@ int unsetenv(const char* name);
size_t wcstombs(char* __restrict s, const wchar_t* __restrict pwcs, size_t n); size_t wcstombs(char* __restrict s, const wchar_t* __restrict pwcs, size_t n);
int wctomb(char* s, wchar_t wchar); int wctomb(char* s, wchar_t wchar);
char* mktemp(char* _template);
int mkstemps(char* _template, int suffixlen);
int mkostemps(char* _template, int suffixlen, int flags);
__END_DECLS __END_DECLS
#endif #endif

View File

@@ -475,31 +475,36 @@ int system(const char* command)
return stat_val; return stat_val;
} }
static size_t temp_template_count_x(const char* _template) static void randomize_temp(char* buffer)
{ {
const size_t len = strlen(_template); // FIXME: don't use rand()
for (size_t i = 0; i < len; i++) const uint32_t value = rand() & 0xFFFFFF;
if (_template[len - i - 1] != 'X') sprintf(buffer, "%06x", value);
return i;
return len;
} }
static void generate_temp_template(char* _template, size_t x_count) static char* validate_temp_template(char* _template, int suffixlen)
{ {
const size_t len = strlen(_template); const size_t length = strlen(_template);
for (size_t i = 0; i < x_count; i++) if (suffixlen < 0 || length < static_cast<size_t>(suffixlen + 6))
{ {
const uint8_t nibble = rand() & 0xF; errno = EINVAL;
_template[len - i - 1] = (nibble < 10) return nullptr;
? ('0' + nibble)
: ('a' + nibble - 10);
} }
char* xptr = _template + length - suffixlen - 6;
if (memcmp(xptr, "XXXXXX", 6) != 0)
{
errno = EINVAL;
return nullptr;
}
return xptr;
} }
char* mktemp(char* _template) char* mktemp(char* _template)
{ {
const size_t x_count = temp_template_count_x(_template); char* xptr = validate_temp_template(_template, 0);
if (x_count < 6) if (xptr == nullptr)
{ {
errno = EINVAL; errno = EINVAL;
_template[0] = '\0'; _template[0] = '\0';
@@ -508,18 +513,22 @@ char* mktemp(char* _template)
for (;;) for (;;)
{ {
generate_temp_template(_template, x_count); randomize_temp(xptr);
struct stat st; struct stat st;
if (stat(_template, &st) == 0) if (stat(_template, &st) == -1)
{
if (errno != ENOENT)
_template[0] = '\0';
return _template; return _template;
}
} }
} }
char* mkdtemp(char* _template) char* mkdtemp(char* _template)
{ {
const size_t x_count = temp_template_count_x(_template); char* xptr = validate_temp_template(_template, 0);
if (x_count < 6) if (xptr == nullptr)
{ {
errno = EINVAL; errno = EINVAL;
return nullptr; return nullptr;
@@ -527,8 +536,7 @@ char* mkdtemp(char* _template)
for (;;) for (;;)
{ {
generate_temp_template(_template, x_count); randomize_temp(xptr);
if (mkdir(_template, S_IRUSR | S_IWUSR | S_IXUSR) != -1) if (mkdir(_template, S_IRUSR | S_IWUSR | S_IXUSR) != -1)
return _template; return _template;
if (errno != EEXIST) if (errno != EEXIST)
@@ -538,8 +546,26 @@ char* mkdtemp(char* _template)
int mkstemp(char* _template) int mkstemp(char* _template)
{ {
const size_t x_count = temp_template_count_x(_template); return mkostemps(_template, 0, 0);
if (x_count < 6) }
int mkostemp(char* _template, int flags)
{
return mkostemps(_template, 0, flags);
}
int mkstemps(char* _template, int suffixlen)
{
return mkostemps(_template, suffixlen, 0);
}
int mkostemps(char* _template, int suffixlen, int flags)
{
flags &= O_APPEND | O_CLOEXEC | O_SYNC;
flags |= O_RDWR | O_CREAT | O_EXCL;
char* xptr = validate_temp_template(_template, suffixlen);
if (xptr == nullptr)
{ {
errno = EINVAL; errno = EINVAL;
return -1; return -1;
@@ -547,10 +573,8 @@ int mkstemp(char* _template)
for (;;) for (;;)
{ {
generate_temp_template(_template, x_count); randomize_temp(xptr);
if (int fd = open(_template, flags, 0600); fd != -1)
int fd = open(_template, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
if (fd != -1)
return fd; return fd;
if (errno != EEXIST) if (errno != EEXIST)
return -1; return -1;