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 void put_workdir(int fd, const char *name, size_t length)
54 /* close the previous directory if any */
58 /* copy the name and the fd if existing */
65 assert(length < sizeof workdir);
66 memcpy(workdir, name, 1 + length);
71 int set_workdir(const char *name, int create)
76 /* check the length */
77 length = strlen(name);
78 if (length >= sizeof workdir) {
79 ERROR("workdir name too long");
84 /* opens the directory */
85 dirfd = openat(AT_FDCWD, name, O_PATH|O_DIRECTORY|O_RDONLY);
87 if (errno != ENOENT) {
88 ERROR("error while opening workdir %s: %m", name);
92 ERROR("workdir %s doesn't exist", name);
95 rc = mkdirat(AT_FDCWD, name, dirmode);
97 ERROR("can't create workdir %s", name);
100 dirfd = openat(AT_FDCWD, name, O_PATH|O_DIRECTORY|O_RDONLY);
102 ERROR("can't open workdir %s", name);
107 /* record new workdir */
108 put_workdir(dirfd, name, length);
112 int make_workdir(const char *root, const char *prefix, int reuse)
116 put_workdir(AT_FDCWD, ".", 1);
118 n = snprintf(workdir, sizeof workdir, "%s/%s", root, prefix);
119 if (n >= sizeof workdir) {
120 ERROR("workdir prefix too long");
124 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 (!mkdirat(AT_FDCWD, 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 move_workdir(const char *dest, int parents, int force)
165 if (strlen(dest) >= sizeof workdir) {
166 ERROR("destination dirname too long");
171 /* if an existing directory exist remove it if force */
174 if (!S_ISDIR(s.st_mode)) {
175 ERROR("in move_workdir, can't overwrite regular file %s", dest);
180 ERROR("in move_workdir, can't overwrite regular file %s", dest);
184 rc = remove_directory_content(dest);
186 ERROR("in move_workdir, can't clean dir %s", dest);
191 ERROR("in move_workdir, can't remove dir %s", dest);
195 /* check parent of dest */
196 iter = strrchr(dest, '/');
197 len = iter ? iter - dest : 0;
199 /* is parent existing? */
200 copy = strndupa(dest, len);
204 if (!S_ISDIR(s.st_mode)) {
205 ERROR("in move_workdir, '%s' isn't a directory", copy);
209 } else if (!parents) {
210 /* parent entry not found but not allowed to create it */
211 ERROR("in move_workdir, parent directory '%s' not found: %m", copy);
213 } else if (create_directory(copy, dirmode, 1)) {
214 ERROR("in move_workdir, creation of directory %s failed: %m", copy);
220 /* try to rename now */
223 rc = renameat(AT_FDCWD, workdir, AT_FDCWD, dest);
225 ERROR("in move_workdir, renameat failed %s -> %s: %m", workdir, dest);
229 return set_workdir(dest, 0);