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);
int mbtowc(wchar_t* __restrict pwc, const char* __restrict s, size_t n);
char* mkdtemp(char* _template);
char* mktemp(char* _template);
int mkstemp(char* _template);
int mkostemp(char* _template, int flags);
long mrand48(void);
long nrand48(unsigned short xsubi[3]);
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);
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
#endif

View File

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