util: add generic calls for prefixing a root directory to a path
So far a number of utilities implemented their own calls for this, unify them in prefix_root() and prefix_roota(). The former uses heap memory, the latter allocates from the stack via alloca(). Port over most users of a --root= logic.
This commit is contained in:
@@ -36,12 +36,13 @@
|
||||
|
||||
static int files_add(Hashmap *h, const char *root, const char *path, const char *suffix) {
|
||||
_cleanup_closedir_ DIR *dir = NULL;
|
||||
char *dirpath;
|
||||
const char *dirpath;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
assert(suffix);
|
||||
|
||||
dirpath = strjoina(root ? root : "", path);
|
||||
dirpath = prefix_roota(root, path);
|
||||
|
||||
dir = opendir(dirpath);
|
||||
if (!dir) {
|
||||
@@ -53,7 +54,6 @@ static int files_add(Hashmap *h, const char *root, const char *path, const char
|
||||
for (;;) {
|
||||
struct dirent *de;
|
||||
char *p;
|
||||
int r;
|
||||
|
||||
errno = 0;
|
||||
de = readdir(dir);
|
||||
|
||||
@@ -793,3 +793,37 @@ int fsck_exists(const char *fstype) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *prefix_root(const char *root, const char *path) {
|
||||
char *n, *p;
|
||||
size_t l;
|
||||
|
||||
/* If root is passed, prefixes path with it. Otherwise returns
|
||||
* it as is. */
|
||||
|
||||
assert(path);
|
||||
|
||||
/* First, drop duplicate prefixing slashes from the path */
|
||||
while (path[0] == '/' && path[1] == '/')
|
||||
path++;
|
||||
|
||||
if (isempty(root) || path_equal(root, "/"))
|
||||
return strdup(path);
|
||||
|
||||
l = strlen(root) + 1 + strlen(path) + 1;
|
||||
|
||||
n = new(char, l);
|
||||
if (!n)
|
||||
return NULL;
|
||||
|
||||
p = stpcpy(n, root);
|
||||
|
||||
while (p > n && p[-1] == '/')
|
||||
p--;
|
||||
|
||||
if (path[0] != '/')
|
||||
*(p++) = '/';
|
||||
|
||||
strcpy(p, path);
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -73,3 +73,30 @@ int fsck_exists(const char *fstype);
|
||||
/* Same as PATH_FOREACH_PREFIX but also includes the specified path itself */
|
||||
#define PATH_FOREACH_PREFIX_MORE(prefix, path) \
|
||||
for (char *_slash = ({ path_kill_slashes(strcpy(prefix, path)); if (streq(prefix, "/")) prefix[0] = 0; strrchr(prefix, 0); }); _slash && ((*_slash = 0), true); _slash = strrchr((prefix), '/'))
|
||||
|
||||
char *prefix_root(const char *root, const char *path);
|
||||
|
||||
/* Similar to prefix_root(), but returns an alloca() buffer, or
|
||||
* possibly a const pointer into the path parameter */
|
||||
#define prefix_roota(root, path) \
|
||||
({ \
|
||||
const char* _path = (path), *_root = (root), *_ret; \
|
||||
char *_p, *_n; \
|
||||
size_t _l; \
|
||||
while (_path[0] == '/' && _path[1] == '/') \
|
||||
_path ++; \
|
||||
if (isempty(_root) || path_equal(_root, "/")) \
|
||||
_ret = _path; \
|
||||
else { \
|
||||
_l = strlen(_root) + 1 + strlen(_path) + 1; \
|
||||
_n = alloca(_l); \
|
||||
_p = stpcpy(_n, _root); \
|
||||
while (_p > _n && _p[-1] == '/') \
|
||||
_p--; \
|
||||
if (_path[0] != '/') \
|
||||
*(_p++) = '/'; \
|
||||
strcpy(_p, _path); \
|
||||
_ret = _n; \
|
||||
} \
|
||||
_ret; \
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user