LCOV - differential code coverage report
Current view: top level - src/port - pgmkdirp.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 75.0 % 32 24 8 24
Current Date: 2024-04-14 14:21:10 Functions: 100.0 % 1 1 1
Baseline: 16@8cea358b128 Branches: 80.8 % 26 21 5 21
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed (240..) days: 75.0 % 32 24 8 24
Function coverage date bins:
(240..) days: 100.0 % 1 1 1
Branch coverage date bins:
(240..) days: 80.8 % 26 21 5 21

 Age         Owner                    Branch data    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
 4874 tgl@sss.pgh.pa.us          57                 :CBC         454 : 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                 :            454 :     retval = 0;
                                 67                 :            454 :     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                 :            454 :     oumask = umask(0);
                                104                 :            454 :     numask = oumask & ~(S_IWUSR | S_IXUSR);
                                105                 :            454 :     (void) umask(numask);
                                106                 :                : 
                                107         [ +  + ]:            454 :     if (p[0] == '/')            /* Skip leading '/'. */
                                108                 :            450 :         ++p;
                                109         [ +  + ]:          64287 :     for (last = 0; !last; ++p)
                                110                 :                :     {
                                111         [ +  + ]:          63833 :         if (p[0] == '\0')
                                112                 :            454 :             last = 1;
                                113         [ +  + ]:          63379 :         else if (p[0] != '/')
                                114                 :          58068 :             continue;
                                115                 :           5765 :         *p = '\0';
                                116   [ +  +  -  + ]:           5765 :         if (!last && p[1] == '\0')
 4874 tgl@sss.pgh.pa.us         117                 :UBC           0 :             last = 1;
                                118                 :                : 
 4874 tgl@sss.pgh.pa.us         119         [ +  + ]:CBC        5765 :         if (last)
                                120                 :            454 :             (void) umask(oumask);
                                121                 :                : 
                                122                 :                :         /* check for pre-existing directory */
                                123         [ +  + ]:           5765 :         if (stat(path, &sb) == 0)
                                124                 :                :         {
                                125         [ -  + ]:           5184 :             if (!S_ISDIR(sb.st_mode))
                                126                 :                :             {
 4874 tgl@sss.pgh.pa.us         127         [ #  # ]:UBC           0 :                 if (last)
                                128                 :              0 :                     errno = EEXIST;
                                129                 :                :                 else
                                130                 :              0 :                     errno = ENOTDIR;
                                131                 :              0 :                 retval = -1;
                                132                 :              0 :                 break;
                                133                 :                :             }
                                134                 :                :         }
 4874 tgl@sss.pgh.pa.us         135   [ +  +  -  + ]:CBC         581 :         else if (mkdir(path, last ? omode : S_IRWXU | S_IRWXG | S_IRWXO) < 0)
                                136                 :                :         {
 4874 tgl@sss.pgh.pa.us         137                 :UBC           0 :             retval = -1;
                                138                 :              0 :             break;
                                139                 :                :         }
 4874 tgl@sss.pgh.pa.us         140         [ +  + ]:CBC        5765 :         if (!last)
                                141                 :           5311 :             *p = '/';
                                142                 :                :     }
                                143                 :                : 
                                144                 :                :     /* ensure we restored umask */
                                145                 :            454 :     (void) umask(oumask);
                                146                 :                : 
                                147                 :            454 :     return retval;
                                148                 :                : }
        

Generated by: LCOV version 2.1-beta2-3-g6141622