#include <unistd.h>
#include <string.h>
#include <dirent.h>
-#include <syslog.h>
#include <errno.h>
#include <fcntl.h>
#include <assert.h>
#include "verbose.h"
#include "wgtpkg.h"
+#include "utils-dir.h"
-static int mode = 0755;
+static const int dirmode = 0755;
char workdir[PATH_MAX] = { 0, };
int workdirfd = -1;
-/* removes recursively the content of a directory */
-static int clean_dirfd(int dirfd)
-{
- int cr, fd;
- DIR *dir;
- struct dirent *ent;
- struct {
- struct dirent entry;
- char spare[PATH_MAX];
- } entry;
-
- dirfd = dup(dirfd);
- if (dirfd < 0) {
- syslog(LOG_ERR, "failed to dup the dirfd");
- return -1;
- }
- dir = fdopendir(dirfd);
- if (dir == NULL) {
- syslog(LOG_ERR, "fdopendir failed in clean_dirfd");
- return -1;
- }
-
- cr = -1;
- for (;;) {
- if (readdir_r(dir, &entry.entry, &ent) != 0) {
- syslog(LOG_ERR, "readdir_r failed in clean_dirfd");
- goto error;
- }
- if (ent == NULL)
- break;
- if (ent->d_name[0] == '.' && (ent->d_name[1] == 0
- || (ent->d_name[1] == '.' && ent->d_name[2] == 0)))
- continue;
- cr = unlinkat(dirfd, ent->d_name, 0);
- if (!cr)
- continue;
- if (errno != EISDIR) {
- syslog(LOG_ERR, "unlink of %s failed in clean_dirfd", ent->d_name);
- goto error;
- }
- fd = openat(dirfd, ent->d_name, O_DIRECTORY|O_RDONLY);
- if (fd < 0) {
- syslog(LOG_ERR, "opening directory %s failed in clean_dirfd", ent->d_name);
- goto error;
- }
- cr = clean_dirfd(fd);
- close(fd);
- if (cr)
- goto error;
- cr = unlinkat(dirfd, ent->d_name, AT_REMOVEDIR);
- if (cr) {
- syslog(LOG_ERR, "rmdir of %s failed in clean_dirfd", ent->d_name);
- goto error;
- }
- }
- cr = 0;
-error:
- closedir(dir);
- return cr;
-}
-
-/* removes recursively the content of a directory */
-static int clean_dir(const char *directory)
-{
- int fd, rc;
-
- fd = openat(AT_FDCWD, directory, O_DIRECTORY|O_RDONLY);
- if (fd < 0) {
- syslog(LOG_ERR, "opening directory %s failed in clean_dir", directory);
- return fd;
- }
- rc = clean_dirfd(fd);
- close(fd);
- return rc;
-}
-
/* removes the working directory */
void remove_workdir()
{
assert(workdirfd >= 0);
- clean_dirfd(workdirfd);
+ remove_directory_content_fd(workdirfd);
close(workdirfd);
workdirfd = -1;
rmdir(workdir);
/* check the length */
length = strlen(name);
if (length >= sizeof workdir) {
- syslog(LOG_ERR, "workdir name too long");
+ ERROR("workdir name too long");
errno = EINVAL;
return -1;
}
dirfd = openat(AT_FDCWD, name, O_DIRECTORY|O_RDONLY);
if (dirfd < 0) {
if (!create || errno != ENOENT) {
- syslog(LOG_ERR, "no workdir %s", name);
+ ERROR("no workdir %s", name);
return -1;
}
- rc = mkdir(name, mode);
+ rc = mkdir(name, dirmode);
if (rc) {
- syslog(LOG_ERR, "can't create workdir %s", name);
+ ERROR("can't create workdir %s", name);
return -1;
}
dirfd = open(name, O_PATH|O_DIRECTORY);
if (dirfd < 0) {
- syslog(LOG_ERR, "can't open workdir %s", name);
+ ERROR("can't open workdir %s", name);
return -1;
}
}
rp = realpath(name, NULL);
if (!rp) {
- syslog(LOG_ERR, "realpath failed for %s", name);
+ ERROR("realpath failed for %s", name);
return -1;
}
rc = set_real_workdir(rp, create);
n = snprintf(workdir, sizeof workdir, "%s/%s", root, prefix);
if (n >= sizeof workdir) {
- syslog(LOG_ERR, "workdir prefix too long");
+ ERROR("workdir prefix too long");
errno = EINVAL;
return -1;
}
/* create a temporary directory */
for (i = 0 ; ; i++) {
if (i == INT_MAX) {
- syslog(LOG_ERR, "exhaustion of workdirs");
+ ERROR("exhaustion of workdirs");
return -1;
}
l = snprintf(workdir + n, r, "%d", i);
if (l >= r) {
- syslog(LOG_ERR, "computed workdir too long");
+ ERROR("computed workdir too long");
errno = EINVAL;
return -1;
}
- if (!mkdir(workdir, mode))
+ if (!mkdir(workdir, dirmode))
break;
if (errno != EEXIST) {
- syslog(LOG_ERR, "error in creation of workdir %s: %m", workdir);
+ ERROR("error in creation of workdir %s: %m", workdir);
return -1;
}
if (reuse)
}
workdirfd = openat(AT_FDCWD, workdir, O_RDONLY|O_DIRECTORY);
if (workdirfd < 0) {
- syslog(LOG_ERR, "error in onnection to workdir %s: %m", workdir);
+ ERROR("error in onnection to workdir %s: %m", workdir);
rmdir(workdir);
return -1;
}
rp = realpath(root, NULL);
if (!rp) {
- syslog(LOG_ERR, "realpath failed for %s", root);
+ ERROR("realpath failed for %s", root);
return -1;
}
rc = make_real_workdir_base(rp, prefix, reuse);
static int move_real_workdir(const char *dest, int parents, int force)
{
- int rc, len, l;
+ int rc, len;
struct stat s;
char *copy;
const char *iter;
/* check length */
if (strlen(dest) >= sizeof workdir) {
- syslog(LOG_ERR, "destination dirname too long");
+ ERROR("destination dirname too long");
errno = EINVAL;
return -1;
}
rc = stat(dest, &s);
if (rc == 0) {
if (!S_ISDIR(s.st_mode)) {
- syslog(LOG_ERR, "in move_real_workdir, can't overwrite regular file %s", dest);
+ ERROR("in move_real_workdir, can't overwrite regular file %s", dest);
errno = EEXIST;
return -1;
}
if (!force) {
- syslog(LOG_ERR, "in move_real_workdir, can't overwrite regular file %s", dest);
+ ERROR("in move_real_workdir, can't overwrite regular file %s", dest);
errno = EEXIST;
return -1;
}
- rc = clean_dir(dest);
+ rc = remove_directory_content(dest);
if (rc) {
- syslog(LOG_ERR, "in move_real_workdir, can't clean dir %s", dest);
+ ERROR("in move_real_workdir, can't clean dir %s", dest);
return rc;
}
rc = rmdir(dest);
if (rc) {
- syslog(LOG_ERR, "in move_real_workdir, can't remove dir %s", dest);
+ ERROR("in move_real_workdir, can't remove dir %s", dest);
return rc;
}
} else {
if (!rc) {
/* found an entry */
if (!S_ISDIR(s.st_mode)) {
- syslog(LOG_ERR, "in move_real_workdir, '%s' isn't a directory", copy);
+ ERROR("in move_real_workdir, '%s' isn't a directory", copy);
errno = ENOTDIR;
return -1;
}
} else if (!parents) {
/* parent entry not found but not allowed to create it */
- syslog(LOG_ERR, "in move_real_workdir, parent directory '%s' not found: %m", copy);
+ ERROR("in move_real_workdir, parent directory '%s' not found: %m", copy);
+ return -1;
+ } else if (create_directory(copy, dirmode, 1)) {
+ ERROR("in move_real_workdir, creation of directory %s failed: %m", copy);
return -1;
- } else {
- /* parent entries to be created */
- l = len;
- for(;;) {
- /* backward loop */
- rc = mkdir(copy, mode);
- if (!rc)
- break;
- if (errno != ENOENT) {
- syslog(LOG_ERR, "in move_real_workdir, mkdir '%s' failed: %m", copy);
- return -1;
- }
- while (l && copy[l] != '/')
- l--;
- if (l == 0) {
- syslog(LOG_ERR, "in move_real_workdir, internal error");
- errno = EINVAL;
- return -1;
- }
- copy[l] = 0;
- }
- while(l < len) {
- /* forward loop */
- copy[l] = '/';
- while (copy[++l]);
- rc = mkdir(copy, mode);
- if (rc && errno != EEXIST) {
- syslog(LOG_ERR, "in move_real_workdir, mkdir '%s' failed: %m", copy);
- return -1;
- }
- }
}
}
}
workdirfd = -1;
rc = renameat(AT_FDCWD, workdir, AT_FDCWD, dest);
if (rc) {
- syslog(LOG_ERR, "in move_real_workdir, renameat failed %s -> %s: %m", workdir, dest);
+ ERROR("in move_real_workdir, renameat failed %s -> %s: %m", workdir, dest);
return -1;
}
rp = realpath(dest, NULL);
if (!rp) {
- syslog(LOG_ERR, "realpath failed for %s", dest);
+ ERROR("realpath failed for %s", dest);
return -1;
}
rc = move_real_workdir(rp, parents, force);