path: add new "systemd-path" utility for querying paths described in file-hierarchy(7)

This new tool is based on "sd-path", a new (so far unexported) API for
libsystemd, that can hopefully grow into a workable API covering /opt
and more one day.
This commit is contained in:
Lennart Poettering 2014-07-02 12:23:36 +02:00
parent cd4ba18a84
commit 9a00f57a5b
14 changed files with 1157 additions and 11 deletions

1
.gitignore vendored
View File

@ -86,6 +86,7 @@
/systemd-networkd-wait-online
/systemd-notify
/systemd-nspawn
/systemd-path
/systemd-quotacheck
/systemd-random-seed
/systemd-rc-local-generator

View File

@ -74,6 +74,7 @@ MANPAGES += \
man/systemd-machine-id-setup.1 \
man/systemd-notify.1 \
man/systemd-nspawn.1 \
man/systemd-path.1 \
man/systemd-remount-fs.service.8 \
man/systemd-run.1 \
man/systemd-shutdownd.service.8 \
@ -1619,6 +1620,7 @@ EXTRA_DIST += \
man/systemd-networkd.service.xml \
man/systemd-notify.xml \
man/systemd-nspawn.xml \
man/systemd-path.xml \
man/systemd-quotacheck.service.xml \
man/systemd-random-seed.service.xml \
man/systemd-readahead-replay.service.xml \

View File

@ -187,6 +187,8 @@ AM_CPPFLAGS = \
-DPOLKIT_AGENT_BINARY_PATH=\"$(bindir)/pkttyagent\" \
-DQUOTACHECK=\"$(QUOTACHECK)\" \
-DKEXEC=\"$(KEXEC)\" \
-DLIBDIR=\"$(libdir)\" \
-DROOTLIBDIR=\"$(rootlibdir)\" \
-I $(top_srcdir)/src \
-I $(top_builddir)/src/shared \
-I $(top_srcdir)/src/shared \
@ -344,7 +346,8 @@ bin_PROGRAMS = \
systemd-detect-virt \
systemd-delta \
systemd-analyze \
systemd-run
systemd-run \
systemd-path
dist_bin_SCRIPTS = \
src/kernel-install/kernel-install
@ -2096,6 +2099,14 @@ systemd_notify_LDADD = \
libsystemd-internal.la \
libsystemd-shared.la
# ------------------------------------------------------------------------------
systemd_path_SOURCES = \
src/path/path.c
systemd_path_LDADD = \
libsystemd-internal.la \
libsystemd-shared.la
# ------------------------------------------------------------------------------
systemd_ask_password_SOURCES = \
src/ask-password/ask-password.c
@ -2221,6 +2232,7 @@ libsystemd_internal_la_SOURCES = \
src/systemd/sd-login.h \
src/systemd/sd-id128.h \
src/systemd/sd-daemon.h \
src/systemd/sd-path.h \
src/libsystemd/sd-bus/sd-bus.c \
src/libsystemd/sd-bus/bus-control.c \
src/libsystemd/sd-bus/bus-control.h \
@ -2274,7 +2286,8 @@ libsystemd_internal_la_SOURCES = \
src/libsystemd/sd-rtnl/rtnl-util.c \
src/libsystemd/sd-id128/sd-id128.c \
src/libsystemd/sd-daemon/sd-daemon.c \
src/libsystemd/sd-login/sd-login.c
src/libsystemd/sd-login/sd-login.c \
src/libsystemd/sd-path/sd-path.c
nodist_libsystemd_internal_la_SOURCES = \
src/libsystemd/libsystemd.sym \
@ -2377,7 +2390,8 @@ pkginclude_HEADERS += \
src/systemd/sd-utf8.h \
src/systemd/sd-event.h \
src/systemd/sd-rtnl.h \
src/systemd/sd-resolve.h
src/systemd/sd-resolve.h \
src/systemd/sd-path.h
endif
lib_LTLIBRARIES += \

View File

