X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fwgtpkg-workdir.c;h=ea376666d0829664e1c1cd0284490057865d29f6;hb=d0cb2a7a1e068a38b4a0c3216ccdbce0e33ecffb;hp=59da1e6ac7ed2cdc505eaece01ae34e36aa6893c;hpb=9ab266df6642c6e930e03b3024d7c3d53ef88bbc;p=src%2Fapp-framework-main.git diff --git a/src/wgtpkg-workdir.c b/src/wgtpkg-workdir.c index 59da1e6..ea37666 100644 --- a/src/wgtpkg-workdir.c +++ b/src/wgtpkg-workdir.c @@ -1,5 +1,7 @@ /* - Copyright 2015 IoT.bzh + Copyright (C) 2015-2018 IoT.bzh + + author: José Bollo Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -18,109 +20,55 @@ #include #include +#include +#include #include -#include #include #include #include #include #include +#include #include "verbose.h" -#include "wgtpkg.h" +#include "wgtpkg-workdir.h" +#include "utils-dir.h" -static int mode = 0755; +static const mode_t 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); workdir[0] = 0; } -static int set_real_workdir(const char *name, int create) +static void put_workdir(int fd, const char *name, size_t length) +{ + /* close the previous directory if any */ + if (workdirfd >= 0) + close(workdirfd); + + /* copy the name and the fd if existing */ + if (fd < 0) { + workdir[0] = '.'; + workdir[1] = 0; + workdirfd = AT_FDCWD; + } else { + + assert(length < sizeof workdir); + memcpy(workdir, name, 1 + length); + workdirfd = fd; + } +} + +int set_workdir(const char *name, int create) { int rc, dirfd; size_t length; @@ -128,88 +76,75 @@ static int set_real_workdir(const char *name, int create) /* 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; } + /* check if . */ + if (length == 1 && name[0] == '.') { + put_workdir(AT_FDCWD, name, length); + return 0; + } + /* opens the directory */ - dirfd = openat(AT_FDCWD, name, O_DIRECTORY|O_RDONLY); + dirfd = openat(AT_FDCWD, name, O_PATH|O_DIRECTORY|O_RDONLY); if (dirfd < 0) { - if (!create || errno != ENOENT) { - syslog(LOG_ERR, "no workdir %s", name); + if (errno != ENOENT) { + ERROR("error while opening workdir %s: %m", name); return -1; } - rc = mkdir(name, mode); + if (!create) { + ERROR("workdir %s doesn't exist", name); + return -1; + } + rc = mkdirat(AT_FDCWD, 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); + dirfd = openat(AT_FDCWD, name, O_PATH|O_DIRECTORY|O_RDONLY); if (dirfd < 0) { - syslog(LOG_ERR, "can't open workdir %s", name); + ERROR("can't open workdir %s", name); return -1; } } - /* close the previous directory if any */ - if (workdirfd >= 0) - close(workdirfd); - workdirfd = dirfd; - memcpy(workdir, name, 1+length); + /* record new workdir */ + put_workdir(dirfd, name, length); return 0; } -int set_workdir(const char *name, int create) -{ - char *rp; - int rc; - - if (name[0] == '/') - return set_real_workdir(name, create); - - rp = realpath(name, NULL); - if (!rp) { - syslog(LOG_ERR, "realpath failed for %s", name); - return -1; - } - rc = set_real_workdir(rp, create); - free(rp); - return rc; -} - -static int make_real_workdir_base(const char *root, const char *prefix, int reuse) +int make_workdir(const char *root, const char *prefix, int reuse) { int i, n, r, l; + put_workdir(AT_FDCWD, ".", 1); + n = snprintf(workdir, sizeof workdir, "%s/%s", root, prefix); - if (n >= sizeof workdir) { - syslog(LOG_ERR, "workdir prefix too long"); + if (n >= (int)sizeof workdir) { + ERROR("workdir prefix too long"); errno = EINVAL; return -1; } r = (int)(sizeof workdir) - n; - if (workdirfd >= 0) - close(workdirfd); - workdirfd = -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); + l = snprintf(workdir + n, (unsigned)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 (!mkdirat(AT_FDCWD, 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) @@ -217,7 +152,7 @@ static int make_real_workdir_base(const char *root, const char *prefix, int reus } 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; } @@ -225,39 +160,17 @@ static int make_real_workdir_base(const char *root, const char *prefix, int reus return 0; } -int make_workdir_base(const char *root, const char *prefix, int reuse) +int move_workdir(const char *dest, int parents, int force) { - char *rp; int rc; - - if (root[0] == '/') - return make_real_workdir_base(root, prefix, reuse); - - rp = realpath(root, NULL); - if (!rp) { - syslog(LOG_ERR, "realpath failed for %s", root); - return -1; - } - rc = make_real_workdir_base(rp, prefix, reuse); - free(rp); - return rc; -} - -int make_workdir(int reuse) -{ - return make_workdir_base(".", "PACK", reuse); -} - -static int move_real_workdir(const char *dest, int parents, int force) -{ - int rc, len, l; + size_t 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; } @@ -266,29 +179,29 @@ static int move_real_workdir(const char *dest, int parents, int force) 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_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_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_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_workdir, can't remove dir %s", dest); return rc; } } else { /* check parent of dest */ iter = strrchr(dest, '/'); - len = iter ? iter - dest : 0; + len = iter ? (size_t)(iter - dest) : 0; if (len) { /* is parent existing? */ copy = strndupa(dest, len); @@ -296,45 +209,17 @@ static int move_real_workdir(const char *dest, int parents, int force) 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_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_workdir, parent directory '%s' not found: %m", copy); + return -1; + } else if (create_directory(copy, dirmode, 1)) { + ERROR("in move_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; - } - } } } } @@ -344,28 +229,10 @@ static int move_real_workdir(const char *dest, int parents, int force) 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_workdir, renameat failed %s -> %s: %m", workdir, dest); return -1; } - return set_real_workdir(dest, 0); -} - -int move_workdir(const char *dest, int parents, int force) -{ - char *rp; - int rc; - - if (dest[0] == '/') - return move_real_workdir(dest, parents, force); - - rp = realpath(dest, NULL); - if (!rp) { - syslog(LOG_ERR, "realpath failed for %s", dest); - return -1; - } - rc = move_real_workdir(rp, parents, force); - free(rp); - return rc; + return set_workdir(dest, 0); }