From 59e7dd00c57e56a5af19605732e26bd36699db94 Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Tue, 2 Jun 2015 13:33:32 +0200 Subject: [PATCH] Add mkdtemps(3). --- libc/Makefile | 1 + libc/include/stdlib.h | 1 + libc/stdlib/mkdtemp.cpp | 37 +--------------------- libc/stdlib/mkdtemps.cpp | 66 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 69 insertions(+), 36 deletions(-) create mode 100644 libc/stdlib/mkdtemps.cpp diff --git a/libc/Makefile b/libc/Makefile index 13078da9..75743d1a 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -443,6 +443,7 @@ stdlib/_Exit.o \ stdlib/exit.o \ stdlib/getenv.o \ stdlib/mkdtemp.o \ +stdlib/mkdtemps.o \ stdlib/mkostemp.o \ stdlib/mkostemps.o \ stdlib/mkstemp.o \ diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h index 038aadab..8f410c0f 100644 --- a/libc/include/stdlib.h +++ b/libc/include/stdlib.h @@ -108,6 +108,7 @@ int mblen(const char*, size_t); size_t mbstowcs(wchar_t* __restrict, const char* __restrict, size_t); int mbtowc(wchar_t *__restrict, const char* __restrict, size_t); char* mkdtemp(char*); +char* mkdtemps(char*, size_t); int mkostemp(char*, int); int mkostemps(char*, int, int); int mkstemp(char*); diff --git a/libc/stdlib/mkdtemp.cpp b/libc/stdlib/mkdtemp.cpp index 7e34d017..fca0dc94 100644 --- a/libc/stdlib/mkdtemp.cpp +++ b/libc/stdlib/mkdtemp.cpp @@ -22,44 +22,9 @@ *******************************************************************************/ -#include -#include #include -#include - -const uint32_t NUM_CHARACTERS = 10 + 26 + 26; - -static inline char random_character() -{ - uint32_t index = arc4random_uniform(NUM_CHARACTERS); - if ( index < 10 ) - return '0' + index; - if ( index < 10 + 26 ) - return 'a' + index - 10; - if ( index < 10 + 26 + 26 ) - return 'A' + index - (10 + 26); - __builtin_unreachable(); -} extern "C" char* mkdtemp(char* templ) { - size_t templ_length = strlen(templ); - if ( templ_length < 6 ) - return errno = EINVAL, (char*) NULL; - size_t xpos = templ_length - 6; - for ( size_t i = 0; i < 6; i++ ) - if ( templ[xpos + i] != 'X' ) - return errno = EINVAL, (char*) NULL; - - do - { - for ( size_t i = 0; i < 6; i++ ) - templ[xpos + i] = random_character(); - if ( mkdir(templ, 0700) == 0 ) - return templ; - } while ( errno == EEXIST ); - - memcpy(templ + xpos, "XXXXXX", 6); - - return NULL; + return mkdtemps(templ, 0); } diff --git a/libc/stdlib/mkdtemps.cpp b/libc/stdlib/mkdtemps.cpp new file mode 100644 index 00000000..0ba3bb5c --- /dev/null +++ b/libc/stdlib/mkdtemps.cpp @@ -0,0 +1,66 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013, 2014, 2015. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdlib/mkdtemps.cpp + Make a unique temporary directory path and create it. + +*******************************************************************************/ + +#include +#include +#include +#include + +const uint32_t NUM_CHARACTERS = 10 + 26 + 26; + +static inline char random_character() +{ + uint32_t index = arc4random_uniform(NUM_CHARACTERS); + if ( index < 10 ) + return '0' + index; + if ( index < 10 + 26 ) + return 'a' + index - 10; + if ( index < 10 + 26 + 26 ) + return 'A' + index - (10 + 26); + __builtin_unreachable(); +} + +extern "C" char* mkdtemps(char* templ, size_t suffixlen) +{ + size_t templ_length = strlen(templ); + if ( templ_length < 6 || + templ_length - 6 < (size_t) suffixlen ) + return errno = EINVAL, (char*) NULL; + size_t xpos = templ_length - (6 + suffixlen); + for ( size_t i = 0; i < 6; i++ ) + if ( templ[xpos + i] != 'X' ) + return errno = EINVAL, (char*) NULL; + + do + { + for ( size_t i = 0; i < 6; i++ ) + templ[xpos + i] = random_character(); + if ( mkdir(templ, 0700) == 0 ) + return templ; + } while ( errno == EEXIST ); + + memcpy(templ + xpos, "XXXXXX", 6); + + return NULL; +}