@ -62,6 +62,11 @@
subset of these specifications that defines more
strictly the suggestions and restrictions systemd
makes on the file system hierarchy.</para>
<para>Many of the paths described here are queriable
with the
<citerefentry><refentrytitle>systemd-path</refentrytitle><manvolnum>1</manvolnum></citerefentry>
tool.</para>
</refsect1>
<refsect1>
@ -296,8 +301,8 @@
<varlistentry>
<term><filename>/usr/lib/<replaceable>arch-id</replaceable></filename></term>
<listitem><para>Location for placing
dynamic libraries, called <varname>$libdir</varname>.
The architecture identifier to use, is defined on <ulink
dynamic libraries, also called <varname>$libdir</varname>.
The architecture identifier to use is defined on <ulink
url="https://wiki.debian.org/Multiarch/Tuples">Multiarch Architecture Specifiers (Tuples)</ulink>
list. Legacy locations of <varname>$libdir</varname> are
<filename>/usr/lib</filename>,
@ -309,7 +314,10 @@
<varname>$libdir</varname> for the
primary architecture of the system,
invoke:
<programlisting># pkg-config --variable=libdir systemd</programlisting></para></listitem>
<programlisting># pkg-config --variable=libdir systemd</programlisting> or
<programlisting># systemd-path system-library-arch</programlisting>
</para></listitem>
</varlistentry>
<varlistentry>
@ -621,7 +629,10 @@
of these directories are also standardized (though
more weakly) by the <ulink
url="http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html">XDG
Base Directory Specification</ulink>.</para>
Base Directory Specification</ulink>. Additional
locations for high-level user resources are defined by
<ulink
url="http://www.freedesktop.org/wiki/Software/xdg-user-dirs/">xdg-user-dirs</ulink>.</para>
<variablelist>
<varlistentry>
@ -952,6 +963,7 @@
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>hier</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-path</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-boot-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sysctl.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>,

111
man/systemd-path.xml Normal file
View File

@ -0,0 +1,111 @@
<?xml version='1.0'?> <!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
This file is part of systemd.
Copyright 2014 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
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/>.
-->
<refentry id="systemd-path"
xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>systemd-path</title>
<productname>systemd</productname>
<authorgroup>
<author>
<contrib>Developer</contrib>
<firstname>Lennart</firstname>
<surname>Poettering</surname>
<email>lennart@poettering.net</email>
</author>
</authorgroup>
</refentryinfo>
<refmeta>
<refentrytitle>systemd-path</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>systemd-path</refname>
<refpurpose>List and query system and user paths</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>systemd-path <arg choice="opt" rep="repeat">OPTIONS</arg> <arg choice="opt" rep="repeat">NAME</arg></command>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><command>systemd-path</command> may be used to
query system and user paths. The tool makes many of
the paths described in
<citerefentry><refentrytitle>file-hierarchy</refentrytitle><manvolnum>7</manvolnum></citerefentry>
queriable.</para>
<para>When invoked without arguments a list of known
paths and their current values is shown. When at least
one argument is passed the path with this is name is
queried and its value shown. The variables whose name
begins with <literal>search-</literal> don't refer to
individual paths, but instead a to a list of
colon-separated search paths, in their order of
precedence.</para>
</refsect1>
<refsect1>
<title>Options</title>
<para>The following options are understood:</para>
<variablelist>
<varlistentry>
<term><option>--suffix=</option></term>
<listitem><para>The printed paths are
suffixed by the specified
string.</para></listitem>
</varlistentry>
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
</variablelist>
</refsect1>
<refsect1>
<title>Exit status</title>
<para>On success, 0 is returned, a non-zero failure
code otherwise.</para>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>file-hierarchy</refentrytitle><manvolnum>7</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View File

@ -0,0 +1 @@
../Makefile

View File

