2 Copyright 2015, 2016, 2017 IoT.bzh
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 mode_t 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 >= (int)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, (unsigned)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)
166 if (strlen(dest) >= sizeof workdir) {
167 ERROR("destination dirname too long");
172 /* if an existing directory exist remove it if force */
175 if (!S_ISDIR(s.st_mode)) {
176 ERROR("in move_workdir, can't overwrite regular file %s", dest);
181 ERROR("in move_workdir, can't overwrite regular file %s", dest);
185 rc = remove_directory_content(dest);
187 ERROR("in move_workdir, can't clean dir %s", dest);
192 ERROR("in move_workdir, can't remove dir %s", dest);
196 /* check parent of dest */
197 iter = strrchr(dest, '/');
198 len = iter ? (size_t)(iter - dest) : 0;
200 /* is parent existing? */
201 copy = strndupa(dest, len);
205 if (!S_ISDIR(s.st_mode)) {
206 ERROR("in move_workdir, '%s' isn't a directory", copy);
210 } else if (!parents) {
211 /* parent entry not found but not allowed to create it */
212 ERROR("in move_workdir, parent directory '%s' not found: %m", copy);
214 } else if (create_directory(copy, dirmode, 1)) {
215 ERROR("in move_workdir, creation of directory %s failed: %m", copy);
221 /* try to rename now */
224 rc = renameat(AT_FDCWD, workdir, AT_FDCWD, dest);
226 ERROR("in move_workdir, renameat failed %s -> %s: %m", workdir, dest);
230 return set_workdir(dest, 0);