This source file includes following definitions.
- make_dir_parents
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #include <config.h>
22
23 #include "mkdir-p.h"
24
25 #include <errno.h>
26 #include <sys/stat.h>
27 #include <unistd.h>
28
29 #include "gettext.h"
30 #define _(msgid) gettext (msgid)
31
32 #include "dirchownmod.h"
33 #include "dirname.h"
34 #include "error.h"
35 #include "quote.h"
36 #include "mkancesdirs.h"
37 #include "savewd.h"
38
39 #ifndef HAVE_FCHMOD
40 # define HAVE_FCHMOD false
41 #endif
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84 bool
85 make_dir_parents (char *dir,
86 struct savewd *wd,
87 int (*make_ancestor) (char const *, char const *, void *),
88 void *options,
89 mode_t mode,
90 void (*announce) (char const *, void *),
91 mode_t mode_bits,
92 uid_t owner,
93 gid_t group,
94 bool preserve_existing)
95 {
96 int mkdir_errno = (IS_ABSOLUTE_FILE_NAME (dir) ? 0 : savewd_errno (wd));
97
98 if (mkdir_errno == 0)
99 {
100 ptrdiff_t prefix_len = 0;
101 int savewd_chdir_options = (HAVE_FCHMOD ? SAVEWD_CHDIR_SKIP_READABLE : 0);
102
103 if (make_ancestor)
104 {
105 prefix_len = mkancesdirs (dir, wd, make_ancestor, options);
106 if (prefix_len < 0)
107 {
108 if (prefix_len < -1)
109 return true;
110 mkdir_errno = errno;
111 }
112 }
113
114 if (0 <= prefix_len)
115 {
116
117
118
119
120
121 bool keep_owner = owner == (uid_t) -1 && group == (gid_t) -1;
122 bool keep_special_mode_bits =
123 ((mode_bits & (S_ISUID | S_ISGID)) | (mode & S_ISVTX)) == 0;
124 mode_t mkdir_mode = mode;
125 if (! keep_owner)
126 mkdir_mode &= ~ (S_IRWXG | S_IRWXO);
127 else if (! keep_special_mode_bits)
128 mkdir_mode &= ~ (S_IWGRP | S_IWOTH);
129
130 if (mkdir (dir + prefix_len, mkdir_mode) == 0)
131 {
132
133
134 bool umask_must_be_ok = (mode & mode_bits & S_IRWXUGO) == 0;
135
136 announce (dir, options);
137 preserve_existing = (keep_owner & keep_special_mode_bits
138 & umask_must_be_ok);
139 savewd_chdir_options |= SAVEWD_CHDIR_NOFOLLOW;
140 }
141 else
142 {
143 mkdir_errno = errno;
144 mkdir_mode = -1;
145 }
146
147 if (preserve_existing)
148 {
149 if (mkdir_errno == 0)
150 return true;
151 if (mkdir_errno != ENOENT && make_ancestor)
152 {
153 struct stat st;
154 if (stat (dir + prefix_len, &st) == 0)
155 {
156 if (S_ISDIR (st.st_mode))
157 return true;
158 }
159 else if (mkdir_errno == EEXIST
160 && errno != ENOENT && errno != ENOTDIR)
161 {
162 error (0, errno, _("cannot stat %s"), quote (dir));
163 return false;
164 }
165 }
166 }
167 else
168 {
169 int open_result[2];
170 int chdir_result =
171 savewd_chdir (wd, dir + prefix_len,
172 savewd_chdir_options, open_result);
173 if (chdir_result < -1)
174 return true;
175 else
176 {
177 bool chdir_ok = (chdir_result == 0);
178 char const *subdir = (chdir_ok ? "." : dir + prefix_len);
179 if (dirchownmod (open_result[0], subdir, mkdir_mode,
180 owner, group, mode, mode_bits)
181 == 0)
182 return true;
183
184 if (mkdir_errno == 0
185 || (mkdir_errno != ENOENT && make_ancestor
186 && errno != ENOTDIR))
187 {
188 error (0, errno,
189 _(keep_owner
190 ? "cannot change permissions of %s"
191 : "cannot change owner and permissions of %s"),
192 quote (dir));
193 return false;
194 }
195 }
196 }
197 }
198 }
199
200 error (0, mkdir_errno, _("cannot create directory %s"), quote (dir));
201 return false;
202 }