/***
This file is part of systemd.
Copyright 2014 Lennart Poettering
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "sd-path.h"
#include "alloc-util.h"
#include "architecture.h"
#include "fd-util.h"
#include "fileio.h"
#include "missing.h"
#include "path-util.h"
#include "string-util.h"
#include "strv.h"
#include "user-util.h"
#include "util.h"
if (envname) {
const char *e;
e = secure_getenv(envname);
if (e && path_is_absolute(e)) {
*ret = e;
return 0;
}
}
if (fallback) {
return 0;
}
return -ENXIO;
}
static int from_home_dir(const char *envname, const char *suffix, char **buffer, const char **ret) {
_cleanup_free_ char *h = NULL;
int r;
if (envname) {
const char *e = NULL;
e = secure_getenv(envname);
if (e && path_is_absolute(e)) {
*ret = e;
return 0;
}
}
r = get_home_dir(&h);
if (r < 0)
return r;
if (endswith(h, "/"))
else
if (!cc)
return -ENOMEM;
return 0;
}
_cleanup_free_ char *b = NULL;
size_t n;
int r;
if (r < 0)
return r;
if (!f) {
goto fallback;
return -errno;
}
/* This is an awful parse, but it follows closely what
* xdg-user-dirs does upstream */
char *l, *p, *e;
continue;
p = l + n;
p += strspn(p, WHITESPACE);
if (*p != '=')
continue;
p++;
p += strspn(p, WHITESPACE);
if (*p != '"')
continue;
p++;
e = strrchr(p, '"');
if (!e)
continue;
*e = 0;
/* Three syntaxes permitted: relative to $HOME, $HOME itself, and absolute path */
if (startswith(p, "$HOME/")) {
_cleanup_free_ char *h = NULL;
char *cc;
r = get_home_dir(&h);
if (r < 0)
return r;
if (!cc)
return -ENOMEM;
return 0;
} else if (streq(p, "$HOME")) {
r = get_home_dir(buffer);
if (r < 0)
return r;
return 0;
} else if (path_is_absolute(p)) {
char *copy;
if (!copy)
return -ENOMEM;
return 0;
}
}
_cleanup_free_ char *h = NULL;
char *cc;
r = get_home_dir(&h);
if (r < 0)
return r;
if (!cc)
return -ENOMEM;
} else {
r = get_home_dir(buffer);
if (r < 0)
return r;
}
return 0;
}
int r;
switch (type) {
case SD_PATH_TEMPORARY:
case SD_PATH_TEMPORARY_LARGE:
case SD_PATH_SYSTEM_BINARIES:
return 0;
case SD_PATH_SYSTEM_INCLUDE:
return 0;
return 0;
return 0;
case SD_PATH_SYSTEM_SHARED:
return 0;
return 0;
return 0;
*ret = "/etc";
return 0;
case SD_PATH_SYSTEM_RUNTIME:
*ret = "/run";
return 0;
return 0;
return 0;
return 0;
return 0;
return 0;
case SD_PATH_USER_BINARIES:
case SD_PATH_USER_SHARED:
case SD_PATH_USER_RUNTIME:
case SD_PATH_USER_STATE_CACHE:
case SD_PATH_USER:
r = get_home_dir(buffer);
if (r < 0)
return r;
return 0;
case SD_PATH_USER_DOCUMENTS:
case SD_PATH_USER_MUSIC:
case SD_PATH_USER_PICTURES:
case SD_PATH_USER_VIDEOS:
case SD_PATH_USER_DOWNLOAD:
case SD_PATH_USER_PUBLIC:
case SD_PATH_USER_TEMPLATES:
case SD_PATH_USER_DESKTOP:
}
return -EOPNOTSUPP;
}
const char *ret;
int r;
_cleanup_strv_free_ char **l = NULL;
if (r < 0)
return r;
if (!buffer)
return -ENOMEM;
return 0;
}
if (r < 0)
return r;
if (!suffix) {
if (!buffer) {
if (!buffer)
return -ENOMEM;
}
return 0;
}
else
if (!cc)
return -ENOMEM;
return 0;
}
static int search_from_environment(
char ***list,
const char *env_home,
const char *home_suffix,
const char *env_search,
bool env_search_sufficient,
const char *first, ...) {
const char *e;
char *h = NULL;
char **l = NULL;
int r;
if (env_search) {
e = secure_getenv(env_search);
if (e) {
l = strv_split(e, ":");
if (!l)
return -ENOMEM;
if (env_search_sufficient) {
*list = l;
return 0;
}
}
}
if (!l && first) {
if (!l)
return -ENOMEM;
}
if (env_home) {
e = secure_getenv(env_home);
if (e && path_is_absolute(e)) {
h = strdup(e);
if (!h) {
strv_free(l);
return -ENOMEM;
}
}
}
if (!h && home_suffix) {
e = secure_getenv("HOME");
if (e && path_is_absolute(e)) {
if (endswith(e, "/"))
h = strappend(e, home_suffix);
else
if (!h) {
strv_free(l);
return -ENOMEM;
}
}
}
if (h) {
r = strv_consume_prepend(&l, h);
if (r < 0) {
strv_free(l);
return -ENOMEM;
}
}
*list = l;
return 0;
}
switch(type) {
case SD_PATH_SEARCH_BINARIES:
return search_from_environment(list,
NULL,
"PATH",
true,
#ifdef HAVE_SPLIT_USR
"/sbin",
"/bin",
#endif
NULL);
return search_from_environment(list,
NULL,
NULL,
false,
#ifdef HAVE_SPLIT_USR
"/lib",
#endif
NULL);
return search_from_environment(list,
NULL,
".local/lib/" LIB_ARCH_TUPLE,
"LD_LIBRARY_PATH",
true,
#ifdef HAVE_SPLIT_USR
#endif
NULL);
case SD_PATH_SEARCH_SHARED:
return search_from_environment(list,
"XDG_DATA_HOME",
"XDG_DATA_DIRS",
false,
NULL);
return search_from_environment(list,
NULL,
NULL,
NULL,
false,
NULL);
return search_from_environment(list,
NULL,
NULL,
NULL,
false,
NULL);
return search_from_environment(list,
"XDG_CONFIG_HOME",
".config",
"XDG_CONFIG_DIRS",
false,
"/etc",
NULL);
}
return -EOPNOTSUPP;
}
char **l, **i, **j, **n;
int r;
char *p;
if (r < 0)
return r;
l = new(char*, 2);
if (!l) {
free(p);
return -ENOMEM;
}
l[0] = p;
l[1] = NULL;
*paths = l;
return 0;
}
r = get_search(type, &l);
if (r < 0)
return r;
if (!suffix) {
*paths = l;
return 0;
}
if (!n) {
strv_free(l);
return -ENOMEM;
}
j = n;
STRV_FOREACH(i, l) {
if (endswith(*i, "/"))
else
if (!*j) {
strv_free(l);
strv_free(n);
return -ENOMEM;
}
j++;
}
*j = NULL;
*paths = n;
return 0;
}