sbase/libutil/mkdirp.c
Michael Forney 529e50a7ad mkdir: Fix created directory permissions
Previously, with -p, the specified directory and all of its parents
would be 0777&~filemask (regardless of the -m flag). POSIX says parent
directories must created as (0300|~filemask)&0777, and of course if -m
is set, the specified directory should be created with those
permissions.

Additionally, POSIX says that for symbolic_mode strings, + and - should
be interpretted relative to a default mode of 0777 (not 0).

Without -p, previously the directory would be created first with
0777&~filemask (before a chmod), but POSIX says that the directory shall
at no point in time have permissions less restrictive than the -m mode
argument.

Rather than dealing with mkdir removing the filemask bits by calling
chmod afterward, just clear the umask and remove the bits manually.
2017-07-03 21:03:11 +02:00

40 lines
717 B
C

/* See LICENSE file for copyright and license details. */
#include <sys/stat.h>
#include <errno.h>
#include <limits.h>
#include "../util.h"
int
mkdirp(const char *path, mode_t mode, mode_t pmode)
{
char tmp[PATH_MAX], *p;
struct stat st;
if (stat(path, &st) == 0) {
if (S_ISDIR(st.st_mode))
return 0;
errno = ENOTDIR;
weprintf("%s:", path);
return -1;
}
estrlcpy(tmp, path, sizeof(tmp));
for (p = tmp + (tmp[0] == '/'); *p; p++) {
if (*p != '/')
continue;
*p = '\0';
if (mkdir(tmp, pmode) < 0 && errno != EEXIST) {
weprintf("mkdir %s:", tmp);
return -1;
}
*p = '/';
}
if (mkdir(tmp, mode) < 0 && errno != EEXIST) {
weprintf("mkdir %s:", tmp);
return -1;
}
return 0;
}