1 /* mkdir_p.c - Create a directory and any missing parents.
2 * Copyright (C) 2015 g10 Code GmbH
4 * This file is part of GnuPG.
6 * This file is free software; you can redistribute it and/or modify
7 * it under the terms of either
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.
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.
19 * or both in parallel, as here.
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.
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/>.
37 #include "stringhelp.h"
44 gnupg_amkdir_p (const char **directory_components)
51 for (count = 0; directory_components[count]; count ++)
54 /* log_debug ("%s: %d directory components.\n", __func__, count); */
56 dirs = xtrycalloc (count, sizeof *dirs);
58 return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
60 for (i = 0; directory_components[i]; i ++)
63 dirs[i] = make_filename_try (directory_components[i], NULL);
65 dirs[i] = make_filename_try (dirs[i-1], directory_components[i], NULL);
68 err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
72 /* log_debug ("%s: Directory %d: `%s'.\n", __func__, i, dirs[i]); */
75 for (i = count - 1; i >= 0; i --)
79 /* log_debug ("%s: stat(%s)\n", __func__, dirs[i]); */
81 if (!stat (dirs[i], &s))
83 if ( ! S_ISDIR (s.st_mode))
85 /* log_debug ("%s: %s exists, but is not a directory!\n", */
86 /* __func__, dirs[i]); */
87 err = gpg_err_make (default_errsource, GPG_ERR_ENOTDIR);
92 /* Got a directory. */
93 /* log_debug ("%s: %s exists and is a directory!\n", */
94 /* __func__, dirs[i]); */
99 else if (errno == ENOENT)
100 /* This directory does not exist yet. Continue walking up the
103 /* log_debug ("%s: %s does not exist!\n", */
104 /* __func__, dirs[i]); */
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. */
112 /* log_debug ("%s: stat(%s) => %s!\n", */
113 /* __func__, dirs[i], strerror (errno)); */
114 err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
120 /* DIRS[I] exists. Start with the following entry. */
123 for (; i < count; i ++)
125 /* log_debug ("Creating directory: %s\n", dirs[i]); */
127 if (gnupg_mkdir (dirs[i], "-rwx"))
129 err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
135 for (i = 0; i < count; i ++)
139 /* log_debug ("%s: Returning %s\n", __func__, gpg_strerror (rc)); */
146 gnupg_mkdir_p (const char *directory_component, ...)
154 dirs = xtrymalloc (space * sizeof (char *));
156 return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
158 dirs[0] = directory_component;
160 va_start (ap, directory_component);
161 for (i = 1; dirs[i - 1]; i ++)
165 const char **tmp_dirs;
168 tmp_dirs = xtryrealloc (dirs, space * sizeof (char *));
171 err = gpg_err_make (default_errsource,
172 gpg_err_code_from_syserror ());
177 dirs[i] = va_arg (ap, char *);
182 err = gnupg_amkdir_p (dirs);