@ -0,0 +1,626 @@
/***
This file is part of systemd.
Copyright 2014 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
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 "util.h"
#include "architecture.h"
#include "path-util.h"
#include "strv.h"
#include "sd-path.h"
static int from_environment(const char *envname, const char *fallback, const char **ret) {
assert(ret);
if (envname) {
const char *e;
e = secure_getenv(envname);
if (e && path_is_absolute(e)) {
*ret = e;
return 0;
}
}
if (fallback) {
*ret = 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;
char *cc = NULL;
int r;
assert(suffix);
assert(buffer);
assert(ret);
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, "/"))
cc = strappend(h, suffix);
else
cc = strjoin(h, "/", suffix, NULL);
if (!cc)
return -ENOMEM;
*buffer = cc;
*ret = cc;
return 0;
}
static int from_user_dir(const char *field, char **buffer, const char **ret) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *b = NULL;
const char *fn = NULL;
char line[LINE_MAX];
size_t n;
int r;
assert(field);
assert(buffer);
assert(ret);
r = from_home_dir(NULL, ".config/user-dirs.dirs", &b, &fn);
if (r < 0)
return r;
f = fopen(fn, "re");
if (!f) {
if (errno == ENOENT)
goto fallback;
return -errno;
}
/* This is an awful parse, but it follows closely what
* xdg-user-dirs does upstream */
n = strlen(field);
FOREACH_LINE(line, f, return -errno) {
char *l, *p, *e;
l = strstrip(line);
if (!strneq(l, field, n))
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;
cc = strappend(h, p+5);
if (!cc)
return -ENOMEM;
*buffer = cc;
*ret = cc;
return 0;
} else if (streq(p, "$HOME")) {
r = get_home_dir(buffer);
if (r < 0)
return r;
*ret = *buffer;
return 0;
} else if (path_is_absolute(p)) {
char *copy;
copy = strdup(p);
if (!copy)
return -ENOMEM;
*buffer = copy;
*ret = copy;
return 0;
}
}
fallback:
/* The desktop directory defaults to $HOME/Desktop, the others to $HOME */
if (streq(field, "XDG_DESKTOP_DIR")) {
_cleanup_free_ char *h = NULL;
char *cc;
r = get_home_dir(&h);
if (r < 0)
return r;
cc = strappend(h, "/Desktop");
if (!cc)
return -ENOMEM;
*buffer = cc;
*ret = cc;
} else {
r = get_home_dir(buffer);
if (r < 0)
return r;
*ret = *buffer;
}
return 0;
}
static int get_path(uint64_t type, char **buffer, const char **ret) {
int r;
assert(buffer);
assert(ret);
switch (type) {
case SD_PATH_TEMPORARY:
return from_environment("TMPDIR", "/tmp", ret);
case SD_PATH_TEMPORARY_LARGE:
return from_environment("TMPDIR", "/var/tmp", ret);
case SD_PATH_SYSTEM_BINARIES:
*ret = "/usr/bin";
return 0;
case SD_PATH_SYSTEM_INCLUDE:
*ret = "/usr/include";
return 0;
case SD_PATH_SYSTEM_LIBRARY_PRIVATE:
*ret = "/usr/lib";
return 0;
case SD_PATH_SYSTEM_LIBRARY_ARCH:
*ret = LIBDIR;
return 0;
case SD_PATH_SYSTEM_SHARED:
*ret = "/usr/share";
return 0;
case SD_PATH_SYSTEM_CONFIGURATION_FACTORY:
*ret = "/usr/share/factory/etc";
return 0;
case SD_PATH_SYSTEM_STATE_FACTORY:
*ret = "/usr/share/factory/var";
return 0;
case SD_PATH_SYSTEM_CONFIGURATION:
*ret = "/etc";
return 0;
case SD_PATH_SYSTEM_RUNTIME:
*ret = "/run";
return 0;
case SD_PATH_SYSTEM_RUNTIME_LOGS:
*ret = "/run/log";
return 0;
case SD_PATH_SYSTEM_STATE_PRIVATE:
*ret = "/var/lib";
return 0;
case SD_PATH_SYSTEM_STATE_LOGS:
*ret = "/var/log";
return 0;
case SD_PATH_SYSTEM_STATE_CACHE:
*ret = "/var/cache";
return 0;
case SD_PATH_SYSTEM_STATE_SPOOL:
*ret = "/var/spool";
return 0;
case SD_PATH_USER_BINARIES:
return from_home_dir(NULL, ".local/bin", buffer, ret);
case SD_PATH_USER_LIBRARY_PRIVATE:
return from_home_dir(NULL, ".local/lib", buffer, ret);
case SD_PATH_USER_LIBRARY_ARCH:
return from_home_dir(NULL, ".local/lib/" ARCH_TUPLE, buffer, ret);
case SD_PATH_USER_SHARED:
return from_home_dir("XDG_DATA_HOME", ".local/share", buffer, ret);
case SD_PATH_USER_CONFIGURATION:
return from_home_dir("XDG_CONFIG_HOME", ".config", buffer, ret);
case SD_PATH_USER_RUNTIME:
return from_environment("XDG_RUNTIME_DIR", NULL, ret);
case SD_PATH_USER_STATE_CACHE:
return from_home_dir("XDG_CACHE_HOME", ".cache", buffer, ret);
case SD_PATH_USER:
r = get_home_dir(buffer);
if (r < 0)
return r;
*ret = *buffer;
return 0;
case SD_PATH_USER_DOCUMENTS:
return from_user_dir("XDG_DOCUMENTS_DIR", buffer, ret);
case SD_PATH_USER_MUSIC:
return from_user_dir("XDG_MUSIC_DIR", buffer, ret);
case SD_PATH_USER_PICTURES:
return from_user_dir("XDG_PICTURES_DIR", buffer, ret);
case SD_PATH_USER_VIDEOS:
return from_user_dir("XDG_VIDEOS_DIR", buffer, ret);
case SD_PATH_USER_DOWNLOAD:
return from_user_dir("XDG_DOWNLOAD_DIR", buffer, ret);
case SD_PATH_USER_PUBLIC:
return from_user_dir("XDG_PUBLICSHARE_DIR", buffer, ret);
case SD_PATH_USER_TEMPLATES:
return from_user_dir("XDG_TEMPLATES_DIR", buffer, ret);
case SD_PATH_USER_DESKTOP:
return from_user_dir("XDG_DESKTOP_DIR", buffer, ret);
}
return -ENOTSUP;
}
int sd_path_home(uint64_t type, const char *suffix, char **path) {
char *buffer = NULL, *cc;
const char *ret;
int r;
assert_return(path, -EINVAL);
if (IN_SET(type,
SD_PATH_SEARCH_BINARIES,
SD_PATH_SEARCH_LIBRARY_PRIVATE,
SD_PATH_SEARCH_LIBRARY_ARCH,
SD_PATH_SEARCH_SHARED,
SD_PATH_SEARCH_CONFIGURATION_FACTORY,
SD_PATH_SEARCH_STATE_FACTORY,
SD_PATH_SEARCH_CONFIGURATION)) {
_cleanup_strv_free_ char **l = NULL;
r = sd_path_search(type, suffix, &l);
if (r < 0)
return r;
buffer = strv_join(l, ":");
if (!buffer)
return -ENOMEM;
*path = buffer;
return 0;
}
r = get_path(type, &buffer, &ret);
if (r < 0)
return r;
if (!suffix) {
if (!buffer) {
buffer = strdup(ret);
if (!buffer)
return -ENOMEM;
}
*path = buffer;
return 0;
}
suffix += strspn(suffix, "/");
if (endswith(ret, "/"))
cc = strappend(ret, suffix);
else
cc = strjoin(ret, "/", suffix, NULL);
free(buffer);
if (!cc)
return -ENOMEM;
*path = cc;
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;
assert(list);
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) {
va_list ap;
va_start(ap, first);
l = strv_new_ap(first, ap);
va_end(ap);
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
h = strjoin(e, "/", home_suffix, NULL);
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;
}
static int get_search(uint64_t type, char ***list) {
assert(list);
switch(type) {
case SD_PATH_SEARCH_BINARIES:
return search_from_environment(list,
NULL,
".local/bin",
"PATH",
true,
"/usr/local/sbin",
"/usr/local/bin",
"/usr/sbin",
"/usr/bin",
#ifdef HAVE_SPLIT_USR
"/sbin",
"/bin",
#endif
NULL);
case SD_PATH_SEARCH_LIBRARY_PRIVATE:
return search_from_environment(list,
NULL,
".local/lib",
NULL,
false,
"/usr/local/lib",
"/usr/lib",
#ifdef HAVE_SPLIT_USR
"/lib",
#endif
NULL);
case SD_PATH_SEARCH_LIBRARY_ARCH:
return search_from_environment(list,
NULL,
".local/lib/" ARCH_TUPLE,
"LD_LIBRARY_PATH",
true,
LIBDIR,
#ifdef HAVE_SPLIT_USR
ROOTLIBDIR,
#endif
NULL);
case SD_PATH_SEARCH_SHARED:
return search_from_environment(list,
"XDG_DATA_HOME",
".local/share",
"XDG_DATA_DIRS",
false,
"/usr/local/share",
"/usr/share",
NULL);
case SD_PATH_SEARCH_CONFIGURATION_FACTORY:
return search_from_environment(list,
NULL,
NULL,
NULL,
false,
"/usr/local/share/factory/etc",
"/usr/share/factory/etc",
NULL);
case SD_PATH_SEARCH_STATE_FACTORY:
return search_from_environment(list,
NULL,
NULL,
NULL,
false,
"/usr/local/share/factory/var",
"/usr/share/factory/var",
NULL);
case SD_PATH_SEARCH_CONFIGURATION:
return search_from_environment(list,
"XDG_CONFIG_HOME",
".config",
"XDG_CONFIG_DIRS",
false,
"/etc",
NULL);
}
return -ENOTSUP;
}
int sd_path_search(uint64_t type, const char *suffix, char ***paths) {
char **l, **i, **j, **n;
int r;
assert_return(paths, -EINVAL);
if (!IN_SET(type,
SD_PATH_SEARCH_BINARIES,
SD_PATH_SEARCH_LIBRARY_PRIVATE,
SD_PATH_SEARCH_LIBRARY_ARCH,
SD_PATH_SEARCH_SHARED,
SD_PATH_SEARCH_CONFIGURATION_FACTORY,
SD_PATH_SEARCH_STATE_FACTORY,
SD_PATH_SEARCH_CONFIGURATION)) {
char *p;
r = sd_path_home(type, suffix, &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;
}
n = new(char*, strv_length(l)+1);
if (!n) {
strv_free(l);
return -ENOMEM;
}
j = n;
STRV_FOREACH(i, l) {
if (endswith(*i, "/"))
*j = strappend(*i, suffix);
else
*j = strjoin(*i, "/", suffix, NULL);
if (!*j) {
strv_free(l);
strv_free(n);
return -ENOMEM;
}
j++;
}
*j = NULL;
*paths = n;
return 0;
}

1
src/path/Makefile Symbolic link
View File

@ -0,0 +1 @@
../Makefile

208
src/path/path.c Normal file
View File

@ -0,0 +1,208 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2014 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
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 <stdio.h>
#include <getopt.h>
#include <error.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "sd-path.h"
#include "build.h"
#include "macro.h"
#include "util.h"
#include "log.h"
static const char *arg_suffix = NULL;
static const char* const path_table[_SD_PATH_MAX] = {
[SD_PATH_TEMPORARY] = "temporary",
[SD_PATH_TEMPORARY_LARGE] = "temporary-large",
[SD_PATH_SYSTEM_BINARIES] = "system-binaries",
[SD_PATH_SYSTEM_INCLUDE] = "system-include",
[SD_PATH_SYSTEM_LIBRARY_PRIVATE] = "system-library-private",
[SD_PATH_SYSTEM_LIBRARY_ARCH] = "system-library-arch",
[SD_PATH_SYSTEM_SHARED] = "system-shared",
[SD_PATH_SYSTEM_CONFIGURATION_FACTORY] = "system-configuration-factory",
[SD_PATH_SYSTEM_STATE_FACTORY] = "system-state-factory",
[SD_PATH_SYSTEM_CONFIGURATION] = "system-configuration",
[SD_PATH_SYSTEM_RUNTIME] = "system-runtime",
[SD_PATH_SYSTEM_RUNTIME_LOGS] = "system-runtime-logs",
[SD_PATH_SYSTEM_STATE_PRIVATE] = "system-state-private",
[SD_PATH_SYSTEM_STATE_LOGS] = "system-state-logs",
[SD_PATH_SYSTEM_STATE_CACHE] = "system-state-cache",
[SD_PATH_SYSTEM_STATE_SPOOL] = "system-state-spool",
[SD_PATH_USER_BINARIES] = "user-binaries",
[SD_PATH_USER_LIBRARY_PRIVATE] = "user-library-private",
[SD_PATH_USER_LIBRARY_ARCH] = "user-library-arch",
[SD_PATH_USER_SHARED] = "user-shared",
[SD_PATH_USER_CONFIGURATION] = "user-configuration",
[SD_PATH_USER_RUNTIME] = "user-runtime",
[SD_PATH_USER_STATE_CACHE] = "user-state-cache",
[SD_PATH_USER] = "user",
[SD_PATH_USER_DOCUMENTS] = "user-documents",
[SD_PATH_USER_MUSIC] = "user-music",
[SD_PATH_USER_PICTURES] = "user-pictures",
[SD_PATH_USER_VIDEOS] = "user-videos",
[SD_PATH_USER_DOWNLOAD] = "user-download",
[SD_PATH_USER_PUBLIC] = "user-public",
[SD_PATH_USER_TEMPLATES] = "user-templates",
[SD_PATH_USER_DESKTOP] = "user-desktop",
[SD_PATH_SEARCH_BINARIES] = "search-binaries",
[SD_PATH_SEARCH_LIBRARY_PRIVATE] = "search-library-private",
[SD_PATH_SEARCH_LIBRARY_ARCH] = "search-library-arch",
[SD_PATH_SEARCH_SHARED] = "search-shared",
[SD_PATH_SEARCH_CONFIGURATION_FACTORY] = "search-configuration-factory",
[SD_PATH_SEARCH_STATE_FACTORY] = "search-state-factory",
[SD_PATH_SEARCH_CONFIGURATION] = "search-configuration",
};
static int help(void) {
printf("%s [OPTIONS...] [NAME...]\n\n"
"Show system and user paths.\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
" --suffix=SUFFIX Suffix to append to paths\n",
program_invocation_short_name);
return 0;
}
static int list_homes(void) {
uint64_t i = 0;
int r = 0;
for (i = 0; i < ELEMENTSOF(path_table); i++) {
_cleanup_free_ char *p = NULL;
int q;
q = sd_path_home(i, arg_suffix, &p);
if (q == -ENXIO)
continue;
if (q < 0) {
log_error("Failed to query %s: %s", path_table[i], strerror(-r));
r = q;
continue;
}
printf("%s: %s\n", path_table[i], p);
}
return r;
}
static int print_home(const char *n) {
uint64_t i = 0;
int r;
for (i = 0; i < ELEMENTSOF(path_table); i++) {
if (streq(path_table[i], n)) {
_cleanup_free_ char *p = NULL;
r = sd_path_home(i, arg_suffix, &p);
if (r < 0) {
log_error("Failed to query %s: %s", n, strerror(-r));
return r;
}
printf("%s\n", p);
return 0;
}
}
log_error("Path %s not known.", n);
return -ENOTSUP;
}
static int parse_argv(int argc, char *argv[]) {
enum {
ARG_VERSION = 0x100,
ARG_SUFFIX,
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "suffix", required_argument, NULL, ARG_SUFFIX },
{}
};
int c;
assert(argc >= 0);
assert(argv);
while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
switch (c) {
case 'h':
return help();
case ARG_VERSION:
puts(PACKAGE_STRING);
puts(SYSTEMD_FEATURES);
return 0;
case ARG_SUFFIX:
arg_suffix = optarg;
break;
case '?':
return -EINVAL;
default:
assert_not_reached("Unhandled option");
}
}
return 1;
}
int main(int argc, char* argv[]) {
int r;
log_parse_environment();
log_open();
r = parse_argv(argc, argv);
if (r <= 0)
goto finish;
if (argc > optind) {
int i, q;
for (i = optind; i < argc; i++) {
q = print_home(argv[i]);
if (q < 0)
r = q;
}
} else
r = list_homes();
finish:
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}

