XBPS Library API 20240111
The X Binary Package System
mkpath.c
1/*
2 * Copyright (c) 1983, 1992, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30/*
31 * The following is a modified function from NetBSD's src/bin/mkdir/mkdir.c
32 */
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include <errno.h>
37#include <sys/stat.h>
38
39#include "xbps_api_impl.h"
40
41int
42xbps_mkpath(const char *path, mode_t mode)
43{
44 struct stat sb;
45 char *ppath, *slash;
46 int done = 0;
47 mode_t dir_mode;
48
49 if ((ppath = strdup(path)) == NULL)
50 return -1;
51
52 slash = ppath;
53 /*
54 * The default file mode is a=rwx (0777) with selected permissions
55 * removed in accordance with the file mode creation mask. For
56 * intermediate path name components, the mode is the default modified
57 * by u+wx so that the subdirectories can always be created.
58 */
59 if (mode == 0)
60 mode = (S_IRWXU | S_IRWXG | S_IRWXO) & ~umask(0);
61
62 dir_mode = mode | S_IRUSR | S_IXUSR | S_IROTH | S_IXOTH;
63
64 for (;;) {
65 slash += strspn(slash, "/");
66 slash += strcspn(slash, "/");
67
68 done = (*slash == '\0');
69 *slash = '\0';
70
71 if (mkdir(ppath, done ? mode : dir_mode) == -1) {
72 /*
73 * Can't create; path exists or no perms.
74 * stat() path to determine what's there now.
75 */
76 int sverrno;
77
78 sverrno = errno;
79 if (stat(ppath, &sb) < 0) {
80 /* Not there; use mkdir()s error */
81 errno = sverrno;
82 free(ppath);
83 return -1;
84 }
85 if (!S_ISDIR(sb.st_mode)) {
86 /* Is there, but isn't a directory */
87 errno = ENOTDIR;
88 free(ppath);
89 return -1;
90 }
91 }
92 if (done)
93 break;
94
95 *slash = '/';
96 }
97 free(ppath);
98
99 return 0;
100}
int xbps_mkpath(const char *path, mode_t mode)
Definition mkpath.c:42