4 author: José Bollo <jose.bollo@iot.bzh>
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
10 http://www.apache.org/licenses/LICENSE-2.0
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
27 #include <sys/types.h>
33 #include "utils-dir.h"
35 static const int dirmode = 0755;
36 char workdir[PATH_MAX] = { 0, };
39 /* removes the working directory */
42 assert(workdirfd >= 0);
43 remove_directory_content_fd(workdirfd);
50 static int set_real_workdir(const char *name, int create)
55 /* check the length */
56 length = strlen(name);
57 if (length >= sizeof workdir) {
58 ERROR("workdir name too long");
63 /* opens the directory */
64 dirfd = openat(AT_FDCWD, name, O_DIRECTORY|O_RDONLY);
66 if (!create || errno != ENOENT) {
67 ERROR("no workdir %s", name);
70 rc = mkdir(name, dirmode);
72 ERROR("can't create workdir %s", name);
75 dirfd = open(name, O_PATH|O_DIRECTORY);
77 ERROR("can't open workdir %s", name);
82 /* close the previous directory if any */
86 memcpy(workdir, name, 1+length);
90 int set_workdir(const char *name, int create)
96 return set_real_workdir(name, create);
98 rp = realpath(name, NULL);
100 ERROR("realpath failed for %s", name);
103 rc = set_real_workdir(rp, create);
108 static int make_real_workdir_base(const char *root, const char *prefix, int reuse)
112 n = snprintf(workdir, sizeof workdir, "%s/%s", root, prefix);
113 if (n >= sizeof workdir) {
114 ERROR("workdir prefix too long");
118 r = (int)(sizeof workdir) - n;
124 /* create a temporary directory */
125 for (i = 0 ; ; i++) {
127 ERROR("exhaustion of workdirs");
130 l = snprintf(workdir + n, r, "%d", i);
132 ERROR("computed workdir too long");
136 if (!mkdir(workdir, dirmode))
138 if (errno != EEXIST) {
139 ERROR("error in creation of workdir %s: %m", workdir);
145 workdirfd = openat(AT_FDCWD, workdir, O_RDONLY|O_DIRECTORY);
147 ERROR("error in onnection to workdir %s: %m", workdir);
155 int make_workdir_base(const char *root, const char *prefix, int reuse)
161 return make_real_workdir_base(root, prefix, reuse);
163 rp = realpath(root, NULL);
165 ERROR("realpath failed for %s", root);
168 rc = make_real_workdir_base(rp, prefix, reuse);
173 int make_workdir(int reuse)
175 return make_workdir_base(".", "PACK", reuse);
178 static int move_real_workdir(const char *dest, int parents, int force)
186 if (strlen(dest) >= sizeof workdir) {
187 ERROR("destination dirname too long");
192 /* if an existing directory exist remove it if force */
195 if (!S_ISDIR(s.st_mode)) {
196 ERROR("in move_real_workdir, can't overwrite regular file %s", dest);
201 ERROR("in move_real_workdir, can't overwrite regular file %s", dest);
205 rc = remove_directory_content(dest);
207 ERROR("in move_real_workdir, can't clean dir %s", dest);
212 ERROR("in move_real_workdir, can't remove dir %s", dest);
216 /* check parent of dest */
217 iter = strrchr(dest, '/');
218 len = iter ? iter - dest : 0;
220 /* is parent existing? */
221 copy = strndupa(dest, len);
225 if (!S_ISDIR(s.st_mode)) {
226 ERROR("in move_real_workdir, '%s' isn't a directory", copy);
230 } else if (!parents) {
231 /* parent entry not found but not allowed to create it */
232 ERROR("in move_real_workdir, parent directory '%s' not found: %m", copy);
234 } else if (create_directory(copy, dirmode, 1)) {
235 ERROR("in move_real_workdir, creation of directory %s failed: %m", copy);
241 /* try to rename now */
244 rc = renameat(AT_FDCWD, workdir, AT_FDCWD, dest);
246 ERROR("in move_real_workdir, renameat failed %s -> %s: %m", workdir, dest);
250 return set_real_workdir(dest, 0);
253 int move_workdir(const char *dest, int parents, int force)
259 return move_real_workdir(dest, parents, force);
261 rp = realpath(dest, NULL);
263 ERROR("realpath failed for %s", dest);
266 rc = move_real_workdir(rp, parents, force);