Fix race condition in makedirs()

This commit is contained in:
Justine Tunney 2022-09-07 22:52:24 -07:00
parent b7c07d548c
commit 571c2c3c69
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
7 changed files with 90 additions and 10 deletions

View file

@ -16,11 +16,11 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/intrin/safemacros.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/strace.internal.h"
#include "libc/errno.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/mem/mem.h"
#include "libc/str/str.h"
#include "libc/x/x.h"
@ -44,7 +44,12 @@ static int MakeDirs(const char *path, unsigned mode, int e) {
free(dir);
if (rc == -1) return -1;
errno = e;
return mkdir(path, mode);
if (!mkdir(path, mode) || errno == EEXIST) {
errno = e;
return 0;
} else {
return -1;
}
}
/**
@ -55,7 +60,7 @@ static int MakeDirs(const char *path, unsigned mode, int e) {
* @param path is a UTF-8 string, preferably relative w/ forward slashes
* @param mode can be, for example, 0755
* @return 0 on success or -1 w/ errno
* @see mkdir()
* @threadsafe
*/
int makedirs(const char *path, unsigned mode) {
return MakeDirs(path, mode, errno);

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/conv.h"
#include "libc/mem/mem.h"
#include "libc/runtime/gc.internal.h"
#include "libc/x/x.h"
@ -24,5 +25,9 @@
* Returns base portion of path.
*/
char *xbasename(const char *path) {
return xstrdup(basename(gc(xstrdup(path))));
char *base;
path = xstrdup(path);
base = xstrdup(basename(path));
free(path);
return base;
}

View file

@ -17,12 +17,16 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/conv.h"
#include "libc/runtime/gc.internal.h"
#include "libc/mem/mem.h"
#include "libc/x/x.h"
/**
* Returns directory portion of path.
*/
char *xdirname(const char *path) {
return xstrdup(dirname(gc(xstrdup(path))));
char *dirp;
path = xstrdup(path);
dirp = xstrdup(dirname(path));
free(path);
return dirp;
}