LCOV - differential code coverage report
Current view: top level - src/port - pgmkdirp.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage HEAD vs 15 Lines: 75.0 % 32 24 8 24
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 1 1 1
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (240..) days: 75.0 % 32 24 8 24
Legend: Lines: hit not hit Function coverage date bins:
(240..) days: 100.0 % 1 1 1

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*
                                  2                 :  * This is adapted from FreeBSD's src/bin/mkdir/mkdir.c, which bears
                                  3                 :  * the following copyright notice:
                                  4                 :  *
                                  5                 :  * Copyright (c) 1983, 1992, 1993
                                  6                 :  *  The Regents of the University of California.  All rights reserved.
                                  7                 :  *
                                  8                 :  * Redistribution and use in source and binary forms, with or without
                                  9                 :  * modification, are permitted provided that the following conditions
                                 10                 :  * are met:
                                 11                 :  * 1. Redistributions of source code must retain the above copyright
                                 12                 :  *    notice, this list of conditions and the following disclaimer.
                                 13                 :  * 2. Redistributions in binary form must reproduce the above copyright
                                 14                 :  *    notice, this list of conditions and the following disclaimer in the
                                 15                 :  *    documentation and/or other materials provided with the distribution.
                                 16                 :  * 4. Neither the name of the University nor the names of its contributors
                                 17                 :  *    may be used to endorse or promote products derived from this software
                                 18                 :  *    without specific prior written permission.
                                 19                 :  *
                                 20                 :  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                                 21                 :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                                 22                 :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                                 23                 :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                                 24                 :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                                 25                 :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                                 26                 :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                                 27                 :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                                 28                 :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                                 29                 :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                                 30                 :  * SUCH DAMAGE.
                                 31                 :  */
                                 32                 : 
                                 33                 : #include "c.h"
                                 34                 : 
                                 35                 : #include <sys/stat.h>
                                 36                 : 
                                 37                 : 
                                 38                 : /*
                                 39                 :  * pg_mkdir_p --- create a directory and, if necessary, parent directories
                                 40                 :  *
                                 41                 :  * This is equivalent to "mkdir -p" except we don't complain if the target
                                 42                 :  * directory already exists.
                                 43                 :  *
                                 44                 :  * We assume the path is in canonical form, i.e., uses / as the separator.
                                 45                 :  *
                                 46                 :  * omode is the file permissions bits for the target directory.  Note that any
                                 47                 :  * parent directories that have to be created get permissions according to the
                                 48                 :  * prevailing umask, but with u+wx forced on to ensure we can create there.
                                 49                 :  * (We declare omode as int, not mode_t, to minimize dependencies for port.h.)
                                 50                 :  *
                                 51                 :  * Returns 0 on success, -1 (with errno set) on failure.
                                 52                 :  *
                                 53                 :  * Note that on failure, the path arg has been modified to show the particular
                                 54                 :  * directory level we had problems with.
                                 55                 :  */
                                 56                 : int
 4503 tgl                        57 CBC         528 : pg_mkdir_p(char *path, int omode)
                                 58                 : {
                                 59                 :     struct stat sb;
                                 60                 :     mode_t      numask,
                                 61                 :                 oumask;
                                 62                 :     int         last,
                                 63                 :                 retval;
                                 64                 :     char       *p;
                                 65                 : 
                                 66             528 :     retval = 0;
                                 67             528 :     p = path;
                                 68                 : 
                                 69                 : #ifdef WIN32
                                 70                 :     /* skip network and drive specifiers for win32 */
                                 71                 :     if (strlen(p) >= 2)
                                 72                 :     {
                                 73                 :         if (p[0] == '/' && p[1] == '/')
                                 74                 :         {
                                 75                 :             /* network drive */
                                 76                 :             p = strstr(p + 2, "/");
                                 77                 :             if (p == NULL)
                                 78                 :             {
                                 79                 :                 errno = EINVAL;
                                 80                 :                 return -1;
                                 81                 :             }
                                 82                 :         }
                                 83                 :         else if (p[1] == ':' &&
                                 84                 :                  ((p[0] >= 'a' && p[0] <= 'z') ||
                                 85                 :                   (p[0] >= 'A' && p[0] <= 'Z')))
                                 86                 :         {
                                 87                 :             /* local drive */
                                 88                 :             p += 2;
                                 89                 :         }
                                 90                 :     }
                                 91                 : #endif
                                 92                 : 
                                 93                 :     /*
                                 94                 :      * POSIX 1003.2: For each dir operand that does not name an existing
                                 95                 :      * directory, effects equivalent to those caused by the following command
                                 96                 :      * shall occur:
                                 97                 :      *
                                 98                 :      * mkdir -p -m $(umask -S),u+wx $(dirname dir) && mkdir [-m mode] dir
                                 99                 :      *
                                100                 :      * We change the user's umask and then restore it, instead of doing
                                101                 :      * chmod's.  Note we assume umask() can't change errno.
                                102                 :      */
                                103             528 :     oumask = umask(0);
                                104             528 :     numask = oumask & ~(S_IWUSR | S_IXUSR);
                                105             528 :     (void) umask(numask);
                                106                 : 
                                107             528 :     if (p[0] == '/')            /* Skip leading '/'. */
                                108             528 :         ++p;
                                109           49011 :     for (last = 0; !last; ++p)
                                110                 :     {
                                111           48483 :         if (p[0] == '\0')
                                112             528 :             last = 1;
                                113           47955 :         else if (p[0] != '/')
                                114           43478 :             continue;
                                115            5005 :         *p = '\0';
                                116            5005 :         if (!last && p[1] == '\0')
 4503 tgl                       117 UBC           0 :             last = 1;
                                118                 : 
 4503 tgl                       119 CBC        5005 :         if (last)
                                120             528 :             (void) umask(oumask);
                                121                 : 
                                122                 :         /* check for pre-existing directory */
                                123            5005 :         if (stat(path, &sb) == 0)
                                124                 :         {
                                125            4386 :             if (!S_ISDIR(sb.st_mode))
                                126                 :             {
 4503 tgl                       127 UBC           0 :                 if (last)
                                128               0 :                     errno = EEXIST;
                                129                 :                 else
                                130               0 :                     errno = ENOTDIR;
                                131               0 :                 retval = -1;
                                132               0 :                 break;
                                133                 :             }
                                134                 :         }
 4503 tgl                       135 CBC         619 :         else if (mkdir(path, last ? omode : S_IRWXU | S_IRWXG | S_IRWXO) < 0)
                                136                 :         {
 4503 tgl                       137 UBC           0 :             retval = -1;
                                138               0 :             break;
                                139                 :         }
 4503 tgl                       140 CBC        5005 :         if (!last)
                                141            4477 :             *p = '/';
                                142                 :     }
                                143                 : 
                                144                 :     /* ensure we restored umask */
                                145             528 :     (void) umask(oumask);
                                146                 : 
                                147             528 :     return retval;
                                148                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a