The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/openzfs/lib/libspl/mkdirp.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * CDDL HEADER START
    3  *
    4  * The contents of this file are subject to the terms of the
    5  * Common Development and Distribution License (the "License").
    6  * You may not use this file except in compliance with the License.
    7  *
    8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
    9  * or https://opensource.org/licenses/CDDL-1.0.
   10  * See the License for the specific language governing permissions
   11  * and limitations under the License.
   12  *
   13  * When distributing Covered Code, include this CDDL HEADER in each
   14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
   15  * If applicable, add the following below this CDDL HEADER, with the
   16  * fields enclosed by brackets "[]" replaced with your own identifying
   17  * information: Portions Copyright [yyyy] [name of copyright owner]
   18  *
   19  * CDDL HEADER END
   20  */
   21 
   22 /*
   23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
   24  * Use is subject to license terms.
   25  */
   26 
   27 /*      Copyright (c) 1988 AT&T */
   28 /*        All Rights Reserved   */
   29 
   30 /*
   31  * Creates directory and it's parents if the parents do not
   32  * exist yet.
   33  *
   34  * Returns -1 if fails for reasons other than non-existing
   35  * parents.
   36  * Does NOT simplify pathnames with . or .. in them.
   37  */
   38 
   39 #include <sys/types.h>
   40 #include <libgen.h>
   41 #include <stdlib.h>
   42 #include <unistd.h>
   43 #include <errno.h>
   44 #include <string.h>
   45 #include <sys/stat.h>
   46 
   47 static char *simplify(const char *str);
   48 
   49 int
   50 mkdirp(const char *d, mode_t mode)
   51 {
   52         char  *endptr, *ptr, *slash, *str;
   53 
   54         str = simplify(d);
   55 
   56         /* If space couldn't be allocated for the simplified names, return. */
   57 
   58         if (str == NULL)
   59                 return (-1);
   60 
   61                 /* Try to make the directory */
   62 
   63         if (mkdir(str, mode) == 0) {
   64                 free(str);
   65                 return (0);
   66         }
   67         if (errno != ENOENT) {
   68                 free(str);
   69                 return (-1);
   70         }
   71         endptr = strrchr(str, '\0');
   72         slash = strrchr(str, '/');
   73 
   74                 /* Search upward for the non-existing parent */
   75 
   76         while (slash != NULL) {
   77 
   78                 ptr = slash;
   79                 *ptr = '\0';
   80 
   81                         /* If reached an existing parent, break */
   82 
   83                 if (access(str, F_OK) == 0)
   84                         break;
   85 
   86                         /* If non-existing parent */
   87 
   88                 else {
   89                         slash = strrchr(str, '/');
   90 
   91                                 /* If under / or current directory, make it. */
   92 
   93                         if (slash == NULL || slash == str) {
   94                                 if (mkdir(str, mode) != 0 && errno != EEXIST) {
   95                                         free(str);
   96                                         return (-1);
   97                                 }
   98                                 break;
   99                         }
  100                 }
  101         }
  102 
  103         /* Create directories starting from upmost non-existing parent */
  104 
  105         while ((ptr = strchr(str, '\0')) != endptr) {
  106                 *ptr = '/';
  107                 if (mkdir(str, mode) != 0 && errno != EEXIST) {
  108                         /*
  109                          *  If the mkdir fails because str already
  110                          *  exists (EEXIST), then str has the form
  111                          *  "existing-dir/..", and this is really
  112                          *  ok. (Remember, this loop is creating the
  113                          *  portion of the path that didn't exist)
  114                          */
  115                         free(str);
  116                         return (-1);
  117                 }
  118         }
  119         free(str);
  120         return (0);
  121 }
  122 
  123 /*
  124  *      simplify - given a pathname, simplify that path by removing
  125  *                 duplicate contiguous slashes.
  126  *
  127  *                 A simplified copy of the argument is returned to the
  128  *                 caller, or NULL is returned on error.
  129  *
  130  *                 The caller should handle error reporting based upon the
  131  *                 returned value, and should free the returned value,
  132  *                 when appropriate.
  133  */
  134 
  135 static char *
  136 simplify(const char *str)
  137 {
  138         int i;
  139         size_t mbPathlen;       /* length of multi-byte path */
  140         size_t wcPathlen;       /* length of wide-character path */
  141         wchar_t *wptr;          /* scratch pointer */
  142         wchar_t *wcPath;        /* wide-character version of the path */
  143         char *mbPath;           /* The copy fo the path to be returned */
  144 
  145         /*
  146          *  bail out if there is nothing there.
  147          */
  148 
  149         if (!str) {
  150                 errno = ENOENT;
  151                 return (NULL);
  152         }
  153 
  154         /*
  155          *  Get a copy of the argument.
  156          */
  157 
  158         if ((mbPath = strdup(str)) == NULL) {
  159                 return (NULL);
  160         }
  161 
  162         /*
  163          *  convert the multi-byte version of the path to a
  164          *  wide-character rendering, for doing our figuring.
  165          */
  166 
  167         mbPathlen = strlen(mbPath);
  168 
  169         if ((wcPath = calloc(mbPathlen+1, sizeof (wchar_t))) == NULL) {
  170                 free(mbPath);
  171                 return (NULL);
  172         }
  173 
  174         if ((wcPathlen = mbstowcs(wcPath, mbPath, mbPathlen)) == (size_t)-1) {
  175                 free(mbPath);
  176                 free(wcPath);
  177                 return (NULL);
  178         }
  179 
  180         /*
  181          *  remove duplicate slashes first ("//../" -> "/")
  182          */
  183 
  184         for (wptr = wcPath, i = 0; i < wcPathlen; i++) {
  185                 *wptr++ = wcPath[i];
  186 
  187                 if (wcPath[i] == '/') {
  188                         i++;
  189 
  190                         while (wcPath[i] == '/') {
  191                                 i++;
  192                         }
  193 
  194                         i--;
  195                 }
  196         }
  197 
  198         *wptr = '\0';
  199 
  200         /*
  201          *  now convert back to the multi-byte format.
  202          */
  203 
  204         if (wcstombs(mbPath, wcPath, mbPathlen) == (size_t)-1) {
  205                 free(mbPath);
  206                 free(wcPath);
  207                 return (NULL);
  208         }
  209 
  210         free(wcPath);
  211         return (mbPath);
  212 }

Cache object: 4d381dbc6a83f70e7acc06e7c3c890ed


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.