LCOV - code coverage report
Current view: top level - common - mkdir_p.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 56 0.0 %
Date: 2016-11-29 15:00:56 Functions: 0 2 0.0 %

          Line data    Source code
       1             : /* mkdir_p.c - Create a directory and any missing parents.
       2             :  * Copyright (C) 2015 g10 Code GmbH
       3             :  *
       4             :  * This file is part of GnuPG.
       5             :  *
       6             :  * This file is free software; you can redistribute it and/or modify
       7             :  * it under the terms of either
       8             :  *
       9             :  *   - the GNU Lesser General Public License as published by the Free
      10             :  *     Software Foundation; either version 3 of the License, or (at
      11             :  *     your option) any later version.
      12             :  *
      13             :  * or
      14             :  *
      15             :  *   - the GNU General Public License as published by the Free
      16             :  *     Software Foundation; either version 2 of the License, or (at
      17             :  *     your option) any later version.
      18             :  *
      19             :  * or both in parallel, as here.
      20             :  *
      21             :  * This file is distributed in the hope that it will be useful,
      22             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      23             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      24             :  * GNU General Public License for more details.
      25             :  *
      26             :  * You should have received a copy of the GNU General Public License
      27             :  * along with this program; if not, see <https://www.gnu.org/licenses/>.
      28             :  */
      29             : 
      30             : #include <config.h>
      31             : #include <sys/stat.h>
      32             : #include <errno.h>
      33             : #include <assert.h>
      34             : #include <stdarg.h>
      35             : 
      36             : #include "util.h"
      37             : #include "stringhelp.h"
      38             : #include "logging.h"
      39             : #include "sysutils.h"
      40             : #include "mkdir_p.h"
      41             : 
      42             : 
      43             : gpg_error_t
      44           0 : gnupg_amkdir_p (const char **directory_components)
      45             : {
      46           0 :   gpg_error_t err = 0;
      47             :   int count;
      48             :   char **dirs;
      49             :   int i;
      50             : 
      51           0 :   for (count = 0; directory_components[count]; count ++)
      52             :     ;
      53             : 
      54             :   /* log_debug ("%s: %d directory components.\n", __func__, count); */
      55             : 
      56           0 :   dirs = xtrycalloc (count, sizeof *dirs);
      57           0 :   if (!dirs)
      58           0 :     return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
      59             : 
      60           0 :   for (i = 0; directory_components[i]; i ++)
      61             :     {
      62           0 :       if (i == 0)
      63           0 :         dirs[i] = make_filename_try (directory_components[i], NULL);
      64             :       else
      65           0 :         dirs[i] = make_filename_try (dirs[i-1], directory_components[i], NULL);
      66           0 :       if (!dirs[i])
      67             :         {
      68           0 :           err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
      69           0 :           goto out;
      70             :         }
      71             : 
      72             :       /* log_debug ("%s: Directory %d: `%s'.\n", __func__, i, dirs[i]); */
      73             :     }
      74             : 
      75           0 :   for (i = count - 1; i >= 0; i --)
      76             :     {
      77             :       struct stat s;
      78             : 
      79             :       /* log_debug ("%s: stat(%s)\n", __func__, dirs[i]); */
      80             : 
      81           0 :       if (!stat (dirs[i], &s))
      82             :         {
      83           0 :           if ( ! S_ISDIR (s.st_mode))
      84             :             {
      85             :               /* log_debug ("%s: %s exists, but is not a directory!\n", */
      86             :               /*            __func__, dirs[i]); */
      87           0 :               err = gpg_err_make (default_errsource, GPG_ERR_ENOTDIR);
      88           0 :               goto out;
      89             :             }
      90             :           else
      91             :             {
      92             :               /* Got a directory.  */
      93             :               /* log_debug ("%s: %s exists and is a directory!\n",  */
      94             :               /*            __func__, dirs[i]); */
      95           0 :               err = 0;
      96           0 :               break;
      97             :             }
      98             :         }
      99           0 :       else if (errno == ENOENT)
     100             :         /* This directory does not exist yet.  Continue walking up the
     101             :            hierarchy.  */
     102             :         {
     103             :           /* log_debug ("%s: %s does not exist!\n", */
     104             :           /*            __func__, dirs[i]); */
     105           0 :           continue;
     106             :         }
     107             :       else
     108             :         /* Some other error code.  Die.  Note: this could be ENOTDIR
     109             :            (we return this above), which means that a component of the
     110             :            path prefix is not a directory.  */
     111             :         {
     112             :           /* log_debug ("%s: stat(%s) => %s!\n", */
     113             :           /*            __func__, dirs[i], strerror (errno)); */
     114           0 :           err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
     115           0 :           goto out;
     116             :         }
     117             :     }
     118             : 
     119           0 :   assert (i >= -1);
     120             :   /* DIRS[I] exists.  Start with the following entry.  */
     121           0 :   i ++;
     122             : 
     123           0 :   for (; i < count; i ++)
     124             :     {
     125             :       /* log_debug ("Creating directory: %s\n", dirs[i]); */
     126             : 
     127           0 :       if (gnupg_mkdir (dirs[i], "-rwx"))
     128             :         {
     129           0 :           err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
     130           0 :           goto out;
     131             :         }
     132             :     }
     133             : 
     134             :  out:
     135           0 :   for (i = 0; i < count; i ++)
     136           0 :     xfree (dirs[i]);
     137           0 :   xfree (dirs);
     138             : 
     139             :   /* log_debug ("%s: Returning %s\n", __func__, gpg_strerror (rc)); */
     140             : 
     141           0 :   return err;
     142             : }
     143             : 
     144             : 
     145             : gpg_error_t
     146           0 : gnupg_mkdir_p (const char *directory_component, ...)
     147             : {
     148             :   va_list ap;
     149           0 :   gpg_error_t err = 0;
     150             :   int i;
     151           0 :   int space = 1;
     152             :   const char **dirs;
     153             : 
     154           0 :   dirs = xtrymalloc (space * sizeof (char *));
     155           0 :   if (!dirs)
     156           0 :     return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
     157             : 
     158           0 :   dirs[0] = directory_component;
     159             : 
     160           0 :   va_start (ap, directory_component);
     161           0 :   for (i = 1; dirs[i - 1]; i ++)
     162             :     {
     163           0 :       if (i == space)
     164             :         {
     165             :           const char **tmp_dirs;
     166             : 
     167           0 :           space = 2 * space;
     168           0 :           tmp_dirs = xtryrealloc (dirs, space * sizeof (char *));
     169           0 :           if (!tmp_dirs)
     170             :             {
     171           0 :               err = gpg_err_make (default_errsource,
     172             :                                   gpg_err_code_from_syserror ());
     173           0 :               break;
     174             :             }
     175           0 :           dirs = tmp_dirs;
     176             :         }
     177           0 :       dirs[i] = va_arg (ap, char *);
     178             :     }
     179           0 :   va_end (ap);
     180             : 
     181           0 :   if (!err)
     182           0 :     err = gnupg_amkdir_p (dirs);
     183             : 
     184           0 :   xfree (dirs);
     185             : 
     186           0 :   return err;
     187             : }

Generated by: LCOV version 1.11