LibC: Implement/fix mk{,o}stemp{,s}
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user