Loading...
util/mkpath_np.c Libc-1725.40.4 /dev/null
--- Libc/Libc-1725.40.4/util/mkpath_np.c
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Copyright (c) 2011 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-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;
-	mode_t chmod_mode = 0;
-	int retval = 0;
-	int old_errno = errno;
-	struct stat sbuf;
-
-	/* Try the trivial case first. */
-	if (0 == mkdirat(dfd, path, omode)) {
-		if (firstdir) {
-			*firstdir = strdup(path);
-		}
-		goto mkpath_exit;
-	}
-
-	/* Anything other than an ENOENT, EEXIST, or EISDIR indicates an
-	 * error that we need to send back to the caller.  ENOENT indicates
-	 * that we need to try a lower level.
-	 */
-	switch (errno) {
-		case ENOENT:
-			break;
-		case EEXIST:
-			if (fstatat(dfd, path, &sbuf, 0) == 0) {
-			    if (S_ISDIR(sbuf.st_mode)) {
-					retval = EEXIST;
-				} else {
-					retval = ENOTDIR;
-				}
-			} else {
-				retval = EIO;
-			}
-			goto mkpath_exit;
-		case EISDIR: /* <rdar://problem/10288022> */
-			retval = EEXIST;
-			goto mkpath_exit;
-		default:
-			retval = errno;
-			goto mkpath_exit;
-	}
-
-	apath = strdup(path);
-	if (apath == NULL) {
-		retval = ENOMEM;
-		goto mkpath_exit;
-	}
-
-	sl = s = apath + strlen(apath) - 1;
-	do {
-		sn = s;
-		/* Strip off trailing /., see <rdar://problem/14351794> */
-		if (s - 1 > apath && *s == '.' && *(s - 1) == '/')
-			s -= 2;
-		/* Strip off trailing /, see <rdar://problem/11592386> */
-		if (s > apath && *s == '/')
-			s--;
-	} while (s < sn);
-	if (s < sl) {
-		s[1] = '\0';
-		path = opath = strdup(apath);
-		if (opath == NULL) {
-			retval = ENOMEM;
-			goto mkpath_exit;
-		}
-	}
-
-	/* Retry the trivial case after having stripped of trailing /. <rdar://problem/14351794> */
-	if (0 == mkdirat(dfd, path, omode)) {
-		if (firstdir) {
-			*firstdir = strdup(path);
-		}
-		goto mkpath_exit;
-	}
-
-	while (1) {
-		/* Increase our depth and try making that directory */
-		s = strrchr(apath, '/');
-		if (!s) {
-			/* We should never hit this under normal circumstances,
-			 * but it can occur due to really unfortunate timing
-			 */
-			retval = ENOENT;
-			goto mkpath_exit;
-		}
-		*s = '\0';
-		depth++;
-
-		if (0 == mkdirat(dfd, apath, S_IRWXU | S_IRWXG | S_IRWXO)) {
-			/* Found our starting point */
-
-			/* POSIX 1003.2:
-			 * For each dir operand that does not name an existing
-			 * directory, effects equivalent to those cased by the
-			 * following command shall occcur:
-			 *
-			 * mkdir -p -m $(umask -S),u+wx $(dirname dir) &&
-			 *    mkdir [-m mode] dir
-			 */
-
-			struct stat dirstat;
-			if (-1 == fstatat(dfd, apath, &dirstat, 0)) {
-				/* Really unfortunate timing ... */
-				retval = ENOENT;
-				goto mkpath_exit;
-			}
-
-			if ((dirstat.st_mode & (S_IWUSR | S_IXUSR)) != (S_IWUSR | S_IXUSR)) {
-			        chmod_mode = dirstat.st_mode | S_IWUSR | S_IXUSR;
-				if (-1 == fchmodat(dfd, apath, chmod_mode, 0)) {
-					/* Really unfortunate timing ... */
-					retval = ENOENT;
-					goto mkpath_exit;
-				}
-			}
-
-			if (firstdir) {
-				*firstdir = strdup(apath);
-			}
-			break;
-		} else if (errno == EEXIST) {
-			/* Some other process won the race in creating this directory
-			 * before we did.  We will use this as our starting point.
-			 * See: <rdar://problem/10279893>
-			 */
-			if (fstatat(dfd, apath, &sbuf, 0) == 0 &&
-			    S_ISDIR(sbuf.st_mode)) {
-
-				if (firstdir) {
-					*firstdir = strdup(apath);
-				}
-				break;
-			}
-
-			retval = ENOTDIR;
-			goto mkpath_exit;
-		} else if (errno != ENOENT) {
-			retval = errno;
-			goto mkpath_exit;
-		}
-	}
-
-	while (depth > 1) {
-		/* Decrease our depth and make that directory */
-		s = strrchr(apath, '\0');
-		*s = '/';
-		depth--;
-
-		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;
-			retval = errno;
-			goto mkpath_exit;
-		}
-
-		if (chmod_mode) {
-			if (-1 == fchmodat(dfd, apath, chmod_mode, 0)) {
-				/* Really unfortunate timing ... */
-				retval = ENOENT;
-				goto mkpath_exit;
-			}
-		}
-	}
-
-	if (-1 == mkdirat(dfd, path, omode)) {
-		retval = errno;
-		if (errno == EEXIST &&
-		    fstatat(dfd, path, &sbuf, 0) == 0 &&
-		    !S_ISDIR(sbuf.st_mode)) {
-			retval = ENOTDIR;
-		}
-	}
-
-mkpath_exit:
-	free(apath);
-	free(opath);
-
-	errno = old_errno;
-	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: <rdar://problem/9888987>
- */
-
-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(AT_FDCWD, path, omode, NULL);
-}
-
-int mkpathat_np(int dfd, const char *path, mode_t omode) {
-	return _mkpath(dfd, path, omode, NULL);
-}