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:
parent
cd4ba18a84
commit
9a00f57a5b
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -86,6 +86,7 @@
|
||||||
/systemd-networkd-wait-online
|
/systemd-networkd-wait-online
|
||||||
/systemd-notify
|
/systemd-notify
|
||||||
/systemd-nspawn
|
/systemd-nspawn
|
||||||
|
/systemd-path
|
||||||
/systemd-quotacheck
|
/systemd-quotacheck
|
||||||
/systemd-random-seed
|
/systemd-random-seed
|
||||||
/systemd-rc-local-generator
|
/systemd-rc-local-generator
|
||||||
|
|
|
@ -74,6 +74,7 @@ MANPAGES += \
|
||||||
man/systemd-machine-id-setup.1 \
|
man/systemd-machine-id-setup.1 \
|
||||||
man/systemd-notify.1 \
|
man/systemd-notify.1 \
|
||||||
man/systemd-nspawn.1 \
|
man/systemd-nspawn.1 \
|
||||||
|
man/systemd-path.1 \
|
||||||
man/systemd-remount-fs.service.8 \
|
man/systemd-remount-fs.service.8 \
|
||||||
man/systemd-run.1 \
|
man/systemd-run.1 \
|
||||||
man/systemd-shutdownd.service.8 \
|
man/systemd-shutdownd.service.8 \
|
||||||
|
@ -1619,6 +1620,7 @@ EXTRA_DIST += \
|
||||||
man/systemd-networkd.service.xml \
|
man/systemd-networkd.service.xml \
|
||||||
man/systemd-notify.xml \
|
man/systemd-notify.xml \
|
||||||
man/systemd-nspawn.xml \
|
man/systemd-nspawn.xml \
|
||||||
|
man/systemd-path.xml \
|
||||||
man/systemd-quotacheck.service.xml \
|
man/systemd-quotacheck.service.xml \
|
||||||
man/systemd-random-seed.service.xml \
|
man/systemd-random-seed.service.xml \
|
||||||
man/systemd-readahead-replay.service.xml \
|
man/systemd-readahead-replay.service.xml \
|
||||||
|
|
20
Makefile.am
20
Makefile.am
|
@ -187,6 +187,8 @@ AM_CPPFLAGS = \
|
||||||
-DPOLKIT_AGENT_BINARY_PATH=\"$(bindir)/pkttyagent\" \
|
-DPOLKIT_AGENT_BINARY_PATH=\"$(bindir)/pkttyagent\" \
|
||||||
-DQUOTACHECK=\"$(QUOTACHECK)\" \
|
-DQUOTACHECK=\"$(QUOTACHECK)\" \
|
||||||
-DKEXEC=\"$(KEXEC)\" \
|
-DKEXEC=\"$(KEXEC)\" \
|
||||||
|
-DLIBDIR=\"$(libdir)\" \
|
||||||
|
-DROOTLIBDIR=\"$(rootlibdir)\" \
|
||||||
-I $(top_srcdir)/src \
|
-I $(top_srcdir)/src \
|
||||||
-I $(top_builddir)/src/shared \
|
-I $(top_builddir)/src/shared \
|
||||||
-I $(top_srcdir)/src/shared \
|
-I $(top_srcdir)/src/shared \
|
||||||
|
@ -344,7 +346,8 @@ bin_PROGRAMS = \
|
||||||
systemd-detect-virt \
|
systemd-detect-virt \
|
||||||
systemd-delta \
|
systemd-delta \
|
||||||
systemd-analyze \
|
systemd-analyze \
|
||||||
systemd-run
|
systemd-run \
|
||||||
|
systemd-path
|
||||||
|
|
||||||
dist_bin_SCRIPTS = \
|
dist_bin_SCRIPTS = \
|
||||||
src/kernel-install/kernel-install
|
src/kernel-install/kernel-install
|
||||||
|
@ -2096,6 +2099,14 @@ systemd_notify_LDADD = \
|
||||||
libsystemd-internal.la \
|
libsystemd-internal.la \
|
||||||
libsystemd-shared.la
|
libsystemd-shared.la
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
systemd_path_SOURCES = \
|
||||||
|
src/path/path.c
|
||||||
|
|
||||||
|
systemd_path_LDADD = \
|
||||||
|
libsystemd-internal.la \
|
||||||
|
libsystemd-shared.la
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
systemd_ask_password_SOURCES = \
|
systemd_ask_password_SOURCES = \
|
||||||
src/ask-password/ask-password.c
|
src/ask-password/ask-password.c
|
||||||
|
@ -2221,6 +2232,7 @@ libsystemd_internal_la_SOURCES = \
|
||||||
src/systemd/sd-login.h \
|
src/systemd/sd-login.h \
|
||||||
src/systemd/sd-id128.h \
|
src/systemd/sd-id128.h \
|
||||||
src/systemd/sd-daemon.h \
|
src/systemd/sd-daemon.h \
|
||||||
|
src/systemd/sd-path.h \
|
||||||
src/libsystemd/sd-bus/sd-bus.c \
|
src/libsystemd/sd-bus/sd-bus.c \
|
||||||
src/libsystemd/sd-bus/bus-control.c \
|
src/libsystemd/sd-bus/bus-control.c \
|
||||||
src/libsystemd/sd-bus/bus-control.h \
|
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-rtnl/rtnl-util.c \
|
||||||
src/libsystemd/sd-id128/sd-id128.c \
|
src/libsystemd/sd-id128/sd-id128.c \
|
||||||
src/libsystemd/sd-daemon/sd-daemon.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 = \
|
nodist_libsystemd_internal_la_SOURCES = \
|
||||||
src/libsystemd/libsystemd.sym \
|
src/libsystemd/libsystemd.sym \
|
||||||
|
@ -2377,7 +2390,8 @@ pkginclude_HEADERS += \
|
||||||
src/systemd/sd-utf8.h \
|
src/systemd/sd-utf8.h \
|
||||||
src/systemd/sd-event.h \
|
src/systemd/sd-event.h \
|
||||||
src/systemd/sd-rtnl.h \
|
src/systemd/sd-rtnl.h \
|
||||||
src/systemd/sd-resolve.h
|
src/systemd/sd-resolve.h \
|
||||||
|
src/systemd/sd-path.h
|
||||||
endif
|
endif
|
||||||
|
|
||||||
lib_LTLIBRARIES += \
|
lib_LTLIBRARIES += \
|
||||||
|
|
|
@ -62,6 +62,11 @@
|
||||||
subset of these specifications that defines more
|
subset of these specifications that defines more
|
||||||
strictly the suggestions and restrictions systemd
|
strictly the suggestions and restrictions systemd
|
||||||
makes on the file system hierarchy.</para>
|
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>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
|
@ -296,8 +301,8 @@
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><filename>/usr/lib/<replaceable>arch-id</replaceable></filename></term>
|
<term><filename>/usr/lib/<replaceable>arch-id</replaceable></filename></term>
|
||||||
<listitem><para>Location for placing
|
<listitem><para>Location for placing
|
||||||
dynamic libraries, called <varname>$libdir</varname>.
|
dynamic libraries, also called <varname>$libdir</varname>.
|
||||||
The architecture identifier to use, is defined on <ulink
|
The architecture identifier to use is defined on <ulink
|
||||||
url="https://wiki.debian.org/Multiarch/Tuples">Multiarch Architecture Specifiers (Tuples)</ulink>
|
url="https://wiki.debian.org/Multiarch/Tuples">Multiarch Architecture Specifiers (Tuples)</ulink>
|
||||||
list. Legacy locations of <varname>$libdir</varname> are
|
list. Legacy locations of <varname>$libdir</varname> are
|
||||||
<filename>/usr/lib</filename>,
|
<filename>/usr/lib</filename>,
|
||||||
|
@ -309,7 +314,10 @@
|
||||||
<varname>$libdir</varname> for the
|
<varname>$libdir</varname> for the
|
||||||
primary architecture of the system,
|
primary architecture of the system,
|
||||||
invoke:
|
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>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
|
@ -621,7 +629,10 @@
|
||||||
of these directories are also standardized (though
|
of these directories are also standardized (though
|
||||||
more weakly) by the <ulink
|
more weakly) by the <ulink
|
||||||
url="http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html">XDG
|
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>
|
<variablelist>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
|
@ -952,6 +963,7 @@
|
||||||
<para>
|
<para>
|
||||||
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||||
<citerefentry><refentrytitle>hier</refentrytitle><manvolnum>7</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>systemd-boot-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||||
<citerefentry><refentrytitle>sysctl.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
|
<citerefentry><refentrytitle>sysctl.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
|
||||||
<citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
|
<citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
|
||||||
|
|
111
man/systemd-path.xml
Normal file
111
man/systemd-path.xml
Normal 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>
|
1
src/libsystemd/sd-path/Makefile
Symbolic link
1
src/libsystemd/sd-path/Makefile
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../Makefile
|
626
src/libsystemd/sd-path/sd-path.c
Normal file
626
src/libsystemd/sd-path/sd-path.c
Normal 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
1
src/path/Makefile
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../Makefile
|
208
src/path/path.c
Normal file
208
src/path/path.c
Normal 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;
|
||||||
|
}
|
|
@ -23,6 +23,8 @@
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
/* A cleaned up architecture definition */
|
||||||
|
|
||||||
typedef enum Architecture {
|
typedef enum Architecture {
|
||||||
ARCHITECTURE_X86 = 0,
|
ARCHITECTURE_X86 = 0,
|
||||||
ARCHITECTURE_X86_64,
|
ARCHITECTURE_X86_64,
|
||||||
|
@ -38,7 +40,9 @@ typedef enum Architecture {
|
||||||
ARCHITECTURE_SPARC,
|
ARCHITECTURE_SPARC,
|
||||||
ARCHITECTURE_SPARC64,
|
ARCHITECTURE_SPARC64,
|
||||||
ARCHITECTURE_MIPS,
|
ARCHITECTURE_MIPS,
|
||||||
|
ARCHITECTURE_MIPS_LE,
|
||||||
ARCHITECTURE_MIPS64,
|
ARCHITECTURE_MIPS64,
|
||||||
|
ARCHITECTURE_MIPS64_LE,
|
||||||
ARCHITECTURE_ALPHA,
|
ARCHITECTURE_ALPHA,
|
||||||
ARCHITECTURE_ARM,
|
ARCHITECTURE_ARM,
|
||||||
ARCHITECTURE_ARM_BE,
|
ARCHITECTURE_ARM_BE,
|
||||||
|
@ -55,64 +59,107 @@ typedef enum Architecture {
|
||||||
|
|
||||||
Architecture uname_architecture(void);
|
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__)
|
#if defined(__x86_64__)
|
||||||
# define native_architecture() ARCHITECTURE_X86_64
|
# define native_architecture() ARCHITECTURE_X86_64
|
||||||
|
# define ARCH_TUPLE "x86_64-linux-gnu"
|
||||||
#elif defined(__i386__)
|
#elif defined(__i386__)
|
||||||
# define native_architecture() ARCHITECTURE_X86
|
# define native_architecture() ARCHITECTURE_X86
|
||||||
|
# define ARCH_TUPLE "i386-linux-gnu"
|
||||||
#elif defined(__powerpc64__)
|
#elif defined(__powerpc64__)
|
||||||
# if defined(WORDS_BIGENDIAN)
|
# if defined(WORDS_BIGENDIAN)
|
||||||
# define native_architecture() ARCHITECTURE_PPC64
|
# define native_architecture() ARCHITECTURE_PPC64
|
||||||
|
# define ARCH_TUPLE "ppc64-linux-gnu"
|
||||||
# else
|
# else
|
||||||
# define native_architecture() ARCHITECTURE_PPC64_LE
|
# define native_architecture() ARCHITECTURE_PPC64_LE
|
||||||
|
# error "Missing ARCH_TUPLE for PPC64LE"
|
||||||
# endif
|
# endif
|
||||||
#elif defined(__powerpc__)
|
#elif defined(__powerpc__)
|
||||||
# if defined(WORDS_BIGENDIAN)
|
# if defined(WORDS_BIGENDIAN)
|
||||||
# define native_architecture() ARCHITECTURE_PPC
|
# define native_architecture() ARCHITECTURE_PPC
|
||||||
|
# define ARCH_TUPLE "powerpc-linux-gnu"
|
||||||
# else
|
# else
|
||||||
# define native_architecture() ARCHITECTURE_PPC_LE
|
# define native_architecture() ARCHITECTURE_PPC_LE
|
||||||
|
# error "Missing ARCH_TUPLE for PPCLE"
|
||||||
# endif
|
# endif
|
||||||
#elif defined(__ia64__)
|
#elif defined(__ia64__)
|
||||||
# define native_architecture() ARCHITECTURE_IA64
|
# define native_architecture() ARCHITECTURE_IA64
|
||||||
|
# define ARCH_TUPLE "ia64-linux-gnu"
|
||||||
#elif defined(__hppa64__)
|
#elif defined(__hppa64__)
|
||||||
# define native_architecture() ARCHITECTURE_PARISC64
|
# define native_architecture() ARCHITECTURE_PARISC64
|
||||||
|
# error "Missing ARCH_TUPLE for HPPA64"
|
||||||
#elif defined(__hppa__)
|
#elif defined(__hppa__)
|
||||||
# define native_architecture() ARCHITECTURE_PARISC
|
# define native_architecture() ARCHITECTURE_PARISC
|
||||||
|
# define ARCH_TUPLE "hppa‑linux‑gnu"
|
||||||
#elif defined(__s390x__)
|
#elif defined(__s390x__)
|
||||||
# define native_architecture() ARCHITECTURE_S390X
|
# define native_architecture() ARCHITECTURE_S390X
|
||||||
|
# define ARCH_TUPLE "s390x-linux-gnu"
|
||||||
#elif defined(__s390__)
|
#elif defined(__s390__)
|
||||||
# define native_architecture() ARCHITECTURE_S390
|
# define native_architecture() ARCHITECTURE_S390
|
||||||
|
# define ARCH_TUPLE "s390-linux-gnu"
|
||||||
#elif defined(__sparc64__)
|
#elif defined(__sparc64__)
|
||||||
# define native_architecture() ARCHITECTURE_SPARC64
|
# define native_architecture() ARCHITECTURE_SPARC64
|
||||||
|
# define ARCH_TUPLE "sparc64-linux-gnu"
|
||||||
#elif defined(__sparc__)
|
#elif defined(__sparc__)
|
||||||
# define native_architecture() ARCHITECTURE_SPARC
|
# define native_architecture() ARCHITECTURE_SPARC
|
||||||
|
# define ARCH_TUPLE "sparc-linux-gnu"
|
||||||
#elif defined(__mips64__)
|
#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__)
|
#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__)
|
#elif defined(__alpha__)
|
||||||
# define native_architecture() ARCHITECTURE_ALPHA
|
# define native_architecture() ARCHITECTURE_ALPHA
|
||||||
|
# define ARCH_TUPLE "alpha-linux-gnu"
|
||||||
#elif defined(__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
# if defined(WORDS_BIGENDIAN)
|
# if defined(WORDS_BIGENDIAN)
|
||||||
# define native_architecture() ARCHITECTURE_ARM64_BE
|
# define native_architecture() ARCHITECTURE_ARM64_BE
|
||||||
|
# define ARCH_TUPLE "aarch64_be-linux-gnu"
|
||||||
# else
|
# else
|
||||||
# define native_architecture() ARCHITECTURE_ARM64
|
# define native_architecture() ARCHITECTURE_ARM64
|
||||||
|
# define ARCH_TUPLE "aarch64-linux-gnu"
|
||||||
# endif
|
# endif
|
||||||
#elif defined(__arm__)
|
#elif defined(__arm__)
|
||||||
# if defined(WORDS_BIGENDIAN)
|
# if defined(WORDS_BIGENDIAN)
|
||||||
# define native_architecture() ARCHITECTURE_ARM_BE
|
# define native_architecture() ARCHITECTURE_ARM_BE
|
||||||
|
# error "Missing ARCH_TUPLE for ARM_BE"
|
||||||
# else
|
# else
|
||||||
# define native_architecture() ARCHITECTURE_ARM
|
# define native_architecture() ARCHITECTURE_ARM
|
||||||
|
# error "Missing ARCH_TUPLE for ARM"
|
||||||
# endif
|
# endif
|
||||||
#elif defined(__sh64__)
|
#elif defined(__sh64__)
|
||||||
# define native_architecture() ARCHITECTURE_SH64
|
# define native_architecture() ARCHITECTURE_SH64
|
||||||
|
# error "Missing ARCH_TUPLE for SH64"
|
||||||
#elif defined(__sh__)
|
#elif defined(__sh__)
|
||||||
# define native_architecture() ARCHITECTURE_SH
|
# define native_architecture() ARCHITECTURE_SH
|
||||||
|
# define ARCH_TUPLE "sh4-linux-gnu"
|
||||||
#elif defined(__m68k__)
|
#elif defined(__m68k__)
|
||||||
# define native_architecture() ARCHITECTURE_M68K
|
# define native_architecture() ARCHITECTURE_M68K
|
||||||
|
# define ARCH_TUPLE "m68k-linux-gnu"
|
||||||
#elif defined(__tilegx__)
|
#elif defined(__tilegx__)
|
||||||
# define native_architecture() ARCHITECTURE_TILEGX
|
# define native_architecture() ARCHITECTURE_TILEGX
|
||||||
|
# error "Missing ARCH_TUPLE for TILEGX"
|
||||||
#elif defined(__cris__)
|
#elif defined(__cris__)
|
||||||
# define native_architecture() ARCHITECTURE_CRIS
|
# define native_architecture() ARCHITECTURE_CRIS
|
||||||
|
# error "Missing ARCH_TUPLE for CRIS"
|
||||||
#else
|
#else
|
||||||
#error "Please register your architecture here!"
|
#error "Please register your architecture here!"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -378,6 +378,30 @@ int strv_push(char ***l, char *value) {
|
||||||
return 0;
|
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 strv_consume(char ***l, char *value) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
@ -388,6 +412,16 @@ int strv_consume(char ***l, char *value) {
|
||||||
return r;
|
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) {
|
int strv_extend(char ***l, const char *value) {
|
||||||
char *v;
|
char *v;
|
||||||
|
|
||||||
|
|
|
@ -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_extend(char ***l, const char *value);
|
||||||
int strv_extendf(char ***l, const char *format, ...) _printf_(2,0);
|
int strv_extendf(char ***l, const char *format, ...) _printf_(2,0);
|
||||||
int strv_push(char ***l, char *value);
|
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(char ***l, char *value);
|
||||||
|
int strv_consume_prepend(char ***l, char *value);
|
||||||
|
|
||||||
char **strv_remove(char **l, const char *s);
|
char **strv_remove(char **l, const char *s);
|
||||||
char **strv_uniq(char **l);
|
char **strv_uniq(char **l);
|
||||||
|
|
|
@ -5226,8 +5226,8 @@ int get_home_dir(char **_h) {
|
||||||
assert(_h);
|
assert(_h);
|
||||||
|
|
||||||
/* Take the user specified one */
|
/* Take the user specified one */
|
||||||
e = getenv("HOME");
|
e = secure_getenv("HOME");
|
||||||
if (e) {
|
if (e && path_is_absolute(e)) {
|
||||||
h = strdup(e);
|
h = strdup(e);
|
||||||
if (!h)
|
if (!h)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
87
src/systemd/sd-path.h
Normal file
87
src/systemd/sd-path.h
Normal 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
|
Loading…
Reference in a new issue