Mercurial > hg > toybox
comparison lib/lib.c @ 1219:468444e5c7c5 draft
Move mkpathat to lib, remove redundant function used by patch.
author | Rob Landley <rob@landley.net> |
---|---|
date | Tue, 11 Mar 2014 20:44:55 -0500 |
parents | fba5d8d3905c |
children | e1b09affb6db |
comparison
equal
deleted
inserted
replaced
1218:fba5d8d3905c | 1219:468444e5c7c5 |
---|---|
112 else offset -= or; | 112 else offset -= or; |
113 if (or < try) break; | 113 if (or < try) break; |
114 } | 114 } |
115 | 115 |
116 return offset; | 116 return offset; |
117 } | |
118 | |
119 // flags: 1=make last dir (with mode lastmode, otherwise skips last component) | |
120 // 2=make path (already exists is ok) | |
121 // 4=verbose | |
122 // returns 0 = path ok, 1 = error | |
123 int mkpathat(int atfd, char *dir, mode_t lastmode, int flags) | |
124 { | |
125 struct stat buf; | |
126 char *s; | |
127 | |
128 // mkdir -p one/two/three is not an error if the path already exists, | |
129 // but is if "three" is a file. The others we dereference and catch | |
130 // not-a-directory along the way, but the last one we must explicitly | |
131 // test for. Might as well do it up front. | |
132 | |
133 if (!fstatat(atfd, dir, &buf, 0) && !S_ISDIR(buf.st_mode)) { | |
134 errno = EEXIST; | |
135 return 1; | |
136 } | |
137 | |
138 // Skip leading / of absolute paths | |
139 while (*dir == '/') dir++; | |
140 | |
141 for (s=dir; ;s++) { | |
142 char save = 0; | |
143 mode_t mode = (0777&~toys.old_umask)|0300; | |
144 | |
145 // Skip leading / of absolute paths. | |
146 if (*s == '/' && (flags&2)) { | |
147 save = *s; | |
148 *s = 0; | |
149 } else if (*s) continue; | |
150 | |
151 // Use the mode from the -m option only for the last directory. | |
152 if (!save) { | |
153 if (flags&1) mode = lastmode; | |
154 else break; | |
155 } | |
156 | |
157 if (mkdirat(atfd, dir, mode)) { | |
158 if (!(flags&2) || errno != EEXIST) return 1; | |
159 } else if (flags&4) | |
160 fprintf(stderr, "%s: created directory '%s'\n", toys.which->name, dir); | |
161 | |
162 if (!(*s = save)) break; | |
163 } | |
164 | |
165 return 0; | |
117 } | 166 } |
118 | 167 |
119 // Split a path into linked list of components, tracking head and tail of list. | 168 // Split a path into linked list of components, tracking head and tail of list. |
120 // Filters out // entries with no contents. | 169 // Filters out // entries with no contents. |
121 struct string_list **splitpath(char *path, struct string_list **list) | 170 struct string_list **splitpath(char *path, struct string_list **list) |