View File

@ -23,6 +23,8 @@
#include "util.h"
/* A cleaned up architecture definition */
typedef enum Architecture {
ARCHITECTURE_X86 = 0,
ARCHITECTURE_X86_64,
@ -38,7 +40,9 @@ typedef enum Architecture {
ARCHITECTURE_SPARC,
ARCHITECTURE_SPARC64,
ARCHITECTURE_MIPS,
ARCHITECTURE_MIPS_LE,
ARCHITECTURE_MIPS64,
ARCHITECTURE_MIPS64_LE,
ARCHITECTURE_ALPHA,
ARCHITECTURE_ARM,
ARCHITECTURE_ARM_BE,
@ -55,64 +59,107 @@ typedef enum Architecture {
Architecture uname_architecture(void);
/*
* ARCH_TUPLE should resolve to the local architecture systemd is
* built for, according to the Debian tuple list:
*
* https://wiki.debian.org/Multiarch/Tuples
*
*/
#if defined(__x86_64__)
# define native_architecture() ARCHITECTURE_X86_64
# define ARCH_TUPLE "x86_64-linux-gnu"
#elif defined(__i386__)
# define native_architecture() ARCHITECTURE_X86
# define ARCH_TUPLE "i386-linux-gnu"
#elif defined(__powerpc64__)
# if defined(WORDS_BIGENDIAN)
# define native_architecture() ARCHITECTURE_PPC64
# define ARCH_TUPLE "ppc64-linux-gnu"
# else
# define native_architecture() ARCHITECTURE_PPC64_LE
# error "Missing ARCH_TUPLE for PPC64LE"
# endif
#elif defined(__powerpc__)
# if defined(WORDS_BIGENDIAN)
# define native_architecture() ARCHITECTURE_PPC
# define ARCH_TUPLE "powerpc-linux-gnu"
# else
# define native_architecture() ARCHITECTURE_PPC_LE
# error "Missing ARCH_TUPLE for PPCLE"
# endif
#elif defined(__ia64__)
# define native_architecture() ARCHITECTURE_IA64
# define ARCH_TUPLE "ia64-linux-gnu"
#elif defined(__hppa64__)
# define native_architecture() ARCHITECTURE_PARISC64
# error "Missing ARCH_TUPLE for HPPA64"
#elif defined(__hppa__)
# define native_architecture() ARCHITECTURE_PARISC
# define ARCH_TUPLE "hppalinuxgnu"
#elif defined(__s390x__)
# define native_architecture() ARCHITECTURE_S390X
# define ARCH_TUPLE "s390x-linux-gnu"
#elif defined(__s390__)
# define native_architecture() ARCHITECTURE_S390
# define ARCH_TUPLE "s390-linux-gnu"
#elif defined(__sparc64__)
# define native_architecture() ARCHITECTURE_SPARC64
# define ARCH_TUPLE "sparc64-linux-gnu"
#elif defined(__sparc__)
# define native_architecture() ARCHITECTURE_SPARC
# define ARCH_TUPLE "sparc-linux-gnu"
#elif defined(__mips64__)
# define native_architecture() ARCHITECTURE_MIPS64
# if defined(WORDS_BIGENDIAN)
# define native_architecture() ARCHITECTURE_MIPS64
# error "Missing ARCH_TUPLE for MIPS64"
# else
# define native_architecture() ARCHITECTURE_MIPS64_LE
# error "Missing ARCH_TUPLE for MIPS64_LE"
# endif
#elif defined(__mips__)
# define native_architecture() ARCHITECTURE_MIPS
# if defined(WORDS_BIGENDIAN)
# define native_architecture() ARCHITECTURE_MIPS
# define ARCH_TUPLE "mips-linux-gnu"
# else
# define native_architecture() ARCHITECTURE_MIPS_LE
# define ARCH_TUPLE "mipsel-linux-gnu"
#endif
#elif defined(__alpha__)
# define native_architecture() ARCHITECTURE_ALPHA
# define ARCH_TUPLE "alpha-linux-gnu"
#elif defined(__aarch64__)
# if defined(WORDS_BIGENDIAN)
# define native_architecture() ARCHITECTURE_ARM64_BE
# define ARCH_TUPLE "aarch64_be-linux-gnu"
# else
# define native_architecture() ARCHITECTURE_ARM64
# define ARCH_TUPLE "aarch64-linux-gnu"
# endif
#elif defined(__arm__)
# if defined(WORDS_BIGENDIAN)
# define native_architecture() ARCHITECTURE_ARM_BE
# error "Missing ARCH_TUPLE for ARM_BE"
# else
# define native_architecture() ARCHITECTURE_ARM
# error "Missing ARCH_TUPLE for ARM"
# endif
#elif defined(__sh64__)
# define native_architecture() ARCHITECTURE_SH64
# error "Missing ARCH_TUPLE for SH64"
#elif defined(__sh__)
# define native_architecture() ARCHITECTURE_SH
# define ARCH_TUPLE "sh4-linux-gnu"
#elif defined(__m68k__)
# define native_architecture() ARCHITECTURE_M68K
# define ARCH_TUPLE "m68k-linux-gnu"
#elif defined(__tilegx__)
# define native_architecture() ARCHITECTURE_TILEGX
# error "Missing ARCH_TUPLE for TILEGX"
#elif defined(__cris__)
# define native_architecture() ARCHITECTURE_CRIS
# error "Missing ARCH_TUPLE for CRIS"
#else
#error "Please register your architecture here!"
#endif

View File

@ -378,6 +378,30 @@ int strv_push(char ***l, char *value) {
return 0;
}
int strv_push_prepend(char ***l, char *value) {
char **c;
unsigned n, i;
if (!value)
return 0;
n = strv_length(*l);
c = new(char*, n + 2);
if (!c)
return -ENOMEM;
for (i = 0; i < n; i++)
c[i+1] = (*l)[i];
c[0] = value;
c[n+1] = NULL;
free(*l);
*l = c;
return 0;
}
int strv_consume(char ***l, char *value) {
int r;
@ -388,6 +412,16 @@ int strv_consume(char ***l, char *value) {
return r;
}
int strv_consume_prepend(char ***l, char *value) {
int r;
r = strv_push_prepend(l, value);
if (r < 0)
free(value);
return r;
}
int strv_extend(char ***l, const char *value) {
char *v;

View File

@ -41,7 +41,9 @@ int strv_extend_strv_concat(char ***a, char **b, const char *suffix);
int strv_extend(char ***l, const char *value);
int strv_extendf(char ***l, const char *format, ...) _printf_(2,0);
int strv_push(char ***l, char *value);
int strv_push_prepend(char ***l, char *value);
int strv_consume(char ***l, char *value);
int strv_consume_prepend(char ***l, char *value);
char **strv_remove(char **l, const char *s);
char **strv_uniq(char **l);

View File

@ -5226,8 +5226,8 @@ int get_home_dir(char **_h) {
assert(_h);
/* Take the user specified one */
e = getenv("HOME");
if (e) {
e = secure_getenv("HOME");
if (e && path_is_absolute(e)) {
h = strdup(e);
if (!h)
return -ENOMEM;

87
src/systemd/sd-path.h Normal file
View File

@ -0,0 +1,87 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
#ifndef foosdpathhfoo
#define foosdpathhfoo
/***
This file is part of systemd.
Copyright 2014 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
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 <inttypes.h>
enum {
/* Temporary files */
SD_PATH_TEMPORARY = 0x0ULL,
SD_PATH_TEMPORARY_LARGE,
/* Vendor supplied data */
SD_PATH_SYSTEM_BINARIES,
SD_PATH_SYSTEM_INCLUDE,
SD_PATH_SYSTEM_LIBRARY_PRIVATE,
SD_PATH_SYSTEM_LIBRARY_ARCH,
SD_PATH_SYSTEM_SHARED,
SD_PATH_SYSTEM_CONFIGURATION_FACTORY,
SD_PATH_SYSTEM_STATE_FACTORY,
/* System configuration, runtime, state, ... */
SD_PATH_SYSTEM_CONFIGURATION,
SD_PATH_SYSTEM_RUNTIME,
SD_PATH_SYSTEM_RUNTIME_LOGS,
SD_PATH_SYSTEM_STATE_PRIVATE,
SD_PATH_SYSTEM_STATE_LOGS,
SD_PATH_SYSTEM_STATE_CACHE,
SD_PATH_SYSTEM_STATE_SPOOL,
/* Vendor supplied data */
SD_PATH_USER_BINARIES,
SD_PATH_USER_LIBRARY_PRIVATE,
SD_PATH_USER_LIBRARY_ARCH,
SD_PATH_USER_SHARED,
/* User configuration, state, runtime ... */
SD_PATH_USER_CONFIGURATION, /* takes both actual configuration (like /etc) and state (like /var/lib) */
SD_PATH_USER_RUNTIME,
SD_PATH_USER_STATE_CACHE,
/* User resources */
SD_PATH_USER, /* $HOME itself */
SD_PATH_USER_DOCUMENTS,
SD_PATH_USER_MUSIC,
SD_PATH_USER_PICTURES,
SD_PATH_USER_VIDEOS,
SD_PATH_USER_DOWNLOAD,
SD_PATH_USER_PUBLIC,
SD_PATH_USER_TEMPLATES,
SD_PATH_USER_DESKTOP,
/* Search paths */
SD_PATH_SEARCH_BINARIES,
SD_PATH_SEARCH_LIBRARY_PRIVATE,
SD_PATH_SEARCH_LIBRARY_ARCH,
SD_PATH_SEARCH_SHARED,
SD_PATH_SEARCH_CONFIGURATION_FACTORY,
SD_PATH_SEARCH_STATE_FACTORY,
SD_PATH_SEARCH_CONFIGURATION,
_SD_PATH_MAX,
};
int sd_path_home(uint64_t type, const char *suffix, char **path);
int sd_path_search(uint64_t type, const char *suffix, char ***paths);
#endif