1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2025-03-08 20:58:20 +03:00

mkdir: Add mkdirat_parents()

This commit is contained in:
Daan De Meyer 2022-09-26 11:19:03 +02:00
parent 8df60ed768
commit 92dae2bd23
4 changed files with 48 additions and 27 deletions

View File

@ -92,46 +92,39 @@ int mkdirat_safe(int dir_fd, const char *path, mode_t mode, uid_t uid, gid_t gid
return mkdirat_safe_internal(dir_fd, path, mode, uid, gid, flags, mkdirat_errno_wrapper);
}
int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdirat) {
const char *p, *e = NULL;
int mkdirat_parents_internal(int dir_fd, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdirat) {
const char *e = NULL;
int r;
assert(path);
assert(_mkdirat != mkdirat);
if (prefix) {
p = path_startswith_full(path, prefix, /* accept_dot_dot= */ false);
if (!p)
return -ENOTDIR;
} else
p = path;
if (isempty(p))
if (isempty(path))
return 0;
if (!path_is_safe(p))
if (!path_is_safe(path))
return -ENOTDIR;
/* return immediately if directory exists */
r = path_find_last_component(p, /* accept_dot_dot= */ false, &e, NULL);
r = path_find_last_component(path, /* accept_dot_dot= */ false, &e, NULL);
if (r <= 0) /* r == 0 means path is equivalent to prefix. */
return r;
if (e == p)
if (e == path)
return 0;
assert(e > p);
assert(e > path);
assert(*e == '/');
/* drop the last component */
path = strndupa_safe(path, e - path);
r = is_dir(path, true);
r = is_dir_full(dir_fd, path, true);
if (r > 0)
return 0;
if (r == 0)
return -ENOTDIR;
/* create every parent directory in the path, except the last component */
for (p = path;;) {
for (const char *p = path;;) {
char *s;
int n;
@ -145,18 +138,39 @@ int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, ui
s[n] = '\0';
if (!prefix || !path_startswith_full(prefix, path, /* accept_dot_dot= */ false)) {
r = mkdir_safe_internal(path, mode, uid, gid, flags | MKDIR_IGNORE_EXISTING, _mkdirat);
if (r < 0 && r != -EEXIST)
return r;
}
r = mkdirat_safe_internal(dir_fd, path, mode, uid, gid, flags | MKDIR_IGNORE_EXISTING, _mkdirat);
if (r < 0 && r != -EEXIST)
return r;
s[n] = *p == '\0' ? '\0' : '/';
}
}
int mkdir_parents(const char *path, mode_t mode) {
return mkdir_parents_internal(NULL, path, mode, UID_INVALID, UID_INVALID, 0, mkdirat_errno_wrapper);
int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdirat) {
_cleanup_close_ int fd = AT_FDCWD;
const char *p;
assert(path);
assert(_mkdirat != mkdirat);
if (prefix) {
p = path_startswith_full(path, prefix, /* accept_dot_dot= */ false);
if (!p)
return -ENOTDIR;
} else
p = path;
if (prefix) {
fd = open(prefix, O_PATH|O_DIRECTORY|O_CLOEXEC);
if (fd < 0)
return -errno;
}
return mkdirat_parents_internal(fd, p, mode, uid, gid, flags, _mkdirat);
}
int mkdirat_parents(int dir_fd, const char *path, mode_t mode) {
return mkdirat_parents_internal(dir_fd, path, mode, UID_INVALID, UID_INVALID, 0, mkdirat_errno_wrapper);
}
int mkdir_parents_safe(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags) {

View File

@ -16,7 +16,10 @@ int mkdirat_safe(int dir_fd, const char *path, mode_t mode, uid_t uid, gid_t gid
static inline int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags) {
return mkdirat_safe(AT_FDCWD, path, mode, uid, gid, flags);
}
int mkdir_parents(const char *path, mode_t mode);
int mkdirat_parents(int dir_fd, const char *path, mode_t mode);
static inline int mkdir_parents(const char *path, mode_t mode) {
return mkdirat_parents(AT_FDCWD, path, mode);
}
int mkdir_parents_safe(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags);
int mkdir_p(const char *path, mode_t mode);
int mkdir_p_safe(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags);
@ -28,5 +31,6 @@ int mkdirat_safe_internal(int dir_fd, const char *path, mode_t mode, uid_t uid,
static inline int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdir) {
return mkdirat_safe_internal(AT_FDCWD, path, mode, uid, gid, flags, _mkdir);
}
int mkdirat_parents_internal(int dir_fd, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdirat);
int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdir);
int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdir);

View File

@ -29,8 +29,8 @@ int mkdirat_safe_label(int dir_fd, const char *path, mode_t mode, uid_t uid, gid
return mkdirat_safe_internal(dir_fd, path, mode, uid, gid, flags, mkdirat_label);
}
int mkdir_parents_label(const char *path, mode_t mode) {
return mkdir_parents_internal(NULL, path, mode, UID_INVALID, UID_INVALID, 0, mkdirat_label);
int mkdirat_parents_label(int dir_fd, const char *path, mode_t mode) {
return mkdirat_parents_internal(dir_fd, path, mode, UID_INVALID, UID_INVALID, 0, mkdirat_label);
}
int mkdir_p_label(const char *path, mode_t mode) {

View File

@ -16,5 +16,8 @@ int mkdirat_safe_label(int dir_fd, const char *path, mode_t mode, uid_t uid, gid
static inline int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags) {
return mkdirat_safe_label(AT_FDCWD, path, mode, uid, gid, flags);
}
int mkdir_parents_label(const char *path, mode_t mod);
int mkdirat_parents_label(int dir_fd, const char *path, mode_t mod);
static inline int mkdir_parents_label(const char *path, mode_t mod) {
return mkdirat_parents_label(AT_FDCWD, path, mod);
}
int mkdir_p_label(const char *path, mode_t mode);