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.
29 #include <sys/types.h>
34 #include "wgtpkg-workdir.h"
35 #include "utils-dir.h"
37 static const int dirmode = 0755;
38 char workdir[PATH_MAX] = { 0, };
41 /* removes the working directory */
44 assert(workdirfd >= 0);
45 remove_directory_content_fd(workdirfd);
52 static int set_real_workdir(const char *name, int create)
57 /* check the length */
58 length = strlen(name);
59 if (length >= sizeof workdir) {
60 ERROR("workdir name too long");
65 /* opens the directory */
66 dirfd = openat(AT_FDCWD, name, O_DIRECTORY|O_RDONLY);
68 if (!create || errno != ENOENT) {
69 ERROR("no workdir %s", name);
72 rc = mkdir(name, dirmode);
74 ERROR("can't create workdir %s", name);
77 dirfd = open(name, O_PATH|O_DIRECTORY);
79 ERROR("can't open workdir %s", name);
84 /* close the previous directory if any */
88 memcpy(workdir, name, 1+length);
92 int set_workdir(const char *name, int create)
98 return set_real_workdir(name, create);
100 rp = realpath(name, NULL);
102 ERROR("realpath failed for %s", name);
105 rc = set_real_workdir(rp, create);
110 static int make_real_workdir_base(const char *root, const char *prefix, int reuse)
114 n = snprintf(workdir, sizeof workdir, "%s/%s", root, prefix);
115 if (n >= sizeof workdir) {
116 ERROR("workdir prefix too long");
120 r = (int)(sizeof workdir) - n;
126 /* create a temporary directory */
127 for (i = 0 ; ; i++) {
129 ERROR("exhaustion of workdirs");
132 l = snprintf(workdir + n, r, "%d", i);
134 ERROR("computed workdir too long");
138 if (!mkdir(workdir, dirmode))
140 if (errno != EEXIST) {
141 ERROR("error in creation of workdir %s: %m", workdir);
147 workdirfd = openat(AT_FDCWD, workdir, O_RDONLY|O_DIRECTORY);
149 ERROR("error in onnection to workdir %s: %m", workdir);
157 int make_workdir_base(const char *root, const char *prefix, int reuse)
163 return make_real_workdir_base(root, prefix, reuse);
165 rp = realpath(root, NULL);
167 ERROR("realpath failed for %s", root);
170 rc = make_real_workdir_base(rp, prefix, reuse);
175 int make_workdir(int reuse)
177 return make_workdir_base(".", "PACK", reuse);
180 static int move_real_workdir(const char *dest, int parents, int force)
188 if (strlen(dest) >= sizeof workdir) {
189 ERROR("destination dirname too long");
194 /* if an existing directory exist remove it if force */
197 if (!S_ISDIR(s.st_mode)) {
198 ERROR("in move_real_workdir, can't overwrite regular file %s", dest);
203 ERROR("in move_real_workdir, can't overwrite regular file %s", dest);
207 rc = remove_directory_content(dest);
209 ERROR("in move_real_workdir, can't clean dir %s", dest);
214 ERROR("in move_real_workdir, can't remove dir %s", dest);
218 /* check parent of dest */
219 iter = strrchr(dest, '/');
220 len = iter ? iter - dest : 0;
222 /* is parent existing? */
223 copy = strndupa(dest, len);
227 if (!S_ISDIR(s.st_mode)) {
228 ERROR("in move_real_workdir, '%s' isn't a directory", copy);
232 } else if (!parents) {
233 /* parent entry not found but not allowed to create it */
234 ERROR("in move_real_workdir, parent directory '%s' not found: %m", copy);
236 } else if (create_directory(copy, dirmode, 1)) {
237 ERROR("in move_real_workdir, creation of directory %s failed: %m", copy);
243 /* try to rename now */
246 rc = renameat(AT_FDCWD, workdir, AT_FDCWD, dest);
248 ERROR("in move_real_workdir, renameat failed %s -> %s: %m", workdir, dest);
252 return set_real_workdir(dest, 0);
255 int move_workdir(const char *dest, int parents, int force)
261 return move_real_workdir(dest, parents, force);
263 rp = realpath(dest, NULL);
265 ERROR("realpath failed for %s", dest);
268 rc = move_real_workdir(rp, parents, force);