Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:15

0001 /**
0002  * @file
0003  *
0004  * @ingroup LibIO
0005  *
0006  * @brief rtems_mkdir() implementation.
0007  *
0008  * The implementation is based on FreeBSD 'bin/mkdir/mkdir.c' revision 163213.
0009  */
0010 
0011 /*-
0012  * Copyright (c) 2010 embedded brains GmbH & Co. KG
0013  *
0014  * Copyright (c) 1983, 1992, 1993
0015  *  The Regents of the University of California.  All rights reserved.
0016  *
0017  * Redistribution and use in source and binary forms, with or without
0018  * modification, are permitted provided that the following conditions
0019  * are met:
0020  * 1. Redistributions of source code must retain the above copyright
0021  *    notice, this list of conditions and the following disclaimer.
0022  * 2. Redistributions in binary form must reproduce the above copyright
0023  *    notice, this list of conditions and the following disclaimer in the
0024  *    documentation and/or other materials provided with the distribution.
0025  * 4. Neither the name of the University nor the names of its contributors
0026  *    may be used to endorse or promote products derived from this software
0027  *    without specific prior written permission.
0028  *
0029  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
0030  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0031  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0032  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
0033  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0034  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
0035  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
0036  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
0037  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
0038  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0039  * SUCH DAMAGE.
0040  */
0041 
0042 #ifdef HAVE_CONFIG_H
0043 #include "config.h"
0044 #endif
0045 
0046 #include <sys/types.h>
0047 #include <sys/stat.h>
0048 
0049 #include <errno.h>
0050 #include <stdlib.h>
0051 #include <string.h>
0052 #include <unistd.h>
0053 
0054 #include <rtems/libio.h>
0055 
0056 /*
0057  * Returns 1 if a directory has been created,
0058  * 2 if it already existed, and 0 on failure.
0059  */
0060 static int
0061 build(char *path, mode_t omode)
0062 {
0063   struct stat sb;
0064   mode_t numask, oumask;
0065   int first, last, retval;
0066   char *p;
0067 
0068   p = path;
0069   oumask = 0;
0070   retval = 1;
0071   if (p[0] == '/')    /* Skip leading '/'. */
0072     ++p;
0073   for (first = 1, last = 0; !last ; ++p) {
0074     if (p[0] == '\0')
0075       last = 1;
0076     else if (p[0] != '/')
0077       continue;
0078     *p = '\0';
0079     if (!last && p[1] == '\0')
0080       last = 1;
0081     if (first) {
0082       /*
0083        * POSIX 1003.2:
0084        * For each dir operand that does not name an existing
0085        * directory, effects equivalent to those caused by the
0086        * following command shall occcur:
0087        *
0088        * mkdir -p -m $(umask -S),u+wx $(dirname dir) &&
0089        *    mkdir [-m mode] dir
0090        *
0091        * We change the user's umask and then restore it,
0092        * instead of doing chmod's.
0093        */
0094       oumask = umask(0);
0095       numask = oumask & ~(S_IWUSR | S_IXUSR);
0096       (void)umask(numask);
0097       first = 0;
0098     }
0099     if (last)
0100       (void)umask(oumask);
0101     if (mkdir(path, last ? omode : S_IRWXU | S_IRWXG | S_IRWXO) < 0) {
0102       if (errno == EEXIST || errno == EISDIR) {
0103         if (stat(path, &sb) < 0) {
0104           retval = 0;
0105           break;
0106         } else if (!S_ISDIR(sb.st_mode)) {
0107           if (last)
0108             errno = EEXIST;
0109           else
0110             errno = ENOTDIR;
0111           retval = 0;
0112           break;
0113         }
0114         if (last)
0115           retval = 2;
0116       } else {
0117         retval = 0;
0118         break;
0119       }
0120     }
0121     if (!last)
0122         *p = '/';
0123   }
0124   if (!first && !last)
0125     (void)umask(oumask);
0126   return (retval);
0127 }
0128 
0129 int
0130 rtems_mkdir(const char *path, mode_t mode)
0131 {
0132   int success = 0;
0133   char *dup_path = strdup(path);
0134 
0135   if (dup_path != NULL) {
0136     success = build(dup_path, mode);
0137     free(dup_path);
0138   }
0139 
0140   return success != 0 ? 0 : -1;
0141 }