libc: Add mkdtemp() and mkstemp()
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
No mktemp() though, as it has race conditions and was removed in POSIX.1-2008.
This commit is contained in:
parent
a0b45a51de
commit
1215c38d75
@ -131,6 +131,12 @@ extern "C"
|
||||
/* Convert a wide character string to a multibyte character string. */
|
||||
size_t wcstombs(char* buf, const wchar_t* src, size_t max);
|
||||
|
||||
/* Create a unique directory from a template string whose last 6 bytes must be XXXXXX. */
|
||||
char* mkdtemp(char* _template);
|
||||
|
||||
/* Create a unique file from a template string whose last 6 bytes must be XXXXXX. */
|
||||
int mkstemp(char* _template);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1,10 +1,13 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <luna/Heap.h>
|
||||
#include <luna/NumberParsing.h>
|
||||
#include <luna/Sort.h>
|
||||
#include <luna/Utf8.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
@ -218,4 +221,66 @@ extern "C"
|
||||
{
|
||||
next = seed;
|
||||
}
|
||||
|
||||
static void generate_random_character(char* ptr)
|
||||
{
|
||||
constexpr const char chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
|
||||
*ptr = chars[rand() % sizeof(chars)];
|
||||
}
|
||||
|
||||
static int check_template(char* _template, size_t* len)
|
||||
{
|
||||
*len = strlen(_template);
|
||||
if (*len < 6)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strncmp(_template + (*len - 6), "XXXXXX", 6))
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void generate_random_name(char* _template, const size_t* len)
|
||||
{
|
||||
size_t index = *len - 6;
|
||||
while (index < *len) generate_random_character(&_template[index++]);
|
||||
}
|
||||
|
||||
char* mkdtemp(char* _template)
|
||||
{
|
||||
size_t len;
|
||||
if (check_template(_template, &len) < 0) return nullptr;
|
||||
|
||||
while (true)
|
||||
{
|
||||
generate_random_name(_template, &len);
|
||||
|
||||
if (mkdir(_template, 0700) == 0) return _template;
|
||||
|
||||
if (errno != EEXIST) return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
int mkstemp(char* _template)
|
||||
{
|
||||
size_t len;
|
||||
if (check_template(_template, &len) < 0) return -1;
|
||||
|
||||
while (true)
|
||||
{
|
||||
generate_random_name(_template, &len);
|
||||
|
||||
int fd;
|
||||
|
||||
if ((fd = open(_template, O_RDWR | O_CREAT | O_EXCL, 0600)) >= 0) return fd;
|
||||
|
||||
if (errno != EEXIST) return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user