X-Git-Url: https://git.saurik.com/apple/libc.git/blobdiff_plain/15de9d6b4ab2de27ae24b13b7b6c4d55fffe4aef..974e388456677d82eb6d10d4fd72390641a5bdfe:/util/mkpath_np.c?ds=sidebyside diff --git a/util/mkpath_np.c b/util/mkpath_np.c index fb02297..b830b3f 100644 --- a/util/mkpath_np.c +++ b/util/mkpath_np.c @@ -26,19 +26,10 @@ #include #include #include +#include -/* This extended version of mkpath_np is provided to help NSFileManager - * maintain binary compatibility. If firstdir is not NULL, *firstdir will be - * set to the path of the first created directory, and it is the caller's - * responsibility to free the returned string. This SPI is subject to removal - * once NSFileManager no longer has a need for it, and use in new code is - * highly discouraged. - * - * See: - */ - -int -_mkpath_np(const char *path, mode_t omode, const char ** firstdir) +static int +_mkpath(int dfd, const char *path, mode_t omode, const char ** firstdir) { char *apath = NULL, *opath = NULL, *s, *sn, *sl; unsigned int depth = 0; @@ -48,7 +39,7 @@ _mkpath_np(const char *path, mode_t omode, const char ** firstdir) struct stat sbuf; /* Try the trivial case first. */ - if (0 == mkdir(path, omode)) { + if (0 == mkdirat(dfd, path, omode)) { if (firstdir) { *firstdir = strdup(path); } @@ -63,7 +54,7 @@ _mkpath_np(const char *path, mode_t omode, const char ** firstdir) case ENOENT: break; case EEXIST: - if (stat(path, &sbuf) == 0) { + if (fstatat(dfd, path, &sbuf, 0) == 0) { if (S_ISDIR(sbuf.st_mode)) { retval = EEXIST; } else { @@ -107,7 +98,7 @@ _mkpath_np(const char *path, mode_t omode, const char ** firstdir) } /* Retry the trivial case after having stripped of trailing /. */ - if (0 == mkdir(path, omode)) { + if (0 == mkdirat(dfd, path, omode)) { if (firstdir) { *firstdir = strdup(path); } @@ -127,7 +118,7 @@ _mkpath_np(const char *path, mode_t omode, const char ** firstdir) *s = '\0'; depth++; - if (0 == mkdir(apath, S_IRWXU | S_IRWXG | S_IRWXO)) { + if (0 == mkdirat(dfd, apath, S_IRWXU | S_IRWXG | S_IRWXO)) { /* Found our starting point */ /* POSIX 1003.2: @@ -140,7 +131,7 @@ _mkpath_np(const char *path, mode_t omode, const char ** firstdir) */ struct stat dirstat; - if (-1 == stat(apath, &dirstat)) { + if (-1 == fstatat(dfd, apath, &dirstat, 0)) { /* Really unfortunate timing ... */ retval = ENOENT; goto mkpath_exit; @@ -148,7 +139,7 @@ _mkpath_np(const char *path, mode_t omode, const char ** firstdir) if ((dirstat.st_mode & (S_IWUSR | S_IXUSR)) != (S_IWUSR | S_IXUSR)) { chmod_mode = dirstat.st_mode | S_IWUSR | S_IXUSR; - if (-1 == chmod(apath, chmod_mode)) { + if (-1 == fchmodat(dfd, apath, chmod_mode, 0)) { /* Really unfortunate timing ... */ retval = ENOENT; goto mkpath_exit; @@ -164,7 +155,7 @@ _mkpath_np(const char *path, mode_t omode, const char ** firstdir) * before we did. We will use this as our starting point. * See: */ - if (stat(apath, &sbuf) == 0 && + if (fstatat(dfd, apath, &sbuf, 0) == 0 && S_ISDIR(sbuf.st_mode)) { if (firstdir) { @@ -187,7 +178,7 @@ _mkpath_np(const char *path, mode_t omode, const char ** firstdir) *s = '/'; depth--; - if (-1 == mkdir(apath, S_IRWXU | S_IRWXG | S_IRWXO)) { + if (-1 == mkdirat(dfd, apath, S_IRWXU | S_IRWXG | S_IRWXO)) { /* This handles "." and ".." added to the new section of path */ if (errno == EEXIST) continue; @@ -196,7 +187,7 @@ _mkpath_np(const char *path, mode_t omode, const char ** firstdir) } if (chmod_mode) { - if (-1 == chmod(apath, chmod_mode)) { + if (-1 == fchmodat(dfd, apath, chmod_mode, 0)) { /* Really unfortunate timing ... */ retval = ENOENT; goto mkpath_exit; @@ -204,10 +195,10 @@ _mkpath_np(const char *path, mode_t omode, const char ** firstdir) } } - if (-1 == mkdir(path, omode)) { + if (-1 == mkdirat(dfd, path, omode)) { retval = errno; if (errno == EEXIST && - stat(path, &sbuf) == 0 && + fstatat(dfd, path, &sbuf, 0) == 0 && !S_ISDIR(sbuf.st_mode)) { retval = ENOTDIR; } @@ -221,6 +212,25 @@ mkpath_exit: return retval; } +/* This extended version of mkpath_np is provided to help NSFileManager + * maintain binary compatibility. If firstdir is not NULL, *firstdir will be + * set to the path of the first created directory, and it is the caller's + * responsibility to free the returned string. This SPI is subject to removal + * once NSFileManager no longer has a need for it, and use in new code is + * highly discouraged. + * + * See: + */ + +int +_mkpath_np(const char *path, mode_t omode, const char ** firstdir) { + return _mkpath(AT_FDCWD, path, omode, firstdir); +} + int mkpath_np(const char *path, mode_t omode) { - return _mkpath_np(path, omode, NULL); + return _mkpath(AT_FDCWD, path, omode, NULL); +} + +int mkpathat_np(int dfd, const char *path, mode_t omode) { + return _mkpath(dfd, path, omode, NULL); }