path-util: add new path_join_many() API

This commit is contained in:
Lennart Poettering
2018-11-29 20:03:56 +01:00
parent de06c0cf77
commit cd8194a389
3 changed files with 105 additions and 0 deletions
+64
View File
@@ -495,6 +495,70 @@ char* path_join(const char *root, const char *path, const char *rest) {
rest && rest[0] == '/' ? rest+1 : rest);
}
char* path_join_many_internal(const char *first, ...) {
char *joined, *q;
const char *p;
va_list ap;
bool slash;
size_t sz;
assert(first);
/* Joins all listed strings until NULL and places an "/" between them unless the strings end/begin already with
* one so that it is unnecessary. Note that "/" which are already duplicate won't be removed. The string
* returned is hence always equal or longer than the sum of the lengths of each individual string.
*
* Note: any listed empty string is simply skipped. This can be useful for concatenating strings of which some
* are optional.
*
* Examples:
*
* path_join_many("foo", "bar") → "foo/bar"
* path_join_many("foo/", "bar") → "foo/bar"
* path_join_many("", "foo", "", "bar", "") → "foo/bar" */
sz = strlen(first);
va_start(ap, first);
while ((p = va_arg(ap, char*))) {
if (*p == 0) /* Skip empty items */
continue;
sz += 1 + strlen(p);
}
va_end(ap);
joined = new(char, sz + 1);
if (!joined)
return NULL;
if (first[0] != 0) {
q = stpcpy(joined, first);
slash = endswith(first, "/");
} else {
/* Skip empty items */
joined[0] = 0;
q = joined;
slash = true; /* no need to generate a slash anymore */
}
va_start(ap, first);
while ((p = va_arg(ap, char*))) {
if (*p == 0) /* Skip empty items */
continue;
if (!slash && p[0] != '/')
*(q++) = '/';
q = stpcpy(q, p);
slash = endswith(p, "/");
}
va_end(ap);
return joined;
}
int find_binary(const char *name, char **ret) {
int last_error, r;
const char *p;