From: Sven Eden Date: Tue, 14 Mar 2017 10:30:17 +0000 (+0100) Subject: Major cleanup of all leftovers after rebasing on master. X-Git-Tag: v226.4~1^2~3 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=3d1092eab0f4a5c771225c78072a7b6eccb82849 Major cleanup of all leftovers after rebasing on The patching of elogind in several steps with only partly rebasing on a common commit with upstream, left the tree in a state, that was unmergeable with master. By rebasing on master and manually cleaning up all commits, this merge is now possible. However, this process left some orphans, that are cleanup now. --- diff --git a/autogen.sh b/autogen.sh index 2d4acdfef..8a88a3447 100755 --- a/autogen.sh +++ b/autogen.sh @@ -21,63 +21,14 @@ oldpwd=$(pwd) topdir=$(dirname $0) cd $topdir -if [ -f .git/hooks/pre-commit.sample ] && [ ! -f .git/hooks/pre-commit ]; then - # This part is allowed to fail - cp -p .git/hooks/pre-commit.sample .git/hooks/pre-commit && \ - chmod +x .git/hooks/pre-commit && \ - echo "Activated pre-commit hook." || : -fi - +# We do not need this, we are not systemd upstream! +#if [ -f .git/hooks/pre-commit.sample ] && [ ! -f .git/hooks/pre-commit ]; then +# # This part is allowed to fail +# cp -p .git/hooks/pre-commit.sample .git/hooks/pre-commit && \ +# chmod +x .git/hooks/pre-commit && \ +# echo "Activated pre-commit hook." || : +#fi intltoolize --force --automake autoreconf --force --install --symlink -libdir() { - echo $(cd "$1/$(gcc -print-multi-os-directory)"; pwd) -} - -args="\ ---sysconfdir=/etc \ ---localstatedir=/var \ ---libdir=$(libdir /usr/lib) \ -" - -if [ -f "$topdir/.config.args" ]; then - args="$args $(cat $topdir/.config.args)" -fi - -if [ ! -L /bin ]; then -args="$args \ ---with-rootprefix=/ \ ---with-rootlibdir=$(libdir /lib) \ -" -fi - cd $oldpwd - -if [ "x$1" = "xc" ]; then - $topdir/configure CFLAGS='-g -O0 -ftrapv' --enable-compat-libs --enable-kdbus $args - make clean -elif [ "x$1" = "xt" ]; then - $topdir/configure CFLAGS='-g -O0 -ftrapv' --enable-compat-libs --enable-kdbus --enable-terminal $args - make clean -elif [ "x$1" = "xg" ]; then - $topdir/configure CFLAGS='-g -Og -ftrapv' --enable-compat-libs --enable-kdbus $args - make clean -elif [ "x$1" = "xa" ]; then - $topdir/configure CFLAGS='-g -O0 -Wsuggest-attribute=pure -Wsuggest-attribute=const -ftrapv' --enable-compat-libs --enable-kdbus $args - make clean -elif [ "x$1" = "xl" ]; then - $topdir/configure CC=clang CFLAGS='-g -O0 -ftrapv' --enable-compat-libs --enable-kdbus $args - make clean -elif [ "x$1" = "xs" ]; then - scan-build $topdir/configure CFLAGS='-std=gnu99 -g -O0 -ftrapv' --enable-kdbus $args - scan-build make -else - echo - echo "----------------------------------------------------------------" - echo "Initialized build system. For a common configuration please run:" - echo "----------------------------------------------------------------" - echo - echo "$topdir/configure CFLAGS='-g -O0 -ftrapv' --enable-compat-libs --enable-kdbus $args" - echo -fi diff --git a/docs/Makefile b/docs/Makefile new file mode 120000 index 000000000..bd1047548 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1 @@ +../src/Makefile \ No newline at end of file diff --git a/hwdb/60-evdev.hwdb b/hwdb/60-evdev.hwdb deleted file mode 100644 index ca82f8a51..000000000 --- a/hwdb/60-evdev.hwdb +++ /dev/null @@ -1,119 +0,0 @@ -# This file is part of systemd. -# -# The lookup keys are composed in: -# 60-evdev.rules -# -# Note: The format of the "evdev:" prefix match key is a -# contract between the rules file and the hardware data, it might -# change in later revisions to support more or better matches, it -# is not necessarily expected to be a stable ABI. -# -# Match string formats: -# evdev: -# evdev:name::dmi: -# -# To add local entries, create a new file -# /etc/udev/hwdb.d/61-evdev-local.hwdb -# and add your rules there. To load the new rules execute (as root): -# udevadm hwdb --update -# udevadm trigger /dev/input/eventXX -# where /dev/input/eventXX is the device in question. If in -# doubt, simply use /dev/input/event* to reload all input rules. -# -# If your changes are generally applicable, open a bug report on -# http://bugs.freedesktop.org/enter_bug.cgi?product=systemd -# and include your new rules, a description of the device, and the -# output of -# udevadm info /dev/input/eventXX -# (or /dev/input/event*). -# -# Allowed properties are: -# EVDEV_ABS_=:::: -# -# where is the hexadecimal EV_ABS code as listed in linux/input.h -# and min, max, res, fuzz, flat are the decimal values to the respective -# fields of the struct input_absinfo as listed in linux/input.h. -# If a field is missing the field will be left as-is. Not all fields need to -# be present. e.g. ::45 sets the resolution to 45 units/mm. - -# -# Sort by brand, model - -######################################### -# Apple -######################################### - -# Macbook2,1 (late 2006), single-button touchpad -evdev:input:b0003v05ACp021B* - EVDEV_ABS_00=256:1471:12 - EVDEV_ABS_01=256:831:12 - -# Macbook5,1 (unibody), aka wellspring3 -evdev:input:b0003v05ACp0236* -evdev:input:b0003v05ACp0237* -evdev:input:b0003v05ACp0238* - EVDEV_ABS_00=::92 - EVDEV_ABS_01=::90 - EVDEV_ABS_35=::92 - EVDEV_ABS_36=::90 - -# Macbook8 (unibody, March 2011) -evdev:input:b0003v05ACp0245* -evdev:input:b0003v05ACp0246* -evdev:input:b0003v05ACp0247* - EVDEV_ABS_00=::92 - EVDEV_ABS_01=::91 - EVDEV_ABS_35=::92 - EVDEV_ABS_36=::91 - -# Macbook8,2 (unibody) -evdev:input:b0003v05ACp0252* -evdev:input:b0003v05ACp0253* -evdev:input:b0003v05ACp0254* - EVDEV_ABS_00=::94 - EVDEV_ABS_01=::92 - EVDEV_ABS_35=::94 - EVDEV_ABS_36=::92 - -# MacbookPro10,1 (unibody, June 2012) -evdev:input:b0003v05ACp0259* -evdev:input:b0003v05ACp025a* -evdev:input:b0003v05ACp025b* -# MacbookPro10,2 (unibody, October 2012) -evdev:input:b0003v05ACp0259* -evdev:input:b0003v05ACp025a* -evdev:input:b0003v05ACp025b* - EVDEV_ABS_00=::94 - EVDEV_ABS_01=::92 - EVDEV_ABS_35=::94 - EVDEV_ABS_36=::92 - -######################################### -# ASUS -######################################### -# Asus K52JT -evdev:name:ETPS/2 Elantech Touchpad:dmi:bvn*:bvr*:bd*:svnASUSTeKComputerInc.:pnK52JT:* - EVDEV_ABS_00=::18 - EVDEV_ABS_01=::16 - EVDEV_ABS_35=::18 - EVDEV_ABS_36=::16 - -######################################### -# Google -######################################### - -# Chromebook Pixel (2015) - Samus -evdev:name:Atmel maXTouch Touch*:dmi:bvn*:bvr*:bd*:svnGOOGLE:pnSamus* - EVDEV_ABS_00=::10 - EVDEV_ABS_01=::10 - EVDEV_ABS_35=::10 - EVDEV_ABS_36=::10 - -######################################### -# Lenovo -######################################### - -# Lenovo X230 series -evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pn*ThinkPad*X230* - EVDEV_ABS_01=::100 - EVDEV_ABS_36=::100 diff --git a/man/custom-html.xsl b/man/custom-html.xsl index 27714633e..73a643b41 100644 --- a/man/custom-html.xsl +++ b/man/custom-html.xsl @@ -277,12 +277,6 @@ elogind.directives.html Directives - · - - - ../python-elogind/index.html - - Python diff --git a/man/less-variables.xml b/man/less-variables.xml new file mode 100644 index 000000000..0fb4d7fbc --- /dev/null +++ b/man/less-variables.xml @@ -0,0 +1,29 @@ + + + + + Environment + + + + $SYSTEMD_PAGER + + Pager to use when + is not given; + overrides $PAGER. Setting + this to an empty string or the value + cat is equivalent to passing + . + + + + $SYSTEMD_LESS + + Override the default + options passed to + less + (FRSXMK). + + + diff --git a/man/sd_pid_get_session.xml b/man/sd_pid_get_session.xml deleted file mode 100644 index fac072a4c..000000000 --- a/man/sd_pid_get_session.xml +++ /dev/null @@ -1,296 +0,0 @@ - - - - - - - - - sd_pid_get_session - systemd - - - - Developer - Lennart - Poettering - lennart@poettering.net - - - - - - sd_pid_get_session - 3 - - - - sd_pid_get_session - sd_pid_get_unit - sd_pid_get_user_unit - sd_pid_get_owner_uid - sd_pid_get_machine_name - sd_pid_get_slice - sd_peer_get_session - sd_peer_get_unit - sd_peer_get_user_unit - sd_peer_get_owner_uid - sd_peer_get_machine_name - sd_peer_get_slice - Determine session, service, owner of a - session, container/VM or slice of a specific - PID or socket peer - - - - - #include <systemd/sd-login.h> - - - int sd_pid_get_session - pid_t pid - char **session - - - - int sd_pid_get_unit - pid_t pid - char **unit - - - - int sd_pid_get_user_unit - pid_t pid - char **unit - - - - int sd_pid_get_owner_uid - pid_t pid - uid_t *uid - - - - int sd_pid_get_machine_name - pid_t pid - char **name - - - - int sd_pid_get_slice - pid_t pid - char **slice - - - - int sd_peer_get_session - int fd - char **session - - - - int sd_peer_get_unit - int fd - char **unit - - - - int sd_peer_get_user_unit - int fd - char **unit - - - - int sd_peer_get_owner_uid - int fd - uid_t *uid - - - - int sd_peer_get_machine_name - int fd - char **name - - - - int sd_peer_get_slice - int fd - char **slice - - - - - - Description - - sd_pid_get_session() may be used to - determine the login session identifier of a process identified by - the specified process identifier. The session identifier is a - short string, suitable for usage in file system paths. Note that - not all processes are part of a login session (e.g. system service - processes, user processes that are shared between multiple - sessions of the same user, or kernel threads). For processes not - being part of a login session this function will fail with - -ENXIO. The returned string needs to be freed with the libc - free3 - call after use. - - sd_pid_get_unit() may be used to - determine the systemd system unit (i.e. system service) identifier - of a process identified by the specified PID. The unit name is a - short string, suitable for usage in file system paths. Note that - not all processes are part of a system unit/service (e.g. user - processes, or kernel threads). For processes not being part of a - systemd system unit this function will fail with -ENXIO (More - specifically: this call will not work for processes that are part - of user units, use sd_pid_get_user_unit() for - that.) The returned string needs to be freed with the libc - free3 - call after use. - - sd_pid_get_user_unit() may be used to - determine the systemd user unit (i.e. user service) identifier of - a process identified by the specified PID. This is similar to - sd_pid_get_unit() but applies to user units - instead of system units. - - sd_pid_get_owner_uid() may be used to - determine the Unix user identifier of the owner of the session of - a process identified the specified PID. Note that this function - will succeed for user processes which are shared between multiple - login sessions of the same user, where - sd_pid_get_session() will fail. For processes - not being part of a login session and not being a shared process - of a user this function will fail with -ENXIO. - - sd_pid_get_machine_name() may be used - to determine the name of the VM or container is a member of. The - machine name is a short string, suitable for usage in file system - paths. The returned string needs to be freed with the libc - free3 - call after use. For processes not part of a VM or containers this - function fails with -ENXIO. - - sd_pid_get_slice() may be used to - determine the slice unit the process is a member of. See - systemd.slice5 - for details about slices. The returned string needs to be freed - with the libc - free3 - call after use. - - If the pid parameter of any of these - functions is passed as 0, the operation is executed for the - calling process. - - The sd_peer_get_session(), - sd_peer_get_unit(), - sd_peer_get_user_unit(), - sd_peer_get_owner_uid(), - sd_peer_get_machine_name() and - sd_peer_get_slice() calls operate similar to - their PID counterparts, but operate on a connected AF_UNIX socket - and retrieve information about the connected peer process. - - - - Return Value - - On success, these calls return 0 or a positive integer. On - failure, these calls return a negative errno-style error - code. - - - - Errors - - Returned errors may indicate the following problems: - - - - - -ENXIO - - Given field is not specified for the described - process or peer. - - - - - -ESRCH - - The specified PID does not refer to a running - process. - - - - - -ENOMEM - - Memory allocation failed. - - - - - - Notes - - The sd_pid_get_session(), - sd_pid_get_unit(), - sd_pid_get_user_unit(), - sd_pid_get_owner_uid(), - sd_pid_get_machine_name(), - sd_pid_get_slice(), - sd_peer_get_session(), - sd_peer_get_unit(), - sd_peer_get_user_unit(), - sd_peer_get_owner_uid(), - sd_peer_get_machine_name() and - sd_peer_get_slice() interfaces are - available as a shared library, which can be compiled - and linked to with the - libelogind pkg-config1 - file. - - Note that the login session identifier as - returned by sd_pid_get_session() - is completely unrelated to the process session - identifier as returned by - getsid2. - - - - See Also - - - systemd1, - sd-login3, - sd_session_is_active3, - getsid2, - systemd.slice5, - systemd-machined.service8 - - - - diff --git a/man/standard-conf.xml b/man/standard-conf.xml new file mode 100644 index 000000000..15268030f --- /dev/null +++ b/man/standard-conf.xml @@ -0,0 +1,73 @@ + + + + + + Configuration Directories and Precedence + + Configuration files are read from directories in + /etc/, /run/, and + /usr/lib/, in order of precedence. + Each configuration file in these configuration directories shall be named in + the style of filename.conf. + Files in /etc/ override files with the same name in + /run/ and /usr/lib/. Files in + /run/ override files with the same name in + /usr/lib/. + + Packages should install their configuration files in + /usr/lib/. Files in /etc/ are + reserved for the local administrator, who may use this logic to override the + configuration files installed by vendor packages. All configuration files + are sorted by their filename in lexicographic order, regardless of which of + the directories they reside in. If multiple files specify the same option, + the entry in the file with the lexicographically latest name will take + precedence. It is recommended to prefix all filenames with a two-digit number + and a dash, to simplify the ordering of the files. + + If the administrator wants to disable a configuration file supplied by + the vendor, the recommended way is to place a symlink to + /dev/null in the configuration directory in + /etc/, with the same filename as the vendor + configuration file. If the vendor configuration file is included in + the initrd image, the image has to be regenerated. + + + + + Configuration Directories and Precedence + + Default configuration is defined during compilation, so a + configuration file is only needed when it is necessary to deviate + from those defaults. By default the configuration file in + /etc/elogind/ contains commented out entries + showing the defaults as a guide to the administrator. This file + can be edited to create local overrides. + + + When packages need to customize the configuration, they can + install configuration snippets in + /usr/lib/elogind/*.conf.d/. Files in + /etc/ are reserved for the local + administrator, who may use this logic to override the + configuration files installed by vendor packages. The main + configuration file is read before any of the configuration + directories, and has the lowest precedence; entries in a file in + any configuration directory override entries in the single + configuration file. Files in the + *.conf.d/ configuration subdirectories + are sorted by their filename in lexicographic order, regardless of + which of the subdirectories they reside in. If multiple files + specify the same option, the entry in the file with the + lexicographically latest name takes precedence. It is recommended + to prefix all filenames in those subdirectories with a two-digit + number and a dash, to simplify the ordering of the files. + + To disable a configuration file supplied by the vendor, the + recommended way is to place a symlink to + /dev/null in the configuration directory in + /etc/, with the same filename as the vendor + configuration file. + + diff --git a/man/standard-options.xml b/man/standard-options.xml new file mode 100644 index 000000000..f21446339 --- /dev/null +++ b/man/standard-options.xml @@ -0,0 +1,39 @@ + + + + + + + + + + Print a short help text and exit. + + + + + + + + Print a short version string and exit. + + + + + + + + Do not pipe output into a pager. + + + + + + + + Do not print the legend, i.e. column headers and the + footer with hints. + + + diff --git a/man/user-system-options.xml b/man/user-system-options.xml new file mode 100644 index 000000000..8616c5424 --- /dev/null +++ b/man/user-system-options.xml @@ -0,0 +1,50 @@ + + + + + + + + + Talk to the service manager of the calling user, + rather than the service manager of the system. + + + + + + + + Talk to the service manager of the system. This is the + implied default. + + + + + + + + + Execute the operation remotely. Specify a hostname, or a + username and hostname separated by @, to + connect to. The hostname may optionally be suffixed by a + container name, separated by :, which + connects directly to a specific container on the specified + host. This will use SSH to talk to the remote machine manager + instance. Container names may be enumerated with + machinectl -H + HOST. + + + + + + + + + Execute operation on a local container. Specify a + container name to connect to. + + + diff --git a/shell-completion/zsh/_elogind-inhibit b/shell-completion/zsh/_elogind-inhibit index 1ecb6dc7e..1b3247b2c 100644 --- a/shell-completion/zsh/_elogind-inhibit +++ b/shell-completion/zsh/_elogind-inhibit @@ -26,8 +26,8 @@ _arguments \ {-h,--help}'[Show this help]' \ '--version[Show package version]' \ '--what=[Operations to inhibit]:options:_inhibit_what' \ - '--who=[A descriptive string who is inhibiting]' \ - '--why=[A descriptive string why is being inhibited]' \ - '--mode=[One of block or delay]' \ + '--who=[A descriptive string who is inhibiting]:who is inhibiting:' \ + '--why=[A descriptive string why is being inhibited]:reason for the lock:' \ + '--mode=[One of block or delay]:lock mode:( block delay )' \ '--list[List active inhibitors]' \ '*:commands:_systemd_inhibit_command' diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 1e54f58f5..b48642588 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -707,7 +707,7 @@ int cg_attach(const char *controller, const char *path, pid_t pid) { snprintf(c, sizeof(c), PID_FMT"\n", pid); - return write_string_file_no_create(fs, c); + return write_string_file(fs, c, 0); } int cg_attach_fallback(const char *controller, const char *path, pid_t pid) { @@ -907,7 +907,7 @@ int cg_install_release_agent(const char *controller, const char *agent) { sc = strstrip(contents); if (isempty(sc)) { - r = write_string_file_no_create(fs, agent); + r = write_string_file(fs, agent, 0); if (r < 0) return r; } else if (!path_equal(sc, agent)) @@ -925,7 +925,7 @@ int cg_install_release_agent(const char *controller, const char *agent) { sc = strstrip(contents); if (streq(sc, "0")) { - r = write_string_file_no_create(fs, "1"); + r = write_string_file(fs, "1", 0); if (r < 0) return r; @@ -952,7 +952,7 @@ int cg_uninstall_release_agent(const char *controller) { if (r < 0) return r; - r = write_string_file_no_create(fs, "0"); + r = write_string_file(fs, "0", 0); if (r < 0) return r; @@ -962,7 +962,7 @@ int cg_uninstall_release_agent(const char *controller) { if (r < 0) return r; - r = write_string_file_no_create(fs, ""); + r = write_string_file(fs, "", 0); if (r < 0) return r; @@ -1860,7 +1860,7 @@ int cg_set_attribute(const char *controller, const char *path, const char *attri if (r < 0) return r; - return write_string_file_no_create(p, value); + return write_string_file(p, value, 0); } /// UNNEEDED by elogind diff --git a/src/basic/missing.h b/src/basic/missing.h index cfe6459c1..bc6fbc539 100644 --- a/src/basic/missing.h +++ b/src/basic/missing.h @@ -454,6 +454,10 @@ struct btrfs_ioctl_quota_ctl_args { #define BTRFS_FIRST_FREE_OBJECTID 256 #endif +#ifndef BTRFS_LAST_FREE_OBJECTID +#define BTRFS_LAST_FREE_OBJECTID -256ULL +#endif + #ifndef BTRFS_ROOT_TREE_OBJECTID #define BTRFS_ROOT_TREE_OBJECTID 1 #endif @@ -478,6 +482,10 @@ struct btrfs_ioctl_quota_ctl_args { #define BTRFS_QGROUP_LIMIT_KEY 244 #endif +#ifndef BTRFS_ROOT_BACKREF_KEY +#define BTRFS_ROOT_BACKREF_KEY 144 +#endif + #ifndef BTRFS_SUPER_MAGIC #define BTRFS_SUPER_MAGIC 0x9123683E #endif @@ -924,6 +932,14 @@ static inline int setns(int fd, int nstype) { #define LOOPBACK_IFINDEX 1 #endif +#if !HAVE_DECL_IFA_FLAGS +#define IFA_FLAGS 8 +#endif + +#ifndef IFA_F_NOPREFIXROUTE +#define IFA_F_NOPREFIXROUTE 0x200 +#endif + #ifndef MAX_AUDIT_MESSAGE_LENGTH #define MAX_AUDIT_MESSAGE_LENGTH 8970 #endif @@ -1007,3 +1023,21 @@ static inline int renameat2(int oldfd, const char *oldname, int newfd, const cha #ifndef RENAME_NOREPLACE #define RENAME_NOREPLACE (1 << 0) #endif + +#if !HAVE_DECL_KCMP +static inline int kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) { + return syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2); +} +#endif + +#ifndef KCMP_FILE +#define KCMP_FILE 0 +#endif + +#ifndef INPUT_PROP_POINTING_STICK +#define INPUT_PROP_POINTING_STICK 0x05 +#endif + +#ifndef INPUT_PROP_ACCELEROMETER +#define INPUT_PROP_ACCELEROMETER 0x06 +#endif diff --git a/src/basic/rm-rf.h b/src/basic/rm-rf.h index 769bbc853..96579eb18 100644 --- a/src/basic/rm-rf.h +++ b/src/basic/rm-rf.h @@ -27,6 +27,7 @@ typedef enum RemoveFlags { REMOVE_ONLY_DIRECTORIES = 1, REMOVE_ROOT = 2, REMOVE_PHYSICAL = 4, /* if not set, only removes files on tmpfs, never physical file systems */ + REMOVE_SUBVOLUME = 8, } RemoveFlags; int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev); diff --git a/src/basic/verbs.h b/src/basic/verbs.h index 03013beb8..d59e4d59b 100644 --- a/src/basic/verbs.h +++ b/src/basic/verbs.h @@ -21,45 +21,14 @@ along with systemd; If not, see . ***/ -#include "in-addr-util.h" +#define VERB_ANY ((unsigned) -1) +#define VERB_DEFAULT 1 -typedef struct DnsServer DnsServer; -typedef enum DnsServerSource DnsServerSource; +typedef struct { + const char *verb; + unsigned min_args, max_args; + unsigned flags; + int (* const dispatch)(int argc, char *argv[], void *userdata); +} Verb; -typedef enum DnsServerType { - DNS_SERVER_SYSTEM, - DNS_SERVER_FALLBACK, - DNS_SERVER_LINK, -} DnsServerType; - -#include "resolved-link.h" - -struct DnsServer { - Manager *manager; - - unsigned n_ref; - - DnsServerType type; - - Link *link; - - int family; - union in_addr_union address; - - bool marked:1; - - LIST_FIELDS(DnsServer, servers); -}; - -int dns_server_new( - Manager *m, - DnsServer **s, - DnsServerType type, - Link *l, - int family, - const union in_addr_union *address); - -DnsServer* dns_server_ref(DnsServer *s); -DnsServer* dns_server_unref(DnsServer *s); - -extern const struct hash_ops dns_server_hash_ops; +int dispatch_verb(int argc, char *argv[], const Verb verbs[], void *userdata); diff --git a/src/libelogind/Makefile b/src/libelogind/Makefile deleted file mode 120000 index d0b0e8e00..000000000 --- a/src/libelogind/Makefile +++ /dev/null @@ -1 +0,0 @@ -../Makefile \ No newline at end of file diff --git a/src/libsystemd/libsystemd.sym b/src/libelogind/libelogind.sym similarity index 57% rename from src/libsystemd/libsystemd.sym rename to src/libelogind/libelogind.sym index 1c3b51a4b..b79d0a3f4 100644 --- a/src/libsystemd/libsystemd.sym +++ b/src/libelogind/libelogind.sym @@ -10,58 +10,58 @@ LIBSYSTEMD_209 { global: /* sd-journal */ - sd_journal_print; - sd_journal_printv; - sd_journal_send; - sd_journal_sendv; - sd_journal_stream_fd; - sd_journal_open; - sd_journal_close; - sd_journal_previous; - sd_journal_next; - sd_journal_previous_skip; - sd_journal_next_skip; - sd_journal_get_realtime_usec; - sd_journal_get_monotonic_usec; - sd_journal_get_data; - sd_journal_enumerate_data; - sd_journal_restart_data; - sd_journal_add_match; - sd_journal_flush_matches; - sd_journal_seek_head; - sd_journal_seek_tail; - sd_journal_seek_monotonic_usec; - sd_journal_seek_realtime_usec; - sd_journal_seek_cursor; - sd_journal_get_cursor; - sd_journal_get_fd; - sd_journal_process; - sd_journal_print_with_location; - sd_journal_printv_with_location; - sd_journal_send_with_location; - sd_journal_sendv_with_location; - sd_journal_get_cutoff_realtime_usec; - sd_journal_get_cutoff_monotonic_usec; - sd_journal_wait; - sd_journal_open_directory; - sd_journal_add_disjunction; - sd_journal_perror; - sd_journal_perror_with_location; - sd_journal_get_usage; - sd_journal_test_cursor; - sd_journal_query_unique; - sd_journal_enumerate_unique; - sd_journal_restart_unique; - sd_journal_get_catalog; - sd_journal_get_catalog_for_message_id; - sd_journal_set_data_threshold; - sd_journal_get_data_threshold; - sd_journal_reliable_fd; - sd_journal_get_events; - sd_journal_get_timeout; - sd_journal_add_conjunction; - sd_journal_open_files; - sd_journal_open_container; + /* sd_journal_print; */ + /* sd_journal_printv; */ + /* sd_journal_send; */ + /* sd_journal_sendv; */ + /* sd_journal_stream_fd; */ + /* sd_journal_open; */ + /* sd_journal_close; */ + /* sd_journal_previous; */ + /* sd_journal_next; */ + /* sd_journal_previous_skip; */ + /* sd_journal_next_skip; */ + /* sd_journal_get_realtime_usec; */ + /* sd_journal_get_monotonic_usec; */ + /* sd_journal_get_data; */ + /* sd_journal_enumerate_data; */ + /* sd_journal_restart_data; */ + /* sd_journal_add_match; */ + /* sd_journal_flush_matches; */ + /* sd_journal_seek_head; */ + /* sd_journal_seek_tail; */ + /* sd_journal_seek_monotonic_usec; */ + /* sd_journal_seek_realtime_usec; */ + /* sd_journal_seek_cursor; */ + /* sd_journal_get_cursor; */ + /* sd_journal_get_fd; */ + /* sd_journal_process; */ + /* sd_journal_print_with_location; */ + /* sd_journal_printv_with_location; */ + /* sd_journal_send_with_location; */ + /* sd_journal_sendv_with_location; */ + /* sd_journal_get_cutoff_realtime_usec; */ + /* sd_journal_get_cutoff_monotonic_usec; */ + /* sd_journal_wait; */ + /* sd_journal_open_directory; */ + /* sd_journal_add_disjunction; */ + /* sd_journal_perror; */ + /* sd_journal_perror_with_location; */ + /* sd_journal_get_usage; */ + /* sd_journal_test_cursor; */ + /* sd_journal_query_unique; */ + /* sd_journal_enumerate_unique; */ + /* sd_journal_restart_unique; */ + /* sd_journal_get_catalog; */ + /* sd_journal_get_catalog_for_message_id; */ + /* sd_journal_set_data_threshold; */ + /* sd_journal_get_data_threshold; */ + /* sd_journal_reliable_fd; */ + /* sd_journal_get_events; */ + /* sd_journal_get_timeout; */ + /* sd_journal_add_conjunction; */ + /* sd_journal_open_files; */ + /* sd_journal_open_container; */ /* sd-daemon */ /* sd_booted; */ @@ -183,36 +183,36 @@ global: sd_bus_new; sd_bus_set_address; sd_bus_set_fd; - sd_bus_set_exec; - sd_bus_get_address; - sd_bus_set_bus_client; - sd_bus_is_bus_client; + /* sd_bus_set_exec; */ + /* sd_bus_get_address; */ + /* sd_bus_set_bus_client; */ + /* sd_bus_is_bus_client; */ sd_bus_set_server; - sd_bus_is_server; - sd_bus_set_anonymous; - sd_bus_is_anonymous; - sd_bus_set_trusted; - sd_bus_is_trusted; - sd_bus_set_monitor; - sd_bus_is_monitor; - sd_bus_set_description; - sd_bus_get_description; + /* sd_bus_is_server; */ + /* sd_bus_set_anonymous; */ + /* sd_bus_is_anonymous; */ + /* sd_bus_set_trusted; */ + /* sd_bus_is_trusted; */ + /* sd_bus_set_monitor; */ + /* sd_bus_is_monitor; */ + /* sd_bus_set_description; */ + /* sd_bus_get_description; */ sd_bus_negotiate_creds; - sd_bus_negotiate_timestamp; - sd_bus_negotiate_fds; + /* sd_bus_negotiate_timestamp; */ + /* sd_bus_negotiate_fds; */ sd_bus_can_send; - sd_bus_get_creds_mask; + /* sd_bus_get_creds_mask; */ sd_bus_set_allow_interactive_authorization; - sd_bus_get_allow_interactive_authorization; + /* sd_bus_get_allow_interactive_authorization; */ sd_bus_start; sd_bus_close; sd_bus_try_close; sd_bus_ref; sd_bus_unref; - sd_bus_is_open; - sd_bus_get_bus_id; - sd_bus_get_scope; - sd_bus_get_tid; + /* sd_bus_is_open; */ + /* sd_bus_get_bus_id; */ + /* sd_bus_get_scope; */ + /* sd_bus_get_tid; */ sd_bus_get_owner_creds; sd_bus_send; sd_bus_send_to; @@ -222,10 +222,10 @@ global: sd_bus_get_events; sd_bus_get_timeout; sd_bus_process; - sd_bus_process_priority; + /* sd_bus_process_priority; */ sd_bus_wait; sd_bus_flush; - sd_bus_get_current_slot; + /* sd_bus_get_current_slot; */ sd_bus_get_current_message; sd_bus_get_current_handler; sd_bus_get_current_userdata; @@ -239,32 +239,32 @@ global: sd_bus_add_object_vtable; sd_bus_add_fallback_vtable; sd_bus_add_node_enumerator; - sd_bus_add_object_manager; + /* sd_bus_add_object_manager; */ sd_bus_slot_ref; sd_bus_slot_unref; - sd_bus_slot_get_bus; - sd_bus_slot_get_userdata; - sd_bus_slot_set_userdata; - sd_bus_slot_get_description; - sd_bus_slot_set_description; - sd_bus_slot_get_current_message; - sd_bus_slot_get_current_handler; - sd_bus_slot_get_current_userdata; + /* sd_bus_slot_get_bus; */ + /* sd_bus_slot_get_userdata; */ + /* sd_bus_slot_set_userdata; */ + /* sd_bus_slot_get_description; */ + /* sd_bus_slot_set_description; */ + /* sd_bus_slot_get_current_message; */ + /* sd_bus_slot_get_current_handler; */ + /* sd_bus_slot_get_current_userdata; */ sd_bus_message_new_signal; sd_bus_message_new_method_call; sd_bus_message_new_method_return; sd_bus_message_new_method_error; sd_bus_message_new_method_errorf; sd_bus_message_new_method_errno; - sd_bus_message_new_method_errnof; + /* sd_bus_message_new_method_errnof; */ sd_bus_message_ref; sd_bus_message_unref; - sd_bus_message_get_type; - sd_bus_message_get_cookie; - sd_bus_message_get_reply_cookie; - sd_bus_message_get_priority; - sd_bus_message_get_expect_reply; - sd_bus_message_get_auto_start; + /* sd_bus_message_get_type; */ + /* sd_bus_message_get_cookie; */ + /* sd_bus_message_get_reply_cookie; */ + /* sd_bus_message_get_priority; */ + /* sd_bus_message_get_expect_reply; */ + /* sd_bus_message_get_auto_start; */ sd_bus_message_get_allow_interactive_authorization; sd_bus_message_get_signature; sd_bus_message_get_path; @@ -274,30 +274,30 @@ global: sd_bus_message_get_sender; sd_bus_message_get_error; sd_bus_message_get_errno; - sd_bus_message_get_monotonic_usec; - sd_bus_message_get_realtime_usec; - sd_bus_message_get_seqnum; + /* sd_bus_message_get_monotonic_usec; */ + /* sd_bus_message_get_realtime_usec; */ + /* sd_bus_message_get_seqnum; */ sd_bus_message_get_bus; sd_bus_message_get_creds; - sd_bus_message_is_signal; + /* sd_bus_message_is_signal; */ sd_bus_message_is_method_call; sd_bus_message_is_method_error; - sd_bus_message_is_empty; - sd_bus_message_has_signature; - sd_bus_message_set_expect_reply; + /* sd_bus_message_is_empty; */ + /* sd_bus_message_has_signature; */ + /* sd_bus_message_set_expect_reply; */ sd_bus_message_set_auto_start; - sd_bus_message_set_allow_interactive_authorization; + /* sd_bus_message_set_allow_interactive_authorization; */ sd_bus_message_set_destination; - sd_bus_message_set_priority; + /* sd_bus_message_set_priority; */ sd_bus_message_append; sd_bus_message_append_basic; sd_bus_message_append_array; sd_bus_message_append_array_space; - sd_bus_message_append_array_iovec; - sd_bus_message_append_array_memfd; + /* sd_bus_message_append_array_iovec; */ + /* sd_bus_message_append_array_memfd; */ sd_bus_message_append_string_space; - sd_bus_message_append_string_iovec; - sd_bus_message_append_string_memfd; + /* sd_bus_message_append_string_iovec; */ + /* sd_bus_message_append_string_memfd; */ sd_bus_message_append_strv; sd_bus_message_open_container; sd_bus_message_close_container; @@ -310,27 +310,27 @@ global: sd_bus_message_enter_container; sd_bus_message_exit_container; sd_bus_message_peek_type; - sd_bus_message_verify_type; - sd_bus_message_at_end; + /* sd_bus_message_verify_type; */ + /* sd_bus_message_at_end; */ sd_bus_message_rewind; sd_bus_get_unique_name; sd_bus_request_name; sd_bus_release_name; sd_bus_list_names; sd_bus_get_name_creds; - sd_bus_get_name_machine_id; + /* sd_bus_get_name_machine_id; */ sd_bus_call_method; - sd_bus_call_method_async; + /* sd_bus_call_method_async; */ sd_bus_get_property; - sd_bus_get_property_trivial; + /* sd_bus_get_property_trivial; */ sd_bus_get_property_string; - sd_bus_get_property_strv; - sd_bus_set_property; + /* sd_bus_get_property_strv; */ + /* sd_bus_set_property; */ sd_bus_reply_method_return; sd_bus_reply_method_error; sd_bus_reply_method_errorf; sd_bus_reply_method_errno; - sd_bus_reply_method_errnof; + /* sd_bus_reply_method_errnof; */ sd_bus_emit_signal; sd_bus_emit_properties_changed_strv; sd_bus_emit_properties_changed; @@ -340,45 +340,45 @@ global: sd_bus_emit_interfaces_removed; sd_bus_query_sender_creds; sd_bus_query_sender_privilege; - sd_bus_creds_new_from_pid; + /* sd_bus_creds_new_from_pid; */ sd_bus_creds_ref; sd_bus_creds_unref; - sd_bus_creds_get_mask; + /* sd_bus_creds_get_mask; */ sd_bus_creds_get_augmented_mask; sd_bus_creds_get_pid; - sd_bus_creds_get_ppid; + /* sd_bus_creds_get_ppid; */ sd_bus_creds_get_tid; sd_bus_creds_get_uid; sd_bus_creds_get_euid; - sd_bus_creds_get_suid; - sd_bus_creds_get_fsuid; - sd_bus_creds_get_gid; + /* sd_bus_creds_get_suid; */ + /* sd_bus_creds_get_fsuid; */ + /* sd_bus_creds_get_gid; */ sd_bus_creds_get_egid; - sd_bus_creds_get_sgid; - sd_bus_creds_get_fsgid; - sd_bus_creds_get_supplementary_gids; - sd_bus_creds_get_comm; - sd_bus_creds_get_tid_comm; - sd_bus_creds_get_exe; + /* sd_bus_creds_get_sgid; */ + /* sd_bus_creds_get_fsgid; */ + /* sd_bus_creds_get_supplementary_gids; */ + /* sd_bus_creds_get_comm; */ + /* sd_bus_creds_get_tid_comm; */ + /* sd_bus_creds_get_exe; */ sd_bus_creds_get_cmdline; - sd_bus_creds_get_cgroup; - sd_bus_creds_get_unit; - sd_bus_creds_get_slice; - sd_bus_creds_get_user_unit; - sd_bus_creds_get_user_slice; + /* sd_bus_creds_get_cgroup; */ + /* sd_bus_creds_get_unit; */ + /* sd_bus_creds_get_slice; */ + /* sd_bus_creds_get_user_unit; */ + /* sd_bus_creds_get_user_slice; */ sd_bus_creds_get_session; sd_bus_creds_get_owner_uid; sd_bus_creds_has_effective_cap; - sd_bus_creds_has_permitted_cap; - sd_bus_creds_has_inheritable_cap; - sd_bus_creds_has_bounding_cap; + /* sd_bus_creds_has_permitted_cap; */ + /* sd_bus_creds_has_inheritable_cap; */ + /* sd_bus_creds_has_bounding_cap; */ sd_bus_creds_get_selinux_context; - sd_bus_creds_get_audit_session_id; + /* sd_bus_creds_get_audit_session_id; */ sd_bus_creds_get_audit_login_uid; sd_bus_creds_get_tty; - sd_bus_creds_get_unique_name; - sd_bus_creds_get_well_known_names; - sd_bus_creds_get_description; + /* sd_bus_creds_get_unique_name; */ + /* sd_bus_creds_get_well_known_names; */ + /* sd_bus_creds_get_description; */ sd_bus_error_free; sd_bus_error_set; sd_bus_error_setf; @@ -391,14 +391,14 @@ global: sd_bus_error_is_set; sd_bus_error_has_name; sd_bus_error_add_map; - sd_bus_path_encode; - sd_bus_path_decode; + /* sd_bus_path_encode; */ + /* sd_bus_path_decode; */ sd_bus_track_new; sd_bus_track_ref; sd_bus_track_unref; sd_bus_track_get_bus; - sd_bus_track_get_userdata; - sd_bus_track_set_userdata; + /* sd_bus_track_get_userdata; */ + /* sd_bus_track_set_userdata; */ sd_bus_track_add_sender; sd_bus_track_remove_sender; sd_bus_track_add_name; @@ -424,47 +424,47 @@ global: sd_event_wait; sd_event_dispatch; sd_event_run; - sd_event_loop; + /* sd_event_loop; */ sd_event_exit; - sd_event_now; - sd_event_get_fd; + /* sd_event_now; */ + /* sd_event_get_fd; */ sd_event_get_state; sd_event_get_tid; sd_event_get_exit_code; sd_event_set_watchdog; - sd_event_get_watchdog; - sd_event_source_ref; + /* sd_event_get_watchdog; */ + /* sd_event_source_ref; */ sd_event_source_unref; sd_event_source_get_event; - sd_event_source_get_userdata; - sd_event_source_set_userdata; + /* sd_event_source_get_userdata; */ + /* sd_event_source_set_userdata; */ sd_event_source_set_description; - sd_event_source_get_description; + /* sd_event_source_get_description; */ sd_event_source_set_prepare; - sd_event_source_get_pending; - sd_event_source_get_priority; + /* sd_event_source_get_pending; */ + /* sd_event_source_get_priority; */ sd_event_source_set_priority; - sd_event_source_get_enabled; + /* sd_event_source_get_enabled; */ sd_event_source_set_enabled; - sd_event_source_get_io_fd; + /* sd_event_source_get_io_fd; */ sd_event_source_set_io_fd; - sd_event_source_get_io_events; + /* sd_event_source_get_io_events; */ sd_event_source_set_io_events; - sd_event_source_get_io_revents; + /* sd_event_source_get_io_revents; */ sd_event_source_get_time; sd_event_source_set_time; - sd_event_source_set_time_accuracy; - sd_event_source_get_time_accuracy; - sd_event_source_get_time_clock; - sd_event_source_get_signal; - sd_event_source_get_child_pid; + /* sd_event_source_set_time_accuracy; */ + /* sd_event_source_get_time_accuracy; */ + /* sd_event_source_get_time_clock; */ + /* sd_event_source_get_signal; */ + /* sd_event_source_get_child_pid; */ } LIBSYSTEMD_220; LIBSYSTEMD_222 { global: /* sd-bus */ sd_bus_emit_object_added; - sd_bus_emit_object_removed; + /* sd_bus_emit_object_removed; */ sd_bus_flush_close_unref; } LIBSYSTEMD_221; diff --git a/src/libelogind/libelogind.sym.m4 b/src/libelogind/libelogind.sym.m4 deleted file mode 100644 index 3121e7128..000000000 --- a/src/libelogind/libelogind.sym.m4 +++ /dev/null @@ -1,499 +0,0 @@ -/*** - This file is part of systemd. - - 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. -***/ - -LIBSYSTEMD_209 { -global: - /* sd-journal */ - sd_journal_print; - sd_journal_printv; - sd_journal_send; - sd_journal_sendv; - sd_journal_stream_fd; - sd_journal_open; - sd_journal_close; - sd_journal_previous; - sd_journal_next; - sd_journal_previous_skip; - sd_journal_next_skip; - sd_journal_get_realtime_usec; - sd_journal_get_monotonic_usec; - sd_journal_get_data; - sd_journal_enumerate_data; - sd_journal_restart_data; - sd_journal_add_match; - sd_journal_flush_matches; - sd_journal_seek_head; - sd_journal_seek_tail; - sd_journal_seek_monotonic_usec; - sd_journal_seek_realtime_usec; - sd_journal_seek_cursor; - sd_journal_get_cursor; - sd_journal_get_fd; - sd_journal_process; - sd_journal_print_with_location; - sd_journal_printv_with_location; - sd_journal_send_with_location; - sd_journal_sendv_with_location; - sd_journal_get_cutoff_realtime_usec; - sd_journal_get_cutoff_monotonic_usec; - sd_journal_wait; - sd_journal_open_directory; - sd_journal_add_disjunction; - sd_journal_perror; - sd_journal_perror_with_location; - sd_journal_get_usage; - sd_journal_test_cursor; - sd_journal_query_unique; - sd_journal_enumerate_unique; - sd_journal_restart_unique; - sd_journal_get_catalog; - sd_journal_get_catalog_for_message_id; - sd_journal_set_data_threshold; - sd_journal_get_data_threshold; - sd_journal_reliable_fd; - sd_journal_get_events; - sd_journal_get_timeout; - sd_journal_add_conjunction; - sd_journal_open_files; - sd_journal_open_container; - - /* sd-daemon */ - sd_booted; - sd_is_fifo; - sd_is_mq; - sd_is_socket; - sd_is_socket_inet; - sd_is_socket_unix; - sd_is_special; - sd_listen_fds; - sd_notify; - sd_notifyf; - sd_watchdog_enabled; - - /* sd-id128 */ - sd_id128_to_string; - sd_id128_from_string; - sd_id128_randomize; - sd_id128_get_machine; - sd_id128_get_boot; - - /* sd-login */ - sd_get_seats; - sd_get_sessions; - sd_get_uids; - sd_login_monitor_flush; - sd_login_monitor_get_fd; - sd_login_monitor_new; - sd_login_monitor_unref; - sd_pid_get_owner_uid; - sd_pid_get_session; - sd_seat_can_multi_session; - sd_seat_get_active; - sd_seat_get_sessions; - sd_session_get_seat; - sd_session_get_uid; - sd_session_is_active; - sd_uid_get_seats; - sd_uid_get_sessions; - sd_uid_get_state; - sd_uid_is_on_seat; - sd_pid_get_unit; - sd_session_get_service; - sd_session_get_type; - sd_session_get_class; - sd_session_get_display; - sd_session_get_state; - sd_seat_can_tty; - sd_seat_can_graphical; - sd_session_get_tty; - sd_login_monitor_get_events; - sd_login_monitor_get_timeout; - sd_pid_get_user_unit; - sd_pid_get_machine_name; - sd_get_machine_names; - sd_pid_get_slice; - sd_session_get_vt; - sd_session_is_remote; - sd_session_get_remote_user; - sd_session_get_remote_host; -local: - *; -}; - -LIBSYSTEMD_211 { -global: - sd_machine_get_class; - sd_peer_get_session; - sd_peer_get_owner_uid; - sd_peer_get_unit; - sd_peer_get_user_unit; - sd_peer_get_machine_name; - sd_peer_get_slice; -} LIBSYSTEMD_209; - -LIBSYSTEMD_213 { -global: - sd_uid_get_display; -} LIBSYSTEMD_211; - -LIBSYSTEMD_214 { -global: - sd_pid_notify; - sd_pid_notifyf; -} LIBSYSTEMD_213; - -LIBSYSTEMD_216 { -global: - sd_machine_get_ifindices; -} LIBSYSTEMD_214; - -LIBSYSTEMD_217 { -global: - sd_session_get_desktop; -} LIBSYSTEMD_216; - -LIBSYSTEMD_219 { -global: - sd_pid_notify_with_fds; -} LIBSYSTEMD_217; - -LIBSYSTEMD_220 { -global: - sd_pid_get_user_slice; - sd_peer_get_user_slice; -} LIBSYSTEMD_219; - -LIBSYSTEMD_221 { -global: - /* sd-bus */ - sd_bus_default; - sd_bus_default_user; - sd_bus_default_system; - sd_bus_open; - sd_bus_open_user; - sd_bus_open_system; - sd_bus_open_system_remote; - sd_bus_open_system_machine; - sd_bus_new; - sd_bus_set_address; - sd_bus_set_fd; - sd_bus_set_exec; - sd_bus_get_address; - sd_bus_set_bus_client; - sd_bus_is_bus_client; - sd_bus_set_server; - sd_bus_is_server; - sd_bus_set_anonymous; - sd_bus_is_anonymous; - sd_bus_set_trusted; - sd_bus_is_trusted; - sd_bus_set_monitor; - sd_bus_is_monitor; - sd_bus_set_description; - sd_bus_get_description; - sd_bus_negotiate_creds; - sd_bus_negotiate_timestamp; - sd_bus_negotiate_fds; - sd_bus_can_send; - sd_bus_get_creds_mask; - sd_bus_set_allow_interactive_authorization; - sd_bus_get_allow_interactive_authorization; - sd_bus_start; - sd_bus_close; - sd_bus_try_close; - sd_bus_ref; - sd_bus_unref; - sd_bus_is_open; - sd_bus_get_bus_id; - sd_bus_get_scope; - sd_bus_get_tid; - sd_bus_get_owner_creds; - sd_bus_send; - sd_bus_send_to; - sd_bus_call; - sd_bus_call_async; - sd_bus_get_fd; - sd_bus_get_events; - sd_bus_get_timeout; - sd_bus_process; - sd_bus_process_priority; - sd_bus_wait; - sd_bus_flush; - sd_bus_get_current_slot; - sd_bus_get_current_message; - sd_bus_get_current_handler; - sd_bus_get_current_userdata; - sd_bus_attach_event; - sd_bus_detach_event; - sd_bus_get_event; - sd_bus_add_filter; - sd_bus_add_match; - sd_bus_add_object; - sd_bus_add_fallback; - sd_bus_add_object_vtable; - sd_bus_add_fallback_vtable; - sd_bus_add_node_enumerator; - sd_bus_add_object_manager; - sd_bus_slot_ref; - sd_bus_slot_unref; - sd_bus_slot_get_bus; - sd_bus_slot_get_userdata; - sd_bus_slot_set_userdata; - sd_bus_slot_get_description; - sd_bus_slot_set_description; - sd_bus_slot_get_current_message; - sd_bus_slot_get_current_handler; - sd_bus_slot_get_current_userdata; - sd_bus_message_new_signal; - sd_bus_message_new_method_call; - sd_bus_message_new_method_return; - sd_bus_message_new_method_error; - sd_bus_message_new_method_errorf; - sd_bus_message_new_method_errno; - sd_bus_message_new_method_errnof; - sd_bus_message_ref; - sd_bus_message_unref; - sd_bus_message_get_type; - sd_bus_message_get_cookie; - sd_bus_message_get_reply_cookie; - sd_bus_message_get_priority; - sd_bus_message_get_expect_reply; - sd_bus_message_get_auto_start; - sd_bus_message_get_allow_interactive_authorization; - sd_bus_message_get_signature; - sd_bus_message_get_path; - sd_bus_message_get_interface; - sd_bus_message_get_member; - sd_bus_message_get_destination; - sd_bus_message_get_sender; - sd_bus_message_get_error; - sd_bus_message_get_errno; - sd_bus_message_get_monotonic_usec; - sd_bus_message_get_realtime_usec; - sd_bus_message_get_seqnum; - sd_bus_message_get_bus; - sd_bus_message_get_creds; - sd_bus_message_is_signal; - sd_bus_message_is_method_call; - sd_bus_message_is_method_error; - sd_bus_message_is_empty; - sd_bus_message_has_signature; - sd_bus_message_set_expect_reply; - sd_bus_message_set_auto_start; - sd_bus_message_set_allow_interactive_authorization; - sd_bus_message_set_destination; - sd_bus_message_set_priority; - sd_bus_message_append; - sd_bus_message_append_basic; - sd_bus_message_append_array; - sd_bus_message_append_array_space; - sd_bus_message_append_array_iovec; - sd_bus_message_append_array_memfd; - sd_bus_message_append_string_space; - sd_bus_message_append_string_iovec; - sd_bus_message_append_string_memfd; - sd_bus_message_append_strv; - sd_bus_message_open_container; - sd_bus_message_close_container; - sd_bus_message_copy; - sd_bus_message_read; - sd_bus_message_read_basic; - sd_bus_message_read_array; - sd_bus_message_read_strv; - sd_bus_message_skip; - sd_bus_message_enter_container; - sd_bus_message_exit_container; - sd_bus_message_peek_type; - sd_bus_message_verify_type; - sd_bus_message_at_end; - sd_bus_message_rewind; - sd_bus_get_unique_name; - sd_bus_request_name; - sd_bus_release_name; - sd_bus_list_names; - sd_bus_get_name_creds; - sd_bus_get_name_machine_id; - sd_bus_call_method; - sd_bus_call_method_async; - sd_bus_get_property; - sd_bus_get_property_trivial; - sd_bus_get_property_string; - sd_bus_get_property_strv; - sd_bus_set_property; - sd_bus_reply_method_return; - sd_bus_reply_method_error; - sd_bus_reply_method_errorf; - sd_bus_reply_method_errno; - sd_bus_reply_method_errnof; - sd_bus_emit_signal; - sd_bus_emit_properties_changed_strv; - sd_bus_emit_properties_changed; - sd_bus_emit_interfaces_added_strv; - sd_bus_emit_interfaces_added; - sd_bus_emit_interfaces_removed_strv; - sd_bus_emit_interfaces_removed; - sd_bus_query_sender_creds; - sd_bus_query_sender_privilege; - sd_bus_creds_new_from_pid; - sd_bus_creds_ref; - sd_bus_creds_unref; - sd_bus_creds_get_mask; - sd_bus_creds_get_augmented_mask; - sd_bus_creds_get_pid; - sd_bus_creds_get_ppid; - sd_bus_creds_get_tid; - sd_bus_creds_get_uid; - sd_bus_creds_get_euid; - sd_bus_creds_get_suid; - sd_bus_creds_get_fsuid; - sd_bus_creds_get_gid; - sd_bus_creds_get_egid; - sd_bus_creds_get_sgid; - sd_bus_creds_get_fsgid; - sd_bus_creds_get_supplementary_gids; - sd_bus_creds_get_comm; - sd_bus_creds_get_tid_comm; - sd_bus_creds_get_exe; - sd_bus_creds_get_cmdline; - sd_bus_creds_get_cgroup; - sd_bus_creds_get_unit; - sd_bus_creds_get_slice; - sd_bus_creds_get_user_unit; - sd_bus_creds_get_user_slice; - sd_bus_creds_get_session; - sd_bus_creds_get_owner_uid; - sd_bus_creds_has_effective_cap; - sd_bus_creds_has_permitted_cap; - sd_bus_creds_has_inheritable_cap; - sd_bus_creds_has_bounding_cap; - sd_bus_creds_get_selinux_context; - sd_bus_creds_get_audit_session_id; - sd_bus_creds_get_audit_login_uid; - sd_bus_creds_get_tty; - sd_bus_creds_get_unique_name; - sd_bus_creds_get_well_known_names; - sd_bus_creds_get_description; - sd_bus_error_free; - sd_bus_error_set; - sd_bus_error_setf; - sd_bus_error_set_const; - sd_bus_error_set_errno; - sd_bus_error_set_errnof; - sd_bus_error_set_errnofv; - sd_bus_error_get_errno; - sd_bus_error_copy; - sd_bus_error_is_set; - sd_bus_error_has_name; - sd_bus_error_add_map; - sd_bus_path_encode; - sd_bus_path_decode; - sd_bus_track_new; - sd_bus_track_ref; - sd_bus_track_unref; - sd_bus_track_get_bus; - sd_bus_track_get_userdata; - sd_bus_track_set_userdata; - sd_bus_track_add_sender; - sd_bus_track_remove_sender; - sd_bus_track_add_name; - sd_bus_track_remove_name; - sd_bus_track_count; - sd_bus_track_contains; - sd_bus_track_first; - sd_bus_track_next; - - /* sd-event */ - sd_event_default; - sd_event_new; - sd_event_ref; - sd_event_unref; - sd_event_add_io; - sd_event_add_time; - sd_event_add_signal; - sd_event_add_child; - sd_event_add_defer; - sd_event_add_post; - sd_event_add_exit; - sd_event_prepare; - sd_event_wait; - sd_event_dispatch; - sd_event_run; - sd_event_loop; - sd_event_exit; - sd_event_now; - sd_event_get_fd; - sd_event_get_state; - sd_event_get_tid; - sd_event_get_exit_code; - sd_event_set_watchdog; - sd_event_get_watchdog; - sd_event_source_ref; - sd_event_source_unref; - sd_event_source_get_event; - sd_event_source_get_userdata; - sd_event_source_set_userdata; - sd_event_source_set_description; - sd_event_source_get_description; - sd_event_source_set_prepare; - sd_event_source_get_pending; - sd_event_source_get_priority; - sd_event_source_set_priority; - sd_event_source_get_enabled; - sd_event_source_set_enabled; - sd_event_source_get_io_fd; - sd_event_source_set_io_fd; - sd_event_source_get_io_events; - sd_event_source_set_io_events; - sd_event_source_get_io_revents; - sd_event_source_get_time; - sd_event_source_set_time; - sd_event_source_set_time_accuracy; - sd_event_source_get_time_accuracy; - sd_event_source_get_time_clock; - sd_event_source_get_signal; - sd_event_source_get_child_pid; -} LIBSYSTEMD_220; - -m4_ifdef(`ENABLE_KDBUS', -LIBSYSTEMD_FUTURE { -global: - /* sd-utf8 */ - sd_utf8_is_valid; - sd_ascii_is_valid; - - /* sd-resolve */ - sd_resolve_default; - sd_resolve_new; - sd_resolve_ref; - sd_resolve_unref; - sd_resolve_get_fd; - sd_resolve_get_events; - sd_resolve_get_timeout; - sd_resolve_process; - sd_resolve_wait; - sd_resolve_get_tid; - sd_resolve_attach_event; - sd_resolve_detach_event; - sd_resolve_get_event; - sd_resolve_getaddrinfo; - sd_resolve_getnameinfo; - sd_resolve_res_query; - sd_resolve_res_search; - sd_resolve_query_ref; - sd_resolve_query_unref; - sd_resolve_query_is_done; - sd_resolve_query_get_userdata; - sd_resolve_query_set_userdata; - sd_resolve_query_get_resolve; - - /* sd-path */ - sd_path_home; - sd_path_search; -} LIBSYSTEMD_220; -) diff --git a/src/libelogind/sd-bus/Makefile b/src/libelogind/sd-bus/Makefile deleted file mode 120000 index 94aaae2c4..000000000 --- a/src/libelogind/sd-bus/Makefile +++ /dev/null @@ -1 +0,0 @@ -../../Makefile \ No newline at end of file diff --git a/src/libelogind/sd-bus/bus-introspect.h b/src/libelogind/sd-bus/bus-introspect.h index 6aac650ac..1914e6cb8 100644 --- a/src/libelogind/sd-bus/bus-introspect.h +++ b/src/libelogind/sd-bus/bus-introspect.h @@ -5,7 +5,7 @@ /*** This file is part of systemd. - Copyright 2014 David Herrmann + Copyright 2013 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 @@ -21,47 +21,21 @@ along with systemd; If not, see . ***/ -#include "sd-bus.h" -#include "bus-xml-policy.h" - -typedef struct Proxy Proxy; -typedef struct ProxyActivation ProxyActivation; - -#define PROXY_ACTIVATIONS_MAX (16) /* max parallel activation requests */ - -struct Proxy { - sd_bus *local_bus; - struct ucred local_creds; - int local_in; - int local_out; - - sd_bus *destination_bus; - - Set *owned_names; - SharedPolicy *policy; +#include - LIST_HEAD(ProxyActivation, activations); - size_t n_activations; - - bool got_hello : 1; - bool queue_overflow : 1; - bool message_matched : 1; - bool synthetic_matched : 1; -}; +#include "sd-bus.h" +#include "set.h" -struct ProxyActivation { - LIST_FIELDS(ProxyActivation, activations_by_proxy); - Proxy *proxy; - sd_bus_message *request; - sd_bus_slot *slot; +struct introspect { + FILE *f; + char *introspection; + size_t size; + bool trusted; }; -int proxy_new(Proxy **out, int in_fd, int out_fd, const char *dest); -Proxy *proxy_free(Proxy *p); - -int proxy_set_policy(Proxy *p, SharedPolicy *policy, char **configuration); -int proxy_hello_policy(Proxy *p, uid_t original_uid); -int proxy_match(sd_bus_message *m, void *userdata, sd_bus_error *error); -int proxy_run(Proxy *p); - -DEFINE_TRIVIAL_CLEANUP_FUNC(Proxy*, proxy_free); +int introspect_begin(struct introspect *i, bool trusted); +int introspect_write_default_interfaces(struct introspect *i, bool object_manager); +int introspect_write_child_nodes(struct introspect *i, Set *s, const char *prefix); +int introspect_write_interface(struct introspect *i, const sd_bus_vtable *v); +int introspect_finish(struct introspect *i, sd_bus *bus, sd_bus_message *m, sd_bus_message **reply); +void introspect_free(struct introspect *i); diff --git a/src/libelogind/sd-bus/bus-slot.h b/src/libelogind/sd-bus/bus-slot.h index da3834f8b..23a15e4d0 100644 --- a/src/libelogind/sd-bus/bus-slot.h +++ b/src/libelogind/sd-bus/bus-slot.h @@ -22,7 +22,8 @@ ***/ #include "sd-bus.h" -#include "bus-xml-policy.h" -#include "proxy.h" +#include "bus-internal.h" -int bus_proxy_process_driver(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m, SharedPolicy *sp, const struct ucred *ucred, Set *owned_names); +sd_bus_slot *bus_slot_allocate(sd_bus *bus, bool floating, BusSlotType type, size_t extra, void *userdata); + +void bus_slot_disconnect(sd_bus_slot *slot); diff --git a/src/libelogind/sd-bus/busctl.c b/src/libelogind/sd-bus/busctl.c deleted file mode 100644 index 6aaaf0e5e..000000000 --- a/src/libelogind/sd-bus/busctl.c +++ /dev/null @@ -1,2073 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2013 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 . -***/ - -#include - -#include "strv.h" -#include "util.h" -#include "log.h" -#include "build.h" -#include "pager.h" -#include "path-util.h" -#include "set.h" - -#include "sd-bus.h" -#include "bus-internal.h" -#include "bus-util.h" -#include "bus-dump.h" -#include "bus-signature.h" -#include "bus-type.h" -#include "busctl-introspect.h" -#include "terminal-util.h" - -static bool arg_no_pager = false; -static bool arg_legend = true; -static char *arg_address = NULL; -static bool arg_unique = false; -static bool arg_acquired = false; -static bool arg_activatable = false; -static bool arg_show_machine = false; -static char **arg_matches = NULL; -static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; -static char *arg_host = NULL; -static bool arg_user = false; -static size_t arg_snaplen = 4096; -static bool arg_list = false; -static bool arg_quiet = false; -static bool arg_verbose = false; -static bool arg_expect_reply = true; -static bool arg_auto_start = true; -static bool arg_allow_interactive_authorization = true; -static bool arg_augment_creds = true; -static usec_t arg_timeout = 0; - -static void pager_open_if_enabled(void) { - - /* Cache result before we open the pager */ - if (arg_no_pager) - return; - - pager_open(false); -} - -#define NAME_IS_ACQUIRED INT_TO_PTR(1) -#define NAME_IS_ACTIVATABLE INT_TO_PTR(2) - -static int list_bus_names(sd_bus *bus, char **argv) { - _cleanup_strv_free_ char **acquired = NULL, **activatable = NULL; - _cleanup_free_ char **merged = NULL; - _cleanup_hashmap_free_ Hashmap *names = NULL; - char **i; - int r; - size_t max_i = 0; - unsigned n = 0; - void *v; - char *k; - Iterator iterator; - - assert(bus); - - if (!arg_unique && !arg_acquired && !arg_activatable) - arg_unique = arg_acquired = arg_activatable = true; - - r = sd_bus_list_names(bus, (arg_acquired || arg_unique) ? &acquired : NULL, arg_activatable ? &activatable : NULL); - if (r < 0) - return log_error_errno(r, "Failed to list names: %m"); - - pager_open_if_enabled(); - - names = hashmap_new(&string_hash_ops); - if (!names) - return log_oom(); - - STRV_FOREACH(i, acquired) { - max_i = MAX(max_i, strlen(*i)); - - r = hashmap_put(names, *i, NAME_IS_ACQUIRED); - if (r < 0) - return log_error_errno(r, "Failed to add to hashmap: %m"); - } - - STRV_FOREACH(i, activatable) { - max_i = MAX(max_i, strlen(*i)); - - r = hashmap_put(names, *i, NAME_IS_ACTIVATABLE); - if (r < 0 && r != -EEXIST) - return log_error_errno(r, "Failed to add to hashmap: %m"); - } - - merged = new(char*, hashmap_size(names) + 1); - HASHMAP_FOREACH_KEY(v, k, names, iterator) - merged[n++] = k; - - merged[n] = NULL; - strv_sort(merged); - - if (arg_legend) { - printf("%-*s %*s %-*s %-*s %-*s %-*s %-*s %-*s", - (int) max_i, "NAME", 10, "PID", 15, "PROCESS", 16, "USER", 13, "CONNECTION", 25, "UNIT", 10, "SESSION", 19, "DESCRIPTION"); - - if (arg_show_machine) - puts(" MACHINE"); - else - putchar('\n'); - } - - STRV_FOREACH(i, merged) { - _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; - sd_id128_t mid; - - if (hashmap_get(names, *i) == NAME_IS_ACTIVATABLE) { - /* Activatable */ - - printf("%-*s", (int) max_i, *i); - printf(" - - - (activatable) - - "); - if (arg_show_machine) - puts(" -"); - else - putchar('\n'); - continue; - - } - - if (!arg_unique && (*i)[0] == ':') - continue; - - if (!arg_acquired && (*i)[0] != ':') - continue; - - printf("%-*s", (int) max_i, *i); - - r = sd_bus_get_name_creds( - bus, *i, - (arg_augment_creds ? SD_BUS_CREDS_AUGMENT : 0) | - SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM| - SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_SESSION| - SD_BUS_CREDS_DESCRIPTION, &creds); - if (r >= 0) { - const char *unique, *session, *unit, *cn; - pid_t pid; - uid_t uid; - - r = sd_bus_creds_get_pid(creds, &pid); - if (r >= 0) { - const char *comm = NULL; - - sd_bus_creds_get_comm(creds, &comm); - - printf(" %10lu %-15s", (unsigned long) pid, strna(comm)); - } else - fputs(" - - ", stdout); - - r = sd_bus_creds_get_euid(creds, &uid); - if (r >= 0) { - _cleanup_free_ char *u = NULL; - - u = uid_to_name(uid); - if (!u) - return log_oom(); - - if (strlen(u) > 16) - u[16] = 0; - - printf(" %-16s", u); - } else - fputs(" - ", stdout); - - r = sd_bus_creds_get_unique_name(creds, &unique); - if (r >= 0) - printf(" %-13s", unique); - else - fputs(" - ", stdout); - - r = sd_bus_creds_get_unit(creds, &unit); - if (r >= 0) { - _cleanup_free_ char *e; - - e = ellipsize(unit, 25, 100); - if (!e) - return log_oom(); - - printf(" %-25s", e); - } else - fputs(" - ", stdout); - - r = sd_bus_creds_get_session(creds, &session); - if (r >= 0) - printf(" %-10s", session); - else - fputs(" - ", stdout); - - r = sd_bus_creds_get_description(creds, &cn); - if (r >= 0) - printf(" %-19s", cn); - else - fputs(" - ", stdout); - - } else - printf(" - - - - - - - "); - - if (arg_show_machine) { - r = sd_bus_get_name_machine_id(bus, *i, &mid); - if (r >= 0) { - char m[SD_ID128_STRING_MAX]; - printf(" %s\n", sd_id128_to_string(mid, m)); - } else - puts(" -"); - } else - putchar('\n'); - } - - return 0; -} - -static void print_subtree(const char *prefix, const char *path, char **l) { - const char *vertical, *space; - char **n; - - /* We assume the list is sorted. Let's first skip over the - * entry we are looking at. */ - for (;;) { - if (!*l) - return; - - if (!streq(*l, path)) - break; - - l++; - } - - vertical = strjoina(prefix, draw_special_char(DRAW_TREE_VERTICAL)); - space = strjoina(prefix, draw_special_char(DRAW_TREE_SPACE)); - - for (;;) { - bool has_more = false; - - if (!*l || !path_startswith(*l, path)) - break; - - n = l + 1; - for (;;) { - if (!*n || !path_startswith(*n, path)) - break; - - if (!path_startswith(*n, *l)) { - has_more = true; - break; - } - - n++; - } - - printf("%s%s%s\n", prefix, draw_special_char(has_more ? DRAW_TREE_BRANCH : DRAW_TREE_RIGHT), *l); - - print_subtree(has_more ? vertical : space, *l, l); - l = n; - } -} - -static void print_tree(const char *prefix, char **l) { - - pager_open_if_enabled(); - - prefix = strempty(prefix); - - if (arg_list) { - char **i; - - STRV_FOREACH(i, l) - printf("%s%s\n", prefix, *i); - return; - } - - if (strv_isempty(l)) { - printf("No objects discovered.\n"); - return; - } - - if (streq(l[0], "/") && !l[1]) { - printf("Only root object discovered.\n"); - return; - } - - print_subtree(prefix, "/", l); -} - -static int on_path(const char *path, void *userdata) { - Set *paths = userdata; - int r; - - assert(paths); - - r = set_put_strdup(paths, path); - if (r < 0) - return log_oom(); - - return 0; -} - -static int find_nodes(sd_bus *bus, const char *service, const char *path, Set *paths, bool many) { - static const XMLIntrospectOps ops = { - .on_path = on_path, - }; - - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; - const char *xml; - int r; - - r = sd_bus_call_method(bus, service, path, "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, ""); - if (r < 0) { - if (many) - printf("Failed to introspect object %s of service %s: %s\n", path, service, bus_error_message(&error, r)); - else - log_error("Failed to introspect object %s of service %s: %s", path, service, bus_error_message(&error, r)); - return r; - } - - r = sd_bus_message_read(reply, "s", &xml); - if (r < 0) - return bus_log_parse_error(r); - - return parse_xml_introspect(path, xml, &ops, paths); -} - -static int tree_one(sd_bus *bus, const char *service, const char *prefix, bool many) { - _cleanup_set_free_free_ Set *paths = NULL, *done = NULL, *failed = NULL; - _cleanup_free_ char **l = NULL; - char *m; - int r; - - paths = set_new(&string_hash_ops); - if (!paths) - return log_oom(); - - done = set_new(&string_hash_ops); - if (!done) - return log_oom(); - - failed = set_new(&string_hash_ops); - if (!failed) - return log_oom(); - - m = strdup("/"); - if (!m) - return log_oom(); - - r = set_put(paths, m); - if (r < 0) { - free(m); - return log_oom(); - } - - for (;;) { - _cleanup_free_ char *p = NULL; - int q; - - p = set_steal_first(paths); - if (!p) - break; - - if (set_contains(done, p) || - set_contains(failed, p)) - continue; - - q = find_nodes(bus, service, p, paths, many); - if (q < 0) { - if (r >= 0) - r = q; - - q = set_put(failed, p); - } else - q = set_put(done, p); - - if (q < 0) - return log_oom(); - - assert(q != 0); - p = NULL; - } - - pager_open_if_enabled(); - - l = set_get_strv(done); - if (!l) - return log_oom(); - - strv_sort(l); - print_tree(prefix, l); - - fflush(stdout); - - return r; -} - -static int tree(sd_bus *bus, char **argv) { - char **i; - int r = 0; - - if (!arg_unique && !arg_acquired) - arg_acquired = true; - - if (strv_length(argv) <= 1) { - _cleanup_strv_free_ char **names = NULL; - bool not_first = false; - - r = sd_bus_list_names(bus, &names, NULL); - if (r < 0) - return log_error_errno(r, "Failed to get name list: %m"); - - pager_open_if_enabled(); - - STRV_FOREACH(i, names) { - int q; - - if (!arg_unique && (*i)[0] == ':') - continue; - - if (!arg_acquired && (*i)[0] == ':') - continue; - - if (not_first) - printf("\n"); - - printf("Service %s%s%s:\n", ansi_highlight(), *i, ansi_highlight_off()); - - q = tree_one(bus, *i, NULL, true); - if (q < 0 && r >= 0) - r = q; - - not_first = true; - } - } else { - STRV_FOREACH(i, argv+1) { - int q; - - if (i > argv+1) - printf("\n"); - - if (argv[2]) { - pager_open_if_enabled(); - printf("Service %s%s%s:\n", ansi_highlight(), *i, ansi_highlight_off()); - } - - q = tree_one(bus, *i, NULL, !!argv[2]); - if (q < 0 && r >= 0) - r = q; - } - } - - return r; -} - -static int format_cmdline(sd_bus_message *m, FILE *f, bool needs_space) { - int r; - - for (;;) { - const char *contents = NULL; - char type; - union { - uint8_t u8; - uint16_t u16; - int16_t s16; - uint32_t u32; - int32_t s32; - uint64_t u64; - int64_t s64; - double d64; - const char *string; - int i; - } basic; - - r = sd_bus_message_peek_type(m, &type, &contents); - if (r <= 0) - return r; - - if (bus_type_is_container(type) > 0) { - - r = sd_bus_message_enter_container(m, type, contents); - if (r < 0) - return r; - - if (type == SD_BUS_TYPE_ARRAY) { - unsigned n = 0; - - /* count array entries */ - for (;;) { - - r = sd_bus_message_skip(m, contents); - if (r < 0) - return r; - if (r == 0) - break; - - n++; - } - - r = sd_bus_message_rewind(m, false); - if (r < 0) - return r; - - if (needs_space) - fputc(' ', f); - - fprintf(f, "%u", n); - } else if (type == SD_BUS_TYPE_VARIANT) { - - if (needs_space) - fputc(' ', f); - - fprintf(f, "%s", contents); - } - - r = format_cmdline(m, f, needs_space || IN_SET(type, SD_BUS_TYPE_ARRAY, SD_BUS_TYPE_VARIANT)); - if (r < 0) - return r; - - r = sd_bus_message_exit_container(m); - if (r < 0) - return r; - - continue; - } - - r = sd_bus_message_read_basic(m, type, &basic); - if (r < 0) - return r; - - if (needs_space) - fputc(' ', f); - - switch (type) { - case SD_BUS_TYPE_BYTE: - fprintf(f, "%u", basic.u8); - break; - - case SD_BUS_TYPE_BOOLEAN: - fputs(true_false(basic.i), f); - break; - - case SD_BUS_TYPE_INT16: - fprintf(f, "%i", basic.s16); - break; - - case SD_BUS_TYPE_UINT16: - fprintf(f, "%u", basic.u16); - break; - - case SD_BUS_TYPE_INT32: - fprintf(f, "%i", basic.s32); - break; - - case SD_BUS_TYPE_UINT32: - fprintf(f, "%u", basic.u32); - break; - - case SD_BUS_TYPE_INT64: - fprintf(f, "%" PRIi64, basic.s64); - break; - - case SD_BUS_TYPE_UINT64: - fprintf(f, "%" PRIu64, basic.u64); - break; - - case SD_BUS_TYPE_DOUBLE: - fprintf(f, "%g", basic.d64); - break; - - case SD_BUS_TYPE_STRING: - case SD_BUS_TYPE_OBJECT_PATH: - case SD_BUS_TYPE_SIGNATURE: { - _cleanup_free_ char *b = NULL; - - b = cescape(basic.string); - if (!b) - return -ENOMEM; - - fprintf(f, "\"%s\"", b); - break; - } - - case SD_BUS_TYPE_UNIX_FD: - fprintf(f, "%i", basic.i); - break; - - default: - assert_not_reached("Unknown basic type."); - } - - needs_space = true; - } -} - -typedef struct Member { - const char *type; - char *interface; - char *name; - char *signature; - char *result; - char *value; - bool writable; - uint64_t flags; -} Member; - -static unsigned long member_hash_func(const void *p, const uint8_t hash_key[]) { - const Member *m = p; - unsigned long ul; - - assert(m); - assert(m->type); - - ul = string_hash_func(m->type, hash_key); - - if (m->name) - ul ^= string_hash_func(m->name, hash_key); - - if (m->interface) - ul ^= string_hash_func(m->interface, hash_key); - - return ul; -} - -static int member_compare_func(const void *a, const void *b) { - const Member *x = a, *y = b; - int d; - - assert(x); - assert(y); - assert(x->type); - assert(y->type); - - if (!x->interface && y->interface) - return -1; - if (x->interface && !y->interface) - return 1; - if (x->interface && y->interface) { - d = strcmp(x->interface, y->interface); - if (d != 0) - return d; - } - - d = strcmp(x->type, y->type); - if (d != 0) - return d; - - if (!x->name && y->name) - return -1; - if (x->name && !y->name) - return 1; - if (x->name && y->name) - return strcmp(x->name, y->name); - - return 0; -} - -static int member_compare_funcp(const void *a, const void *b) { - const Member *const * x = (const Member *const *) a, * const *y = (const Member *const *) b; - - return member_compare_func(*x, *y); -} - -static void member_free(Member *m) { - if (!m) - return; - - free(m->interface); - free(m->name); - free(m->signature); - free(m->result); - free(m->value); - free(m); -} - -DEFINE_TRIVIAL_CLEANUP_FUNC(Member*, member_free); - -static void member_set_free(Set *s) { - Member *m; - - while ((m = set_steal_first(s))) - member_free(m); - - set_free(s); -} - -DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, member_set_free); - -static int on_interface(const char *interface, uint64_t flags, void *userdata) { - _cleanup_(member_freep) Member *m; - Set *members = userdata; - int r; - - assert(interface); - assert(members); - - m = new0(Member, 1); - if (!m) - return log_oom(); - - m->type = "interface"; - m->flags = flags; - - r = free_and_strdup(&m->interface, interface); - if (r < 0) - return log_oom(); - - r = set_put(members, m); - if (r <= 0) { - log_error("Duplicate interface"); - return -EINVAL; - } - - m = NULL; - return 0; -} - -static int on_method(const char *interface, const char *name, const char *signature, const char *result, uint64_t flags, void *userdata) { - _cleanup_(member_freep) Member *m; - Set *members = userdata; - int r; - - assert(interface); - assert(name); - - m = new0(Member, 1); - if (!m) - return log_oom(); - - m->type = "method"; - m->flags = flags; - - r = free_and_strdup(&m->interface, interface); - if (r < 0) - return log_oom(); - - r = free_and_strdup(&m->name, name); - if (r < 0) - return log_oom(); - - r = free_and_strdup(&m->signature, signature); - if (r < 0) - return log_oom(); - - r = free_and_strdup(&m->result, result); - if (r < 0) - return log_oom(); - - r = set_put(members, m); - if (r <= 0) { - log_error("Duplicate method"); - return -EINVAL; - } - - m = NULL; - return 0; -} - -static int on_signal(const char *interface, const char *name, const char *signature, uint64_t flags, void *userdata) { - _cleanup_(member_freep) Member *m; - Set *members = userdata; - int r; - - assert(interface); - assert(name); - - m = new0(Member, 1); - if (!m) - return log_oom(); - - m->type = "signal"; - m->flags = flags; - - r = free_and_strdup(&m->interface, interface); - if (r < 0) - return log_oom(); - - r = free_and_strdup(&m->name, name); - if (r < 0) - return log_oom(); - - r = free_and_strdup(&m->signature, signature); - if (r < 0) - return log_oom(); - - r = set_put(members, m); - if (r <= 0) { - log_error("Duplicate signal"); - return -EINVAL; - } - - m = NULL; - return 0; -} - -static int on_property(const char *interface, const char *name, const char *signature, bool writable, uint64_t flags, void *userdata) { - _cleanup_(member_freep) Member *m; - Set *members = userdata; - int r; - - assert(interface); - assert(name); - - m = new0(Member, 1); - if (!m) - return log_oom(); - - m->type = "property"; - m->flags = flags; - m->writable = writable; - - r = free_and_strdup(&m->interface, interface); - if (r < 0) - return log_oom(); - - r = free_and_strdup(&m->name, name); - if (r < 0) - return log_oom(); - - r = free_and_strdup(&m->signature, signature); - if (r < 0) - return log_oom(); - - r = set_put(members, m); - if (r <= 0) { - log_error("Duplicate property"); - return -EINVAL; - } - - m = NULL; - return 0; -} - -static const char *strdash(const char *x) { - return isempty(x) ? "-" : x; -} - -static int introspect(sd_bus *bus, char **argv) { - static const struct hash_ops member_hash_ops = { - .hash = member_hash_func, - .compare = member_compare_func, - }; - - static const XMLIntrospectOps ops = { - .on_interface = on_interface, - .on_method = on_method, - .on_signal = on_signal, - .on_property = on_property, - }; - - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_(member_set_freep) Set *members = NULL; - Iterator i; - Member *m; - const char *xml; - int r; - unsigned name_width, type_width, signature_width, result_width; - Member **sorted = NULL; - unsigned k = 0, j, n_args; - - n_args = strv_length(argv); - if (n_args < 3) { - log_error("Requires service and object path argument."); - return -EINVAL; - } - - if (n_args > 4) { - log_error("Too many arguments."); - return -EINVAL; - } - - members = set_new(&member_hash_ops); - if (!members) - return log_oom(); - - r = sd_bus_call_method(bus, argv[1], argv[2], "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, ""); - if (r < 0) { - log_error("Failed to introspect object %s of service %s: %s", argv[2], argv[1], bus_error_message(&error, r)); - return r; - } - - r = sd_bus_message_read(reply, "s", &xml); - if (r < 0) - return bus_log_parse_error(r); - - /* First, get list of all properties */ - r = parse_xml_introspect(argv[2], xml, &ops, members); - if (r < 0) - return r; - - /* Second, find the current values for them */ - SET_FOREACH(m, members, i) { - - if (!streq(m->type, "property")) - continue; - - if (m->value) - continue; - - if (argv[3] && !streq(argv[3], m->interface)) - continue; - - r = sd_bus_call_method(bus, argv[1], argv[2], "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", m->interface); - if (r < 0) { - log_error("%s", bus_error_message(&error, r)); - return r; - } - - r = sd_bus_message_enter_container(reply, 'a', "{sv}"); - if (r < 0) - return bus_log_parse_error(r); - - for (;;) { - Member *z; - _cleanup_free_ char *buf = NULL; - _cleanup_fclose_ FILE *mf = NULL; - size_t sz = 0; - const char *name; - - r = sd_bus_message_enter_container(reply, 'e', "sv"); - if (r < 0) - return bus_log_parse_error(r); - - if (r == 0) - break; - - r = sd_bus_message_read(reply, "s", &name); - if (r < 0) - return bus_log_parse_error(r); - - r = sd_bus_message_enter_container(reply, 'v', NULL); - if (r < 0) - return bus_log_parse_error(r); - - mf = open_memstream(&buf, &sz); - if (!mf) - return log_oom(); - - r = format_cmdline(reply, mf, false); - if (r < 0) - return bus_log_parse_error(r); - - fclose(mf); - mf = NULL; - - z = set_get(members, &((Member) { - .type = "property", - .interface = m->interface, - .name = (char*) name })); - if (z) { - free(z->value); - z->value = buf; - buf = NULL; - } - - r = sd_bus_message_exit_container(reply); - if (r < 0) - return bus_log_parse_error(r); - - r = sd_bus_message_exit_container(reply); - if (r < 0) - return bus_log_parse_error(r); - } - - r = sd_bus_message_exit_container(reply); - if (r < 0) - return bus_log_parse_error(r); - } - - pager_open_if_enabled(); - - name_width = strlen("NAME"); - type_width = strlen("TYPE"); - signature_width = strlen("SIGNATURE"); - result_width = strlen("RESULT/VALUE"); - - sorted = newa(Member*, set_size(members)); - - SET_FOREACH(m, members, i) { - - if (argv[3] && !streq(argv[3], m->interface)) - continue; - - if (m->interface) - name_width = MAX(name_width, strlen(m->interface)); - if (m->name) - name_width = MAX(name_width, strlen(m->name) + 1); - if (m->type) - type_width = MAX(type_width, strlen(m->type)); - if (m->signature) - signature_width = MAX(signature_width, strlen(m->signature)); - if (m->result) - result_width = MAX(result_width, strlen(m->result)); - if (m->value) - result_width = MAX(result_width, strlen(m->value)); - - sorted[k++] = m; - } - - if (result_width > 40) - result_width = 40; - - qsort(sorted, k, sizeof(Member*), member_compare_funcp); - - if (arg_legend) { - printf("%-*s %-*s %-*s %-*s %s\n", - (int) name_width, "NAME", - (int) type_width, "TYPE", - (int) signature_width, "SIGNATURE", - (int) result_width, "RESULT/VALUE", - "FLAGS"); - } - - for (j = 0; j < k; j++) { - _cleanup_free_ char *ellipsized = NULL; - const char *rv; - bool is_interface; - - m = sorted[j]; - - if (argv[3] && !streq(argv[3], m->interface)) - continue; - - is_interface = streq(m->type, "interface"); - - if (argv[3] && is_interface) - continue; - - if (m->value) { - ellipsized = ellipsize(m->value, result_width, 100); - if (!ellipsized) - return log_oom(); - - rv = ellipsized; - } else - rv = strdash(m->result); - - printf("%s%s%-*s%s %-*s %-*s %-*s%s%s%s%s%s%s\n", - is_interface ? ansi_highlight() : "", - is_interface ? "" : ".", - - !is_interface + (int) name_width, strdash(streq_ptr(m->type, "interface") ? m->interface : m->name), - is_interface ? ansi_highlight_off() : "", - (int) type_width, strdash(m->type), - (int) signature_width, strdash(m->signature), - (int) result_width, rv, - (m->flags & SD_BUS_VTABLE_DEPRECATED) ? " deprecated" : (m->flags || m->writable ? "" : " -"), - (m->flags & SD_BUS_VTABLE_METHOD_NO_REPLY) ? " no-reply" : "", - (m->flags & SD_BUS_VTABLE_PROPERTY_CONST) ? " const" : "", - (m->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE) ? " emits-change" : "", - (m->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION) ? " emits-invalidation" : "", - m->writable ? " writable" : ""); - } - - return 0; -} - -static int message_dump(sd_bus_message *m, FILE *f) { - return bus_message_dump(m, f, BUS_MESSAGE_DUMP_WITH_HEADER); -} - -static int message_pcap(sd_bus_message *m, FILE *f) { - return bus_message_pcap_frame(m, arg_snaplen, f); -} - -static int monitor(sd_bus *bus, char *argv[], int (*dump)(sd_bus_message *m, FILE *f)) { - bool added_something = false; - char **i; - int r; - - STRV_FOREACH(i, argv+1) { - _cleanup_free_ char *m = NULL; - - if (!service_name_is_valid(*i)) { - log_error("Invalid service name '%s'", *i); - return -EINVAL; - } - - m = strjoin("sender='", *i, "'", NULL); - if (!m) - return log_oom(); - - r = sd_bus_add_match(bus, NULL, m, NULL, NULL); - if (r < 0) - return log_error_errno(r, "Failed to add match: %m"); - - added_something = true; - } - - STRV_FOREACH(i, arg_matches) { - r = sd_bus_add_match(bus, NULL, *i, NULL, NULL); - if (r < 0) - return log_error_errno(r, "Failed to add match: %m"); - - added_something = true; - } - - if (!added_something) { - r = sd_bus_add_match(bus, NULL, "", NULL, NULL); - if (r < 0) - return log_error_errno(r, "Failed to add match: %m"); - } - - log_info("Monitoring bus message stream."); - - for (;;) { - _cleanup_bus_message_unref_ sd_bus_message *m = NULL; - - r = sd_bus_process(bus, &m); - if (r < 0) - return log_error_errno(r, "Failed to process bus: %m"); - - if (m) { - dump(m, stdout); - fflush(stdout); - - if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected") > 0) { - log_info("Connection terminated, exiting."); - return 0; - } - - continue; - } - - if (r > 0) - continue; - - r = sd_bus_wait(bus, (uint64_t) -1); - if (r < 0) - return log_error_errno(r, "Failed to wait for bus: %m"); - } -} - -static int capture(sd_bus *bus, char *argv[]) { - int r; - - if (isatty(fileno(stdout)) > 0) { - log_error("Refusing to write message data to console, please redirect output to a file."); - return -EINVAL; - } - - bus_pcap_header(arg_snaplen, stdout); - - r = monitor(bus, argv, message_pcap); - if (r < 0) - return r; - - if (ferror(stdout)) { - log_error("Couldn't write capture file."); - return -EIO; - } - - return r; -} - -static int status(sd_bus *bus, char *argv[]) { - _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; - pid_t pid; - int r; - - assert(bus); - - if (strv_length(argv) > 2) { - log_error("Expects no or one argument."); - return -EINVAL; - } - - if (argv[1]) { - r = parse_pid(argv[1], &pid); - if (r < 0) - r = sd_bus_get_name_creds( - bus, - argv[1], - (arg_augment_creds ? SD_BUS_CREDS_AUGMENT : 0) | _SD_BUS_CREDS_ALL, - &creds); - else - r = sd_bus_creds_new_from_pid( - &creds, - pid, - _SD_BUS_CREDS_ALL); - } else { - const char *scope, *address; - sd_id128_t bus_id; - - r = sd_bus_get_address(bus, &address); - if (r >= 0) - printf("BusAddress=%s%s%s\n", ansi_highlight(), address, ansi_highlight_off()); - - r = sd_bus_get_scope(bus, &scope); - if (r >= 0) - printf("BusScope=%s%s%s\n", ansi_highlight(), scope, ansi_highlight_off()); - - r = sd_bus_get_bus_id(bus, &bus_id); - if (r >= 0) - printf("BusID=%s" SD_ID128_FORMAT_STR "%s\n", ansi_highlight(), SD_ID128_FORMAT_VAL(bus_id), ansi_highlight_off()); - - r = sd_bus_get_owner_creds( - bus, - (arg_augment_creds ? SD_BUS_CREDS_AUGMENT : 0) | _SD_BUS_CREDS_ALL, - &creds); - } - - if (r < 0) - return log_error_errno(r, "Failed to get credentials: %m"); - - bus_creds_dump(creds, NULL, false); - return 0; -} - -static int message_append_cmdline(sd_bus_message *m, const char *signature, char ***x) { - char **p; - int r; - - assert(m); - assert(signature); - assert(x); - - p = *x; - - for (;;) { - const char *v; - char t; - - t = *signature; - v = *p; - - if (t == 0) - break; - if (!v) { - log_error("Too few parameters for signature."); - return -EINVAL; - } - - signature++; - p++; - - switch (t) { - - case SD_BUS_TYPE_BOOLEAN: - - r = parse_boolean(v); - if (r < 0) { - log_error("Failed to parse as boolean: %s", v); - return r; - } - - r = sd_bus_message_append_basic(m, t, &r); - break; - - case SD_BUS_TYPE_BYTE: { - uint8_t z; - - r = safe_atou8(v, &z); - if (r < 0) { - log_error("Failed to parse as byte (unsigned 8bit integer): %s", v); - return r; - } - - r = sd_bus_message_append_basic(m, t, &z); - break; - } - - case SD_BUS_TYPE_INT16: { - int16_t z; - - r = safe_atoi16(v, &z); - if (r < 0) { - log_error("Failed to parse as signed 16bit integer: %s", v); - return r; - } - - r = sd_bus_message_append_basic(m, t, &z); - break; - } - - case SD_BUS_TYPE_UINT16: { - uint16_t z; - - r = safe_atou16(v, &z); - if (r < 0) { - log_error("Failed to parse as unsigned 16bit integer: %s", v); - return r; - } - - r = sd_bus_message_append_basic(m, t, &z); - break; - } - - case SD_BUS_TYPE_INT32: { - int32_t z; - - r = safe_atoi32(v, &z); - if (r < 0) { - log_error("Failed to parse as signed 32bit integer: %s", v); - return r; - } - - r = sd_bus_message_append_basic(m, t, &z); - break; - } - - case SD_BUS_TYPE_UINT32: { - uint32_t z; - - r = safe_atou32(v, &z); - if (r < 0) { - log_error("Failed to parse as unsigned 32bit integer: %s", v); - return r; - } - - r = sd_bus_message_append_basic(m, t, &z); - break; - } - - case SD_BUS_TYPE_INT64: { - int64_t z; - - r = safe_atoi64(v, &z); - if (r < 0) { - log_error("Failed to parse as signed 64bit integer: %s", v); - return r; - } - - r = sd_bus_message_append_basic(m, t, &z); - break; - } - - case SD_BUS_TYPE_UINT64: { - uint64_t z; - - r = safe_atou64(v, &z); - if (r < 0) { - log_error("Failed to parse as unsigned 64bit integer: %s", v); - return r; - } - - r = sd_bus_message_append_basic(m, t, &z); - break; - } - - - case SD_BUS_TYPE_DOUBLE: { - double z; - - r = safe_atod(v, &z); - if (r < 0) { - log_error("Failed to parse as double precision floating point: %s", v); - return r; - } - - r = sd_bus_message_append_basic(m, t, &z); - break; - } - - case SD_BUS_TYPE_STRING: - case SD_BUS_TYPE_OBJECT_PATH: - case SD_BUS_TYPE_SIGNATURE: - - r = sd_bus_message_append_basic(m, t, v); - break; - - case SD_BUS_TYPE_ARRAY: { - uint32_t n; - size_t k; - - r = safe_atou32(v, &n); - if (r < 0) { - log_error("Failed to parse number of array entries: %s", v); - return r; - } - - r = signature_element_length(signature, &k); - if (r < 0) { - log_error("Invalid array signature."); - return r; - } - - { - unsigned i; - char s[k + 1]; - memcpy(s, signature, k); - s[k] = 0; - - r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s); - if (r < 0) - return bus_log_create_error(r); - - for (i = 0; i < n; i++) { - r = message_append_cmdline(m, s, &p); - if (r < 0) - return r; - } - } - - signature += k; - - r = sd_bus_message_close_container(m); - break; - } - - case SD_BUS_TYPE_VARIANT: - r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, v); - if (r < 0) - return bus_log_create_error(r); - - r = message_append_cmdline(m, v, &p); - if (r < 0) - return r; - - r = sd_bus_message_close_container(m); - break; - - case SD_BUS_TYPE_STRUCT_BEGIN: - case SD_BUS_TYPE_DICT_ENTRY_BEGIN: { - size_t k; - - signature--; - p--; - - r = signature_element_length(signature, &k); - if (r < 0) { - log_error("Invalid struct/dict entry signature."); - return r; - } - - { - char s[k-1]; - memcpy(s, signature + 1, k - 2); - s[k - 2] = 0; - - r = sd_bus_message_open_container(m, t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s); - if (r < 0) - return bus_log_create_error(r); - - r = message_append_cmdline(m, s, &p); - if (r < 0) - return r; - } - - signature += k; - - r = sd_bus_message_close_container(m); - break; - } - - case SD_BUS_TYPE_UNIX_FD: - log_error("UNIX file descriptor not supported as type."); - return -EINVAL; - - default: - log_error("Unknown signature type %c.", t); - return -EINVAL; - } - - if (r < 0) - return bus_log_create_error(r); - } - - *x = p; - return 0; -} - -static int call(sd_bus *bus, char *argv[]) { - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL; - int r; - - assert(bus); - - if (strv_length(argv) < 5) { - log_error("Expects at least four arguments."); - return -EINVAL; - } - - r = sd_bus_message_new_method_call(bus, &m, argv[1], argv[2], argv[3], argv[4]); - if (r < 0) - return bus_log_create_error(r); - - r = sd_bus_message_set_expect_reply(m, arg_expect_reply); - if (r < 0) - return bus_log_create_error(r); - - r = sd_bus_message_set_auto_start(m, arg_auto_start); - if (r < 0) - return bus_log_create_error(r); - - r = sd_bus_message_set_allow_interactive_authorization(m, arg_allow_interactive_authorization); - if (r < 0) - return bus_log_create_error(r); - - if (!isempty(argv[5])) { - char **p; - - p = argv+6; - - r = message_append_cmdline(m, argv[5], &p); - if (r < 0) - return r; - - if (*p) { - log_error("Too many parameters for signature."); - return -EINVAL; - } - } - - if (!arg_expect_reply) { - r = sd_bus_send(bus, m, NULL); - if (r < 0) { - log_error("Failed to send message."); - return r; - } - - return 0; - } - - r = sd_bus_call(bus, m, arg_timeout, &error, &reply); - if (r < 0) { - log_error("%s", bus_error_message(&error, r)); - return r; - } - - r = sd_bus_message_is_empty(reply); - if (r < 0) - return bus_log_parse_error(r); - - if (r == 0 && !arg_quiet) { - - if (arg_verbose) { - pager_open_if_enabled(); - - r = bus_message_dump(reply, stdout, 0); - if (r < 0) - return r; - } else { - - fputs(sd_bus_message_get_signature(reply, true), stdout); - fputc(' ', stdout); - - r = format_cmdline(reply, stdout, false); - if (r < 0) - return bus_log_parse_error(r); - - fputc('\n', stdout); - } - } - - return 0; -} - -static int get_property(sd_bus *bus, char *argv[]) { - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; - unsigned n; - char **i; - int r; - - assert(bus); - - n = strv_length(argv); - if (n < 5) { - log_error("Expects at least four arguments."); - return -EINVAL; - } - - STRV_FOREACH(i, argv + 4) { - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; - const char *contents = NULL; - char type; - - r = sd_bus_call_method(bus, argv[1], argv[2], "org.freedesktop.DBus.Properties", "Get", &error, &reply, "ss", argv[3], *i); - if (r < 0) { - log_error("%s", bus_error_message(&error, r)); - return r; - } - - r = sd_bus_message_peek_type(reply, &type, &contents); - if (r < 0) - return bus_log_parse_error(r); - - r = sd_bus_message_enter_container(reply, 'v', contents); - if (r < 0) - return bus_log_parse_error(r); - - if (arg_verbose) { - pager_open_if_enabled(); - - r = bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_SUBTREE_ONLY); - if (r < 0) - return r; - } else { - fputs(contents, stdout); - fputc(' ', stdout); - - r = format_cmdline(reply, stdout, false); - if (r < 0) - return bus_log_parse_error(r); - - fputc('\n', stdout); - } - - r = sd_bus_message_exit_container(reply); - if (r < 0) - return bus_log_parse_error(r); - } - - return 0; -} - -static int set_property(sd_bus *bus, char *argv[]) { - _cleanup_bus_message_unref_ sd_bus_message *m = NULL; - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; - unsigned n; - char **p; - int r; - - assert(bus); - - n = strv_length(argv); - if (n < 6) { - log_error("Expects at least five arguments."); - return -EINVAL; - } - - r = sd_bus_message_new_method_call(bus, &m, argv[1], argv[2], "org.freedesktop.DBus.Properties", "Set"); - if (r < 0) - return bus_log_create_error(r); - - r = sd_bus_message_append(m, "ss", argv[3], argv[4]); - if (r < 0) - return bus_log_create_error(r); - - r = sd_bus_message_open_container(m, 'v', argv[5]); - if (r < 0) - return bus_log_create_error(r); - - p = argv+6; - r = message_append_cmdline(m, argv[5], &p); - if (r < 0) - return r; - - r = sd_bus_message_close_container(m); - if (r < 0) - return bus_log_create_error(r); - - if (*p) { - log_error("Too many parameters for signature."); - return -EINVAL; - } - - r = sd_bus_call(bus, m, arg_timeout, &error, NULL); - if (r < 0) { - log_error("%s", bus_error_message(&error, r)); - return r; - } - - return 0; -} - -static int help(void) { - printf("%s [OPTIONS...] {COMMAND} ...\n\n" - "Introspect the bus.\n\n" - " -h --help Show this help\n" - " --version Show package version\n" - " --no-pager Do not pipe output into a pager\n" - " --no-legend Do not show the headers and footers\n" - " --system Connect to system bus\n" - " --user Connect to user bus\n" - " -H --host=[USER@]HOST Operate on remote host\n" - " -M --machine=CONTAINER Operate on local container\n" - " --address=ADDRESS Connect to bus specified by address\n" - " --show-machine Show machine ID column in list\n" - " --unique Only show unique names\n" - " --acquired Only show acquired names\n" - " --activatable Only show activatable names\n" - " --match=MATCH Only show matching messages\n" - " --list Don't show tree, but simple object path list\n" - " --quiet Don't show method call reply\n" - " --verbose Show result values in long format\n" - " --expect-reply=BOOL Expect a method call reply\n" - " --auto-start=BOOL Auto-start destination service\n" - " --allow-interactive-authorization=BOOL\n" - " Allow interactive authorization for operation\n" - " --timeout=SECS Maximum time to wait for method call completion\n" - " --augment-creds=BOOL Extend credential data with data read from /proc/$PID\n\n" - "Commands:\n" - " list List bus names\n" - " status [SERVICE] Show bus service, process or bus owner credentials\n" - " monitor [SERVICE...] Show bus traffic\n" - " capture [SERVICE...] Capture bus traffic as pcap\n" - " tree [SERVICE...] Show object tree of service\n" - " introspect SERVICE OBJECT [INTERFACE]\n" - " call SERVICE OBJECT INTERFACE METHOD [SIGNATURE [ARGUMENT...]]\n" - " Call a method\n" - " get-property SERVICE OBJECT INTERFACE PROPERTY...\n" - " Get property value\n" - " set-property SERVICE OBJECT INTERFACE PROPERTY SIGNATURE ARGUMENT...\n" - " Set property value\n" - " help Show this help\n" - , program_invocation_short_name); - - return 0; -} - -static int parse_argv(int argc, char *argv[]) { - - enum { - ARG_VERSION = 0x100, - ARG_NO_PAGER, - ARG_NO_LEGEND, - ARG_SYSTEM, - ARG_USER, - ARG_ADDRESS, - ARG_MATCH, - ARG_SHOW_MACHINE, - ARG_UNIQUE, - ARG_ACQUIRED, - ARG_ACTIVATABLE, - ARG_SIZE, - ARG_LIST, - ARG_VERBOSE, - ARG_EXPECT_REPLY, - ARG_AUTO_START, - ARG_ALLOW_INTERACTIVE_AUTHORIZATION, - ARG_TIMEOUT, - ARG_AUGMENT_CREDS, - }; - - static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - { "no-pager", no_argument, NULL, ARG_NO_PAGER }, - { "no-legend", no_argument, NULL, ARG_NO_LEGEND }, - { "system", no_argument, NULL, ARG_SYSTEM }, - { "user", no_argument, NULL, ARG_USER }, - { "address", required_argument, NULL, ARG_ADDRESS }, - { "show-machine", no_argument, NULL, ARG_SHOW_MACHINE }, - { "unique", no_argument, NULL, ARG_UNIQUE }, - { "acquired", no_argument, NULL, ARG_ACQUIRED }, - { "activatable", no_argument, NULL, ARG_ACTIVATABLE }, - { "match", required_argument, NULL, ARG_MATCH }, - { "host", required_argument, NULL, 'H' }, - { "machine", required_argument, NULL, 'M' }, - { "size", required_argument, NULL, ARG_SIZE }, - { "list", no_argument, NULL, ARG_LIST }, - { "quiet", no_argument, NULL, 'q' }, - { "verbose", no_argument, NULL, ARG_VERBOSE }, - { "expect-reply", required_argument, NULL, ARG_EXPECT_REPLY }, - { "auto-start", required_argument, NULL, ARG_AUTO_START }, - { "allow-interactive-authorization", required_argument, NULL, ARG_ALLOW_INTERACTIVE_AUTHORIZATION }, - { "timeout", required_argument, NULL, ARG_TIMEOUT }, - { "augment-creds",required_argument, NULL, ARG_AUGMENT_CREDS}, - {}, - }; - - int c, r; - - assert(argc >= 0); - assert(argv); - - while ((c = getopt_long(argc, argv, "hH:M:q", options, NULL)) >= 0) - - switch (c) { - - case 'h': - return help(); - - case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; - - case ARG_NO_PAGER: - arg_no_pager = true; - break; - - case ARG_NO_LEGEND: - arg_legend = false; - break; - - case ARG_USER: - arg_user = true; - break; - - case ARG_SYSTEM: - arg_user = false; - break; - - case ARG_ADDRESS: - arg_address = optarg; - break; - - case ARG_SHOW_MACHINE: - arg_show_machine = true; - break; - - case ARG_UNIQUE: - arg_unique = true; - break; - - case ARG_ACQUIRED: - arg_acquired = true; - break; - - case ARG_ACTIVATABLE: - arg_activatable = true; - break; - - case ARG_MATCH: - if (strv_extend(&arg_matches, optarg) < 0) - return log_oom(); - break; - - case ARG_SIZE: { - off_t o; - - r = parse_size(optarg, 0, &o); - if (r < 0) { - log_error("Failed to parse size: %s", optarg); - return r; - } - - if ((off_t) (size_t) o != o) { - log_error("Size out of range."); - return -E2BIG; - } - - arg_snaplen = (size_t) o; - break; - } - - case ARG_LIST: - arg_list = true; - break; - - case 'H': - arg_transport = BUS_TRANSPORT_REMOTE; - arg_host = optarg; - break; - - case 'M': - arg_transport = BUS_TRANSPORT_MACHINE; - arg_host = optarg; - break; - - case 'q': - arg_quiet = true; - break; - - case ARG_VERBOSE: - arg_verbose = true; - break; - - case ARG_EXPECT_REPLY: - r = parse_boolean(optarg); - if (r < 0) { - log_error("Failed to parse --expect-reply= parameter."); - return r; - } - - arg_expect_reply = !!r; - break; - - - case ARG_AUTO_START: - r = parse_boolean(optarg); - if (r < 0) { - log_error("Failed to parse --auto-start= parameter."); - return r; - } - - arg_auto_start = !!r; - break; - - - case ARG_ALLOW_INTERACTIVE_AUTHORIZATION: - r = parse_boolean(optarg); - if (r < 0) { - log_error("Failed to parse --allow-interactive-authorization= parameter."); - return r; - } - - arg_allow_interactive_authorization = !!r; - break; - - case ARG_TIMEOUT: - r = parse_sec(optarg, &arg_timeout); - if (r < 0) { - log_error("Failed to parse --timeout= parameter."); - return r; - } - - break; - - case ARG_AUGMENT_CREDS: - r = parse_boolean(optarg); - if (r < 0) { - log_error("Failed to parse --augment-creds= parameter."); - return r; - } - - arg_augment_creds = !!r; - break; - - case '?': - return -EINVAL; - - default: - assert_not_reached("Unhandled option"); - } - - return 1; -} - -static int busctl_main(sd_bus *bus, int argc, char *argv[]) { - assert(bus); - - if (optind >= argc || - streq(argv[optind], "list")) - return list_bus_names(bus, argv + optind); - - if (streq(argv[optind], "monitor")) - return monitor(bus, argv + optind, message_dump); - - if (streq(argv[optind], "capture")) - return capture(bus, argv + optind); - - if (streq(argv[optind], "status")) - return status(bus, argv + optind); - - if (streq(argv[optind], "tree")) - return tree(bus, argv + optind); - - if (streq(argv[optind], "introspect")) - return introspect(bus, argv + optind); - - if (streq(argv[optind], "call")) - return call(bus, argv + optind); - - if (streq(argv[optind], "get-property")) - return get_property(bus, argv + optind); - - if (streq(argv[optind], "set-property")) - return set_property(bus, argv + optind); - - if (streq(argv[optind], "help")) - return help(); - - log_error("Unknown command '%s'", argv[optind]); - return -EINVAL; -} - -int main(int argc, char *argv[]) { - _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL; - int r; - - log_parse_environment(); - log_open(); - - r = parse_argv(argc, argv); - if (r <= 0) - goto finish; - - r = sd_bus_new(&bus); - if (r < 0) { - log_error_errno(r, "Failed to allocate bus: %m"); - goto finish; - } - - if (streq_ptr(argv[optind], "monitor") || - streq_ptr(argv[optind], "capture")) { - - r = sd_bus_set_monitor(bus, true); - if (r < 0) { - log_error_errno(r, "Failed to set monitor mode: %m"); - goto finish; - } - - r = sd_bus_negotiate_creds(bus, true, _SD_BUS_CREDS_ALL); - if (r < 0) { - log_error_errno(r, "Failed to enable credentials: %m"); - goto finish; - } - - r = sd_bus_negotiate_timestamp(bus, true); - if (r < 0) { - log_error_errno(r, "Failed to enable timestamps: %m"); - goto finish; - } - - r = sd_bus_negotiate_fds(bus, true); - if (r < 0) { - log_error_errno(r, "Failed to enable fds: %m"); - goto finish; - } - } - - if (arg_address) - r = sd_bus_set_address(bus, arg_address); - else { - r = sd_bus_set_bus_client(bus, true); - if (r < 0) { - log_error_errno(r, "Failed to set bus client: %m"); - goto finish; - } - - switch (arg_transport) { - - case BUS_TRANSPORT_LOCAL: - if (arg_user) { - bus->is_user = true; - r = bus_set_address_user(bus); - } else { - bus->is_system = true; - r = bus_set_address_system(bus); - } - break; - - case BUS_TRANSPORT_REMOTE: - r = bus_set_address_system_remote(bus, arg_host); - break; - - case BUS_TRANSPORT_MACHINE: - r = bus_set_address_system_machine(bus, arg_host); - break; - - default: - assert_not_reached("Hmm, unknown transport type."); - } - } - if (r < 0) { - log_error_errno(r, "Failed to set address: %m"); - goto finish; - } - - r = sd_bus_start(bus); - if (r < 0) { - log_error_errno(r, "Failed to connect to bus: %m"); - goto finish; - } - - r = busctl_main(bus, argc, argv); - -finish: - pager_close(); - - strv_free(arg_matches); - - return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; -} diff --git a/src/libelogind/sd-bus/test-bus-chat.c b/src/libelogind/sd-bus/test-bus-chat.c deleted file mode 100644 index 754335b5e..000000000 --- a/src/libelogind/sd-bus/test-bus-chat.c +++ /dev/null @@ -1,562 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2013 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 . -***/ - -#include -#include -#include -#include - -#include "log.h" -#include "util.h" -#include "macro.h" -#include "formats-util.h" - -#include "sd-bus.h" -#include "bus-error.h" -#include "bus-match.h" -#include "bus-internal.h" -#include "bus-util.h" - -static int match_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { - log_info("Match triggered! interface=%s member=%s", strna(sd_bus_message_get_interface(m)), strna(sd_bus_message_get_member(m))); - return 0; -} - -static int object_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { - int r; - - if (sd_bus_message_is_method_error(m, NULL)) - return 0; - - if (sd_bus_message_is_method_call(m, "org.object.test", "Foobar")) { - log_info("Invoked Foobar() on %s", sd_bus_message_get_path(m)); - - r = sd_bus_reply_method_return(m, NULL); - if (r < 0) - return log_error_errno(r, "Failed to send reply: %m"); - - return 1; - } - - return 0; -} - -static int server_init(sd_bus **_bus) { - sd_bus *bus = NULL; - sd_id128_t id; - int r; - const char *unique; - - assert_se(_bus); - - r = sd_bus_open_user(&bus); - if (r < 0) { - log_error_errno(r, "Failed to connect to user bus: %m"); - goto fail; - } - - r = sd_bus_get_bus_id(bus, &id); - if (r < 0) { - log_error_errno(r, "Failed to get server ID: %m"); - goto fail; - } - - r = sd_bus_get_unique_name(bus, &unique); - if (r < 0) { - log_error_errno(r, "Failed to get unique name: %m"); - goto fail; - } - - log_info("Peer ID is " SD_ID128_FORMAT_STR ".", SD_ID128_FORMAT_VAL(id)); - log_info("Unique ID: %s", unique); - log_info("Can send file handles: %i", sd_bus_can_send(bus, 'h')); - - r = sd_bus_request_name(bus, "org.freedesktop.systemd.test", 0); - if (r < 0) { - log_error_errno(r, "Failed to acquire name: %m"); - goto fail; - } - - r = sd_bus_add_fallback(bus, NULL, "/foo/bar", object_callback, NULL); - if (r < 0) { - log_error_errno(r, "Failed to add object: %m"); - goto fail; - } - - r = sd_bus_add_match(bus, NULL, "type='signal',interface='foo.bar',member='Notify'", match_callback, NULL); - if (r < 0) { - log_error_errno(r, "Failed to add match: %m"); - goto fail; - } - - r = sd_bus_add_match(bus, NULL, "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged'", match_callback, NULL); - if (r < 0) { - log_error_errno(r, "Failed to add match: %m"); - goto fail; - } - - bus_match_dump(&bus->match_callbacks, 0); - - *_bus = bus; - return 0; - -fail: - if (bus) - sd_bus_unref(bus); - - return r; -} - -static int server(sd_bus *bus) { - int r; - bool client1_gone = false, client2_gone = false; - - while (!client1_gone || !client2_gone) { - _cleanup_bus_message_unref_ sd_bus_message *m = NULL; - pid_t pid = 0; - const char *label = NULL; - - r = sd_bus_process(bus, &m); - if (r < 0) { - log_error_errno(r, "Failed to process requests: %m"); - goto fail; - } - - if (r == 0) { - r = sd_bus_wait(bus, (uint64_t) -1); - if (r < 0) { - log_error_errno(r, "Failed to wait: %m"); - goto fail; - } - - continue; - } - - if (!m) - continue; - - sd_bus_creds_get_pid(sd_bus_message_get_creds(m), &pid); - sd_bus_creds_get_selinux_context(sd_bus_message_get_creds(m), &label); - log_info("Got message! member=%s pid="PID_FMT" label=%s", - strna(sd_bus_message_get_member(m)), - pid, - strna(label)); - /* bus_message_dump(m); */ - /* sd_bus_message_rewind(m, true); */ - - if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "LowerCase")) { - const char *hello; - _cleanup_free_ char *lowercase = NULL; - - r = sd_bus_message_read(m, "s", &hello); - if (r < 0) { - log_error_errno(r, "Failed to get parameter: %m"); - goto fail; - } - - lowercase = strdup(hello); - if (!lowercase) { - r = log_oom(); - goto fail; - } - - ascii_strlower(lowercase); - - r = sd_bus_reply_method_return(m, "s", lowercase); - if (r < 0) { - log_error_errno(r, "Failed to send reply: %m"); - goto fail; - } - } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient1")) { - - r = sd_bus_reply_method_return(m, NULL); - if (r < 0) { - log_error_errno(r, "Failed to send reply: %m"); - goto fail; - } - - client1_gone = true; - } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient2")) { - - r = sd_bus_reply_method_return(m, NULL); - if (r < 0) { - log_error_errno(r, "Failed to send reply: %m"); - goto fail; - } - - client2_gone = true; - } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Slow")) { - - sleep(1); - - r = sd_bus_reply_method_return(m, NULL); - if (r < 0) { - log_error_errno(r, "Failed to send reply: %m"); - goto fail; - } - - } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "FileDescriptor")) { - int fd; - static const char x = 'X'; - - r = sd_bus_message_read(m, "h", &fd); - if (r < 0) { - log_error_errno(r, "Failed to get parameter: %m"); - goto fail; - } - - log_info("Received fd=%d", fd); - - if (write(fd, &x, 1) < 0) { - log_error_errno(errno, "Failed to write to fd: %m"); - safe_close(fd); - goto fail; - } - - r = sd_bus_reply_method_return(m, NULL); - if (r < 0) { - log_error_errno(r, "Failed to send reply: %m"); - goto fail; - } - - } else if (sd_bus_message_is_method_call(m, NULL, NULL)) { - - r = sd_bus_reply_method_error( - m, - &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method.")); - if (r < 0) { - log_error_errno(r, "Failed to send reply: %m"); - goto fail; - } - } - } - - r = 0; - -fail: - if (bus) { - sd_bus_flush(bus); - sd_bus_unref(bus); - } - - return r; -} - -static void* client1(void*p) { - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; - _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL; - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; - const char *hello; - int r; - _cleanup_close_pair_ int pp[2] = { -1, -1 }; - char x; - - r = sd_bus_open_user(&bus); - if (r < 0) { - log_error_errno(r, "Failed to connect to user bus: %m"); - goto finish; - } - - r = sd_bus_call_method( - bus, - "org.freedesktop.systemd.test", - "/", - "org.freedesktop.systemd.test", - "LowerCase", - &error, - &reply, - "s", - "HELLO"); - if (r < 0) { - log_error_errno(r, "Failed to issue method call: %m"); - goto finish; - } - - r = sd_bus_message_read(reply, "s", &hello); - if (r < 0) { - log_error_errno(r, "Failed to get string: %m"); - goto finish; - } - - assert_se(streq(hello, "hello")); - - if (pipe2(pp, O_CLOEXEC|O_NONBLOCK) < 0) { - log_error_errno(errno, "Failed to allocate pipe: %m"); - r = -errno; - goto finish; - } - - log_info("Sending fd=%d", pp[1]); - - r = sd_bus_call_method( - bus, - "org.freedesktop.systemd.test", - "/", - "org.freedesktop.systemd.test", - "FileDescriptor", - &error, - NULL, - "h", - pp[1]); - if (r < 0) { - log_error_errno(r, "Failed to issue method call: %m"); - goto finish; - } - - errno = 0; - if (read(pp[0], &x, 1) <= 0) { - log_error("Failed to read from pipe: %s", errno ? strerror(errno) : "early read"); - goto finish; - } - - r = 0; - -finish: - if (bus) { - _cleanup_bus_message_unref_ sd_bus_message *q; - - r = sd_bus_message_new_method_call( - bus, - &q, - "org.freedesktop.systemd.test", - "/", - "org.freedesktop.systemd.test", - "ExitClient1"); - if (r < 0) - log_error_errno(r, "Failed to allocate method call: %m"); - else - sd_bus_send(bus, q, NULL); - - } - - return INT_TO_PTR(r); -} - -static int quit_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { - bool *x = userdata; - - log_error("Quit callback: %s", strerror(sd_bus_message_get_errno(m))); - - *x = 1; - return 1; -} - -static void* client2(void*p) { - _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL; - _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL; - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; - bool quit = false; - const char *mid; - int r; - - r = sd_bus_open_user(&bus); - if (r < 0) { - log_error_errno(r, "Failed to connect to user bus: %m"); - goto finish; - } - - r = sd_bus_message_new_method_call( - bus, - &m, - "org.freedesktop.systemd.test", - "/foo/bar/waldo/piep", - "org.object.test", - "Foobar"); - if (r < 0) { - log_error_errno(r, "Failed to allocate method call: %m"); - goto finish; - } - - r = sd_bus_send(bus, m, NULL); - if (r < 0) { - log_error("Failed to issue method call: %s", bus_error_message(&error, -r)); - goto finish; - } - - m = sd_bus_message_unref(m); - - r = sd_bus_message_new_signal( - bus, - &m, - "/foobar", - "foo.bar", - "Notify"); - if (r < 0) { - log_error_errno(r, "Failed to allocate signal: %m"); - goto finish; - } - - r = sd_bus_send(bus, m, NULL); - if (r < 0) { - log_error("Failed to issue signal: %s", bus_error_message(&error, -r)); - goto finish; - } - - m = sd_bus_message_unref(m); - - r = sd_bus_message_new_method_call( - bus, - &m, - "org.freedesktop.systemd.test", - "/", - "org.freedesktop.DBus.Peer", - "GetMachineId"); - if (r < 0) { - log_error_errno(r, "Failed to allocate method call: %m"); - goto finish; - } - - r = sd_bus_call(bus, m, 0, &error, &reply); - if (r < 0) { - log_error("Failed to issue method call: %s", bus_error_message(&error, -r)); - goto finish; - } - - r = sd_bus_message_read(reply, "s", &mid); - if (r < 0) { - log_error_errno(r, "Failed to parse machine ID: %m"); - goto finish; - } - - log_info("Machine ID is %s.", mid); - - m = sd_bus_message_unref(m); - - r = sd_bus_message_new_method_call( - bus, - &m, - "org.freedesktop.systemd.test", - "/", - "org.freedesktop.systemd.test", - "Slow"); - if (r < 0) { - log_error_errno(r, "Failed to allocate method call: %m"); - goto finish; - } - - reply = sd_bus_message_unref(reply); - - r = sd_bus_call(bus, m, 200 * USEC_PER_MSEC, &error, &reply); - if (r < 0) - log_info("Failed to issue method call: %s", bus_error_message(&error, -r)); - else - log_info("Slow call succeed."); - - m = sd_bus_message_unref(m); - - r = sd_bus_message_new_method_call( - bus, - &m, - "org.freedesktop.systemd.test", - "/", - "org.freedesktop.systemd.test", - "Slow"); - if (r < 0) { - log_error_errno(r, "Failed to allocate method call: %m"); - goto finish; - } - - r = sd_bus_call_async(bus, NULL, m, quit_callback, &quit, 200 * USEC_PER_MSEC); - if (r < 0) { - log_info("Failed to issue method call: %s", bus_error_message(&error, -r)); - goto finish; - } - - while (!quit) { - r = sd_bus_process(bus, NULL); - if (r < 0) { - log_error_errno(r, "Failed to process requests: %m"); - goto finish; - } - if (r == 0) { - r = sd_bus_wait(bus, (uint64_t) -1); - if (r < 0) { - log_error_errno(r, "Failed to wait: %m"); - goto finish; - } - } - } - - r = 0; - -finish: - if (bus) { - _cleanup_bus_message_unref_ sd_bus_message *q; - - r = sd_bus_message_new_method_call( - bus, - &q, - "org.freedesktop.systemd.test", - "/", - "org.freedesktop.systemd.test", - "ExitClient2"); - if (r < 0) { - log_error_errno(r, "Failed to allocate method call: %m"); - goto finish; - } - - (void) sd_bus_send(bus, q, NULL); - } - - return INT_TO_PTR(r); -} - -int main(int argc, char *argv[]) { - pthread_t c1, c2; - sd_bus *bus; - void *p; - int q, r; - - r = server_init(&bus); - if (r < 0) { - log_info("Failed to connect to bus, skipping tests."); - return EXIT_TEST_SKIP; - } - - log_info("Initialized..."); - - r = pthread_create(&c1, NULL, client1, bus); - if (r != 0) - return EXIT_FAILURE; - - r = pthread_create(&c2, NULL, client2, bus); - if (r != 0) - return EXIT_FAILURE; - - r = server(bus); - - q = pthread_join(c1, &p); - if (q != 0) - return EXIT_FAILURE; - if (PTR_TO_INT(p) < 0) - return EXIT_FAILURE; - - q = pthread_join(c2, &p); - if (q != 0) - return EXIT_FAILURE; - if (PTR_TO_INT(p) < 0) - return EXIT_FAILURE; - - if (r < 0) - return EXIT_FAILURE; - - return EXIT_SUCCESS; -} diff --git a/src/libelogind/sd-bus/test-bus-gvariant.c b/src/libelogind/sd-bus/test-bus-gvariant.c deleted file mode 100644 index b078bdc5f..000000000 --- a/src/libelogind/sd-bus/test-bus-gvariant.c +++ /dev/null @@ -1,224 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2013 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 . -***/ - -#ifdef HAVE_GLIB -#include -#endif - -#include "util.h" -#include "macro.h" -#include "sd-bus.h" -#include "bus-gvariant.h" -#include "bus-util.h" -#include "bus-internal.h" -#include "bus-message.h" -#include "bus-dump.h" - -static void test_bus_gvariant_is_fixed_size(void) { - assert_se(bus_gvariant_is_fixed_size("") > 0); - assert_se(bus_gvariant_is_fixed_size("()") > 0); - assert_se(bus_gvariant_is_fixed_size("y") > 0); - assert_se(bus_gvariant_is_fixed_size("u") > 0); - assert_se(bus_gvariant_is_fixed_size("b") > 0); - assert_se(bus_gvariant_is_fixed_size("n") > 0); - assert_se(bus_gvariant_is_fixed_size("q") > 0); - assert_se(bus_gvariant_is_fixed_size("i") > 0); - assert_se(bus_gvariant_is_fixed_size("t") > 0); - assert_se(bus_gvariant_is_fixed_size("d") > 0); - assert_se(bus_gvariant_is_fixed_size("s") == 0); - assert_se(bus_gvariant_is_fixed_size("o") == 0); - assert_se(bus_gvariant_is_fixed_size("g") == 0); - assert_se(bus_gvariant_is_fixed_size("h") > 0); - assert_se(bus_gvariant_is_fixed_size("ay") == 0); - assert_se(bus_gvariant_is_fixed_size("v") == 0); - assert_se(bus_gvariant_is_fixed_size("(u)") > 0); - assert_se(bus_gvariant_is_fixed_size("(uuuuy)") > 0); - assert_se(bus_gvariant_is_fixed_size("(uusuuy)") == 0); - assert_se(bus_gvariant_is_fixed_size("a{ss}") == 0); - assert_se(bus_gvariant_is_fixed_size("((u)yyy(b(iiii)))") > 0); - assert_se(bus_gvariant_is_fixed_size("((u)yyy(b(iiivi)))") == 0); -} - -static void test_bus_gvariant_get_size(void) { - assert_se(bus_gvariant_get_size("") == 0); - assert_se(bus_gvariant_get_size("()") == 1); - assert_se(bus_gvariant_get_size("y") == 1); - assert_se(bus_gvariant_get_size("u") == 4); - assert_se(bus_gvariant_get_size("b") == 1); - assert_se(bus_gvariant_get_size("n") == 2); - assert_se(bus_gvariant_get_size("q") == 2); - assert_se(bus_gvariant_get_size("i") == 4); - assert_se(bus_gvariant_get_size("t") == 8); - assert_se(bus_gvariant_get_size("d") == 8); - assert_se(bus_gvariant_get_size("s") < 0); - assert_se(bus_gvariant_get_size("o") < 0); - assert_se(bus_gvariant_get_size("g") < 0); - assert_se(bus_gvariant_get_size("h") == 4); - assert_se(bus_gvariant_get_size("ay") < 0); - assert_se(bus_gvariant_get_size("v") < 0); - assert_se(bus_gvariant_get_size("(u)") == 4); - assert_se(bus_gvariant_get_size("(uuuuy)") == 20); - assert_se(bus_gvariant_get_size("(uusuuy)") < 0); - assert_se(bus_gvariant_get_size("a{ss}") < 0); - assert_se(bus_gvariant_get_size("((u)yyy(b(iiii)))") == 28); - assert_se(bus_gvariant_get_size("((u)yyy(b(iiivi)))") < 0); - assert_se(bus_gvariant_get_size("((b)(t))") == 16); - assert_se(bus_gvariant_get_size("((b)(b)(t))") == 16); - assert_se(bus_gvariant_get_size("(bt)") == 16); - assert_se(bus_gvariant_get_size("((t)(b))") == 16); - assert_se(bus_gvariant_get_size("(tb)") == 16); - assert_se(bus_gvariant_get_size("((b)(b))") == 2); - assert_se(bus_gvariant_get_size("((t)(t))") == 16); -} - -static void test_bus_gvariant_get_alignment(void) { - assert_se(bus_gvariant_get_alignment("") == 1); - assert_se(bus_gvariant_get_alignment("()") == 1); - assert_se(bus_gvariant_get_alignment("y") == 1); - assert_se(bus_gvariant_get_alignment("b") == 1); - assert_se(bus_gvariant_get_alignment("u") == 4); - assert_se(bus_gvariant_get_alignment("s") == 1); - assert_se(bus_gvariant_get_alignment("o") == 1); - assert_se(bus_gvariant_get_alignment("g") == 1); - assert_se(bus_gvariant_get_alignment("v") == 8); - assert_se(bus_gvariant_get_alignment("h") == 4); - assert_se(bus_gvariant_get_alignment("i") == 4); - assert_se(bus_gvariant_get_alignment("t") == 8); - assert_se(bus_gvariant_get_alignment("x") == 8); - assert_se(bus_gvariant_get_alignment("q") == 2); - assert_se(bus_gvariant_get_alignment("n") == 2); - assert_se(bus_gvariant_get_alignment("d") == 8); - assert_se(bus_gvariant_get_alignment("ay") == 1); - assert_se(bus_gvariant_get_alignment("as") == 1); - assert_se(bus_gvariant_get_alignment("au") == 4); - assert_se(bus_gvariant_get_alignment("an") == 2); - assert_se(bus_gvariant_get_alignment("ans") == 2); - assert_se(bus_gvariant_get_alignment("ant") == 8); - assert_se(bus_gvariant_get_alignment("(ss)") == 1); - assert_se(bus_gvariant_get_alignment("(ssu)") == 4); - assert_se(bus_gvariant_get_alignment("a(ssu)") == 4); - assert_se(bus_gvariant_get_alignment("(u)") == 4); - assert_se(bus_gvariant_get_alignment("(uuuuy)") == 4); - assert_se(bus_gvariant_get_alignment("(uusuuy)") == 4); - assert_se(bus_gvariant_get_alignment("a{ss}") == 1); - assert_se(bus_gvariant_get_alignment("((u)yyy(b(iiii)))") == 4); - assert_se(bus_gvariant_get_alignment("((u)yyy(b(iiivi)))") == 8); - assert_se(bus_gvariant_get_alignment("((b)(t))") == 8); - assert_se(bus_gvariant_get_alignment("((b)(b)(t))") == 8); - assert_se(bus_gvariant_get_alignment("(bt)") == 8); - assert_se(bus_gvariant_get_alignment("((t)(b))") == 8); - assert_se(bus_gvariant_get_alignment("(tb)") == 8); - assert_se(bus_gvariant_get_alignment("((b)(b))") == 1); - assert_se(bus_gvariant_get_alignment("((t)(t))") == 8); -} - -static void test_marshal(void) { - _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *n = NULL; - _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL; - _cleanup_free_ void *blob; - size_t sz; - int r; - - r = sd_bus_open_system(&bus); - if (r < 0) - exit(EXIT_TEST_SKIP); - - bus->message_version = 2; /* dirty hack to enable gvariant */ - - assert_se(sd_bus_message_new_method_call(bus, &m, "a.service.name", "/an/object/path/which/is/really/really/long/so/that/we/hit/the/eight/bit/boundary/by/quite/some/margin/to/test/this/stuff/that/it/really/works", "an.interface.name", "AMethodName") >= 0); - - assert_cc(sizeof(struct bus_header) == 16); - - assert_se(sd_bus_message_append(m, - "a(usv)", 3, - 4711, "first-string-parameter", "(st)", "X", (uint64_t) 1111, - 4712, "second-string-parameter", "(a(si))", 2, "Y", 5, "Z", 6, - 4713, "third-string-parameter", "(uu)", 1, 2) >= 0); - - assert_se(bus_message_seal(m, 4711, 0) >= 0); - -#ifdef HAVE_GLIB - { - GVariant *v; - char *t; - -#if !defined(GLIB_VERSION_2_36) - g_type_init(); -#endif - - v = g_variant_new_from_data(G_VARIANT_TYPE("(yyyyuta{tv})"), m->header, sizeof(struct bus_header) + m->fields_size, false, NULL, NULL); - assert_se(g_variant_is_normal_form(v)); - t = g_variant_print(v, TRUE); - printf("%s\n", t); - g_free(t); - g_variant_unref(v); - - v = g_variant_new_from_data(G_VARIANT_TYPE("(a(usv))"), m->body.data, m->user_body_size, false, NULL, NULL); - assert_se(g_variant_is_normal_form(v)); - t = g_variant_print(v, TRUE); - printf("%s\n", t); - g_free(t); - g_variant_unref(v); - } -#endif - - assert_se(bus_message_dump(m, NULL, BUS_MESSAGE_DUMP_WITH_HEADER) >= 0); - - assert_se(bus_message_get_blob(m, &blob, &sz) >= 0); - -#ifdef HAVE_GLIB - { - GVariant *v; - char *t; - - v = g_variant_new_from_data(G_VARIANT_TYPE("(yyyyuta{tv}v)"), blob, sz, false, NULL, NULL); - assert_se(g_variant_is_normal_form(v)); - t = g_variant_print(v, TRUE); - printf("%s\n", t); - g_free(t); - g_variant_unref(v); - } -#endif - - assert_se(bus_message_from_malloc(bus, blob, sz, NULL, 0, NULL, &n) >= 0); - blob = NULL; - - assert_se(bus_message_dump(n, NULL, BUS_MESSAGE_DUMP_WITH_HEADER) >= 0); - - m = sd_bus_message_unref(m); - - assert_se(sd_bus_message_new_method_call(bus, &m, "a.x", "/a/x", "a.x", "Ax") >= 0); - - assert_se(sd_bus_message_append(m, "as", 0) >= 0); - - assert_se(bus_message_seal(m, 4712, 0) >= 0); - assert_se(bus_message_dump(m, NULL, BUS_MESSAGE_DUMP_WITH_HEADER) >= 0); -} - -int main(int argc, char *argv[]) { - - test_bus_gvariant_is_fixed_size(); - test_bus_gvariant_get_size(); - test_bus_gvariant_get_alignment(); - test_marshal(); - - return 0; -} diff --git a/src/libelogind/sd-bus/test-bus-kernel-bloom.c b/src/libelogind/sd-bus/test-bus-kernel-bloom.c deleted file mode 100644 index 90eb1f2a3..000000000 --- a/src/libelogind/sd-bus/test-bus-kernel-bloom.c +++ /dev/null @@ -1,139 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2013 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 . -***/ - -#include "util.h" -#include "log.h" - -#include "sd-bus.h" -#include "bus-kernel.h" -#include "bus-util.h" - -static int test_match(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { - int *found = userdata; - - *found = 1; - - return 0; -} - -static void test_one( - const char *path, - const char *interface, - const char *member, - bool as_list, - const char *arg0, - const char *match, - bool good) { - - _cleanup_close_ int bus_ref = -1; - _cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL; - _cleanup_bus_message_unref_ sd_bus_message *m = NULL; - sd_bus *a, *b; - int r, found = 0; - - assert_se(asprintf(&name, "deine-mutter-%u", (unsigned) getpid()) >= 0); - - bus_ref = bus_kernel_create_bus(name, false, &bus_name); - if (bus_ref == -ENOENT) - exit(EXIT_TEST_SKIP); - - assert_se(bus_ref >= 0); - - address = strappend("kernel:path=", bus_name); - assert_se(address); - - r = sd_bus_new(&a); - assert_se(r >= 0); - - r = sd_bus_new(&b); - assert_se(r >= 0); - - r = sd_bus_set_address(a, address); - assert_se(r >= 0); - - r = sd_bus_set_address(b, address); - assert_se(r >= 0); - - r = sd_bus_start(a); - assert_se(r >= 0); - - r = sd_bus_start(b); - assert_se(r >= 0); - - log_debug("match"); - r = sd_bus_add_match(b, NULL, match, test_match, &found); - assert_se(r >= 0); - - log_debug("signal"); - - if (as_list) - r = sd_bus_emit_signal(a, path, interface, member, "as", 1, arg0); - else - r = sd_bus_emit_signal(a, path, interface, member, "s", arg0); - assert_se(r >= 0); - - r = sd_bus_process(b, &m); - assert_se(r >= 0 && good == !!found); - - sd_bus_unref(a); - sd_bus_unref(b); -} - -int main(int argc, char *argv[]) { - log_set_max_level(LOG_DEBUG); - - test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "", true); - test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo'", true); - test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo/tuut'", false); - test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "interface='waldo.com'", true); - test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "member='Piep'", true); - test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "member='Pi_ep'", false); - test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "arg0='foobar'", true); - test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "arg0='foo_bar'", false); - test_one("/foo/bar/waldo", "waldo.com", "Piep", true, "foobar", "arg0='foobar'", true); - test_one("/foo/bar/waldo", "waldo.com", "Piep", true, "foobar", "arg0='foo_bar'", false); - test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo',interface='waldo.com',member='Piep',arg0='foobar'", true); - test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo',interface='waldo.com',member='Piep',arg0='foobar2'", false); - - test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo'", true); - test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar'", false); - test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo'", false); - test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/'", false); - test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo/quux'", false); - test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/foo/bar/waldo'", true); - test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/foo/bar'", true); - test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/foo'", true); - test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/'", true); - test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/quux'", false); - test_one("/", "waldo.com", "Piep", false, "foobar", "path_namespace='/'", true); - - test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo/'", false); - test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/'", false); - test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/foo/bar/waldo/'", false); - test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/foo/'", true); - - test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "/foo/bar/waldo", "arg0path='/foo/'", true); - test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "/foo", "arg0path='/foo'", true); - test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "/foo", "arg0path='/foo/bar/waldo'", false); - test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "/foo/", "arg0path='/foo/bar/waldo'", true); - - return 0; -} diff --git a/src/libelogind/sd-bus/test-bus-kernel.c b/src/libelogind/sd-bus/test-bus-kernel.c deleted file mode 100644 index 6506eaab2..000000000 --- a/src/libelogind/sd-bus/test-bus-kernel.c +++ /dev/null @@ -1,190 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2013 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 . -***/ - -#include - -#include "util.h" -#include "log.h" - -#include "sd-bus.h" -#include "bus-kernel.h" -#include "bus-util.h" -#include "bus-dump.h" - -int main(int argc, char *argv[]) { - _cleanup_close_ int bus_ref = -1; - _cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL, *bname = NULL; - _cleanup_bus_message_unref_ sd_bus_message *m = NULL; - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; - const char *ua = NULL, *ub = NULL, *the_string = NULL; - sd_bus *a, *b; - int r, pipe_fds[2]; - const char *nn; - - log_set_max_level(LOG_DEBUG); - - assert_se(asprintf(&name, "deine-mutter-%u", (unsigned) getpid()) >= 0); - - bus_ref = bus_kernel_create_bus(name, false, &bus_name); - if (bus_ref == -ENOENT) - return EXIT_TEST_SKIP; - - assert_se(bus_ref >= 0); - - address = strappend("kernel:path=", bus_name); - assert_se(address); - - r = sd_bus_new(&a); - assert_se(r >= 0); - - r = sd_bus_new(&b); - assert_se(r >= 0); - - r = sd_bus_set_description(a, "a"); - assert_se(r >= 0); - - r = sd_bus_set_address(a, address); - assert_se(r >= 0); - - r = sd_bus_set_address(b, address); - assert_se(r >= 0); - - assert_se(sd_bus_negotiate_timestamp(a, 1) >= 0); - assert_se(sd_bus_negotiate_creds(a, true, _SD_BUS_CREDS_ALL) >= 0); - - assert_se(sd_bus_negotiate_timestamp(b, 0) >= 0); - assert_se(sd_bus_negotiate_creds(b, true, 0) >= 0); - - r = sd_bus_start(a); - assert_se(r >= 0); - - r = sd_bus_start(b); - assert_se(r >= 0); - - assert_se(sd_bus_negotiate_timestamp(b, 1) >= 0); - assert_se(sd_bus_negotiate_creds(b, true, _SD_BUS_CREDS_ALL) >= 0); - - r = sd_bus_get_unique_name(a, &ua); - assert_se(r >= 0); - printf("unique a: %s\n", ua); - - r = sd_bus_get_description(a, &nn); - assert_se(r >= 0); - printf("name of a: %s\n", nn); - - r = sd_bus_get_unique_name(b, &ub); - assert_se(r >= 0); - printf("unique b: %s\n", ub); - - r = sd_bus_get_description(b, &nn); - assert_se(r >= 0); - printf("name of b: %s\n", nn); - - assert_se(bus_kernel_get_bus_name(b, &bname) >= 0); - assert_se(endswith(bname, name)); - - r = sd_bus_call_method(a, "this.doesnt.exist", "/foo", "meh.mah", "muh", &error, NULL, "s", "yayayay"); - assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_SERVICE_UNKNOWN)); - assert_se(r == -EHOSTUNREACH); - - r = sd_bus_add_match(b, NULL, "interface='waldo.com',member='Piep'", NULL, NULL); - assert_se(r >= 0); - - r = sd_bus_emit_signal(a, "/foo/bar/waldo", "waldo.com", "Piep", "sss", "I am a string", "/this/is/a/path", "and.this.a.domain.name"); - assert_se(r >= 0); - - r = sd_bus_try_close(b); - assert_se(r == -EBUSY); - - r = sd_bus_process_priority(b, -10, &m); - assert_se(r == 0); - - r = sd_bus_process(b, &m); - assert_se(r > 0); - assert_se(m); - - bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); - assert_se(sd_bus_message_rewind(m, true) >= 0); - - r = sd_bus_message_read(m, "s", &the_string); - assert_se(r >= 0); - assert_se(streq(the_string, "I am a string")); - - sd_bus_message_unref(m); - m = NULL; - - r = sd_bus_request_name(a, "net.x0pointer.foobar", 0); - assert_se(r >= 0); - - r = sd_bus_message_new_method_call(b, &m, "net.x0pointer.foobar", "/a/path", "an.inter.face", "AMethod"); - assert_se(r >= 0); - - assert_se(pipe2(pipe_fds, O_CLOEXEC) >= 0); - - assert_se(write(pipe_fds[1], "x", 1) == 1); - - pipe_fds[1] = safe_close(pipe_fds[1]); - - r = sd_bus_message_append(m, "h", pipe_fds[0]); - assert_se(r >= 0); - - pipe_fds[0] = safe_close(pipe_fds[0]); - - r = sd_bus_send(b, m, NULL); - assert_se(r >= 0); - - for (;;) { - sd_bus_message_unref(m); - m = NULL; - r = sd_bus_process(a, &m); - assert_se(r > 0); - assert_se(m); - - bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); - assert_se(sd_bus_message_rewind(m, true) >= 0); - - if (sd_bus_message_is_method_call(m, "an.inter.face", "AMethod")) { - int fd; - char x; - - r = sd_bus_message_read(m, "h", &fd); - assert_se(r >= 0); - - assert_se(read(fd, &x, 1) == 1); - assert_se(x == 'x'); - break; - } - } - - r = sd_bus_release_name(a, "net.x0pointer.foobar"); - assert_se(r >= 0); - - r = sd_bus_release_name(a, "net.x0pointer.foobar"); - assert_se(r == -ESRCH); - - r = sd_bus_try_close(a); - assert_se(r >= 0); - - sd_bus_unref(a); - sd_bus_unref(b); - - return 0; -} diff --git a/src/libelogind/sd-bus/test-bus-marshal.c b/src/libelogind/sd-bus/test-bus-marshal.c deleted file mode 100644 index b203707f2..000000000 --- a/src/libelogind/sd-bus/test-bus-marshal.c +++ /dev/null @@ -1,398 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2013 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 . -***/ - -#include -#include - -#ifdef HAVE_GLIB -#include -#endif - -#ifdef HAVE_DBUS -#include -#endif - -#include "log.h" -#include "util.h" - -#include "sd-bus.h" -#include "bus-message.h" -#include "bus-util.h" -#include "bus-dump.h" -#include "bus-label.h" - -static void test_bus_path_encode_unique(void) { - _cleanup_free_ char *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL; - - assert_se(bus_path_encode_unique(NULL, "/foo/bar", "some.sender", "a.suffix", &a) >= 0 && streq_ptr(a, "/foo/bar/some_2esender/a_2esuffix")); - assert_se(bus_path_decode_unique(a, "/foo/bar", &b, &c) > 0 && streq_ptr(b, "some.sender") && streq_ptr(c, "a.suffix")); - assert_se(bus_path_decode_unique(a, "/bar/foo", &d, &d) == 0 && !d); - assert_se(bus_path_decode_unique("/foo/bar/onlyOneSuffix", "/foo/bar", &d, &d) == 0 && !d); - assert_se(bus_path_decode_unique("/foo/bar/_/_", "/foo/bar", &d, &e) > 0 && streq_ptr(d, "") && streq_ptr(e, "")); -} - -static void test_bus_path_encode(void) { - _cleanup_free_ char *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL, *f = NULL; - - assert_se(sd_bus_path_encode("/foo/bar", "waldo", &a) >= 0 && streq(a, "/foo/bar/waldo")); - assert_se(sd_bus_path_decode(a, "/waldo", &b) == 0 && b == NULL); - assert_se(sd_bus_path_decode(a, "/foo/bar", &b) > 0 && streq(b, "waldo")); - - assert_se(sd_bus_path_encode("xxxx", "waldo", &c) < 0); - assert_se(sd_bus_path_encode("/foo/", "waldo", &c) < 0); - - assert_se(sd_bus_path_encode("/foo/bar", "", &c) >= 0 && streq(c, "/foo/bar/_")); - assert_se(sd_bus_path_decode(c, "/foo/bar", &d) > 0 && streq(d, "")); - - assert_se(sd_bus_path_encode("/foo/bar", "foo.bar", &e) >= 0 && streq(e, "/foo/bar/foo_2ebar")); - assert_se(sd_bus_path_decode(e, "/foo/bar", &f) > 0 && streq(f, "foo.bar")); -} - -static void test_bus_label_escape_one(const char *a, const char *b) { - _cleanup_free_ char *t = NULL, *x = NULL, *y = NULL; - - assert_se(t = bus_label_escape(a)); - assert_se(streq(t, b)); - - assert_se(x = bus_label_unescape(t)); - assert_se(streq(a, x)); - - assert_se(y = bus_label_unescape(b)); - assert_se(streq(a, y)); -} - -static void test_bus_label_escape(void) { - test_bus_label_escape_one("foo123bar", "foo123bar"); - test_bus_label_escape_one("foo.bar", "foo_2ebar"); - test_bus_label_escape_one("foo_2ebar", "foo_5f2ebar"); - test_bus_label_escape_one("", "_"); - test_bus_label_escape_one("_", "_5f"); - test_bus_label_escape_one("1", "_31"); - test_bus_label_escape_one(":1", "_3a1"); -} - -int main(int argc, char *argv[]) { - _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *copy = NULL; - int r, boolean; - const char *x, *x2, *y, *z, *a, *b, *c, *d, *a_signature; - uint8_t u, v; - void *buffer = NULL; - size_t sz; - char *h; - const int32_t integer_array[] = { -1, -2, 0, 1, 2 }, *return_array; - char *s; - _cleanup_free_ char *first = NULL, *second = NULL, *third = NULL; - _cleanup_fclose_ FILE *ms = NULL; - size_t first_size = 0, second_size = 0, third_size = 0; - _cleanup_bus_unref_ sd_bus *bus = NULL; - double dbl; - uint64_t u64; - - r = sd_bus_default_system(&bus); - if (r < 0) - return EXIT_TEST_SKIP; - - r = sd_bus_message_new_method_call(bus, &m, "foobar.waldo", "/", "foobar.waldo", "Piep"); - assert_se(r >= 0); - - r = sd_bus_message_append(m, ""); - assert_se(r >= 0); - - r = sd_bus_message_append(m, "s", "a string"); - assert_se(r >= 0); - - r = sd_bus_message_append(m, "s", NULL); - assert_se(r >= 0); - - r = sd_bus_message_append(m, "asg", 2, "string #1", "string #2", "sba(tt)ss"); - assert_se(r >= 0); - - r = sd_bus_message_append(m, "sass", "foobar", 5, "foo", "bar", "waldo", "piep", "pap", "after"); - assert_se(r >= 0); - - r = sd_bus_message_append(m, "a{yv}", 2, 3, "s", "foo", 5, "s", "waldo"); - assert_se(r >= 0); - - r = sd_bus_message_append(m, "y(ty)y(yt)y", 8, 777ULL, 7, 9, 77, 7777ULL, 10); - assert_se(r >= 0); - - r = sd_bus_message_append(m, "()"); - assert_se(r >= 0); - - r = sd_bus_message_append(m, "ba(ss)", 255, 3, "aaa", "1", "bbb", "2", "ccc", "3"); - assert_se(r >= 0); - - r = sd_bus_message_open_container(m, 'a', "s"); - assert_se(r >= 0); - - r = sd_bus_message_append_basic(m, 's', "foobar"); - assert_se(r >= 0); - - r = sd_bus_message_append_basic(m, 's', "waldo"); - assert_se(r >= 0); - - r = sd_bus_message_close_container(m); - assert_se(r >= 0); - - r = sd_bus_message_append_string_space(m, 5, &s); - assert_se(r >= 0); - strcpy(s, "hallo"); - - r = sd_bus_message_append_array(m, 'i', integer_array, sizeof(integer_array)); - assert_se(r >= 0); - - r = sd_bus_message_append_array(m, 'u', NULL, 0); - assert_se(r >= 0); - - r = sd_bus_message_append(m, "a(stdo)", 1, "foo", 815ULL, 47.0, "/"); - assert_se(r >= 0); - - r = bus_message_seal(m, 4711, 0); - assert_se(r >= 0); - - bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); - - ms = open_memstream(&first, &first_size); - bus_message_dump(m, ms, 0); - fflush(ms); - assert_se(!ferror(ms)); - - r = bus_message_get_blob(m, &buffer, &sz); - assert_se(r >= 0); - - h = hexmem(buffer, sz); - assert_se(h); - - log_info("message size = %zu, contents =\n%s", sz, h); - free(h); - -#ifdef HAVE_GLIB - { - GDBusMessage *g; - char *p; - -#if !defined(GLIB_VERSION_2_36) - g_type_init(); -#endif - - g = g_dbus_message_new_from_blob(buffer, sz, 0, NULL); - p = g_dbus_message_print(g, 0); - log_info("%s", p); - g_free(p); - g_object_unref(g); - } -#endif - -#ifdef HAVE_DBUS - { - DBusMessage *w; - DBusError error; - - dbus_error_init(&error); - - w = dbus_message_demarshal(buffer, sz, &error); - if (!w) - log_error("%s", error.message); - else - dbus_message_unref(w); - } -#endif - - m = sd_bus_message_unref(m); - - r = bus_message_from_malloc(bus, buffer, sz, NULL, 0, NULL, &m); - assert_se(r >= 0); - - bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); - - fclose(ms); - ms = open_memstream(&second, &second_size); - bus_message_dump(m, ms, 0); - fflush(ms); - assert_se(!ferror(ms)); - assert_se(first_size == second_size); - assert_se(memcmp(first, second, first_size) == 0); - - assert_se(sd_bus_message_rewind(m, true) >= 0); - - r = sd_bus_message_read(m, "ssasg", &x, &x2, 2, &y, &z, &a_signature); - assert_se(r > 0); - assert_se(streq(x, "a string")); - assert_se(streq(x2, "")); - assert_se(streq(y, "string #1")); - assert_se(streq(z, "string #2")); - assert_se(streq(a_signature, "sba(tt)ss")); - - r = sd_bus_message_read(m, "sass", &x, 5, &y, &z, &a, &b, &c, &d); - assert_se(r > 0); - assert_se(streq(x, "foobar")); - assert_se(streq(y, "foo")); - assert_se(streq(z, "bar")); - assert_se(streq(a, "waldo")); - assert_se(streq(b, "piep")); - assert_se(streq(c, "pap")); - assert_se(streq(d, "after")); - - r = sd_bus_message_read(m, "a{yv}", 2, &u, "s", &x, &v, "s", &y); - assert_se(r > 0); - assert_se(u == 3); - assert_se(streq(x, "foo")); - assert_se(v == 5); - assert_se(streq(y, "waldo")); - - r = sd_bus_message_read(m, "y(ty)", &v, &u64, &u); - assert_se(r > 0); - assert_se(v == 8); - assert_se(u64 == 777); - assert_se(u == 7); - - r = sd_bus_message_read(m, "y(yt)", &v, &u, &u64); - assert_se(r > 0); - assert_se(v == 9); - assert_se(u == 77); - assert_se(u64 == 7777); - - r = sd_bus_message_read(m, "y", &v); - assert_se(r > 0); - assert_se(v == 10); - - r = sd_bus_message_read(m, "()"); - assert_se(r > 0); - - r = sd_bus_message_read(m, "ba(ss)", &boolean, 3, &x, &y, &a, &b, &c, &d); - assert_se(r > 0); - assert_se(boolean); - assert_se(streq(x, "aaa")); - assert_se(streq(y, "1")); - assert_se(streq(a, "bbb")); - assert_se(streq(b, "2")); - assert_se(streq(c, "ccc")); - assert_se(streq(d, "3")); - - assert_se(sd_bus_message_verify_type(m, 'a', "s") > 0); - - r = sd_bus_message_read(m, "as", 2, &x, &y); - assert_se(r > 0); - assert_se(streq(x, "foobar")); - assert_se(streq(y, "waldo")); - - r = sd_bus_message_read_basic(m, 's', &s); - assert_se(r > 0); - assert_se(streq(s, "hallo")); - - r = sd_bus_message_read_array(m, 'i', (const void**) &return_array, &sz); - assert_se(r > 0); - assert_se(sz == sizeof(integer_array)); - assert_se(memcmp(integer_array, return_array, sz) == 0); - - r = sd_bus_message_read_array(m, 'u', (const void**) &return_array, &sz); - assert_se(r > 0); - assert_se(sz == 0); - - r = sd_bus_message_read(m, "a(stdo)", 1, &x, &u64, &dbl, &y); - assert_se(r > 0); - assert_se(streq(x, "foo")); - assert_se(u64 == 815ULL); - assert_se(fabs(dbl - 47.0) < 0.1); - assert_se(streq(y, "/")); - - r = sd_bus_message_peek_type(m, NULL, NULL); - assert_se(r == 0); - - r = sd_bus_message_new_method_call(bus, ©, "foobar.waldo", "/", "foobar.waldo", "Piep"); - assert_se(r >= 0); - - r = sd_bus_message_rewind(m, true); - assert_se(r >= 0); - - r = sd_bus_message_copy(copy, m, true); - assert_se(r >= 0); - - r = bus_message_seal(copy, 4712, 0); - assert_se(r >= 0); - - fclose(ms); - ms = open_memstream(&third, &third_size); - bus_message_dump(copy, ms, 0); - fflush(ms); - assert_se(!ferror(ms)); - - printf("<%.*s>\n", (int) first_size, first); - printf("<%.*s>\n", (int) third_size, third); - - assert_se(first_size == third_size); - assert_se(memcmp(first, third, third_size) == 0); - - r = sd_bus_message_rewind(m, true); - assert_se(r >= 0); - - assert_se(sd_bus_message_verify_type(m, 's', NULL) > 0); - - r = sd_bus_message_skip(m, "ssasg"); - assert_se(r > 0); - - assert_se(sd_bus_message_verify_type(m, 's', NULL) > 0); - - r = sd_bus_message_skip(m, "sass"); - assert_se(r >= 0); - - assert_se(sd_bus_message_verify_type(m, 'a', "{yv}") > 0); - - r = sd_bus_message_skip(m, "a{yv}y(ty)y(yt)y()"); - assert_se(r >= 0); - - assert_se(sd_bus_message_verify_type(m, 'b', NULL) > 0); - - r = sd_bus_message_read(m, "b", &boolean); - assert_se(r > 0); - assert_se(boolean); - - r = sd_bus_message_enter_container(m, 0, NULL); - assert_se(r > 0); - - r = sd_bus_message_read(m, "(ss)", &x, &y); - assert_se(r > 0); - - r = sd_bus_message_read(m, "(ss)", &a, &b); - assert_se(r > 0); - - r = sd_bus_message_read(m, "(ss)", &c, &d); - assert_se(r > 0); - - r = sd_bus_message_read(m, "(ss)", &x, &y); - assert_se(r == 0); - - r = sd_bus_message_exit_container(m); - assert_se(r >= 0); - - assert_se(streq(x, "aaa")); - assert_se(streq(y, "1")); - assert_se(streq(a, "bbb")); - assert_se(streq(b, "2")); - assert_se(streq(c, "ccc")); - assert_se(streq(d, "3")); - - test_bus_label_escape(); - test_bus_path_encode(); - test_bus_path_encode_unique(); - - return 0; -} diff --git a/src/libelogind/sd-bus/test-bus-match.c b/src/libelogind/sd-bus/test-bus-match.c deleted file mode 100644 index 83cb5c62c..000000000 --- a/src/libelogind/sd-bus/test-bus-match.c +++ /dev/null @@ -1,162 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2013 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 . -***/ - -#include "log.h" -#include "macro.h" - -#include "bus-match.h" -#include "bus-message.h" -#include "bus-util.h" -#include "bus-slot.h" - -static bool mask[32]; - -static int filter(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { - log_info("Ran %u", PTR_TO_UINT(userdata)); - assert_se(PTR_TO_UINT(userdata) < ELEMENTSOF(mask)); - mask[PTR_TO_UINT(userdata)] = true; - return 0; -} - -static bool mask_contains(unsigned a[], unsigned n) { - unsigned i, j; - - for (i = 0; i < ELEMENTSOF(mask); i++) { - bool found = false; - - for (j = 0; j < n; j++) - if (a[j] == i) { - found = true; - break; - } - - if (found != mask[i]) - return false; - } - - return true; -} - -static int match_add(sd_bus_slot *slots, struct bus_match_node *root, const char *match, int value) { - struct bus_match_component *components = NULL; - unsigned n_components = 0; - sd_bus_slot *s; - int r; - - s = slots + value; - zero(*s); - - r = bus_match_parse(match, &components, &n_components); - if (r < 0) - return r; - - s->userdata = INT_TO_PTR(value); - s->match_callback.callback = filter; - - r = bus_match_add(root, components, n_components, &s->match_callback); - bus_match_parse_free(components, n_components); - - return r; -} - -static void test_match_scope(const char *match, enum bus_match_scope scope) { - struct bus_match_component *components = NULL; - unsigned n_components = 0; - - assert_se(bus_match_parse(match, &components, &n_components) >= 0); - assert_se(bus_match_get_scope(components, n_components) == scope); - bus_match_parse_free(components, n_components); -} - -int main(int argc, char *argv[]) { - struct bus_match_node root = { - .type = BUS_MATCH_ROOT, - }; - - _cleanup_bus_message_unref_ sd_bus_message *m = NULL; - _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL; - enum bus_match_node_type i; - sd_bus_slot slots[19]; - int r; - - r = sd_bus_open_system(&bus); - if (r < 0) - return EXIT_TEST_SKIP; - - assert_se(match_add(slots, &root, "arg2='wal\\'do',sender='foo',type='signal',interface='bar.x',", 1) >= 0); - assert_se(match_add(slots, &root, "arg2='wal\\'do2',sender='foo',type='signal',interface='bar.x',", 2) >= 0); - assert_se(match_add(slots, &root, "arg3='test',sender='foo',type='signal',interface='bar.x',", 3) >= 0); - assert_se(match_add(slots, &root, "arg3='test',sender='foo',type='method_call',interface='bar.x',", 4) >= 0); - assert_se(match_add(slots, &root, "", 5) >= 0); - assert_se(match_add(slots, &root, "interface='quux.x'", 6) >= 0); - assert_se(match_add(slots, &root, "interface='bar.x'", 7) >= 0); - assert_se(match_add(slots, &root, "member='waldo',path='/foo/bar'", 8) >= 0); - assert_se(match_add(slots, &root, "path='/foo/bar'", 9) >= 0); - assert_se(match_add(slots, &root, "path_namespace='/foo'", 10) >= 0); - assert_se(match_add(slots, &root, "path_namespace='/foo/quux'", 11) >= 0); - assert_se(match_add(slots, &root, "arg1='two'", 12) >= 0); - assert_se(match_add(slots, &root, "member='waldo',arg2path='/prefix/'", 13) >= 0); - assert_se(match_add(slots, &root, "member=waldo,path='/foo/bar',arg3namespace='prefix'", 14) >= 0); - assert_se(match_add(slots, &root, "arg4='pi'", 15) >= 0); - assert_se(match_add(slots, &root, "arg4='pa'", 16) >= 0); - assert_se(match_add(slots, &root, "arg4='po'", 17) >= 0); - assert_se(match_add(slots, &root, "arg4='pu'", 18) >= 0); - - bus_match_dump(&root, 0); - - assert_se(sd_bus_message_new_signal(bus, &m, "/foo/bar", "bar.x", "waldo") >= 0); - assert_se(sd_bus_message_append(m, "ssssas", "one", "two", "/prefix/three", "prefix.four", 3, "pi", "pa", "po") >= 0); - assert_se(bus_message_seal(m, 1, 0) >= 0); - - zero(mask); - assert_se(bus_match_run(NULL, &root, m) == 0); - assert_se(mask_contains((unsigned[]) { 9, 8, 7, 5, 10, 12, 13, 14, 15, 16, 17 }, 11)); - - assert_se(bus_match_remove(&root, &slots[8].match_callback) >= 0); - assert_se(bus_match_remove(&root, &slots[13].match_callback) >= 0); - - bus_match_dump(&root, 0); - - zero(mask); - assert_se(bus_match_run(NULL, &root, m) == 0); - assert_se(mask_contains((unsigned[]) { 9, 5, 10, 12, 14, 7, 15, 16, 17 }, 9)); - - for (i = 0; i < _BUS_MATCH_NODE_TYPE_MAX; i++) { - char buf[32]; - const char *x; - - assert_se(x = bus_match_node_type_to_string(i, buf, sizeof(buf))); - - if (i >= BUS_MATCH_MESSAGE_TYPE) - assert_se(bus_match_node_type_from_string(x, strlen(x)) == i); - } - - bus_match_free(&root); - - test_match_scope("interface='foobar'", BUS_MATCH_GENERIC); - test_match_scope("", BUS_MATCH_GENERIC); - test_match_scope("interface='org.freedesktop.DBus.Local'", BUS_MATCH_LOCAL); - test_match_scope("sender='org.freedesktop.DBus.Local'", BUS_MATCH_LOCAL); - test_match_scope("member='gurke',path='/org/freedesktop/DBus/Local'", BUS_MATCH_LOCAL); - test_match_scope("arg2='piep',sender='org.freedesktop.DBus',member='waldo'", BUS_MATCH_DRIVER); - - return 0; -} diff --git a/src/libelogind/sd-bus/test-bus-objects.c b/src/libelogind/sd-bus/test-bus-objects.c deleted file mode 100644 index 359984c7f..000000000 --- a/src/libelogind/sd-bus/test-bus-objects.c +++ /dev/null @@ -1,554 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2013 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 . -***/ - -#include -#include - -#include "log.h" -#include "util.h" -#include "macro.h" -#include "strv.h" - -#include "sd-bus.h" -#include "bus-internal.h" -#include "bus-message.h" -#include "bus-util.h" -#include "bus-dump.h" - -struct context { - int fds[2]; - bool quit; - char *something; - char *automatic_string_property; - uint32_t automatic_integer_property; -}; - -static int something_handler(sd_bus_message *m, void *userdata, sd_bus_error *error) { - struct context *c = userdata; - const char *s; - char *n = NULL; - int r; - - r = sd_bus_message_read(m, "s", &s); - assert_se(r > 0); - - n = strjoin("<<<", s, ">>>", NULL); - assert_se(n); - - free(c->something); - c->something = n; - - log_info("AlterSomething() called, got %s, returning %s", s, n); - - /* This should fail, since the return type doesn't match */ - assert_se(sd_bus_reply_method_return(m, "u", 4711) == -ENOMSG); - - r = sd_bus_reply_method_return(m, "s", n); - assert_se(r >= 0); - - return 1; -} - -static int exit_handler(sd_bus_message *m, void *userdata, sd_bus_error *error) { - struct context *c = userdata; - int r; - - c->quit = true; - - log_info("Exit called"); - - r = sd_bus_reply_method_return(m, ""); - assert_se(r >= 0); - - return 1; -} - -static int get_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { - struct context *c = userdata; - int r; - - log_info("property get for %s called, returning \"%s\".", property, c->something); - - r = sd_bus_message_append(reply, "s", c->something); - assert_se(r >= 0); - - return 1; -} - -static int set_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *error) { - struct context *c = userdata; - const char *s; - char *n; - int r; - - log_info("property set for %s called", property); - - r = sd_bus_message_read(value, "s", &s); - assert_se(r >= 0); - - n = strdup(s); - assert_se(n); - - free(c->something); - c->something = n; - - return 1; -} - -static int value_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { - _cleanup_free_ char *s = NULL; - int r; - - assert_se(asprintf(&s, "object %p, path %s", userdata, path) >= 0); - r = sd_bus_message_append(reply, "s", s); - assert_se(r >= 0); - - assert_se(startswith(path, "/value/") != NULL || strcmp(path, "/value") == 0); - - assert_se(PTR_TO_UINT(userdata) == 30); - - return 1; -} - -static int notify_test(sd_bus_message *m, void *userdata, sd_bus_error *error) { - int r; - - assert_se(sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), m->path, "org.freedesktop.systemd.ValueTest", "Value", NULL) >= 0); - - r = sd_bus_reply_method_return(m, NULL); - assert_se(r >= 0); - - return 1; -} - -static int notify_test2(sd_bus_message *m, void *userdata, sd_bus_error *error) { - int r; - - assert_se(sd_bus_emit_properties_changed_strv(sd_bus_message_get_bus(m), m->path, "org.freedesktop.systemd.ValueTest", NULL) >= 0); - - r = sd_bus_reply_method_return(m, NULL); - assert_se(r >= 0); - - return 1; -} - -static int emit_interfaces_added(sd_bus_message *m, void *userdata, sd_bus_error *error) { - int r; - - assert_se(sd_bus_emit_interfaces_added(sd_bus_message_get_bus(m), "/value/a/x", "org.freedesktop.systemd.ValueTest", NULL) >= 0); - - r = sd_bus_reply_method_return(m, NULL); - assert_se(r >= 0); - - return 1; -} - -static int emit_interfaces_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) { - int r; - - assert_se(sd_bus_emit_interfaces_removed(sd_bus_message_get_bus(m), "/value/a/x", "org.freedesktop.systemd.ValueTest", NULL) >= 0); - - r = sd_bus_reply_method_return(m, NULL); - assert_se(r >= 0); - - return 1; -} - -static int emit_object_added(sd_bus_message *m, void *userdata, sd_bus_error *error) { - int r; - - assert_se(sd_bus_emit_object_added(sd_bus_message_get_bus(m), "/value/a/x") >= 0); - - r = sd_bus_reply_method_return(m, NULL); - assert_se(r >= 0); - - return 1; -} - -static int emit_object_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) { - int r; - - assert_se(sd_bus_emit_object_removed(sd_bus_message_get_bus(m), "/value/a/x") >= 0); - - r = sd_bus_reply_method_return(m, NULL); - assert_se(r >= 0); - - return 1; -} - -static const sd_bus_vtable vtable[] = { - SD_BUS_VTABLE_START(0), - SD_BUS_METHOD("AlterSomething", "s", "s", something_handler, 0), - SD_BUS_METHOD("Exit", "", "", exit_handler, 0), - SD_BUS_WRITABLE_PROPERTY("Something", "s", get_handler, set_handler, 0, 0), - SD_BUS_WRITABLE_PROPERTY("AutomaticStringProperty", "s", NULL, NULL, offsetof(struct context, automatic_string_property), 0), - SD_BUS_WRITABLE_PROPERTY("AutomaticIntegerProperty", "u", NULL, NULL, offsetof(struct context, automatic_integer_property), 0), - SD_BUS_METHOD("NoOperation", NULL, NULL, NULL, 0), - SD_BUS_METHOD("EmitInterfacesAdded", NULL, NULL, emit_interfaces_added, 0), - SD_BUS_METHOD("EmitInterfacesRemoved", NULL, NULL, emit_interfaces_removed, 0), - SD_BUS_METHOD("EmitObjectAdded", NULL, NULL, emit_object_added, 0), - SD_BUS_METHOD("EmitObjectRemoved", NULL, NULL, emit_object_removed, 0), - SD_BUS_VTABLE_END -}; - -static const sd_bus_vtable vtable2[] = { - SD_BUS_VTABLE_START(0), - SD_BUS_METHOD("NotifyTest", "", "", notify_test, 0), - SD_BUS_METHOD("NotifyTest2", "", "", notify_test2, 0), - SD_BUS_PROPERTY("Value", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), - SD_BUS_PROPERTY("Value2", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), - SD_BUS_PROPERTY("Value3", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("Value4", "s", value_handler, 10, 0), - SD_BUS_VTABLE_END -}; - -static int enumerator_callback(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { - - if (object_path_startswith("/value", path)) - assert_se(*nodes = strv_new("/value/a", "/value/b", "/value/c", NULL)); - - return 1; -} - -static int enumerator2_callback(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { - - if (object_path_startswith("/value/a", path)) - assert_se(*nodes = strv_new("/value/a/x", "/value/a/y", "/value/a/z", NULL)); - - return 1; -} - -static void *server(void *p) { - struct context *c = p; - sd_bus *bus = NULL; - sd_id128_t id; - int r; - - c->quit = false; - - assert_se(sd_id128_randomize(&id) >= 0); - - assert_se(sd_bus_new(&bus) >= 0); - assert_se(sd_bus_set_fd(bus, c->fds[0], c->fds[0]) >= 0); - assert_se(sd_bus_set_server(bus, 1, id) >= 0); - - assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test", vtable, c) >= 0); - assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test2", vtable, c) >= 0); - assert_se(sd_bus_add_fallback_vtable(bus, NULL, "/value", "org.freedesktop.systemd.ValueTest", vtable2, NULL, UINT_TO_PTR(20)) >= 0); - assert_se(sd_bus_add_node_enumerator(bus, NULL, "/value", enumerator_callback, NULL) >= 0); - assert_se(sd_bus_add_node_enumerator(bus, NULL, "/value/a", enumerator2_callback, NULL) >= 0); - assert_se(sd_bus_add_object_manager(bus, NULL, "/value") >= 0); - assert_se(sd_bus_add_object_manager(bus, NULL, "/value/a") >= 0); - - assert_se(sd_bus_start(bus) >= 0); - - log_error("Entering event loop on server"); - - while (!c->quit) { - log_error("Loop!"); - - r = sd_bus_process(bus, NULL); - if (r < 0) { - log_error_errno(r, "Failed to process requests: %m"); - goto fail; - } - - if (r == 0) { - r = sd_bus_wait(bus, (uint64_t) -1); - if (r < 0) { - log_error_errno(r, "Failed to wait: %m"); - goto fail; - } - - continue; - } - } - - r = 0; - -fail: - if (bus) { - sd_bus_flush(bus); - sd_bus_unref(bus); - } - - return INT_TO_PTR(r); -} - -static int client(struct context *c) { - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; - _cleanup_bus_unref_ sd_bus *bus = NULL; - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; - const char *s; - int r; - - assert_se(sd_bus_new(&bus) >= 0); - assert_se(sd_bus_set_fd(bus, c->fds[1], c->fds[1]) >= 0); - assert_se(sd_bus_start(bus) >= 0); - - r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "NoOperation", &error, NULL, NULL); - assert_se(r >= 0); - - r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AlterSomething", &error, &reply, "s", "hallo"); - assert_se(r >= 0); - - r = sd_bus_message_read(reply, "s", &s); - assert_se(r >= 0); - assert_se(streq(s, "<<>>")); - - sd_bus_message_unref(reply); - reply = NULL; - - r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Doesntexist", &error, &reply, ""); - assert_se(r < 0); - assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD)); - - sd_bus_error_free(&error); - - r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AlterSomething", &error, &reply, "as", 1, "hallo"); - assert_se(r < 0); - assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_INVALID_ARGS)); - - sd_bus_error_free(&error); - - r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, &reply, "s"); - assert_se(r >= 0); - - r = sd_bus_message_read(reply, "s", &s); - assert_se(r >= 0); - assert_se(streq(s, "<<>>")); - - sd_bus_message_unref(reply); - reply = NULL; - - r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, "s", "test"); - assert_se(r >= 0); - - r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, &reply, "s"); - assert_se(r >= 0); - - r = sd_bus_message_read(reply, "s", &s); - assert_se(r >= 0); - assert_se(streq(s, "test")); - - sd_bus_message_unref(reply); - reply = NULL; - - r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AutomaticIntegerProperty", &error, "u", 815); - assert_se(r >= 0); - - assert_se(c->automatic_integer_property == 815); - - r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AutomaticStringProperty", &error, "s", "Du Dödel, Du!"); - assert_se(r >= 0); - - assert_se(streq(c->automatic_string_property, "Du Dödel, Du!")); - - r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, ""); - assert_se(r >= 0); - - r = sd_bus_message_read(reply, "s", &s); - assert_se(r >= 0); - fputs(s, stdout); - - sd_bus_message_unref(reply); - reply = NULL; - - r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/value/xuzz", "org.freedesktop.systemd.ValueTest", "Value", &error, &reply, "s"); - assert_se(r >= 0); - - r = sd_bus_message_read(reply, "s", &s); - assert_se(r >= 0); - log_info("read %s", s); - - sd_bus_message_unref(reply); - reply = NULL; - - r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, ""); - assert_se(r >= 0); - - r = sd_bus_message_read(reply, "s", &s); - assert_se(r >= 0); - fputs(s, stdout); - - sd_bus_message_unref(reply); - reply = NULL; - - r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, ""); - assert_se(r >= 0); - - r = sd_bus_message_read(reply, "s", &s); - assert_se(r >= 0); - fputs(s, stdout); - - sd_bus_message_unref(reply); - reply = NULL; - - r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, ""); - assert_se(r >= 0); - - r = sd_bus_message_read(reply, "s", &s); - assert_se(r >= 0); - fputs(s, stdout); - - sd_bus_message_unref(reply); - reply = NULL; - - r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", ""); - assert_se(r >= 0); - - bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); - - sd_bus_message_unref(reply); - reply = NULL; - - r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", "org.freedesktop.systemd.ValueTest2"); - assert_se(r < 0); - assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_INTERFACE)); - sd_bus_error_free(&error); - - r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, ""); - assert_se(r < 0); - assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD)); - sd_bus_error_free(&error); - - r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, ""); - assert_se(r >= 0); - - bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); - - sd_bus_message_unref(reply); - reply = NULL; - - r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.systemd.ValueTest", "NotifyTest", &error, NULL, ""); - assert_se(r >= 0); - - r = sd_bus_process(bus, &reply); - assert_se(r > 0); - - assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.Properties", "PropertiesChanged")); - bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); - - sd_bus_message_unref(reply); - reply = NULL; - - r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.systemd.ValueTest", "NotifyTest2", &error, NULL, ""); - assert_se(r >= 0); - - r = sd_bus_process(bus, &reply); - assert_se(r > 0); - - assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.Properties", "PropertiesChanged")); - bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); - - sd_bus_message_unref(reply); - reply = NULL; - - r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitInterfacesAdded", &error, NULL, ""); - assert_se(r >= 0); - - r = sd_bus_process(bus, &reply); - assert_se(r > 0); - - assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded")); - bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); - - sd_bus_message_unref(reply); - reply = NULL; - - r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitInterfacesRemoved", &error, NULL, ""); - assert_se(r >= 0); - - r = sd_bus_process(bus, &reply); - assert_se(r > 0); - - assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved")); - bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); - - sd_bus_message_unref(reply); - reply = NULL; - - r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitObjectAdded", &error, NULL, ""); - assert_se(r >= 0); - - r = sd_bus_process(bus, &reply); - assert_se(r > 0); - - assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded")); - bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); - - sd_bus_message_unref(reply); - reply = NULL; - - r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitObjectRemoved", &error, NULL, ""); - assert_se(r >= 0); - - r = sd_bus_process(bus, &reply); - assert_se(r > 0); - - assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved")); - bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); - - sd_bus_message_unref(reply); - reply = NULL; - - r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Exit", &error, NULL, ""); - assert_se(r >= 0); - - sd_bus_flush(bus); - - return 0; -} - -int main(int argc, char *argv[]) { - struct context c = {}; - pthread_t s; - void *p; - int r, q; - - zero(c); - - c.automatic_integer_property = 4711; - assert_se(c.automatic_string_property = strdup("dudeldu")); - - assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, c.fds) >= 0); - - r = pthread_create(&s, NULL, server, &c); - if (r != 0) - return -r; - - r = client(&c); - - q = pthread_join(s, &p); - if (q != 0) - return -q; - - if (r < 0) - return r; - - if (PTR_TO_INT(p) < 0) - return PTR_TO_INT(p); - - free(c.something); - free(c.automatic_string_property); - - return EXIT_SUCCESS; -} diff --git a/src/libelogind/sd-bus/test-bus-signature.c b/src/libelogind/sd-bus/test-bus-signature.c deleted file mode 100644 index 17c6188ca..000000000 --- a/src/libelogind/sd-bus/test-bus-signature.c +++ /dev/null @@ -1,166 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2013 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 . -***/ - - -#include "log.h" -#include "bus-signature.h" -#include "bus-internal.h" - -int main(int argc, char *argv[]) { - char prefix[256]; - int r; - - assert_se(signature_is_single("y", false)); - assert_se(signature_is_single("u", false)); - assert_se(signature_is_single("v", false)); - assert_se(signature_is_single("as", false)); - assert_se(signature_is_single("(ss)", false)); - assert_se(signature_is_single("()", false)); - assert_se(signature_is_single("(()()()()())", false)); - assert_se(signature_is_single("(((())))", false)); - assert_se(signature_is_single("((((s))))", false)); - assert_se(signature_is_single("{ss}", true)); - assert_se(signature_is_single("a{ss}", false)); - assert_se(!signature_is_single("uu", false)); - assert_se(!signature_is_single("", false)); - assert_se(!signature_is_single("(", false)); - assert_se(!signature_is_single(")", false)); - assert_se(!signature_is_single("())", false)); - assert_se(!signature_is_single("((())", false)); - assert_se(!signature_is_single("{)", false)); - assert_se(!signature_is_single("{}", true)); - assert_se(!signature_is_single("{sss}", true)); - assert_se(!signature_is_single("{s}", true)); - assert_se(!signature_is_single("{ss}", false)); - assert_se(!signature_is_single("{ass}", true)); - assert_se(!signature_is_single("a}", true)); - - assert_se(signature_is_pair("yy")); - assert_se(signature_is_pair("ss")); - assert_se(signature_is_pair("sas")); - assert_se(signature_is_pair("sv")); - assert_se(signature_is_pair("sa(vs)")); - assert_se(!signature_is_pair("")); - assert_se(!signature_is_pair("va")); - assert_se(!signature_is_pair("sss")); - assert_se(!signature_is_pair("{s}ss")); - - assert_se(signature_is_valid("ssa{ss}sssub", true)); - assert_se(signature_is_valid("ssa{ss}sssub", false)); - assert_se(signature_is_valid("{ss}", true)); - assert_se(!signature_is_valid("{ss}", false)); - assert_se(signature_is_valid("", true)); - assert_se(signature_is_valid("", false)); - - assert_se(signature_is_valid("sssusa(uuubbba(uu)uuuu)a{u(uuuvas)}", false)); - - assert_se(!signature_is_valid("a", false)); - assert_se(signature_is_valid("as", false)); - assert_se(signature_is_valid("aas", false)); - assert_se(signature_is_valid("aaas", false)); - assert_se(signature_is_valid("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaad", false)); - assert_se(signature_is_valid("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaas", false)); - assert_se(!signature_is_valid("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaau", false)); - - assert_se(signature_is_valid("(((((((((((((((((((((((((((((((())))))))))))))))))))))))))))))))", false)); - assert_se(!signature_is_valid("((((((((((((((((((((((((((((((((()))))))))))))))))))))))))))))))))", false)); - - assert_se(namespace_complex_pattern("", "")); - assert_se(namespace_complex_pattern("foobar", "foobar")); - assert_se(namespace_complex_pattern("foobar.waldo", "foobar.waldo")); - assert_se(namespace_complex_pattern("foobar.", "foobar.waldo")); - assert_se(namespace_complex_pattern("foobar.waldo", "foobar.")); - assert_se(!namespace_complex_pattern("foobar.waldo", "foobar")); - assert_se(!namespace_complex_pattern("foobar", "foobar.waldo")); - assert_se(!namespace_complex_pattern("", "foo")); - assert_se(!namespace_complex_pattern("foo", "")); - assert_se(!namespace_complex_pattern("foo.", "")); - - assert_se(path_complex_pattern("", "")); - assert_se(!path_complex_pattern("", "/")); - assert_se(!path_complex_pattern("/", "")); - assert_se(path_complex_pattern("/", "/")); - assert_se(path_complex_pattern("/foobar/", "/")); - assert_se(!path_complex_pattern("/foobar/", "/foobar")); - assert_se(path_complex_pattern("/foobar", "/foobar")); - assert_se(!path_complex_pattern("/foobar", "/foobar/")); - assert_se(!path_complex_pattern("/foobar", "/foobar/waldo")); - assert_se(path_complex_pattern("/foobar/", "/foobar/waldo")); - assert_se(path_complex_pattern("/foobar/waldo", "/foobar/")); - - assert_se(path_simple_pattern("/foo/", "/foo/bar/waldo")); - - assert_se(namespace_simple_pattern("", "")); - assert_se(namespace_simple_pattern("", ".foobar")); - assert_se(namespace_simple_pattern("foobar", "foobar")); - assert_se(namespace_simple_pattern("foobar.waldo", "foobar.waldo")); - assert_se(namespace_simple_pattern("foobar", "foobar.waldo")); - assert_se(!namespace_simple_pattern("foobar.waldo", "foobar")); - assert_se(!namespace_simple_pattern("", "foo")); - assert_se(!namespace_simple_pattern("foo", "")); - assert_se(namespace_simple_pattern("foo.", "foo.bar.waldo")); - - assert_se(streq(object_path_startswith("/foo/bar", "/foo"), "bar")); - assert_se(streq(object_path_startswith("/foo", "/foo"), "")); - assert_se(streq(object_path_startswith("/foo", "/"), "foo")); - assert_se(streq(object_path_startswith("/", "/"), "")); - assert_se(!object_path_startswith("/foo", "/bar")); - assert_se(!object_path_startswith("/", "/bar")); - assert_se(!object_path_startswith("/foo", "")); - - assert_se(object_path_is_valid("/foo/bar")); - assert_se(object_path_is_valid("/foo")); - assert_se(object_path_is_valid("/")); - assert_se(object_path_is_valid("/foo5")); - assert_se(object_path_is_valid("/foo_5")); - assert_se(!object_path_is_valid("")); - assert_se(!object_path_is_valid("/foo/")); - assert_se(!object_path_is_valid("//")); - assert_se(!object_path_is_valid("//foo")); - assert_se(!object_path_is_valid("/foo//bar")); - assert_se(!object_path_is_valid("/foo/aaaäöä")); - - OBJECT_PATH_FOREACH_PREFIX(prefix, "/") { - log_info("<%s>", prefix); - assert_not_reached("???"); - } - - r = 0; - OBJECT_PATH_FOREACH_PREFIX(prefix, "/xxx") { - log_info("<%s>", prefix); - assert_se(streq(prefix, "/")); - assert_se(r == 0); - r++; - } - assert_se(r == 1); - - r = 0; - OBJECT_PATH_FOREACH_PREFIX(prefix, "/xxx/yyy/zzz") { - log_info("<%s>", prefix); - assert_se(r != 0 || streq(prefix, "/xxx/yyy")); - assert_se(r != 1 || streq(prefix, "/xxx")); - assert_se(r != 2 || streq(prefix, "/")); - r++; - } - assert_se(r == 3); - - return 0; -} diff --git a/src/libelogind/sd-daemon/Makefile b/src/libelogind/sd-daemon/Makefile index d0b0e8e00..94aaae2c4 120000 --- a/src/libelogind/sd-daemon/Makefile +++ b/src/libelogind/sd-daemon/Makefile @@ -1 +1 @@ -../Makefile \ No newline at end of file +../../Makefile \ No newline at end of file diff --git a/src/libelogind/sd-device/sd-device.c b/src/libelogind/sd-device/sd-device.c deleted file mode 100644 index 7cea5a074..000000000 --- a/src/libelogind/sd-device/sd-device.c +++ /dev/null @@ -1,1864 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2008-2012 Kay Sievers - Copyright 2014 Tom Gundersen - - 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 . -***/ - -#include -#include -#include - -#include "util.h" -#include "macro.h" -#include "path-util.h" -#include "strxcpyx.h" -#include "fileio.h" -#include "hashmap.h" -#include "set.h" -#include "strv.h" - -#include "sd-device.h" - -#include "device-util.h" -#include "device-private.h" -#include "device-internal.h" - -int device_new_aux(sd_device **ret) { - _cleanup_device_unref_ sd_device *device = NULL; - - assert(ret); - - device = new0(sd_device, 1); - if (!device) - return -ENOMEM; - - device->n_ref = 1; - device->watch_handle = -1; - - *ret = device; - device = NULL; - - return 0; -} - -_public_ sd_device *sd_device_ref(sd_device *device) { - if (device) - assert_se(++ device->n_ref >= 2); - - return device; -} - -_public_ sd_device *sd_device_unref(sd_device *device) { - if (device && -- device->n_ref == 0) { - sd_device_unref(device->parent); - free(device->syspath); - free(device->sysname); - free(device->devtype); - free(device->devname); - free(device->subsystem); - free(device->driver); - free(device->id_filename); - free(device->properties_strv); - free(device->properties_nulstr); - - ordered_hashmap_free_free_free(device->properties); - ordered_hashmap_free_free_free(device->properties_db); - hashmap_free_free_free(device->sysattr_values); - set_free_free(device->sysattrs); - set_free_free(device->tags); - set_free_free(device->devlinks); - - free(device); - } - - return NULL; -} - -int device_add_property_aux(sd_device *device, const char *_key, const char *_value, bool db) { - OrderedHashmap **properties; - - assert(device); - assert(_key); - - if (db) - properties = &device->properties_db; - else - properties = &device->properties; - - if (_value) { - _cleanup_free_ char *key = NULL, *value = NULL, *old_key = NULL, *old_value = NULL; - int r; - - r = ordered_hashmap_ensure_allocated(properties, &string_hash_ops); - if (r < 0) - return r; - - key = strdup(_key); - if (!key) - return -ENOMEM; - - value = strdup(_value); - if (!value) - return -ENOMEM; - - old_value = ordered_hashmap_get2(*properties, key, (void**) &old_key); - - r = ordered_hashmap_replace(*properties, key, value); - if (r < 0) - return r; - - key = NULL; - value = NULL; - } else { - _cleanup_free_ char *key = NULL; - _cleanup_free_ char *value = NULL; - - value = ordered_hashmap_remove2(*properties, _key, (void**) &key); - } - - if (!db) { - device->properties_generation ++; - device->properties_buf_outdated = true; - } - - return 0; -} - -int device_add_property_internal(sd_device *device, const char *key, const char *value) { - return device_add_property_aux(device, key, value, false); -} - -int device_set_syspath(sd_device *device, const char *_syspath, bool verify) { - _cleanup_free_ char *syspath = NULL; - const char *devpath; - int r; - - assert(device); - assert(_syspath); - - /* must be a subdirectory of /sys */ - if (!path_startswith(_syspath, "/sys/")) { - log_debug("sd-device: syspath '%s' is not a subdirectory of /sys", _syspath); - return -EINVAL; - } - - if (verify) { - r = readlink_and_canonicalize(_syspath, &syspath); - if (r == -ENOENT) - /* the device does not exist (any more?) */ - return -ENODEV; - else if (r == -EINVAL) { - /* not a symlink */ - syspath = canonicalize_file_name(_syspath); - if (!syspath) { - if (errno == ENOENT) - /* the device does not exist (any more?) */ - return -ENODEV; - - log_debug("sd-device: could not canonicalize '%s': %m", _syspath); - return -errno; - } - } else if (r < 0) { - log_debug("sd-device: could not get target of '%s': %s", _syspath, strerror(-r)); - return r; - } - - if (path_startswith(syspath, "/sys/devices/")) { - char *path; - - /* all 'devices' require an 'uevent' file */ - path = strjoina(syspath, "/uevent"); - r = access(path, F_OK); - if (r < 0) { - if (errno == ENOENT) - /* this is not a valid device */ - return -ENODEV; - - log_debug("sd-device: %s does not have an uevent file: %m", syspath); - return -errno; - } - } else { - /* everything else just just needs to be a directory */ - if (!is_dir(syspath, false)) - return -ENODEV; - } - } else { - syspath = strdup(_syspath); - if (!syspath) - return -ENOMEM; - } - - devpath = syspath + strlen("/sys"); - - r = device_add_property_internal(device, "DEVPATH", devpath); - if (r < 0) - return r; - - free(device->syspath); - device->syspath = syspath; - syspath = NULL; - - device->devpath = devpath; - - return 0; -} - -_public_ int sd_device_new_from_syspath(sd_device **ret, const char *syspath) { - _cleanup_device_unref_ sd_device *device = NULL; - int r; - - assert_return(ret, -EINVAL); - assert_return(syspath, -EINVAL); - - r = device_new_aux(&device); - if (r < 0) - return r; - - r = device_set_syspath(device, syspath, true); - if (r < 0) - return r; - - *ret = device; - device = NULL; - - return 0; -} - -_public_ int sd_device_new_from_devnum(sd_device **ret, char type, dev_t devnum) { - char *syspath; - char id[DECIMAL_STR_MAX(unsigned) * 2 + 1]; - - assert_return(ret, -EINVAL); - assert_return(type == 'b' || type == 'c', -EINVAL); - - /* use /sys/dev/{block,char}/: link */ - snprintf(id, sizeof(id), "%u:%u", major(devnum), minor(devnum)); - - syspath = strjoina("/sys/dev/", (type == 'b' ? "block" : "char"), "/", id); - - return sd_device_new_from_syspath(ret, syspath); -} - -_public_ int sd_device_new_from_subsystem_sysname(sd_device **ret, const char *subsystem, const char *sysname) { - char *syspath; - - assert_return(ret, -EINVAL); - assert_return(subsystem, -EINVAL); - assert_return(sysname, -EINVAL); - - if (streq(subsystem, "subsystem")) { - syspath = strjoina("/sys/subsystem/", sysname); - if (access(syspath, F_OK) >= 0) - return sd_device_new_from_syspath(ret, syspath); - - syspath = strjoina("/sys/bus/", sysname); - if (access(syspath, F_OK) >= 0) - return sd_device_new_from_syspath(ret, syspath); - - syspath = strjoina("/sys/class/", sysname); - if (access(syspath, F_OK) >= 0) - return sd_device_new_from_syspath(ret, syspath); - } else if (streq(subsystem, "module")) { - syspath = strjoina("/sys/module/", sysname); - if (access(syspath, F_OK) >= 0) - return sd_device_new_from_syspath(ret, syspath); - } else if (streq(subsystem, "drivers")) { - char subsys[PATH_MAX]; - char *driver; - - strscpy(subsys, sizeof(subsys), sysname); - driver = strchr(subsys, ':'); - if (driver) { - driver[0] = '\0'; - driver++; - - syspath = strjoina("/sys/subsystem/", subsys, "/drivers/", driver); - if (access(syspath, F_OK) >= 0) - return sd_device_new_from_syspath(ret, syspath); - - syspath = strjoina("/sys/bus/", subsys, "/drivers/", driver); - if (access(syspath, F_OK) >= 0) - return sd_device_new_from_syspath(ret, syspath); - } else - return -EINVAL; - } else { - syspath = strjoina("/sys/subsystem/", subsystem, "/devices/", sysname); - if (access(syspath, F_OK) >= 0) - return sd_device_new_from_syspath(ret, syspath); - - syspath = strjoina("/sys/bus/", subsystem, "/devices/", sysname); - if (access(syspath, F_OK) >= 0) - return sd_device_new_from_syspath(ret, syspath); - - syspath = strjoina("/sys/class/", subsystem, "/", sysname); - if (access(syspath, F_OK) >= 0) - return sd_device_new_from_syspath(ret, syspath); - } - - return -ENODEV; -} - -int device_set_devtype(sd_device *device, const char *_devtype) { - _cleanup_free_ char *devtype = NULL; - int r; - - assert(device); - assert(_devtype); - - devtype = strdup(_devtype); - if (!devtype) - return -ENOMEM; - - r = device_add_property_internal(device, "DEVTYPE", devtype); - if (r < 0) - return r; - - free(device->devtype); - device->devtype = devtype; - devtype = NULL; - - return 0; -} - -int device_set_ifindex(sd_device *device, const char *_ifindex) { - int ifindex, r; - - assert(device); - assert(_ifindex); - - r = safe_atoi(_ifindex, &ifindex); - if (r < 0) - return r; - - if (ifindex <= 0) - return -EINVAL; - - r = device_add_property_internal(device, "IFINDEX", _ifindex); - if (r < 0) - return r; - - device->ifindex = ifindex; - - return 0; -} - -int device_set_devname(sd_device *device, const char *_devname) { - _cleanup_free_ char *devname = NULL; - int r; - - assert(device); - assert(_devname); - - if (_devname[0] != '/') { - r = asprintf(&devname, "/dev/%s", _devname); - if (r < 0) - return -ENOMEM; - } else { - devname = strdup(_devname); - if (!devname) - return -ENOMEM; - } - - r = device_add_property_internal(device, "DEVNAME", devname); - if (r < 0) - return r; - - free(device->devname); - device->devname = devname; - devname = NULL; - - return 0; -} - -int device_set_devmode(sd_device *device, const char *_devmode) { - unsigned devmode; - int r; - - assert(device); - assert(_devmode); - - r = safe_atou(_devmode, &devmode); - if (r < 0) - return r; - - if (devmode > 07777) - return -EINVAL; - - r = device_add_property_internal(device, "DEVMODE", _devmode); - if (r < 0) - return r; - - device->devmode = devmode; - - return 0; -} - -int device_set_devnum(sd_device *device, const char *major, const char *minor) { - unsigned maj = 0, min = 0; - int r; - - assert(device); - assert(major); - - r = safe_atou(major, &maj); - if (r < 0) - return r; - if (!maj) - return 0; - - if (minor) { - r = safe_atou(minor, &min); - if (r < 0) - return r; - } - - r = device_add_property_internal(device, "MAJOR", major); - if (r < 0) - return r; - - if (minor) { - r = device_add_property_internal(device, "MINOR", minor); - if (r < 0) - return r; - } - - device->devnum = makedev(maj, min); - - return 0; -} - -static int handle_uevent_line(sd_device *device, const char *key, const char *value, const char **major, const char **minor) { - int r; - - assert(device); - assert(key); - assert(value); - assert(major); - assert(minor); - - if (streq(key, "DEVTYPE")) { - r = device_set_devtype(device, value); - if (r < 0) - return r; - } else if (streq(key, "IFINDEX")) { - r = device_set_ifindex(device, value); - if (r < 0) - return r; - } else if (streq(key, "DEVNAME")) { - r = device_set_devname(device, value); - if (r < 0) - return r; - } else if (streq(key, "DEVMODE")) { - r = device_set_devmode(device, value); - if (r < 0) - return r; - } else if (streq(key, "MAJOR")) - *major = value; - else if (streq(key, "MINOR")) - *minor = value; - else { - r = device_add_property_internal(device, key, value); - if (r < 0) - return r; - } - - return 0; -} - -int device_read_uevent_file(sd_device *device) { - _cleanup_free_ char *uevent = NULL; - const char *syspath, *key, *value, *major = NULL, *minor = NULL; - char *path; - size_t uevent_len; - unsigned i; - int r; - - enum { - PRE_KEY, - KEY, - PRE_VALUE, - VALUE, - INVALID_LINE, - } state = PRE_KEY; - - assert(device); - - if (device->uevent_loaded || device->sealed) - return 0; - - device->uevent_loaded = true; - - r = sd_device_get_syspath(device, &syspath); - if (r < 0) - return r; - - path = strjoina(syspath, "/uevent"); - - r = read_full_file(path, &uevent, &uevent_len); - if (r == -EACCES) - /* empty uevent files may be write-only */ - return 0; - else if (r == -ENOENT) - /* some devices may not have uevent files, see set_syspath() */ - return 0; - else if (r < 0) { - log_debug("sd-device: failed to read uevent file '%s': %s", path, strerror(-r)); - return r; - } - - for (i = 0; i < uevent_len; i++) { - switch (state) { - case PRE_KEY: - if (!strchr(NEWLINE, uevent[i])) { - key = &uevent[i]; - - state = KEY; - } - - break; - case KEY: - if (uevent[i] == '=') { - uevent[i] = '\0'; - - state = PRE_VALUE; - } else if (strchr(NEWLINE, uevent[i])) { - uevent[i] = '\0'; - log_debug("sd-device: ignoring invalid uevent line '%s'", key); - - state = PRE_KEY; - } - - break; - case PRE_VALUE: - value = &uevent[i]; - - state = VALUE; - - break; - case VALUE: - if (strchr(NEWLINE, uevent[i])) { - uevent[i] = '\0'; - - r = handle_uevent_line(device, key, value, &major, &minor); - if (r < 0) - log_debug("sd-device: failed to handle uevent entry '%s=%s': %s", key, value, strerror(-r)); - - state = PRE_KEY; - } - - break; - default: - assert_not_reached("invalid state when parsing uevent file"); - } - } - - if (major) { - r = device_set_devnum(device, major, minor); - if (r < 0) - log_debug("sd-device: could not set 'MAJOR=%s' or 'MINOR=%s' from '%s': %s", major, minor, path, strerror(-r)); - } - - return 0; -} - -_public_ int sd_device_get_ifindex(sd_device *device, int *ifindex) { - int r; - - assert_return(device, -EINVAL); - assert_return(ifindex, -EINVAL); - - r = device_read_uevent_file(device); - if (r < 0) - return r; - - *ifindex = device->ifindex; - - return 0; -} - -_public_ int sd_device_new_from_device_id(sd_device **ret, const char *id) { - int r; - - assert_return(ret, -EINVAL); - assert_return(id, -EINVAL); - - switch (id[0]) { - case 'b': - case 'c': - { - char type; - int maj, min; - - r = sscanf(id, "%c%i:%i", &type, &maj, &min); - if (r != 3) - return -EINVAL; - - return sd_device_new_from_devnum(ret, type, makedev(maj, min)); - } - case 'n': - { - _cleanup_device_unref_ sd_device *device = NULL; - _cleanup_close_ int sk = -1; - struct ifreq ifr = {}; - int ifindex; - - r = safe_atoi(&id[1], &ifr.ifr_ifindex); - if (r < 0) - return r; - else if (ifr.ifr_ifindex <= 0) - return -EINVAL; - - sk = socket(PF_INET, SOCK_DGRAM, 0); - if (sk < 0) - return -errno; - - r = ioctl(sk, SIOCGIFNAME, &ifr); - if (r < 0) - return -errno; - - r = sd_device_new_from_subsystem_sysname(&device, "net", ifr.ifr_name); - if (r < 0) - return r; - - r = sd_device_get_ifindex(device, &ifindex); - if (r < 0) - return r; - - /* this is racey, so we might end up with the wrong device */ - if (ifr.ifr_ifindex != ifindex) - return -ENODEV; - - *ret = device; - device = NULL; - - return 0; - } - case '+': - { - char subsys[PATH_MAX]; - char *sysname; - - (void)strscpy(subsys, sizeof(subsys), id + 1); - sysname = strchr(subsys, ':'); - if (!sysname) - return -EINVAL; - - sysname[0] = '\0'; - sysname ++; - - return sd_device_new_from_subsystem_sysname(ret, subsys, sysname); - } - default: - return -EINVAL; - } -} - -_public_ int sd_device_get_syspath(sd_device *device, const char **ret) { - assert_return(device, -EINVAL); - assert_return(ret, -EINVAL); - - assert(path_startswith(device->syspath, "/sys/")); - - *ret = device->syspath; - - return 0; -} - -static int device_new_from_child(sd_device **ret, sd_device *child) { - _cleanup_free_ char *path = NULL; - const char *subdir, *syspath; - int r; - - assert(ret); - assert(child); - - r = sd_device_get_syspath(child, &syspath); - if (r < 0) - return r; - - path = strdup(syspath); - if (!path) - return -ENOMEM; - subdir = path + strlen("/sys"); - - for (;;) { - char *pos; - - pos = strrchr(subdir, '/'); - if (!pos || pos < subdir + 2) - break; - - *pos = '\0'; - - r = sd_device_new_from_syspath(ret, path); - if (r < 0) - continue; - - return 0; - } - - return -ENODEV; -} - -_public_ int sd_device_get_parent(sd_device *child, sd_device **ret) { - - assert_return(ret, -EINVAL); - assert_return(child, -EINVAL); - - if (!child->parent_set) { - child->parent_set = true; - - (void)device_new_from_child(&child->parent, child); - } - - if (!child->parent) - return -ENOENT; - - *ret = child->parent; - - return 0; -} - -int device_set_subsystem(sd_device *device, const char *_subsystem) { - _cleanup_free_ char *subsystem = NULL; - int r; - - assert(device); - assert(_subsystem); - - subsystem = strdup(_subsystem); - if (!subsystem) - return -ENOMEM; - - r = device_add_property_internal(device, "SUBSYSTEM", subsystem); - if (r < 0) - return r; - - free(device->subsystem); - device->subsystem = subsystem; - subsystem = NULL; - - device->subsystem_set = true; - - return 0; -} - -_public_ int sd_device_get_subsystem(sd_device *device, const char **ret) { - assert_return(ret, -EINVAL); - assert_return(device, -EINVAL); - - if (!device->subsystem_set) { - _cleanup_free_ char *subsystem = NULL; - const char *syspath; - char *path; - int r; - - /* read 'subsystem' link */ - r = sd_device_get_syspath(device, &syspath); - if (r < 0) - return r; - - path = strjoina(syspath, "/subsystem"); - r = readlink_value(path, &subsystem); - if (r >= 0) - r = device_set_subsystem(device, subsystem); - /* use implicit names */ - else if (path_startswith(device->devpath, "/module/")) - r = device_set_subsystem(device, "module"); - else if (strstr(device->devpath, "/drivers/")) - r = device_set_subsystem(device, "drivers"); - else if (path_startswith(device->devpath, "/subsystem/") || - path_startswith(device->devpath, "/class/") || - path_startswith(device->devpath, "/bus/")) - r = device_set_subsystem(device, "subsystem"); - if (r < 0 && r != -ENOENT) - return log_debug_errno(r, "sd-device: could not set subsystem for %s: %m", device->devpath); - - device->subsystem_set = true; - } - - if (!device->subsystem) - return -ENOENT; - - *ret = device->subsystem; - - return 0; -} - -_public_ int sd_device_get_devtype(sd_device *device, const char **devtype) { - int r; - - assert(devtype); - assert(device); - - r = device_read_uevent_file(device); - if (r < 0) - return r; - - *devtype = device->devtype; - - return 0; -} - -_public_ int sd_device_get_parent_with_subsystem_devtype(sd_device *child, const char *subsystem, const char *devtype, sd_device **ret) { - sd_device *parent = NULL; - int r; - - assert_return(child, -EINVAL); - assert_return(subsystem, -EINVAL); - - r = sd_device_get_parent(child, &parent); - while (r >= 0) { - const char *parent_subsystem = NULL; - const char *parent_devtype = NULL; - - (void)sd_device_get_subsystem(parent, &parent_subsystem); - if (streq_ptr(parent_subsystem, subsystem)) { - if (!devtype) - break; - - (void)sd_device_get_devtype(parent, &parent_devtype); - if (streq_ptr(parent_devtype, devtype)) - break; - } - r = sd_device_get_parent(parent, &parent); - } - - if (r < 0) - return r; - - *ret = parent; - - return 0; -} - -_public_ int sd_device_get_devnum(sd_device *device, dev_t *devnum) { - int r; - - assert_return(device, -EINVAL); - assert_return(devnum, -EINVAL); - - r = device_read_uevent_file(device); - if (r < 0) - return r; - - *devnum = device->devnum; - - return 0; -} - -int device_set_driver(sd_device *device, const char *_driver) { - _cleanup_free_ char *driver = NULL; - int r; - - assert(device); - assert(_driver); - - driver = strdup(_driver); - if (!driver) - return -ENOMEM; - - r = device_add_property_internal(device, "DRIVER", driver); - if (r < 0) - return r; - - free(device->driver); - device->driver = driver; - driver = NULL; - - device->driver_set = true; - - return 0; -} - -_public_ int sd_device_get_driver(sd_device *device, const char **ret) { - assert_return(device, -EINVAL); - assert_return(ret, -EINVAL); - - if (!device->driver_set) { - _cleanup_free_ char *driver = NULL; - const char *syspath; - char *path; - int r; - - r = sd_device_get_syspath(device, &syspath); - if (r < 0) - return r; - - path = strjoina(syspath, "/driver"); - r = readlink_value(path, &driver); - if (r >= 0) { - r = device_set_driver(device, driver); - if (r < 0) - return log_debug_errno(r, "sd-device: could not set driver for %s: %m", device->devpath); - } else if (r == -ENOENT) - device->driver_set = true; - else - return log_debug_errno(r, "sd-device: could not set driver for %s: %m", device->devpath); - } - - if (!device->driver) - return -ENOENT; - - *ret = device->driver; - - return 0; -} - -_public_ int sd_device_get_devpath(sd_device *device, const char **devpath) { - assert_return(device, -EINVAL); - assert_return(devpath, -EINVAL); - - assert(device->devpath); - assert(device->devpath[0] == '/'); - - *devpath = device->devpath; - - return 0; -} - -_public_ int sd_device_get_devname(sd_device *device, const char **devname) { - int r; - - assert_return(device, -EINVAL); - assert_return(devname, -EINVAL); - - r = device_read_uevent_file(device); - if (r < 0) - return r; - - if (!device->devname) - return -ENOENT; - - assert(path_startswith(device->devname, "/dev/")); - - *devname = device->devname; - - return 0; -} - -static int device_set_sysname(sd_device *device) { - _cleanup_free_ char *sysname = NULL; - const char *sysnum = NULL; - const char *pos; - size_t len = 0; - - pos = strrchr(device->devpath, '/'); - if (!pos) - return -EINVAL; - pos ++; - - /* devpath is not a root directory */ - if (*pos == '\0' || pos <= device->devpath) - return -EINVAL; - - sysname = strdup(pos); - if (!sysname) - return -ENOMEM; - - /* some devices have '!' in their name, change that to '/' */ - while (sysname[len] != '\0') { - if (sysname[len] == '!') - sysname[len] = '/'; - - len ++; - } - - /* trailing number */ - while (len > 0 && isdigit(sysname[--len])) - sysnum = &sysname[len]; - - if (len == 0) - sysnum = NULL; - - free(device->sysname); - device->sysname = sysname; - sysname = NULL; - - device->sysnum = sysnum; - - device->sysname_set = true; - - return 0; -} - -_public_ int sd_device_get_sysname(sd_device *device, const char **ret) { - int r; - - assert_return(device, -EINVAL); - assert_return(ret, -EINVAL); - - if (!device->sysname_set) { - r = device_set_sysname(device); - if (r < 0) - return r; - } - - assert_return(device->sysname, -ENOENT); - - *ret = device->sysname; - - return 0; -} - -_public_ int sd_device_get_sysnum(sd_device *device, const char **ret) { - int r; - - assert_return(device, -EINVAL); - assert_return(ret, -EINVAL); - - if (!device->sysname_set) { - r = device_set_sysname(device); - if (r < 0) - return r; - } - - *ret = device->sysnum; - - return 0; -} - -static bool is_valid_tag(const char *tag) { - assert(tag); - - return !strchr(tag, ':') && !strchr(tag, ' '); -} - -int device_add_tag(sd_device *device, const char *tag) { - int r; - - assert(device); - assert(tag); - - if (!is_valid_tag(tag)) - return -EINVAL; - - r = set_ensure_allocated(&device->tags, &string_hash_ops); - if (r < 0) - return r; - - r = set_put_strdup(device->tags, tag); - if (r < 0) - return r; - - device->tags_generation ++; - device->property_tags_outdated = true; - - return 0; -} - -int device_add_devlink(sd_device *device, const char *devlink) { - int r; - - assert(device); - assert(devlink); - - r = set_ensure_allocated(&device->devlinks, &string_hash_ops); - if (r < 0) - return r; - - r = set_put_strdup(device->devlinks, devlink); - if (r < 0) - return r; - - device->devlinks_generation ++; - device->property_devlinks_outdated = true; - - return 0; -} - -static int device_add_property_internal_from_string(sd_device *device, const char *str) { - _cleanup_free_ char *key = NULL; - char *value; - - assert(device); - assert(str); - - key = strdup(str); - if (!key) - return -ENOMEM; - - value = strchr(key, '='); - if (!value) - return -EINVAL; - - *value = '\0'; - - if (isempty(++value)) - value = NULL; - - return device_add_property_internal(device, key, value); -} - -int device_set_usec_initialized(sd_device *device, const char *initialized) { - uint64_t usec_initialized; - int r; - - assert(device); - assert(initialized); - - r = safe_atou64(initialized, &usec_initialized); - if (r < 0) - return r; - - r = device_add_property_internal(device, "USEC_INITIALIZED", initialized); - if (r < 0) - return r; - - device->usec_initialized = usec_initialized; - - return 0; -} - -static int handle_db_line(sd_device *device, char key, const char *value) { - char *path; - int r; - - assert(device); - assert(value); - - switch (key) { - case 'G': - r = device_add_tag(device, value); - if (r < 0) - return r; - - break; - case 'S': - path = strjoina("/dev/", value); - r = device_add_devlink(device, path); - if (r < 0) - return r; - - break; - case 'E': - r = device_add_property_internal_from_string(device, value); - if (r < 0) - return r; - - break; - case 'I': - r = device_set_usec_initialized(device, value); - if (r < 0) - return r; - - break; - case 'L': - r = safe_atoi(value, &device->devlink_priority); - if (r < 0) - return r; - - break; - case 'W': - r = safe_atoi(value, &device->watch_handle); - if (r < 0) - return r; - - break; - default: - log_debug("device db: unknown key '%c'", key); - } - - return 0; -} - -int device_get_id_filename(sd_device *device, const char **ret) { - assert(device); - assert(ret); - - if (!device->id_filename) { - _cleanup_free_ char *id = NULL; - const char *subsystem; - dev_t devnum; - int ifindex, r; - - r = sd_device_get_subsystem(device, &subsystem); - if (r < 0) - return r; - - r = sd_device_get_devnum(device, &devnum); - if (r < 0) - return r; - - r = sd_device_get_ifindex(device, &ifindex); - if (r < 0) - return r; - - if (major(devnum) > 0) { - assert(subsystem); - - /* use dev_t -- b259:131072, c254:0 */ - r = asprintf(&id, "%c%u:%u", - streq(subsystem, "block") ? 'b' : 'c', - major(devnum), minor(devnum)); - if (r < 0) - return -ENOMEM; - } else if (ifindex > 0) { - /* use netdev ifindex -- n3 */ - r = asprintf(&id, "n%u", ifindex); - if (r < 0) - return -ENOMEM; - } else { - /* use $subsys:$sysname -- pci:0000:00:1f.2 - * sysname() has '!' translated, get it from devpath - */ - const char *sysname; - - sysname = basename(device->devpath); - if (!sysname) - return -EINVAL; - - if (!subsystem) - return -EINVAL; - - r = asprintf(&id, "+%s:%s", subsystem, sysname); - if (r < 0) - return -ENOMEM; - } - - device->id_filename = id; - id = NULL; - } - - *ret = device->id_filename; - - return 0; -} - -int device_read_db_aux(sd_device *device, bool force) { - _cleanup_free_ char *db = NULL; - char *path; - const char *id, *value; - char key; - size_t db_len; - unsigned i; - int r; - - enum { - PRE_KEY, - KEY, - PRE_VALUE, - VALUE, - INVALID_LINE, - } state = PRE_KEY; - - if (device->db_loaded || (!force && device->sealed)) - return 0; - - device->db_loaded = true; - - r = device_get_id_filename(device, &id); - if (r < 0) - return r; - - path = strjoina("/run/udev/data/", id); - - r = read_full_file(path, &db, &db_len); - if (r < 0) { - if (r == -ENOENT) - return 0; - else { - log_debug("sd-device: failed to read db '%s': %s", path, strerror(-r)); - return r; - } - } - - /* devices with a database entry are initialized */ - device->is_initialized = true; - - for (i = 0; i < db_len; i++) { - switch (state) { - case PRE_KEY: - if (!strchr(NEWLINE, db[i])) { - key = db[i]; - - state = KEY; - } - - break; - case KEY: - if (db[i] != ':') { - log_debug("sd-device: ignoring invalid db entry with key '%c'", key); - - state = INVALID_LINE; - } else { - db[i] = '\0'; - - state = PRE_VALUE; - } - - break; - case PRE_VALUE: - value = &db[i]; - - state = VALUE; - - break; - case INVALID_LINE: - if (strchr(NEWLINE, db[i])) - state = PRE_KEY; - - break; - case VALUE: - if (strchr(NEWLINE, db[i])) { - db[i] = '\0'; - r = handle_db_line(device, key, value); - if (r < 0) - log_debug("sd-device: failed to handle db entry '%c:%s': %s", key, value, strerror(-r)); - - state = PRE_KEY; - } - - break; - default: - assert_not_reached("invalid state when parsing db"); - } - } - - return 0; -} - -static int device_read_db(sd_device *device) { - return device_read_db_aux(device, false); -} - -_public_ int sd_device_get_is_initialized(sd_device *device, int *initialized) { - int r; - - assert_return(device, -EINVAL); - assert_return(initialized, -EINVAL); - - r = device_read_db(device); - if (r < 0) - return r; - - *initialized = device->is_initialized; - - return 0; -} - -_public_ int sd_device_get_usec_since_initialized(sd_device *device, uint64_t *usec) { - usec_t now_ts; - int r; - - assert_return(device, -EINVAL); - assert_return(usec, -EINVAL); - - r = device_read_db(device); - if (r < 0) - return r; - - if (!device->is_initialized) - return -EBUSY; - - if (!device->usec_initialized) - return -ENODATA; - - now_ts = now(clock_boottime_or_monotonic()); - - if (now_ts < device->usec_initialized) - return -EIO; - - *usec = now_ts - device->usec_initialized; - - return 0; -} - -_public_ const char *sd_device_get_tag_first(sd_device *device) { - void *v; - - assert_return(device, NULL); - - (void) device_read_db(device); - - device->tags_iterator_generation = device->tags_generation; - device->tags_iterator = ITERATOR_FIRST; - - set_iterate(device->tags, &device->tags_iterator, &v); - return v; -} - -_public_ const char *sd_device_get_tag_next(sd_device *device) { - void *v; - - assert_return(device, NULL); - - (void) device_read_db(device); - - if (device->tags_iterator_generation != device->tags_generation) - return NULL; - - set_iterate(device->tags, &device->tags_iterator, &v); - return v; -} - -_public_ const char *sd_device_get_devlink_first(sd_device *device) { - void *v; - - assert_return(device, NULL); - - (void) device_read_db(device); - - device->devlinks_iterator_generation = device->devlinks_generation; - device->devlinks_iterator = ITERATOR_FIRST; - - set_iterate(device->devlinks, &device->devlinks_iterator, &v); - return v; -} - -_public_ const char *sd_device_get_devlink_next(sd_device *device) { - void *v; - - assert_return(device, NULL); - - (void) device_read_db(device); - - if (device->devlinks_iterator_generation != device->devlinks_generation) - return NULL; - - set_iterate(device->devlinks, &device->devlinks_iterator, &v); - return v; -} - -static int device_properties_prepare(sd_device *device) { - int r; - - assert(device); - - r = device_read_uevent_file(device); - if (r < 0) - return r; - - r = device_read_db(device); - if (r < 0) - return r; - - if (device->property_devlinks_outdated) { - char *devlinks = NULL; - const char *devlink; - - devlink = sd_device_get_devlink_first(device); - if (devlink) - devlinks = strdupa(devlink); - - while ((devlink = sd_device_get_devlink_next(device))) - devlinks = strjoina(devlinks, " ", devlink); - - r = device_add_property_internal(device, "DEVLINKS", devlinks); - if (r < 0) - return r; - - device->property_devlinks_outdated = false; - } - - if (device->property_tags_outdated) { - char *tags = NULL; - const char *tag; - - tag = sd_device_get_tag_first(device); - if (tag) - tags = strjoina(":", tag); - - while ((tag = sd_device_get_tag_next(device))) - tags = strjoina(tags, ":", tag); - - tags = strjoina(tags, ":"); - - r = device_add_property_internal(device, "TAGS", tags); - if (r < 0) - return r; - - device->property_tags_outdated = false; - } - - return 0; -} - -_public_ const char *sd_device_get_property_first(sd_device *device, const char **_value) { - const char *key; - const char *value; - int r; - - assert_return(device, NULL); - - r = device_properties_prepare(device); - if (r < 0) - return NULL; - - device->properties_iterator_generation = device->properties_generation; - device->properties_iterator = ITERATOR_FIRST; - - ordered_hashmap_iterate(device->properties, &device->properties_iterator, (void**)&value, (const void**)&key); - - if (_value) - *_value = value; - - return key; -} - -_public_ const char *sd_device_get_property_next(sd_device *device, const char **_value) { - const char *key; - const char *value; - int r; - - assert_return(device, NULL); - - r = device_properties_prepare(device); - if (r < 0) - return NULL; - - if (device->properties_iterator_generation != device->properties_generation) - return NULL; - - ordered_hashmap_iterate(device->properties, &device->properties_iterator, (void**)&value, (const void**)&key); - - if (_value) - *_value = value; - - return key; -} - -static int device_sysattrs_read_all(sd_device *device) { - _cleanup_closedir_ DIR *dir = NULL; - const char *syspath; - struct dirent *dent; - int r; - - assert(device); - - if (device->sysattrs_read) - return 0; - - r = sd_device_get_syspath(device, &syspath); - if (r < 0) - return r; - - dir = opendir(syspath); - if (!dir) - return -errno; - - r = set_ensure_allocated(&device->sysattrs, &string_hash_ops); - if (r < 0) - return r; - - for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { - char *path; - struct stat statbuf; - - /* only handle symlinks and regular files */ - if (dent->d_type != DT_LNK && dent->d_type != DT_REG) - continue; - - path = strjoina(syspath, "/", dent->d_name); - - if (lstat(path, &statbuf) != 0) - continue; - - if (!(statbuf.st_mode & S_IRUSR)) - continue; - - r = set_put_strdup(device->sysattrs, dent->d_name); - if (r < 0) - return r; - } - - device->sysattrs_read = true; - - return 0; -} - -_public_ const char *sd_device_get_sysattr_first(sd_device *device) { - void *v; - int r; - - assert_return(device, NULL); - - if (!device->sysattrs_read) { - r = device_sysattrs_read_all(device); - if (r < 0) { - errno = -r; - return NULL; - } - } - - device->sysattrs_iterator = ITERATOR_FIRST; - - set_iterate(device->sysattrs, &device->sysattrs_iterator, &v); - return v; -} - -_public_ const char *sd_device_get_sysattr_next(sd_device *device) { - void *v; - - assert_return(device, NULL); - - if (!device->sysattrs_read) - return NULL; - - set_iterate(device->sysattrs, &device->sysattrs_iterator, &v); - return v; -} - -_public_ int sd_device_has_tag(sd_device *device, const char *tag) { - assert_return(device, -EINVAL); - assert_return(tag, -EINVAL); - - (void) device_read_db(device); - - return !!set_contains(device->tags, tag); -} - -_public_ int sd_device_get_property_value(sd_device *device, const char *key, const char **_value) { - char *value; - int r; - - assert_return(device, -EINVAL); - assert_return(key, -EINVAL); - assert_return(_value, -EINVAL); - - r = device_properties_prepare(device); - if (r < 0) - return r; - - value = ordered_hashmap_get(device->properties, key); - if (!value) - return -ENOENT; - - *_value = value; - - return 0; -} - -/* replaces the value if it already exists */ -static int device_add_sysattr_value(sd_device *device, const char *_key, char *value) { - _cleanup_free_ char *key = NULL; - _cleanup_free_ char *value_old = NULL; - int r; - - assert(device); - assert(_key); - - r = hashmap_ensure_allocated(&device->sysattr_values, &string_hash_ops); - if (r < 0) - return r; - - value_old = hashmap_remove2(device->sysattr_values, _key, (void **)&key); - if (!key) { - key = strdup(_key); - if (!key) - return -ENOMEM; - } - - r = hashmap_put(device->sysattr_values, key, value); - if (r < 0) - return r; - - key = NULL; - - return 0; -} - -static int device_get_sysattr_value(sd_device *device, const char *_key, const char **_value) { - const char *key = NULL, *value; - - assert(device); - assert(_key); - - value = hashmap_get2(device->sysattr_values, _key, (void **) &key); - if (!key) - return -ENOENT; - - if (_value) - *_value = value; - - return 0; -} - -/* We cache all sysattr lookups. If an attribute does not exist, it is stored - * with a NULL value in the cache, otherwise the returned string is stored */ -_public_ int sd_device_get_sysattr_value(sd_device *device, const char *sysattr, const char **_value) { - _cleanup_free_ char *value = NULL; - const char *syspath, *cached_value = NULL; - char *path; - struct stat statbuf; - int r; - - assert_return(device, -EINVAL); - assert_return(sysattr, -EINVAL); - - /* look for possibly already cached result */ - r = device_get_sysattr_value(device, sysattr, &cached_value); - if (r != -ENOENT) { - if (r < 0) - return r; - - if (!cached_value) - /* we looked up the sysattr before and it did not exist */ - return -ENOENT; - - if (_value) - *_value = cached_value; - - return 0; - } - - r = sd_device_get_syspath(device, &syspath); - if (r < 0) - return r; - - path = strjoina(syspath, "/", sysattr); - r = lstat(path, &statbuf); - if (r < 0) { - /* remember that we could not access the sysattr */ - r = device_add_sysattr_value(device, sysattr, NULL); - if (r < 0) - return r; - - return -ENOENT; - } else if (S_ISLNK(statbuf.st_mode)) { - /* Some core links return only the last element of the target path, - * these are just values, the paths should not be exposed. */ - if (STR_IN_SET(sysattr, "driver", "subsystem", "module")) { - r = readlink_value(path, &value); - if (r < 0) - return r; - } else - return -EINVAL; - } else if (S_ISDIR(statbuf.st_mode)) { - /* skip directories */ - return -EINVAL; - } else if (!(statbuf.st_mode & S_IRUSR)) { - /* skip non-readable files */ - return -EPERM; - } else { - size_t size; - - /* read attribute value */ - r = read_full_file(path, &value, &size); - if (r < 0) - return r; - - /* drop trailing newlines */ - while (size > 0 && value[--size] == '\n') - value[size] = '\0'; - } - - r = device_add_sysattr_value(device, sysattr, value); - if (r < 0) - return r; - - *_value = value; - value = NULL; - - return 0; -} - -static void device_remove_sysattr_value(sd_device *device, const char *_key) { - _cleanup_free_ char *key = NULL; - _cleanup_free_ char *value = NULL; - - assert(device); - assert(_key); - - value = hashmap_remove2(device->sysattr_values, _key, (void **) &key); - - return; -} - -/* set the attribute and save it in the cache. If a NULL value is passed the - * attribute is cleared from the cache */ -_public_ int sd_device_set_sysattr_value(sd_device *device, const char *sysattr, char *_value) { - _cleanup_close_ int fd = -1; - _cleanup_free_ char *value = NULL; - const char *syspath; - char *path; - struct stat statbuf; - size_t value_len = 0; - ssize_t size; - int r; - - assert_return(device, -EINVAL); - assert_return(sysattr, -EINVAL); - - if (!_value) { - device_remove_sysattr_value(device, sysattr); - - return 0; - } - - r = sd_device_get_syspath(device, &syspath); - if (r < 0) - return r; - - path = strjoina(syspath, "/", sysattr); - r = lstat(path, &statbuf); - if (r < 0) { - value = strdup(""); - if (!value) - return -ENOMEM; - - r = device_add_sysattr_value(device, sysattr, value); - if (r < 0) - return r; - - return -ENXIO; - } - - if (S_ISLNK(statbuf.st_mode)) - return -EINVAL; - - /* skip directories */ - if (S_ISDIR(statbuf.st_mode)) - return -EISDIR; - - /* skip non-readable files */ - if ((statbuf.st_mode & S_IRUSR) == 0) - return -EACCES; - - value_len = strlen(_value); - - /* drop trailing newlines */ - while (value_len > 0 && _value[value_len - 1] == '\n') - _value[--value_len] = '\0'; - - /* value length is limited to 4k */ - if (value_len > 4096) - return -EINVAL; - - fd = open(path, O_WRONLY | O_CLOEXEC); - if (fd < 0) - return -errno; - - value = strdup(_value); - if (!value) - return -ENOMEM; - - size = write(fd, value, value_len); - if (size < 0) - return -errno; - - if ((size_t)size != value_len) - return -EIO; - - r = device_add_sysattr_value(device, sysattr, value); - if (r < 0) - return r; - - value = NULL; - - return 0; -} diff --git a/src/libelogind/sd-event/Makefile b/src/libelogind/sd-event/Makefile deleted file mode 120000 index 94aaae2c4..000000000 --- a/src/libelogind/sd-event/Makefile +++ /dev/null @@ -1 +0,0 @@ -../../Makefile \ No newline at end of file diff --git a/src/libelogind/sd-event/test-event.c b/src/libelogind/sd-event/test-event.c deleted file mode 100644 index 408e1679a..000000000 --- a/src/libelogind/sd-event/test-event.c +++ /dev/null @@ -1,249 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2013 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 . -***/ - -#include "sd-event.h" -#include "log.h" -#include "util.h" -#include "macro.h" -#include "signal-util.h" - -static int prepare_handler(sd_event_source *s, void *userdata) { - log_info("preparing %c", PTR_TO_INT(userdata)); - return 1; -} - -static bool got_a, got_b, got_c, got_unref; -static unsigned got_d; - -static int unref_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) { - sd_event_source_unref(s); - got_unref = true; - return 0; -} - -static int io_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) { - - log_info("got IO on %c", PTR_TO_INT(userdata)); - - if (userdata == INT_TO_PTR('a')) { - assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0); - assert_se(!got_a); - got_a = true; - } else if (userdata == INT_TO_PTR('b')) { - assert_se(!got_b); - got_b = true; - } else if (userdata == INT_TO_PTR('d')) { - got_d++; - if (got_d < 2) - assert_se(sd_event_source_set_enabled(s, SD_EVENT_ONESHOT) >= 0); - else - assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0); - } else - assert_not_reached("Yuck!"); - - return 1; -} - -static int child_handler(sd_event_source *s, const siginfo_t *si, void *userdata) { - - assert_se(s); - assert_se(si); - - log_info("got child on %c", PTR_TO_INT(userdata)); - - assert_se(userdata == INT_TO_PTR('f')); - - assert_se(sd_event_exit(sd_event_source_get_event(s), 0) >= 0); - sd_event_source_unref(s); - - return 1; -} - -static int signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { - sd_event_source *p = NULL; - pid_t pid; - - assert_se(s); - assert_se(si); - - log_info("got signal on %c", PTR_TO_INT(userdata)); - - assert_se(userdata == INT_TO_PTR('e')); - - assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0); - - pid = fork(); - assert_se(pid >= 0); - - if (pid == 0) - _exit(0); - - assert_se(sd_event_add_child(sd_event_source_get_event(s), &p, pid, WEXITED, child_handler, INT_TO_PTR('f')) >= 0); - assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0); - - sd_event_source_unref(s); - - return 1; -} - -static int defer_handler(sd_event_source *s, void *userdata) { - sd_event_source *p = NULL; - - assert_se(s); - - log_info("got defer on %c", PTR_TO_INT(userdata)); - - assert_se(userdata == INT_TO_PTR('d')); - - assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGUSR1, -1) >= 0); - - assert_se(sd_event_add_signal(sd_event_source_get_event(s), &p, SIGUSR1, signal_handler, INT_TO_PTR('e')) >= 0); - assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0); - raise(SIGUSR1); - - sd_event_source_unref(s); - - return 1; -} - -static bool do_quit = false; - -static int time_handler(sd_event_source *s, uint64_t usec, void *userdata) { - log_info("got timer on %c", PTR_TO_INT(userdata)); - - if (userdata == INT_TO_PTR('c')) { - - if (do_quit) { - sd_event_source *p; - - assert_se(sd_event_add_defer(sd_event_source_get_event(s), &p, defer_handler, INT_TO_PTR('d')) >= 0); - assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0); - } else { - assert_se(!got_c); - got_c = true; - } - } else - assert_not_reached("Huh?"); - - return 2; -} - -static bool got_exit = false; - -static int exit_handler(sd_event_source *s, void *userdata) { - log_info("got quit handler on %c", PTR_TO_INT(userdata)); - - got_exit = true; - - return 3; -} - -int main(int argc, char *argv[]) { - sd_event *e = NULL; - sd_event_source *w = NULL, *x = NULL, *y = NULL, *z = NULL, *q = NULL, *t = NULL; - static const char ch = 'x'; - int a[2] = { -1, -1 }, b[2] = { -1, -1}, d[2] = { -1, -1}, k[2] = { -1, -1 }; - - assert_se(pipe(a) >= 0); - assert_se(pipe(b) >= 0); - assert_se(pipe(d) >= 0); - assert_se(pipe(k) >= 0); - - assert_se(sd_event_default(&e) >= 0); - - assert_se(sd_event_set_watchdog(e, true) >= 0); - - /* Test whether we cleanly can destroy an io event source from its own handler */ - got_unref = false; - assert_se(sd_event_add_io(e, &t, k[0], EPOLLIN, unref_handler, NULL) >= 0); - assert_se(write(k[1], &ch, 1) == 1); - assert_se(sd_event_run(e, (uint64_t) -1) >= 1); - assert_se(got_unref); - - got_a = false, got_b = false, got_c = false, got_d = 0; - - /* Add a oneshot handler, trigger it, re-enable it, and trigger - * it again. */ - assert_se(sd_event_add_io(e, &w, d[0], EPOLLIN, io_handler, INT_TO_PTR('d')) >= 0); - assert_se(sd_event_source_set_enabled(w, SD_EVENT_ONESHOT) >= 0); - assert_se(write(d[1], &ch, 1) >= 0); - assert_se(sd_event_run(e, (uint64_t) -1) >= 1); - assert_se(got_d == 1); - assert_se(write(d[1], &ch, 1) >= 0); - assert_se(sd_event_run(e, (uint64_t) -1) >= 1); - assert_se(got_d == 2); - - assert_se(sd_event_add_io(e, &x, a[0], EPOLLIN, io_handler, INT_TO_PTR('a')) >= 0); - assert_se(sd_event_add_io(e, &y, b[0], EPOLLIN, io_handler, INT_TO_PTR('b')) >= 0); - assert_se(sd_event_add_time(e, &z, CLOCK_MONOTONIC, 0, 0, time_handler, INT_TO_PTR('c')) >= 0); - assert_se(sd_event_add_exit(e, &q, exit_handler, INT_TO_PTR('g')) >= 0); - - assert_se(sd_event_source_set_priority(x, 99) >= 0); - assert_se(sd_event_source_set_enabled(y, SD_EVENT_ONESHOT) >= 0); - assert_se(sd_event_source_set_prepare(x, prepare_handler) >= 0); - assert_se(sd_event_source_set_priority(z, 50) >= 0); - assert_se(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT) >= 0); - assert_se(sd_event_source_set_prepare(z, prepare_handler) >= 0); - - /* Test for floating event sources */ - assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+1, -1) >= 0); - assert_se(sd_event_add_signal(e, NULL, SIGRTMIN+1, NULL, NULL) >= 0); - - assert_se(write(a[1], &ch, 1) >= 0); - assert_se(write(b[1], &ch, 1) >= 0); - - assert_se(!got_a && !got_b && !got_c); - - assert_se(sd_event_run(e, (uint64_t) -1) >= 1); - - assert_se(!got_a && got_b && !got_c); - - assert_se(sd_event_run(e, (uint64_t) -1) >= 1); - - assert_se(!got_a && got_b && got_c); - - assert_se(sd_event_run(e, (uint64_t) -1) >= 1); - - assert_se(got_a && got_b && got_c); - - sd_event_source_unref(x); - sd_event_source_unref(y); - - do_quit = true; - assert_se(sd_event_source_set_time(z, now(CLOCK_MONOTONIC) + 200 * USEC_PER_MSEC) >= 0); - assert_se(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT) >= 0); - - assert_se(sd_event_loop(e) >= 0); - - sd_event_source_unref(z); - sd_event_source_unref(q); - - sd_event_source_unref(w); - - sd_event_unref(e); - - safe_close_pair(a); - safe_close_pair(b); - safe_close_pair(d); - safe_close_pair(k); - - return 0; -} diff --git a/src/libelogind/sd-hwdb/hwdb-util.h b/src/libelogind/sd-hwdb/hwdb-util.h deleted file mode 100644 index 627c46be1..000000000 --- a/src/libelogind/sd-hwdb/hwdb-util.h +++ /dev/null @@ -1,56 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2014 Tom Gundersen - - 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 . -***/ - -#pragma once - -#include "sd-event.h" -#include "sd-netlink.h" -#include "sd-network.h" - -#include "hashmap.h" - -typedef struct Manager Manager; - -#include "networkd-wait-online-link.h" - -struct Manager { - Hashmap *links; - Hashmap *links_by_name; - - char **interfaces; - char **ignore; - - sd_netlink *rtnl; - sd_event_source *rtnl_event_source; - - sd_network_monitor *network_monitor; - sd_event_source *network_monitor_event_source; - - sd_event *event; -}; - -void manager_free(Manager *m); -int manager_new(Manager **ret, char **interfaces, char **ignore, usec_t timeout); - -DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free); - -bool manager_all_configured(Manager *m); -bool manager_ignore_link(Manager *m, Link *link); diff --git a/src/libelogind/sd-id128/libelogind-id128.pc.in b/src/libelogind/sd-id128/libelogind-id128.pc.in deleted file mode 100644 index f7922b8b8..000000000 --- a/src/libelogind/sd-id128/libelogind-id128.pc.in +++ /dev/null @@ -1,18 +0,0 @@ -# This file is part of systemd. -# -# 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. - -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: elogind -Description: elogind 128 Bit ID Utility Library -URL: @PACKAGE_URL@ -Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lelogind-id128 -Cflags: -I${includedir} diff --git a/src/libelogind/sd-login/Makefile b/src/libelogind/sd-login/Makefile index d0b0e8e00..94aaae2c4 120000 --- a/src/libelogind/sd-login/Makefile +++ b/src/libelogind/sd-login/Makefile @@ -1 +1 @@ -../Makefile \ No newline at end of file +../../Makefile \ No newline at end of file diff --git a/src/libelogind/sd-netlink/netlink-types.h b/src/libelogind/sd-netlink/netlink-types.h deleted file mode 100644 index bf7c64154..000000000 --- a/src/libelogind/sd-netlink/netlink-types.h +++ /dev/null @@ -1,94 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -#pragma once - -/*** - This file is part of systemd. - - Copyright 2014 Tom Gundersen - - 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 . -***/ - -enum { - NETLINK_TYPE_UNSPEC, - NETLINK_TYPE_U8, /* NLA_U8 */ - NETLINK_TYPE_U16, /* NLA_U16 */ - NETLINK_TYPE_U32, /* NLA_U32 */ - NETLINK_TYPE_U64, /* NLA_U64 */ - NETLINK_TYPE_STRING, /* NLA_STRING */ - NETLINK_TYPE_FLAG, /* NLA_FLAG */ - NETLINK_TYPE_IN_ADDR, - NETLINK_TYPE_ETHER_ADDR, - NETLINK_TYPE_CACHE_INFO, - NETLINK_TYPE_NESTED, /* NLA_NESTED */ - NETLINK_TYPE_UNION, -}; - -typedef enum NLMatchType { - NL_MATCH_SIBLING, - NL_MATCH_PROTOCOL, -} NLMatchType; - -typedef struct NLTypeSystemUnion NLTypeSystemUnion; -typedef struct NLTypeSystem NLTypeSystem; -typedef struct NLType NLType; - -struct NLTypeSystemUnion { - int num; - NLMatchType match_type; - uint16_t match; - int (*lookup)(const char *); - const NLTypeSystem *type_systems; -}; - -extern const NLTypeSystem type_system_root; - -uint16_t type_get_type(const NLType *type); -size_t type_get_size(const NLType *type); -void type_get_type_system(const NLType *type, const NLTypeSystem **ret); -void type_get_type_system_union(const NLType *type, const NLTypeSystemUnion **ret); - -uint16_t type_system_get_count(const NLTypeSystem *type_system); -int type_system_get_type(const NLTypeSystem *type_system, const NLType **ret, uint16_t type); -int type_system_get_type_system(const NLTypeSystem *type_system, const NLTypeSystem **ret, uint16_t type); -int type_system_get_type_system_union(const NLTypeSystem *type_system, const NLTypeSystemUnion **ret, uint16_t type); -int type_system_union_get_type_system(const NLTypeSystemUnion *type_system_union, const NLTypeSystem **ret, const char *key); -int type_system_union_protocol_get_type_system(const NLTypeSystemUnion *type_system_union, const NLTypeSystem **ret, uint16_t protocol); - -typedef enum NLUnionLinkInfoData { - NL_UNION_LINK_INFO_DATA_BOND, - NL_UNION_LINK_INFO_DATA_BRIDGE, - NL_UNION_LINK_INFO_DATA_VLAN, - NL_UNION_LINK_INFO_DATA_VETH, - NL_UNION_LINK_INFO_DATA_DUMMY, - NL_UNION_LINK_INFO_DATA_MACVLAN, - NL_UNION_LINK_INFO_DATA_MACVTAP, - NL_UNION_LINK_INFO_DATA_IPVLAN, - NL_UNION_LINK_INFO_DATA_VXLAN, - NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL, - NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL, - NL_UNION_LINK_INFO_DATA_IPGRETAP_TUNNEL, - NL_UNION_LINK_INFO_DATA_IP6GRE_TUNNEL, - NL_UNION_LINK_INFO_DATA_IP6GRETAP_TUNNEL, - NL_UNION_LINK_INFO_DATA_SIT_TUNNEL, - NL_UNION_LINK_INFO_DATA_VTI_TUNNEL, - NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL, - NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL, - _NL_UNION_LINK_INFO_DATA_MAX, - _NL_UNION_LINK_INFO_DATA_INVALID = -1 -} NLUnionLinkInfoData; - -const char *nl_union_link_info_data_to_string(NLUnionLinkInfoData p) _const_; -NLUnionLinkInfoData nl_union_link_info_data_from_string(const char *p) _pure_; diff --git a/src/libelogind/sd-network/Makefile b/src/libelogind/sd-network/Makefile deleted file mode 120000 index d0b0e8e00..000000000 --- a/src/libelogind/sd-network/Makefile +++ /dev/null @@ -1 +0,0 @@ -../Makefile \ No newline at end of file diff --git a/src/libelogind/sd-path/Makefile b/src/libelogind/sd-path/Makefile deleted file mode 120000 index d0b0e8e00..000000000 --- a/src/libelogind/sd-path/Makefile +++ /dev/null @@ -1 +0,0 @@ -../Makefile \ No newline at end of file diff --git a/src/libelogind/sd-rtnl/local-addresses.c b/src/libelogind/sd-rtnl/local-addresses.c deleted file mode 100644 index f05cbf1f4..000000000 --- a/src/libelogind/sd-rtnl/local-addresses.c +++ /dev/null @@ -1,276 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2008-2011 Lennart Poettering - Copyright 2014 Tom Gundersen - - 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 . -***/ - -#include "sd-rtnl.h" -#include "rtnl-util.h" -#include "macro.h" -#include "local-addresses.h" - -static int address_compare(const void *_a, const void *_b) { - const struct local_address *a = _a, *b = _b; - - /* Order lowest scope first, IPv4 before IPv6, lowest interface index first */ - - if (a->family == AF_INET && b->family == AF_INET6) - return -1; - if (a->family == AF_INET6 && b->family == AF_INET) - return 1; - - if (a->scope < b->scope) - return -1; - if (a->scope > b->scope) - return 1; - - if (a->metric < b->metric) - return -1; - if (a->metric > b->metric) - return 1; - - if (a->ifindex < b->ifindex) - return -1; - if (a->ifindex > b->ifindex) - return 1; - - return memcmp(&a->address, &b->address, FAMILY_ADDRESS_SIZE(a->family)); -} - -int local_addresses(sd_rtnl *context, int ifindex, int af, struct local_address **ret) { - _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL; - _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL; - _cleanup_free_ struct local_address *list = NULL; - size_t n_list = 0, n_allocated = 0; - sd_rtnl_message *m; - int r; - - assert(ret); - - if (context) - rtnl = sd_rtnl_ref(context); - else { - r = sd_rtnl_open(&rtnl); - if (r < 0) - return r; - } - - r = sd_rtnl_message_new_addr(rtnl, &req, RTM_GETADDR, 0, af); - if (r < 0) - return r; - - r = sd_rtnl_call(rtnl, req, 0, &reply); - if (r < 0) - return r; - - for (m = reply; m; m = sd_rtnl_message_next(m)) { - struct local_address *a; - unsigned char flags; - uint16_t type; - int ifi, family; - - r = sd_rtnl_message_get_errno(m); - if (r < 0) - return r; - - r = sd_rtnl_message_get_type(m, &type); - if (r < 0) - return r; - if (type != RTM_NEWADDR) - continue; - - r = sd_rtnl_message_addr_get_ifindex(m, &ifi); - if (r < 0) - return r; - if (ifindex > 0 && ifi != ifindex) - continue; - - r = sd_rtnl_message_addr_get_family(m, &family); - if (r < 0) - return r; - if (af != AF_UNSPEC && af != family) - continue; - - r = sd_rtnl_message_addr_get_flags(m, &flags); - if (r < 0) - return r; - if (flags & IFA_F_DEPRECATED) - continue; - - if (!GREEDY_REALLOC0(list, n_allocated, n_list+1)) - return -ENOMEM; - - a = list + n_list; - - r = sd_rtnl_message_addr_get_scope(m, &a->scope); - if (r < 0) - return r; - - if (ifindex == 0 && (a->scope == RT_SCOPE_HOST || a->scope == RT_SCOPE_NOWHERE)) - continue; - - switch (family) { - - case AF_INET: - r = sd_rtnl_message_read_in_addr(m, IFA_LOCAL, &a->address.in); - if (r < 0) { - r = sd_rtnl_message_read_in_addr(m, IFA_ADDRESS, &a->address.in); - if (r < 0) - continue; - } - break; - - case AF_INET6: - r = sd_rtnl_message_read_in6_addr(m, IFA_LOCAL, &a->address.in6); - if (r < 0) { - r = sd_rtnl_message_read_in6_addr(m, IFA_ADDRESS, &a->address.in6); - if (r < 0) - continue; - } - break; - - default: - continue; - } - - a->ifindex = ifi; - a->family = family; - - n_list++; - }; - - if (n_list > 0) - qsort(list, n_list, sizeof(struct local_address), address_compare); - - *ret = list; - list = NULL; - - return (int) n_list; -} - -int local_gateways(sd_rtnl *context, int ifindex, int af, struct local_address **ret) { - _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL; - _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL; - _cleanup_free_ struct local_address *list = NULL; - sd_rtnl_message *m = NULL; - size_t n_list = 0, n_allocated = 0; - int r; - - assert(ret); - - if (context) - rtnl = sd_rtnl_ref(context); - else { - r = sd_rtnl_open(&rtnl); - if (r < 0) - return r; - } - - r = sd_rtnl_message_new_route(rtnl, &req, RTM_GETROUTE, af, RTPROT_UNSPEC); - if (r < 0) - return r; - - r = sd_rtnl_message_request_dump(req, true); - if (r < 0) - return r; - - r = sd_rtnl_call(rtnl, req, 0, &reply); - if (r < 0) - return r; - - for (m = reply; m; m = sd_rtnl_message_next(m)) { - struct local_address *a; - uint16_t type; - unsigned char dst_len, src_len; - uint32_t ifi; - int family; - - r = sd_rtnl_message_get_errno(m); - if (r < 0) - return r; - - r = sd_rtnl_message_get_type(m, &type); - if (r < 0) - return r; - if (type != RTM_NEWROUTE) - continue; - - /* We only care for default routes */ - r = sd_rtnl_message_route_get_dst_prefixlen(m, &dst_len); - if (r < 0) - return r; - if (dst_len != 0) - continue; - - r = sd_rtnl_message_route_get_src_prefixlen(m, &src_len); - if (r < 0) - return r; - if (src_len != 0) - continue; - - r = sd_rtnl_message_read_u32(m, RTA_OIF, &ifi); - if (r < 0) - return r; - if (ifindex > 0 && (int) ifi != ifindex) - continue; - - r = sd_rtnl_message_route_get_family(m, &family); - if (r < 0) - return r; - if (af != AF_UNSPEC && af != family) - continue; - - if (!GREEDY_REALLOC0(list, n_allocated, n_list + 1)) - return -ENOMEM; - - a = list + n_list; - - switch (family) { - case AF_INET: - r = sd_rtnl_message_read_in_addr(m, RTA_GATEWAY, &a->address.in); - if (r < 0) - continue; - - break; - case AF_INET6: - r = sd_rtnl_message_read_in6_addr(m, RTA_GATEWAY, &a->address.in6); - if (r < 0) - continue; - - break; - default: - continue; - } - - sd_rtnl_message_read_u32(m, RTA_PRIORITY, &a->metric); - - a->ifindex = ifi; - a->family = family; - - n_list++; - } - - if (n_list > 0) - qsort(list, n_list, sizeof(struct local_address), address_compare); - - *ret = list; - list = NULL; - - return (int) n_list; -} diff --git a/src/libelogind/sd-rtnl/rtnl-message.c b/src/libelogind/sd-rtnl/rtnl-message.c deleted file mode 100644 index 9dcf7df55..000000000 --- a/src/libelogind/sd-rtnl/rtnl-message.c +++ /dev/null @@ -1,1705 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2013 Tom Gundersen - - 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 . -***/ - -#include -#include -#include - -#include "util.h" -#include "formats-util.h" -#include "refcnt.h" -#include "missing.h" - -#include "sd-rtnl.h" -#include "rtnl-util.h" -#include "rtnl-internal.h" -#include "rtnl-types.h" - -#define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->container_offsets[i]) : NULL) -#define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers ++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr; - -#define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK) - -static int message_new_empty(sd_rtnl *rtnl, sd_rtnl_message **ret) { - sd_rtnl_message *m; - - assert_return(ret, -EINVAL); - - /* Note that 'rtnl' is currently unused, if we start using it internally - we must take care to avoid problems due to mutual references between - buses and their queued messages. See sd-bus. - */ - - m = new0(sd_rtnl_message, 1); - if (!m) - return -ENOMEM; - - m->n_ref = REFCNT_INIT; - - m->sealed = false; - - *ret = m; - - return 0; -} - -int message_new(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t type) { - _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL; - const NLType *nl_type; - size_t size; - int r; - - r = type_system_get_type(NULL, &nl_type, type); - if (r < 0) - return r; - - r = message_new_empty(rtnl, &m); - if (r < 0) - return r; - - size = NLMSG_SPACE(nl_type->size); - - assert(size >= sizeof(struct nlmsghdr)); - m->hdr = malloc0(size); - if (!m->hdr) - return -ENOMEM; - - m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; - - m->container_type_system[0] = nl_type->type_system; - m->hdr->nlmsg_len = size; - m->hdr->nlmsg_type = type; - - *ret = m; - m = NULL; - - return 0; -} - -int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) { - struct rtmsg *rtm; - - assert_return(m, -EINVAL); - assert_return(m->hdr, -EINVAL); - assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); - - rtm = NLMSG_DATA(m->hdr); - - if ((rtm->rtm_family == AF_INET && prefixlen > 32) || - (rtm->rtm_family == AF_INET6 && prefixlen > 128)) - return -ERANGE; - - rtm->rtm_dst_len = prefixlen; - - return 0; -} - -int sd_rtnl_message_route_set_src_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) { - struct rtmsg *rtm; - - assert_return(m, -EINVAL); - assert_return(m->hdr, -EINVAL); - assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); - - rtm = NLMSG_DATA(m->hdr); - - if ((rtm->rtm_family == AF_INET && prefixlen > 32) || - (rtm->rtm_family == AF_INET6 && prefixlen > 128)) - return -ERANGE; - - rtm->rtm_src_len = prefixlen; - - return 0; -} - -int sd_rtnl_message_route_set_scope(sd_rtnl_message *m, unsigned char scope) { - struct rtmsg *rtm; - - assert_return(m, -EINVAL); - assert_return(m->hdr, -EINVAL); - assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); - - rtm = NLMSG_DATA(m->hdr); - - rtm->rtm_scope = scope; - - return 0; -} - -int sd_rtnl_message_route_get_family(sd_rtnl_message *m, int *family) { - struct rtmsg *rtm; - - assert_return(m, -EINVAL); - assert_return(m->hdr, -EINVAL); - assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); - assert_return(family, -EINVAL); - - rtm = NLMSG_DATA(m->hdr); - - *family = rtm->rtm_family; - - return 0; -} - -int sd_rtnl_message_route_get_dst_prefixlen(sd_rtnl_message *m, unsigned char *dst_len) { - struct rtmsg *rtm; - - assert_return(m, -EINVAL); - assert_return(m->hdr, -EINVAL); - assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); - assert_return(dst_len, -EINVAL); - - rtm = NLMSG_DATA(m->hdr); - - *dst_len = rtm->rtm_dst_len; - - return 0; -} - -int sd_rtnl_message_route_get_src_prefixlen(sd_rtnl_message *m, unsigned char *src_len) { - struct rtmsg *rtm; - - assert_return(m, -EINVAL); - assert_return(m->hdr, -EINVAL); - assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); - assert_return(src_len, -EINVAL); - - rtm = NLMSG_DATA(m->hdr); - - *src_len = rtm->rtm_src_len; - - return 0; -} - -int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret, - uint16_t nlmsg_type, int rtm_family, - unsigned char rtm_protocol) { - struct rtmsg *rtm; - int r; - - assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL); - assert_return((nlmsg_type == RTM_GETROUTE && rtm_family == AF_UNSPEC) || - rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL); - assert_return(ret, -EINVAL); - - r = message_new(rtnl, ret, nlmsg_type); - if (r < 0) - return r; - - if (nlmsg_type == RTM_NEWROUTE) - (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND; - - rtm = NLMSG_DATA((*ret)->hdr); - - rtm->rtm_family = rtm_family; - rtm->rtm_scope = RT_SCOPE_UNIVERSE; - rtm->rtm_type = RTN_UNICAST; - rtm->rtm_table = RT_TABLE_MAIN; - rtm->rtm_protocol = rtm_protocol; - - return 0; -} - -int sd_rtnl_message_neigh_set_flags(sd_rtnl_message *m, uint8_t flags) { - struct ndmsg *ndm; - - assert_return(m, -EINVAL); - assert_return(m->hdr, -EINVAL); - assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL); - - ndm = NLMSG_DATA(m->hdr); - ndm->ndm_flags |= flags; - - return 0; -} - -int sd_rtnl_message_neigh_set_state(sd_rtnl_message *m, uint16_t state) { - struct ndmsg *ndm; - - assert_return(m, -EINVAL); - assert_return(m->hdr, -EINVAL); - assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL); - - ndm = NLMSG_DATA(m->hdr); - ndm->ndm_state |= state; - - return 0; -} - -int sd_rtnl_message_neigh_get_flags(sd_rtnl_message *m, uint8_t *flags) { - struct ndmsg *ndm; - - assert_return(m, -EINVAL); - assert_return(m->hdr, -EINVAL); - assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL); - - ndm = NLMSG_DATA(m->hdr); - *flags = ndm->ndm_flags; - - return 0; -} - -int sd_rtnl_message_neigh_get_state(sd_rtnl_message *m, uint16_t *state) { - struct ndmsg *ndm; - - assert_return(m, -EINVAL); - assert_return(m->hdr, -EINVAL); - assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL); - - ndm = NLMSG_DATA(m->hdr); - *state = ndm->ndm_state; - - return 0; -} - -int sd_rtnl_message_neigh_get_family(sd_rtnl_message *m, int *family) { - struct ndmsg *ndm; - - assert_return(m, -EINVAL); - assert_return(m->hdr, -EINVAL); - assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL); - assert_return(family, -EINVAL); - - ndm = NLMSG_DATA(m->hdr); - - *family = ndm->ndm_family; - - return 0; -} - -int sd_rtnl_message_neigh_get_ifindex(sd_rtnl_message *m, int *index) { - struct ndmsg *ndm; - - assert_return(m, -EINVAL); - assert_return(m->hdr, -EINVAL); - assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL); - assert_return(index, -EINVAL); - - ndm = NLMSG_DATA(m->hdr); - - *index = ndm->ndm_ifindex; - - return 0; -} - -int sd_rtnl_message_new_neigh(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t nlmsg_type, int index, int ndm_family) { - struct ndmsg *ndm; - int r; - - assert_return(rtnl_message_type_is_neigh(nlmsg_type), -EINVAL); - assert_return(ndm_family == AF_INET || - ndm_family == AF_INET6 || - ndm_family == PF_BRIDGE, -EINVAL); - assert_return(ret, -EINVAL); - - r = message_new(rtnl, ret, nlmsg_type); - if (r < 0) - return r; - - if (nlmsg_type == RTM_NEWNEIGH) - (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND; - - ndm = NLMSG_DATA((*ret)->hdr); - - ndm->ndm_family = ndm_family; - ndm->ndm_ifindex = index; - - return 0; -} - -int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) { - struct ifinfomsg *ifi; - - assert_return(m, -EINVAL); - assert_return(m->hdr, -EINVAL); - assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL); - assert_return(change, -EINVAL); - - ifi = NLMSG_DATA(m->hdr); - - ifi->ifi_flags = flags; - ifi->ifi_change = change; - - return 0; -} - -int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) { - struct ifinfomsg *ifi; - - assert_return(m, -EINVAL); - assert_return(m->hdr, -EINVAL); - assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL); - - ifi = NLMSG_DATA(m->hdr); - - ifi->ifi_type = type; - - return 0; -} - -int sd_rtnl_message_link_set_family(sd_rtnl_message *m, unsigned family) { - struct ifinfomsg *ifi; - - assert_return(m, -EINVAL); - assert_return(m->hdr, -EINVAL); - assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL); - - ifi = NLMSG_DATA(m->hdr); - - ifi->ifi_family = family; - - return 0; -} - -int sd_rtnl_message_new_link(sd_rtnl *rtnl, sd_rtnl_message **ret, - uint16_t nlmsg_type, int index) { - struct ifinfomsg *ifi; - int r; - - assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL); - assert_return(nlmsg_type != RTM_DELLINK || index > 0, -EINVAL); - assert_return(ret, -EINVAL); - - r = message_new(rtnl, ret, nlmsg_type); - if (r < 0) - return r; - - if (nlmsg_type == RTM_NEWLINK) - (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL; - - ifi = NLMSG_DATA((*ret)->hdr); - - ifi->ifi_family = AF_UNSPEC; - ifi->ifi_index = index; - - return 0; -} - -int sd_rtnl_message_request_dump(sd_rtnl_message *m, int dump) { - assert_return(m, -EINVAL); - assert_return(m->hdr, -EINVAL); - assert_return(m->hdr->nlmsg_type == RTM_GETLINK || - m->hdr->nlmsg_type == RTM_GETADDR || - m->hdr->nlmsg_type == RTM_GETROUTE || - m->hdr->nlmsg_type == RTM_GETNEIGH, - -EINVAL); - - if (dump) - m->hdr->nlmsg_flags |= NLM_F_DUMP; - else - m->hdr->nlmsg_flags &= ~NLM_F_DUMP; - - return 0; -} - -int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) { - struct ifaddrmsg *ifa; - - assert_return(m, -EINVAL); - assert_return(m->hdr, -EINVAL); - assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); - - ifa = NLMSG_DATA(m->hdr); - - if ((ifa->ifa_family == AF_INET && prefixlen > 32) || - (ifa->ifa_family == AF_INET6 && prefixlen > 128)) - return -ERANGE; - - ifa->ifa_prefixlen = prefixlen; - - return 0; -} - -int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) { - struct ifaddrmsg *ifa; - - assert_return(m, -EINVAL); - assert_return(m->hdr, -EINVAL); - assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); - - ifa = NLMSG_DATA(m->hdr); - - ifa->ifa_flags = flags; - - return 0; -} - -int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) { - struct ifaddrmsg *ifa; - - assert_return(m, -EINVAL); - assert_return(m->hdr, -EINVAL); - assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); - - ifa = NLMSG_DATA(m->hdr); - - ifa->ifa_scope = scope; - - return 0; -} - -int sd_rtnl_message_addr_get_family(sd_rtnl_message *m, int *family) { - struct ifaddrmsg *ifa; - - assert_return(m, -EINVAL); - assert_return(m->hdr, -EINVAL); - assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); - assert_return(family, -EINVAL); - - ifa = NLMSG_DATA(m->hdr); - - *family = ifa->ifa_family; - - return 0; -} - -int sd_rtnl_message_addr_get_prefixlen(sd_rtnl_message *m, unsigned char *prefixlen) { - struct ifaddrmsg *ifa; - - assert_return(m, -EINVAL); - assert_return(m->hdr, -EINVAL); - assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); - assert_return(prefixlen, -EINVAL); - - ifa = NLMSG_DATA(m->hdr); - - *prefixlen = ifa->ifa_prefixlen; - - return 0; -} - -int sd_rtnl_message_addr_get_scope(sd_rtnl_message *m, unsigned char *scope) { - struct ifaddrmsg *ifa; - - assert_return(m, -EINVAL); - assert_return(m->hdr, -EINVAL); - assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); - assert_return(scope, -EINVAL); - - ifa = NLMSG_DATA(m->hdr); - - *scope = ifa->ifa_scope; - - return 0; -} - -int sd_rtnl_message_addr_get_flags(sd_rtnl_message *m, unsigned char *flags) { - struct ifaddrmsg *ifa; - - assert_return(m, -EINVAL); - assert_return(m->hdr, -EINVAL); - assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); - assert_return(flags, -EINVAL); - - ifa = NLMSG_DATA(m->hdr); - - *flags = ifa->ifa_flags; - - return 0; -} - -int sd_rtnl_message_addr_get_ifindex(sd_rtnl_message *m, int *ifindex) { - struct ifaddrmsg *ifa; - - assert_return(m, -EINVAL); - assert_return(m->hdr, -EINVAL); - assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); - assert_return(ifindex, -EINVAL); - - ifa = NLMSG_DATA(m->hdr); - - *ifindex = ifa->ifa_index; - - return 0; -} - -int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret, - uint16_t nlmsg_type, int index, - int family) { - struct ifaddrmsg *ifa; - int r; - - assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL); - assert_return((nlmsg_type == RTM_GETADDR && index == 0) || - index > 0, -EINVAL); - assert_return((nlmsg_type == RTM_GETADDR && family == AF_UNSPEC) || - family == AF_INET || family == AF_INET6, -EINVAL); - assert_return(ret, -EINVAL); - - r = message_new(rtnl, ret, nlmsg_type); - if (r < 0) - return r; - - if (nlmsg_type == RTM_GETADDR) - (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP; - - ifa = NLMSG_DATA((*ret)->hdr); - - ifa->ifa_index = index; - ifa->ifa_family = family; - if (family == AF_INET) - ifa->ifa_prefixlen = 32; - else if (family == AF_INET6) - ifa->ifa_prefixlen = 128; - - return 0; -} - -int sd_rtnl_message_new_addr_update(sd_rtnl *rtnl, sd_rtnl_message **ret, - int index, int family) { - int r; - - r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, index, family); - if (r < 0) - return r; - - (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE; - - return 0; -} - -sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) { - if (m) - assert_se(REFCNT_INC(m->n_ref) >= 2); - - return m; -} - -sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) { - if (m && REFCNT_DEC(m->n_ref) == 0) { - unsigned i; - - free(m->hdr); - - for (i = 0; i <= m->n_containers; i++) - free(m->rta_offset_tb[i]); - - sd_rtnl_message_unref(m->next); - - free(m); - } - - return NULL; -} - -int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) { - assert_return(m, -EINVAL); - assert_return(type, -EINVAL); - - *type = m->hdr->nlmsg_type; - - return 0; -} - -int sd_rtnl_message_get_family(sd_rtnl_message *m, int *family) { - assert_return(m, -EINVAL); - assert_return(family, -EINVAL); - - assert(m->hdr); - - if (rtnl_message_type_is_link(m->hdr->nlmsg_type)) { - struct ifinfomsg *ifi; - - ifi = NLMSG_DATA(m->hdr); - - *family = ifi->ifi_family; - - return 0; - } else if (rtnl_message_type_is_route(m->hdr->nlmsg_type)) { - struct rtmsg *rtm; - - rtm = NLMSG_DATA(m->hdr); - - *family = rtm->rtm_family; - - return 0; - } else if (rtnl_message_type_is_neigh(m->hdr->nlmsg_type)) { - struct ndmsg *ndm; - - ndm = NLMSG_DATA(m->hdr); - - *family = ndm->ndm_family; - - return 0; - } else if (rtnl_message_type_is_addr(m->hdr->nlmsg_type)) { - struct ifaddrmsg *ifa; - - ifa = NLMSG_DATA(m->hdr); - - *family = ifa->ifa_family; - - return 0; - } - - return -EOPNOTSUPP; -} - -int sd_rtnl_message_is_broadcast(sd_rtnl_message *m) { - assert_return(m, -EINVAL); - - return m->broadcast; -} - -int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) { - struct ifinfomsg *ifi; - - assert_return(m, -EINVAL); - assert_return(m->hdr, -EINVAL); - assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL); - assert_return(ifindex, -EINVAL); - - ifi = NLMSG_DATA(m->hdr); - - *ifindex = ifi->ifi_index; - - return 0; -} - -int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) { - struct ifinfomsg *ifi; - - assert_return(m, -EINVAL); - assert_return(m->hdr, -EINVAL); - assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL); - assert_return(flags, -EINVAL); - - ifi = NLMSG_DATA(m->hdr); - - *flags = ifi->ifi_flags; - - return 0; -} - -int sd_rtnl_message_link_get_type(sd_rtnl_message *m, unsigned *type) { - struct ifinfomsg *ifi; - - assert_return(m, -EINVAL); - assert_return(m->hdr, -EINVAL); - assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL); - assert_return(type, -EINVAL); - - ifi = NLMSG_DATA(m->hdr); - - *type = ifi->ifi_type; - - return 0; -} - -/* If successful the updated message will be correctly aligned, if - unsuccessful the old message is untouched. */ -static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) { - uint32_t rta_length; - size_t message_length, padding_length; - struct nlmsghdr *new_hdr; - struct rtattr *rta; - char *padding; - unsigned i; - int offset; - - assert(m); - assert(m->hdr); - assert(!m->sealed); - assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len); - assert(!data || data_length); - - /* get offset of the new attribute */ - offset = m->hdr->nlmsg_len; - - /* get the size of the new rta attribute (with padding at the end) */ - rta_length = RTA_LENGTH(data_length); - - /* get the new message size (with padding at the end) */ - message_length = offset + RTA_ALIGN(rta_length); - - /* realloc to fit the new attribute */ - new_hdr = realloc(m->hdr, message_length); - if (!new_hdr) - return -ENOMEM; - m->hdr = new_hdr; - - /* get pointer to the attribute we are about to add */ - rta = (struct rtattr *) ((uint8_t *) m->hdr + offset); - - /* if we are inside containers, extend them */ - for (i = 0; i < m->n_containers; i++) - GET_CONTAINER(m, i)->rta_len += message_length - offset; - - /* fill in the attribute */ - rta->rta_type = type; - rta->rta_len = rta_length; - if (data) - /* we don't deal with the case where the user lies about the type - * and gives us too little data (so don't do that) - */ - padding = mempcpy(RTA_DATA(rta), data, data_length); - else { - /* if no data was passed, make sure we still initialize the padding - note that we can have data_length > 0 (used by some containers) */ - padding = RTA_DATA(rta); - } - - /* make sure also the padding at the end of the message is initialized */ - padding_length = (uint8_t*)m->hdr + message_length - (uint8_t*)padding; - memzero(padding, padding_length); - - /* update message size */ - m->hdr->nlmsg_len = message_length; - - return offset; -} - -static int message_attribute_has_type(sd_rtnl_message *m, uint16_t attribute_type, uint16_t data_type) { - const NLType *type; - int r; - - r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type); - if (r < 0) - return r; - - if (type->type != data_type) - return -EINVAL; - - return type->size; -} - -int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) { - size_t length, size; - int r; - - assert_return(m, -EINVAL); - assert_return(!m->sealed, -EPERM); - assert_return(data, -EINVAL); - - r = message_attribute_has_type(m, type, NLA_STRING); - if (r < 0) - return r; - else - size = (size_t)r; - - if (size) { - length = strnlen(data, size+1); - if (length > size) - return -EINVAL; - } else - length = strlen(data); - - r = add_rtattr(m, type, data, length + 1); - if (r < 0) - return r; - - return 0; -} - -int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) { - int r; - - assert_return(m, -EINVAL); - assert_return(!m->sealed, -EPERM); - - r = message_attribute_has_type(m, type, NLA_U8); - if (r < 0) - return r; - - r = add_rtattr(m, type, &data, sizeof(uint8_t)); - if (r < 0) - return r; - - return 0; -} - - -int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) { - int r; - - assert_return(m, -EINVAL); - assert_return(!m->sealed, -EPERM); - - r = message_attribute_has_type(m, type, NLA_U16); - if (r < 0) - return r; - - r = add_rtattr(m, type, &data, sizeof(uint16_t)); - if (r < 0) - return r; - - return 0; -} - -int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) { - int r; - - assert_return(m, -EINVAL); - assert_return(!m->sealed, -EPERM); - - r = message_attribute_has_type(m, type, NLA_U32); - if (r < 0) - return r; - - r = add_rtattr(m, type, &data, sizeof(uint32_t)); - if (r < 0) - return r; - - return 0; -} - -int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) { - int r; - - assert_return(m, -EINVAL); - assert_return(!m->sealed, -EPERM); - assert_return(data, -EINVAL); - - r = message_attribute_has_type(m, type, NLA_IN_ADDR); - if (r < 0) - return r; - - r = add_rtattr(m, type, data, sizeof(struct in_addr)); - if (r < 0) - return r; - - return 0; -} - -int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) { - int r; - - assert_return(m, -EINVAL); - assert_return(!m->sealed, -EPERM); - assert_return(data, -EINVAL); - - r = message_attribute_has_type(m, type, NLA_IN_ADDR); - if (r < 0) - return r; - - r = add_rtattr(m, type, data, sizeof(struct in6_addr)); - if (r < 0) - return r; - - return 0; -} - -int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) { - int r; - - assert_return(m, -EINVAL); - assert_return(!m->sealed, -EPERM); - assert_return(data, -EINVAL); - - r = message_attribute_has_type(m, type, NLA_ETHER_ADDR); - if (r < 0) - return r; - - r = add_rtattr(m, type, data, ETH_ALEN); - if (r < 0) - return r; - - return 0; -} - -int sd_rtnl_message_append_cache_info(sd_rtnl_message *m, unsigned short type, const struct ifa_cacheinfo *info) { - int r; - - assert_return(m, -EINVAL); - assert_return(!m->sealed, -EPERM); - assert_return(info, -EINVAL); - - r = message_attribute_has_type(m, type, NLA_CACHE_INFO); - if (r < 0) - return r; - - r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo)); - if (r < 0) - return r; - - return 0; -} - -int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) { - size_t size; - int r; - - assert_return(m, -EINVAL); - assert_return(!m->sealed, -EPERM); - assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -ERANGE); - - r = message_attribute_has_type(m, type, NLA_NESTED); - if (r < 0) { - const NLTypeSystemUnion *type_system_union; - int family; - - r = message_attribute_has_type(m, type, NLA_UNION); - if (r < 0) - return r; - size = (size_t) r; - - r = sd_rtnl_message_get_family(m, &family); - if (r < 0) - return r; - - r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type); - if (r < 0) - return r; - - r = type_system_union_protocol_get_type_system(type_system_union, - &m->container_type_system[m->n_containers + 1], - family); - if (r < 0) - return r; - } else { - size = (size_t)r; - - r = type_system_get_type_system(m->container_type_system[m->n_containers], - &m->container_type_system[m->n_containers + 1], - type); - if (r < 0) - return r; - } - - r = add_rtattr(m, type | NLA_F_NESTED, NULL, size); - if (r < 0) - return r; - - m->container_offsets[m->n_containers ++] = r; - - return 0; -} - -int sd_rtnl_message_open_container_union(sd_rtnl_message *m, unsigned short type, const char *key) { - const NLTypeSystemUnion *type_system_union; - int r; - - assert_return(m, -EINVAL); - assert_return(!m->sealed, -EPERM); - - r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type); - if (r < 0) - return r; - - r = type_system_union_get_type_system(type_system_union, - &m->container_type_system[m->n_containers + 1], - key); - if (r < 0) - return r; - - r = sd_rtnl_message_append_string(m, type_system_union->match, key); - if (r < 0) - return r; - - /* do we evere need non-null size */ - r = add_rtattr(m, type, NULL, 0); - if (r < 0) - return r; - - m->container_offsets[m->n_containers ++] = r; - - return 0; -} - - -int sd_rtnl_message_close_container(sd_rtnl_message *m) { - assert_return(m, -EINVAL); - assert_return(!m->sealed, -EPERM); - assert_return(m->n_containers > 0, -EINVAL); - - m->container_type_system[m->n_containers] = NULL; - m->n_containers --; - - return 0; -} - -int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) { - struct rtattr *rta; - - assert_return(m, -EINVAL); - assert_return(m->sealed, -EPERM); - assert_return(data, -EINVAL); - assert(m->n_containers <= RTNL_CONTAINER_DEPTH); - assert(m->rta_offset_tb[m->n_containers]); - assert(type < m->rta_tb_size[m->n_containers]); - - if(!m->rta_offset_tb[m->n_containers][type]) - return -ENODATA; - - rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]); - - *data = RTA_DATA(rta); - - return RTA_PAYLOAD(rta); -} - -int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, const char **data) { - int r; - void *attr_data; - - assert_return(m, -EINVAL); - - r = message_attribute_has_type(m, type, NLA_STRING); - if (r < 0) - return r; - - r = rtnl_message_read_internal(m, type, &attr_data); - if (r < 0) - return r; - else if (strnlen(attr_data, r) >= (size_t) r) - return -EIO; - - if (data) - *data = (const char *) attr_data; - - return 0; -} - -int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) { - int r; - void *attr_data; - - assert_return(m, -EINVAL); - - r = message_attribute_has_type(m, type, NLA_U8); - if (r < 0) - return r; - - r = rtnl_message_read_internal(m, type, &attr_data); - if (r < 0) - return r; - else if ((size_t) r < sizeof(uint8_t)) - return -EIO; - - if (data) - *data = *(uint8_t *) attr_data; - - return 0; -} - -int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) { - int r; - void *attr_data; - - assert_return(m, -EINVAL); - - r = message_attribute_has_type(m, type, NLA_U16); - if (r < 0) - return r; - - r = rtnl_message_read_internal(m, type, &attr_data); - if (r < 0) - return r; - else if ((size_t) r < sizeof(uint16_t)) - return -EIO; - - if (data) - *data = *(uint16_t *) attr_data; - - return 0; -} - -int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) { - int r; - void *attr_data; - - assert_return(m, -EINVAL); - - r = message_attribute_has_type(m, type, NLA_U32); - if (r < 0) - return r; - - r = rtnl_message_read_internal(m, type, &attr_data); - if (r < 0) - return r; - else if ((size_t)r < sizeof(uint32_t)) - return -EIO; - - if (data) - *data = *(uint32_t *) attr_data; - - return 0; -} - -int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) { - int r; - void *attr_data; - - assert_return(m, -EINVAL); - - r = message_attribute_has_type(m, type, NLA_ETHER_ADDR); - if (r < 0) - return r; - - r = rtnl_message_read_internal(m, type, &attr_data); - if (r < 0) - return r; - else if ((size_t)r < sizeof(struct ether_addr)) - return -EIO; - - if (data) - memcpy(data, attr_data, sizeof(struct ether_addr)); - - return 0; -} - -int sd_rtnl_message_read_cache_info(sd_rtnl_message *m, unsigned short type, struct ifa_cacheinfo *info) { - int r; - void *attr_data; - - assert_return(m, -EINVAL); - - r = message_attribute_has_type(m, type, NLA_CACHE_INFO); - if (r < 0) - return r; - - r = rtnl_message_read_internal(m, type, &attr_data); - if (r < 0) - return r; - else if ((size_t)r < sizeof(struct ifa_cacheinfo)) - return -EIO; - - if (info) - memcpy(info, attr_data, sizeof(struct ifa_cacheinfo)); - - return 0; -} - -int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) { - int r; - void *attr_data; - - assert_return(m, -EINVAL); - - r = message_attribute_has_type(m, type, NLA_IN_ADDR); - if (r < 0) - return r; - - r = rtnl_message_read_internal(m, type, &attr_data); - if (r < 0) - return r; - else if ((size_t)r < sizeof(struct in_addr)) - return -EIO; - - if (data) - memcpy(data, attr_data, sizeof(struct in_addr)); - - return 0; -} - -int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) { - int r; - void *attr_data; - - assert_return(m, -EINVAL); - - r = message_attribute_has_type(m, type, NLA_IN_ADDR); - if (r < 0) - return r; - - r = rtnl_message_read_internal(m, type, &attr_data); - if (r < 0) - return r; - else if ((size_t)r < sizeof(struct in6_addr)) - return -EIO; - - if (data) - memcpy(data, attr_data, sizeof(struct in6_addr)); - - return 0; -} - -int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) { - const NLType *nl_type; - const NLTypeSystem *type_system; - void *container; - size_t size; - int r; - - assert_return(m, -EINVAL); - assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL); - - r = type_system_get_type(m->container_type_system[m->n_containers], - &nl_type, - type); - if (r < 0) - return r; - - if (nl_type->type == NLA_NESTED) { - r = type_system_get_type_system(m->container_type_system[m->n_containers], - &type_system, - type); - if (r < 0) - return r; - } else if (nl_type->type == NLA_UNION) { - const NLTypeSystemUnion *type_system_union; - - r = type_system_get_type_system_union(m->container_type_system[m->n_containers], - &type_system_union, - type); - if (r < 0) - return r; - - switch (type_system_union->match_type) { - case NL_MATCH_SIBLING: - { - const char *key; - - r = sd_rtnl_message_read_string(m, type_system_union->match, &key); - if (r < 0) - return r; - - r = type_system_union_get_type_system(type_system_union, - &type_system, - key); - if (r < 0) - return r; - - break; - } - case NL_MATCH_PROTOCOL: - { - int family; - - r = sd_rtnl_message_get_family(m, &family); - if (r < 0) - return r; - - r = type_system_union_protocol_get_type_system(type_system_union, - &type_system, - family); - if (r < 0) - return r; - - break; - } - default: - assert_not_reached("sd-rtnl: invalid type system union type"); - } - } else - return -EINVAL; - - r = rtnl_message_read_internal(m, type, &container); - if (r < 0) - return r; - else - size = (size_t)r; - - m->n_containers ++; - - r = rtnl_message_parse(m, - &m->rta_offset_tb[m->n_containers], - &m->rta_tb_size[m->n_containers], - type_system->max, - container, - size); - if (r < 0) { - m->n_containers --; - return r; - } - - m->container_type_system[m->n_containers] = type_system; - - return 0; -} - -int sd_rtnl_message_exit_container(sd_rtnl_message *m) { - assert_return(m, -EINVAL); - assert_return(m->sealed, -EINVAL); - assert_return(m->n_containers > 0, -EINVAL); - - free(m->rta_offset_tb[m->n_containers]); - m->rta_offset_tb[m->n_containers] = NULL; - m->container_type_system[m->n_containers] = NULL; - - m->n_containers --; - - return 0; -} - -uint32_t rtnl_message_get_serial(sd_rtnl_message *m) { - assert(m); - assert(m->hdr); - - return m->hdr->nlmsg_seq; -} - -int sd_rtnl_message_is_error(sd_rtnl_message *m) { - assert_return(m, 0); - assert_return(m->hdr, 0); - - return m->hdr->nlmsg_type == NLMSG_ERROR; -} - -int sd_rtnl_message_get_errno(sd_rtnl_message *m) { - struct nlmsgerr *err; - - assert_return(m, -EINVAL); - assert_return(m->hdr, -EINVAL); - - if (!sd_rtnl_message_is_error(m)) - return 0; - - err = NLMSG_DATA(m->hdr); - - return err->error; -} - -int rtnl_message_parse(sd_rtnl_message *m, - size_t **rta_offset_tb, - unsigned short *rta_tb_size, - int max, - struct rtattr *rta, - unsigned int rt_len) { - unsigned short type; - size_t *tb; - - tb = new0(size_t, max + 1); - if(!tb) - return -ENOMEM; - - *rta_tb_size = max + 1; - - for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) { - type = RTA_TYPE(rta); - - /* if the kernel is newer than the headers we used - when building, we ignore out-of-range attributes - */ - if (type > max) - continue; - - if (tb[type]) - log_debug("rtnl: message parse - overwriting repeated attribute"); - - tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr; - } - - *rta_offset_tb = tb; - - return 0; -} - -/* returns the number of bytes sent, or a negative error code */ -int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) { - union { - struct sockaddr sa; - struct sockaddr_nl nl; - } addr = { - .nl.nl_family = AF_NETLINK, - }; - ssize_t k; - - assert(nl); - assert(m); - assert(m->hdr); - - k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len, - 0, &addr.sa, sizeof(addr)); - if (k < 0) - return (errno == EAGAIN) ? 0 : -errno; - - return k; -} - -static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool peek) { - uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred)) + - CMSG_SPACE(sizeof(struct nl_pktinfo))]; - struct msghdr msg = { - .msg_iov = iov, - .msg_iovlen = 1, - .msg_control = cred_buffer, - .msg_controllen = sizeof(cred_buffer), - }; - struct cmsghdr *cmsg; - uint32_t group = 0; - bool auth = false; - int r; - - assert(fd >= 0); - assert(iov); - - r = recvmsg(fd, &msg, MSG_TRUNC | (peek ? MSG_PEEK : 0)); - if (r < 0) { - /* no data */ - if (errno == ENOBUFS) - log_debug("rtnl: kernel receive buffer overrun"); - else if (errno == EAGAIN) - log_debug("rtnl: no data in socket"); - - return (errno == EAGAIN || errno == EINTR) ? 0 : -errno; - } - - CMSG_FOREACH(cmsg, &msg) { - if (cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SCM_CREDENTIALS && - cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) { - struct ucred *ucred = (void *)CMSG_DATA(cmsg); - - /* from the kernel */ - if (ucred->pid == 0) - auth = true; - else - log_debug("rtnl: ignoring message from PID "PID_FMT, ucred->pid); - } else if (cmsg->cmsg_level == SOL_NETLINK && - cmsg->cmsg_type == NETLINK_PKTINFO && - cmsg->cmsg_len == CMSG_LEN(sizeof(struct nl_pktinfo))) { - struct nl_pktinfo *pktinfo = (void *)CMSG_DATA(cmsg); - - /* multi-cast group */ - group = pktinfo->group; - } - } - - if (!auth) { - /* not from the kernel, ignore */ - if (peek) { - /* drop the message */ - r = recvmsg(fd, &msg, 0); - if (r < 0) - return (errno == EAGAIN || errno == EINTR) ? 0 : -errno; - } - - return 0; - } - - if (_group) - *_group = group; - - return r; -} - -/* On success, the number of bytes received is returned and *ret points to the received message - * which has a valid header and the correct size. - * If nothing useful was received 0 is returned. - * On failure, a negative error code is returned. - */ -int socket_read_message(sd_rtnl *rtnl) { - _cleanup_rtnl_message_unref_ sd_rtnl_message *first = NULL; - struct iovec iov = {}; - uint32_t group = 0; - bool multi_part = false, done = false; - struct nlmsghdr *new_msg; - size_t len; - int r; - unsigned i = 0; - - assert(rtnl); - assert(rtnl->rbuffer); - assert(rtnl->rbuffer_allocated >= sizeof(struct nlmsghdr)); - - /* read nothing, just get the pending message size */ - r = socket_recv_message(rtnl->fd, &iov, NULL, true); - if (r <= 0) - return r; - else - len = (size_t)r; - - /* make room for the pending message */ - if (!greedy_realloc((void **)&rtnl->rbuffer, - &rtnl->rbuffer_allocated, - len, sizeof(uint8_t))) - return -ENOMEM; - - iov.iov_base = rtnl->rbuffer; - iov.iov_len = rtnl->rbuffer_allocated; - - /* read the pending message */ - r = socket_recv_message(rtnl->fd, &iov, &group, false); - if (r <= 0) - return r; - else - len = (size_t)r; - - if (len > rtnl->rbuffer_allocated) - /* message did not fit in read buffer */ - return -EIO; - - if (NLMSG_OK(rtnl->rbuffer, len) && rtnl->rbuffer->nlmsg_flags & NLM_F_MULTI) { - multi_part = true; - - for (i = 0; i < rtnl->rqueue_partial_size; i++) { - if (rtnl_message_get_serial(rtnl->rqueue_partial[i]) == - rtnl->rbuffer->nlmsg_seq) { - first = rtnl->rqueue_partial[i]; - break; - } - } - } - - for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len) && !done; new_msg = NLMSG_NEXT(new_msg, len)) { - _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL; - const NLType *nl_type; - - if (!group && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid) - /* not broadcast and not for us */ - continue; - - if (new_msg->nlmsg_type == NLMSG_NOOP) - /* silently drop noop messages */ - continue; - - if (new_msg->nlmsg_type == NLMSG_DONE) { - /* finished reading multi-part message */ - done = true; - - /* if first is not defined, put NLMSG_DONE into the receive queue. */ - if (first) - continue; - } - - /* check that we support this message type */ - r = type_system_get_type(NULL, &nl_type, new_msg->nlmsg_type); - if (r < 0) { - if (r == -EOPNOTSUPP) - log_debug("sd-rtnl: ignored message with unknown type: %i", - new_msg->nlmsg_type); - - continue; - } - - /* check that the size matches the message type */ - if (new_msg->nlmsg_len < NLMSG_LENGTH(nl_type->size)) { - log_debug("sd-rtnl: message larger than expected, dropping"); - continue; - } - - r = message_new_empty(rtnl, &m); - if (r < 0) - return r; - - m->broadcast = !!group; - - m->hdr = memdup(new_msg, new_msg->nlmsg_len); - if (!m->hdr) - return -ENOMEM; - - /* seal and parse the top-level message */ - r = sd_rtnl_message_rewind(m); - if (r < 0) - return r; - - /* push the message onto the multi-part message stack */ - if (first) - m->next = first; - first = m; - m = NULL; - } - - if (len) - log_debug("sd-rtnl: discarding %zu bytes of incoming message", len); - - if (!first) - return 0; - - if (!multi_part || done) { - /* we got a complete message, push it on the read queue */ - r = rtnl_rqueue_make_room(rtnl); - if (r < 0) - return r; - - rtnl->rqueue[rtnl->rqueue_size ++] = first; - first = NULL; - - if (multi_part && (i < rtnl->rqueue_partial_size)) { - /* remove the message form the partial read queue */ - memmove(rtnl->rqueue_partial + i,rtnl->rqueue_partial + i + 1, - sizeof(sd_rtnl_message*) * (rtnl->rqueue_partial_size - i - 1)); - rtnl->rqueue_partial_size --; - } - - return 1; - } else { - /* we only got a partial multi-part message, push it on the - partial read queue */ - if (i < rtnl->rqueue_partial_size) { - rtnl->rqueue_partial[i] = first; - } else { - r = rtnl_rqueue_partial_make_room(rtnl); - if (r < 0) - return r; - - rtnl->rqueue_partial[rtnl->rqueue_partial_size ++] = first; - } - first = NULL; - - return 0; - } -} - -int sd_rtnl_message_rewind(sd_rtnl_message *m) { - const NLType *type; - unsigned i; - int r; - - assert_return(m, -EINVAL); - - /* don't allow appending to message once parsed */ - if (!m->sealed) - rtnl_message_seal(m); - - for (i = 1; i <= m->n_containers; i++) { - free(m->rta_offset_tb[i]); - m->rta_offset_tb[i] = NULL; - m->rta_tb_size[i] = 0; - m->container_type_system[i] = NULL; - } - - m->n_containers = 0; - - if (m->rta_offset_tb[0]) { - /* top-level attributes have already been parsed */ - return 0; - } - - assert(m->hdr); - - r = type_system_get_type(NULL, &type, m->hdr->nlmsg_type); - if (r < 0) - return r; - - if (type->type == NLA_NESTED) { - const NLTypeSystem *type_system = type->type_system; - - assert(type_system); - - m->container_type_system[0] = type_system; - - r = rtnl_message_parse(m, - &m->rta_offset_tb[m->n_containers], - &m->rta_tb_size[m->n_containers], - type_system->max, - (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) + - NLMSG_ALIGN(type->size)), - NLMSG_PAYLOAD(m->hdr, type->size)); - if (r < 0) - return r; - } - - return 0; -} - -void rtnl_message_seal(sd_rtnl_message *m) { - assert(m); - assert(!m->sealed); - - m->sealed = true; -} - -sd_rtnl_message *sd_rtnl_message_next(sd_rtnl_message *m) { - assert_return(m, NULL); - - return m->next; -} diff --git a/src/libelogind/sd-rtnl/rtnl-util.c b/src/libelogind/sd-rtnl/rtnl-util.c deleted file mode 100644 index c2b1a5c65..000000000 --- a/src/libelogind/sd-rtnl/rtnl-util.c +++ /dev/null @@ -1,173 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright (C) 2013 Tom Gundersen - - 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 . -***/ - - -#include "sd-rtnl.h" - -#include "rtnl-util.h" -#include "rtnl-internal.h" - -int rtnl_set_link_name(sd_rtnl **rtnl, int ifindex, const char *name) { - _cleanup_rtnl_message_unref_ sd_rtnl_message *message = NULL; - int r; - - assert(rtnl); - assert(ifindex > 0); - assert(name); - - if (!*rtnl) { - r = sd_rtnl_open(rtnl); - if (r < 0) - return r; - } - - r = sd_rtnl_message_new_link(*rtnl, &message, RTM_SETLINK, ifindex); - if (r < 0) - return r; - - r = sd_rtnl_message_append_string(message, IFLA_IFNAME, name); - if (r < 0) - return r; - - r = sd_rtnl_call(*rtnl, message, 0, NULL); - if (r < 0) - return r; - - return 0; -} - -int rtnl_set_link_properties(sd_rtnl **rtnl, int ifindex, const char *alias, - const struct ether_addr *mac, unsigned mtu) { - _cleanup_rtnl_message_unref_ sd_rtnl_message *message = NULL; - int r; - - assert(rtnl); - assert(ifindex > 0); - - if (!alias && !mac && mtu == 0) - return 0; - - if (!*rtnl) { - r = sd_rtnl_open(rtnl); - if (r < 0) - return r; - } - - r = sd_rtnl_message_new_link(*rtnl, &message, RTM_SETLINK, ifindex); - if (r < 0) - return r; - - if (alias) { - r = sd_rtnl_message_append_string(message, IFLA_IFALIAS, alias); - if (r < 0) - return r; - } - - if (mac) { - r = sd_rtnl_message_append_ether_addr(message, IFLA_ADDRESS, mac); - if (r < 0) - return r; - } - - if (mtu > 0) { - r = sd_rtnl_message_append_u32(message, IFLA_MTU, mtu); - if (r < 0) - return r; - } - - r = sd_rtnl_call(*rtnl, message, 0, NULL); - if (r < 0) - return r; - - return 0; -} - -int rtnl_message_new_synthetic_error(int error, uint32_t serial, sd_rtnl_message **ret) { - struct nlmsgerr *err; - int r; - - assert(error <= 0); - - r = message_new(NULL, ret, NLMSG_ERROR); - if (r < 0) - return r; - - (*ret)->hdr->nlmsg_seq = serial; - - err = NLMSG_DATA((*ret)->hdr); - - err->error = error; - - return 0; -} - -bool rtnl_message_type_is_neigh(uint16_t type) { - switch (type) { - case RTM_NEWNEIGH: - case RTM_GETNEIGH: - case RTM_DELNEIGH: - return true; - default: - return false; - } -} - -bool rtnl_message_type_is_route(uint16_t type) { - switch (type) { - case RTM_NEWROUTE: - case RTM_GETROUTE: - case RTM_DELROUTE: - return true; - default: - return false; - } -} - -bool rtnl_message_type_is_link(uint16_t type) { - switch (type) { - case RTM_NEWLINK: - case RTM_SETLINK: - case RTM_GETLINK: - case RTM_DELLINK: - return true; - default: - return false; - } -} - -bool rtnl_message_type_is_addr(uint16_t type) { - switch (type) { - case RTM_NEWADDR: - case RTM_GETADDR: - case RTM_DELADDR: - return true; - default: - return false; - } -} - -int rtnl_log_parse_error(int r) { - return log_error_errno(r, "Failed to parse netlink message: %m"); -} - -int rtnl_log_create_error(int r) { - return log_error_errno(r, "Failed to create netlink message: %m"); -} diff --git a/src/libelogind/sd-rtnl/sd-rtnl.c b/src/libelogind/sd-rtnl/sd-rtnl.c deleted file mode 100644 index c682007fc..000000000 --- a/src/libelogind/sd-rtnl/sd-rtnl.c +++ /dev/null @@ -1,1060 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2013 Tom Gundersen - - 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 . -***/ - -#include -#include - -#include "missing.h" -#include "macro.h" -#include "util.h" -#include "hashmap.h" - -#include "sd-rtnl.h" -#include "rtnl-internal.h" -#include "rtnl-util.h" - -static int sd_rtnl_new(sd_rtnl **ret) { - _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL; - - assert_return(ret, -EINVAL); - - rtnl = new0(sd_rtnl, 1); - if (!rtnl) - return -ENOMEM; - - rtnl->n_ref = REFCNT_INIT; - - rtnl->fd = -1; - - rtnl->sockaddr.nl.nl_family = AF_NETLINK; - - rtnl->original_pid = getpid(); - - LIST_HEAD_INIT(rtnl->match_callbacks); - - /* We guarantee that wqueue always has space for at least - * one entry */ - if (!GREEDY_REALLOC(rtnl->wqueue, rtnl->wqueue_allocated, 1)) - return -ENOMEM; - - /* We guarantee that the read buffer has at least space for - * a message header */ - if (!greedy_realloc((void**)&rtnl->rbuffer, &rtnl->rbuffer_allocated, - sizeof(struct nlmsghdr), sizeof(uint8_t))) - return -ENOMEM; - - /* Change notification responses have sequence 0, so we must - * start our request sequence numbers at 1, or we may confuse our - * responses with notifications from the kernel */ - rtnl->serial = 1; - - *ret = rtnl; - rtnl = NULL; - - return 0; -} - -int sd_rtnl_new_from_netlink(sd_rtnl **ret, int fd) { - _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL; - socklen_t addrlen; - int r; - - assert_return(ret, -EINVAL); - - r = sd_rtnl_new(&rtnl); - if (r < 0) - return r; - - addrlen = sizeof(rtnl->sockaddr); - - r = getsockname(fd, &rtnl->sockaddr.sa, &addrlen); - if (r < 0) - return -errno; - - rtnl->fd = fd; - - *ret = rtnl; - rtnl = NULL; - - return 0; -} - -static bool rtnl_pid_changed(sd_rtnl *rtnl) { - assert(rtnl); - - /* We don't support people creating an rtnl connection and - * keeping it around over a fork(). Let's complain. */ - - return rtnl->original_pid != getpid(); -} - -int sd_rtnl_open_fd(sd_rtnl **ret, int fd) { - _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL; - socklen_t addrlen; - int r, one = 1; - - assert_return(ret, -EINVAL); - assert_return(fd >= 0, -EINVAL); - - r = sd_rtnl_new(&rtnl); - if (r < 0) - return r; - - r = setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)); - if (r < 0) - return -errno; - - r = setsockopt(fd, SOL_NETLINK, NETLINK_PKTINFO, &one, sizeof(one)); - if (r < 0) - return -errno; - - addrlen = sizeof(rtnl->sockaddr); - - r = bind(fd, &rtnl->sockaddr.sa, addrlen); - /* ignore EINVAL to allow opening an already bound socket */ - if (r < 0 && errno != EINVAL) - return -errno; - - r = getsockname(fd, &rtnl->sockaddr.sa, &addrlen); - if (r < 0) - return -errno; - - rtnl->fd = fd; - - *ret = rtnl; - rtnl = NULL; - - return 0; -} - -int sd_rtnl_open(sd_rtnl **ret) { - _cleanup_close_ int fd = -1; - int r; - - fd = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_ROUTE); - if (fd < 0) - return -errno; - - r = sd_rtnl_open_fd(ret, fd); - if (r < 0) - return r; - - fd = -1; - - return 0; -} - -static int rtnl_join_broadcast_group(sd_rtnl *rtnl, unsigned group) { - int r; - - assert(rtnl); - assert(rtnl->fd >= 0); - assert(group > 0); - - r = setsockopt(rtnl->fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &group, sizeof(group)); - if (r < 0) - return -errno; - - return 0; -} - -int sd_rtnl_inc_rcvbuf(const sd_rtnl *const rtnl, const int size) { - return fd_inc_rcvbuf(rtnl->fd, size); -} - -sd_rtnl *sd_rtnl_ref(sd_rtnl *rtnl) { - assert_return(rtnl, NULL); - assert_return(!rtnl_pid_changed(rtnl), NULL); - - if (rtnl) - assert_se(REFCNT_INC(rtnl->n_ref) >= 2); - - return rtnl; -} - -sd_rtnl *sd_rtnl_unref(sd_rtnl *rtnl) { - if (!rtnl) - return NULL; - - assert_return(!rtnl_pid_changed(rtnl), NULL); - - if (REFCNT_DEC(rtnl->n_ref) == 0) { - struct match_callback *f; - unsigned i; - - for (i = 0; i < rtnl->rqueue_size; i++) - sd_rtnl_message_unref(rtnl->rqueue[i]); - free(rtnl->rqueue); - - for (i = 0; i < rtnl->rqueue_partial_size; i++) - sd_rtnl_message_unref(rtnl->rqueue_partial[i]); - free(rtnl->rqueue_partial); - - for (i = 0; i < rtnl->wqueue_size; i++) - sd_rtnl_message_unref(rtnl->wqueue[i]); - free(rtnl->wqueue); - - free(rtnl->rbuffer); - - hashmap_free_free(rtnl->reply_callbacks); - prioq_free(rtnl->reply_callbacks_prioq); - - sd_event_source_unref(rtnl->io_event_source); - sd_event_source_unref(rtnl->time_event_source); - sd_event_source_unref(rtnl->exit_event_source); - sd_event_unref(rtnl->event); - - while ((f = rtnl->match_callbacks)) { - LIST_REMOVE(match_callbacks, rtnl->match_callbacks, f); - free(f); - } - - safe_close(rtnl->fd); - free(rtnl); - } - - return NULL; -} - -static void rtnl_seal_message(sd_rtnl *rtnl, sd_rtnl_message *m) { - assert(rtnl); - assert(!rtnl_pid_changed(rtnl)); - assert(m); - assert(m->hdr); - - /* don't use seq == 0, as that is used for broadcasts, so we - would get confused by replies to such messages */ - m->hdr->nlmsg_seq = rtnl->serial++ ? : rtnl->serial++; - - rtnl_message_seal(m); - - return; -} - -int sd_rtnl_send(sd_rtnl *nl, - sd_rtnl_message *message, - uint32_t *serial) { - int r; - - assert_return(nl, -EINVAL); - assert_return(!rtnl_pid_changed(nl), -ECHILD); - assert_return(message, -EINVAL); - assert_return(!message->sealed, -EPERM); - - rtnl_seal_message(nl, message); - - if (nl->wqueue_size <= 0) { - /* send directly */ - r = socket_write_message(nl, message); - if (r < 0) - return r; - else if (r == 0) { - /* nothing was sent, so let's put it on - * the queue */ - nl->wqueue[0] = sd_rtnl_message_ref(message); - nl->wqueue_size = 1; - } - } else { - /* append to queue */ - if (nl->wqueue_size >= RTNL_WQUEUE_MAX) { - log_debug("rtnl: exhausted the write queue size (%d)", RTNL_WQUEUE_MAX); - return -ENOBUFS; - } - - if (!GREEDY_REALLOC(nl->wqueue, nl->wqueue_allocated, nl->wqueue_size + 1)) - return -ENOMEM; - - nl->wqueue[nl->wqueue_size ++] = sd_rtnl_message_ref(message); - } - - if (serial) - *serial = rtnl_message_get_serial(message); - - return 1; -} - -int rtnl_rqueue_make_room(sd_rtnl *rtnl) { - assert(rtnl); - - if (rtnl->rqueue_size >= RTNL_RQUEUE_MAX) { - log_debug("rtnl: exhausted the read queue size (%d)", RTNL_RQUEUE_MAX); - return -ENOBUFS; - } - - if (!GREEDY_REALLOC(rtnl->rqueue, rtnl->rqueue_allocated, rtnl->rqueue_size + 1)) - return -ENOMEM; - - return 0; -} - -int rtnl_rqueue_partial_make_room(sd_rtnl *rtnl) { - assert(rtnl); - - if (rtnl->rqueue_partial_size >= RTNL_RQUEUE_MAX) { - log_debug("rtnl: exhausted the partial read queue size (%d)", RTNL_RQUEUE_MAX); - return -ENOBUFS; - } - - if (!GREEDY_REALLOC(rtnl->rqueue_partial, rtnl->rqueue_partial_allocated, - rtnl->rqueue_partial_size + 1)) - return -ENOMEM; - - return 0; -} - -static int dispatch_rqueue(sd_rtnl *rtnl, sd_rtnl_message **message) { - int r; - - assert(rtnl); - assert(message); - - if (rtnl->rqueue_size <= 0) { - /* Try to read a new message */ - r = socket_read_message(rtnl); - if (r <= 0) - return r; - } - - /* Dispatch a queued message */ - *message = rtnl->rqueue[0]; - rtnl->rqueue_size --; - memmove(rtnl->rqueue, rtnl->rqueue + 1, sizeof(sd_rtnl_message*) * rtnl->rqueue_size); - - return 1; -} - -static int dispatch_wqueue(sd_rtnl *rtnl) { - int r, ret = 0; - - assert(rtnl); - - while (rtnl->wqueue_size > 0) { - r = socket_write_message(rtnl, rtnl->wqueue[0]); - if (r < 0) - return r; - else if (r == 0) - /* Didn't do anything this time */ - return ret; - else { - /* see equivalent in sd-bus.c */ - sd_rtnl_message_unref(rtnl->wqueue[0]); - rtnl->wqueue_size --; - memmove(rtnl->wqueue, rtnl->wqueue + 1, sizeof(sd_rtnl_message*) * rtnl->wqueue_size); - - ret = 1; - } - } - - return ret; -} - -static int process_timeout(sd_rtnl *rtnl) { - _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL; - struct reply_callback *c; - usec_t n; - int r; - - assert(rtnl); - - c = prioq_peek(rtnl->reply_callbacks_prioq); - if (!c) - return 0; - - n = now(CLOCK_MONOTONIC); - if (c->timeout > n) - return 0; - - r = rtnl_message_new_synthetic_error(-ETIMEDOUT, c->serial, &m); - if (r < 0) - return r; - - assert_se(prioq_pop(rtnl->reply_callbacks_prioq) == c); - hashmap_remove(rtnl->reply_callbacks, &c->serial); - - r = c->callback(rtnl, m, c->userdata); - if (r < 0) - log_debug_errno(r, "sd-rtnl: timedout callback failed: %m"); - - free(c); - - return 1; -} - -static int process_reply(sd_rtnl *rtnl, sd_rtnl_message *m) { - _cleanup_free_ struct reply_callback *c = NULL; - uint64_t serial; - uint16_t type; - int r; - - assert(rtnl); - assert(m); - - serial = rtnl_message_get_serial(m); - c = hashmap_remove(rtnl->reply_callbacks, &serial); - if (!c) - return 0; - - if (c->timeout != 0) - prioq_remove(rtnl->reply_callbacks_prioq, c, &c->prioq_idx); - - r = sd_rtnl_message_get_type(m, &type); - if (r < 0) - return 0; - - if (type == NLMSG_DONE) - m = NULL; - - r = c->callback(rtnl, m, c->userdata); - if (r < 0) - log_debug_errno(r, "sd-rtnl: callback failed: %m"); - - return 1; -} - -static int process_match(sd_rtnl *rtnl, sd_rtnl_message *m) { - struct match_callback *c; - uint16_t type; - int r; - - assert(rtnl); - assert(m); - - r = sd_rtnl_message_get_type(m, &type); - if (r < 0) - return r; - - LIST_FOREACH(match_callbacks, c, rtnl->match_callbacks) { - if (type == c->type) { - r = c->callback(rtnl, m, c->userdata); - if (r != 0) { - if (r < 0) - log_debug_errno(r, "sd-rtnl: match callback failed: %m"); - - break; - } - } - } - - return 1; -} - -static int process_running(sd_rtnl *rtnl, sd_rtnl_message **ret) { - _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL; - int r; - - assert(rtnl); - - r = process_timeout(rtnl); - if (r != 0) - goto null_message; - - r = dispatch_wqueue(rtnl); - if (r != 0) - goto null_message; - - r = dispatch_rqueue(rtnl, &m); - if (r < 0) - return r; - if (!m) - goto null_message; - - if (sd_rtnl_message_is_broadcast(m)) { - r = process_match(rtnl, m); - if (r != 0) - goto null_message; - } else { - r = process_reply(rtnl, m); - if (r != 0) - goto null_message; - } - - if (ret) { - *ret = m; - m = NULL; - - return 1; - } - - return 1; - -null_message: - if (r >= 0 && ret) - *ret = NULL; - - return r; -} - -int sd_rtnl_process(sd_rtnl *rtnl, sd_rtnl_message **ret) { - RTNL_DONT_DESTROY(rtnl); - int r; - - assert_return(rtnl, -EINVAL); - assert_return(!rtnl_pid_changed(rtnl), -ECHILD); - assert_return(!rtnl->processing, -EBUSY); - - rtnl->processing = true; - r = process_running(rtnl, ret); - rtnl->processing = false; - - return r; -} - -static usec_t calc_elapse(uint64_t usec) { - if (usec == (uint64_t) -1) - return 0; - - if (usec == 0) - usec = RTNL_DEFAULT_TIMEOUT; - - return now(CLOCK_MONOTONIC) + usec; -} - -static int rtnl_poll(sd_rtnl *rtnl, bool need_more, uint64_t timeout_usec) { - struct pollfd p[1] = {}; - struct timespec ts; - usec_t m = USEC_INFINITY; - int r, e; - - assert(rtnl); - - e = sd_rtnl_get_events(rtnl); - if (e < 0) - return e; - - if (need_more) - /* Caller wants more data, and doesn't care about - * what's been read or any other timeouts. */ - e |= POLLIN; - else { - usec_t until; - /* Caller wants to process if there is something to - * process, but doesn't care otherwise */ - - r = sd_rtnl_get_timeout(rtnl, &until); - if (r < 0) - return r; - if (r > 0) { - usec_t nw; - nw = now(CLOCK_MONOTONIC); - m = until > nw ? until - nw : 0; - } - } - - if (timeout_usec != (uint64_t) -1 && (m == (uint64_t) -1 || timeout_usec < m)) - m = timeout_usec; - - p[0].fd = rtnl->fd; - p[0].events = e; - - r = ppoll(p, 1, m == (uint64_t) -1 ? NULL : timespec_store(&ts, m), NULL); - if (r < 0) - return -errno; - - return r > 0 ? 1 : 0; -} - -int sd_rtnl_wait(sd_rtnl *nl, uint64_t timeout_usec) { - assert_return(nl, -EINVAL); - assert_return(!rtnl_pid_changed(nl), -ECHILD); - - if (nl->rqueue_size > 0) - return 0; - - return rtnl_poll(nl, false, timeout_usec); -} - -static int timeout_compare(const void *a, const void *b) { - const struct reply_callback *x = a, *y = b; - - if (x->timeout != 0 && y->timeout == 0) - return -1; - - if (x->timeout == 0 && y->timeout != 0) - return 1; - - if (x->timeout < y->timeout) - return -1; - - if (x->timeout > y->timeout) - return 1; - - return 0; -} - -int sd_rtnl_call_async(sd_rtnl *nl, - sd_rtnl_message *m, - sd_rtnl_message_handler_t callback, - void *userdata, - uint64_t usec, - uint32_t *serial) { - struct reply_callback *c; - uint32_t s; - int r, k; - - assert_return(nl, -EINVAL); - assert_return(m, -EINVAL); - assert_return(callback, -EINVAL); - assert_return(!rtnl_pid_changed(nl), -ECHILD); - - r = hashmap_ensure_allocated(&nl->reply_callbacks, &uint64_hash_ops); - if (r < 0) - return r; - - if (usec != (uint64_t) -1) { - r = prioq_ensure_allocated(&nl->reply_callbacks_prioq, timeout_compare); - if (r < 0) - return r; - } - - c = new0(struct reply_callback, 1); - if (!c) - return -ENOMEM; - - c->callback = callback; - c->userdata = userdata; - c->timeout = calc_elapse(usec); - - k = sd_rtnl_send(nl, m, &s); - if (k < 0) { - free(c); - return k; - } - - c->serial = s; - - r = hashmap_put(nl->reply_callbacks, &c->serial, c); - if (r < 0) { - free(c); - return r; - } - - if (c->timeout != 0) { - r = prioq_put(nl->reply_callbacks_prioq, c, &c->prioq_idx); - if (r > 0) { - c->timeout = 0; - sd_rtnl_call_async_cancel(nl, c->serial); - return r; - } - } - - if (serial) - *serial = s; - - return k; -} - -int sd_rtnl_call_async_cancel(sd_rtnl *nl, uint32_t serial) { - struct reply_callback *c; - uint64_t s = serial; - - assert_return(nl, -EINVAL); - assert_return(serial != 0, -EINVAL); - assert_return(!rtnl_pid_changed(nl), -ECHILD); - - c = hashmap_remove(nl->reply_callbacks, &s); - if (!c) - return 0; - - if (c->timeout != 0) - prioq_remove(nl->reply_callbacks_prioq, c, &c->prioq_idx); - - free(c); - return 1; -} - -int sd_rtnl_call(sd_rtnl *rtnl, - sd_rtnl_message *message, - uint64_t usec, - sd_rtnl_message **ret) { - usec_t timeout; - uint32_t serial; - int r; - - assert_return(rtnl, -EINVAL); - assert_return(!rtnl_pid_changed(rtnl), -ECHILD); - assert_return(message, -EINVAL); - - r = sd_rtnl_send(rtnl, message, &serial); - if (r < 0) - return r; - - timeout = calc_elapse(usec); - - for (;;) { - usec_t left; - unsigned i; - - for (i = 0; i < rtnl->rqueue_size; i++) { - uint32_t received_serial; - - received_serial = rtnl_message_get_serial(rtnl->rqueue[i]); - - if (received_serial == serial) { - _cleanup_rtnl_message_unref_ sd_rtnl_message *incoming = NULL; - uint16_t type; - - incoming = rtnl->rqueue[i]; - - /* found a match, remove from rqueue and return it */ - memmove(rtnl->rqueue + i,rtnl->rqueue + i + 1, - sizeof(sd_rtnl_message*) * (rtnl->rqueue_size - i - 1)); - rtnl->rqueue_size--; - - r = sd_rtnl_message_get_errno(incoming); - if (r < 0) - return r; - - r = sd_rtnl_message_get_type(incoming, &type); - if (r < 0) - return r; - - if (type == NLMSG_DONE) { - *ret = NULL; - return 0; - } - - if (ret) { - *ret = incoming; - incoming = NULL; - } - - return 1; - } - } - - r = socket_read_message(rtnl); - if (r < 0) - return r; - if (r > 0) - /* received message, so try to process straight away */ - continue; - - if (timeout > 0) { - usec_t n; - - n = now(CLOCK_MONOTONIC); - if (n >= timeout) - return -ETIMEDOUT; - - left = timeout - n; - } else - left = (uint64_t) -1; - - r = rtnl_poll(rtnl, true, left); - if (r < 0) - return r; - else if (r == 0) - return -ETIMEDOUT; - - r = dispatch_wqueue(rtnl); - if (r < 0) - return r; - } -} - -int sd_rtnl_flush(sd_rtnl *rtnl) { - int r; - - assert_return(rtnl, -EINVAL); - assert_return(!rtnl_pid_changed(rtnl), -ECHILD); - - if (rtnl->wqueue_size <= 0) - return 0; - - for (;;) { - r = dispatch_wqueue(rtnl); - if (r < 0) - return r; - - if (rtnl->wqueue_size <= 0) - return 0; - - r = rtnl_poll(rtnl, false, (uint64_t) -1); - if (r < 0) - return r; - } -} - -int sd_rtnl_get_events(sd_rtnl *rtnl) { - int flags = 0; - - assert_return(rtnl, -EINVAL); - assert_return(!rtnl_pid_changed(rtnl), -ECHILD); - - if (rtnl->rqueue_size <= 0) - flags |= POLLIN; - if (rtnl->wqueue_size > 0) - flags |= POLLOUT; - - return flags; -} - -int sd_rtnl_get_timeout(sd_rtnl *rtnl, uint64_t *timeout_usec) { - struct reply_callback *c; - - assert_return(rtnl, -EINVAL); - assert_return(timeout_usec, -EINVAL); - assert_return(!rtnl_pid_changed(rtnl), -ECHILD); - - if (rtnl->rqueue_size > 0) { - *timeout_usec = 0; - return 1; - } - - c = prioq_peek(rtnl->reply_callbacks_prioq); - if (!c) { - *timeout_usec = (uint64_t) -1; - return 0; - } - - *timeout_usec = c->timeout; - - return 1; -} - -static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) { - sd_rtnl *rtnl = userdata; - int r; - - assert(rtnl); - - r = sd_rtnl_process(rtnl, NULL); - if (r < 0) - return r; - - return 1; -} - -static int time_callback(sd_event_source *s, uint64_t usec, void *userdata) { - sd_rtnl *rtnl = userdata; - int r; - - assert(rtnl); - - r = sd_rtnl_process(rtnl, NULL); - if (r < 0) - return r; - - return 1; -} - -static int prepare_callback(sd_event_source *s, void *userdata) { - sd_rtnl *rtnl = userdata; - int r, e; - usec_t until; - - assert(s); - assert(rtnl); - - e = sd_rtnl_get_events(rtnl); - if (e < 0) - return e; - - r = sd_event_source_set_io_events(rtnl->io_event_source, e); - if (r < 0) - return r; - - r = sd_rtnl_get_timeout(rtnl, &until); - if (r < 0) - return r; - if (r > 0) { - int j; - - j = sd_event_source_set_time(rtnl->time_event_source, until); - if (j < 0) - return j; - } - - r = sd_event_source_set_enabled(rtnl->time_event_source, r > 0); - if (r < 0) - return r; - - return 1; -} - -static int exit_callback(sd_event_source *event, void *userdata) { - sd_rtnl *rtnl = userdata; - - assert(event); - - sd_rtnl_flush(rtnl); - - return 1; -} - -int sd_rtnl_attach_event(sd_rtnl *rtnl, sd_event *event, int priority) { - int r; - - assert_return(rtnl, -EINVAL); - assert_return(!rtnl->event, -EBUSY); - - assert(!rtnl->io_event_source); - assert(!rtnl->time_event_source); - - if (event) - rtnl->event = sd_event_ref(event); - else { - r = sd_event_default(&rtnl->event); - if (r < 0) - return r; - } - - r = sd_event_add_io(rtnl->event, &rtnl->io_event_source, rtnl->fd, 0, io_callback, rtnl); - if (r < 0) - goto fail; - - r = sd_event_source_set_priority(rtnl->io_event_source, priority); - if (r < 0) - goto fail; - - r = sd_event_source_set_description(rtnl->io_event_source, "rtnl-receive-message"); - if (r < 0) - goto fail; - - r = sd_event_source_set_prepare(rtnl->io_event_source, prepare_callback); - if (r < 0) - goto fail; - - r = sd_event_add_time(rtnl->event, &rtnl->time_event_source, CLOCK_MONOTONIC, 0, 0, time_callback, rtnl); - if (r < 0) - goto fail; - - r = sd_event_source_set_priority(rtnl->time_event_source, priority); - if (r < 0) - goto fail; - - r = sd_event_source_set_description(rtnl->time_event_source, "rtnl-timer"); - if (r < 0) - goto fail; - - r = sd_event_add_exit(rtnl->event, &rtnl->exit_event_source, exit_callback, rtnl); - if (r < 0) - goto fail; - - r = sd_event_source_set_description(rtnl->exit_event_source, "rtnl-exit"); - if (r < 0) - goto fail; - - return 0; - -fail: - sd_rtnl_detach_event(rtnl); - return r; -} - -int sd_rtnl_detach_event(sd_rtnl *rtnl) { - assert_return(rtnl, -EINVAL); - assert_return(rtnl->event, -ENXIO); - - if (rtnl->io_event_source) - rtnl->io_event_source = sd_event_source_unref(rtnl->io_event_source); - - if (rtnl->time_event_source) - rtnl->time_event_source = sd_event_source_unref(rtnl->time_event_source); - - if (rtnl->exit_event_source) - rtnl->exit_event_source = sd_event_source_unref(rtnl->exit_event_source); - - if (rtnl->event) - rtnl->event = sd_event_unref(rtnl->event); - - return 0; -} - -int sd_rtnl_add_match(sd_rtnl *rtnl, - uint16_t type, - sd_rtnl_message_handler_t callback, - void *userdata) { - _cleanup_free_ struct match_callback *c = NULL; - int r; - - assert_return(rtnl, -EINVAL); - assert_return(callback, -EINVAL); - assert_return(!rtnl_pid_changed(rtnl), -ECHILD); - - c = new0(struct match_callback, 1); - if (!c) - return -ENOMEM; - - c->callback = callback; - c->type = type; - c->userdata = userdata; - - switch (type) { - case RTM_NEWLINK: - case RTM_SETLINK: - case RTM_GETLINK: - case RTM_DELLINK: - r = rtnl_join_broadcast_group(rtnl, RTNLGRP_LINK); - if (r < 0) - return r; - - break; - case RTM_NEWADDR: - case RTM_GETADDR: - case RTM_DELADDR: - r = rtnl_join_broadcast_group(rtnl, RTNLGRP_IPV4_IFADDR); - if (r < 0) - return r; - - r = rtnl_join_broadcast_group(rtnl, RTNLGRP_IPV6_IFADDR); - if (r < 0) - return r; - - break; - default: - return -EOPNOTSUPP; - } - - LIST_PREPEND(match_callbacks, rtnl->match_callbacks, c); - - c = NULL; - - return 0; -} - -int sd_rtnl_remove_match(sd_rtnl *rtnl, - uint16_t type, - sd_rtnl_message_handler_t callback, - void *userdata) { - struct match_callback *c; - - assert_return(rtnl, -EINVAL); - assert_return(callback, -EINVAL); - assert_return(!rtnl_pid_changed(rtnl), -ECHILD); - - /* we should unsubscribe from the broadcast groups at this point, but it is not so - trivial for a few reasons: the refcounting is a bit of a mess and not obvious - how it will look like after we add genetlink support, and it is also not possible - to query what broadcast groups were subscribed to when we inherit the socket to get - the initial refcount. The latter could indeed be done for the first 32 broadcast - groups (which incidentally is all we currently support in .socket units anyway), - but we better not rely on only ever using 32 groups. */ - LIST_FOREACH(match_callbacks, c, rtnl->match_callbacks) - if (c->callback == callback && c->type == type && c->userdata == userdata) { - LIST_REMOVE(match_callbacks, rtnl->match_callbacks, c); - free(c); - - return 1; - } - - return 0; -} diff --git a/src/libelogind/sd-rtnl/test-rtnl.c b/src/libelogind/sd-rtnl/test-rtnl.c deleted file mode 100644 index 94b1cb7c7..000000000 --- a/src/libelogind/sd-rtnl/test-rtnl.c +++ /dev/null @@ -1,443 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2013 Tom Gundersen - - 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 . -***/ - -#include -#include - -#include "util.h" -#include "macro.h" -#include "sd-rtnl.h" -#include "socket-util.h" -#include "rtnl-util.h" -#include "event-util.h" -#include "missing.h" - -static void test_message_link_bridge(sd_rtnl *rtnl) { - _cleanup_rtnl_message_unref_ sd_rtnl_message *message = NULL; - uint32_t cost; - - assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_NEWLINK, 1) >= 0); - assert_se(sd_rtnl_message_link_set_family(message, PF_BRIDGE) >= 0); - assert_se(sd_rtnl_message_open_container(message, IFLA_PROTINFO) >= 0); - assert_se(sd_rtnl_message_append_u32(message, IFLA_BRPORT_COST, 10) >= 0); - assert_se(sd_rtnl_message_close_container(message) >= 0); - - assert_se(sd_rtnl_message_rewind(message) >= 0); - - assert_se(sd_rtnl_message_enter_container(message, IFLA_PROTINFO) >= 0); - assert_se(sd_rtnl_message_read_u32(message, IFLA_BRPORT_COST, &cost) >= 0); - assert_se(cost == 10); - assert_se(sd_rtnl_message_exit_container(message) >= 0); -} - -static void test_link_configure(sd_rtnl *rtnl, int ifindex) { - _cleanup_rtnl_message_unref_ sd_rtnl_message *message = NULL; - const char *mac = "98:fe:94:3f:c6:18", *name = "test"; - char buffer[ETHER_ADDR_TO_STRING_MAX]; - unsigned int mtu = 1450, mtu_out; - const char *name_out; - struct ether_addr mac_out; - - /* we'd really like to test NEWLINK, but let's not mess with the running kernel */ - assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_GETLINK, ifindex) >= 0); - assert_se(sd_rtnl_message_append_string(message, IFLA_IFNAME, name) >= 0); - assert_se(sd_rtnl_message_append_ether_addr(message, IFLA_ADDRESS, ether_aton(mac)) >= 0); - assert_se(sd_rtnl_message_append_u32(message, IFLA_MTU, mtu) >= 0); - - assert_se(sd_rtnl_call(rtnl, message, 0, NULL) == 1); - assert_se(sd_rtnl_message_rewind(message) >= 0); - - assert_se(sd_rtnl_message_read_string(message, IFLA_IFNAME, &name_out) >= 0); - assert_se(streq(name, name_out)); - - assert_se(sd_rtnl_message_read_ether_addr(message, IFLA_ADDRESS, &mac_out) >= 0); - assert_se(streq(mac, ether_addr_to_string(&mac_out, buffer))); - - assert_se(sd_rtnl_message_read_u32(message, IFLA_MTU, &mtu_out) >= 0); - assert_se(mtu == mtu_out); -} - -static void test_link_get(sd_rtnl *rtnl, int ifindex) { - sd_rtnl_message *m; - sd_rtnl_message *r; - unsigned int mtu = 1500; - const char *str_data; - uint8_t u8_data; - uint32_t u32_data; - struct ether_addr eth_data; - - assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0); - assert_se(m); - - /* u8 test cases */ - assert_se(sd_rtnl_message_append_u8(m, IFLA_CARRIER, 0) >= 0); - assert_se(sd_rtnl_message_append_u8(m, IFLA_OPERSTATE, 0) >= 0); - assert_se(sd_rtnl_message_append_u8(m, IFLA_LINKMODE, 0) >= 0); - - /* u32 test cases */ - assert_se(sd_rtnl_message_append_u32(m, IFLA_MTU, mtu) >= 0); - assert_se(sd_rtnl_message_append_u32(m, IFLA_GROUP, 0) >= 0); - assert_se(sd_rtnl_message_append_u32(m, IFLA_TXQLEN, 0) >= 0); - assert_se(sd_rtnl_message_append_u32(m, IFLA_NUM_TX_QUEUES, 0) >= 0); - assert_se(sd_rtnl_message_append_u32(m, IFLA_NUM_RX_QUEUES, 0) >= 0); - - assert_se(sd_rtnl_call(rtnl, m, -1, &r) == 1); - - assert_se(sd_rtnl_message_read_string(r, IFLA_IFNAME, &str_data) == 0); - - assert_se(sd_rtnl_message_read_u8(r, IFLA_CARRIER, &u8_data) == 0); - assert_se(sd_rtnl_message_read_u8(r, IFLA_OPERSTATE, &u8_data) == 0); - assert_se(sd_rtnl_message_read_u8(r, IFLA_LINKMODE, &u8_data) == 0); - - assert_se(sd_rtnl_message_read_u32(r, IFLA_MTU, &u32_data) == 0); - assert_se(sd_rtnl_message_read_u32(r, IFLA_GROUP, &u32_data) == 0); - assert_se(sd_rtnl_message_read_u32(r, IFLA_TXQLEN, &u32_data) == 0); - assert_se(sd_rtnl_message_read_u32(r, IFLA_NUM_TX_QUEUES, &u32_data) == 0); - assert_se(sd_rtnl_message_read_u32(r, IFLA_NUM_RX_QUEUES, &u32_data) == 0); - - assert_se(sd_rtnl_message_read_ether_addr(r, IFLA_ADDRESS, ð_data) == 0); - - assert_se(sd_rtnl_flush(rtnl) >= 0); - assert_se((m = sd_rtnl_message_unref(m)) == NULL); - assert_se((r = sd_rtnl_message_unref(r)) == NULL); -} - - -static void test_address_get(sd_rtnl *rtnl, int ifindex) { - sd_rtnl_message *m; - sd_rtnl_message *r; - struct in_addr in_data; - struct ifa_cacheinfo cache; - const char *label; - - assert_se(sd_rtnl_message_new_addr(rtnl, &m, RTM_GETADDR, ifindex, AF_INET) >= 0); - assert_se(m); - - assert_se(sd_rtnl_call(rtnl, m, -1, &r) == 1); - - assert_se(sd_rtnl_message_read_in_addr(r, IFA_LOCAL, &in_data) == 0); - assert_se(sd_rtnl_message_read_in_addr(r, IFA_ADDRESS, &in_data) == 0); - assert_se(sd_rtnl_message_read_string(r, IFA_LABEL, &label) == 0); - assert_se(sd_rtnl_message_read_cache_info(r, IFA_CACHEINFO, &cache) == 0); - - assert_se(sd_rtnl_flush(rtnl) >= 0); - assert_se((m = sd_rtnl_message_unref(m)) == NULL); - assert_se((r = sd_rtnl_message_unref(r)) == NULL); - -} - -static void test_route(void) { - _cleanup_rtnl_message_unref_ sd_rtnl_message *req; - struct in_addr addr, addr_data; - uint32_t index = 2, u32_data; - int r; - - r = sd_rtnl_message_new_route(NULL, &req, RTM_NEWROUTE, AF_INET, RTPROT_STATIC); - if (r < 0) { - log_error_errno(r, "Could not create RTM_NEWROUTE message: %m"); - return; - } - - addr.s_addr = htonl(INADDR_LOOPBACK); - - r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &addr); - if (r < 0) { - log_error_errno(r, "Could not append RTA_GATEWAY attribute: %m"); - return; - } - - r = sd_rtnl_message_append_u32(req, RTA_OIF, index); - if (r < 0) { - log_error_errno(r, "Could not append RTA_OIF attribute: %m"); - return; - } - - assert_se(sd_rtnl_message_rewind(req) >= 0); - - assert_se(sd_rtnl_message_read_in_addr(req, RTA_GATEWAY, &addr_data) >= 0); - assert_se(addr_data.s_addr == addr.s_addr); - - assert_se(sd_rtnl_message_read_u32(req, RTA_OIF, &u32_data) >= 0); - assert_se(u32_data == index); - - assert_se((req = sd_rtnl_message_unref(req)) == NULL); -} - -static void test_multiple(void) { - sd_rtnl *rtnl1, *rtnl2; - - assert_se(sd_rtnl_open(&rtnl1) >= 0); - assert_se(sd_rtnl_open(&rtnl2) >= 0); - - rtnl1 = sd_rtnl_unref(rtnl1); - rtnl2 = sd_rtnl_unref(rtnl2); -} - -static int link_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) { - char *ifname = userdata; - const char *data; - - assert_se(rtnl); - assert_se(m); - - log_info("got link info about %s", ifname); - free(ifname); - - assert_se(sd_rtnl_message_read_string(m, IFLA_IFNAME, &data) >= 0); - assert_se(streq(data, "lo")); - - return 1; -} - -static void test_event_loop(int ifindex) { - _cleanup_event_unref_ sd_event *event = NULL; - _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL; - _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL; - char *ifname; - - ifname = strdup("lo2"); - assert_se(ifname); - - assert_se(sd_rtnl_open(&rtnl) >= 0); - assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0); - - assert_se(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, NULL) >= 0); - - assert_se(sd_event_default(&event) >= 0); - - assert_se(sd_rtnl_attach_event(rtnl, event, 0) >= 0); - - assert_se(sd_event_run(event, 0) >= 0); - - assert_se(sd_rtnl_detach_event(rtnl) >= 0); - - assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL); -} - -static int pipe_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) { - int *counter = userdata; - int r; - - (*counter) --; - - r = sd_rtnl_message_get_errno(m); - - log_info_errno(r, "%d left in pipe. got reply: %m", *counter); - - assert_se(r >= 0); - - return 1; -} - -static void test_async(int ifindex) { - _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL; - _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL, *r = NULL; - uint32_t serial; - char *ifname; - - ifname = strdup("lo"); - assert_se(ifname); - - assert_se(sd_rtnl_open(&rtnl) >= 0); - - assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0); - - assert_se(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, &serial) >= 0); - - assert_se(sd_rtnl_wait(rtnl, 0) >= 0); - assert_se(sd_rtnl_process(rtnl, &r) >= 0); - - assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL); -} - -static void test_pipe(int ifindex) { - _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL; - _cleanup_rtnl_message_unref_ sd_rtnl_message *m1 = NULL, *m2 = NULL; - int counter = 0; - - assert_se(sd_rtnl_open(&rtnl) >= 0); - - assert_se(sd_rtnl_message_new_link(rtnl, &m1, RTM_GETLINK, ifindex) >= 0); - assert_se(sd_rtnl_message_new_link(rtnl, &m2, RTM_GETLINK, ifindex) >= 0); - - counter ++; - assert_se(sd_rtnl_call_async(rtnl, m1, &pipe_handler, &counter, 0, NULL) >= 0); - - counter ++; - assert_se(sd_rtnl_call_async(rtnl, m2, &pipe_handler, &counter, 0, NULL) >= 0); - - while (counter > 0) { - assert_se(sd_rtnl_wait(rtnl, 0) >= 0); - assert_se(sd_rtnl_process(rtnl, NULL) >= 0); - } - - assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL); -} - -static void test_container(void) { - _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL; - uint16_t u16_data; - uint32_t u32_data; - const char *string_data; - - assert_se(sd_rtnl_message_new_link(NULL, &m, RTM_NEWLINK, 0) >= 0); - - assert_se(sd_rtnl_message_open_container(m, IFLA_LINKINFO) >= 0); - assert_se(sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA, "vlan") >= 0); - assert_se(sd_rtnl_message_append_u16(m, IFLA_VLAN_ID, 100) >= 0); - assert_se(sd_rtnl_message_close_container(m) >= 0); - assert_se(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "vlan") >= 0); - assert_se(sd_rtnl_message_close_container(m) >= 0); - assert_se(sd_rtnl_message_close_container(m) == -EINVAL); - - assert_se(sd_rtnl_message_rewind(m) >= 0); - - assert_se(sd_rtnl_message_enter_container(m, IFLA_LINKINFO) >= 0); - assert_se(sd_rtnl_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0); - assert_se(streq("vlan", string_data)); - - assert_se(sd_rtnl_message_enter_container(m, IFLA_INFO_DATA) >= 0); - assert_se(sd_rtnl_message_read_u16(m, IFLA_VLAN_ID, &u16_data) >= 0); - assert_se(sd_rtnl_message_exit_container(m) >= 0); - - assert_se(sd_rtnl_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0); - assert_se(streq("vlan", string_data)); - assert_se(sd_rtnl_message_exit_container(m) >= 0); - - assert_se(sd_rtnl_message_read_u32(m, IFLA_LINKINFO, &u32_data) < 0); - - assert_se(sd_rtnl_message_exit_container(m) == -EINVAL); -} - -static void test_match(void) { - _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL; - - assert_se(sd_rtnl_open(&rtnl) >= 0); - - assert_se(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0); - assert_se(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0); - - assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1); - assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1); - assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 0); - - assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL); -} - -static void test_get_addresses(sd_rtnl *rtnl) { - _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL; - sd_rtnl_message *m; - - assert_se(sd_rtnl_message_new_addr(rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC) >= 0); - - assert_se(sd_rtnl_call(rtnl, req, 0, &reply) >= 0); - - for (m = reply; m; m = sd_rtnl_message_next(m)) { - uint16_t type; - unsigned char scope, flags; - int family, ifindex; - - assert_se(sd_rtnl_message_get_type(m, &type) >= 0); - assert_se(type == RTM_NEWADDR); - - assert_se(sd_rtnl_message_addr_get_ifindex(m, &ifindex) >= 0); - assert_se(sd_rtnl_message_addr_get_family(m, &family) >= 0); - assert_se(sd_rtnl_message_addr_get_scope(m, &scope) >= 0); - assert_se(sd_rtnl_message_addr_get_flags(m, &flags) >= 0); - - assert_se(ifindex > 0); - assert_se(family == AF_INET || family == AF_INET6); - - log_info("got IPv%u address on ifindex %i", family == AF_INET ? 4: 6, ifindex); - } -} - -static void test_message(void) { - _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL; - - assert_se(rtnl_message_new_synthetic_error(-ETIMEDOUT, 1, &m) >= 0); - assert_se(sd_rtnl_message_get_errno(m) == -ETIMEDOUT); -} - -int main(void) { - sd_rtnl *rtnl; - sd_rtnl_message *m; - sd_rtnl_message *r; - const char *string_data; - int if_loopback; - uint16_t type; - - test_message(); - - test_match(); - - test_multiple(); - - test_route(); - - test_container(); - - assert_se(sd_rtnl_open(&rtnl) >= 0); - assert_se(rtnl); - - if_loopback = (int) if_nametoindex("lo"); - assert_se(if_loopback > 0); - - test_async(if_loopback); - - test_pipe(if_loopback); - - test_event_loop(if_loopback); - - test_link_configure(rtnl, if_loopback); - - test_get_addresses(rtnl); - - test_message_link_bridge(rtnl); - - assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, if_loopback) >= 0); - assert_se(m); - - assert_se(sd_rtnl_message_get_type(m, &type) >= 0); - assert_se(type == RTM_GETLINK); - - assert_se(sd_rtnl_message_read_string(m, IFLA_IFNAME, &string_data) == -EPERM); - - assert_se(sd_rtnl_call(rtnl, m, 0, &r) == 1); - assert_se(sd_rtnl_message_get_type(r, &type) >= 0); - assert_se(type == RTM_NEWLINK); - - assert_se((r = sd_rtnl_message_unref(r)) == NULL); - - assert_se(sd_rtnl_call(rtnl, m, -1, &r) == -EPERM); - assert_se((m = sd_rtnl_message_unref(m)) == NULL); - assert_se((r = sd_rtnl_message_unref(r)) == NULL); - - test_link_get(rtnl, if_loopback); - test_address_get(rtnl, if_loopback); - - assert_se(sd_rtnl_flush(rtnl) >= 0); - assert_se((m = sd_rtnl_message_unref(m)) == NULL); - assert_se((r = sd_rtnl_message_unref(r)) == NULL); - assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL); - - return EXIT_SUCCESS; -} diff --git a/src/libsystemd/sd-device/device-enumerator-private.h b/src/libsystemd/sd-device/device-enumerator-private.h deleted file mode 100644 index adc5af795..000000000 --- a/src/libsystemd/sd-device/device-enumerator-private.h +++ /dev/null @@ -1,40 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -#pragma once - -/*** - This file is part of systemd. - - Copyright 2015 Tom Gundersen - - 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 . -***/ - -#include "libudev-private.h" -#include "sd-device.h" - -int device_enumerator_scan_devices(sd_device_enumerator *enumeartor); -int device_enumerator_scan_subsystems(sd_device_enumerator *enumeartor); -int device_enumerator_add_device(sd_device_enumerator *enumerator, sd_device *device); -int device_enumerator_add_match_is_initialized(sd_device_enumerator *enumerator); -sd_device *device_enumerator_get_first(sd_device_enumerator *enumerator); -sd_device *device_enumerator_get_next(sd_device_enumerator *enumerator); - bool properties_read:1; - bool tags_read:1; - bool devlinks_read:1; - -#define FOREACH_DEVICE_AND_SUBSYSTEM(enumerator, device) \ - for (device = device_enumerator_get_first(enumerator); \ - device; \ - device = device_enumerator_get_next(enumerator)) diff --git a/src/libsystemd/sd-device/device-enumerator.c b/src/libsystemd/sd-device/device-enumerator.c deleted file mode 100644 index 5c4bd780e..000000000 --- a/src/libsystemd/sd-device/device-enumerator.c +++ /dev/null @@ -1,990 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2008-2012 Kay Sievers - Copyright 2014-2015 Tom Gundersen - - 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 . -***/ - -#include "util.h" -#include "prioq.h" -#include "strv.h" -#include "set.h" - -#include "sd-device.h" - -#include "device-util.h" -#include "device-enumerator-private.h" - -#define DEVICE_ENUMERATE_MAX_DEPTH 256 - -typedef enum DeviceEnumerationType { - DEVICE_ENUMERATION_TYPE_DEVICES, - DEVICE_ENUMERATION_TYPE_SUBSYSTEMS, - _DEVICE_ENUMERATION_TYPE_MAX, - _DEVICE_ENUMERATION_TYPE_INVALID = -1, -} DeviceEnumerationType; - -struct sd_device_enumerator { - unsigned n_ref; - - DeviceEnumerationType type; - Prioq *devices; - bool scan_uptodate; - - Set *match_subsystem; - Set *nomatch_subsystem; - Hashmap *match_sysattr; - Hashmap *nomatch_sysattr; - Hashmap *match_property; - Set *match_sysname; - Set *match_tag; - sd_device *match_parent; - bool match_allow_uninitialized; -}; - -_public_ int sd_device_enumerator_new(sd_device_enumerator **ret) { - _cleanup_device_enumerator_unref_ sd_device_enumerator *enumerator = NULL; - - assert(ret); - - enumerator = new0(sd_device_enumerator, 1); - if (!enumerator) - return -ENOMEM; - - enumerator->n_ref = 1; - enumerator->type = _DEVICE_ENUMERATION_TYPE_INVALID; - - *ret = enumerator; - enumerator = NULL; - - return 0; -} - -_public_ sd_device_enumerator *sd_device_enumerator_ref(sd_device_enumerator *enumerator) { - assert_return(enumerator, NULL); - - assert_se((++ enumerator->n_ref) >= 2); - - return enumerator; -} - -_public_ sd_device_enumerator *sd_device_enumerator_unref(sd_device_enumerator *enumerator) { - if (enumerator && (-- enumerator->n_ref) == 0) { - sd_device *device; - - while ((device = prioq_pop(enumerator->devices))) - sd_device_unref(device); - - prioq_free(enumerator->devices); - - set_free_free(enumerator->match_subsystem); - set_free_free(enumerator->nomatch_subsystem); - hashmap_free_free_free(enumerator->match_sysattr); - hashmap_free_free_free(enumerator->nomatch_sysattr); - hashmap_free_free_free(enumerator->match_property); - set_free_free(enumerator->match_sysname); - set_free_free(enumerator->match_tag); - sd_device_unref(enumerator->match_parent); - - free(enumerator); - } - - return NULL; -} - -_public_ int sd_device_enumerator_add_match_subsystem(sd_device_enumerator *enumerator, const char *subsystem, int match) { - Set **set; - int r; - - assert_return(enumerator, -EINVAL); - assert_return(subsystem, -EINVAL); - - if (match) - set = &enumerator->match_subsystem; - else - set = &enumerator->nomatch_subsystem; - - r = set_ensure_allocated(set, NULL); - if (r < 0) - return r; - - r = set_put_strdup(*set, subsystem); - if (r < 0) - return r; - - enumerator->scan_uptodate = false; - - return 0; -} - -_public_ int sd_device_enumerator_add_match_sysattr(sd_device_enumerator *enumerator, const char *_sysattr, const char *_value, int match) { - _cleanup_free_ char *sysattr = NULL, *value = NULL; - Hashmap **hashmap; - int r; - - assert_return(enumerator, -EINVAL); - assert_return(_sysattr, -EINVAL); - - if (match) - hashmap = &enumerator->match_sysattr; - else - hashmap = &enumerator->nomatch_sysattr; - - r = hashmap_ensure_allocated(hashmap, NULL); - if (r < 0) - return r; - - sysattr = strdup(_sysattr); - if (!sysattr) - return -ENOMEM; - - if (_value) { - value = strdup(_value); - if (!value) - return -ENOMEM; - } - - r = hashmap_put(*hashmap, sysattr, value); - if (r < 0) - return r; - - sysattr = NULL; - value = NULL; - - enumerator->scan_uptodate = false; - - return 0; -} - -_public_ int sd_device_enumerator_add_match_property(sd_device_enumerator *enumerator, const char *_property, const char *_value) { - _cleanup_free_ char *property = NULL, *value = NULL; - int r; - - assert_return(enumerator, -EINVAL); - assert_return(_property, -EINVAL); - - r = hashmap_ensure_allocated(&enumerator->match_property, NULL); - if (r < 0) - return r; - - property = strdup(_property); - if (!property) - return -ENOMEM; - - if (_value) { - value = strdup(_value); - if (!value) - return -ENOMEM; - } - - r = hashmap_put(enumerator->match_property, property, value); - if (r < 0) - return r; - - property = NULL; - value = NULL; - - enumerator->scan_uptodate = false; - - return 0; -} - -_public_ int sd_device_enumerator_add_match_sysname(sd_device_enumerator *enumerator, const char *sysname) { - int r; - - assert_return(enumerator, -EINVAL); - assert_return(sysname, -EINVAL); - - r = set_ensure_allocated(&enumerator->match_sysname, NULL); - if (r < 0) - return r; - - r = set_put_strdup(enumerator->match_sysname, sysname); - if (r < 0) - return r; - - enumerator->scan_uptodate = false; - - return 0; -} - -_public_ int sd_device_enumerator_add_match_tag(sd_device_enumerator *enumerator, const char *tag) { - int r; - - assert_return(enumerator, -EINVAL); - assert_return(tag, -EINVAL); - - r = set_ensure_allocated(&enumerator->match_tag, NULL); - if (r < 0) - return r; - - r = set_put_strdup(enumerator->match_tag, tag); - if (r < 0) - return r; - - enumerator->scan_uptodate = false; - - return 0; -} - -_public_ int sd_device_enumerator_add_match_parent(sd_device_enumerator *enumerator, sd_device *parent) { - assert_return(enumerator, -EINVAL); - assert_return(parent, -EINVAL); - - sd_device_unref(enumerator->match_parent); - enumerator->match_parent = sd_device_ref(parent); - - enumerator->scan_uptodate = false; - - return 0; -} - -_public_ int sd_device_enumerator_allow_uninitialized(sd_device_enumerator *enumerator) { - assert_return(enumerator, -EINVAL); - - enumerator->match_allow_uninitialized = true; - - enumerator->scan_uptodate = false; - - return 0; -} - -int device_enumerator_add_match_is_initialized(sd_device_enumerator *enumerator) { - assert_return(enumerator, -EINVAL); - - enumerator->match_allow_uninitialized = false; - - enumerator->scan_uptodate = false; - - return 0; -} - -static int device_compare(const void *_a, const void *_b) { - sd_device *a = (sd_device *)_a, *b = (sd_device *)_b; - const char *devpath_a, *devpath_b, *sound_a; - bool delay_a = false, delay_b = false; - - assert_se(sd_device_get_devpath(a, &devpath_a) >= 0); - assert_se(sd_device_get_devpath(b, &devpath_b) >= 0); - - sound_a = strstr(devpath_a, "/sound/card"); - if (sound_a) { - /* For sound cards the control device must be enumerated last to - * make sure it's the final device node that gets ACLs applied. - * Applications rely on this fact and use ACL changes on the - * control node as an indicator that the ACL change of the - * entire sound card completed. The kernel makes this guarantee - * when creating those devices, and hence we should too when - * enumerating them. */ - sound_a += strlen("/sound/card"); - sound_a = strchr(sound_a, '/'); - - if (sound_a) { - unsigned prefix_len; - - prefix_len = sound_a - devpath_a; - - if (strncmp(devpath_a, devpath_b, prefix_len) == 0) { - const char *sound_b; - - sound_b = devpath_b + prefix_len; - - if (startswith(sound_a, "/controlC") && - !startswith(sound_b, "/contolC")) - return 1; - - if (!startswith(sound_a, "/controlC") && - startswith(sound_b, "/controlC")) - return -1; - } - } - } - - /* md and dm devices are enumerated after all other devices */ - if (strstr(devpath_a, "/block/md") || strstr(devpath_a, "/block/dm-")) - delay_a = true; - - if (strstr(devpath_b, "/block/md") || strstr(devpath_b, "/block/dm-")) - delay_b = true; - - if (delay_a && !delay_b) - return 1; - - if (!delay_a && delay_b) - return -1; - - return strcmp(devpath_a, devpath_b); -} - -int device_enumerator_add_device(sd_device_enumerator *enumerator, sd_device *device) { - int r; - - assert_return(enumerator, -EINVAL); - assert_return(device, -EINVAL); - - r = prioq_ensure_allocated(&enumerator->devices, device_compare); - if (r < 0) - return r; - - r = prioq_put(enumerator->devices, device, NULL); - if (r < 0) - return r; - - sd_device_ref(device); - - return 0; -} - -static bool match_sysattr_value(sd_device *device, const char *sysattr, const char *match_value) { - const char *value; - int r; - - assert(device); - assert(sysattr); - - r = sd_device_get_sysattr_value(device, sysattr, &value); - if (r < 0) - return false; - - if (!match_value) - return true; - - if (fnmatch(match_value, value, 0) == 0) - return true; - - return false; -} - -static bool match_sysattr(sd_device_enumerator *enumerator, sd_device *device) { - const char *sysattr; - const char *value; - Iterator i; - - assert(enumerator); - assert(device); - - HASHMAP_FOREACH_KEY(value, sysattr, enumerator->nomatch_sysattr, i) - if (match_sysattr_value(device, sysattr, value)) - return false; - - HASHMAP_FOREACH_KEY(value, sysattr, enumerator->match_sysattr, i) - if (!match_sysattr_value(device, sysattr, value)) - return false; - - return true; -} - -static bool match_property(sd_device_enumerator *enumerator, sd_device *device) { - const char *property; - const char *value; - Iterator i; - - assert(enumerator); - assert(device); - - if (hashmap_isempty(enumerator->match_property)) - return true; - - HASHMAP_FOREACH_KEY(value, property, enumerator->match_property, i) { - const char *property_dev, *value_dev; - - FOREACH_DEVICE_PROPERTY(device, property_dev, value_dev) { - if (fnmatch(property, property_dev, 0) != 0) - continue; - - if (!value && !value_dev) - return true; - - if (!value || !value_dev) - continue; - - if (fnmatch(value, value_dev, 0) == 0) - return true; - } - } - - return false; -} - -static bool match_tag(sd_device_enumerator *enumerator, sd_device *device) { - const char *tag; - Iterator i; - - assert(enumerator); - assert(device); - - SET_FOREACH(tag, enumerator->match_tag, i) - if (!sd_device_has_tag(device, tag)) - return false; - - return true; -} - -static bool match_parent(sd_device_enumerator *enumerator, sd_device *device) { - const char *devpath, *devpath_dev; - int r; - - assert(enumerator); - assert(device); - - if (!enumerator->match_parent) - return true; - - r = sd_device_get_devpath(enumerator->match_parent, &devpath); - assert(r >= 0); - - r = sd_device_get_devpath(device, &devpath_dev); - assert(r >= 0); - - return startswith(devpath_dev, devpath); -} - -static bool match_sysname(sd_device_enumerator *enumerator, const char *sysname) { - const char *sysname_match; - Iterator i; - - assert(enumerator); - assert(sysname); - - if (set_isempty(enumerator->match_sysname)) - return true; - - SET_FOREACH(sysname_match, enumerator->match_sysname, i) - if (fnmatch(sysname_match, sysname, 0) == 0) - return true; - - return false; -} - -static int enumerator_scan_dir_and_add_devices(sd_device_enumerator *enumerator, const char *basedir, const char *subdir1, const char *subdir2) { - _cleanup_closedir_ DIR *dir = NULL; - char *path; - struct dirent *dent; - int r = 0; - - assert(enumerator); - assert(basedir); - - path = strjoina("/sys/", basedir, "/"); - - if (subdir1) - path = strjoina(path, subdir1, "/"); - - if (subdir2) - path = strjoina(path, subdir2, "/"); - - dir = opendir(path); - if (!dir) - return -errno; - - FOREACH_DIRENT_ALL(dent, dir, return -errno) { - _cleanup_device_unref_ sd_device *device = NULL; - char syspath[strlen(path) + 1 + strlen(dent->d_name) + 1]; - dev_t devnum; - int ifindex, initialized, k; - - if (dent->d_name[0] == '.') - continue; - - if (!match_sysname(enumerator, dent->d_name)) - continue; - - (void)sprintf(syspath, "%s%s", path, dent->d_name); - - k = sd_device_new_from_syspath(&device, syspath); - if (k < 0) { - if (k != -ENODEV) - /* this is necessarily racey, so ignore missing devices */ - r = k; - - continue; - } - - k = sd_device_get_devnum(device, &devnum); - if (k < 0) { - r = k; - continue; - } - - k = sd_device_get_ifindex(device, &ifindex); - if (k < 0) { - r = k; - continue; - } - - k = sd_device_get_is_initialized(device, &initialized); - if (k < 0) { - r = k; - continue; - } - - /* - * All devices with a device node or network interfaces - * possibly need udev to adjust the device node permission - * or context, or rename the interface before it can be - * reliably used from other processes. - * - * For now, we can only check these types of devices, we - * might not store a database, and have no way to find out - * for all other types of devices. - */ - if (!enumerator->match_allow_uninitialized && - !initialized && - (major(devnum) > 0 || ifindex > 0)) - continue; - - if (!match_parent(enumerator, device)) - continue; - - if (!match_tag(enumerator, device)) - continue; - - if (!match_property(enumerator, device)) - continue; - - if (!match_sysattr(enumerator, device)) - continue; - - k = device_enumerator_add_device(enumerator, device); - if (k < 0) - r = k; - } - - return r; -} - -static bool match_subsystem(sd_device_enumerator *enumerator, const char *subsystem) { - const char *subsystem_match; - Iterator i; - - assert(enumerator); - - if (!subsystem) - return false; - - SET_FOREACH(subsystem_match, enumerator->nomatch_subsystem, i) - if (fnmatch(subsystem_match, subsystem, 0) == 0) - return false; - - if (set_isempty(enumerator->match_subsystem)) - return true; - - SET_FOREACH(subsystem_match, enumerator->match_subsystem, i) - if (fnmatch(subsystem_match, subsystem, 0) == 0) - return true; - - return false; -} - -static int enumerator_scan_dir(sd_device_enumerator *enumerator, const char *basedir, const char *subdir, const char *subsystem) { - _cleanup_closedir_ DIR *dir = NULL; - char *path; - struct dirent *dent; - int r = 0; - - path = strjoina("/sys/", basedir); - - dir = opendir(path); - if (!dir) - return -errno; - - log_debug(" device-enumerator: scanning %s", path); - - FOREACH_DIRENT_ALL(dent, dir, return -errno) { - int k; - - if (dent->d_name[0] == '.') - continue; - - if (!match_subsystem(enumerator, subsystem ? : dent->d_name)) - continue; - - k = enumerator_scan_dir_and_add_devices(enumerator, basedir, dent->d_name, subdir); - if (k < 0) - r = k; - } - - return r; -} - -static int enumerator_scan_devices_tag(sd_device_enumerator *enumerator, const char *tag) { - _cleanup_closedir_ DIR *dir = NULL; - char *path; - struct dirent *dent; - int r = 0; - - assert(enumerator); - assert(tag); - - path = strjoina("/run/udev/tags/", tag); - - dir = opendir(path); - if (!dir) { - if (errno == ENOENT) - return 0; - else { - log_error("sd-device-enumerator: could not open tags directory %s: %m", path); - return -errno; - } - } - - /* TODO: filter away subsystems? */ - - FOREACH_DIRENT_ALL(dent, dir, return -errno) { - _cleanup_device_unref_ sd_device *device = NULL; - const char *subsystem, *sysname; - int k; - - if (dent->d_name[0] == '.') - continue; - - k = sd_device_new_from_device_id(&device, dent->d_name); - if (k < 0) { - if (k != -ENODEV) - /* this is necessarily racy, so ignore missing devices */ - r = k; - - continue; - } - - k = sd_device_get_subsystem(device, &subsystem); - if (k < 0) { - r = k; - continue; - } - - if (!match_subsystem(enumerator, subsystem)) - continue; - - k = sd_device_get_sysname(device, &sysname); - if (k < 0) { - r = k; - continue; - } - - if (!match_sysname(enumerator, sysname)) - continue; - - if (!match_parent(enumerator, device)) - continue; - - if (!match_property(enumerator, device)) - continue; - - if (!match_sysattr(enumerator, device)) - continue; - - k = device_enumerator_add_device(enumerator, device); - if (k < 0) { - r = k; - continue; - } - } - - return r; -} - -static int enumerator_scan_devices_tags(sd_device_enumerator *enumerator) { - const char *tag; - Iterator i; - int r; - - assert(enumerator); - - SET_FOREACH(tag, enumerator->match_tag, i) { - r = enumerator_scan_devices_tag(enumerator, tag); - if (r < 0) - return r; - } - - return 0; -} - -static int parent_add_child(sd_device_enumerator *enumerator, const char *path) { - _cleanup_device_unref_ sd_device *device = NULL; - const char *subsystem, *sysname; - int r; - - r = sd_device_new_from_syspath(&device, path); - if (r == -ENODEV) - /* this is necessarily racy, so ignore missing devices */ - return 0; - else if (r < 0) - return r; - - r = sd_device_get_subsystem(device, &subsystem); - if (r < 0) - return r; - - if (!match_subsystem(enumerator, subsystem)) - return 0; - - r = sd_device_get_sysname(device, &sysname); - if (r < 0) - return r; - - if (!match_sysname(enumerator, sysname)) - return 0; - - if (!match_property(enumerator, device)) - return 0; - - if (!match_sysattr(enumerator, device)) - return 0; - - r = device_enumerator_add_device(enumerator, device); - if (r < 0) - return r; - - return 1; -} - -static int parent_crawl_children(sd_device_enumerator *enumerator, const char *path, unsigned maxdepth) { - _cleanup_closedir_ DIR *dir = NULL; - struct dirent *dent; - int r = 0; - - dir = opendir(path); - if (!dir) { - log_debug("sd-device-enumerate: could not open parent directory %s: %m", path); - return -errno; - } - - FOREACH_DIRENT_ALL(dent, dir, return -errno) { - _cleanup_free_ char *child = NULL; - int k; - - if (dent->d_name[0] == '.') - continue; - - if (dent->d_type != DT_DIR) - continue; - - child = strjoin(path, "/", dent->d_name, NULL); - if (!child) - return -ENOMEM; - - k = parent_add_child(enumerator, child); - if (k < 0) - r = k; - - if (maxdepth > 0) - parent_crawl_children(enumerator, child, maxdepth - 1); - else - log_debug("device-enumerate: max depth reached, %s: ignoring devices", child); - } - - return r; -} - -static int enumerator_scan_devices_children(sd_device_enumerator *enumerator) { - const char *path; - int r = 0, k; - - r = sd_device_get_syspath(enumerator->match_parent, &path); - if (r < 0) - return r; - - k = parent_add_child(enumerator, path); - if (k < 0) - r = k; - - k = parent_crawl_children(enumerator, path, DEVICE_ENUMERATE_MAX_DEPTH); - if (k < 0) - r = k; - - return r; -} - -static int enumerator_scan_devices_all(sd_device_enumerator *enumerator) { - int r = 0; - - log_debug("device-enumerator: scan all dirs"); - - if (access("/sys/subsystem", F_OK) >= 0) { - /* we have /subsystem/, forget all the old stuff */ - r = enumerator_scan_dir(enumerator, "subsystem", "devices", NULL); - if (r < 0) { - log_debug("device-enumerator: failed to scan /sys/subsystem: %s", strerror(-r)); - return r; - } - } else { - int k; - - k = enumerator_scan_dir(enumerator, "bus", "devices", NULL); - if (k < 0) { - log_debug_errno(k, "device-enumerator: failed to scan /sys/bus: %m"); - r = k; - } - - k = enumerator_scan_dir(enumerator, "class", NULL, NULL); - if (k < 0) { - log_debug_errno(k, "device-enumerator: failed to scan /sys/class: %m"); - r = k; - } - } - - return r; -} - -int device_enumerator_scan_devices(sd_device_enumerator *enumerator) { - sd_device *device; - int r; - - assert(enumerator); - - if (enumerator->scan_uptodate && - enumerator->type == DEVICE_ENUMERATION_TYPE_DEVICES) - return 0; - - while ((device = prioq_pop(enumerator->devices))) - sd_device_unref(device); - - if (!set_isempty(enumerator->match_tag)) { - r = enumerator_scan_devices_tags(enumerator); - if (r < 0) - return r; - } else if (enumerator->match_parent) { - r = enumerator_scan_devices_children(enumerator); - if (r < 0) - return r; - } else { - r = enumerator_scan_devices_all(enumerator); - if (r < 0) - return r; - } - - enumerator->scan_uptodate = true; - - return 0; -} - -_public_ sd_device *sd_device_enumerator_get_device_first(sd_device_enumerator *enumerator) { - int r; - - assert_return(enumerator, NULL); - - r = device_enumerator_scan_devices(enumerator); - if (r < 0) - return NULL; - - enumerator->type = DEVICE_ENUMERATION_TYPE_DEVICES; - - return prioq_peek(enumerator->devices); -} - -_public_ sd_device *sd_device_enumerator_get_device_next(sd_device_enumerator *enumerator) { - assert_return(enumerator, NULL); - - if (!enumerator->scan_uptodate || - enumerator->type != DEVICE_ENUMERATION_TYPE_DEVICES) - return NULL; - - sd_device_unref(prioq_pop(enumerator->devices)); - - return prioq_peek(enumerator->devices); -} - -int device_enumerator_scan_subsystems(sd_device_enumerator *enumerator) { - sd_device *device; - const char *subsysdir; - int r = 0, k; - - assert(enumerator); - - if (enumerator->scan_uptodate && - enumerator->type == DEVICE_ENUMERATION_TYPE_SUBSYSTEMS) - return 0; - - while ((device = prioq_pop(enumerator->devices))) - sd_device_unref(device); - - /* modules */ - if (match_subsystem(enumerator, "module")) { - k = enumerator_scan_dir_and_add_devices(enumerator, "module", NULL, NULL); - if (k < 0) { - log_debug_errno(k, "device-enumerator: failed to scan modules: %m"); - r = k; - } - } - - if (access("/sys/subsystem", F_OK) >= 0) - subsysdir = "subsystem"; - else - subsysdir = "bus"; - - /* subsystems (only buses support coldplug) */ - if (match_subsystem(enumerator, "subsystem")) { - k = enumerator_scan_dir_and_add_devices(enumerator, subsysdir, NULL, NULL); - if (k < 0) { - log_debug_errno(k, "device-enumerator: failed to scan subsystems: %m"); - r = k; - } - } - - /* subsystem drivers */ - if (match_subsystem(enumerator, "drivers")) { - k = enumerator_scan_dir(enumerator, subsysdir, "drivers", "drivers"); - if (k < 0) { - log_debug_errno(k, "device-enumerator: failed to scan drivers: %m"); - r = k; - } - } - - enumerator->scan_uptodate = true; - - return r; -} - -_public_ sd_device *sd_device_enumerator_get_subsystem_first(sd_device_enumerator *enumerator) { - int r; - - assert_return(enumerator, NULL); - - r = device_enumerator_scan_subsystems(enumerator); - if (r < 0) - return NULL; - - enumerator->type = DEVICE_ENUMERATION_TYPE_SUBSYSTEMS; - - return prioq_peek(enumerator->devices); -} - -_public_ sd_device *sd_device_enumerator_get_subsystem_next(sd_device_enumerator *enumerator) { - assert_return(enumerator, NULL); - - if (enumerator->scan_uptodate || - enumerator->type != DEVICE_ENUMERATION_TYPE_SUBSYSTEMS) - return NULL; - - sd_device_unref(prioq_pop(enumerator->devices)); - - return prioq_peek(enumerator->devices); -} - -sd_device *device_enumerator_get_first(sd_device_enumerator *enumerator) { - assert_return(enumerator, NULL); - - return prioq_peek(enumerator->devices); -} - -sd_device *device_enumerator_get_next(sd_device_enumerator *enumerator) { - assert_return(enumerator, NULL); - - sd_device_unref(prioq_pop(enumerator->devices)); - - return prioq_peek(enumerator->devices); -} diff --git a/src/libsystemd/sd-netlink/netlink-internal.h b/src/libsystemd/sd-netlink/netlink-internal.h deleted file mode 100644 index ed627444d..000000000 --- a/src/libsystemd/sd-netlink/netlink-internal.h +++ /dev/null @@ -1,134 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -#pragma once - -/*** - This file is part of systemd. - - Copyright 2013 Tom Gundersen - - 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 . -***/ - -#include - -#include "refcnt.h" -#include "prioq.h" -#include "list.h" - -#include "sd-netlink.h" - -#include "netlink-types.h" - -#define RTNL_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC)) - -#define RTNL_WQUEUE_MAX 1024 -#define RTNL_RQUEUE_MAX 64*1024 - -#define RTNL_CONTAINER_DEPTH 32 - -struct reply_callback { - sd_netlink_message_handler_t callback; - void *userdata; - usec_t timeout; - uint64_t serial; - unsigned prioq_idx; -}; - -struct match_callback { - sd_netlink_message_handler_t callback; - uint16_t type; - void *userdata; - - LIST_FIELDS(struct match_callback, match_callbacks); -}; - -struct sd_netlink { - RefCount n_ref; - - int fd; - - union { - struct sockaddr sa; - struct sockaddr_nl nl; - } sockaddr; - - sd_netlink_message **rqueue; - unsigned rqueue_size; - size_t rqueue_allocated; - - sd_netlink_message **rqueue_partial; - unsigned rqueue_partial_size; - size_t rqueue_partial_allocated; - - sd_netlink_message **wqueue; - unsigned wqueue_size; - size_t wqueue_allocated; - - struct nlmsghdr *rbuffer; - size_t rbuffer_allocated; - - bool processing:1; - - uint32_t serial; - - struct Prioq *reply_callbacks_prioq; - Hashmap *reply_callbacks; - - LIST_HEAD(struct match_callback, match_callbacks); - - pid_t original_pid; - - sd_event_source *io_event_source; - sd_event_source *time_event_source; - sd_event_source *exit_event_source; - sd_event *event; -}; - -struct netlink_attribute { - size_t offset; /* offset from hdr to attribute */ -}; - -struct netlink_container { - const struct NLTypeSystem *type_system; /* the type system of the container */ - size_t offset; /* offset from hdr to the start of the container */ - struct netlink_attribute *attributes; - unsigned short n_attributes; /* number of attributes in container */ -}; - -struct sd_netlink_message { - RefCount n_ref; - - sd_netlink *rtnl; - - struct nlmsghdr *hdr; - struct netlink_container containers[RTNL_CONTAINER_DEPTH]; - unsigned n_containers; /* number of containers */ - bool sealed:1; - bool broadcast:1; - - sd_netlink_message *next; /* next in a chain of multi-part messages */ -}; - -int message_new(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t type); - -int socket_write_message(sd_netlink *nl, sd_netlink_message *m); -int socket_read_message(sd_netlink *nl); - -int rtnl_rqueue_make_room(sd_netlink *rtnl); -int rtnl_rqueue_partial_make_room(sd_netlink *rtnl); - -/* Make sure callbacks don't destroy the rtnl connection */ -#define RTNL_DONT_DESTROY(rtnl) \ - _cleanup_netlink_unref_ _unused_ sd_netlink *_dont_destroy_##rtnl = sd_netlink_ref(rtnl) diff --git a/src/libsystemd/sd-netlink/netlink-message.c b/src/libsystemd/sd-netlink/netlink-message.c deleted file mode 100644 index a913d82cf..000000000 --- a/src/libsystemd/sd-netlink/netlink-message.c +++ /dev/null @@ -1,933 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2013 Tom Gundersen - - 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 . -***/ - -#include -#include -#include - -#include "util.h" -#include "socket-util.h" -#include "formats-util.h" -#include "refcnt.h" -#include "missing.h" - -#include "sd-netlink.h" -#include "netlink-util.h" -#include "netlink-internal.h" -#include "netlink-types.h" - -#define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->container_offsets[i]) : NULL) -#define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers ++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr; - -#define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK) - -int message_new_empty(sd_netlink *rtnl, sd_netlink_message **ret) { - sd_netlink_message *m; - - assert_return(ret, -EINVAL); - - /* Note that 'rtnl' is currently unused, if we start using it internally - we must take care to avoid problems due to mutual references between - buses and their queued messages. See sd-bus. - */ - - m = new0(sd_netlink_message, 1); - if (!m) - return -ENOMEM; - - m->n_ref = REFCNT_INIT; - - m->sealed = false; - - *ret = m; - - return 0; -} - -int message_new(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t type) { - _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL; - const NLType *nl_type; - size_t size; - int r; - - r = type_system_get_type(&type_system_root, &nl_type, type); - if (r < 0) - return r; - - if (type_get_type(nl_type) != NETLINK_TYPE_NESTED) - return -EINVAL; - - r = message_new_empty(rtnl, &m); - if (r < 0) - return r; - - size = NLMSG_SPACE(type_get_size(nl_type)); - - assert(size >= sizeof(struct nlmsghdr)); - m->hdr = malloc0(size); - if (!m->hdr) - return -ENOMEM; - - m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; - - type_get_type_system(nl_type, &m->container_type_system[0]); - m->hdr->nlmsg_len = size; - m->hdr->nlmsg_type = type; - - *ret = m; - m = NULL; - - return 0; -} - -int sd_netlink_message_request_dump(sd_netlink_message *m, int dump) { - assert_return(m, -EINVAL); - assert_return(m->hdr, -EINVAL); - assert_return(m->hdr->nlmsg_type == RTM_GETLINK || - m->hdr->nlmsg_type == RTM_GETADDR || - m->hdr->nlmsg_type == RTM_GETROUTE || - m->hdr->nlmsg_type == RTM_GETNEIGH, - -EINVAL); - - if (dump) - m->hdr->nlmsg_flags |= NLM_F_DUMP; - else - m->hdr->nlmsg_flags &= ~NLM_F_DUMP; - - return 0; -} - -sd_netlink_message *sd_netlink_message_ref(sd_netlink_message *m) { - if (m) - assert_se(REFCNT_INC(m->n_ref) >= 2); - - return m; -} - -sd_netlink_message *sd_netlink_message_unref(sd_netlink_message *m) { - if (m && REFCNT_DEC(m->n_ref) == 0) { - unsigned i; - - free(m->hdr); - - for (i = 0; i <= m->n_containers; i++) - free(m->rta_offset_tb[i]); - - sd_netlink_message_unref(m->next); - - free(m); - } - - return NULL; -} - -int sd_netlink_message_get_type(sd_netlink_message *m, uint16_t *type) { - assert_return(m, -EINVAL); - assert_return(type, -EINVAL); - - *type = m->hdr->nlmsg_type; - - return 0; -} - -int sd_netlink_message_is_broadcast(sd_netlink_message *m) { - assert_return(m, -EINVAL); - - return m->broadcast; -} - -/* If successful the updated message will be correctly aligned, if - unsuccessful the old message is untouched. */ -static int add_rtattr(sd_netlink_message *m, unsigned short type, const void *data, size_t data_length) { - uint32_t rta_length; - size_t message_length, padding_length; - struct nlmsghdr *new_hdr; - struct rtattr *rta; - char *padding; - unsigned i; - int offset; - - assert(m); - assert(m->hdr); - assert(!m->sealed); - assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len); - assert(!data || data_length); - - /* get offset of the new attribute */ - offset = m->hdr->nlmsg_len; - - /* get the size of the new rta attribute (with padding at the end) */ - rta_length = RTA_LENGTH(data_length); - - /* get the new message size (with padding at the end) */ - message_length = offset + RTA_ALIGN(rta_length); - - /* realloc to fit the new attribute */ - new_hdr = realloc(m->hdr, message_length); - if (!new_hdr) - return -ENOMEM; - m->hdr = new_hdr; - - /* get pointer to the attribute we are about to add */ - rta = (struct rtattr *) ((uint8_t *) m->hdr + offset); - - /* if we are inside containers, extend them */ - for (i = 0; i < m->n_containers; i++) - GET_CONTAINER(m, i)->rta_len += message_length - offset; - - /* fill in the attribute */ - rta->rta_type = type; - rta->rta_len = rta_length; - if (data) - /* we don't deal with the case where the user lies about the type - * and gives us too little data (so don't do that) - */ - padding = mempcpy(RTA_DATA(rta), data, data_length); - else { - /* if no data was passed, make sure we still initialize the padding - note that we can have data_length > 0 (used by some containers) */ - padding = RTA_DATA(rta); - } - - /* make sure also the padding at the end of the message is initialized */ - padding_length = (uint8_t*)m->hdr + message_length - (uint8_t*)padding; - memzero(padding, padding_length); - - /* update message size */ - m->hdr->nlmsg_len = message_length; - - return offset; -} - -static int message_attribute_has_type(sd_netlink_message *m, size_t *out_size, uint16_t attribute_type, uint16_t data_type) { - const NLType *type; - int r; - - assert(m); - - r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type); - if (r < 0) - return r; - - if (type_get_type(type) != data_type) - return -EINVAL; - - if (out_size) - *out_size = type_get_size(type); - return 0; -} - -int sd_netlink_message_append_string(sd_netlink_message *m, unsigned short type, const char *data) { - size_t length, size; - int r; - - assert_return(m, -EINVAL); - assert_return(!m->sealed, -EPERM); - assert_return(data, -EINVAL); - - r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_STRING); - if (r < 0) - return r; - - if (size) { - length = strnlen(data, size+1); - if (length > size) - return -EINVAL; - } else - length = strlen(data); - - r = add_rtattr(m, type, data, length + 1); - if (r < 0) - return r; - - return 0; -} - -int sd_netlink_message_append_flag(sd_netlink_message *m, unsigned short type) { - size_t size; - int r; - - assert_return(m, -EINVAL); - assert_return(!m->sealed, -EPERM); - - r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_FLAG); - if (r < 0) - return r; - - r = add_rtattr(m, type, NULL, 0); - if (r < 0) - return r; - - return 0; -} - -int sd_netlink_message_append_u8(sd_netlink_message *m, unsigned short type, uint8_t data) { - int r; - - assert_return(m, -EINVAL); - assert_return(!m->sealed, -EPERM); - - r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U8); - if (r < 0) - return r; - - r = add_rtattr(m, type, &data, sizeof(uint8_t)); - if (r < 0) - return r; - - return 0; -} - - -int sd_netlink_message_append_u16(sd_netlink_message *m, unsigned short type, uint16_t data) { - int r; - - assert_return(m, -EINVAL); - assert_return(!m->sealed, -EPERM); - - r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U16); - if (r < 0) - return r; - - r = add_rtattr(m, type, &data, sizeof(uint16_t)); - if (r < 0) - return r; - - return 0; -} - -int sd_netlink_message_append_u32(sd_netlink_message *m, unsigned short type, uint32_t data) { - int r; - - assert_return(m, -EINVAL); - assert_return(!m->sealed, -EPERM); - - r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U32); - if (r < 0) - return r; - - r = add_rtattr(m, type, &data, sizeof(uint32_t)); - if (r < 0) - return r; - - return 0; -} - -int sd_netlink_message_append_in_addr(sd_netlink_message *m, unsigned short type, const struct in_addr *data) { - int r; - - assert_return(m, -EINVAL); - assert_return(!m->sealed, -EPERM); - assert_return(data, -EINVAL); - - r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_IN_ADDR); - if (r < 0) - return r; - - r = add_rtattr(m, type, data, sizeof(struct in_addr)); - if (r < 0) - return r; - - return 0; -} - -int sd_netlink_message_append_in6_addr(sd_netlink_message *m, unsigned short type, const struct in6_addr *data) { - int r; - - assert_return(m, -EINVAL); - assert_return(!m->sealed, -EPERM); - assert_return(data, -EINVAL); - - r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_IN_ADDR); - if (r < 0) - return r; - - r = add_rtattr(m, type, data, sizeof(struct in6_addr)); - if (r < 0) - return r; - - return 0; -} - -int sd_netlink_message_append_ether_addr(sd_netlink_message *m, unsigned short type, const struct ether_addr *data) { - int r; - - assert_return(m, -EINVAL); - assert_return(!m->sealed, -EPERM); - assert_return(data, -EINVAL); - - r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_ETHER_ADDR); - if (r < 0) - return r; - - r = add_rtattr(m, type, data, ETH_ALEN); - if (r < 0) - return r; - - return 0; -} - -int sd_netlink_message_append_cache_info(sd_netlink_message *m, unsigned short type, const struct ifa_cacheinfo *info) { - int r; - - assert_return(m, -EINVAL); - assert_return(!m->sealed, -EPERM); - assert_return(info, -EINVAL); - - r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_CACHE_INFO); - if (r < 0) - return r; - - r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo)); - if (r < 0) - return r; - - return 0; -} - -int sd_netlink_message_open_container(sd_netlink_message *m, unsigned short type) { - size_t size; - int r; - - assert_return(m, -EINVAL); - assert_return(!m->sealed, -EPERM); - assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -ERANGE); - - r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_NESTED); - if (r < 0) { - const NLTypeSystemUnion *type_system_union; - int family; - - r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_UNION); - if (r < 0) - return r; - - r = sd_rtnl_message_get_family(m, &family); - if (r < 0) - return r; - - r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type); - if (r < 0) - return r; - - r = type_system_union_protocol_get_type_system(type_system_union, - &m->container_type_system[m->n_containers + 1], - family); - if (r < 0) - return r; - } else { - r = type_system_get_type_system(m->container_type_system[m->n_containers], - &m->container_type_system[m->n_containers + 1], - type); - if (r < 0) - return r; - } - - r = add_rtattr(m, type | NLA_F_NESTED, NULL, size); - if (r < 0) - return r; - - m->container_offsets[m->n_containers ++] = r; - - return 0; -} - -int sd_netlink_message_open_container_union(sd_netlink_message *m, unsigned short type, const char *key) { - const NLTypeSystemUnion *type_system_union; - int r; - - assert_return(m, -EINVAL); - assert_return(!m->sealed, -EPERM); - - r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type); - if (r < 0) - return r; - - r = type_system_union_get_type_system(type_system_union, - &m->container_type_system[m->n_containers + 1], - key); - if (r < 0) - return r; - - r = sd_netlink_message_append_string(m, type_system_union->match, key); - if (r < 0) - return r; - - /* do we evere need non-null size */ - r = add_rtattr(m, type | NLA_F_NESTED, NULL, 0); - if (r < 0) - return r; - - m->container_offsets[m->n_containers ++] = r; - - return 0; -} - - -int sd_netlink_message_close_container(sd_netlink_message *m) { - assert_return(m, -EINVAL); - assert_return(!m->sealed, -EPERM); - assert_return(m->n_containers > 0, -EINVAL); - - m->container_type_system[m->n_containers] = NULL; - m->n_containers --; - - return 0; -} - -static int netlink_message_read_internal(sd_netlink_message *m, unsigned short type, void **data) { - struct rtattr *rta; - - assert_return(m, -EINVAL); - assert_return(m->sealed, -EPERM); - assert_return(data, -EINVAL); - assert(m->n_containers <= RTNL_CONTAINER_DEPTH); - assert(m->rta_offset_tb[m->n_containers]); - assert(type < m->rta_tb_size[m->n_containers]); - - if(!m->rta_offset_tb[m->n_containers][type]) - return -ENODATA; - - rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]); - - *data = RTA_DATA(rta); - - return RTA_PAYLOAD(rta); -} - -int sd_netlink_message_read_string(sd_netlink_message *m, unsigned short type, const char **data) { - int r; - void *attr_data; - - assert_return(m, -EINVAL); - - r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_STRING); - if (r < 0) - return r; - - r = netlink_message_read_internal(m, type, &attr_data); - if (r < 0) - return r; - else if (strnlen(attr_data, r) >= (size_t) r) - return -EIO; - - if (data) - *data = (const char *) attr_data; - - return 0; -} - -int sd_netlink_message_read_u8(sd_netlink_message *m, unsigned short type, uint8_t *data) { - int r; - void *attr_data; - - assert_return(m, -EINVAL); - - r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U8); - if (r < 0) - return r; - - r = netlink_message_read_internal(m, type, &attr_data); - if (r < 0) - return r; - else if ((size_t) r < sizeof(uint8_t)) - return -EIO; - - if (data) - *data = *(uint8_t *) attr_data; - - return 0; -} - -int sd_netlink_message_read_u16(sd_netlink_message *m, unsigned short type, uint16_t *data) { - int r; - void *attr_data; - - assert_return(m, -EINVAL); - - r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U16); - if (r < 0) - return r; - - r = netlink_message_read_internal(m, type, &attr_data); - if (r < 0) - return r; - else if ((size_t) r < sizeof(uint16_t)) - return -EIO; - - if (data) - *data = *(uint16_t *) attr_data; - - return 0; -} - -int sd_netlink_message_read_u32(sd_netlink_message *m, unsigned short type, uint32_t *data) { - int r; - void *attr_data; - - assert_return(m, -EINVAL); - - r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U32); - if (r < 0) - return r; - - r = netlink_message_read_internal(m, type, &attr_data); - if (r < 0) - return r; - else if ((size_t)r < sizeof(uint32_t)) - return -EIO; - - if (data) - *data = *(uint32_t *) attr_data; - - return 0; -} - -int sd_netlink_message_read_ether_addr(sd_netlink_message *m, unsigned short type, struct ether_addr *data) { - int r; - void *attr_data; - - assert_return(m, -EINVAL); - - r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_ETHER_ADDR); - if (r < 0) - return r; - - r = netlink_message_read_internal(m, type, &attr_data); - if (r < 0) - return r; - else if ((size_t)r < sizeof(struct ether_addr)) - return -EIO; - - if (data) - memcpy(data, attr_data, sizeof(struct ether_addr)); - - return 0; -} - -int sd_netlink_message_read_cache_info(sd_netlink_message *m, unsigned short type, struct ifa_cacheinfo *info) { - int r; - void *attr_data; - - assert_return(m, -EINVAL); - - r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_CACHE_INFO); - if (r < 0) - return r; - - r = netlink_message_read_internal(m, type, &attr_data); - if (r < 0) - return r; - else if ((size_t)r < sizeof(struct ifa_cacheinfo)) - return -EIO; - - if (info) - memcpy(info, attr_data, sizeof(struct ifa_cacheinfo)); - - return 0; -} - -int sd_netlink_message_read_in_addr(sd_netlink_message *m, unsigned short type, struct in_addr *data) { - int r; - void *attr_data; - - assert_return(m, -EINVAL); - - r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_IN_ADDR); - if (r < 0) - return r; - - r = netlink_message_read_internal(m, type, &attr_data); - if (r < 0) - return r; - else if ((size_t)r < sizeof(struct in_addr)) - return -EIO; - - if (data) - memcpy(data, attr_data, sizeof(struct in_addr)); - - return 0; -} - -int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type, struct in6_addr *data) { - int r; - void *attr_data; - - assert_return(m, -EINVAL); - - r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_IN_ADDR); - if (r < 0) - return r; - - r = netlink_message_read_internal(m, type, &attr_data); - if (r < 0) - return r; - else if ((size_t)r < sizeof(struct in6_addr)) - return -EIO; - - if (data) - memcpy(data, attr_data, sizeof(struct in6_addr)); - - return 0; -} - -static int netlink_message_parse(sd_netlink_message *m, - size_t **rta_offset_tb, - unsigned short *rta_tb_size, - int count, - struct rtattr *rta, - unsigned int rt_len) { - unsigned short type; - size_t *tb; - - tb = new0(size_t, count); - if(!tb) - return -ENOMEM; - - *rta_tb_size = count; - - for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) { - type = RTA_TYPE(rta); - - /* if the kernel is newer than the headers we used - when building, we ignore out-of-range attributes - */ - if (type >= count) - continue; - - if (tb[type]) - log_debug("rtnl: message parse - overwriting repeated attribute"); - - tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr; - } - - *rta_offset_tb = tb; - - return 0; -} - -int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short type_id) { - const NLType *nl_type; - const NLTypeSystem *type_system; - void *container; - uint16_t type; - size_t size; - int r; - - assert_return(m, -EINVAL); - assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL); - - r = type_system_get_type(m->container_type_system[m->n_containers], - &nl_type, - type_id); - if (r < 0) - return r; - - type = type_get_type(nl_type); - - if (type == NETLINK_TYPE_NESTED) { - r = type_system_get_type_system(m->container_type_system[m->n_containers], - &type_system, - type_id); - if (r < 0) - return r; - } else if (type == NETLINK_TYPE_UNION) { - const NLTypeSystemUnion *type_system_union; - - r = type_system_get_type_system_union(m->container_type_system[m->n_containers], - &type_system_union, - type_id); - if (r < 0) - return r; - - switch (type_system_union->match_type) { - case NL_MATCH_SIBLING: - { - const char *key; - - r = sd_netlink_message_read_string(m, type_system_union->match, &key); - if (r < 0) - return r; - - r = type_system_union_get_type_system(type_system_union, - &type_system, - key); - if (r < 0) - return r; - - break; - } - case NL_MATCH_PROTOCOL: - { - int family; - - r = sd_rtnl_message_get_family(m, &family); - if (r < 0) - return r; - - r = type_system_union_protocol_get_type_system(type_system_union, - &type_system, - family); - if (r < 0) - return r; - - break; - } - default: - assert_not_reached("sd-netlink: invalid type system union type"); - } - } else - return -EINVAL; - - r = netlink_message_read_internal(m, type_id, &container); - if (r < 0) - return r; - else - size = (size_t)r; - - m->n_containers ++; - - r = netlink_message_parse(m, - &m->rta_offset_tb[m->n_containers], - &m->rta_tb_size[m->n_containers], - type_system_get_count(type_system), - container, - size); - if (r < 0) { - m->n_containers --; - return r; - } - - m->container_type_system[m->n_containers] = type_system; - - return 0; -} - -int sd_netlink_message_exit_container(sd_netlink_message *m) { - assert_return(m, -EINVAL); - assert_return(m->sealed, -EINVAL); - assert_return(m->n_containers > 0, -EINVAL); - - free(m->rta_offset_tb[m->n_containers]); - m->rta_offset_tb[m->n_containers] = NULL; - m->container_type_system[m->n_containers] = NULL; - - m->n_containers --; - - return 0; -} - -uint32_t rtnl_message_get_serial(sd_netlink_message *m) { - assert(m); - assert(m->hdr); - - return m->hdr->nlmsg_seq; -} - -int sd_netlink_message_is_error(sd_netlink_message *m) { - assert_return(m, 0); - assert_return(m->hdr, 0); - - return m->hdr->nlmsg_type == NLMSG_ERROR; -} - -int sd_netlink_message_get_errno(sd_netlink_message *m) { - struct nlmsgerr *err; - - assert_return(m, -EINVAL); - assert_return(m->hdr, -EINVAL); - - if (!sd_netlink_message_is_error(m)) - return 0; - - err = NLMSG_DATA(m->hdr); - - return err->error; -} - -int sd_netlink_message_rewind(sd_netlink_message *m) { - const NLType *nl_type; - uint16_t type; - size_t size; - unsigned i; - int r; - - assert_return(m, -EINVAL); - - /* don't allow appending to message once parsed */ - if (!m->sealed) - rtnl_message_seal(m); - - for (i = 1; i <= m->n_containers; i++) { - free(m->rta_offset_tb[i]); - m->rta_offset_tb[i] = NULL; - m->rta_tb_size[i] = 0; - m->container_type_system[i] = NULL; - } - - m->n_containers = 0; - - if (m->rta_offset_tb[0]) { - /* top-level attributes have already been parsed */ - return 0; - } - - assert(m->hdr); - - r = type_system_get_type(&type_system_root, &nl_type, m->hdr->nlmsg_type); - if (r < 0) - return r; - - type = type_get_type(nl_type); - size = type_get_size(nl_type); - - if (type == NETLINK_TYPE_NESTED) { - const NLTypeSystem *type_system; - - type_get_type_system(nl_type, &type_system); - - m->container_type_system[0] = type_system; - - r = netlink_message_parse(m, - &m->rta_offset_tb[m->n_containers], - &m->rta_tb_size[m->n_containers], - type_system_get_count(type_system), - (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) + NLMSG_ALIGN(size)), - NLMSG_PAYLOAD(m->hdr, size)); - if (r < 0) - return r; - } - - return 0; -} - -void rtnl_message_seal(sd_netlink_message *m) { - assert(m); - assert(!m->sealed); - - m->sealed = true; -} - -sd_netlink_message *sd_netlink_message_next(sd_netlink_message *m) { - assert_return(m, NULL); - - return m->next; -} diff --git a/src/libsystemd/sd-netlink/netlink-types.c b/src/libsystemd/sd-netlink/netlink-types.c deleted file mode 100644 index 212832919..000000000 --- a/src/libsystemd/sd-netlink/netlink-types.c +++ /dev/null @@ -1,652 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2014 Tom Gundersen - - 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 . -***/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "macro.h" -#include "util.h" - -#include "netlink-types.h" -#include "missing.h" - -/* Maximum ARP IP target defined in kernel */ -#define BOND_MAX_ARP_TARGETS 16 - -typedef enum { - BOND_ARP_TARGETS_0, - BOND_ARP_TARGETS_1, - BOND_ARP_TARGETS_2, - BOND_ARP_TARGETS_3, - BOND_ARP_TARGETS_4, - BOND_ARP_TARGETS_5, - BOND_ARP_TARGETS_6, - BOND_ARP_TARGETS_7, - BOND_ARP_TARGETS_8, - BOND_ARP_TARGETS_9, - BOND_ARP_TARGETS_10, - BOND_ARP_TARGETS_11, - BOND_ARP_TARGETS_12, - BOND_ARP_TARGETS_13, - BOND_ARP_TARGETS_14, - BOND_ARP_TARGETS_MAX = BOND_MAX_ARP_TARGETS, -} BondArpTargets; - -struct NLType { - uint16_t type; - size_t size; - const NLTypeSystem *type_system; - const NLTypeSystemUnion *type_system_union; -}; - -struct NLTypeSystem { - uint16_t count; - const NLType *types; -}; - -static const NLTypeSystem rtnl_link_type_system; - -static const NLType empty_types[1] = { - /* fake array to avoid .types==NULL, which denotes invalid type-systems */ -}; - -static const NLTypeSystem empty_type_system = { - .count = 0, - .types = empty_types, -}; - -static const NLType rtnl_link_info_data_veth_types[VETH_INFO_MAX + 1] = { - [VETH_INFO_PEER] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, -}; - -static const NLType rtnl_link_info_data_ipvlan_types[IFLA_IPVLAN_MAX + 1] = { - [IFLA_IPVLAN_MODE] = { .type = NETLINK_TYPE_U16 }, -}; - -static const NLType rtnl_link_info_data_macvlan_types[IFLA_MACVLAN_MAX + 1] = { - [IFLA_MACVLAN_MODE] = { .type = NETLINK_TYPE_U32 }, - [IFLA_MACVLAN_FLAGS] = { .type = NETLINK_TYPE_U16 }, -}; - -static const NLType rtnl_link_info_data_bridge_types[IFLA_BRIDGE_MAX + 1] = { - [IFLA_BRIDGE_FLAGS] = { .type = NETLINK_TYPE_U16 }, - [IFLA_BRIDGE_MODE] = { .type = NETLINK_TYPE_U16 }, -/* - [IFLA_BRIDGE_VLAN_INFO] = { .type = NETLINK_TYPE_BINARY, - .len = sizeof(struct bridge_vlan_info), }, -*/ -}; - -static const NLType rtnl_link_info_data_vlan_types[IFLA_VLAN_MAX + 1] = { - [IFLA_VLAN_ID] = { .type = NETLINK_TYPE_U16 }, -/* - [IFLA_VLAN_FLAGS] = { .len = sizeof(struct ifla_vlan_flags) }, - [IFLA_VLAN_EGRESS_QOS] = { .type = NETLINK_TYPE_NESTED }, - [IFLA_VLAN_INGRESS_QOS] = { .type = NETLINK_TYPE_NESTED }, -*/ - [IFLA_VLAN_PROTOCOL] = { .type = NETLINK_TYPE_U16 }, -}; - -static const NLType rtnl_link_info_data_vxlan_types[IFLA_VXLAN_MAX+1] = { - [IFLA_VXLAN_ID] = { .type = NETLINK_TYPE_U32 }, - [IFLA_VXLAN_GROUP] = { .type = NETLINK_TYPE_IN_ADDR }, - [IFLA_VXLAN_LINK] = { .type = NETLINK_TYPE_U32 }, - [IFLA_VXLAN_LOCAL] = { .type = NETLINK_TYPE_U32}, - [IFLA_VXLAN_TTL] = { .type = NETLINK_TYPE_U8 }, - [IFLA_VXLAN_TOS] = { .type = NETLINK_TYPE_U8 }, - [IFLA_VXLAN_LEARNING] = { .type = NETLINK_TYPE_U8 }, - [IFLA_VXLAN_AGEING] = { .type = NETLINK_TYPE_U32 }, - [IFLA_VXLAN_LIMIT] = { .type = NETLINK_TYPE_U32 }, - [IFLA_VXLAN_PORT_RANGE] = { .type = NETLINK_TYPE_U32}, - [IFLA_VXLAN_PROXY] = { .type = NETLINK_TYPE_U8 }, - [IFLA_VXLAN_RSC] = { .type = NETLINK_TYPE_U8 }, - [IFLA_VXLAN_L2MISS] = { .type = NETLINK_TYPE_U8 }, - [IFLA_VXLAN_L3MISS] = { .type = NETLINK_TYPE_U8 }, - [IFLA_VXLAN_PORT] = { .type = NETLINK_TYPE_U16 }, - [IFLA_VXLAN_GROUP6] = { .type = NETLINK_TYPE_IN_ADDR }, - [IFLA_VXLAN_LOCAL6] = { .type = NETLINK_TYPE_IN_ADDR }, - [IFLA_VXLAN_UDP_CSUM] = { .type = NETLINK_TYPE_U8 }, - [IFLA_VXLAN_UDP_ZERO_CSUM6_TX] = { .type = NETLINK_TYPE_U8 }, - [IFLA_VXLAN_UDP_ZERO_CSUM6_RX] = { .type = NETLINK_TYPE_U8 }, - [IFLA_VXLAN_REMCSUM_TX] = { .type = NETLINK_TYPE_U8 }, - [IFLA_VXLAN_REMCSUM_RX] = { .type = NETLINK_TYPE_U8 }, - [IFLA_VXLAN_GBP] = { .type = NETLINK_TYPE_FLAG }, - [IFLA_VXLAN_REMCSUM_NOPARTIAL] = { .type = NETLINK_TYPE_FLAG }, -}; - -static const NLType rtnl_bond_arp_target_types[BOND_ARP_TARGETS_MAX + 1] = { - [BOND_ARP_TARGETS_0] = { .type = NETLINK_TYPE_U32 }, - [BOND_ARP_TARGETS_1] = { .type = NETLINK_TYPE_U32 }, - [BOND_ARP_TARGETS_2] = { .type = NETLINK_TYPE_U32 }, - [BOND_ARP_TARGETS_3] = { .type = NETLINK_TYPE_U32 }, - [BOND_ARP_TARGETS_4] = { .type = NETLINK_TYPE_U32 }, - [BOND_ARP_TARGETS_5] = { .type = NETLINK_TYPE_U32 }, - [BOND_ARP_TARGETS_6] = { .type = NETLINK_TYPE_U32 }, - [BOND_ARP_TARGETS_7] = { .type = NETLINK_TYPE_U32 }, - [BOND_ARP_TARGETS_8] = { .type = NETLINK_TYPE_U32 }, - [BOND_ARP_TARGETS_9] = { .type = NETLINK_TYPE_U32 }, - [BOND_ARP_TARGETS_10] = { .type = NETLINK_TYPE_U32 }, - [BOND_ARP_TARGETS_11] = { .type = NETLINK_TYPE_U32 }, - [BOND_ARP_TARGETS_12] = { .type = NETLINK_TYPE_U32 }, - [BOND_ARP_TARGETS_13] = { .type = NETLINK_TYPE_U32 }, - [BOND_ARP_TARGETS_14] = { .type = NETLINK_TYPE_U32 }, - [BOND_ARP_TARGETS_MAX] = { .type = NETLINK_TYPE_U32 }, -}; - -static const NLTypeSystem rtnl_bond_arp_type_system = { - .count = ELEMENTSOF(rtnl_bond_arp_target_types), - .types = rtnl_bond_arp_target_types, -}; - -static const NLType rtnl_link_info_data_bond_types[IFLA_BOND_MAX + 1] = { - [IFLA_BOND_MODE] = { .type = NETLINK_TYPE_U8 }, - [IFLA_BOND_ACTIVE_SLAVE] = { .type = NETLINK_TYPE_U32 }, - [IFLA_BOND_MIIMON] = { .type = NETLINK_TYPE_U32 }, - [IFLA_BOND_UPDELAY] = { .type = NETLINK_TYPE_U32 }, - [IFLA_BOND_DOWNDELAY] = { .type = NETLINK_TYPE_U32 }, - [IFLA_BOND_USE_CARRIER] = { .type = NETLINK_TYPE_U8 }, - [IFLA_BOND_ARP_INTERVAL] = { .type = NETLINK_TYPE_U32 }, - [IFLA_BOND_ARP_IP_TARGET] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bond_arp_type_system }, - [IFLA_BOND_ARP_VALIDATE] = { .type = NETLINK_TYPE_U32 }, - [IFLA_BOND_ARP_ALL_TARGETS] = { .type = NETLINK_TYPE_U32 }, - [IFLA_BOND_PRIMARY] = { .type = NETLINK_TYPE_U32 }, - [IFLA_BOND_PRIMARY_RESELECT] = { .type = NETLINK_TYPE_U8 }, - [IFLA_BOND_FAIL_OVER_MAC] = { .type = NETLINK_TYPE_U8 }, - [IFLA_BOND_XMIT_HASH_POLICY] = { .type = NETLINK_TYPE_U8 }, - [IFLA_BOND_RESEND_IGMP] = { .type = NETLINK_TYPE_U32 }, - [IFLA_BOND_NUM_PEER_NOTIF] = { .type = NETLINK_TYPE_U8 }, - [IFLA_BOND_ALL_SLAVES_ACTIVE] = { .type = NETLINK_TYPE_U8 }, - [IFLA_BOND_MIN_LINKS] = { .type = NETLINK_TYPE_U32 }, - [IFLA_BOND_LP_INTERVAL] = { .type = NETLINK_TYPE_U32 }, - [IFLA_BOND_PACKETS_PER_SLAVE] = { .type = NETLINK_TYPE_U32 }, - [IFLA_BOND_AD_LACP_RATE] = { .type = NETLINK_TYPE_U8 }, - [IFLA_BOND_AD_SELECT] = { .type = NETLINK_TYPE_U8 }, - [IFLA_BOND_AD_INFO] = { .type = NETLINK_TYPE_NESTED }, -}; - -static const NLType rtnl_link_info_data_iptun_types[IFLA_IPTUN_MAX + 1] = { - [IFLA_IPTUN_LINK] = { .type = NETLINK_TYPE_U32 }, - [IFLA_IPTUN_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR }, - [IFLA_IPTUN_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR }, - [IFLA_IPTUN_TTL] = { .type = NETLINK_TYPE_U8 }, - [IFLA_IPTUN_TOS] = { .type = NETLINK_TYPE_U8 }, - [IFLA_IPTUN_PMTUDISC] = { .type = NETLINK_TYPE_U8 }, - [IFLA_IPTUN_FLAGS] = { .type = NETLINK_TYPE_U16 }, - [IFLA_IPTUN_PROTO] = { .type = NETLINK_TYPE_U8 }, - [IFLA_IPTUN_6RD_PREFIX] = { .type = NETLINK_TYPE_IN_ADDR }, - [IFLA_IPTUN_6RD_RELAY_PREFIX] = { .type = NETLINK_TYPE_U32 }, - [IFLA_IPTUN_6RD_PREFIXLEN] = { .type = NETLINK_TYPE_U16 }, - [IFLA_IPTUN_6RD_RELAY_PREFIXLEN] = { .type = NETLINK_TYPE_U16 }, - [IFLA_IPTUN_ENCAP_TYPE] = { .type = NETLINK_TYPE_U16 }, - [IFLA_IPTUN_ENCAP_FLAGS] = { .type = NETLINK_TYPE_U16 }, - [IFLA_IPTUN_ENCAP_SPORT] = { .type = NETLINK_TYPE_U16 }, - [IFLA_IPTUN_ENCAP_DPORT] = { .type = NETLINK_TYPE_U16 }, -}; - -static const NLType rtnl_link_info_data_ipgre_types[IFLA_GRE_MAX + 1] = { - [IFLA_GRE_LINK] = { .type = NETLINK_TYPE_U32 }, - [IFLA_GRE_IFLAGS] = { .type = NETLINK_TYPE_U16 }, - [IFLA_GRE_OFLAGS] = { .type = NETLINK_TYPE_U16 }, - [IFLA_GRE_IKEY] = { .type = NETLINK_TYPE_U32 }, - [IFLA_GRE_OKEY] = { .type = NETLINK_TYPE_U32 }, - [IFLA_GRE_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR }, - [IFLA_GRE_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR }, - [IFLA_GRE_TTL] = { .type = NETLINK_TYPE_U8 }, - [IFLA_GRE_TOS] = { .type = NETLINK_TYPE_U8 }, - [IFLA_GRE_PMTUDISC] = { .type = NETLINK_TYPE_U8 }, - [IFLA_GRE_FLOWINFO] = { .type = NETLINK_TYPE_U32 }, - [IFLA_GRE_FLAGS] = { .type = NETLINK_TYPE_U32 }, - [IFLA_GRE_ENCAP_TYPE] = { .type = NETLINK_TYPE_U16 }, - [IFLA_GRE_ENCAP_FLAGS] = { .type = NETLINK_TYPE_U16 }, - [IFLA_GRE_ENCAP_SPORT] = { .type = NETLINK_TYPE_U16 }, - [IFLA_GRE_ENCAP_DPORT] = { .type = NETLINK_TYPE_U16 }, -}; - -static const NLType rtnl_link_info_data_ipvti_types[IFLA_VTI_MAX + 1] = { - [IFLA_VTI_LINK] = { .type = NETLINK_TYPE_U32 }, - [IFLA_VTI_IKEY] = { .type = NETLINK_TYPE_U32 }, - [IFLA_VTI_OKEY] = { .type = NETLINK_TYPE_U32 }, - [IFLA_VTI_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR }, - [IFLA_VTI_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR }, -}; - -static const NLType rtnl_link_info_data_ip6tnl_types[IFLA_IPTUN_MAX + 1] = { - [IFLA_IPTUN_LINK] = { .type = NETLINK_TYPE_U32 }, - [IFLA_IPTUN_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR }, - [IFLA_IPTUN_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR }, - [IFLA_IPTUN_TTL] = { .type = NETLINK_TYPE_U8 }, - [IFLA_IPTUN_FLAGS] = { .type = NETLINK_TYPE_U32 }, - [IFLA_IPTUN_PROTO] = { .type = NETLINK_TYPE_U8 }, - [IFLA_IPTUN_ENCAP_LIMIT] = { .type = NETLINK_TYPE_U8 }, - [IFLA_IPTUN_FLOWINFO] = { .type = NETLINK_TYPE_U32 }, -}; - -/* these strings must match the .kind entries in the kernel */ -static const char* const nl_union_link_info_data_table[_NL_UNION_LINK_INFO_DATA_MAX] = { - [NL_UNION_LINK_INFO_DATA_BOND] = "bond", - [NL_UNION_LINK_INFO_DATA_BRIDGE] = "bridge", - [NL_UNION_LINK_INFO_DATA_VLAN] = "vlan", - [NL_UNION_LINK_INFO_DATA_VETH] = "veth", - [NL_UNION_LINK_INFO_DATA_DUMMY] = "dummy", - [NL_UNION_LINK_INFO_DATA_MACVLAN] = "macvlan", - [NL_UNION_LINK_INFO_DATA_MACVTAP] = "macvtap", - [NL_UNION_LINK_INFO_DATA_IPVLAN] = "ipvlan", - [NL_UNION_LINK_INFO_DATA_VXLAN] = "vxlan", - [NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL] = "ipip", - [NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL] = "gre", - [NL_UNION_LINK_INFO_DATA_IPGRETAP_TUNNEL] = "gretap", - [NL_UNION_LINK_INFO_DATA_IP6GRE_TUNNEL] = "ip6gre", - [NL_UNION_LINK_INFO_DATA_IP6GRETAP_TUNNEL] = "ip6gretap", - [NL_UNION_LINK_INFO_DATA_SIT_TUNNEL] = "sit", - [NL_UNION_LINK_INFO_DATA_VTI_TUNNEL] = "vti", - [NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL] = "vti6", - [NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] = "ip6tnl", -}; - -DEFINE_STRING_TABLE_LOOKUP(nl_union_link_info_data, NLUnionLinkInfoData); - -static const NLTypeSystem rtnl_link_info_data_type_systems[_NL_UNION_LINK_INFO_DATA_MAX] = { - [NL_UNION_LINK_INFO_DATA_BOND] = { .count = ELEMENTSOF(rtnl_link_info_data_bond_types), - .types = rtnl_link_info_data_bond_types }, - [NL_UNION_LINK_INFO_DATA_BRIDGE] = { .count = ELEMENTSOF(rtnl_link_info_data_bridge_types), - .types = rtnl_link_info_data_bridge_types }, - [NL_UNION_LINK_INFO_DATA_VLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_vlan_types), - .types = rtnl_link_info_data_vlan_types }, - [NL_UNION_LINK_INFO_DATA_VETH] = { .count = ELEMENTSOF(rtnl_link_info_data_veth_types), - .types = rtnl_link_info_data_veth_types }, - [NL_UNION_LINK_INFO_DATA_MACVLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_macvlan_types), - .types = rtnl_link_info_data_macvlan_types }, - [NL_UNION_LINK_INFO_DATA_MACVTAP] = { .count = ELEMENTSOF(rtnl_link_info_data_macvlan_types), - .types = rtnl_link_info_data_macvlan_types }, - [NL_UNION_LINK_INFO_DATA_IPVLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvlan_types), - .types = rtnl_link_info_data_ipvlan_types }, - [NL_UNION_LINK_INFO_DATA_VXLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_vxlan_types), - .types = rtnl_link_info_data_vxlan_types }, - [NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_iptun_types), - .types = rtnl_link_info_data_iptun_types }, - [NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types), - .types = rtnl_link_info_data_ipgre_types }, - [NL_UNION_LINK_INFO_DATA_IPGRETAP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types), - .types = rtnl_link_info_data_ipgre_types }, - [NL_UNION_LINK_INFO_DATA_IP6GRE_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types), - .types = rtnl_link_info_data_ipgre_types }, - [NL_UNION_LINK_INFO_DATA_IP6GRETAP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types), - .types = rtnl_link_info_data_ipgre_types }, - [NL_UNION_LINK_INFO_DATA_SIT_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_iptun_types), - .types = rtnl_link_info_data_iptun_types }, - [NL_UNION_LINK_INFO_DATA_VTI_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvti_types), - .types = rtnl_link_info_data_ipvti_types }, - [NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvti_types), - .types = rtnl_link_info_data_ipvti_types }, - [NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ip6tnl_types), - .types = rtnl_link_info_data_ip6tnl_types }, - -}; - -static const NLTypeSystemUnion rtnl_link_info_data_type_system_union = { - .num = _NL_UNION_LINK_INFO_DATA_MAX, - .lookup = nl_union_link_info_data_from_string, - .type_systems = rtnl_link_info_data_type_systems, - .match_type = NL_MATCH_SIBLING, - .match = IFLA_INFO_KIND, -}; - -static const NLType rtnl_link_info_types[IFLA_INFO_MAX + 1] = { - [IFLA_INFO_KIND] = { .type = NETLINK_TYPE_STRING }, - [IFLA_INFO_DATA] = { .type = NETLINK_TYPE_UNION, .type_system_union = &rtnl_link_info_data_type_system_union}, -/* - [IFLA_INFO_XSTATS], - [IFLA_INFO_SLAVE_KIND] = { .type = NETLINK_TYPE_STRING }, - [IFLA_INFO_SLAVE_DATA] = { .type = NETLINK_TYPE_NESTED }, -*/ -}; - -static const NLTypeSystem rtnl_link_info_type_system = { - .count = ELEMENTSOF(rtnl_link_info_types), - .types = rtnl_link_info_types, -}; - -static const struct NLType rtnl_prot_info_bridge_port_types[IFLA_BRPORT_MAX + 1] = { - [IFLA_BRPORT_STATE] = { .type = NETLINK_TYPE_U8 }, - [IFLA_BRPORT_COST] = { .type = NETLINK_TYPE_U32 }, - [IFLA_BRPORT_PRIORITY] = { .type = NETLINK_TYPE_U16 }, - [IFLA_BRPORT_MODE] = { .type = NETLINK_TYPE_U8 }, - [IFLA_BRPORT_GUARD] = { .type = NETLINK_TYPE_U8 }, - [IFLA_BRPORT_PROTECT] = { .type = NETLINK_TYPE_U8 }, - [IFLA_BRPORT_FAST_LEAVE] = { .type = NETLINK_TYPE_U8 }, - [IFLA_BRPORT_LEARNING] = { .type = NETLINK_TYPE_U8 }, - [IFLA_BRPORT_UNICAST_FLOOD] = { .type = NETLINK_TYPE_U8 }, - [IFLA_BRPORT_PROXYARP] = { .type = NETLINK_TYPE_U8 }, - [IFLA_BRPORT_LEARNING_SYNC] = { .type = NETLINK_TYPE_U8 }, -}; - -static const NLTypeSystem rtnl_prot_info_type_systems[AF_MAX] = { - [AF_BRIDGE] = { .count = ELEMENTSOF(rtnl_prot_info_bridge_port_types), - .types = rtnl_prot_info_bridge_port_types }, -}; - -static const NLTypeSystemUnion rtnl_prot_info_type_system_union = { - .num = AF_MAX, - .type_systems = rtnl_prot_info_type_systems, - .match_type = NL_MATCH_PROTOCOL, -}; - -static const struct NLType rtnl_af_spec_inet6_types[IFLA_INET6_MAX + 1] = { - [IFLA_INET6_FLAGS] = { .type = NETLINK_TYPE_U32 }, -/* - IFLA_INET6_CONF, - IFLA_INET6_STATS, - IFLA_INET6_MCAST, - IFLA_INET6_CACHEINFO, - IFLA_INET6_ICMP6STATS, -*/ - [IFLA_INET6_TOKEN] = { .type = NETLINK_TYPE_IN_ADDR }, - [IFLA_INET6_ADDR_GEN_MODE] = { .type = NETLINK_TYPE_U8 }, -}; - -static const NLTypeSystem rtnl_af_spec_inet6_type_system = { - .count = ELEMENTSOF(rtnl_af_spec_inet6_types), - .types = rtnl_af_spec_inet6_types, -}; - -static const NLType rtnl_af_spec_types[AF_MAX + 1] = { - [AF_INET6] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_af_spec_inet6_type_system }, -}; - -static const NLTypeSystem rtnl_af_spec_type_system = { - .count = ELEMENTSOF(rtnl_af_spec_types), - .types = rtnl_af_spec_types, -}; - -static const NLType rtnl_link_types[IFLA_MAX + 1 ] = { - [IFLA_ADDRESS] = { .type = NETLINK_TYPE_ETHER_ADDR }, - [IFLA_BROADCAST] = { .type = NETLINK_TYPE_ETHER_ADDR }, - [IFLA_IFNAME] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ - 1 }, - [IFLA_MTU] = { .type = NETLINK_TYPE_U32 }, - [IFLA_LINK] = { .type = NETLINK_TYPE_U32 }, -/* - [IFLA_QDISC], - [IFLA_STATS], - [IFLA_COST], - [IFLA_PRIORITY], -*/ - [IFLA_MASTER] = { .type = NETLINK_TYPE_U32 }, -/* - [IFLA_WIRELESS], -*/ - [IFLA_PROTINFO] = { .type = NETLINK_TYPE_UNION, .type_system_union = &rtnl_prot_info_type_system_union }, - [IFLA_TXQLEN] = { .type = NETLINK_TYPE_U32 }, -/* - [IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) }, -*/ - [IFLA_WEIGHT] = { .type = NETLINK_TYPE_U32 }, - [IFLA_OPERSTATE] = { .type = NETLINK_TYPE_U8 }, - [IFLA_LINKMODE] = { .type = NETLINK_TYPE_U8 }, - [IFLA_LINKINFO] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_info_type_system }, - [IFLA_NET_NS_PID] = { .type = NETLINK_TYPE_U32 }, - [IFLA_IFALIAS] = { .type = NETLINK_TYPE_STRING, .size = IFALIASZ - 1 }, -/* - [IFLA_NUM_VF], - [IFLA_VFINFO_LIST] = {. type = NETLINK_TYPE_NESTED, }, - [IFLA_STATS64], - [IFLA_VF_PORTS] = { .type = NETLINK_TYPE_NESTED }, - [IFLA_PORT_SELF] = { .type = NETLINK_TYPE_NESTED }, -*/ - [IFLA_AF_SPEC] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_af_spec_type_system }, -/* - [IFLA_VF_PORTS], - [IFLA_PORT_SELF], - [IFLA_AF_SPEC], -*/ - [IFLA_GROUP] = { .type = NETLINK_TYPE_U32 }, - [IFLA_NET_NS_FD] = { .type = NETLINK_TYPE_U32 }, - [IFLA_EXT_MASK] = { .type = NETLINK_TYPE_U32 }, - [IFLA_PROMISCUITY] = { .type = NETLINK_TYPE_U32 }, - [IFLA_NUM_TX_QUEUES] = { .type = NETLINK_TYPE_U32 }, - [IFLA_NUM_RX_QUEUES] = { .type = NETLINK_TYPE_U32 }, - [IFLA_CARRIER] = { .type = NETLINK_TYPE_U8 }, -/* - [IFLA_PHYS_PORT_ID] = { .type = NETLINK_TYPE_BINARY, .len = MAX_PHYS_PORT_ID_LEN }, -*/ -}; - -static const NLTypeSystem rtnl_link_type_system = { - .count = ELEMENTSOF(rtnl_link_types), - .types = rtnl_link_types, -}; - -/* IFA_FLAGS was defined in kernel 3.14, but we still support older - * kernels where IFA_MAX is lower. */ -static const NLType rtnl_address_types[CONST_MAX(IFA_MAX, IFA_FLAGS) + 1] = { - [IFA_ADDRESS] = { .type = NETLINK_TYPE_IN_ADDR }, - [IFA_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR }, - [IFA_LABEL] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ - 1 }, - [IFA_BROADCAST] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */ - [IFA_CACHEINFO] = { .type = NETLINK_TYPE_CACHE_INFO, .size = sizeof(struct ifa_cacheinfo) }, -/* - [IFA_ANYCAST], - [IFA_MULTICAST], -*/ - [IFA_FLAGS] = { .type = NETLINK_TYPE_U32 }, -}; - -static const NLTypeSystem rtnl_address_type_system = { - .count = ELEMENTSOF(rtnl_address_types), - .types = rtnl_address_types, -}; - -static const NLType rtnl_route_types[RTA_MAX + 1] = { - [RTA_DST] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */ - [RTA_SRC] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */ - [RTA_IIF] = { .type = NETLINK_TYPE_U32 }, - [RTA_OIF] = { .type = NETLINK_TYPE_U32 }, - [RTA_GATEWAY] = { .type = NETLINK_TYPE_IN_ADDR }, - [RTA_PRIORITY] = { .type = NETLINK_TYPE_U32 }, - [RTA_PREFSRC] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */ -/* - [RTA_METRICS] = { .type = NETLINK_TYPE_NESTED }, - [RTA_MULTIPATH] = { .len = sizeof(struct rtnexthop) }, -*/ - [RTA_FLOW] = { .type = NETLINK_TYPE_U32 }, /* 6? */ -/* - RTA_CACHEINFO, - RTA_TABLE, - RTA_MARK, - RTA_MFC_STATS, -*/ -}; - -static const NLTypeSystem rtnl_route_type_system = { - .count = ELEMENTSOF(rtnl_route_types), - .types = rtnl_route_types, -}; - -static const NLType rtnl_neigh_types[NDA_MAX + 1] = { - [NDA_DST] = { .type = NETLINK_TYPE_IN_ADDR }, - [NDA_LLADDR] = { .type = NETLINK_TYPE_ETHER_ADDR }, - [NDA_CACHEINFO] = { .type = NETLINK_TYPE_CACHE_INFO, .size = sizeof(struct nda_cacheinfo) }, - [NDA_PROBES] = { .type = NETLINK_TYPE_U32 }, - [NDA_VLAN] = { .type = NETLINK_TYPE_U16 }, - [NDA_PORT] = { .type = NETLINK_TYPE_U16 }, - [NDA_VNI] = { .type = NETLINK_TYPE_U32 }, - [NDA_IFINDEX] = { .type = NETLINK_TYPE_U32 }, -}; - -static const NLTypeSystem rtnl_neigh_type_system = { - .count = ELEMENTSOF(rtnl_neigh_types), - .types = rtnl_neigh_types, -}; - -static const NLType rtnl_types[RTM_MAX + 1] = { - [NLMSG_DONE] = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system, .size = 0 }, - [NLMSG_ERROR] = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system, .size = sizeof(struct nlmsgerr) }, - [RTM_NEWLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, - [RTM_DELLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, - [RTM_GETLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, - [RTM_SETLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, - [RTM_NEWADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) }, - [RTM_DELADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) }, - [RTM_GETADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) }, - [RTM_NEWROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) }, - [RTM_DELROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) }, - [RTM_GETROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) }, - [RTM_NEWNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) }, - [RTM_DELNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) }, - [RTM_GETNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) }, -}; - -const NLTypeSystem type_system_root = { - .count = ELEMENTSOF(rtnl_types), - .types = rtnl_types, -}; - -uint16_t type_get_type(const NLType *type) { - assert(type); - return type->type; -} - -size_t type_get_size(const NLType *type) { - assert(type); - return type->size; -} - -void type_get_type_system(const NLType *nl_type, const NLTypeSystem **ret) { - assert(nl_type); - assert(ret); - assert(nl_type->type == NETLINK_TYPE_NESTED); - assert(nl_type->type_system); - - *ret = nl_type->type_system; -} - -void type_get_type_system_union(const NLType *nl_type, const NLTypeSystemUnion **ret) { - assert(nl_type); - assert(ret); - assert(nl_type->type == NETLINK_TYPE_UNION); - assert(nl_type->type_system_union); - - *ret = nl_type->type_system_union; -} - -uint16_t type_system_get_count(const NLTypeSystem *type_system) { - assert(type_system); - return type_system->count; -} - -int type_system_get_type(const NLTypeSystem *type_system, const NLType **ret, uint16_t type) { - const NLType *nl_type; - - assert(ret); - assert(type_system); - assert(type_system->types); - - if (type >= type_system->count) - return -EOPNOTSUPP; - - nl_type = &type_system->types[type]; - - if (nl_type->type == NETLINK_TYPE_UNSPEC) - return -EOPNOTSUPP; - - *ret = nl_type; - - return 0; -} - -int type_system_get_type_system(const NLTypeSystem *type_system, const NLTypeSystem **ret, uint16_t type) { - const NLType *nl_type; - int r; - - assert(ret); - - r = type_system_get_type(type_system, &nl_type, type); - if (r < 0) - return r; - - type_get_type_system(nl_type, ret); - return 0; -} - -int type_system_get_type_system_union(const NLTypeSystem *type_system, const NLTypeSystemUnion **ret, uint16_t type) { - const NLType *nl_type; - int r; - - assert(ret); - - r = type_system_get_type(type_system, &nl_type, type); - if (r < 0) - return r; - - type_get_type_system_union(nl_type, ret); - return 0; -} - -int type_system_union_get_type_system(const NLTypeSystemUnion *type_system_union, const NLTypeSystem **ret, const char *key) { - int type; - - assert(type_system_union); - assert(type_system_union->match_type == NL_MATCH_SIBLING); - assert(type_system_union->lookup); - assert(type_system_union->type_systems); - assert(ret); - assert(key); - - type = type_system_union->lookup(key); - if (type < 0) - return -EOPNOTSUPP; - - assert(type < type_system_union->num); - - *ret = &type_system_union->type_systems[type]; - - return 0; -} - -int type_system_union_protocol_get_type_system(const NLTypeSystemUnion *type_system_union, const NLTypeSystem **ret, uint16_t protocol) { - const NLTypeSystem *type_system; - - assert(type_system_union); - assert(type_system_union->type_systems); - assert(type_system_union->match_type == NL_MATCH_PROTOCOL); - assert(ret); - - if (protocol >= type_system_union->num) - return -EOPNOTSUPP; - - type_system = &type_system_union->type_systems[protocol]; - if (!type_system->types) - return -EOPNOTSUPP; - - *ret = type_system; - - return 0; -} diff --git a/src/login/logind-button.h b/src/login/logind-button.h index 95bb6a524..80d93c7e6 100644 --- a/src/login/logind-button.h +++ b/src/login/logind-button.h @@ -5,7 +5,7 @@ /*** This file is part of systemd. - Copyright 2014 Daniel Mack + Copyright 2012 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 @@ -21,24 +21,26 @@ along with systemd; If not, see . ***/ -typedef struct BusEndpoint BusEndpoint; -typedef struct BusEndpointPolicy BusEndpointPolicy; +typedef struct Button Button; -#include "hashmap.h" -#include "bus-policy.h" +#include "logind.h" -struct BusEndpointPolicy { - char *name; - BusPolicyAccess access; -}; +struct Button { + Manager *manager; -struct BusEndpoint { - Hashmap *policy_hash; -}; + sd_event_source *io_event_source; + sd_event_source *check_event_source; -// UNNEEDED int bus_endpoint_new(BusEndpoint **ep); -void bus_endpoint_free(BusEndpoint *endpoint); + char *name; + char *seat; + int fd; -// UNNEEDED int bus_endpoint_add_policy(BusEndpoint *ep, const char *name, BusPolicyAccess access); + bool lid_closed; + bool docked; +}; -int bus_kernel_set_endpoint_policy(int fd, uid_t uid, BusEndpoint *ep); +Button* button_new(Manager *m, const char *name); +void button_free(Button*b); +int button_open(Button *b); +int button_set_seat(Button *b, const char *sn); +int button_check_switches(Button *b); diff --git a/src/login/logind-core.c b/src/login/logind-core.c index 2b4d6ff0b..fe97c1de0 100644 --- a/src/login/logind-core.c +++ b/src/login/logind-core.c @@ -354,7 +354,7 @@ int manager_get_user_by_pid(Manager *m, pid_t pid, User **user) { int manager_get_idle_hint(Manager *m, dual_timestamp *t) { Session *s; bool idle_hint; - dual_timestamp ts = { 0, 0 }; + dual_timestamp ts = DUAL_TIMESTAMP_NULL; Iterator i; assert(m); @@ -474,7 +474,7 @@ int manager_spawn_autovt(Manager *m, unsigned int vtnr) { } #endif // 0 -bool manager_is_docked(Manager *m) { +static bool manager_is_docked(Manager *m) { Iterator i; Button *b; @@ -485,7 +485,7 @@ bool manager_is_docked(Manager *m) { return false; } -int manager_count_displays(Manager *m) { +static int manager_count_external_displays(Manager *m) { _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; struct udev_list_entry *item = NULL, *first = NULL; int r; @@ -507,7 +507,8 @@ int manager_count_displays(Manager *m) { udev_list_entry_foreach(item, first) { _cleanup_udev_device_unref_ struct udev_device *d = NULL; struct udev_device *p; - const char *status; + const char *status, *enabled, *dash, *nn, *i; + bool external = false; d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item)); if (!d) @@ -523,6 +524,40 @@ int manager_count_displays(Manager *m) { if (!streq_ptr(udev_device_get_subsystem(p), "drm")) continue; + nn = udev_device_get_sysname(d); + if (!nn) + continue; + + /* Ignore internal displays: the type is encoded in + * the sysfs name, as the second dash seperated item + * (the first is the card name, the last the connector + * number). We implement a whitelist of external + * displays here, rather than a whitelist, to ensure + * we don't block suspends too eagerly. */ + dash = strchr(nn, '-'); + if (!dash) + continue; + + dash++; + FOREACH_STRING(i, "VGA-", "DVI-I-", "DVI-D-", "DVI-A-" + "Composite-", "SVIDEO-", "Component-", + "DIN-", "DP-", "HDMI-A-", "HDMI-B-", "TV-") { + + if (startswith(dash, i)) { + external = true; + break; + } + } + if (!external) + continue; + + /* Ignore ports that are not enabled */ + enabled = udev_device_get_sysattr_value(d, "enabled"); + if (!enabled) + continue; + if (!streq_ptr(enabled, "enabled")) + continue; + /* We count any connector which is not explicitly * "disconnected" as connected. */ status = udev_device_get_sysattr_value(d, "status"); @@ -533,7 +568,7 @@ int manager_count_displays(Manager *m) { return n; } -bool manager_is_docked_or_multiple_displays(Manager *m) { +bool manager_is_docked_or_external_displays(Manager *m) { int n; /* If we are docked don't react to lid closing */ @@ -544,11 +579,11 @@ bool manager_is_docked_or_multiple_displays(Manager *m) { /* If we have more than one display connected, * assume that we are docked. */ - n = manager_count_displays(m); + n = manager_count_external_displays(m); if (n < 0) log_warning_errno(n, "Display counting failed: %m"); - else if (n > 1) { - log_debug("Multiple (%i) displays connected.", n); + else if (n >= 1) { + log_debug("External (%i) displays connected.", n); return true; } diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 800e2a51b..e59795eed 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -158,7 +158,7 @@ static int property_get_idle_since_hint( sd_bus_error *error) { Manager *m = userdata; - dual_timestamp t; + dual_timestamp t = DUAL_TIMESTAMP_NULL; assert(bus); assert(reply); @@ -243,6 +243,24 @@ static int property_get_scheduled_shutdown( static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction); +static int property_get_docked( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + + assert(bus); + assert(reply); + assert(m); + + return sd_bus_message_append(reply, "b", manager_is_docked_or_external_displays(m)); +} + static int method_get_session(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_free_ char *p = NULL; Manager *m = userdata; @@ -671,45 +689,26 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus return r; } - manager_get_session_by_pid(m, leader, &session); - if (session) { - _cleanup_free_ char *path = NULL; - _cleanup_close_ int fifo_fd = -1; - - /* Session already exists, client is probably - * something like "su" which changes uid but is still - * the same session */ - - fifo_fd = session_create_fifo(session); - if (fifo_fd < 0) - return fifo_fd; - - path = session_bus_path(session); - if (!path) - return -ENOMEM; - - log_debug("Sending reply about an existing session: " - "id=%s object_path=%s uid=%u runtime_path=%s " - "session_fd=%d seat=%s vtnr=%u", - session->id, - path, - (uint32_t) session->user->uid, - session->user->runtime_path, - fifo_fd, - session->seat ? session->seat->id : "", - (uint32_t) session->vtnr); - - return sd_bus_reply_method_return( - message, "soshusub", - session->id, - path, - session->user->runtime_path, - fifo_fd, - (uint32_t) session->user->uid, - session->seat ? session->seat->id : "", - (uint32_t) session->vtnr, - true); - } + r = manager_get_session_by_pid(m, leader, NULL); + if (r > 0) + return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already running in a session"); + + /* + * Old gdm and lightdm start the user-session on the same VT as + * the greeter session. But they destroy the greeter session + * after the user-session and want the user-session to take + * over the VT. We need to support this for + * backwards-compatibility, so make sure we allow new sessions + * on a VT that a greeter is running on. Furthermore, to allow + * re-logins, we have to allow a greeter to take over a used VT for + * the exact same reasons. + */ + if (c != SESSION_GREETER && + vtnr > 0 && + vtnr < m->seat0->position_count && + m->seat0->positions[vtnr] && + m->seat0->positions[vtnr]->class != SESSION_GREETER) + return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already occupied by a session"); audit_session_from_pid(leader, &audit_id); if (audit_id > 0) { @@ -825,8 +824,6 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus if (r < 0) goto fail; - session_save(session); - return 1; fail: @@ -1184,7 +1181,7 @@ static int trigger_device(Manager *m, struct udev_device *d) { if (!t) return -ENOMEM; - write_string_file(t, "change"); + write_string_file(t, "change", WRITE_STRING_FILE_CREATE); } return 0; @@ -1523,18 +1520,13 @@ static int execute_shutdown_or_sleep( return 0; } -static int manager_inhibit_timeout_handler( - sd_event_source *s, - uint64_t usec, - void *userdata) { +int manager_dispatch_delayed(Manager *manager, bool timeout) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; Inhibitor *offending = NULL; - Manager *manager = userdata; int r; assert(manager); - assert(manager->inhibit_timeout_source == s); if (manager->action_what == 0) return 0; @@ -1542,6 +1534,9 @@ static int manager_inhibit_timeout_handler( if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) { _cleanup_free_ char *comm = NULL, *u = NULL; + if (!timeout) + return 0; + (void) get_process_comm(offending->pid, &comm); u = uid_to_name(offending->uid); @@ -1557,9 +1552,25 @@ static int manager_inhibit_timeout_handler( manager->pending_action = HANDLE_IGNORE; manager->action_what = 0; + return r; } - return 0; + return 1; +} + +static int manager_inhibit_timeout_handler( + sd_event_source *s, + uint64_t usec, + void *userdata) { + + Manager *manager = userdata; + int r; + + assert(manager); + assert(manager->inhibit_timeout_source == s); + + r = manager_dispatch_delayed(manager, true); + return (r < 0) ? r : 0; } static int delay_shutdown_or_sleep( @@ -1790,7 +1801,7 @@ static int nologin_timeout_handler( log_info("Creating /run/nologin, blocking further logins..."); - r = write_string_file_atomic("/run/nologin", "System is going down."); + r = write_string_file("/run/nologin", "System is going down.", WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC); if (r < 0) log_error_errno(r, "Failed to create /run/nologin: %m"); else @@ -2001,6 +2012,11 @@ static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userd m->scheduled_shutdown_type = mfree(m->scheduled_shutdown_type); m->scheduled_shutdown_timeout = 0; + if (m->unlink_nologin) { + (void) unlink("/run/nologin"); + m->unlink_nologin = false; + } + if (cancelled) { _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; const char *tty = NULL; @@ -2483,6 +2499,7 @@ const sd_bus_vtable manager_vtable[] = { SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0), SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0), SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0), + SD_BUS_PROPERTY("Docked", "b", property_get_docked, 0, 0), SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED), @@ -2512,8 +2529,6 @@ const sd_bus_vtable manager_vtable[] = { SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED), @@ -2521,6 +2536,8 @@ const sd_bus_vtable manager_vtable[] = { SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED), @@ -2599,6 +2616,7 @@ int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *err session_jobs_reply(session, unit, result); session_save(session); + user_save(session->user); session_add_to_gc_queue(session); } diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c index b0db8e2cc..5d3fec411 100644 --- a/src/login/logind-session-dbus.c +++ b/src/login/logind-session-dbus.c @@ -720,9 +720,10 @@ int session_send_create_reply(Session *s, sd_bus_error *error) { if (fifo_fd < 0) return fifo_fd; - /* Update the session state file before we notify the client - * about the result. */ + /* Update the session and user state files before we notify + * the client about the result. */ session_save(s); + user_save(s->user); p = session_bus_path(s); if (!p) diff --git a/src/login/logind.c b/src/login/logind.c index 23f405993..0b7d9653a 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -30,11 +30,11 @@ #include "conf-parser.h" #include "bus-util.h" #include "bus-error.h" -#include "logind.h" #include "udev-util.h" #include "formats-util.h" +#include "signal-util.h" #include "label.h" -#include "label.h" +#include "logind.h" #include "cgroup.h" #include "mount-setup.h" #include "virt.h" @@ -203,7 +203,7 @@ static void manager_free(Manager *m) { udev_unref(m->udev); if (m->unlink_nologin) - unlink("/run/nologin"); + (void) unlink("/run/nologin"); bus_verify_polkit_async_registry_free(m->polkit_registry); @@ -869,13 +869,8 @@ static int manager_connect_console(Manager *m) { return -EINVAL; } - r = ignore_signals(SIGRTMIN + 1, -1); - if (r < 0) - return log_error_errno(r, "Cannot ignore SIGRTMIN + 1: %m"); - - r = sigprocmask_many(SIG_BLOCK, SIGRTMIN, -1); - if (r < 0) - return log_error_errno(r, "Cannot block SIGRTMIN: %m"); + assert_se(ignore_signals(SIGRTMIN + 1, -1) >= 0); + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN, -1) >= 0); r = sd_event_add_signal(m->event, NULL, SIGRTMIN, manager_vt_switch, m); if (r < 0) @@ -1202,6 +1197,12 @@ static int manager_run(Manager *m) { manager_gc(m, true); + r = manager_dispatch_delayed(m, false); + if (r < 0) + return r; + if (r > 0) + continue; + r = sd_event_run(m->event, (uint64_t) -1); if (r < 0) return r; diff --git a/src/login/logind.h b/src/login/logind.h index 29432823e..4783ea3b2 100644 --- a/src/login/logind.h +++ b/src/login/logind.h @@ -185,9 +185,7 @@ int manager_get_idle_hint(Manager *m, dual_timestamp *t); int manager_get_user_by_pid(Manager *m, pid_t pid, User **user); int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session); -bool manager_is_docked(Manager *m); -int manager_count_displays(Manager *m); -bool manager_is_docked_or_multiple_displays(Manager *m); +bool manager_is_docked_or_external_displays(Manager *m); extern const sd_bus_vtable manager_vtable[]; @@ -227,3 +225,5 @@ int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char int manager_setup_wall_message_timer(Manager *m); bool logind_wall_tty_filter(const char *tty, void *userdata); + +int manager_dispatch_delayed(Manager *manager, bool timeout); diff --git a/src/login/org.freedesktop.login1.conf b/src/login/org.freedesktop.login1.conf index c89e40457..1662d4c42 100644 --- a/src/login/org.freedesktop.login1.conf +++ b/src/login/org.freedesktop.login1.conf @@ -232,10 +232,6 @@ send_interface="org.freedesktop.login1.Session" send_member="SetIdleHint"/> - - diff --git a/src/login/org.freedesktop.login1.service b/src/login/org.freedesktop.login1.service index a30a8da60..762dae2bb 100644 --- a/src/login/org.freedesktop.login1.service +++ b/src/login/org.freedesktop.login1.service @@ -5,7 +5,8 @@ # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. -# See tmpfiles.d(5), systemd-user-session.service(5) and pam_nologin(8). -# This file has special suffix so it is not run by mistake. - -F! /run/nologin 0644 - - - "System is booting up. See pam_nologin(8)" +[D-BUS Service] +Name=org.freedesktop.login1 +Exec=/bin/false +User=root +SystemdService=dbus-org.freedesktop.login1.service diff --git a/src/login/pam_elogind.sym b/src/login/pam_elogind.sym index 8f3aed665..23ff75f68 100644 --- a/src/login/pam_elogind.sym +++ b/src/login/pam_elogind.sym @@ -11,9 +11,5 @@ global: pam_sm_close_session; pam_sm_open_session; - _nss_mymachines_getpwnam_r; - _nss_mymachines_getpwuid_r; - _nss_mymachines_getgrnam_r; - _nss_mymachines_getgrgid_r; local: *; }; diff --git a/src/login/test-login-tables.c b/src/login/test-login-tables.c index 0ee5ddcc9..a4196bf14 100644 --- a/src/login/test-login-tables.c +++ b/src/login/test-login-tables.c @@ -1,7 +1,7 @@ /*** This file is part of systemd - Copyright 2014 Zbigniew Jędrzejewski-Szmek + Copyright 2013 Zbigniew Jędrzejewski-Szmek 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 @@ -17,47 +17,19 @@ along with systemd; If not, see . ***/ -#include "set.h" +#include "logind-action.h" +#include "logind-session.h" -static void test_set_steal_first(void) { - _cleanup_set_free_ Set *m = NULL; - int seen[3] = {}; - char *val; +#include "test-tables.h" - m = set_new(&string_hash_ops); - assert_se(m); +int main(int argc, char **argv) { + test_table(handle_action, HANDLE_ACTION); + test_table(inhibit_mode, INHIBIT_MODE); + test_table(kill_who, KILL_WHO); + test_table(session_class, SESSION_CLASS); + test_table(session_state, SESSION_STATE); + test_table(session_type, SESSION_TYPE); + test_table(user_state, USER_STATE); - assert_se(set_put(m, (void*) "1") == 1); - assert_se(set_put(m, (void*) "22") == 1); - assert_se(set_put(m, (void*) "333") == 1); - - while ((val = set_steal_first(m))) - seen[strlen(val) - 1]++; - - assert_se(seen[0] == 1 && seen[1] == 1 && seen[2] == 1); - - assert_se(set_isempty(m)); -} - -static void test_set_put(void) { - _cleanup_set_free_ Set *m = NULL; - - m = set_new(&string_hash_ops); - assert_se(m); - - assert_se(set_put(m, (void*) "1") == 1); - assert_se(set_put(m, (void*) "22") == 1); - assert_se(set_put(m, (void*) "333") == 1); - assert_se(set_put(m, (void*) "333") == 0); - assert_se(set_remove(m, (void*) "333")); - assert_se(set_put(m, (void*) "333") == 1); - assert_se(set_put(m, (void*) "333") == 0); - assert_se(set_put(m, (void*) "22") == 0); -} - -int main(int argc, const char *argv[]) { - test_set_steal_first(); - test_set_put(); - - return 0; + return EXIT_SUCCESS; } diff --git a/src/shared/apparmor-util.h b/src/shared/apparmor-util.h deleted file mode 100644 index 0e206a2f2..000000000 --- a/src/shared/apparmor-util.h +++ /dev/null @@ -1,33 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2014 Zbigniew Jędrzejewski-Szmek - - 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 . -***/ - -#pragma once - -#include - -#include "path-lookup.h" - -int verify_units(char **filenames, ManagerRunningAs running_as, bool check_man); - -/* XXX: find an authoritative list of all pseudo types? */ -bool dns_type_is_pseudo(int n) { - return IN_SET(n, DNS_TYPE_ANY, DNS_TYPE_AXFR, DNS_TYPE_IXFR, DNS_TYPE_OPT); -} diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c deleted file mode 100644 index 3941605ce..000000000 --- a/src/shared/ask-password-api.c +++ /dev/null @@ -1,572 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2010 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 . -***/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "util.h" -#include "formats-util.h" -#include "mkdir.h" -#include "strv.h" -#include "random-util.h" -#include "terminal-util.h" -#include "signal-util.h" -#include "ask-password-api.h" - -static void backspace_chars(int ttyfd, size_t p) { - - if (ttyfd < 0) - return; - - while (p > 0) { - p--; - - loop_write(ttyfd, "\b \b", 3, false); - } -} - -int ask_password_tty( - const char *message, - usec_t until, - bool echo, - const char *flag_file, - char **_passphrase) { - - struct termios old_termios, new_termios; - char passphrase[LINE_MAX], *x; - size_t p = 0; - int r; - _cleanup_close_ int ttyfd = -1, notify = -1; - struct pollfd pollfd[2]; - bool reset_tty = false; - bool silent_mode = false; - bool dirty = false; - enum { - POLL_TTY, - POLL_INOTIFY - }; - - assert(message); - assert(_passphrase); - - if (flag_file) { - notify = inotify_init1(IN_CLOEXEC|IN_NONBLOCK); - if (notify < 0) { - r = -errno; - goto finish; - } - - if (inotify_add_watch(notify, flag_file, IN_ATTRIB /* for the link count */) < 0) { - r = -errno; - goto finish; - } - } - - ttyfd = open("/dev/tty", O_RDWR|O_NOCTTY|O_CLOEXEC); - if (ttyfd >= 0) { - - if (tcgetattr(ttyfd, &old_termios) < 0) { - r = -errno; - goto finish; - } - - loop_write(ttyfd, ANSI_HIGHLIGHT_ON, sizeof(ANSI_HIGHLIGHT_ON)-1, false); - loop_write(ttyfd, message, strlen(message), false); - loop_write(ttyfd, " ", 1, false); - loop_write(ttyfd, ANSI_HIGHLIGHT_OFF, sizeof(ANSI_HIGHLIGHT_OFF)-1, false); - - new_termios = old_termios; - new_termios.c_lflag &= ~(ICANON|ECHO); - new_termios.c_cc[VMIN] = 1; - new_termios.c_cc[VTIME] = 0; - - if (tcsetattr(ttyfd, TCSADRAIN, &new_termios) < 0) { - r = -errno; - goto finish; - } - - reset_tty = true; - } - - zero(pollfd); - pollfd[POLL_TTY].fd = ttyfd >= 0 ? ttyfd : STDIN_FILENO; - pollfd[POLL_TTY].events = POLLIN; - pollfd[POLL_INOTIFY].fd = notify; - pollfd[POLL_INOTIFY].events = POLLIN; - - for (;;) { - char c; - int sleep_for = -1, k; - ssize_t n; - - if (until > 0) { - usec_t y; - - y = now(CLOCK_MONOTONIC); - - if (y > until) { - r = -ETIME; - goto finish; - } - - sleep_for = (int) ((until - y) / USEC_PER_MSEC); - } - - if (flag_file) - if (access(flag_file, F_OK) < 0) { - r = -errno; - goto finish; - } - - k = poll(pollfd, notify > 0 ? 2 : 1, sleep_for); - if (k < 0) { - if (errno == EINTR) - continue; - - r = -errno; - goto finish; - } else if (k == 0) { - r = -ETIME; - goto finish; - } - - if (notify > 0 && pollfd[POLL_INOTIFY].revents != 0) - flush_fd(notify); - - if (pollfd[POLL_TTY].revents == 0) - continue; - - n = read(ttyfd >= 0 ? ttyfd : STDIN_FILENO, &c, 1); - if (n < 0) { - if (errno == EINTR || errno == EAGAIN) - continue; - - r = -errno; - goto finish; - - } else if (n == 0) - break; - - if (c == '\n') - break; - else if (c == 21) { /* C-u */ - - if (!silent_mode) - backspace_chars(ttyfd, p); - p = 0; - - } else if (c == '\b' || c == 127) { - - if (p > 0) { - - if (!silent_mode) - backspace_chars(ttyfd, 1); - - p--; - } else if (!dirty && !silent_mode) { - - silent_mode = true; - - /* There are two ways to enter silent - * mode. Either by pressing backspace - * as first key (and only as first key), - * or ... */ - if (ttyfd >= 0) - loop_write(ttyfd, "(no echo) ", 10, false); - - } else if (ttyfd >= 0) - loop_write(ttyfd, "\a", 1, false); - - } else if (c == '\t' && !silent_mode) { - - backspace_chars(ttyfd, p); - silent_mode = true; - - /* ... or by pressing TAB at any time. */ - - if (ttyfd >= 0) - loop_write(ttyfd, "(no echo) ", 10, false); - } else { - if (p >= sizeof(passphrase)-1) { - loop_write(ttyfd, "\a", 1, false); - continue; - } - - passphrase[p++] = c; - - if (!silent_mode && ttyfd >= 0) - loop_write(ttyfd, echo ? &c : "*", 1, false); - - dirty = true; - } - } - - x = strndup(passphrase, p); - if (!x) { - r = -ENOMEM; - goto finish; - } - - *_passphrase = x; - r = 0; - -finish: - if (ttyfd >= 0 && reset_tty) { - loop_write(ttyfd, "\n", 1, false); - tcsetattr(ttyfd, TCSADRAIN, &old_termios); - } - - return r; -} - -static int create_socket(char **name) { - int fd; - union { - struct sockaddr sa; - struct sockaddr_un un; - } sa = { - .un.sun_family = AF_UNIX, - }; - int one = 1; - int r = 0; - char *c; - - assert(name); - - fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); - if (fd < 0) - return log_error_errno(errno, "socket() failed: %m"); - - snprintf(sa.un.sun_path, sizeof(sa.un.sun_path)-1, "/run/systemd/ask-password/sck.%" PRIx64, random_u64()); - - RUN_WITH_UMASK(0177) { - r = bind(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)); - } - - if (r < 0) { - r = -errno; - log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path); - goto fail; - } - - if (setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0) { - r = -errno; - log_error_errno(errno, "SO_PASSCRED failed: %m"); - goto fail; - } - - c = strdup(sa.un.sun_path); - if (!c) { - r = log_oom(); - goto fail; - } - - *name = c; - return fd; - -fail: - safe_close(fd); - - return r; -} - -int ask_password_agent( - const char *message, - const char *icon, - const char *id, - usec_t until, - bool echo, - bool accept_cached, - char ***_passphrases) { - - enum { - FD_SOCKET, - FD_SIGNAL, - _FD_MAX - }; - - char temp[] = "/run/systemd/ask-password/tmp.XXXXXX"; - char final[sizeof(temp)] = ""; - _cleanup_fclose_ FILE *f = NULL; - _cleanup_free_ char *socket_name = NULL; - _cleanup_close_ int socket_fd = -1, signal_fd = -1, fd = -1; - sigset_t mask, oldmask; - struct pollfd pollfd[_FD_MAX]; - int r; - - assert(_passphrases); - - assert_se(sigemptyset(&mask) >= 0); - assert_se(sigset_add_many(&mask, SIGINT, SIGTERM, -1) >= 0); - assert_se(sigprocmask(SIG_BLOCK, &mask, &oldmask) >= 0); - - mkdir_p_label("/run/systemd/ask-password", 0755); - - fd = mkostemp_safe(temp, O_WRONLY|O_CLOEXEC); - if (fd < 0) { - log_error_errno(errno, "Failed to create password file: %m"); - r = -errno; - goto finish; - } - - fchmod(fd, 0644); - - f = fdopen(fd, "w"); - if (!f) { - log_error_errno(errno, "Failed to allocate FILE: %m"); - r = -errno; - goto finish; - } - - fd = -1; - - signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC); - if (signal_fd < 0) { - log_error_errno(errno, "signalfd(): %m"); - r = -errno; - goto finish; - } - - socket_fd = create_socket(&socket_name); - if (socket_fd < 0) { - r = socket_fd; - goto finish; - } - - fprintf(f, - "[Ask]\n" - "PID="PID_FMT"\n" - "Socket=%s\n" - "AcceptCached=%i\n" - "Echo=%i\n" - "NotAfter="USEC_FMT"\n", - getpid(), - socket_name, - accept_cached ? 1 : 0, - echo ? 1 : 0, - until); - - if (message) - fprintf(f, "Message=%s\n", message); - - if (icon) - fprintf(f, "Icon=%s\n", icon); - - if (id) - fprintf(f, "Id=%s\n", id); - - fflush(f); - - if (ferror(f)) { - log_error_errno(errno, "Failed to write query file: %m"); - r = -errno; - goto finish; - } - - memcpy(final, temp, sizeof(temp)); - - final[sizeof(final)-11] = 'a'; - final[sizeof(final)-10] = 's'; - final[sizeof(final)-9] = 'k'; - - if (rename(temp, final) < 0) { - log_error_errno(errno, "Failed to rename query file: %m"); - r = -errno; - goto finish; - } - - zero(pollfd); - pollfd[FD_SOCKET].fd = socket_fd; - pollfd[FD_SOCKET].events = POLLIN; - pollfd[FD_SIGNAL].fd = signal_fd; - pollfd[FD_SIGNAL].events = POLLIN; - - for (;;) { - char passphrase[LINE_MAX+1]; - struct msghdr msghdr; - struct iovec iovec; - struct ucred *ucred; - union { - struct cmsghdr cmsghdr; - uint8_t buf[CMSG_SPACE(sizeof(struct ucred))]; - } control; - ssize_t n; - int k; - usec_t t; - - t = now(CLOCK_MONOTONIC); - - if (until > 0 && until <= t) { - log_notice("Timed out"); - r = -ETIME; - goto finish; - } - - k = poll(pollfd, _FD_MAX, until > 0 ? (int) ((until-t)/USEC_PER_MSEC) : -1); - if (k < 0) { - if (errno == EINTR) - continue; - - log_error_errno(errno, "poll() failed: %m"); - r = -errno; - goto finish; - } - - if (k <= 0) { - log_notice("Timed out"); - r = -ETIME; - goto finish; - } - - if (pollfd[FD_SIGNAL].revents & POLLIN) { - r = -EINTR; - goto finish; - } - - if (pollfd[FD_SOCKET].revents != POLLIN) { - log_error("Unexpected poll() event."); - r = -EIO; - goto finish; - } - - zero(iovec); - iovec.iov_base = passphrase; - iovec.iov_len = sizeof(passphrase); - - zero(control); - zero(msghdr); - msghdr.msg_iov = &iovec; - msghdr.msg_iovlen = 1; - msghdr.msg_control = &control; - msghdr.msg_controllen = sizeof(control); - - n = recvmsg(socket_fd, &msghdr, 0); - if (n < 0) { - if (errno == EAGAIN || - errno == EINTR) - continue; - - log_error_errno(errno, "recvmsg() failed: %m"); - r = -errno; - goto finish; - } - - cmsg_close_all(&msghdr); - - if (n <= 0) { - log_error("Message too short"); - continue; - } - - if (msghdr.msg_controllen < CMSG_LEN(sizeof(struct ucred)) || - control.cmsghdr.cmsg_level != SOL_SOCKET || - control.cmsghdr.cmsg_type != SCM_CREDENTIALS || - control.cmsghdr.cmsg_len != CMSG_LEN(sizeof(struct ucred))) { - log_warning("Received message without credentials. Ignoring."); - continue; - } - - ucred = (struct ucred*) CMSG_DATA(&control.cmsghdr); - if (ucred->uid != 0) { - log_warning("Got request from unprivileged user. Ignoring."); - continue; - } - - if (passphrase[0] == '+') { - char **l; - - if (n == 1) - l = strv_new("", NULL); - else - l = strv_parse_nulstr(passphrase+1, n-1); - /* An empty message refers to the empty password */ - - if (!l) { - r = -ENOMEM; - goto finish; - } - - if (strv_length(l) <= 0) { - strv_free(l); - log_error("Invalid packet"); - continue; - } - - *_passphrases = l; - - } else if (passphrase[0] == '-') { - r = -ECANCELED; - goto finish; - } else { - log_error("Invalid packet"); - continue; - } - - break; - } - - r = 0; - -finish: - if (socket_name) - unlink(socket_name); - - unlink(temp); - - if (final[0]) - unlink(final); - - assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) == 0); - - return r; -} - -int ask_password_auto(const char *message, const char *icon, const char *id, - usec_t until, bool accept_cached, char ***_passphrases) { - assert(message); - assert(_passphrases); - - if (isatty(STDIN_FILENO)) { - int r; - char *s = NULL, **l = NULL; - - r = ask_password_tty(message, until, false, NULL, &s); - if (r < 0) - return r; - - r = strv_consume(&l, s); - if (r < 0) - return r; - - *_passphrases = l; - return r; - } else - return ask_password_agent(message, icon, id, until, false, accept_cached, _passphrases); -} diff --git a/src/shared/ask-password-api.h b/src/shared/ask-password-api.h deleted file mode 100644 index 571101ced..000000000 --- a/src/shared/ask-password-api.h +++ /dev/null @@ -1,32 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -#pragma once - -/*** - This file is part of systemd. - - Copyright 2010 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 . -***/ - - -int ask_password_tty(const char *message, usec_t until, bool echo, const char *flag_file, char **_passphrase); - -int ask_password_agent(const char *message, const char *icon, const char *id, - usec_t until, bool echo, bool accept_cached, char ***_passphrases); - -int ask_password_auto(const char *message, const char *icon, const char *id, - usec_t until, bool accept_cached, char ***_passphrases); - SD_BUS_PROPERTY("TimeoutIdleUSec", "t", bus_property_get_usec, offsetof(Automount, timeout_idle_usec), SD_BUS_VTABLE_PROPERTY_CONST), diff --git a/src/shared/blkid-util.h b/src/shared/blkid-util.h deleted file mode 100644 index b596daddf..000000000 --- a/src/shared/blkid-util.h +++ /dev/null @@ -1,37 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -#pragma once - -/*** - 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 . -***/ - -#include "sd-bus.h" -#include "proxy.h" - -int synthetic_driver_send(sd_bus *b, sd_bus_message *m); - -int synthetic_reply_method_return(sd_bus_message *call, const char *types, ...); -int synthetic_reply_method_return_strv(sd_bus_message *call, char **l); - -int synthetic_reply_method_error(sd_bus_message *call, const sd_bus_error *e); -int synthetic_reply_method_errorf(sd_bus_message *call, const char *name, const char *format, ...) _sd_printf_(3, 4); -int synthetic_reply_method_errno(sd_bus_message *call, int error, const sd_bus_error *p); -int synthetic_reply_method_errnof(sd_bus_message *call, int error, const char *format, ...) _sd_printf_(3, 4); - -int synthesize_name_acquired(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m); diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index 1e80ebcf6..dc8727c8f 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -1924,6 +1924,16 @@ int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path) { return set_put_strdup(d->jobs, path); } +int bus_wait_for_jobs_one(BusWaitForJobs *d, const char *path, bool quiet) { + int r; + + r = bus_wait_for_jobs_add(d, path); + if (r < 0) + return log_oom(); + + return bus_wait_for_jobs(d, quiet); +} + int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, unsigned *n_changes) { const char *type, *path, *source; int r; diff --git a/src/shared/cgroup-show.c b/src/shared/cgroup-show.c index a59f7c2a9..4b038452f 100644 --- a/src/shared/cgroup-show.c +++ b/src/shared/cgroup-show.c @@ -26,6 +26,7 @@ #include "util.h" #include "formats-util.h" +#include "process-util.h" #include "macro.h" #include "path-util.h" #include "cgroup-util.h" diff --git a/src/shared/condition.c b/src/shared/condition.c deleted file mode 100644 index 24871b0da..000000000 --- a/src/shared/condition.c +++ /dev/null @@ -1,527 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2010 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 . -***/ - -#include -#include -#include -#include -#include - -#include "sd-id128.h" -#include "util.h" -#include "virt.h" -#include "path-util.h" -#include "architecture.h" -#include "smack-util.h" -#include "apparmor-util.h" -#include "ima-util.h" -#include "selinux-util.h" -#include "audit.h" -#include "cap-list.h" -#include "hostname-util.h" -#include "condition.h" - -Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate) { - Condition *c; - int r; - - assert(type >= 0); - assert(type < _CONDITION_TYPE_MAX); - assert((!parameter) == (type == CONDITION_NULL)); - - c = new0(Condition, 1); - if (!c) - return NULL; - - c->type = type; - c->trigger = trigger; - c->negate = negate; - - r = free_and_strdup(&c->parameter, parameter); - if (r < 0) { - free(c); - return NULL; - } - - return c; -} - -void condition_free(Condition *c) { - assert(c); - - free(c->parameter); - free(c); -} - -Condition* condition_free_list(Condition *first) { - Condition *c, *n; - - LIST_FOREACH_SAFE(conditions, c, n, first) - condition_free(c); - - return NULL; -} - -static int condition_test_kernel_command_line(Condition *c) { - _cleanup_free_ char *line = NULL; - const char *p; - bool equal; - int r; - - assert(c); - assert(c->parameter); - assert(c->type == CONDITION_KERNEL_COMMAND_LINE); - - r = proc_cmdline(&line); - if (r < 0) - return r; - - equal = !!strchr(c->parameter, '='); - p = line; - - for (;;) { - _cleanup_free_ char *word = NULL; - bool found; - - r = unquote_first_word(&p, &word, UNQUOTE_RELAX); - if (r < 0) - return r; - if (r == 0) - break; - - if (equal) - found = streq(word, c->parameter); - else { - const char *f; - - f = startswith(word, c->parameter); - found = f && (*f == '=' || *f == 0); - } - - if (found) - return true; - } - - return false; -} - -static int condition_test_virtualization(Condition *c) { - int b, v; - const char *id; - - assert(c); - assert(c->parameter); - assert(c->type == CONDITION_VIRTUALIZATION); - - v = detect_virtualization(&id); - if (v < 0) - return v; - - /* First, compare with yes/no */ - b = parse_boolean(c->parameter); - - if (v > 0 && b > 0) - return true; - - if (v == 0 && b == 0) - return true; - - /* Then, compare categorization */ - if (v == VIRTUALIZATION_VM && streq(c->parameter, "vm")) - return true; - - if (v == VIRTUALIZATION_CONTAINER && streq(c->parameter, "container")) - return true; - - /* Finally compare id */ - return v > 0 && streq(c->parameter, id); -} - -static int condition_test_architecture(Condition *c) { - int a, b; - - assert(c); - assert(c->parameter); - assert(c->type == CONDITION_ARCHITECTURE); - - a = uname_architecture(); - if (a < 0) - return a; - - if (streq(c->parameter, "native")) - b = native_architecture(); - else - b = architecture_from_string(c->parameter); - if (b < 0) - return b; - - return a == b; -} - -static int condition_test_host(Condition *c) { - _cleanup_free_ char *h = NULL; - sd_id128_t x, y; - int r; - - assert(c); - assert(c->parameter); - assert(c->type == CONDITION_HOST); - - if (sd_id128_from_string(c->parameter, &x) >= 0) { - - r = sd_id128_get_machine(&y); - if (r < 0) - return r; - - return sd_id128_equal(x, y); - } - - h = gethostname_malloc(); - if (!h) - return -ENOMEM; - - return fnmatch(c->parameter, h, FNM_CASEFOLD) == 0; -} - -static int condition_test_ac_power(Condition *c) { - int r; - - assert(c); - assert(c->parameter); - assert(c->type == CONDITION_AC_POWER); - - r = parse_boolean(c->parameter); - if (r < 0) - return r; - - return (on_ac_power() != 0) == !!r; -} - -static int condition_test_security(Condition *c) { - assert(c); - assert(c->parameter); - assert(c->type == CONDITION_SECURITY); - - if (streq(c->parameter, "selinux")) - return mac_selinux_use(); - if (streq(c->parameter, "smack")) - return mac_smack_use(); - if (streq(c->parameter, "apparmor")) - return mac_apparmor_use(); - if (streq(c->parameter, "audit")) - return use_audit(); - if (streq(c->parameter, "ima")) - return use_ima(); - - return false; -} - -static int condition_test_capability(Condition *c) { - _cleanup_fclose_ FILE *f = NULL; - int value; - char line[LINE_MAX]; - unsigned long long capabilities = -1; - - assert(c); - assert(c->parameter); - assert(c->type == CONDITION_CAPABILITY); - - /* If it's an invalid capability, we don't have it */ - value = capability_from_name(c->parameter); - if (value < 0) - return -EINVAL; - - /* If it's a valid capability we default to assume - * that we have it */ - - f = fopen("/proc/self/status", "re"); - if (!f) - return -errno; - - while (fgets(line, sizeof(line), f)) { - truncate_nl(line); - - if (startswith(line, "CapBnd:")) { - (void) sscanf(line+7, "%llx", &capabilities); - break; - } - } - - return !!(capabilities & (1ULL << value)); -} - -static int condition_test_needs_update(Condition *c) { - const char *p; - struct stat usr, other; - - assert(c); - assert(c->parameter); - assert(c->type == CONDITION_NEEDS_UPDATE); - - /* If the file system is read-only we shouldn't suggest an update */ - if (path_is_read_only_fs(c->parameter) > 0) - return false; - - /* Any other failure means we should allow the condition to be true, - * so that we rather invoke too many update tools then too - * few. */ - - if (!path_is_absolute(c->parameter)) - return true; - - p = strjoina(c->parameter, "/.updated"); - if (lstat(p, &other) < 0) - return true; - - if (lstat("/usr/", &usr) < 0) - return true; - - return usr.st_mtim.tv_sec > other.st_mtim.tv_sec || - (usr.st_mtim.tv_sec == other.st_mtim.tv_sec && usr.st_mtim.tv_nsec > other.st_mtim.tv_nsec); -} - -static int condition_test_first_boot(Condition *c) { - int r; - - assert(c); - assert(c->parameter); - assert(c->type == CONDITION_FIRST_BOOT); - - r = parse_boolean(c->parameter); - if (r < 0) - return r; - - return (access("/run/systemd/first-boot", F_OK) >= 0) == !!r; -} - -static int condition_test_path_exists(Condition *c) { - assert(c); - assert(c->parameter); - assert(c->type == CONDITION_PATH_EXISTS); - - return access(c->parameter, F_OK) >= 0; -} - -static int condition_test_path_exists_glob(Condition *c) { - assert(c); - assert(c->parameter); - assert(c->type == CONDITION_PATH_EXISTS_GLOB); - - return glob_exists(c->parameter) > 0; -} - -static int condition_test_path_is_directory(Condition *c) { - assert(c); - assert(c->parameter); - assert(c->type == CONDITION_PATH_IS_DIRECTORY); - - return is_dir(c->parameter, true) > 0; -} - -static int condition_test_path_is_symbolic_link(Condition *c) { - assert(c); - assert(c->parameter); - assert(c->type == CONDITION_PATH_IS_SYMBOLIC_LINK); - - return is_symlink(c->parameter) > 0; -} - -static int condition_test_path_is_mount_point(Condition *c) { - assert(c); - assert(c->parameter); - assert(c->type == CONDITION_PATH_IS_MOUNT_POINT); - - return path_is_mount_point(c->parameter, AT_SYMLINK_FOLLOW) > 0; -} - -static int condition_test_path_is_read_write(Condition *c) { - assert(c); - assert(c->parameter); - assert(c->type == CONDITION_PATH_IS_READ_WRITE); - - return path_is_read_only_fs(c->parameter) <= 0; -} - -static int condition_test_directory_not_empty(Condition *c) { - int r; - - assert(c); - assert(c->parameter); - assert(c->type == CONDITION_DIRECTORY_NOT_EMPTY); - - r = dir_is_empty(c->parameter); - return r <= 0 && r != -ENOENT; -} - -static int condition_test_file_not_empty(Condition *c) { - struct stat st; - - assert(c); - assert(c->parameter); - assert(c->type == CONDITION_FILE_NOT_EMPTY); - - return (stat(c->parameter, &st) >= 0 && - S_ISREG(st.st_mode) && - st.st_size > 0); -} - -static int condition_test_file_is_executable(Condition *c) { - struct stat st; - - assert(c); - assert(c->parameter); - assert(c->type == CONDITION_FILE_IS_EXECUTABLE); - - return (stat(c->parameter, &st) >= 0 && - S_ISREG(st.st_mode) && - (st.st_mode & 0111)); -} - -static int condition_test_null(Condition *c) { - assert(c); - assert(c->type == CONDITION_NULL); - - /* Note that during parsing we already evaluate the string and - * store it in c->negate */ - return true; -} - -int condition_test(Condition *c) { - - static int (*const condition_tests[_CONDITION_TYPE_MAX])(Condition *c) = { - [CONDITION_PATH_EXISTS] = condition_test_path_exists, - [CONDITION_PATH_EXISTS_GLOB] = condition_test_path_exists_glob, - [CONDITION_PATH_IS_DIRECTORY] = condition_test_path_is_directory, - [CONDITION_PATH_IS_SYMBOLIC_LINK] = condition_test_path_is_symbolic_link, - [CONDITION_PATH_IS_MOUNT_POINT] = condition_test_path_is_mount_point, - [CONDITION_PATH_IS_READ_WRITE] = condition_test_path_is_read_write, - [CONDITION_DIRECTORY_NOT_EMPTY] = condition_test_directory_not_empty, - [CONDITION_FILE_NOT_EMPTY] = condition_test_file_not_empty, - [CONDITION_FILE_IS_EXECUTABLE] = condition_test_file_is_executable, - [CONDITION_KERNEL_COMMAND_LINE] = condition_test_kernel_command_line, - [CONDITION_VIRTUALIZATION] = condition_test_virtualization, - [CONDITION_SECURITY] = condition_test_security, - [CONDITION_CAPABILITY] = condition_test_capability, - [CONDITION_HOST] = condition_test_host, - [CONDITION_AC_POWER] = condition_test_ac_power, - [CONDITION_ARCHITECTURE] = condition_test_architecture, - [CONDITION_NEEDS_UPDATE] = condition_test_needs_update, - [CONDITION_FIRST_BOOT] = condition_test_first_boot, - [CONDITION_NULL] = condition_test_null, - }; - - int r, b; - - assert(c); - assert(c->type >= 0); - assert(c->type < _CONDITION_TYPE_MAX); - - r = condition_tests[c->type](c); - if (r < 0) { - c->result = CONDITION_ERROR; - return r; - } - - b = (r > 0) == !c->negate; - c->result = b ? CONDITION_SUCCEEDED : CONDITION_FAILED; - return b; -} - -void condition_dump(Condition *c, FILE *f, const char *prefix, const char *(*to_string)(ConditionType t)) { - assert(c); - assert(f); - - if (!prefix) - prefix = ""; - - fprintf(f, - "%s\t%s: %s%s%s %s\n", - prefix, - to_string(c->type), - c->trigger ? "|" : "", - c->negate ? "!" : "", - c->parameter, - condition_result_to_string(c->result)); -} - -void condition_dump_list(Condition *first, FILE *f, const char *prefix, const char *(*to_string)(ConditionType t)) { - Condition *c; - - LIST_FOREACH(conditions, c, first) - condition_dump(c, f, prefix, to_string); -} - -static const char* const condition_type_table[_CONDITION_TYPE_MAX] = { - [CONDITION_ARCHITECTURE] = "ConditionArchitecture", - [CONDITION_VIRTUALIZATION] = "ConditionVirtualization", - [CONDITION_HOST] = "ConditionHost", - [CONDITION_KERNEL_COMMAND_LINE] = "ConditionKernelCommandLine", - [CONDITION_SECURITY] = "ConditionSecurity", - [CONDITION_CAPABILITY] = "ConditionCapability", - [CONDITION_AC_POWER] = "ConditionACPower", - [CONDITION_NEEDS_UPDATE] = "ConditionNeedsUpdate", - [CONDITION_FIRST_BOOT] = "ConditionFirstBoot", - [CONDITION_PATH_EXISTS] = "ConditionPathExists", - [CONDITION_PATH_EXISTS_GLOB] = "ConditionPathExistsGlob", - [CONDITION_PATH_IS_DIRECTORY] = "ConditionPathIsDirectory", - [CONDITION_PATH_IS_SYMBOLIC_LINK] = "ConditionPathIsSymbolicLink", - [CONDITION_PATH_IS_MOUNT_POINT] = "ConditionPathIsMountPoint", - [CONDITION_PATH_IS_READ_WRITE] = "ConditionPathIsReadWrite", - [CONDITION_DIRECTORY_NOT_EMPTY] = "ConditionDirectoryNotEmpty", - [CONDITION_FILE_NOT_EMPTY] = "ConditionFileNotEmpty", - [CONDITION_FILE_IS_EXECUTABLE] = "ConditionFileIsExecutable", - [CONDITION_NULL] = "ConditionNull" -}; - -DEFINE_STRING_TABLE_LOOKUP(condition_type, ConditionType); - -static const char* const assert_type_table[_CONDITION_TYPE_MAX] = { - [CONDITION_ARCHITECTURE] = "AssertArchitecture", - [CONDITION_VIRTUALIZATION] = "AssertVirtualization", - [CONDITION_HOST] = "AssertHost", - [CONDITION_KERNEL_COMMAND_LINE] = "AssertKernelCommandLine", - [CONDITION_SECURITY] = "AssertSecurity", - [CONDITION_CAPABILITY] = "AssertCapability", - [CONDITION_AC_POWER] = "AssertACPower", - [CONDITION_NEEDS_UPDATE] = "AssertNeedsUpdate", - [CONDITION_FIRST_BOOT] = "AssertFirstBoot", - [CONDITION_PATH_EXISTS] = "AssertPathExists", - [CONDITION_PATH_EXISTS_GLOB] = "AssertPathExistsGlob", - [CONDITION_PATH_IS_DIRECTORY] = "AssertPathIsDirectory", - [CONDITION_PATH_IS_SYMBOLIC_LINK] = "AssertPathIsSymbolicLink", - [CONDITION_PATH_IS_MOUNT_POINT] = "AssertPathIsMountPoint", - [CONDITION_PATH_IS_READ_WRITE] = "AssertPathIsReadWrite", - [CONDITION_DIRECTORY_NOT_EMPTY] = "AssertDirectoryNotEmpty", - [CONDITION_FILE_NOT_EMPTY] = "AssertFileNotEmpty", - [CONDITION_FILE_IS_EXECUTABLE] = "AssertFileIsExecutable", - [CONDITION_NULL] = "AssertNull" -}; - -DEFINE_STRING_TABLE_LOOKUP(assert_type, ConditionType); - -static const char* const condition_result_table[_CONDITION_RESULT_MAX] = { - [CONDITION_UNTESTED] = "untested", - [CONDITION_SUCCEEDED] = "succeeded", - [CONDITION_FAILED] = "failed", - [CONDITION_ERROR] = "error", -}; - -DEFINE_STRING_TABLE_LOOKUP(condition_result, ConditionResult); diff --git a/src/shared/copy.c b/src/shared/copy.c deleted file mode 100644 index 230e7e4d3..000000000 --- a/src/shared/copy.c +++ /dev/null @@ -1,507 +0,0 @@ -/*-*- 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 . -***/ - -#include -#include - -#include "util.h" -#include "btrfs-util.h" -#include "copy.h" - -#define COPY_BUFFER_SIZE (16*1024) - -int copy_bytes(int fdf, int fdt, off_t max_bytes, bool try_reflink) { - bool try_sendfile = true; - int r; - - assert(fdf >= 0); - assert(fdt >= 0); - - /* Try btrfs reflinks first. */ - if (try_reflink && max_bytes == (off_t) -1) { - r = btrfs_reflink(fdf, fdt); - if (r >= 0) - return r; - } - - for (;;) { - size_t m = COPY_BUFFER_SIZE; - ssize_t n; - - if (max_bytes != (off_t) -1) { - - if (max_bytes <= 0) - return -EFBIG; - - if ((off_t) m > max_bytes) - m = (size_t) max_bytes; - } - - /* First try sendfile(), unless we already tried */ - if (try_sendfile) { - - n = sendfile(fdt, fdf, NULL, m); - if (n < 0) { - if (errno != EINVAL && errno != ENOSYS) - return -errno; - - try_sendfile = false; - /* use fallback below */ - } else if (n == 0) /* EOF */ - break; - else if (n > 0) - /* Succcess! */ - goto next; - } - - /* As a fallback just copy bits by hand */ - { - char buf[m]; - - n = read(fdf, buf, m); - if (n < 0) - return -errno; - if (n == 0) /* EOF */ - break; - - r = loop_write(fdt, buf, (size_t) n, false); - if (r < 0) - return r; - } - - next: - if (max_bytes != (off_t) -1) { - assert(max_bytes >= n); - max_bytes -= n; - } - } - - return 0; -} - -static int fd_copy_symlink(int df, const char *from, const struct stat *st, int dt, const char *to) { - _cleanup_free_ char *target = NULL; - int r; - - assert(from); - assert(st); - assert(to); - - r = readlinkat_malloc(df, from, &target); - if (r < 0) - return r; - - if (symlinkat(target, dt, to) < 0) - return -errno; - - if (fchownat(dt, to, st->st_uid, st->st_gid, AT_SYMLINK_NOFOLLOW) < 0) - return -errno; - - return 0; -} - -static int fd_copy_regular(int df, const char *from, const struct stat *st, int dt, const char *to) { - _cleanup_close_ int fdf = -1, fdt = -1; - struct timespec ts[2]; - int r, q; - - assert(from); - assert(st); - assert(to); - - fdf = openat(df, from, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); - if (fdf < 0) - return -errno; - - fdt = openat(dt, to, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, st->st_mode & 07777); - if (fdt < 0) - return -errno; - - r = copy_bytes(fdf, fdt, (off_t) -1, true); - if (r < 0) { - unlinkat(dt, to, 0); - return r; - } - - if (fchown(fdt, st->st_uid, st->st_gid) < 0) - r = -errno; - - if (fchmod(fdt, st->st_mode & 07777) < 0) - r = -errno; - - ts[0] = st->st_atim; - ts[1] = st->st_mtim; - (void) futimens(fdt, ts); - - (void) copy_xattr(fdf, fdt); - - q = close(fdt); - fdt = -1; - - if (q < 0) { - r = -errno; - unlinkat(dt, to, 0); - } - - return r; -} - -static int fd_copy_fifo(int df, const char *from, const struct stat *st, int dt, const char *to) { - int r; - - assert(from); - assert(st); - assert(to); - - r = mkfifoat(dt, to, st->st_mode & 07777); - if (r < 0) - return -errno; - - if (fchownat(dt, to, st->st_uid, st->st_gid, AT_SYMLINK_NOFOLLOW) < 0) - r = -errno; - - if (fchmodat(dt, to, st->st_mode & 07777, 0) < 0) - r = -errno; - - return r; -} - -static int fd_copy_node(int df, const char *from, const struct stat *st, int dt, const char *to) { - int r; - - assert(from); - assert(st); - assert(to); - - r = mknodat(dt, to, st->st_mode, st->st_rdev); - if (r < 0) - return -errno; - - if (fchownat(dt, to, st->st_uid, st->st_gid, AT_SYMLINK_NOFOLLOW) < 0) - r = -errno; - - if (fchmodat(dt, to, st->st_mode & 07777, 0) < 0) - r = -errno; - - return r; -} - -static int fd_copy_directory( - int df, - const char *from, - const struct stat *st, - int dt, - const char *to, - dev_t original_device, - bool merge) { - - _cleanup_close_ int fdf = -1, fdt = -1; - _cleanup_closedir_ DIR *d = NULL; - struct dirent *de; - bool created; - int r; - - assert(st); - assert(to); - - if (from) - fdf = openat(df, from, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); - else - fdf = fcntl(df, F_DUPFD_CLOEXEC, 3); - - d = fdopendir(fdf); - if (!d) - return -errno; - fdf = -1; - - r = mkdirat(dt, to, st->st_mode & 07777); - if (r >= 0) - created = true; - else if (errno == EEXIST && merge) - created = false; - else - return -errno; - - fdt = openat(dt, to, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); - if (fdt < 0) - return -errno; - - r = 0; - - if (created) { - struct timespec ut[2] = { - st->st_atim, - st->st_mtim - }; - - if (fchown(fdt, st->st_uid, st->st_gid) < 0) - r = -errno; - - if (fchmod(fdt, st->st_mode & 07777) < 0) - r = -errno; - - (void) futimens(fdt, ut); - (void) copy_xattr(dirfd(d), fdt); - } - - FOREACH_DIRENT(de, d, return -errno) { - struct stat buf; - int q; - - if (fstatat(dirfd(d), de->d_name, &buf, AT_SYMLINK_NOFOLLOW) < 0) { - r = -errno; - continue; - } - - if (buf.st_dev != original_device) - continue; - - if (S_ISREG(buf.st_mode)) - q = fd_copy_regular(dirfd(d), de->d_name, &buf, fdt, de->d_name); - else if (S_ISDIR(buf.st_mode)) - q = fd_copy_directory(dirfd(d), de->d_name, &buf, fdt, de->d_name, original_device, merge); - else if (S_ISLNK(buf.st_mode)) - q = fd_copy_symlink(dirfd(d), de->d_name, &buf, fdt, de->d_name); - else if (S_ISFIFO(buf.st_mode)) - q = fd_copy_fifo(dirfd(d), de->d_name, &buf, fdt, de->d_name); - else if (S_ISBLK(buf.st_mode) || S_ISCHR(buf.st_mode)) - q = fd_copy_node(dirfd(d), de->d_name, &buf, fdt, de->d_name); - else - q = -EOPNOTSUPP; - - if (q == -EEXIST && merge) - q = 0; - - if (q < 0) - r = q; - } - - return r; -} - -int copy_tree_at(int fdf, const char *from, int fdt, const char *to, bool merge) { - struct stat st; - - assert(from); - assert(to); - - if (fstatat(fdf, from, &st, AT_SYMLINK_NOFOLLOW) < 0) - return -errno; - - if (S_ISREG(st.st_mode)) - return fd_copy_regular(fdf, from, &st, fdt, to); - else if (S_ISDIR(st.st_mode)) - return fd_copy_directory(fdf, from, &st, fdt, to, st.st_dev, merge); - else if (S_ISLNK(st.st_mode)) - return fd_copy_symlink(fdf, from, &st, fdt, to); - else if (S_ISFIFO(st.st_mode)) - return fd_copy_fifo(fdf, from, &st, fdt, to); - else if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) - return fd_copy_node(fdf, from, &st, fdt, to); - else - return -EOPNOTSUPP; -} - -int copy_tree(const char *from, const char *to, bool merge) { - return copy_tree_at(AT_FDCWD, from, AT_FDCWD, to, merge); -} - -int copy_directory_fd(int dirfd, const char *to, bool merge) { - - struct stat st; - - assert(dirfd >= 0); - assert(to); - - if (fstat(dirfd, &st) < 0) - return -errno; - - if (!S_ISDIR(st.st_mode)) - return -ENOTDIR; - - return fd_copy_directory(dirfd, NULL, &st, AT_FDCWD, to, st.st_dev, merge); -} - -int copy_file_fd(const char *from, int fdt, bool try_reflink) { - _cleanup_close_ int fdf = -1; - int r; - - assert(from); - assert(fdt >= 0); - - fdf = open(from, O_RDONLY|O_CLOEXEC|O_NOCTTY); - if (fdf < 0) - return -errno; - - r = copy_bytes(fdf, fdt, (off_t) -1, try_reflink); - - (void) copy_times(fdf, fdt); - (void) copy_xattr(fdf, fdt); - - return r; -} - -int copy_file(const char *from, const char *to, int flags, mode_t mode, unsigned chattr_flags) { - int fdt = -1, r; - - assert(from); - assert(to); - - RUN_WITH_UMASK(0000) { - fdt = open(to, flags|O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, mode); - if (fdt < 0) - return -errno; - } - - if (chattr_flags != 0) - (void) chattr_fd(fdt, chattr_flags, (unsigned) -1); - - r = copy_file_fd(from, fdt, true); - if (r < 0) { - close(fdt); - unlink(to); - return r; - } - - if (close(fdt) < 0) { - unlink_noerrno(to); - return -errno; - } - - return 0; -} - -int copy_file_atomic(const char *from, const char *to, mode_t mode, bool replace, unsigned chattr_flags) { - _cleanup_free_ char *t = NULL; - int r; - - assert(from); - assert(to); - - r = tempfn_random(to, NULL, &t); - if (r < 0) - return r; - - r = copy_file(from, t, O_NOFOLLOW|O_EXCL, mode, chattr_flags); - if (r < 0) - return r; - - if (replace) { - r = renameat(AT_FDCWD, t, AT_FDCWD, to); - if (r < 0) - r = -errno; - } else - r = rename_noreplace(AT_FDCWD, t, AT_FDCWD, to); - if (r < 0) { - (void) unlink_noerrno(t); - return r; - } - - return 0; -} - -int copy_times(int fdf, int fdt) { - struct timespec ut[2]; - struct stat st; - usec_t crtime = 0; - - assert(fdf >= 0); - assert(fdt >= 0); - - if (fstat(fdf, &st) < 0) - return -errno; - - ut[0] = st.st_atim; - ut[1] = st.st_mtim; - - if (futimens(fdt, ut) < 0) - return -errno; - - if (fd_getcrtime(fdf, &crtime) >= 0) - (void) fd_setcrtime(fdt, crtime); - - return 0; -} - -int copy_xattr(int fdf, int fdt) { - _cleanup_free_ char *bufa = NULL, *bufb = NULL; - size_t sza = 100, szb = 100; - ssize_t n; - int ret = 0; - const char *p; - - for (;;) { - bufa = malloc(sza); - if (!bufa) - return -ENOMEM; - - n = flistxattr(fdf, bufa, sza); - if (n == 0) - return 0; - if (n > 0) - break; - if (errno != ERANGE) - return -errno; - - sza *= 2; - - free(bufa); - bufa = NULL; - } - - p = bufa; - while (n > 0) { - size_t l; - - l = strlen(p); - assert(l < (size_t) n); - - if (startswith(p, "user.")) { - ssize_t m; - - if (!bufb) { - bufb = malloc(szb); - if (!bufb) - return -ENOMEM; - } - - m = fgetxattr(fdf, p, bufb, szb); - if (m < 0) { - if (errno == ERANGE) { - szb *= 2; - free(bufb); - bufb = NULL; - continue; - } - - return -errno; - } - - if (fsetxattr(fdt, p, bufb, m, 0) < 0) - ret = -errno; - } - - p += l + 1; - n -= l + 1; - } - - return ret; -} diff --git a/src/shared/dns-domain.c b/src/shared/dns-domain.c deleted file mode 100644 index 8a0dec154..000000000 --- a/src/shared/dns-domain.c +++ /dev/null @@ -1,700 +0,0 @@ -/*-*- 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 . - ***/ - -#ifdef HAVE_LIBIDN -#include -#include -#endif - -#include "dns-domain.h" - -int dns_label_unescape(const char **name, char *dest, size_t sz) { - const char *n; - char *d; - int r = 0; - - assert(name); - assert(*name); - assert(dest); - - n = *name; - d = dest; - - for (;;) { - if (*n == '.') { - n++; - break; - } - - if (*n == 0) - break; - - if (sz <= 0) - return -ENOSPC; - - if (r >= DNS_LABEL_MAX) - return -EINVAL; - - if (*n == '\\') { - /* Escaped character */ - - n++; - - if (*n == 0) - /* Ending NUL */ - return -EINVAL; - - else if (*n == '\\' || *n == '.') { - /* Escaped backslash or dot */ - *(d++) = *(n++); - sz--; - r++; - - } else if (n[0] >= '0' && n[0] <= '9') { - unsigned k; - - /* Escaped literal ASCII character */ - - if (!(n[1] >= '0' && n[1] <= '9') || - !(n[2] >= '0' && n[2] <= '9')) - return -EINVAL; - - k = ((unsigned) (n[0] - '0') * 100) + - ((unsigned) (n[1] - '0') * 10) + - ((unsigned) (n[2] - '0')); - - /* Don't allow CC characters or anything that doesn't fit in 8bit */ - if (k < ' ' || k > 255 || k == 127) - return -EINVAL; - - *(d++) = (char) k; - sz--; - r++; - - n += 3; - } else - return -EINVAL; - - } else if ((uint8_t) *n >= (uint8_t) ' ' && *n != 127) { - - /* Normal character */ - *(d++) = *(n++); - sz--; - r++; - } else - return -EINVAL; - } - - /* Empty label that is not at the end? */ - if (r == 0 && *n) - return -EINVAL; - - if (sz >= 1) - *d = 0; - - *name = n; - return r; -} - -/* @label_terminal: terminal character of a label, updated to point to the terminal character of - * the previous label (always skipping one dot) or to NULL if there are no more - * labels. */ -int dns_label_unescape_suffix(const char *name, const char **label_terminal, char *dest, size_t sz) { - const char *terminal; - int r; - - assert(name); - assert(label_terminal); - assert(dest); - - /* no more labels */ - if (!*label_terminal) { - if (sz >= 1) - *dest = 0; - - return 0; - } - - assert(**label_terminal == '.' || **label_terminal == 0); - - /* skip current terminal character */ - terminal = *label_terminal - 1; - - /* point name to the last label, and terminal to the preceding terminal symbol (or make it a NULL pointer) */ - for (;;) { - if (terminal < name) { - /* reached the first label, so indicate that there are no more */ - terminal = NULL; - break; - } - - /* find the start of the last label */ - if (*terminal == '.') { - const char *y; - unsigned slashes = 0; - - for (y = terminal - 1; y >= name && *y == '\\'; y--) - slashes ++; - - if (slashes % 2 == 0) { - /* the '.' was not escaped */ - name = terminal + 1; - break; - } else { - terminal = y; - continue; - } - } - - terminal --; - } - - r = dns_label_unescape(&name, dest, sz); - if (r < 0) - return r; - - *label_terminal = terminal; - - return r; -} - -int dns_label_escape(const char *p, size_t l, char **ret) { - _cleanup_free_ char *s = NULL; - char *q; - int r; - - assert(p); - assert(ret); - - if (l > DNS_LABEL_MAX) - return -EINVAL; - - s = malloc(l * 4 + 1); - if (!s) - return -ENOMEM; - - q = s; - while (l > 0) { - - if (*p == '.' || *p == '\\') { - - /* Dot or backslash */ - *(q++) = '\\'; - *(q++) = *p; - - } else if (*p == '_' || - *p == '-' || - (*p >= '0' && *p <= '9') || - (*p >= 'a' && *p <= 'z') || - (*p >= 'A' && *p <= 'Z')) { - - /* Proper character */ - *(q++) = *p; - } else if ((uint8_t) *p >= (uint8_t) ' ' && *p != 127) { - - /* Everything else */ - *(q++) = '\\'; - *(q++) = '0' + (char) ((uint8_t) *p / 100); - *(q++) = '0' + (char) (((uint8_t) *p / 10) % 10); - *(q++) = '0' + (char) ((uint8_t) *p % 10); - - } else - return -EINVAL; - - p++; - l--; - } - - *q = 0; - *ret = s; - r = q - s; - s = NULL; - - return r; -} - -int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) { -#ifdef HAVE_LIBIDN - _cleanup_free_ uint32_t *input = NULL; - size_t input_size; - const char *p; - bool contains_8bit = false; - - assert(encoded); - assert(decoded); - assert(decoded_max >= DNS_LABEL_MAX); - - if (encoded_size <= 0) - return 0; - - for (p = encoded; p < encoded + encoded_size; p++) - if ((uint8_t) *p > 127) - contains_8bit = true; - - if (!contains_8bit) - return 0; - - input = stringprep_utf8_to_ucs4(encoded, encoded_size, &input_size); - if (!input) - return -ENOMEM; - - if (idna_to_ascii_4i(input, input_size, decoded, 0) != 0) - return -EINVAL; - - return strlen(decoded); -#else - return 0; -#endif -} - -int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) { -#ifdef HAVE_LIBIDN - size_t input_size, output_size; - _cleanup_free_ uint32_t *input = NULL; - _cleanup_free_ char *result = NULL; - uint32_t *output = NULL; - size_t w; - - /* To be invoked after unescaping */ - - assert(encoded); - assert(decoded); - - if (encoded_size < sizeof(IDNA_ACE_PREFIX)-1) - return 0; - - if (memcmp(encoded, IDNA_ACE_PREFIX, sizeof(IDNA_ACE_PREFIX) -1) != 0) - return 0; - - input = stringprep_utf8_to_ucs4(encoded, encoded_size, &input_size); - if (!input) - return -ENOMEM; - - output_size = input_size; - output = newa(uint32_t, output_size); - - idna_to_unicode_44i(input, input_size, output, &output_size, 0); - - result = stringprep_ucs4_to_utf8(output, output_size, NULL, &w); - if (!result) - return -ENOMEM; - if (w <= 0) - return 0; - if (w+1 > decoded_max) - return -EINVAL; - - memcpy(decoded, result, w+1); - return w; -#else - return 0; -#endif -} - -int dns_name_normalize(const char *s, char **_ret) { - _cleanup_free_ char *ret = NULL; - size_t n = 0, allocated = 0; - const char *p = s; - bool first = true; - int r; - - assert(s); - - for (;;) { - _cleanup_free_ char *t = NULL; - char label[DNS_LABEL_MAX]; - int k; - - r = dns_label_unescape(&p, label, sizeof(label)); - if (r < 0) - return r; - if (r == 0) { - if (*p != 0) - return -EINVAL; - break; - } - - k = dns_label_undo_idna(label, r, label, sizeof(label)); - if (k < 0) - return k; - if (k > 0) - r = k; - - r = dns_label_escape(label, r, &t); - if (r < 0) - return r; - - if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1)) - return -ENOMEM; - - if (!first) - ret[n++] = '.'; - else - first = false; - - memcpy(ret + n, t, r); - n += r; - } - - if (n > DNS_NAME_MAX) - return -EINVAL; - - if (!GREEDY_REALLOC(ret, allocated, n + 1)) - return -ENOMEM; - - ret[n] = 0; - - if (_ret) { - *_ret = ret; - ret = NULL; - } - - return 0; -} - -unsigned long dns_name_hash_func(const void *s, const uint8_t hash_key[HASH_KEY_SIZE]) { - const char *p = s; - unsigned long ul = hash_key[0]; - int r; - - assert(p); - - while (*p) { - char label[DNS_LABEL_MAX+1]; - int k; - - r = dns_label_unescape(&p, label, sizeof(label)); - if (r < 0) - break; - - k = dns_label_undo_idna(label, r, label, sizeof(label)); - if (k < 0) - break; - if (k > 0) - r = k; - - label[r] = 0; - ascii_strlower(label); - - ul = ul * hash_key[1] + ul + string_hash_func(label, hash_key); - } - - return ul; -} - -int dns_name_compare_func(const void *a, const void *b) { - const char *x, *y; - int r, q, k, w; - - assert(a); - assert(b); - - x = (const char *) a + strlen(a); - y = (const char *) b + strlen(b); - - for (;;) { - char la[DNS_LABEL_MAX+1], lb[DNS_LABEL_MAX+1]; - - if (x == NULL && y == NULL) - return 0; - - r = dns_label_unescape_suffix(a, &x, la, sizeof(la)); - q = dns_label_unescape_suffix(b, &y, lb, sizeof(lb)); - if (r < 0 || q < 0) - return r - q; - - k = dns_label_undo_idna(la, r, la, sizeof(la)); - w = dns_label_undo_idna(lb, q, lb, sizeof(lb)); - if (k < 0 || w < 0) - return k - w; - if (k > 0) - r = k; - if (w > 0) - r = w; - - la[r] = lb[q] = 0; - r = strcasecmp(la, lb); - if (r != 0) - return r; - } -} - -const struct hash_ops dns_name_hash_ops = { - .hash = dns_name_hash_func, - .compare = dns_name_compare_func -}; - -int dns_name_equal(const char *x, const char *y) { - int r, q, k, w; - - assert(x); - assert(y); - - for (;;) { - char la[DNS_LABEL_MAX+1], lb[DNS_LABEL_MAX+1]; - - if (*x == 0 && *y == 0) - return true; - - r = dns_label_unescape(&x, la, sizeof(la)); - if (r < 0) - return r; - - k = dns_label_undo_idna(la, r, la, sizeof(la)); - if (k < 0) - return k; - if (k > 0) - r = k; - - q = dns_label_unescape(&y, lb, sizeof(lb)); - if (q < 0) - return q; - w = dns_label_undo_idna(lb, q, lb, sizeof(lb)); - if (w < 0) - return w; - if (w > 0) - q = w; - - la[r] = lb[q] = 0; - if (strcasecmp(la, lb)) - return false; - } -} - -int dns_name_endswith(const char *name, const char *suffix) { - const char *n, *s, *saved_n = NULL; - int r, q, k, w; - - assert(name); - assert(suffix); - - n = name; - s = suffix; - - for (;;) { - char ln[DNS_LABEL_MAX+1], ls[DNS_LABEL_MAX+1]; - - r = dns_label_unescape(&n, ln, sizeof(ln)); - if (r < 0) - return r; - k = dns_label_undo_idna(ln, r, ln, sizeof(ln)); - if (k < 0) - return k; - if (k > 0) - r = k; - - if (!saved_n) - saved_n = n; - - q = dns_label_unescape(&s, ls, sizeof(ls)); - if (q < 0) - return q; - w = dns_label_undo_idna(ls, q, ls, sizeof(ls)); - if (w < 0) - return w; - if (w > 0) - q = w; - - if (r == 0 && q == 0) - return true; - if (r == 0 && saved_n == n) - return false; - - ln[r] = ls[q] = 0; - - if (r != q || strcasecmp(ln, ls)) { - - /* Not the same, let's jump back, and try with the next label again */ - s = suffix; - n = saved_n; - saved_n = NULL; - } - } -} - -int dns_name_between(const char *a, const char *b, const char *c) { - int n; - - /* Determine if b is strictly greater than a and strictly smaller than c. - We consider the order of names to be circular, so that if a is - strictly greater than c, we consider b to be between them if it is - either greater than a or smaller than c. This is how the canonical - DNS name order used in NSEC records work. */ - - n = dns_name_compare_func(a, c); - if (n == 0) - return -EINVAL; - else if (n < 0) - /* a<---b--->c */ - return dns_name_compare_func(a, b) < 0 && - dns_name_compare_func(b, c) < 0; - else - /* <--b--c a--b--> */ - return dns_name_compare_func(b, c) < 0 || - dns_name_compare_func(a, b) < 0; -} - -int dns_name_reverse(int family, const union in_addr_union *a, char **ret) { - const uint8_t *p; - int r; - - assert(a); - assert(ret); - - p = (const uint8_t*) a; - - if (family == AF_INET) - r = asprintf(ret, "%u.%u.%u.%u.in-addr.arpa", p[3], p[2], p[1], p[0]); - else if (family == AF_INET6) - r = asprintf(ret, "%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.ip6.arpa", - hexchar(p[15] & 0xF), hexchar(p[15] >> 4), hexchar(p[14] & 0xF), hexchar(p[14] >> 4), - hexchar(p[13] & 0xF), hexchar(p[13] >> 4), hexchar(p[12] & 0xF), hexchar(p[12] >> 4), - hexchar(p[11] & 0xF), hexchar(p[11] >> 4), hexchar(p[10] & 0xF), hexchar(p[10] >> 4), - hexchar(p[ 9] & 0xF), hexchar(p[ 9] >> 4), hexchar(p[ 8] & 0xF), hexchar(p[ 8] >> 4), - hexchar(p[ 7] & 0xF), hexchar(p[ 7] >> 4), hexchar(p[ 6] & 0xF), hexchar(p[ 6] >> 4), - hexchar(p[ 5] & 0xF), hexchar(p[ 5] >> 4), hexchar(p[ 4] & 0xF), hexchar(p[ 4] >> 4), - hexchar(p[ 3] & 0xF), hexchar(p[ 3] >> 4), hexchar(p[ 2] & 0xF), hexchar(p[ 2] >> 4), - hexchar(p[ 1] & 0xF), hexchar(p[ 1] >> 4), hexchar(p[ 0] & 0xF), hexchar(p[ 0] >> 4)); - else - return -EAFNOSUPPORT; - if (r < 0) - return -ENOMEM; - - return 0; -} - -int dns_name_address(const char *p, int *family, union in_addr_union *address) { - int r; - - assert(p); - assert(family); - assert(address); - - r = dns_name_endswith(p, "in-addr.arpa"); - if (r < 0) - return r; - if (r > 0) { - uint8_t a[4]; - unsigned i; - - for (i = 0; i < ELEMENTSOF(a); i++) { - char label[DNS_LABEL_MAX+1]; - - r = dns_label_unescape(&p, label, sizeof(label)); - if (r < 0) - return r; - if (r == 0) - return -EINVAL; - if (r > 3) - return -EINVAL; - - r = safe_atou8(label, &a[i]); - if (r < 0) - return r; - } - - r = dns_name_equal(p, "in-addr.arpa"); - if (r <= 0) - return r; - - *family = AF_INET; - address->in.s_addr = htobe32(((uint32_t) a[3] << 24) | - ((uint32_t) a[2] << 16) | - ((uint32_t) a[1] << 8) | - (uint32_t) a[0]); - - return 1; - } - - r = dns_name_endswith(p, "ip6.arpa"); - if (r < 0) - return r; - if (r > 0) { - struct in6_addr a; - unsigned i; - - for (i = 0; i < ELEMENTSOF(a.s6_addr); i++) { - char label[DNS_LABEL_MAX+1]; - int x, y; - - r = dns_label_unescape(&p, label, sizeof(label)); - if (r <= 0) - return r; - if (r != 1) - return -EINVAL; - x = unhexchar(label[0]); - if (x < 0) - return -EINVAL; - - r = dns_label_unescape(&p, label, sizeof(label)); - if (r <= 0) - return r; - if (r != 1) - return -EINVAL; - y = unhexchar(label[0]); - if (y < 0) - return -EINVAL; - - a.s6_addr[ELEMENTSOF(a.s6_addr) - i - 1] = (uint8_t) y << 4 | (uint8_t) x; - } - - r = dns_name_equal(p, "ip6.arpa"); - if (r <= 0) - return r; - - *family = AF_INET6; - address->in6 = a; - return 1; - } - - return 0; -} - -int dns_name_root(const char *name) { - char label[DNS_LABEL_MAX+1]; - int r; - - assert(name); - - r = dns_label_unescape(&name, label, sizeof(label)); - if (r < 0) - return r; - - return r == 0 && *name == 0; -} - -int dns_name_single_label(const char *name) { - char label[DNS_LABEL_MAX+1]; - int r; - - assert(name); - - r = dns_label_unescape(&name, label, sizeof(label)); - if (r < 0) - return r; - if (r == 0) - return 0; - - r = dns_label_unescape(&name, label, sizeof(label)); - if (r < 0) - return r; - - return r == 0 && *name == 0; -} diff --git a/src/shared/dns-domain.h b/src/shared/dns-domain.h deleted file mode 100644 index 4ee10ab9e..000000000 --- a/src/shared/dns-domain.h +++ /dev/null @@ -1,52 +0,0 @@ -/*-*- 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 . - ***/ - -#pragma once - - -#include "hashmap.h" -#include "in-addr-util.h" - -#define DNS_LABEL_MAX 63 -#define DNS_NAME_MAX 255 - -int dns_label_unescape(const char **name, char *dest, size_t sz); -int dns_label_unescape_suffix(const char *name, const char **label_end, char *dest, size_t sz); -int dns_label_escape(const char *p, size_t l, char **ret); - -int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max); -int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max); - -int dns_name_normalize(const char *s, char **_ret); - -unsigned long dns_name_hash_func(const void *s, const uint8_t hash_key[HASH_KEY_SIZE]); -int dns_name_compare_func(const void *a, const void *b); -extern const struct hash_ops dns_name_hash_ops; - -int dns_name_between(const char *a, const char *b, const char *c); -int dns_name_equal(const char *x, const char *y); -int dns_name_endswith(const char *name, const char *suffix); - -int dns_name_reverse(int family, const union in_addr_union *a, char **ret); -int dns_name_address(const char *p, int *family, union in_addr_union *a); - -int dns_name_root(const char *name); -int dns_name_single_label(const char *name); diff --git a/src/shared/efivars.h b/src/shared/efivars.h new file mode 100644 index 000000000..e953a1273 --- /dev/null +++ b/src/shared/efivars.h @@ -0,0 +1,130 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2013 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 . +***/ + +#include + +#include "sd-id128.h" +#include "time-util.h" + +#define EFI_VENDOR_LOADER SD_ID128_MAKE(4a,67,b0,82,0a,4c,41,cf,b6,c7,44,0b,29,bb,8c,4f) +#define EFI_VENDOR_GLOBAL SD_ID128_MAKE(8b,e4,df,61,93,ca,11,d2,aa,0d,00,e0,98,03,2b,8c) +#define EFI_VARIABLE_NON_VOLATILE 0x0000000000000001 +#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002 +#define EFI_VARIABLE_RUNTIME_ACCESS 0x0000000000000004 + +#ifdef ENABLE_EFI + +bool is_efi_boot(void); +bool is_efi_secure_boot(void); +bool is_efi_secure_boot_setup_mode(void); +int efi_reboot_to_firmware_supported(void); +int efi_get_reboot_to_firmware(void); +int efi_set_reboot_to_firmware(bool value); + +int efi_get_variable(sd_id128_t vendor, const char *name, uint32_t *attribute, void **value, size_t *size); +int efi_set_variable(sd_id128_t vendor, const char *name, const void *value, size_t size); +int efi_get_variable_string(sd_id128_t vendor, const char *name, char **p); + +int efi_get_boot_option(uint16_t nr, char **title, sd_id128_t *part_uuid, char **path, bool *active); +int efi_add_boot_option(uint16_t id, const char *title, uint32_t part, uint64_t pstart, uint64_t psize, sd_id128_t part_uuid, const char *path); +int efi_remove_boot_option(uint16_t id); +int efi_get_boot_order(uint16_t **order); +int efi_set_boot_order(uint16_t *order, size_t n); +int efi_get_boot_options(uint16_t **options); + +int efi_loader_get_device_part_uuid(sd_id128_t *u); +int efi_loader_get_boot_usec(usec_t *firmware, usec_t *loader); + +#else + +static inline bool is_efi_boot(void) { + return false; +} + +static inline bool is_efi_secure_boot(void) { + return false; +} + +static inline bool is_efi_secure_boot_setup_mode(void) { + return false; +} + +static inline int efi_reboot_to_firmware_supported(void) { + return -EOPNOTSUPP; +} + +static inline int efi_get_reboot_to_firmware(void) { + return -EOPNOTSUPP; +} + +static inline int efi_set_reboot_to_firmware(bool value) { + return -EOPNOTSUPP; +} + +static inline int efi_get_variable(sd_id128_t vendor, const char *name, uint32_t *attribute, void **value, size_t *size) { + return -EOPNOTSUPP; +} + +static inline int efi_set_variable(sd_id128_t vendor, const char *name, const void *value, size_t size) { + return -EOPNOTSUPP; +} + +static inline int efi_get_variable_string(sd_id128_t vendor, const char *name, char **p) { + return -EOPNOTSUPP; +} + +static inline int efi_get_boot_option(uint16_t nr, char **title, sd_id128_t *part_uuid, char **path, bool *active) { + return -EOPNOTSUPP; +} + +static inline int efi_add_boot_option(uint16_t id, const char *title, uint32_t part, uint64_t pstart, uint64_t psize, sd_id128_t part_uuid, const char *path) { + return -EOPNOTSUPP; +} + +static inline int efi_remove_boot_option(uint16_t id) { + return -EOPNOTSUPP; +} + +static inline int efi_get_boot_order(uint16_t **order) { + return -EOPNOTSUPP; +} + +static inline int efi_set_boot_order(uint16_t *order, size_t n) { + return -EOPNOTSUPP; +} + +static inline int efi_get_boot_options(uint16_t **options) { + return -EOPNOTSUPP; +} + +static inline int efi_loader_get_device_part_uuid(sd_id128_t *u) { + return -EOPNOTSUPP; +} + +static inline int efi_loader_get_boot_usec(usec_t *firmware, usec_t *loader) { + return -EOPNOTSUPP; +} + +#endif + +char *efi_tilt_backslashes(char *s); diff --git a/src/shared/generator.c b/src/shared/generator.c deleted file mode 100644 index e58bbea77..000000000 --- a/src/shared/generator.c +++ /dev/null @@ -1,188 +0,0 @@ -/*-*- 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 . -***/ - -#include - -#include "util.h" -#include "special.h" -#include "mkdir.h" -#include "unit-name.h" -#include "generator.h" -#include "path-util.h" -#include "fstab-util.h" -#include "fileio.h" -#include "dropin.h" - -static int write_fsck_sysroot_service(const char *dir, const char *what) { - const char *unit; - _cleanup_free_ char *device = NULL; - _cleanup_free_ char *escaped; - _cleanup_fclose_ FILE *f = NULL; - int r; - - escaped = cescape(what); - if (!escaped) - return log_oom(); - - unit = strjoina(dir, "/systemd-fsck-root.service"); - log_debug("Creating %s", unit); - - r = unit_name_from_path(what, ".device", &device); - if (r < 0) - return log_error_errno(r, "Failed to convert device \"%s\" to unit name: %m", what); - - f = fopen(unit, "wxe"); - if (!f) - return log_error_errno(errno, "Failed to create unit file %s: %m", unit); - - fprintf(f, - "# Automatically generated by %1$s\n\n" - "[Unit]\n" - "Documentation=man:systemd-fsck-root.service(8)\n" - "Description=File System Check on %2$s\n" - "DefaultDependencies=no\n" - "BindsTo=%3$s\n" - "After=%3$s\n" - "Before=shutdown.target\n" - "\n" - "[Service]\n" - "Type=oneshot\n" - "RemainAfterExit=yes\n" - "ExecStart=" SYSTEMD_FSCK_PATH " %4$s\n" - "TimeoutSec=0\n", - program_invocation_short_name, - what, - device, - escaped); - - r = fflush_and_check(f); - if (r < 0) - return log_error_errno(r, "Failed to write unit file %s: %m", unit); - - return 0; -} - -int generator_write_fsck_deps( - FILE *f, - const char *dir, - const char *what, - const char *where, - const char *fstype) { - - int r; - - assert(f); - assert(dir); - assert(what); - assert(where); - - if (!is_device_path(what)) { - log_warning("Checking was requested for \"%s\", but it is not a device.", what); - return 0; - } - - if (!isempty(fstype) && !streq(fstype, "auto")) { - r = fsck_exists(fstype); - if (r == -ENOENT) { - /* treat missing check as essentially OK */ - log_debug_errno(r, "Checking was requested for %s, but fsck.%s does not exist: %m", what, fstype); - return 0; - } else if (r < 0) - return log_warning_errno(r, "Checking was requested for %s, but fsck.%s cannot be used: %m", what, fstype); - } - - if (path_equal(where, "/")) { - char *lnk; - - lnk = strjoina(dir, "/" SPECIAL_LOCAL_FS_TARGET ".wants/systemd-fsck-root.service"); - - mkdir_parents(lnk, 0755); - if (symlink(SYSTEM_DATA_UNIT_PATH "/systemd-fsck-root.service", lnk) < 0) - return log_error_errno(errno, "Failed to create symlink %s: %m", lnk); - - } else { - _cleanup_free_ char *_fsck = NULL; - const char *fsck; - - if (in_initrd() && path_equal(where, "/sysroot")) { - r = write_fsck_sysroot_service(dir, what); - if (r < 0) - return r; - - fsck = "systemd-fsck-root.service"; - } else { - r = unit_name_from_path_instance("systemd-fsck", what, ".service", &_fsck); - if (r < 0) - return log_error_errno(r, "Failed to create fsck service name: %m"); - - fsck = _fsck; - } - - fprintf(f, - "RequiresOverridable=%1$s\n" - "After=%1$s\n", - fsck); - } - - return 0; -} - -int generator_write_timeouts( - const char *dir, - const char *what, - const char *where, - const char *opts, - char **filtered) { - - /* Allow configuration how long we wait for a device that - * backs a mount point to show up. This is useful to support - * endless device timeouts for devices that show up only after - * user input, like crypto devices. */ - - _cleanup_free_ char *node = NULL, *unit = NULL, *timeout = NULL; - usec_t u; - int r; - - r = fstab_filter_options(opts, "comment=systemd.device-timeout\0" "x-systemd.device-timeout\0", - NULL, &timeout, filtered); - if (r <= 0) - return r; - - r = parse_sec(timeout, &u); - if (r < 0) { - log_warning("Failed to parse timeout for %s, ignoring: %s", where, timeout); - return 0; - } - - node = fstab_node_to_udev_node(what); - if (!node) - return log_oom(); - - r = unit_name_from_path(node, ".device", &unit); - if (r < 0) - return log_error_errno(r, "Failed to make unit name from path: %m"); - - return write_drop_in_format(dir, unit, 50, "device-timeout", - "# Automatically generated by %s\n\n" - "[Unit]\nJobTimeoutSec=" USEC_FMT, - program_invocation_short_name, - u / USEC_PER_SEC); -} diff --git a/src/shared/install.c b/src/shared/install.c deleted file mode 100644 index 3d2b5ae77..000000000 --- a/src/shared/install.c +++ /dev/null @@ -1,2298 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2011 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 . -***/ - -#include -#include -#include -#include -#include - -#include "util.h" -#include "mkdir.h" -#include "hashmap.h" -#include "set.h" -#include "path-util.h" -#include "path-lookup.h" -#include "strv.h" -#include "unit-name.h" -#include "install.h" -#include "conf-parser.h" -#include "conf-files.h" -#include "install-printf.h" -#include "special.h" - -typedef struct { - OrderedHashmap *will_install; - OrderedHashmap *have_installed; -} InstallContext; - -static int in_search_path(const char *path, char **search) { - _cleanup_free_ char *parent = NULL; - int r; - - assert(path); - - r = path_get_parent(path, &parent); - if (r < 0) - return r; - - return strv_contains(search, parent); -} - -static int get_config_path(UnitFileScope scope, bool runtime, const char *root_dir, char **ret) { - char *p = NULL; - int r; - - assert(scope >= 0); - assert(scope < _UNIT_FILE_SCOPE_MAX); - assert(ret); - - switch (scope) { - - case UNIT_FILE_SYSTEM: - - if (runtime) - p = path_join(root_dir, "/run/systemd/system", NULL); - else - p = path_join(root_dir, SYSTEM_CONFIG_UNIT_PATH, NULL); - break; - - case UNIT_FILE_GLOBAL: - - if (root_dir) - return -EINVAL; - - if (runtime) - p = strdup("/run/systemd/user"); - else - p = strdup(USER_CONFIG_UNIT_PATH); - break; - - case UNIT_FILE_USER: - - if (root_dir) - return -EINVAL; - - if (runtime) - r = user_runtime_dir(&p); - else - r = user_config_home(&p); - - if (r <= 0) - return r < 0 ? r : -ENOENT; - - break; - - default: - assert_not_reached("Bad scope"); - } - - if (!p) - return -ENOMEM; - - *ret = p; - return 0; -} - -static int mark_symlink_for_removal( - Set **remove_symlinks_to, - const char *p) { - - char *n; - int r; - - assert(p); - - r = set_ensure_allocated(remove_symlinks_to, &string_hash_ops); - if (r < 0) - return r; - - n = strdup(p); - if (!n) - return -ENOMEM; - - path_kill_slashes(n); - - r = set_consume(*remove_symlinks_to, n); - if (r < 0) - return r == -EEXIST ? 0 : r; - - return 0; -} - -static int remove_marked_symlinks_fd( - Set *remove_symlinks_to, - int fd, - const char *path, - const char *config_path, - bool *deleted, - UnitFileChange **changes, - unsigned *n_changes, - char** instance_whitelist) { - - _cleanup_closedir_ DIR *d = NULL; - int r = 0; - - assert(remove_symlinks_to); - assert(fd >= 0); - assert(path); - assert(config_path); - assert(deleted); - - d = fdopendir(fd); - if (!d) { - safe_close(fd); - return -errno; - } - - rewinddir(d); - - for (;;) { - struct dirent *de; - - errno = 0; - de = readdir(d); - if (!de && errno != 0) { - r = -errno; - break; - } - - if (!de) - break; - - if (hidden_file(de->d_name)) - continue; - - dirent_ensure_type(d, de); - - if (de->d_type == DT_DIR) { - int nfd, q; - _cleanup_free_ char *p = NULL; - - nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW); - if (nfd < 0) { - if (errno == ENOENT) - continue; - - if (r == 0) - r = -errno; - continue; - } - - p = path_make_absolute(de->d_name, path); - if (!p) { - safe_close(nfd); - return -ENOMEM; - } - - /* This will close nfd, regardless whether it succeeds or not */ - q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, deleted, changes, n_changes, instance_whitelist); - if (q < 0 && r == 0) - r = q; - - } else if (de->d_type == DT_LNK) { - _cleanup_free_ char *p = NULL, *dest = NULL; - int q; - bool found; - - if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY)) - continue; - - if (unit_name_is_valid(de->d_name, UNIT_NAME_INSTANCE) && - instance_whitelist && - !strv_contains(instance_whitelist, de->d_name)) { - - _cleanup_free_ char *w = NULL; - - /* OK, the file is not listed directly - * in the whitelist, so let's check if - * the template of it might be - * listed. */ - - r = unit_name_template(de->d_name, &w); - if (r < 0) - return r; - - if (!strv_contains(instance_whitelist, w)) - continue; - } - - p = path_make_absolute(de->d_name, path); - if (!p) - return -ENOMEM; - - q = readlink_and_canonicalize(p, &dest); - if (q < 0) { - if (q == -ENOENT) - continue; - - if (r == 0) - r = q; - continue; - } - - found = - set_get(remove_symlinks_to, dest) || - set_get(remove_symlinks_to, basename(dest)); - - if (!found) - continue; - - if (unlink(p) < 0 && errno != ENOENT) { - if (r == 0) - r = -errno; - continue; - } - - path_kill_slashes(p); - rmdir_parents(p, config_path); - unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, p, NULL); - - if (!set_get(remove_symlinks_to, p)) { - - q = mark_symlink_for_removal(&remove_symlinks_to, p); - if (q < 0) { - if (r == 0) - r = q; - } else - *deleted = true; - } - } - } - - return r; -} - -static int remove_marked_symlinks( - Set *remove_symlinks_to, - const char *config_path, - UnitFileChange **changes, - unsigned *n_changes, - char** instance_whitelist) { - - _cleanup_close_ int fd = -1; - int r = 0; - bool deleted; - - assert(config_path); - - if (set_size(remove_symlinks_to) <= 0) - return 0; - - fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW); - if (fd < 0) - return -errno; - - do { - int q, cfd; - deleted = false; - - cfd = fcntl(fd, F_DUPFD_CLOEXEC, 3); - if (cfd < 0) { - r = -errno; - break; - } - - /* This takes possession of cfd and closes it */ - q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, instance_whitelist); - if (r == 0) - r = q; - } while (deleted); - - return r; -} - -static int find_symlinks_fd( - const char *name, - int fd, - const char *path, - const char *config_path, - bool *same_name_link) { - - int r = 0; - _cleanup_closedir_ DIR *d = NULL; - - assert(name); - assert(fd >= 0); - assert(path); - assert(config_path); - assert(same_name_link); - - d = fdopendir(fd); - if (!d) { - safe_close(fd); - return -errno; - } - - for (;;) { - struct dirent *de; - - errno = 0; - de = readdir(d); - if (!de && errno != 0) - return -errno; - - if (!de) - return r; - - if (hidden_file(de->d_name)) - continue; - - dirent_ensure_type(d, de); - - if (de->d_type == DT_DIR) { - int nfd, q; - _cleanup_free_ char *p = NULL; - - nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW); - if (nfd < 0) { - if (errno == ENOENT) - continue; - - if (r == 0) - r = -errno; - continue; - } - - p = path_make_absolute(de->d_name, path); - if (!p) { - safe_close(nfd); - return -ENOMEM; - } - - /* This will close nfd, regardless whether it succeeds or not */ - q = find_symlinks_fd(name, nfd, p, config_path, same_name_link); - if (q > 0) - return 1; - if (r == 0) - r = q; - - } else if (de->d_type == DT_LNK) { - _cleanup_free_ char *p = NULL, *dest = NULL; - bool found_path, found_dest, b = false; - int q; - - /* Acquire symlink name */ - p = path_make_absolute(de->d_name, path); - if (!p) - return -ENOMEM; - - /* Acquire symlink destination */ - q = readlink_and_canonicalize(p, &dest); - if (q < 0) { - if (q == -ENOENT) - continue; - - if (r == 0) - r = q; - continue; - } - - /* Check if the symlink itself matches what we - * are looking for */ - if (path_is_absolute(name)) - found_path = path_equal(p, name); - else - found_path = streq(de->d_name, name); - - /* Check if what the symlink points to - * matches what we are looking for */ - if (path_is_absolute(name)) - found_dest = path_equal(dest, name); - else - found_dest = streq(basename(dest), name); - - if (found_path && found_dest) { - _cleanup_free_ char *t = NULL; - - /* Filter out same name links in the main - * config path */ - t = path_make_absolute(name, config_path); - if (!t) - return -ENOMEM; - - b = path_equal(t, p); - } - - if (b) - *same_name_link = true; - else if (found_path || found_dest) - return 1; - } - } -} - -static int find_symlinks( - const char *name, - const char *config_path, - bool *same_name_link) { - - int fd; - - assert(name); - assert(config_path); - assert(same_name_link); - - fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW); - if (fd < 0) { - if (errno == ENOENT) - return 0; - return -errno; - } - - /* This takes possession of fd and closes it */ - return find_symlinks_fd(name, fd, config_path, config_path, same_name_link); -} - -static int find_symlinks_in_scope( - UnitFileScope scope, - const char *root_dir, - const char *name, - UnitFileState *state) { - - int r; - _cleanup_free_ char *normal_path = NULL, *runtime_path = NULL; - bool same_name_link_runtime = false, same_name_link = false; - - assert(scope >= 0); - assert(scope < _UNIT_FILE_SCOPE_MAX); - assert(name); - - /* First look in runtime config path */ - r = get_config_path(scope, true, root_dir, &normal_path); - if (r < 0) - return r; - - r = find_symlinks(name, normal_path, &same_name_link_runtime); - if (r < 0) - return r; - else if (r > 0) { - *state = UNIT_FILE_ENABLED_RUNTIME; - return r; - } - - /* Then look in the normal config path */ - r = get_config_path(scope, false, root_dir, &runtime_path); - if (r < 0) - return r; - - r = find_symlinks(name, runtime_path, &same_name_link); - if (r < 0) - return r; - else if (r > 0) { - *state = UNIT_FILE_ENABLED; - return r; - } - - /* Hmm, we didn't find it, but maybe we found the same name - * link? */ - if (same_name_link_runtime) { - *state = UNIT_FILE_LINKED_RUNTIME; - return 1; - } else if (same_name_link) { - *state = UNIT_FILE_LINKED; - return 1; - } - - return 0; -} - -int unit_file_mask( - UnitFileScope scope, - bool runtime, - const char *root_dir, - char **files, - bool force, - UnitFileChange **changes, - unsigned *n_changes) { - - char **i; - _cleanup_free_ char *prefix = NULL; - int r; - - assert(scope >= 0); - assert(scope < _UNIT_FILE_SCOPE_MAX); - - r = get_config_path(scope, runtime, root_dir, &prefix); - if (r < 0) - return r; - - STRV_FOREACH(i, files) { - _cleanup_free_ char *path = NULL; - - if (!unit_name_is_valid(*i, UNIT_NAME_ANY)) { - if (r == 0) - r = -EINVAL; - continue; - } - - path = path_make_absolute(*i, prefix); - if (!path) { - r = -ENOMEM; - break; - } - - if (symlink("/dev/null", path) >= 0) { - unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null"); - continue; - } - - if (errno == EEXIST) { - - if (null_or_empty_path(path) > 0) - continue; - - if (force) { - if (symlink_atomic("/dev/null", path) >= 0) { - unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL); - unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null"); - continue; - } - } - - if (r == 0) - r = -EEXIST; - } else { - if (r == 0) - r = -errno; - } - } - - return r; -} - -int unit_file_unmask( - UnitFileScope scope, - bool runtime, - const char *root_dir, - char **files, - UnitFileChange **changes, - unsigned *n_changes) { - - char **i, *config_path = NULL; - int r, q; - Set *remove_symlinks_to = NULL; - - assert(scope >= 0); - assert(scope < _UNIT_FILE_SCOPE_MAX); - - r = get_config_path(scope, runtime, root_dir, &config_path); - if (r < 0) - goto finish; - - STRV_FOREACH(i, files) { - _cleanup_free_ char *path = NULL; - - if (!unit_name_is_valid(*i, UNIT_NAME_ANY)) { - if (r == 0) - r = -EINVAL; - continue; - } - - path = path_make_absolute(*i, config_path); - if (!path) { - r = -ENOMEM; - break; - } - - q = null_or_empty_path(path); - if (q > 0) { - if (unlink(path) < 0) - q = -errno; - else { - q = mark_symlink_for_removal(&remove_symlinks_to, path); - unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL); - } - } - - if (q != -ENOENT && r == 0) - r = q; - } - - -finish: - q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files); - if (r == 0) - r = q; - - set_free_free(remove_symlinks_to); - free(config_path); - - return r; -} - -int unit_file_link( - UnitFileScope scope, - bool runtime, - const char *root_dir, - char **files, - bool force, - UnitFileChange **changes, - unsigned *n_changes) { - - _cleanup_lookup_paths_free_ LookupPaths paths = {}; - char **i; - _cleanup_free_ char *config_path = NULL; - int r, q; - - assert(scope >= 0); - assert(scope < _UNIT_FILE_SCOPE_MAX); - - r = lookup_paths_init_from_scope(&paths, scope, root_dir); - if (r < 0) - return r; - - r = get_config_path(scope, runtime, root_dir, &config_path); - if (r < 0) - return r; - - STRV_FOREACH(i, files) { - _cleanup_free_ char *path = NULL; - char *fn; - struct stat st; - - fn = basename(*i); - - if (!path_is_absolute(*i) || - !unit_name_is_valid(fn, UNIT_NAME_ANY)) { - if (r == 0) - r = -EINVAL; - continue; - } - - if (lstat(*i, &st) < 0) { - if (r == 0) - r = -errno; - continue; - } - - if (!S_ISREG(st.st_mode)) { - r = -ENOENT; - continue; - } - - q = in_search_path(*i, paths.unit_path); - if (q < 0) - return q; - - if (q > 0) - continue; - - path = path_make_absolute(fn, config_path); - if (!path) - return -ENOMEM; - - if (symlink(*i, path) >= 0) { - unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, path, *i); - continue; - } - - if (errno == EEXIST) { - _cleanup_free_ char *dest = NULL; - - q = readlink_and_make_absolute(path, &dest); - if (q < 0 && errno != ENOENT) { - if (r == 0) - r = q; - continue; - } - - if (q >= 0 && path_equal(dest, *i)) - continue; - - if (force) { - if (symlink_atomic(*i, path) >= 0) { - unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL); - unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, path, *i); - continue; - } - } - - if (r == 0) - r = -EEXIST; - } else { - if (r == 0) - r = -errno; - } - } - - return r; -} - -void unit_file_list_free(Hashmap *h) { - UnitFileList *i; - - while ((i = hashmap_steal_first(h))) { - free(i->path); - free(i); - } - - hashmap_free(h); -} - -int unit_file_changes_add( - UnitFileChange **changes, - unsigned *n_changes, - UnitFileChangeType type, - const char *path, - const char *source) { - - UnitFileChange *c; - unsigned i; - - assert(path); - assert(!changes == !n_changes); - - if (!changes) - return 0; - - c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange)); - if (!c) - return -ENOMEM; - - *changes = c; - i = *n_changes; - - c[i].type = type; - c[i].path = strdup(path); - if (!c[i].path) - return -ENOMEM; - - path_kill_slashes(c[i].path); - - if (source) { - c[i].source = strdup(source); - if (!c[i].source) { - free(c[i].path); - return -ENOMEM; - } - - path_kill_slashes(c[i].path); - } else - c[i].source = NULL; - - *n_changes = i+1; - return 0; -} - -void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) { - unsigned i; - - assert(changes || n_changes == 0); - - if (!changes) - return; - - for (i = 0; i < n_changes; i++) { - free(changes[i].path); - free(changes[i].source); - } - - free(changes); -} - -static void install_info_free(UnitFileInstallInfo *i) { - assert(i); - - free(i->name); - free(i->path); - strv_free(i->aliases); - strv_free(i->wanted_by); - strv_free(i->required_by); - strv_free(i->also); - free(i->default_instance); - free(i); -} - -static void install_info_hashmap_free(OrderedHashmap *m) { - UnitFileInstallInfo *i; - - if (!m) - return; - - while ((i = ordered_hashmap_steal_first(m))) - install_info_free(i); - - ordered_hashmap_free(m); -} - -static void install_context_done(InstallContext *c) { - assert(c); - - install_info_hashmap_free(c->will_install); - install_info_hashmap_free(c->have_installed); - - c->will_install = c->have_installed = NULL; -} - -static int install_info_add( - InstallContext *c, - const char *name, - const char *path) { - UnitFileInstallInfo *i = NULL; - int r; - - assert(c); - assert(name || path); - - if (!name) - name = basename(path); - - if (!unit_name_is_valid(name, UNIT_NAME_ANY)) - return -EINVAL; - - if (ordered_hashmap_get(c->have_installed, name) || - ordered_hashmap_get(c->will_install, name)) - return 0; - - r = ordered_hashmap_ensure_allocated(&c->will_install, &string_hash_ops); - if (r < 0) - return r; - - i = new0(UnitFileInstallInfo, 1); - if (!i) - return -ENOMEM; - - i->name = strdup(name); - if (!i->name) { - r = -ENOMEM; - goto fail; - } - - if (path) { - i->path = strdup(path); - if (!i->path) { - r = -ENOMEM; - goto fail; - } - } - - r = ordered_hashmap_put(c->will_install, i->name, i); - if (r < 0) - goto fail; - - return 0; - -fail: - if (i) - install_info_free(i); - - return r; -} - -static int install_info_add_auto( - InstallContext *c, - const char *name_or_path) { - - assert(c); - assert(name_or_path); - - if (path_is_absolute(name_or_path)) - return install_info_add(c, NULL, name_or_path); - else - return install_info_add(c, name_or_path, NULL); -} - -static int config_parse_also( - const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { - - size_t l; - const char *word, *state; - InstallContext *c = data; - UnitFileInstallInfo *i = userdata; - - assert(filename); - assert(lvalue); - assert(rvalue); - - FOREACH_WORD_QUOTED(word, l, rvalue, state) { - _cleanup_free_ char *n; - int r; - - n = strndup(word, l); - if (!n) - return -ENOMEM; - - r = install_info_add(c, n, NULL); - if (r < 0) - return r; - - r = strv_extend(&i->also, n); - if (r < 0) - return r; - } - if (!isempty(state)) - log_syntax(unit, LOG_ERR, filename, line, EINVAL, - "Trailing garbage, ignoring."); - - return 0; -} - -static int config_parse_user( - const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { - - UnitFileInstallInfo *i = data; - char *printed; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - - r = install_full_printf(i, rvalue, &printed); - if (r < 0) - return r; - - free(i->user); - i->user = printed; - - return 0; -} - -static int config_parse_default_instance( - const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { - - UnitFileInstallInfo *i = data; - char *printed; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - - r = install_full_printf(i, rvalue, &printed); - if (r < 0) - return r; - - if (!unit_instance_is_valid(printed)) { - free(printed); - return -EINVAL; - } - - free(i->default_instance); - i->default_instance = printed; - - return 0; -} - -static int unit_file_load( - InstallContext *c, - UnitFileInstallInfo *info, - const char *path, - const char *root_dir, - bool allow_symlink, - bool load, - bool *also) { - - const ConfigTableItem items[] = { - { "Install", "Alias", config_parse_strv, 0, &info->aliases }, - { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by }, - { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by }, - { "Install", "DefaultInstance", config_parse_default_instance, 0, info }, - { "Install", "Also", config_parse_also, 0, c }, - { "Exec", "User", config_parse_user, 0, info }, - {} - }; - - _cleanup_fclose_ FILE *f = NULL; - int fd, r; - - assert(c); - assert(info); - assert(path); - - if (!isempty(root_dir)) - path = strjoina(root_dir, "/", path); - - if (!load) { - r = access(path, F_OK) ? -errno : 0; - return r; - } - - fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW)); - if (fd < 0) - return -errno; - - f = fdopen(fd, "re"); - if (!f) { - safe_close(fd); - return -ENOMEM; - } - - r = config_parse(NULL, path, f, - NULL, - config_item_table_lookup, items, - true, true, false, info); - if (r < 0) - return r; - - if (also) - *also = !strv_isempty(info->also); - - return - (int) strv_length(info->aliases) + - (int) strv_length(info->wanted_by) + - (int) strv_length(info->required_by); -} - -static int unit_file_search( - InstallContext *c, - UnitFileInstallInfo *info, - const LookupPaths *paths, - const char *root_dir, - bool allow_symlink, - bool load, - bool *also) { - - char **p; - int r; - - assert(c); - assert(info); - assert(paths); - - if (info->path) - return unit_file_load(c, info, info->path, root_dir, allow_symlink, load, also); - - assert(info->name); - - STRV_FOREACH(p, paths->unit_path) { - _cleanup_free_ char *path = NULL; - - path = strjoin(*p, "/", info->name, NULL); - if (!path) - return -ENOMEM; - - r = unit_file_load(c, info, path, root_dir, allow_symlink, load, also); - if (r >= 0) { - info->path = path; - path = NULL; - return r; - } - if (r != -ENOENT && r != -ELOOP) - return r; - } - - if (unit_name_is_valid(info->name, UNIT_NAME_INSTANCE)) { - - /* Unit file doesn't exist, however instance - * enablement was requested. We will check if it is - * possible to load template unit file. */ - - _cleanup_free_ char *template = NULL; - - r = unit_name_template(info->name, &template); - if (r < 0) - return r; - - STRV_FOREACH(p, paths->unit_path) { - _cleanup_free_ char *path = NULL; - - path = strjoin(*p, "/", template, NULL); - if (!path) - return -ENOMEM; - - r = unit_file_load(c, info, path, root_dir, allow_symlink, load, also); - if (r >= 0) { - info->path = path; - path = NULL; - return r; - } - if (r != -ENOENT && r != -ELOOP) - return r; - } - } - - return -ENOENT; -} - -static int unit_file_can_install( - const LookupPaths *paths, - const char *root_dir, - const char *name, - bool allow_symlink, - bool *also) { - - _cleanup_(install_context_done) InstallContext c = {}; - UnitFileInstallInfo *i; - int r; - - assert(paths); - assert(name); - - r = install_info_add_auto(&c, name); - if (r < 0) - return r; - - assert_se(i = ordered_hashmap_first(c.will_install)); - - r = unit_file_search(&c, i, paths, root_dir, allow_symlink, true, also); - - if (r >= 0) - r = - (int) strv_length(i->aliases) + - (int) strv_length(i->wanted_by) + - (int) strv_length(i->required_by); - - return r; -} - -static int create_symlink( - const char *old_path, - const char *new_path, - bool force, - UnitFileChange **changes, - unsigned *n_changes) { - - _cleanup_free_ char *dest = NULL; - int r; - - assert(old_path); - assert(new_path); - - mkdir_parents_label(new_path, 0755); - - if (symlink(old_path, new_path) >= 0) { - unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path); - return 0; - } - - if (errno != EEXIST) - return -errno; - - r = readlink_and_make_absolute(new_path, &dest); - if (r < 0) - return r; - - if (path_equal(dest, old_path)) - return 0; - - if (!force) - return -EEXIST; - - r = symlink_atomic(old_path, new_path); - if (r < 0) - return r; - - unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL); - unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path); - - return 0; -} - -static int install_info_symlink_alias( - UnitFileInstallInfo *i, - const char *config_path, - bool force, - UnitFileChange **changes, - unsigned *n_changes) { - - char **s; - int r = 0, q; - - assert(i); - assert(config_path); - - STRV_FOREACH(s, i->aliases) { - _cleanup_free_ char *alias_path = NULL, *dst = NULL; - - q = install_full_printf(i, *s, &dst); - if (q < 0) - return q; - - alias_path = path_make_absolute(dst, config_path); - if (!alias_path) - return -ENOMEM; - - q = create_symlink(i->path, alias_path, force, changes, n_changes); - if (r == 0) - r = q; - } - - return r; -} - -static int install_info_symlink_wants( - UnitFileInstallInfo *i, - const char *config_path, - char **list, - const char *suffix, - bool force, - UnitFileChange **changes, - unsigned *n_changes) { - - _cleanup_free_ char *buf = NULL; - const char *n; - char **s; - int r = 0, q; - - assert(i); - assert(config_path); - - if (unit_name_is_valid(i->name, UNIT_NAME_TEMPLATE)) { - - /* Don't install any symlink if there's no default - * instance configured */ - - if (!i->default_instance) - return 0; - - r = unit_name_replace_instance(i->name, i->default_instance, &buf); - if (r < 0) - return r; - - n = buf; - } else - n = i->name; - - STRV_FOREACH(s, list) { - _cleanup_free_ char *path = NULL, *dst = NULL; - - q = install_full_printf(i, *s, &dst); - if (q < 0) - return q; - - if (!unit_name_is_valid(dst, UNIT_NAME_ANY)) { - r = -EINVAL; - continue; - } - - path = strjoin(config_path, "/", dst, suffix, n, NULL); - if (!path) - return -ENOMEM; - - q = create_symlink(i->path, path, force, changes, n_changes); - if (r == 0) - r = q; - } - - return r; -} - -static int install_info_symlink_link( - UnitFileInstallInfo *i, - const LookupPaths *paths, - const char *config_path, - const char *root_dir, - bool force, - UnitFileChange **changes, - unsigned *n_changes) { - - _cleanup_free_ char *path = NULL; - int r; - - assert(i); - assert(paths); - assert(config_path); - assert(i->path); - - r = in_search_path(i->path, paths->unit_path); - if (r != 0) - return r; - - path = strjoin(config_path, "/", i->name, NULL); - if (!path) - return -ENOMEM; - - return create_symlink(i->path, path, force, changes, n_changes); -} - -static int install_info_apply( - UnitFileInstallInfo *i, - const LookupPaths *paths, - const char *config_path, - const char *root_dir, - bool force, - UnitFileChange **changes, - unsigned *n_changes) { - - int r, q; - - assert(i); - assert(paths); - assert(config_path); - - r = install_info_symlink_alias(i, config_path, force, changes, n_changes); - - q = install_info_symlink_wants(i, config_path, i->wanted_by, ".wants/", force, changes, n_changes); - if (r == 0) - r = q; - - q = install_info_symlink_wants(i, config_path, i->required_by, ".requires/", force, changes, n_changes); - if (r == 0) - r = q; - - q = install_info_symlink_link(i, paths, config_path, root_dir, force, changes, n_changes); - if (r == 0) - r = q; - - return r; -} - -static int install_context_apply( - InstallContext *c, - const LookupPaths *paths, - const char *config_path, - const char *root_dir, - bool force, - UnitFileChange **changes, - unsigned *n_changes) { - - UnitFileInstallInfo *i; - int r, q; - - assert(c); - assert(paths); - assert(config_path); - - if (!ordered_hashmap_isempty(c->will_install)) { - r = ordered_hashmap_ensure_allocated(&c->have_installed, &string_hash_ops); - if (r < 0) - return r; - - r = ordered_hashmap_reserve(c->have_installed, ordered_hashmap_size(c->will_install)); - if (r < 0) - return r; - } - - r = 0; - while ((i = ordered_hashmap_first(c->will_install))) { - assert_se(ordered_hashmap_move_one(c->have_installed, c->will_install, i->name) == 0); - - q = unit_file_search(c, i, paths, root_dir, false, true, NULL); - if (q < 0) { - if (r >= 0) - r = q; - - return r; - } else if (r >= 0) - r += q; - - q = install_info_apply(i, paths, config_path, root_dir, force, changes, n_changes); - if (r >= 0 && q < 0) - r = q; - } - - return r; -} - -static int install_context_mark_for_removal( - InstallContext *c, - const LookupPaths *paths, - Set **remove_symlinks_to, - const char *config_path, - const char *root_dir) { - - UnitFileInstallInfo *i; - int r, q; - - assert(c); - assert(paths); - assert(config_path); - - /* Marks all items for removal */ - - if (!ordered_hashmap_isempty(c->will_install)) { - r = ordered_hashmap_ensure_allocated(&c->have_installed, &string_hash_ops); - if (r < 0) - return r; - - r = ordered_hashmap_reserve(c->have_installed, ordered_hashmap_size(c->will_install)); - if (r < 0) - return r; - } - - r = 0; - while ((i = ordered_hashmap_first(c->will_install))) { - assert_se(ordered_hashmap_move_one(c->have_installed, c->will_install, i->name) == 0); - - q = unit_file_search(c, i, paths, root_dir, false, true, NULL); - if (q == -ENOENT) { - /* do nothing */ - } else if (q < 0) { - if (r >= 0) - r = q; - - return r; - } else if (r >= 0) - r += q; - - if (unit_name_is_valid(i->name, UNIT_NAME_INSTANCE)) { - char *unit_file; - - if (i->path) { - unit_file = basename(i->path); - - if (unit_name_is_valid(unit_file, UNIT_NAME_INSTANCE)) - /* unit file named as instance exists, thus all symlinks - * pointing to it will be removed */ - q = mark_symlink_for_removal(remove_symlinks_to, i->name); - else - /* does not exist, thus we will mark for removal symlinks - * to template unit file */ - q = mark_symlink_for_removal(remove_symlinks_to, unit_file); - } else { - /* If i->path is not set, it means that we didn't actually find - * the unit file. But we can still remove symlinks to the - * nonexistent template. */ - r = unit_name_template(i->name, &unit_file); - if (r < 0) - return r; - - q = mark_symlink_for_removal(remove_symlinks_to, unit_file); - free(unit_file); - } - } else - q = mark_symlink_for_removal(remove_symlinks_to, i->name); - - if (r >= 0 && q < 0) - r = q; - } - - return r; -} - -int unit_file_add_dependency( - UnitFileScope scope, - bool runtime, - const char *root_dir, - char **files, - char *target, - UnitDependency dep, - bool force, - UnitFileChange **changes, - unsigned *n_changes) { - - _cleanup_lookup_paths_free_ LookupPaths paths = {}; - _cleanup_(install_context_done) InstallContext c = {}; - _cleanup_free_ char *config_path = NULL; - char **i; - int r; - UnitFileInstallInfo *info; - - assert(scope >= 0); - assert(scope < _UNIT_FILE_SCOPE_MAX); - - r = lookup_paths_init_from_scope(&paths, scope, root_dir); - if (r < 0) - return r; - - r = get_config_path(scope, runtime, root_dir, &config_path); - if (r < 0) - return r; - - STRV_FOREACH(i, files) { - UnitFileState state; - - state = unit_file_get_state(scope, root_dir, *i); - if (state < 0) - return log_error_errno(state, "Failed to get unit file state for %s: %m", *i); - - if (state == UNIT_FILE_MASKED || state == UNIT_FILE_MASKED_RUNTIME) { - log_error("Failed to enable unit: Unit %s is masked", *i); - return -EOPNOTSUPP; - } - - r = install_info_add_auto(&c, *i); - if (r < 0) - return r; - } - - if (!ordered_hashmap_isempty(c.will_install)) { - r = ordered_hashmap_ensure_allocated(&c.have_installed, &string_hash_ops); - if (r < 0) - return r; - - r = ordered_hashmap_reserve(c.have_installed, ordered_hashmap_size(c.will_install)); - if (r < 0) - return r; - } - - while ((info = ordered_hashmap_first(c.will_install))) { - assert_se(ordered_hashmap_move_one(c.have_installed, c.will_install, info->name) == 0); - - r = unit_file_search(&c, info, &paths, root_dir, false, false, NULL); - if (r < 0) - return r; - - if (dep == UNIT_WANTS) - r = strv_extend(&info->wanted_by, target); - else if (dep == UNIT_REQUIRES) - r = strv_extend(&info->required_by, target); - else - r = -EINVAL; - - if (r < 0) - return r; - - r = install_info_apply(info, &paths, config_path, root_dir, force, changes, n_changes); - if (r < 0) - return r; - } - - return 0; -} - -int unit_file_enable( - UnitFileScope scope, - bool runtime, - const char *root_dir, - char **files, - bool force, - UnitFileChange **changes, - unsigned *n_changes) { - - _cleanup_lookup_paths_free_ LookupPaths paths = {}; - _cleanup_(install_context_done) InstallContext c = {}; - char **i; - _cleanup_free_ char *config_path = NULL; - int r; - - assert(scope >= 0); - assert(scope < _UNIT_FILE_SCOPE_MAX); - - r = lookup_paths_init_from_scope(&paths, scope, root_dir); - if (r < 0) - return r; - - r = get_config_path(scope, runtime, root_dir, &config_path); - if (r < 0) - return r; - - STRV_FOREACH(i, files) { - UnitFileState state; - - /* We only want to know if this unit is masked, so we ignore - * errors from unit_file_get_state, deferring other checks. - * This allows templated units to be enabled on the fly. */ - state = unit_file_get_state(scope, root_dir, *i); - if (state == UNIT_FILE_MASKED || state == UNIT_FILE_MASKED_RUNTIME) { - log_error("Failed to enable unit: Unit %s is masked", *i); - return -EOPNOTSUPP; - } - - r = install_info_add_auto(&c, *i); - if (r < 0) - return r; - } - - /* This will return the number of symlink rules that were - supposed to be created, not the ones actually created. This is - useful to determine whether the passed files had any - installation data at all. */ - - return install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes); -} - -int unit_file_disable( - UnitFileScope scope, - bool runtime, - const char *root_dir, - char **files, - UnitFileChange **changes, - unsigned *n_changes) { - - _cleanup_lookup_paths_free_ LookupPaths paths = {}; - _cleanup_(install_context_done) InstallContext c = {}; - char **i; - _cleanup_free_ char *config_path = NULL; - _cleanup_set_free_free_ Set *remove_symlinks_to = NULL; - int r, q; - - assert(scope >= 0); - assert(scope < _UNIT_FILE_SCOPE_MAX); - - r = lookup_paths_init_from_scope(&paths, scope, root_dir); - if (r < 0) - return r; - - r = get_config_path(scope, runtime, root_dir, &config_path); - if (r < 0) - return r; - - STRV_FOREACH(i, files) { - r = install_info_add_auto(&c, *i); - if (r < 0) - return r; - } - - r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir); - - q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files); - if (r >= 0) - r = q; - - return r; -} - -int unit_file_reenable( - UnitFileScope scope, - bool runtime, - const char *root_dir, - char **files, - bool force, - UnitFileChange **changes, - unsigned *n_changes) { - int r; - - r = unit_file_disable(scope, runtime, root_dir, files, - changes, n_changes); - if (r < 0) - return r; - - return unit_file_enable(scope, runtime, root_dir, files, force, - changes, n_changes); -} - -int unit_file_set_default( - UnitFileScope scope, - const char *root_dir, - const char *file, - bool force, - UnitFileChange **changes, - unsigned *n_changes) { - - _cleanup_lookup_paths_free_ LookupPaths paths = {}; - _cleanup_(install_context_done) InstallContext c = {}; - _cleanup_free_ char *config_path = NULL; - char *path; - int r; - UnitFileInstallInfo *i = NULL; - - assert(scope >= 0); - assert(scope < _UNIT_FILE_SCOPE_MAX); - assert(file); - - if (unit_name_to_type(file) != UNIT_TARGET) - return -EINVAL; - - r = lookup_paths_init_from_scope(&paths, scope, root_dir); - if (r < 0) - return r; - - r = get_config_path(scope, false, root_dir, &config_path); - if (r < 0) - return r; - - r = install_info_add_auto(&c, file); - if (r < 0) - return r; - - assert_se(i = ordered_hashmap_first(c.will_install)); - - r = unit_file_search(&c, i, &paths, root_dir, false, true, NULL); - if (r < 0) - return r; - - path = strjoina(config_path, "/" SPECIAL_DEFAULT_TARGET); - - r = create_symlink(i->path, path, force, changes, n_changes); - if (r < 0) - return r; - - return 0; -} - -int unit_file_get_default( - UnitFileScope scope, - const char *root_dir, - char **name) { - - _cleanup_lookup_paths_free_ LookupPaths paths = {}; - char **p; - int r; - - assert(scope >= 0); - assert(scope < _UNIT_FILE_SCOPE_MAX); - assert(name); - - r = lookup_paths_init_from_scope(&paths, scope, root_dir); - if (r < 0) - return r; - - STRV_FOREACH(p, paths.unit_path) { - _cleanup_free_ char *path = NULL, *tmp = NULL; - char *n; - - path = path_join(root_dir, *p, SPECIAL_DEFAULT_TARGET); - if (!path) - return -ENOMEM; - - r = readlink_malloc(path, &tmp); - if (r == -ENOENT) - continue; - else if (r == -EINVAL) - /* not a symlink */ - n = strdup(SPECIAL_DEFAULT_TARGET); - else if (r < 0) - return r; - else - n = strdup(basename(tmp)); - - if (!n) - return -ENOMEM; - - *name = n; - return 0; - } - - return -ENOENT; -} - -UnitFileState unit_file_lookup_state( - UnitFileScope scope, - const char *root_dir, - const LookupPaths *paths, - const char *name) { - - UnitFileState state = _UNIT_FILE_STATE_INVALID; - char **i; - _cleanup_free_ char *path = NULL; - int r = 0; - - assert(paths); - - if (!unit_name_is_valid(name, UNIT_NAME_ANY)) - return -EINVAL; - - STRV_FOREACH(i, paths->unit_path) { - struct stat st; - char *partial; - bool also = false; - - free(path); - path = path_join(root_dir, *i, name); - if (!path) - return -ENOMEM; - - if (root_dir) - partial = path + strlen(root_dir); - else - partial = path; - - /* - * Search for a unit file in our default paths, to - * be sure, that there are no broken symlinks. - */ - if (lstat(path, &st) < 0) { - r = -errno; - if (errno != ENOENT) - return r; - - if (!unit_name_is_valid(name, UNIT_NAME_INSTANCE)) - continue; - } else { - if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) - return -ENOENT; - - r = null_or_empty_path(path); - if (r < 0 && r != -ENOENT) - return r; - else if (r > 0) { - state = path_startswith(*i, "/run") ? UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED; - return state; - } - } - - r = find_symlinks_in_scope(scope, root_dir, name, &state); - if (r < 0) - return r; - else if (r > 0) - return state; - - r = unit_file_can_install(paths, root_dir, partial, true, &also); - if (r < 0 && errno != ENOENT) - return r; - else if (r > 0) - return UNIT_FILE_DISABLED; - else if (r == 0) { - if (also) - return UNIT_FILE_INDIRECT; - return UNIT_FILE_STATIC; - } - } - - return r < 0 ? r : state; -} - -UnitFileState unit_file_get_state( - UnitFileScope scope, - const char *root_dir, - const char *name) { - - _cleanup_lookup_paths_free_ LookupPaths paths = {}; - int r; - - assert(scope >= 0); - assert(scope < _UNIT_FILE_SCOPE_MAX); - assert(name); - - if (root_dir && scope != UNIT_FILE_SYSTEM) - return -EINVAL; - - r = lookup_paths_init_from_scope(&paths, scope, root_dir); - if (r < 0) - return r; - - return unit_file_lookup_state(scope, root_dir, &paths, name); -} - -int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) { - _cleanup_strv_free_ char **files = NULL; - char **p; - int r; - - assert(scope >= 0); - assert(scope < _UNIT_FILE_SCOPE_MAX); - assert(name); - - if (scope == UNIT_FILE_SYSTEM) - r = conf_files_list(&files, ".preset", root_dir, - "/etc/systemd/system-preset", - "/usr/local/lib/systemd/system-preset", - "/usr/lib/systemd/system-preset", -#ifdef HAVE_SPLIT_USR - "/lib/systemd/system-preset", -#endif - NULL); - else if (scope == UNIT_FILE_GLOBAL) - r = conf_files_list(&files, ".preset", root_dir, - "/etc/systemd/user-preset", - "/usr/local/lib/systemd/user-preset", - "/usr/lib/systemd/user-preset", - NULL); - else - return 1; - - if (r < 0) - return r; - - STRV_FOREACH(p, files) { - _cleanup_fclose_ FILE *f; - - f = fopen(*p, "re"); - if (!f) { - if (errno == ENOENT) - continue; - - return -errno; - } - - for (;;) { - char line[LINE_MAX], *l; - - if (!fgets(line, sizeof(line), f)) - break; - - l = strstrip(line); - if (!*l) - continue; - - if (strchr(COMMENTS "\n", *l)) - continue; - - if (first_word(l, "enable")) { - l += 6; - l += strspn(l, WHITESPACE); - - if (fnmatch(l, name, FNM_NOESCAPE) == 0) { - log_debug("Preset file says enable %s.", name); - return 1; - } - - } else if (first_word(l, "disable")) { - l += 7; - l += strspn(l, WHITESPACE); - - if (fnmatch(l, name, FNM_NOESCAPE) == 0) { - log_debug("Preset file says disable %s.", name); - return 0; - } - - } else - log_debug("Couldn't parse line '%s'", l); - } - } - - /* Default is "enable" */ - log_debug("Preset file doesn't say anything about %s, enabling.", name); - return 1; -} - -int unit_file_preset( - UnitFileScope scope, - bool runtime, - const char *root_dir, - char **files, - UnitFilePresetMode mode, - bool force, - UnitFileChange **changes, - unsigned *n_changes) { - - _cleanup_(install_context_done) InstallContext plus = {}, minus = {}; - _cleanup_lookup_paths_free_ LookupPaths paths = {}; - _cleanup_free_ char *config_path = NULL; - char **i; - int r, q; - - assert(scope >= 0); - assert(scope < _UNIT_FILE_SCOPE_MAX); - assert(mode < _UNIT_FILE_PRESET_MAX); - - r = lookup_paths_init_from_scope(&paths, scope, root_dir); - if (r < 0) - return r; - - r = get_config_path(scope, runtime, root_dir, &config_path); - if (r < 0) - return r; - - STRV_FOREACH(i, files) { - - if (!unit_name_is_valid(*i, UNIT_NAME_ANY)) - return -EINVAL; - - r = unit_file_query_preset(scope, root_dir, *i); - if (r < 0) - return r; - - if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY) - r = install_info_add_auto(&plus, *i); - else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY) - r = install_info_add_auto(&minus, *i); - else - r = 0; - if (r < 0) - return r; - } - - r = 0; - - if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) { - _cleanup_set_free_free_ Set *remove_symlinks_to = NULL; - - r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir); - - q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files); - if (r == 0) - r = q; - } - - if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) { - /* Returns number of symlinks that where supposed to be installed. */ - q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes); - if (r == 0) - r = q; - } - - return r; -} - -int unit_file_preset_all( - UnitFileScope scope, - bool runtime, - const char *root_dir, - UnitFilePresetMode mode, - bool force, - UnitFileChange **changes, - unsigned *n_changes) { - - _cleanup_(install_context_done) InstallContext plus = {}, minus = {}; - _cleanup_lookup_paths_free_ LookupPaths paths = {}; - _cleanup_free_ char *config_path = NULL; - char **i; - int r, q; - - assert(scope >= 0); - assert(scope < _UNIT_FILE_SCOPE_MAX); - assert(mode < _UNIT_FILE_PRESET_MAX); - - r = lookup_paths_init_from_scope(&paths, scope, root_dir); - if (r < 0) - return r; - - r = get_config_path(scope, runtime, root_dir, &config_path); - if (r < 0) - return r; - - STRV_FOREACH(i, paths.unit_path) { - _cleanup_closedir_ DIR *d = NULL; - _cleanup_free_ char *units_dir; - - units_dir = path_join(root_dir, *i, NULL); - if (!units_dir) - return -ENOMEM; - - d = opendir(units_dir); - if (!d) { - if (errno == ENOENT) - continue; - - return -errno; - } - - for (;;) { - struct dirent *de; - - errno = 0; - de = readdir(d); - if (!de && errno != 0) - return -errno; - - if (!de) - break; - - if (hidden_file(de->d_name)) - continue; - - if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY)) - continue; - - dirent_ensure_type(d, de); - - if (de->d_type != DT_REG) - continue; - - r = unit_file_query_preset(scope, root_dir, de->d_name); - if (r < 0) - return r; - - if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY) - r = install_info_add_auto(&plus, de->d_name); - else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY) - r = install_info_add_auto(&minus, de->d_name); - else - r = 0; - if (r < 0) - return r; - } - } - - r = 0; - - if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) { - _cleanup_set_free_free_ Set *remove_symlinks_to = NULL; - - r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir); - - q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, NULL); - if (r == 0) - r = q; - } - - if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) { - q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes); - if (r == 0) - r = q; - } - - return r; -} - -static void unit_file_list_free_one(UnitFileList *f) { - if (!f) - return; - - free(f->path); - free(f); -} - -DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList*, unit_file_list_free_one); - -int unit_file_get_list( - UnitFileScope scope, - const char *root_dir, - Hashmap *h) { - - _cleanup_lookup_paths_free_ LookupPaths paths = {}; - char **i; - int r; - - assert(scope >= 0); - assert(scope < _UNIT_FILE_SCOPE_MAX); - assert(h); - - if (root_dir && scope != UNIT_FILE_SYSTEM) - return -EINVAL; - - if (root_dir) { - r = access(root_dir, F_OK); - if (r < 0) - return -errno; - } - - r = lookup_paths_init_from_scope(&paths, scope, root_dir); - if (r < 0) - return r; - - STRV_FOREACH(i, paths.unit_path) { - _cleanup_closedir_ DIR *d = NULL; - _cleanup_free_ char *units_dir; - - units_dir = path_join(root_dir, *i, NULL); - if (!units_dir) - return -ENOMEM; - - d = opendir(units_dir); - if (!d) { - if (errno == ENOENT) - continue; - - return -errno; - } - - for (;;) { - _cleanup_(unit_file_list_free_onep) UnitFileList *f = NULL; - struct dirent *de; - _cleanup_free_ char *path = NULL; - bool also = false; - - errno = 0; - de = readdir(d); - if (!de && errno != 0) - return -errno; - - if (!de) - break; - - if (hidden_file(de->d_name)) - continue; - - if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY)) - continue; - - if (hashmap_get(h, de->d_name)) - continue; - - dirent_ensure_type(d, de); - - if (!IN_SET(de->d_type, DT_LNK, DT_REG)) - continue; - - f = new0(UnitFileList, 1); - if (!f) - return -ENOMEM; - - f->path = path_make_absolute(de->d_name, units_dir); - if (!f->path) - return -ENOMEM; - - r = null_or_empty_path(f->path); - if (r < 0 && r != -ENOENT) - return r; - else if (r > 0) { - f->state = - path_startswith(*i, "/run") ? - UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED; - goto found; - } - - r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state); - if (r < 0) - return r; - else if (r > 0) { - f->state = UNIT_FILE_ENABLED; - goto found; - } - - path = path_make_absolute(de->d_name, *i); - if (!path) - return -ENOMEM; - - r = unit_file_can_install(&paths, root_dir, path, true, &also); - if (r == -EINVAL || /* Invalid setting? */ - r == -EBADMSG || /* Invalid format? */ - r == -ENOENT /* Included file not found? */) - f->state = UNIT_FILE_INVALID; - else if (r < 0) - return r; - else if (r > 0) - f->state = UNIT_FILE_DISABLED; - else - f->state = also ? UNIT_FILE_INDIRECT : UNIT_FILE_STATIC; - - found: - r = hashmap_put(h, basename(f->path), f); - if (r < 0) - return r; - f = NULL; /* prevent cleanup */ - } - } - - return 0; -} - -static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = { - [UNIT_FILE_ENABLED] = "enabled", - [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime", - [UNIT_FILE_LINKED] = "linked", - [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime", - [UNIT_FILE_MASKED] = "masked", - [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime", - [UNIT_FILE_STATIC] = "static", - [UNIT_FILE_DISABLED] = "disabled", - [UNIT_FILE_INDIRECT] = "indirect", - [UNIT_FILE_INVALID] = "invalid", -}; - -DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState); - -static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = { - [UNIT_FILE_SYMLINK] = "symlink", - [UNIT_FILE_UNLINK] = "unlink", -}; - -DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType); - -static const char* const unit_file_preset_mode_table[_UNIT_FILE_PRESET_MAX] = { - [UNIT_FILE_PRESET_FULL] = "full", - [UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only", - [UNIT_FILE_PRESET_DISABLE_ONLY] = "disable-only", -}; - -DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode, UnitFilePresetMode); diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c deleted file mode 100644 index 068da465d..000000000 --- a/src/shared/logs-show.c +++ /dev/null @@ -1,1291 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2012 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 . -***/ - -#include -#include -#include -#include -#include - -#include "logs-show.h" -#include "log.h" -#include "util.h" -#include "utf8.h" -#include "hashmap.h" -#include "journal-internal.h" -#include "formats-util.h" -#include "process-util.h" -#include "terminal-util.h" - -/* up to three lines (each up to 100 characters), - or 300 characters, whichever is less */ -#define PRINT_LINE_THRESHOLD 3 -#define PRINT_CHAR_THRESHOLD 300 - -#define JSON_THRESHOLD 4096 - -static int print_catalog(FILE *f, sd_journal *j) { - int r; - _cleanup_free_ char *t = NULL, *z = NULL; - - - r = sd_journal_get_catalog(j, &t); - if (r < 0) - return r; - - z = strreplace(strstrip(t), "\n", "\n-- "); - if (!z) - return log_oom(); - - fputs("-- ", f); - fputs(z, f); - fputc('\n', f); - - return 0; -} - -static int parse_field(const void *data, size_t length, const char *field, char **target, size_t *target_size) { - size_t fl, nl; - void *buf; - - assert(data); - assert(field); - assert(target); - assert(target_size); - - fl = strlen(field); - if (length < fl) - return 0; - - if (memcmp(data, field, fl)) - return 0; - - nl = length - fl; - buf = malloc(nl+1); - if (!buf) - return log_oom(); - - memcpy(buf, (const char*) data + fl, nl); - ((char*)buf)[nl] = 0; - - free(*target); - *target = buf; - *target_size = nl; - - return 1; -} - -static bool shall_print(const char *p, size_t l, OutputFlags flags) { - assert(p); - - if (flags & OUTPUT_SHOW_ALL) - return true; - - if (l >= PRINT_CHAR_THRESHOLD) - return false; - - if (!utf8_is_printable(p, l)) - return false; - - return true; -} - -static bool print_multiline(FILE *f, unsigned prefix, unsigned n_columns, OutputFlags flags, int priority, const char* message, size_t message_len) { - const char *color_on = "", *color_off = ""; - const char *pos, *end; - bool ellipsized = false; - int line = 0; - - if (flags & OUTPUT_COLOR) { - if (priority <= LOG_ERR) { - color_on = ANSI_HIGHLIGHT_RED_ON; - color_off = ANSI_HIGHLIGHT_OFF; - } else if (priority <= LOG_NOTICE) { - color_on = ANSI_HIGHLIGHT_ON; - color_off = ANSI_HIGHLIGHT_OFF; - } - } - - /* A special case: make sure that we print a newline when - the message is empty. */ - if (message_len == 0) - fputs("\n", f); - - for (pos = message; - pos < message + message_len; - pos = end + 1, line++) { - bool continuation = line > 0; - bool tail_line; - int len; - for (end = pos; end < message + message_len && *end != '\n'; end++) - ; - len = end - pos; - assert(len >= 0); - - /* We need to figure out when we are showing not-last line, *and* - * will skip subsequent lines. In that case, we will put the dots - * at the end of the line, instead of putting dots in the middle - * or not at all. - */ - tail_line = - line + 1 == PRINT_LINE_THRESHOLD || - end + 1 >= message + PRINT_CHAR_THRESHOLD; - - if (flags & (OUTPUT_FULL_WIDTH | OUTPUT_SHOW_ALL) || - (prefix + len + 1 < n_columns && !tail_line)) { - fprintf(f, "%*s%s%.*s%s\n", - continuation * prefix, "", - color_on, len, pos, color_off); - continue; - } - - /* Beyond this point, ellipsization will happen. */ - ellipsized = true; - - if (prefix < n_columns && n_columns - prefix >= 3) { - if (n_columns - prefix > (unsigned) len + 3) - fprintf(f, "%*s%s%.*s...%s\n", - continuation * prefix, "", - color_on, len, pos, color_off); - else { - _cleanup_free_ char *e; - - e = ellipsize_mem(pos, len, n_columns - prefix, - tail_line ? 100 : 90); - if (!e) - fprintf(f, "%*s%s%.*s%s\n", - continuation * prefix, "", - color_on, len, pos, color_off); - else - fprintf(f, "%*s%s%s%s\n", - continuation * prefix, "", - color_on, e, color_off); - } - } else - fputs("...\n", f); - - if (tail_line) - break; - } - - return ellipsized; -} - -static int output_short( - FILE *f, - sd_journal *j, - OutputMode mode, - unsigned n_columns, - OutputFlags flags) { - - int r; - const void *data; - size_t length; - size_t n = 0; - _cleanup_free_ char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL, *priority = NULL; - size_t hostname_len = 0, identifier_len = 0, comm_len = 0, pid_len = 0, fake_pid_len = 0, message_len = 0, realtime_len = 0, monotonic_len = 0, priority_len = 0; - int p = LOG_INFO; - bool ellipsized = false; - - assert(f); - assert(j); - - /* Set the threshold to one bigger than the actual print - * threshold, so that if the line is actually longer than what - * we're willing to print, ellipsization will occur. This way - * we won't output a misleading line without any indication of - * truncation. - */ - sd_journal_set_data_threshold(j, flags & (OUTPUT_SHOW_ALL|OUTPUT_FULL_WIDTH) ? 0 : PRINT_CHAR_THRESHOLD + 1); - - JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) { - - r = parse_field(data, length, "PRIORITY=", &priority, &priority_len); - if (r < 0) - return r; - else if (r > 0) - continue; - - r = parse_field(data, length, "_HOSTNAME=", &hostname, &hostname_len); - if (r < 0) - return r; - else if (r > 0) - continue; - - r = parse_field(data, length, "SYSLOG_IDENTIFIER=", &identifier, &identifier_len); - if (r < 0) - return r; - else if (r > 0) - continue; - - r = parse_field(data, length, "_COMM=", &comm, &comm_len); - if (r < 0) - return r; - else if (r > 0) - continue; - - r = parse_field(data, length, "_PID=", &pid, &pid_len); - if (r < 0) - return r; - else if (r > 0) - continue; - - r = parse_field(data, length, "SYSLOG_PID=", &fake_pid, &fake_pid_len); - if (r < 0) - return r; - else if (r > 0) - continue; - - r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &realtime, &realtime_len); - if (r < 0) - return r; - else if (r > 0) - continue; - - r = parse_field(data, length, "_SOURCE_MONOTONIC_TIMESTAMP=", &monotonic, &monotonic_len); - if (r < 0) - return r; - else if (r > 0) - continue; - - r = parse_field(data, length, "MESSAGE=", &message, &message_len); - if (r < 0) - return r; - } - - if (r < 0) - return log_error_errno(r, "Failed to get journal fields: %m"); - - if (!message) { - log_debug("Skipping message without MESSAGE= field."); - return 0; - } - - if (!(flags & OUTPUT_SHOW_ALL)) - strip_tab_ansi(&message, &message_len); - - if (priority_len == 1 && *priority >= '0' && *priority <= '7') - p = *priority - '0'; - - if (mode == OUTPUT_SHORT_MONOTONIC) { - uint64_t t; - sd_id128_t boot_id; - - r = -ENOENT; - - if (monotonic) - r = safe_atou64(monotonic, &t); - - if (r < 0) - r = sd_journal_get_monotonic_usec(j, &t, &boot_id); - - if (r < 0) - return log_error_errno(r, "Failed to get monotonic timestamp: %m"); - - fprintf(f, "[%5llu.%06llu]", - (unsigned long long) (t / USEC_PER_SEC), - (unsigned long long) (t % USEC_PER_SEC)); - - n += 1 + 5 + 1 + 6 + 1; - - } else { - char buf[64]; - uint64_t x; - time_t t; - struct tm tm; - struct tm *(*gettime_r)(const time_t *, struct tm *); - - r = -ENOENT; - gettime_r = (flags & OUTPUT_UTC) ? gmtime_r : localtime_r; - - if (realtime) - r = safe_atou64(realtime, &x); - - if (r < 0) - r = sd_journal_get_realtime_usec(j, &x); - - if (r < 0) - return log_error_errno(r, "Failed to get realtime timestamp: %m"); - - t = (time_t) (x / USEC_PER_SEC); - - switch(mode) { - case OUTPUT_SHORT_ISO: - r = strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S%z", gettime_r(&t, &tm)); - break; - case OUTPUT_SHORT_PRECISE: - r = strftime(buf, sizeof(buf), "%b %d %H:%M:%S", gettime_r(&t, &tm)); - if (r > 0) { - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), - ".%06llu", (unsigned long long) (x % USEC_PER_SEC)); - } - break; - default: - r = strftime(buf, sizeof(buf), "%b %d %H:%M:%S", gettime_r(&t, &tm)); - } - - if (r <= 0) { - log_error("Failed to format time."); - return -EINVAL; - } - - fputs(buf, f); - n += strlen(buf); - } - - if (hostname && shall_print(hostname, hostname_len, flags)) { - fprintf(f, " %.*s", (int) hostname_len, hostname); - n += hostname_len + 1; - } - - if (identifier && shall_print(identifier, identifier_len, flags)) { - fprintf(f, " %.*s", (int) identifier_len, identifier); - n += identifier_len + 1; - } else if (comm && shall_print(comm, comm_len, flags)) { - fprintf(f, " %.*s", (int) comm_len, comm); - n += comm_len + 1; - } else - fputs(" unknown", f); - - if (pid && shall_print(pid, pid_len, flags)) { - fprintf(f, "[%.*s]", (int) pid_len, pid); - n += pid_len + 2; - } else if (fake_pid && shall_print(fake_pid, fake_pid_len, flags)) { - fprintf(f, "[%.*s]", (int) fake_pid_len, fake_pid); - n += fake_pid_len + 2; - } - - if (!(flags & OUTPUT_SHOW_ALL) && !utf8_is_printable(message, message_len)) { - char bytes[FORMAT_BYTES_MAX]; - fprintf(f, ": [%s blob data]\n", format_bytes(bytes, sizeof(bytes), message_len)); - } else { - fputs(": ", f); - ellipsized |= - print_multiline(f, n + 2, n_columns, flags, p, message, message_len); - } - - if (flags & OUTPUT_CATALOG) - print_catalog(f, j); - - return ellipsized; -} - -static int output_verbose( - FILE *f, - sd_journal *j, - OutputMode mode, - unsigned n_columns, - OutputFlags flags) { - - const void *data; - size_t length; - _cleanup_free_ char *cursor = NULL; - uint64_t realtime; - char ts[FORMAT_TIMESTAMP_MAX + 7]; - int r; - - assert(f); - assert(j); - - sd_journal_set_data_threshold(j, 0); - - r = sd_journal_get_data(j, "_SOURCE_REALTIME_TIMESTAMP", &data, &length); - if (r == -ENOENT) - log_debug("Source realtime timestamp not found"); - else if (r < 0) - return log_full_errno(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR, r, "Failed to get source realtime timestamp: %m"); - else { - _cleanup_free_ char *value = NULL; - size_t size; - - r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &value, &size); - if (r < 0) - log_debug_errno(r, "_SOURCE_REALTIME_TIMESTAMP invalid: %m"); - else { - r = safe_atou64(value, &realtime); - if (r < 0) - log_debug_errno(r, "Failed to parse realtime timestamp: %m"); - } - } - - if (r < 0) { - r = sd_journal_get_realtime_usec(j, &realtime); - if (r < 0) - return log_full_errno(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR, r, "Failed to get realtime timestamp: %m"); - } - - r = sd_journal_get_cursor(j, &cursor); - if (r < 0) - return log_error_errno(r, "Failed to get cursor: %m"); - - fprintf(f, "%s [%s]\n", - flags & OUTPUT_UTC ? - format_timestamp_us_utc(ts, sizeof(ts), realtime) : - format_timestamp_us(ts, sizeof(ts), realtime), - cursor); - - JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) { - const char *c; - int fieldlen; - const char *on = "", *off = ""; - - c = memchr(data, '=', length); - if (!c) { - log_error("Invalid field."); - return -EINVAL; - } - fieldlen = c - (const char*) data; - - if (flags & OUTPUT_COLOR && startswith(data, "MESSAGE=")) { - on = ANSI_HIGHLIGHT_ON; - off = ANSI_HIGHLIGHT_OFF; - } - - if (flags & OUTPUT_SHOW_ALL || - (((length < PRINT_CHAR_THRESHOLD) || flags & OUTPUT_FULL_WIDTH) - && utf8_is_printable(data, length))) { - fprintf(f, " %s%.*s=", on, fieldlen, (const char*)data); - print_multiline(f, 4 + fieldlen + 1, 0, OUTPUT_FULL_WIDTH, 0, c + 1, length - fieldlen - 1); - fputs(off, f); - } else { - char bytes[FORMAT_BYTES_MAX]; - - fprintf(f, " %s%.*s=[%s blob data]%s\n", - on, - (int) (c - (const char*) data), - (const char*) data, - format_bytes(bytes, sizeof(bytes), length - (c - (const char *) data) - 1), - off); - } - } - - if (r < 0) - return r; - - if (flags & OUTPUT_CATALOG) - print_catalog(f, j); - - return 0; -} - -static int output_export( - FILE *f, - sd_journal *j, - OutputMode mode, - unsigned n_columns, - OutputFlags flags) { - - sd_id128_t boot_id; - char sid[33]; - int r; - usec_t realtime, monotonic; - _cleanup_free_ char *cursor = NULL; - const void *data; - size_t length; - - assert(j); - - sd_journal_set_data_threshold(j, 0); - - r = sd_journal_get_realtime_usec(j, &realtime); - if (r < 0) - return log_error_errno(r, "Failed to get realtime timestamp: %m"); - - r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id); - if (r < 0) - return log_error_errno(r, "Failed to get monotonic timestamp: %m"); - - r = sd_journal_get_cursor(j, &cursor); - if (r < 0) - return log_error_errno(r, "Failed to get cursor: %m"); - - fprintf(f, - "__CURSOR=%s\n" - "__REALTIME_TIMESTAMP="USEC_FMT"\n" - "__MONOTONIC_TIMESTAMP="USEC_FMT"\n" - "_BOOT_ID=%s\n", - cursor, - realtime, - monotonic, - sd_id128_to_string(boot_id, sid)); - - JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) { - - /* We already printed the boot id, from the data in - * the header, hence let's suppress it here */ - if (length >= 9 && - startswith(data, "_BOOT_ID=")) - continue; - - if (utf8_is_printable_newline(data, length, false)) - fwrite(data, length, 1, f); - else { - const char *c; - uint64_t le64; - - c = memchr(data, '=', length); - if (!c) { - log_error("Invalid field."); - return -EINVAL; - } - - fwrite(data, c - (const char*) data, 1, f); - fputc('\n', f); - le64 = htole64(length - (c - (const char*) data) - 1); - fwrite(&le64, sizeof(le64), 1, f); - fwrite(c + 1, length - (c - (const char*) data) - 1, 1, f); - } - - fputc('\n', f); - } - - if (r < 0) - return r; - - fputc('\n', f); - - return 0; -} - -void json_escape( - FILE *f, - const char* p, - size_t l, - OutputFlags flags) { - - assert(f); - assert(p); - - if (!(flags & OUTPUT_SHOW_ALL) && l >= JSON_THRESHOLD) - - fputs("null", f); - - else if (!utf8_is_printable(p, l)) { - bool not_first = false; - - fputs("[ ", f); - - while (l > 0) { - if (not_first) - fprintf(f, ", %u", (uint8_t) *p); - else { - not_first = true; - fprintf(f, "%u", (uint8_t) *p); - } - - p++; - l--; - } - - fputs(" ]", f); - } else { - fputc('\"', f); - - while (l > 0) { - if (*p == '"' || *p == '\\') { - fputc('\\', f); - fputc(*p, f); - } else if (*p == '\n') - fputs("\\n", f); - else if (*p < ' ') - fprintf(f, "\\u%04x", *p); - else - fputc(*p, f); - - p++; - l--; - } - - fputc('\"', f); - } -} - -static int output_json( - FILE *f, - sd_journal *j, - OutputMode mode, - unsigned n_columns, - OutputFlags flags) { - - uint64_t realtime, monotonic; - _cleanup_free_ char *cursor = NULL; - const void *data; - size_t length; - sd_id128_t boot_id; - char sid[33], *k; - int r; - Hashmap *h = NULL; - bool done, separator; - - assert(j); - - sd_journal_set_data_threshold(j, flags & OUTPUT_SHOW_ALL ? 0 : JSON_THRESHOLD); - - r = sd_journal_get_realtime_usec(j, &realtime); - if (r < 0) - return log_error_errno(r, "Failed to get realtime timestamp: %m"); - - r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id); - if (r < 0) - return log_error_errno(r, "Failed to get monotonic timestamp: %m"); - - r = sd_journal_get_cursor(j, &cursor); - if (r < 0) - return log_error_errno(r, "Failed to get cursor: %m"); - - if (mode == OUTPUT_JSON_PRETTY) - fprintf(f, - "{\n" - "\t\"__CURSOR\" : \"%s\",\n" - "\t\"__REALTIME_TIMESTAMP\" : \""USEC_FMT"\",\n" - "\t\"__MONOTONIC_TIMESTAMP\" : \""USEC_FMT"\",\n" - "\t\"_BOOT_ID\" : \"%s\"", - cursor, - realtime, - monotonic, - sd_id128_to_string(boot_id, sid)); - else { - if (mode == OUTPUT_JSON_SSE) - fputs("data: ", f); - - fprintf(f, - "{ \"__CURSOR\" : \"%s\", " - "\"__REALTIME_TIMESTAMP\" : \""USEC_FMT"\", " - "\"__MONOTONIC_TIMESTAMP\" : \""USEC_FMT"\", " - "\"_BOOT_ID\" : \"%s\"", - cursor, - realtime, - monotonic, - sd_id128_to_string(boot_id, sid)); - } - - h = hashmap_new(&string_hash_ops); - if (!h) - return log_oom(); - - /* First round, iterate through the entry and count how often each field appears */ - JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) { - const char *eq; - char *n; - unsigned u; - - if (length >= 9 && - memcmp(data, "_BOOT_ID=", 9) == 0) - continue; - - eq = memchr(data, '=', length); - if (!eq) - continue; - - n = strndup(data, eq - (const char*) data); - if (!n) { - r = log_oom(); - goto finish; - } - - u = PTR_TO_UINT(hashmap_get(h, n)); - if (u == 0) { - r = hashmap_put(h, n, UINT_TO_PTR(1)); - if (r < 0) { - free(n); - log_oom(); - goto finish; - } - } else { - r = hashmap_update(h, n, UINT_TO_PTR(u + 1)); - free(n); - if (r < 0) { - log_oom(); - goto finish; - } - } - } - - if (r < 0) - return r; - - separator = true; - do { - done = true; - - SD_JOURNAL_FOREACH_DATA(j, data, length) { - const char *eq; - char *kk, *n; - size_t m; - unsigned u; - - /* We already printed the boot id, from the data in - * the header, hence let's suppress it here */ - if (length >= 9 && - memcmp(data, "_BOOT_ID=", 9) == 0) - continue; - - eq = memchr(data, '=', length); - if (!eq) - continue; - - if (separator) { - if (mode == OUTPUT_JSON_PRETTY) - fputs(",\n\t", f); - else - fputs(", ", f); - } - - m = eq - (const char*) data; - - n = strndup(data, m); - if (!n) { - r = log_oom(); - goto finish; - } - - u = PTR_TO_UINT(hashmap_get2(h, n, (void**) &kk)); - if (u == 0) { - /* We already printed this, let's jump to the next */ - free(n); - separator = false; - - continue; - } else if (u == 1) { - /* Field only appears once, output it directly */ - - json_escape(f, data, m, flags); - fputs(" : ", f); - - json_escape(f, eq + 1, length - m - 1, flags); - - hashmap_remove(h, n); - free(kk); - free(n); - - separator = true; - - continue; - - } else { - /* Field appears multiple times, output it as array */ - json_escape(f, data, m, flags); - fputs(" : [ ", f); - json_escape(f, eq + 1, length - m - 1, flags); - - /* Iterate through the end of the list */ - - while (sd_journal_enumerate_data(j, &data, &length) > 0) { - if (length < m + 1) - continue; - - if (memcmp(data, n, m) != 0) - continue; - - if (((const char*) data)[m] != '=') - continue; - - fputs(", ", f); - json_escape(f, (const char*) data + m + 1, length - m - 1, flags); - } - - fputs(" ]", f); - - hashmap_remove(h, n); - free(kk); - free(n); - - /* Iterate data fields form the beginning */ - done = false; - separator = true; - - break; - } - } - - } while (!done); - - if (mode == OUTPUT_JSON_PRETTY) - fputs("\n}\n", f); - else if (mode == OUTPUT_JSON_SSE) - fputs("}\n\n", f); - else - fputs(" }\n", f); - - r = 0; - -finish: - while ((k = hashmap_steal_first_key(h))) - free(k); - - hashmap_free(h); - - return r; -} - -static int output_cat( - FILE *f, - sd_journal *j, - OutputMode mode, - unsigned n_columns, - OutputFlags flags) { - - const void *data; - size_t l; - int r; - - assert(j); - assert(f); - - sd_journal_set_data_threshold(j, 0); - - r = sd_journal_get_data(j, "MESSAGE", &data, &l); - if (r < 0) { - /* An entry without MESSAGE=? */ - if (r == -ENOENT) - return 0; - - return log_error_errno(r, "Failed to get data: %m"); - } - - assert(l >= 8); - - fwrite((const char*) data + 8, 1, l - 8, f); - fputc('\n', f); - - return 0; -} - -static int (*output_funcs[_OUTPUT_MODE_MAX])( - FILE *f, - sd_journal*j, - OutputMode mode, - unsigned n_columns, - OutputFlags flags) = { - - [OUTPUT_SHORT] = output_short, - [OUTPUT_SHORT_ISO] = output_short, - [OUTPUT_SHORT_PRECISE] = output_short, - [OUTPUT_SHORT_MONOTONIC] = output_short, - [OUTPUT_VERBOSE] = output_verbose, - [OUTPUT_EXPORT] = output_export, - [OUTPUT_JSON] = output_json, - [OUTPUT_JSON_PRETTY] = output_json, - [OUTPUT_JSON_SSE] = output_json, - [OUTPUT_CAT] = output_cat -}; - -int output_journal( - FILE *f, - sd_journal *j, - OutputMode mode, - unsigned n_columns, - OutputFlags flags, - bool *ellipsized) { - - int ret; - assert(mode >= 0); - assert(mode < _OUTPUT_MODE_MAX); - - if (n_columns <= 0) - n_columns = columns(); - - ret = output_funcs[mode](f, j, mode, n_columns, flags); - fflush(stdout); - - if (ellipsized && ret > 0) - *ellipsized = true; - - return ret; -} - -static int maybe_print_begin_newline(FILE *f, OutputFlags *flags) { - assert(f); - assert(flags); - - if (!(*flags & OUTPUT_BEGIN_NEWLINE)) - return 0; - - /* Print a beginning new line if that's request, but only once - * on the first line we print. */ - - fputc('\n', f); - *flags &= ~OUTPUT_BEGIN_NEWLINE; - return 0; -} - -static int show_journal(FILE *f, - sd_journal *j, - OutputMode mode, - unsigned n_columns, - usec_t not_before, - unsigned how_many, - OutputFlags flags, - bool *ellipsized) { - - int r; - unsigned line = 0; - bool need_seek = false; - int warn_cutoff = flags & OUTPUT_WARN_CUTOFF; - - assert(j); - assert(mode >= 0); - assert(mode < _OUTPUT_MODE_MAX); - - /* Seek to end */ - r = sd_journal_seek_tail(j); - if (r < 0) - return log_error_errno(r, "Failed to seek to tail: %m"); - - r = sd_journal_previous_skip(j, how_many); - if (r < 0) - return log_error_errno(r, "Failed to skip previous: %m"); - - for (;;) { - for (;;) { - usec_t usec; - - if (need_seek) { - r = sd_journal_next(j); - if (r < 0) - return log_error_errno(r, "Failed to iterate through journal: %m"); - } - - if (r == 0) - break; - - need_seek = true; - - if (not_before > 0) { - r = sd_journal_get_monotonic_usec(j, &usec, NULL); - - /* -ESTALE is returned if the - timestamp is not from this boot */ - if (r == -ESTALE) - continue; - else if (r < 0) - return log_error_errno(r, "Failed to get journal time: %m"); - - if (usec < not_before) - continue; - } - - line ++; - maybe_print_begin_newline(f, &flags); - - r = output_journal(f, j, mode, n_columns, flags, ellipsized); - if (r < 0) - return r; - } - - if (warn_cutoff && line < how_many && not_before > 0) { - sd_id128_t boot_id; - usec_t cutoff = 0; - - /* Check whether the cutoff line is too early */ - - r = sd_id128_get_boot(&boot_id); - if (r < 0) - return log_error_errno(r, "Failed to get boot id: %m"); - - r = sd_journal_get_cutoff_monotonic_usec(j, boot_id, &cutoff, NULL); - if (r < 0) - return log_error_errno(r, "Failed to get journal cutoff time: %m"); - - if (r > 0 && not_before < cutoff) { - maybe_print_begin_newline(f, &flags); - fprintf(f, "Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.\n"); - } - - warn_cutoff = false; - } - - if (!(flags & OUTPUT_FOLLOW)) - break; - - r = sd_journal_wait(j, USEC_INFINITY); - if (r < 0) - return log_error_errno(r, "Failed to wait for journal: %m"); - - } - - return 0; -} - -int add_matches_for_unit(sd_journal *j, const char *unit) { - int r; - char *m1, *m2, *m3, *m4; - - assert(j); - assert(unit); - - m1 = strjoina("_SYSTEMD_UNIT=", unit); - m2 = strjoina("COREDUMP_UNIT=", unit); - m3 = strjoina("UNIT=", unit); - m4 = strjoina("OBJECT_SYSTEMD_UNIT=", unit); - - (void)( - /* Look for messages from the service itself */ - (r = sd_journal_add_match(j, m1, 0)) || - - /* Look for coredumps of the service */ - (r = sd_journal_add_disjunction(j)) || - (r = sd_journal_add_match(j, "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1", 0)) || - (r = sd_journal_add_match(j, "_UID=0", 0)) || - (r = sd_journal_add_match(j, m2, 0)) || - - /* Look for messages from PID 1 about this service */ - (r = sd_journal_add_disjunction(j)) || - (r = sd_journal_add_match(j, "_PID=1", 0)) || - (r = sd_journal_add_match(j, m3, 0)) || - - /* Look for messages from authorized daemons about this service */ - (r = sd_journal_add_disjunction(j)) || - (r = sd_journal_add_match(j, "_UID=0", 0)) || - (r = sd_journal_add_match(j, m4, 0)) - ); - - if (r == 0 && endswith(unit, ".slice")) { - char *m5 = strappend("_SYSTEMD_SLICE=", unit); - - /* Show all messages belonging to a slice */ - (void)( - (r = sd_journal_add_disjunction(j)) || - (r = sd_journal_add_match(j, m5, 0)) - ); - } - - return r; -} - -int add_matches_for_user_unit(sd_journal *j, const char *unit, uid_t uid) { - int r; - char *m1, *m2, *m3, *m4; - char muid[sizeof("_UID=") + DECIMAL_STR_MAX(uid_t)]; - - assert(j); - assert(unit); - - m1 = strjoina("_SYSTEMD_USER_UNIT=", unit); - m2 = strjoina("USER_UNIT=", unit); - m3 = strjoina("COREDUMP_USER_UNIT=", unit); - m4 = strjoina("OBJECT_SYSTEMD_USER_UNIT=", unit); - sprintf(muid, "_UID="UID_FMT, uid); - - (void) ( - /* Look for messages from the user service itself */ - (r = sd_journal_add_match(j, m1, 0)) || - (r = sd_journal_add_match(j, muid, 0)) || - - /* Look for messages from systemd about this service */ - (r = sd_journal_add_disjunction(j)) || - (r = sd_journal_add_match(j, m2, 0)) || - (r = sd_journal_add_match(j, muid, 0)) || - - /* Look for coredumps of the service */ - (r = sd_journal_add_disjunction(j)) || - (r = sd_journal_add_match(j, m3, 0)) || - (r = sd_journal_add_match(j, muid, 0)) || - (r = sd_journal_add_match(j, "_UID=0", 0)) || - - /* Look for messages from authorized daemons about this service */ - (r = sd_journal_add_disjunction(j)) || - (r = sd_journal_add_match(j, m4, 0)) || - (r = sd_journal_add_match(j, muid, 0)) || - (r = sd_journal_add_match(j, "_UID=0", 0)) - ); - - if (r == 0 && endswith(unit, ".slice")) { - char *m5 = strappend("_SYSTEMD_SLICE=", unit); - - /* Show all messages belonging to a slice */ - (void)( - (r = sd_journal_add_disjunction(j)) || - (r = sd_journal_add_match(j, m5, 0)) || - (r = sd_journal_add_match(j, muid, 0)) - ); - } - - return r; -} - -static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) { - _cleanup_close_pair_ int pair[2] = { -1, -1 }; - _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1; - pid_t pid, child; - siginfo_t si; - char buf[37]; - ssize_t k; - int r; - - assert(machine); - assert(boot_id); - - if (!machine_name_is_valid(machine)) - return -EINVAL; - - r = container_get_leader(machine, &pid); - if (r < 0) - return r; - - r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &rootfd); - if (r < 0) - return r; - - if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0) - return -errno; - - child = fork(); - if (child < 0) - return -errno; - - if (child == 0) { - int fd; - - pair[0] = safe_close(pair[0]); - - r = namespace_enter(pidnsfd, mntnsfd, -1, rootfd); - if (r < 0) - _exit(EXIT_FAILURE); - - fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY); - if (fd < 0) - _exit(EXIT_FAILURE); - - r = loop_read_exact(fd, buf, 36, false); - safe_close(fd); - if (r < 0) - _exit(EXIT_FAILURE); - - k = send(pair[1], buf, 36, MSG_NOSIGNAL); - if (k != 36) - _exit(EXIT_FAILURE); - - _exit(EXIT_SUCCESS); - } - - pair[1] = safe_close(pair[1]); - - r = wait_for_terminate(child, &si); - if (r < 0 || si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS) - return r < 0 ? r : -EIO; - - k = recv(pair[0], buf, 36, 0); - if (k != 36) - return -EIO; - - buf[36] = 0; - r = sd_id128_from_string(buf, boot_id); - if (r < 0) - return r; - - return 0; -} - -int add_match_this_boot(sd_journal *j, const char *machine) { - char match[9+32+1] = "_BOOT_ID="; - sd_id128_t boot_id; - int r; - - assert(j); - - if (machine) { - r = get_boot_id_for_machine(machine, &boot_id); - if (r < 0) - return log_error_errno(r, "Failed to get boot id of container %s: %m", machine); - } else { - r = sd_id128_get_boot(&boot_id); - if (r < 0) - return log_error_errno(r, "Failed to get boot id: %m"); - } - - sd_id128_to_string(boot_id, match + 9); - r = sd_journal_add_match(j, match, strlen(match)); - if (r < 0) - return log_error_errno(r, "Failed to add match: %m"); - - r = sd_journal_add_conjunction(j); - if (r < 0) - return log_error_errno(r, "Failed to add conjunction: %m"); - - return 0; -} - -int show_journal_by_unit( - FILE *f, - const char *unit, - OutputMode mode, - unsigned n_columns, - usec_t not_before, - unsigned how_many, - uid_t uid, - OutputFlags flags, - int journal_open_flags, - bool system_unit, - bool *ellipsized) { - - _cleanup_journal_close_ sd_journal*j = NULL; - int r; - - assert(mode >= 0); - assert(mode < _OUTPUT_MODE_MAX); - assert(unit); - - if (how_many <= 0) - return 0; - - r = sd_journal_open(&j, journal_open_flags); - if (r < 0) - return log_error_errno(r, "Failed to open journal: %m"); - - r = add_match_this_boot(j, NULL); - if (r < 0) - return r; - - if (system_unit) - r = add_matches_for_unit(j, unit); - else - r = add_matches_for_user_unit(j, unit, uid); - if (r < 0) - return log_error_errno(r, "Failed to add unit matches: %m"); - - if (_unlikely_(log_get_max_level() >= LOG_DEBUG)) { - _cleanup_free_ char *filter; - - filter = journal_make_match_string(j); - if (!filter) - return log_oom(); - - log_debug("Journal filter: %s", filter); - } - - return show_journal(f, j, mode, n_columns, not_before, how_many, flags, ellipsized); -} - -static const char *const output_mode_table[_OUTPUT_MODE_MAX] = { - [OUTPUT_SHORT] = "short", - [OUTPUT_SHORT_ISO] = "short-iso", - [OUTPUT_SHORT_PRECISE] = "short-precise", - [OUTPUT_SHORT_MONOTONIC] = "short-monotonic", - [OUTPUT_VERBOSE] = "verbose", - [OUTPUT_EXPORT] = "export", - [OUTPUT_JSON] = "json", - [OUTPUT_JSON_PRETTY] = "json-pretty", - [OUTPUT_JSON_SSE] = "json-sse", - [OUTPUT_CAT] = "cat" -}; - -DEFINE_STRING_TABLE_LOOKUP(output_mode, OutputMode); diff --git a/src/shared/machine-pool.c b/src/shared/machine-pool.c deleted file mode 100644 index 8af78f47d..000000000 --- a/src/shared/machine-pool.c +++ /dev/null @@ -1,379 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2015 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 . -***/ - -#include -#include -#include -#include - -#include "util.h" -#include "process-util.h" -#include "lockfile-util.h" -#include "mkdir.h" -#include "btrfs-util.h" -#include "path-util.h" -#include "signal-util.h" -#include "machine-pool.h" - -#define VAR_LIB_MACHINES_SIZE_START (1024UL*1024UL*500UL) -#define VAR_LIB_MACHINES_FREE_MIN (1024UL*1024UL*750UL) - -static int check_btrfs(void) { - struct statfs sfs; - - if (statfs("/var/lib/machines", &sfs) < 0) { - if (errno != ENOENT) - return -errno; - - if (statfs("/var/lib", &sfs) < 0) - return -errno; - } - - return F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC); -} - -static int setup_machine_raw(uint64_t size, sd_bus_error *error) { - _cleanup_free_ char *tmp = NULL; - _cleanup_close_ int fd = -1; - struct statvfs ss; - pid_t pid = 0; - siginfo_t si; - int r; - - /* We want to be able to make use of btrfs-specific file - * system features, in particular subvolumes, reflinks and - * quota. Hence, if we detect that /var/lib/machines.raw is - * not located on btrfs, let's create a loopback file, place a - * btrfs file system into it, and mount it to - * /var/lib/machines. */ - - fd = open("/var/lib/machines.raw", O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); - if (fd >= 0) { - r = fd; - fd = -1; - return r; - } - - if (errno != ENOENT) - return sd_bus_error_set_errnof(error, errno, "Failed to open /var/lib/machines.raw: %m"); - - r = tempfn_xxxxxx("/var/lib/machines.raw", NULL, &tmp); - if (r < 0) - return r; - - (void) mkdir_p_label("/var/lib", 0755); - fd = open(tmp, O_RDWR|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0600); - if (fd < 0) - return sd_bus_error_set_errnof(error, errno, "Failed to create /var/lib/machines.raw: %m"); - - if (fstatvfs(fd, &ss) < 0) { - r = sd_bus_error_set_errnof(error, errno, "Failed to determine free space on /var/lib/machines.raw: %m"); - goto fail; - } - - if (ss.f_bsize * ss.f_bavail < VAR_LIB_MACHINES_FREE_MIN) { - r = sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Not enough free disk space to set up /var/lib/machines."); - goto fail; - } - - if (ftruncate(fd, size) < 0) { - r = sd_bus_error_set_errnof(error, errno, "Failed to enlarge /var/lib/machines.raw: %m"); - goto fail; - } - - pid = fork(); - if (pid < 0) { - r = sd_bus_error_set_errnof(error, errno, "Failed to fork mkfs.btrfs: %m"); - goto fail; - } - - if (pid == 0) { - - /* Child */ - - (void) reset_all_signal_handlers(); - (void) reset_signal_mask(); - assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); - - fd = safe_close(fd); - - execlp("mkfs.btrfs", "-Lvar-lib-machines", tmp, NULL); - if (errno == ENOENT) - return 99; - - _exit(EXIT_FAILURE); - } - - r = wait_for_terminate(pid, &si); - if (r < 0) { - sd_bus_error_set_errnof(error, r, "Failed to wait for mkfs.btrfs: %m"); - goto fail; - } - - pid = 0; - - if (si.si_code != CLD_EXITED) { - r = sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "mkfs.btrfs died abnormally."); - goto fail; - } - if (si.si_status == 99) { - r = sd_bus_error_set_errnof(error, ENOENT, "Cannot set up /var/lib/machines, mkfs.btrfs is missing"); - goto fail; - } - if (si.si_status != 0) { - r = sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "mkfs.btrfs failed with error code %i", si.si_status); - goto fail; - } - - r = rename_noreplace(AT_FDCWD, tmp, AT_FDCWD, "/var/lib/machines.raw"); - if (r < 0) { - sd_bus_error_set_errnof(error, r, "Failed to move /var/lib/machines.raw into place: %m"); - goto fail; - } - - r = fd; - fd = -1; - - return r; - -fail: - unlink_noerrno(tmp); - - if (pid > 1) - kill_and_sigcont(pid, SIGKILL); - - return r; -} - -int setup_machine_directory(uint64_t size, sd_bus_error *error) { - _cleanup_release_lock_file_ LockFile lock_file = LOCK_FILE_INIT; - struct loop_info64 info = { - .lo_flags = LO_FLAGS_AUTOCLEAR, - }; - _cleanup_close_ int fd = -1, control = -1, loop = -1; - _cleanup_free_ char* loopdev = NULL; - char tmpdir[] = "/tmp/import-mount.XXXXXX", *mntdir = NULL; - bool tmpdir_made = false, mntdir_made = false, mntdir_mounted = false; - char buf[FORMAT_BYTES_MAX]; - int r, nr = -1; - - /* btrfs cannot handle file systems < 16M, hence use this as minimum */ - if (size == (uint64_t) -1) - size = VAR_LIB_MACHINES_SIZE_START; - else if (size < 16*1024*1024) - size = 16*1024*1024; - - /* Make sure we only set the directory up once at a time */ - r = make_lock_file("/run/systemd/machines.lock", LOCK_EX, &lock_file); - if (r < 0) - return r; - - r = check_btrfs(); - if (r < 0) - return sd_bus_error_set_errnof(error, r, "Failed to determine whether /var/lib/machines is located on btrfs: %m"); - if (r > 0) { - (void) btrfs_subvol_make_label("/var/lib/machines"); - - r = btrfs_quota_enable("/var/lib/machines", true); - if (r < 0) - log_warning_errno(r, "Failed to enable quota, ignoring: %m"); - - return 0; - } - - if (path_is_mount_point("/var/lib/machines", AT_SYMLINK_FOLLOW) > 0 || - dir_is_empty("/var/lib/machines") == 0) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "/var/lib/machines is not a btrfs file system. Operation is not supported on legacy file systems."); - - fd = setup_machine_raw(size, error); - if (fd < 0) - return fd; - - control = open("/dev/loop-control", O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK); - if (control < 0) - return sd_bus_error_set_errnof(error, errno, "Failed to open /dev/loop-control: %m"); - - nr = ioctl(control, LOOP_CTL_GET_FREE); - if (nr < 0) - return sd_bus_error_set_errnof(error, errno, "Failed to allocate loop device: %m"); - - if (asprintf(&loopdev, "/dev/loop%i", nr) < 0) { - r = -ENOMEM; - goto fail; - } - - loop = open(loopdev, O_CLOEXEC|O_RDWR|O_NOCTTY|O_NONBLOCK); - if (loop < 0) { - r = sd_bus_error_set_errnof(error, errno, "Failed to open loopback device: %m"); - goto fail; - } - - if (ioctl(loop, LOOP_SET_FD, fd) < 0) { - r = sd_bus_error_set_errnof(error, errno, "Failed to bind loopback device: %m"); - goto fail; - } - - if (ioctl(loop, LOOP_SET_STATUS64, &info) < 0) { - r = sd_bus_error_set_errnof(error, errno, "Failed to enable auto-clear for loopback device: %m"); - goto fail; - } - - /* We need to make sure the new /var/lib/machines directory - * has an access mode of 0700 at the time it is first made - * available. mkfs will create it with 0755 however. Hence, - * let's mount the directory into an inaccessible directory - * below /tmp first, fix the access mode, and move it to the - * public place then. */ - - if (!mkdtemp(tmpdir)) { - r = sd_bus_error_set_errnof(error, errno, "Failed to create temporary mount parent directory: %m"); - goto fail; - } - tmpdir_made = true; - - mntdir = strjoina(tmpdir, "/mnt"); - if (mkdir(mntdir, 0700) < 0) { - r = sd_bus_error_set_errnof(error, errno, "Failed to create temporary mount directory: %m"); - goto fail; - } - mntdir_made = true; - - if (mount(loopdev, mntdir, "btrfs", 0, NULL) < 0) { - r = sd_bus_error_set_errnof(error, errno, "Failed to mount loopback device: %m"); - goto fail; - } - mntdir_mounted = true; - - r = btrfs_quota_enable(mntdir, true); - if (r < 0) - log_warning_errno(r, "Failed to enable quota, ignoring: %m"); - - if (chmod(mntdir, 0700) < 0) { - r = sd_bus_error_set_errnof(error, errno, "Failed to fix owner: %m"); - goto fail; - } - - (void) mkdir_p_label("/var/lib/machines", 0700); - - if (mount(mntdir, "/var/lib/machines", NULL, MS_BIND, NULL) < 0) { - r = sd_bus_error_set_errnof(error, errno, "Failed to mount directory into right place: %m"); - goto fail; - } - - (void) syncfs(fd); - - log_info("Set up /var/lib/machines as btrfs loopback file system of size %s mounted on /var/lib/machines.raw.", format_bytes(buf, sizeof(buf), size)); - - (void) umount2(mntdir, MNT_DETACH); - (void) rmdir(mntdir); - (void) rmdir(tmpdir); - - return 0; - -fail: - if (mntdir_mounted) - (void) umount2(mntdir, MNT_DETACH); - - if (mntdir_made) - (void) rmdir(mntdir); - if (tmpdir_made) - (void) rmdir(tmpdir); - - if (loop >= 0) { - (void) ioctl(loop, LOOP_CLR_FD); - loop = safe_close(loop); - } - - if (control >= 0 && nr >= 0) - (void) ioctl(control, LOOP_CTL_REMOVE, nr); - - return r; -} - -static int sync_path(const char *p) { - _cleanup_close_ int fd = -1; - - fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY); - if (fd < 0) - return -errno; - - if (syncfs(fd) < 0) - return -errno; - - return 0; -} - -int grow_machine_directory(void) { - char buf[FORMAT_BYTES_MAX]; - struct statvfs a, b; - uint64_t old_size, new_size, max_add; - int r; - - /* Ensure the disk space data is accurate */ - sync_path("/var/lib/machines"); - sync_path("/var/lib/machines.raw"); - - if (statvfs("/var/lib/machines.raw", &a) < 0) - return -errno; - - if (statvfs("/var/lib/machines", &b) < 0) - return -errno; - - /* Don't grow if not enough disk space is available on the host */ - if (((uint64_t) a.f_bavail * (uint64_t) a.f_bsize) <= VAR_LIB_MACHINES_FREE_MIN) - return 0; - - /* Don't grow if at least 1/3th of the fs is still free */ - if (b.f_bavail > b.f_blocks / 3) - return 0; - - /* Calculate how much we are willing to add at maximum */ - max_add = ((uint64_t) a.f_bavail * (uint64_t) a.f_bsize) - VAR_LIB_MACHINES_FREE_MIN; - - /* Calculate the old size */ - old_size = (uint64_t) b.f_blocks * (uint64_t) b.f_bsize; - - /* Calculate the new size as three times the size of what is used right now */ - new_size = ((uint64_t) b.f_blocks - (uint64_t) b.f_bavail) * (uint64_t) b.f_bsize * 3; - - /* Always, grow at least to the start size */ - if (new_size < VAR_LIB_MACHINES_SIZE_START) - new_size = VAR_LIB_MACHINES_SIZE_START; - - /* If the new size is smaller than the old size, don't grow */ - if (new_size < old_size) - return 0; - - /* Ensure we never add more than the maximum */ - if (new_size > old_size + max_add) - new_size = old_size + max_add; - - r = btrfs_resize_loopback("/var/lib/machines", new_size, true); - if (r <= 0) - return r; - - r = btrfs_quota_limit("/var/lib/machines", new_size); - if (r < 0) - return r; - - log_info("Grew /var/lib/machines btrfs loopback file system to %s.", format_bytes(buf, sizeof(buf), new_size)); - return 1; -} diff --git a/src/shared/nss-util.h b/src/shared/nss-util.h deleted file mode 100644 index 3657aa5d9..000000000 --- a/src/shared/nss-util.h +++ /dev/null @@ -1,157 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -#pragma once - -/*** - 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 . -***/ - -#include -#include -#include -#include -#include - - -#define NSS_GETHOSTBYNAME_PROTOTYPES(module) \ -enum nss_status _nss_##module##_gethostbyname4_r( \ - const char *name, \ - struct gaih_addrtuple **pat, \ - char *buffer, size_t buflen, \ - int *errnop, int *h_errnop, \ - int32_t *ttlp) _public_; \ -enum nss_status _nss_##module##_gethostbyname3_r( \ - const char *name, \ - int af, \ - struct hostent *host, \ - char *buffer, size_t buflen, \ - int *errnop, int *h_errnop, \ - int32_t *ttlp, \ - char **canonp) _public_; \ -enum nss_status _nss_##module##_gethostbyname2_r( \ - const char *name, \ - int af, \ - struct hostent *host, \ - char *buffer, size_t buflen, \ - int *errnop, int *h_errnop) _public_; \ -enum nss_status _nss_##module##_gethostbyname_r( \ - const char *name, \ - struct hostent *host, \ - char *buffer, size_t buflen, \ - int *errnop, int *h_errnop) _public_ - -#define NSS_GETHOSTBYADDR_PROTOTYPES(module) \ -enum nss_status _nss_##module##_gethostbyaddr2_r( \ - const void* addr, socklen_t len, \ - int af, \ - struct hostent *host, \ - char *buffer, size_t buflen, \ - int *errnop, int *h_errnop, \ - int32_t *ttlp) _public_; \ -enum nss_status _nss_##module##_gethostbyaddr_r( \ - const void* addr, socklen_t len, \ - int af, \ - struct hostent *host, \ - char *buffer, size_t buflen, \ - int *errnop, int *h_errnop) _public_ - -#define NSS_GETHOSTBYNAME_FALLBACKS(module) \ -enum nss_status _nss_##module##_gethostbyname2_r( \ - const char *name, \ - int af, \ - struct hostent *host, \ - char *buffer, size_t buflen, \ - int *errnop, int *h_errnop) { \ - return _nss_##module##_gethostbyname3_r( \ - name, \ - af, \ - host, \ - buffer, buflen, \ - errnop, h_errnop, \ - NULL, \ - NULL); \ -} \ -enum nss_status _nss_##module##_gethostbyname_r( \ - const char *name, \ - struct hostent *host, \ - char *buffer, size_t buflen, \ - int *errnop, int *h_errnop) { \ - enum nss_status ret = NSS_STATUS_NOTFOUND; \ - \ - if (_res.options & RES_USE_INET6) \ - ret = _nss_##module##_gethostbyname3_r( \ - name, \ - AF_INET6, \ - host, \ - buffer, buflen, \ - errnop, h_errnop, \ - NULL, \ - NULL); \ - if (ret == NSS_STATUS_NOTFOUND) \ - ret = _nss_##module##_gethostbyname3_r( \ - name, \ - AF_INET, \ - host, \ - buffer, buflen, \ - errnop, h_errnop, \ - NULL, \ - NULL); \ - return ret; \ -} \ -struct __useless_struct_to_allow_trailing_semicolon__ - -#define NSS_GETHOSTBYADDR_FALLBACKS(module) \ -enum nss_status _nss_##module##_gethostbyaddr_r( \ - const void* addr, socklen_t len, \ - int af, \ - struct hostent *host, \ - char *buffer, size_t buflen, \ - int *errnop, int *h_errnop) { \ - return _nss_##module##_gethostbyaddr2_r( \ - addr, len, \ - af, \ - host, \ - buffer, buflen, \ - errnop, h_errnop, \ - NULL); \ -} \ -struct __useless_struct_to_allow_trailing_semicolon__ - -#define NSS_GETPW_PROTOTYPES(module) \ -enum nss_status _nss_##module##_getpwnam_r( \ - const char *name, \ - struct passwd *pwd, \ - char *buffer, size_t buflen, \ - int *errnop) _public_; \ -enum nss_status _nss_mymachines_getpwuid_r( \ - uid_t uid, \ - struct passwd *pwd, \ - char *buffer, size_t buflen, \ - int *errnop) _public_ - -#define NSS_GETGR_PROTOTYPES(module) \ -enum nss_status _nss_##module##_getgrnam_r( \ - const char *name, \ - struct group *gr, \ - char *buffer, size_t buflen, \ - int *errnop) _public_; \ -enum nss_status _nss_##module##_getgrgid_r( \ - gid_t gid, \ - struct group *gr, \ - char *buffer, size_t buflen, \ - int *errnop) _public_ diff --git a/src/shared/socket-label.c b/src/shared/socket-label.c deleted file mode 100644 index 144e6fd86..000000000 --- a/src/shared/socket-label.c +++ /dev/null @@ -1,171 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2010 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 . -***/ - -#include -#include -#include -#include -#include - -#include "macro.h" -#include "util.h" -#include "mkdir.h" -#include "missing.h" -#include "selinux-util.h" -#include "socket-util.h" - -int socket_address_listen( - const SocketAddress *a, - int flags, - int backlog, - SocketAddressBindIPv6Only only, - const char *bind_to_device, - bool reuse_port, - bool free_bind, - bool transparent, - mode_t directory_mode, - mode_t socket_mode, - const char *label) { - - _cleanup_close_ int fd = -1; - int r, one; - - assert(a); - - r = socket_address_verify(a); - if (r < 0) - return r; - - if (socket_address_family(a) == AF_INET6 && !socket_ipv6_is_supported()) - return -EAFNOSUPPORT; - - if (label) { - r = mac_selinux_create_socket_prepare(label); - if (r < 0) - return r; - } - - fd = socket(socket_address_family(a), a->type | flags, a->protocol); - r = fd < 0 ? -errno : 0; - - if (label) - mac_selinux_create_socket_clear(); - - if (r < 0) - return r; - - if (socket_address_family(a) == AF_INET6 && only != SOCKET_ADDRESS_DEFAULT) { - int flag = only == SOCKET_ADDRESS_IPV6_ONLY; - - if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &flag, sizeof(flag)) < 0) - return -errno; - } - - if (socket_address_family(a) == AF_INET || socket_address_family(a) == AF_INET6) { - if (bind_to_device) - if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, bind_to_device, strlen(bind_to_device)+1) < 0) - return -errno; - - if (reuse_port) { - one = 1; - if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) < 0) - log_warning_errno(errno, "SO_REUSEPORT failed: %m"); - } - - if (free_bind) { - one = 1; - if (setsockopt(fd, IPPROTO_IP, IP_FREEBIND, &one, sizeof(one)) < 0) - log_warning_errno(errno, "IP_FREEBIND failed: %m"); - } - - if (transparent) { - one = 1; - if (setsockopt(fd, IPPROTO_IP, IP_TRANSPARENT, &one, sizeof(one)) < 0) - log_warning_errno(errno, "IP_TRANSPARENT failed: %m"); - } - } - - one = 1; - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) - return -errno; - - if (socket_address_family(a) == AF_UNIX && a->sockaddr.un.sun_path[0] != 0) { - mode_t old_mask; - - /* Create parents */ - mkdir_parents_label(a->sockaddr.un.sun_path, directory_mode); - - /* Enforce the right access mode for the socket */ - old_mask = umask(~ socket_mode); - - r = mac_selinux_bind(fd, &a->sockaddr.sa, a->size); - - if (r < 0 && errno == EADDRINUSE) { - /* Unlink and try again */ - unlink(a->sockaddr.un.sun_path); - r = bind(fd, &a->sockaddr.sa, a->size); - } - - umask(old_mask); - } else - r = bind(fd, &a->sockaddr.sa, a->size); - - if (r < 0) - return -errno; - - if (socket_address_can_accept(a)) - if (listen(fd, backlog) < 0) - return -errno; - - r = fd; - fd = -1; - - return r; -} - -int make_socket_fd(int log_level, const char* address, int flags) { - SocketAddress a; - int fd, r; - - r = socket_address_parse(&a, address); - if (r < 0) { - log_error("Failed to parse socket address \"%s\": %s", - address, strerror(-r)); - return r; - } - - fd = socket_address_listen(&a, flags, SOMAXCONN, SOCKET_ADDRESS_DEFAULT, - NULL, false, false, false, 0755, 0644, NULL); - if (fd < 0 || log_get_max_level() >= log_level) { - _cleanup_free_ char *p = NULL; - - r = socket_address_print(&a, &p); - if (r < 0) - return log_error_errno(r, "socket_address_print(): %m"); - - if (fd < 0) - log_error_errno(fd, "Failed to listen on %s: %m", p); - else - log_full(log_level, "Listening on %s", p); - } - - return fd; -} diff --git a/src/shared/socket-util.c b/src/shared/socket-util.c deleted file mode 100644 index 62f99b322..000000000 --- a/src/shared/socket-util.c +++ /dev/null @@ -1,769 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2010 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 . -***/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "macro.h" -#include "path-util.h" -#include "util.h" -#include "socket-util.h" -#include "missing.h" -#include "fileio.h" -#include "formats-util.h" - -int socket_address_parse(SocketAddress *a, const char *s) { - char *e, *n; - unsigned u; - int r; - - assert(a); - assert(s); - - zero(*a); - a->type = SOCK_STREAM; - - if (*s == '[') { - /* IPv6 in [x:.....:z]:p notation */ - - e = strchr(s+1, ']'); - if (!e) - return -EINVAL; - - n = strndupa(s+1, e-s-1); - - errno = 0; - if (inet_pton(AF_INET6, n, &a->sockaddr.in6.sin6_addr) <= 0) - return errno > 0 ? -errno : -EINVAL; - - e++; - if (*e != ':') - return -EINVAL; - - e++; - r = safe_atou(e, &u); - if (r < 0) - return r; - - if (u <= 0 || u > 0xFFFF) - return -EINVAL; - - a->sockaddr.in6.sin6_family = AF_INET6; - a->sockaddr.in6.sin6_port = htons((uint16_t) u); - a->size = sizeof(struct sockaddr_in6); - - } else if (*s == '/') { - /* AF_UNIX socket */ - - size_t l; - - l = strlen(s); - if (l >= sizeof(a->sockaddr.un.sun_path)) - return -EINVAL; - - a->sockaddr.un.sun_family = AF_UNIX; - memcpy(a->sockaddr.un.sun_path, s, l); - a->size = offsetof(struct sockaddr_un, sun_path) + l + 1; - - } else if (*s == '@') { - /* Abstract AF_UNIX socket */ - size_t l; - - l = strlen(s+1); - if (l >= sizeof(a->sockaddr.un.sun_path) - 1) - return -EINVAL; - - a->sockaddr.un.sun_family = AF_UNIX; - memcpy(a->sockaddr.un.sun_path+1, s+1, l); - a->size = offsetof(struct sockaddr_un, sun_path) + 1 + l; - - } else { - e = strchr(s, ':'); - if (e) { - r = safe_atou(e+1, &u); - if (r < 0) - return r; - - if (u <= 0 || u > 0xFFFF) - return -EINVAL; - - n = strndupa(s, e-s); - - /* IPv4 in w.x.y.z:p notation? */ - r = inet_pton(AF_INET, n, &a->sockaddr.in.sin_addr); - if (r < 0) - return -errno; - - if (r > 0) { - /* Gotcha, it's a traditional IPv4 address */ - a->sockaddr.in.sin_family = AF_INET; - a->sockaddr.in.sin_port = htons((uint16_t) u); - a->size = sizeof(struct sockaddr_in); - } else { - unsigned idx; - - if (strlen(n) > IF_NAMESIZE-1) - return -EINVAL; - - /* Uh, our last resort, an interface name */ - idx = if_nametoindex(n); - if (idx == 0) - return -EINVAL; - - a->sockaddr.in6.sin6_family = AF_INET6; - a->sockaddr.in6.sin6_port = htons((uint16_t) u); - a->sockaddr.in6.sin6_scope_id = idx; - a->sockaddr.in6.sin6_addr = in6addr_any; - a->size = sizeof(struct sockaddr_in6); - } - } else { - - /* Just a port */ - r = safe_atou(s, &u); - if (r < 0) - return r; - - if (u <= 0 || u > 0xFFFF) - return -EINVAL; - - if (socket_ipv6_is_supported()) { - a->sockaddr.in6.sin6_family = AF_INET6; - a->sockaddr.in6.sin6_port = htons((uint16_t) u); - a->sockaddr.in6.sin6_addr = in6addr_any; - a->size = sizeof(struct sockaddr_in6); - } else { - a->sockaddr.in.sin_family = AF_INET; - a->sockaddr.in.sin_port = htons((uint16_t) u); - a->sockaddr.in.sin_addr.s_addr = INADDR_ANY; - a->size = sizeof(struct sockaddr_in); - } - } - } - - return 0; -} - -int socket_address_parse_and_warn(SocketAddress *a, const char *s) { - SocketAddress b; - int r; - - /* Similar to socket_address_parse() but warns for IPv6 sockets when we don't support them. */ - - r = socket_address_parse(&b, s); - if (r < 0) - return r; - - if (!socket_ipv6_is_supported() && b.sockaddr.sa.sa_family == AF_INET6) { - log_warning("Binding to IPv6 address not available since kernel does not support IPv6."); - return -EAFNOSUPPORT; - } - - *a = b; - return 0; -} - -int socket_address_parse_netlink(SocketAddress *a, const char *s) { - int family; - unsigned group = 0; - _cleanup_free_ char *sfamily = NULL; - assert(a); - assert(s); - - zero(*a); - a->type = SOCK_RAW; - - errno = 0; - if (sscanf(s, "%ms %u", &sfamily, &group) < 1) - return errno > 0 ? -errno : -EINVAL; - - family = netlink_family_from_string(sfamily); - if (family < 0) - return -EINVAL; - - a->sockaddr.nl.nl_family = AF_NETLINK; - a->sockaddr.nl.nl_groups = group; - - a->type = SOCK_RAW; - a->size = sizeof(struct sockaddr_nl); - a->protocol = family; - - return 0; -} - -int socket_address_verify(const SocketAddress *a) { - assert(a); - - switch (socket_address_family(a)) { - - case AF_INET: - if (a->size != sizeof(struct sockaddr_in)) - return -EINVAL; - - if (a->sockaddr.in.sin_port == 0) - return -EINVAL; - - if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM) - return -EINVAL; - - return 0; - - case AF_INET6: - if (a->size != sizeof(struct sockaddr_in6)) - return -EINVAL; - - if (a->sockaddr.in6.sin6_port == 0) - return -EINVAL; - - if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM) - return -EINVAL; - - return 0; - - case AF_UNIX: - if (a->size < offsetof(struct sockaddr_un, sun_path)) - return -EINVAL; - - if (a->size > offsetof(struct sockaddr_un, sun_path)) { - - if (a->sockaddr.un.sun_path[0] != 0) { - char *e; - - /* path */ - e = memchr(a->sockaddr.un.sun_path, 0, sizeof(a->sockaddr.un.sun_path)); - if (!e) - return -EINVAL; - - if (a->size != offsetof(struct sockaddr_un, sun_path) + (e - a->sockaddr.un.sun_path) + 1) - return -EINVAL; - } - } - - if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM && a->type != SOCK_SEQPACKET) - return -EINVAL; - - return 0; - - case AF_NETLINK: - - if (a->size != sizeof(struct sockaddr_nl)) - return -EINVAL; - - if (a->type != SOCK_RAW && a->type != SOCK_DGRAM) - return -EINVAL; - - return 0; - - default: - return -EAFNOSUPPORT; - } -} - -int socket_address_print(const SocketAddress *a, char **ret) { - int r; - - assert(a); - assert(ret); - - r = socket_address_verify(a); - if (r < 0) - return r; - - if (socket_address_family(a) == AF_NETLINK) { - _cleanup_free_ char *sfamily = NULL; - - r = netlink_family_to_string_alloc(a->protocol, &sfamily); - if (r < 0) - return r; - - r = asprintf(ret, "%s %u", sfamily, a->sockaddr.nl.nl_groups); - if (r < 0) - return -ENOMEM; - - return 0; - } - - return sockaddr_pretty(&a->sockaddr.sa, a->size, false, true, ret); -} - -bool socket_address_can_accept(const SocketAddress *a) { - assert(a); - - return - a->type == SOCK_STREAM || - a->type == SOCK_SEQPACKET; -} - -bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) { - assert(a); - assert(b); - - /* Invalid addresses are unequal to all */ - if (socket_address_verify(a) < 0 || - socket_address_verify(b) < 0) - return false; - - if (a->type != b->type) - return false; - - if (socket_address_family(a) != socket_address_family(b)) - return false; - - switch (socket_address_family(a)) { - - case AF_INET: - if (a->sockaddr.in.sin_addr.s_addr != b->sockaddr.in.sin_addr.s_addr) - return false; - - if (a->sockaddr.in.sin_port != b->sockaddr.in.sin_port) - return false; - - break; - - case AF_INET6: - if (memcmp(&a->sockaddr.in6.sin6_addr, &b->sockaddr.in6.sin6_addr, sizeof(a->sockaddr.in6.sin6_addr)) != 0) - return false; - - if (a->sockaddr.in6.sin6_port != b->sockaddr.in6.sin6_port) - return false; - - break; - - case AF_UNIX: - if (a->size <= offsetof(struct sockaddr_un, sun_path) || - b->size <= offsetof(struct sockaddr_un, sun_path)) - return false; - - if ((a->sockaddr.un.sun_path[0] == 0) != (b->sockaddr.un.sun_path[0] == 0)) - return false; - - if (a->sockaddr.un.sun_path[0]) { - if (!path_equal_or_files_same(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path)) - return false; - } else { - if (a->size != b->size) - return false; - - if (memcmp(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path, a->size) != 0) - return false; - } - - break; - - case AF_NETLINK: - if (a->protocol != b->protocol) - return false; - - if (a->sockaddr.nl.nl_groups != b->sockaddr.nl.nl_groups) - return false; - - break; - - default: - /* Cannot compare, so we assume the addresses are different */ - return false; - } - - return true; -} - -bool socket_address_is(const SocketAddress *a, const char *s, int type) { - struct SocketAddress b; - - assert(a); - assert(s); - - if (socket_address_parse(&b, s) < 0) - return false; - - b.type = type; - - return socket_address_equal(a, &b); -} - -bool socket_address_is_netlink(const SocketAddress *a, const char *s) { - struct SocketAddress b; - - assert(a); - assert(s); - - if (socket_address_parse_netlink(&b, s) < 0) - return false; - - return socket_address_equal(a, &b); -} - -const char* socket_address_get_path(const SocketAddress *a) { - assert(a); - - if (socket_address_family(a) != AF_UNIX) - return NULL; - - if (a->sockaddr.un.sun_path[0] == 0) - return NULL; - - return a->sockaddr.un.sun_path; -} - -bool socket_ipv6_is_supported(void) { - _cleanup_free_ char *l = NULL; - - if (access("/sys/module/ipv6", F_OK) != 0) - return false; - - /* If we can't check "disable" parameter, assume enabled */ - if (read_one_line_file("/sys/module/ipv6/parameters/disable", &l) < 0) - return true; - - /* If module was loaded with disable=1 no IPv6 available */ - return l[0] == '0'; -} - -bool socket_address_matches_fd(const SocketAddress *a, int fd) { - SocketAddress b; - socklen_t solen; - - assert(a); - assert(fd >= 0); - - b.size = sizeof(b.sockaddr); - if (getsockname(fd, &b.sockaddr.sa, &b.size) < 0) - return false; - - if (b.sockaddr.sa.sa_family != a->sockaddr.sa.sa_family) - return false; - - solen = sizeof(b.type); - if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &b.type, &solen) < 0) - return false; - - if (b.type != a->type) - return false; - - if (a->protocol != 0) { - solen = sizeof(b.protocol); - if (getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &b.protocol, &solen) < 0) - return false; - - if (b.protocol != a->protocol) - return false; - } - - return socket_address_equal(a, &b); -} - -int sockaddr_port(const struct sockaddr *_sa) { - union sockaddr_union *sa = (union sockaddr_union*) _sa; - - assert(sa); - - if (!IN_SET(sa->sa.sa_family, AF_INET, AF_INET6)) - return -EAFNOSUPPORT; - - return ntohs(sa->sa.sa_family == AF_INET6 ? - sa->in6.sin6_port : - sa->in.sin_port); -} - -int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret) { - union sockaddr_union *sa = (union sockaddr_union*) _sa; - char *p; - int r; - - assert(sa); - assert(salen >= sizeof(sa->sa.sa_family)); - - switch (sa->sa.sa_family) { - - case AF_INET: { - uint32_t a; - - a = ntohl(sa->in.sin_addr.s_addr); - - if (include_port) - r = asprintf(&p, - "%u.%u.%u.%u:%u", - a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF, - ntohs(sa->in.sin_port)); - else - r = asprintf(&p, - "%u.%u.%u.%u", - a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF); - if (r < 0) - return -ENOMEM; - break; - } - - case AF_INET6: { - static const unsigned char ipv4_prefix[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF - }; - - if (translate_ipv6 && - memcmp(&sa->in6.sin6_addr, ipv4_prefix, sizeof(ipv4_prefix)) == 0) { - const uint8_t *a = sa->in6.sin6_addr.s6_addr+12; - if (include_port) - r = asprintf(&p, - "%u.%u.%u.%u:%u", - a[0], a[1], a[2], a[3], - ntohs(sa->in6.sin6_port)); - else - r = asprintf(&p, - "%u.%u.%u.%u", - a[0], a[1], a[2], a[3]); - if (r < 0) - return -ENOMEM; - } else { - char a[INET6_ADDRSTRLEN]; - - inet_ntop(AF_INET6, &sa->in6.sin6_addr, a, sizeof(a)); - - if (include_port) { - r = asprintf(&p, - "[%s]:%u", - a, - ntohs(sa->in6.sin6_port)); - if (r < 0) - return -ENOMEM; - } else { - p = strdup(a); - if (!p) - return -ENOMEM; - } - } - - break; - } - - case AF_UNIX: - if (salen <= offsetof(struct sockaddr_un, sun_path)) { - p = strdup(""); - if (!p) - return -ENOMEM; - - } else if (sa->un.sun_path[0] == 0) { - /* abstract */ - - /* FIXME: We assume we can print the - * socket path here and that it hasn't - * more than one NUL byte. That is - * actually an invalid assumption */ - - p = new(char, sizeof(sa->un.sun_path)+1); - if (!p) - return -ENOMEM; - - p[0] = '@'; - memcpy(p+1, sa->un.sun_path+1, sizeof(sa->un.sun_path)-1); - p[sizeof(sa->un.sun_path)] = 0; - - } else { - p = strndup(sa->un.sun_path, sizeof(sa->un.sun_path)); - if (!ret) - return -ENOMEM; - } - - break; - - default: - return -EOPNOTSUPP; - } - - - *ret = p; - return 0; -} - -int getpeername_pretty(int fd, char **ret) { - union sockaddr_union sa; - socklen_t salen = sizeof(sa); - int r; - - assert(fd >= 0); - assert(ret); - - if (getpeername(fd, &sa.sa, &salen) < 0) - return -errno; - - if (sa.sa.sa_family == AF_UNIX) { - struct ucred ucred = {}; - - /* UNIX connection sockets are anonymous, so let's use - * PID/UID as pretty credentials instead */ - - r = getpeercred(fd, &ucred); - if (r < 0) - return r; - - if (asprintf(ret, "PID "PID_FMT"/UID "UID_FMT, ucred.pid, ucred.uid) < 0) - return -ENOMEM; - - return 0; - } - - /* For remote sockets we translate IPv6 addresses back to IPv4 - * if applicable, since that's nicer. */ - - return sockaddr_pretty(&sa.sa, salen, true, true, ret); -} - -int getsockname_pretty(int fd, char **ret) { - union sockaddr_union sa; - socklen_t salen = sizeof(sa); - - assert(fd >= 0); - assert(ret); - - if (getsockname(fd, &sa.sa, &salen) < 0) - return -errno; - - /* For local sockets we do not translate IPv6 addresses back - * to IPv6 if applicable, since this is usually used for - * listening sockets where the difference between IPv4 and - * IPv6 matters. */ - - return sockaddr_pretty(&sa.sa, salen, false, true, ret); -} - -int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret) { - int r; - char host[NI_MAXHOST], *ret; - - assert(_ret); - - r = getnameinfo(&sa->sa, salen, host, sizeof(host), NULL, 0, - NI_IDN|NI_IDN_USE_STD3_ASCII_RULES); - if (r != 0) { - int saved_errno = errno; - - r = sockaddr_pretty(&sa->sa, salen, true, true, &ret); - if (r < 0) - return r; - - log_debug_errno(saved_errno, "getnameinfo(%s) failed: %m", ret); - } else { - ret = strdup(host); - if (!ret) - return -ENOMEM; - } - - *_ret = ret; - return 0; -} - -int getnameinfo_pretty(int fd, char **ret) { - union sockaddr_union sa; - socklen_t salen = sizeof(sa); - - assert(fd >= 0); - assert(ret); - - if (getsockname(fd, &sa.sa, &salen) < 0) - return -errno; - - return socknameinfo_pretty(&sa, salen, ret); -} - -int socket_address_unlink(SocketAddress *a) { - assert(a); - - if (socket_address_family(a) != AF_UNIX) - return 0; - - if (a->sockaddr.un.sun_path[0] == 0) - return 0; - - if (unlink(a->sockaddr.un.sun_path) < 0) - return -errno; - - return 1; -} - -static const char* const netlink_family_table[] = { - [NETLINK_ROUTE] = "route", - [NETLINK_FIREWALL] = "firewall", - [NETLINK_INET_DIAG] = "inet-diag", - [NETLINK_NFLOG] = "nflog", - [NETLINK_XFRM] = "xfrm", - [NETLINK_SELINUX] = "selinux", - [NETLINK_ISCSI] = "iscsi", - [NETLINK_AUDIT] = "audit", - [NETLINK_FIB_LOOKUP] = "fib-lookup", - [NETLINK_CONNECTOR] = "connector", - [NETLINK_NETFILTER] = "netfilter", - [NETLINK_IP6_FW] = "ip6-fw", - [NETLINK_DNRTMSG] = "dnrtmsg", - [NETLINK_KOBJECT_UEVENT] = "kobject-uevent", - [NETLINK_GENERIC] = "generic", - [NETLINK_SCSITRANSPORT] = "scsitransport", - [NETLINK_ECRYPTFS] = "ecryptfs" -}; - -DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(netlink_family, int, INT_MAX); - -static const char* const socket_address_bind_ipv6_only_table[_SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX] = { - [SOCKET_ADDRESS_DEFAULT] = "default", - [SOCKET_ADDRESS_BOTH] = "both", - [SOCKET_ADDRESS_IPV6_ONLY] = "ipv6-only" -}; - -DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only, SocketAddressBindIPv6Only); - -bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b) { - assert(a); - assert(b); - - if (a->sa.sa_family != b->sa.sa_family) - return false; - - if (a->sa.sa_family == AF_INET) - return a->in.sin_addr.s_addr == b->in.sin_addr.s_addr; - - if (a->sa.sa_family == AF_INET6) - return memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr)) == 0; - - return false; -} - -char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR_TO_STRING_MAX]) { - assert(addr); - assert(buffer); - - /* Like ether_ntoa() but uses %02x instead of %x to print - * ethernet addresses, which makes them look less funny. Also, - * doesn't use a static buffer. */ - - sprintf(buffer, "%02x:%02x:%02x:%02x:%02x:%02x", - addr->ether_addr_octet[0], - addr->ether_addr_octet[1], - addr->ether_addr_octet[2], - addr->ether_addr_octet[3], - addr->ether_addr_octet[4], - addr->ether_addr_octet[5]); - - return buffer; -} diff --git a/src/shared/sysctl-util.c b/src/shared/sysctl-util.c deleted file mode 100644 index 1de0b94fd..000000000 --- a/src/shared/sysctl-util.c +++ /dev/null @@ -1,80 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2010 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 . -***/ - -#include -#include -#include -#include -#include -#include -#include - -#include "log.h" -#include "util.h" -#include "fileio.h" -#include "build.h" -#include "sysctl-util.h" - -char *sysctl_normalize(char *s) { - char *n; - - n = strpbrk(s, "/."); - /* If the first separator is a slash, the path is - * assumed to be normalized and slashes remain slashes - * and dots remains dots. */ - if (!n || *n == '/') - return s; - - /* Otherwise, dots become slashes and slashes become - * dots. Fun. */ - while (n) { - if (*n == '.') - *n = '/'; - else - *n = '.'; - - n = strpbrk(n + 1, "/."); - } - - return s; -} - -int sysctl_write(const char *property, const char *value) { - char *p; - - assert(property); - assert(value); - - log_debug("Setting '%s' to '%s'", property, value); - - p = strjoina("/proc/sys/", property); - return write_string_file(p, value, 0); -} - -int sysctl_read(const char *property, char **content) { - char *p; - - assert(property); - assert(content); - - p = strjoina("/proc/sys/", property); - return read_full_file(p, content, NULL); -} diff --git a/src/shared/utmp-wtmp.c b/src/shared/utmp-wtmp.c deleted file mode 100644 index 6fa9a3d7a..000000000 --- a/src/shared/utmp-wtmp.c +++ /dev/null @@ -1,408 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2010 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 . -***/ - -#include -#include -#include -#include -#include -#include -#include - -#include "macro.h" -#include "path-util.h" -#include "terminal-util.h" -#include "hostname-util.h" -#include "utmp-wtmp.h" - -int utmp_get_runlevel(int *runlevel, int *previous) { - struct utmpx *found, lookup = { .ut_type = RUN_LVL }; - int r; - const char *e; - - assert(runlevel); - - /* If these values are set in the environment this takes - * precedence. Presumably, sysvinit does this to work around a - * race condition that would otherwise exist where we'd always - * go to disk and hence might read runlevel data that might be - * very new and does not apply to the current script being - * executed. */ - - e = getenv("RUNLEVEL"); - if (e && e[0] > 0) { - *runlevel = e[0]; - - if (previous) { - /* $PREVLEVEL seems to be an Upstart thing */ - - e = getenv("PREVLEVEL"); - if (e && e[0] > 0) - *previous = e[0]; - else - *previous = 0; - } - - return 0; - } - - if (utmpxname(_PATH_UTMPX) < 0) - return -errno; - - setutxent(); - - found = getutxid(&lookup); - if (!found) - r = -errno; - else { - int a, b; - - a = found->ut_pid & 0xFF; - b = (found->ut_pid >> 8) & 0xFF; - - *runlevel = a; - if (previous) - *previous = b; - - r = 0; - } - - endutxent(); - - return r; -} - -static void init_timestamp(struct utmpx *store, usec_t t) { - assert(store); - - if (t <= 0) - t = now(CLOCK_REALTIME); - - store->ut_tv.tv_sec = t / USEC_PER_SEC; - store->ut_tv.tv_usec = t % USEC_PER_SEC; -} - -static void init_entry(struct utmpx *store, usec_t t) { - struct utsname uts = {}; - - assert(store); - - init_timestamp(store, t); - - if (uname(&uts) >= 0) - strncpy(store->ut_host, uts.release, sizeof(store->ut_host)); - - strncpy(store->ut_line, "~", sizeof(store->ut_line)); /* or ~~ ? */ - strncpy(store->ut_id, "~~", sizeof(store->ut_id)); -} - -static int write_entry_utmp(const struct utmpx *store) { - int r; - - assert(store); - - /* utmp is similar to wtmp, but there is only one entry for - * each entry type resp. user; i.e. basically a key/value - * table. */ - - if (utmpxname(_PATH_UTMPX) < 0) - return -errno; - - setutxent(); - - if (!pututxline(store)) - r = -errno; - else - r = 0; - - endutxent(); - - return r; -} - -static int write_entry_wtmp(const struct utmpx *store) { - assert(store); - - /* wtmp is a simple append-only file where each entry is - simply appended to the end; i.e. basically a log. */ - - errno = 0; - updwtmpx(_PATH_WTMPX, store); - return -errno; -} - -static int write_utmp_wtmp(const struct utmpx *store_utmp, const struct utmpx *store_wtmp) { - int r, s; - - r = write_entry_utmp(store_utmp); - s = write_entry_wtmp(store_wtmp); - - if (r >= 0) - r = s; - - /* If utmp/wtmp have been disabled, that's a good thing, hence - * ignore the errors */ - if (r == -ENOENT) - r = 0; - - return r; -} - -static int write_entry_both(const struct utmpx *store) { - return write_utmp_wtmp(store, store); -} - -int utmp_put_shutdown(void) { - struct utmpx store = {}; - - init_entry(&store, 0); - - store.ut_type = RUN_LVL; - strncpy(store.ut_user, "shutdown", sizeof(store.ut_user)); - - return write_entry_both(&store); -} - -int utmp_put_reboot(usec_t t) { - struct utmpx store = {}; - - init_entry(&store, t); - - store.ut_type = BOOT_TIME; - strncpy(store.ut_user, "reboot", sizeof(store.ut_user)); - - return write_entry_both(&store); -} - -_pure_ static const char *sanitize_id(const char *id) { - size_t l; - - assert(id); - l = strlen(id); - - if (l <= sizeof(((struct utmpx*) NULL)->ut_id)) - return id; - - return id + l - sizeof(((struct utmpx*) NULL)->ut_id); -} - -int utmp_put_init_process(const char *id, pid_t pid, pid_t sid, const char *line) { - struct utmpx store = { - .ut_type = INIT_PROCESS, - .ut_pid = pid, - .ut_session = sid, - }; - - assert(id); - - init_timestamp(&store, 0); - - /* ut_id needs only be nul-terminated if it is shorter than sizeof(ut_id) */ - strncpy(store.ut_id, sanitize_id(id), sizeof(store.ut_id)); - - if (line) - strncpy(store.ut_line, basename(line), sizeof(store.ut_line)); - - return write_entry_both(&store); -} - -int utmp_put_dead_process(const char *id, pid_t pid, int code, int status) { - struct utmpx lookup = { - .ut_type = INIT_PROCESS /* looks for DEAD_PROCESS, LOGIN_PROCESS, USER_PROCESS, too */ - }, store, store_wtmp, *found; - - assert(id); - - setutxent(); - - /* ut_id needs only be nul-terminated if it is shorter than sizeof(ut_id) */ - strncpy(lookup.ut_id, sanitize_id(id), sizeof(lookup.ut_id)); - - found = getutxid(&lookup); - if (!found) - return 0; - - if (found->ut_pid != pid) - return 0; - - memcpy(&store, found, sizeof(store)); - store.ut_type = DEAD_PROCESS; - store.ut_exit.e_termination = code; - store.ut_exit.e_exit = status; - - zero(store.ut_user); - zero(store.ut_host); - zero(store.ut_tv); - - memcpy(&store_wtmp, &store, sizeof(store_wtmp)); - /* wtmp wants the current time */ - init_timestamp(&store_wtmp, 0); - - return write_utmp_wtmp(&store, &store_wtmp); -} - - -int utmp_put_runlevel(int runlevel, int previous) { - struct utmpx store = {}; - int r; - - assert(runlevel > 0); - - if (previous <= 0) { - /* Find the old runlevel automatically */ - - r = utmp_get_runlevel(&previous, NULL); - if (r < 0) { - if (r != -ESRCH) - return r; - - previous = 0; - } - } - - if (previous == runlevel) - return 0; - - init_entry(&store, 0); - - store.ut_type = RUN_LVL; - store.ut_pid = (runlevel & 0xFF) | ((previous & 0xFF) << 8); - strncpy(store.ut_user, "runlevel", sizeof(store.ut_user)); - - return write_entry_both(&store); -} - -#define TIMEOUT_MSEC 50 - -static int write_to_terminal(const char *tty, const char *message) { - _cleanup_close_ int fd = -1; - const char *p; - size_t left; - usec_t end; - - assert(tty); - assert(message); - - fd = open(tty, O_WRONLY|O_NDELAY|O_NOCTTY|O_CLOEXEC); - if (fd < 0 || !isatty(fd)) - return -errno; - - p = message; - left = strlen(message); - - end = now(CLOCK_MONOTONIC) + TIMEOUT_MSEC*USEC_PER_MSEC; - - while (left > 0) { - ssize_t n; - struct pollfd pollfd = { - .fd = fd, - .events = POLLOUT, - }; - usec_t t; - int k; - - t = now(CLOCK_MONOTONIC); - - if (t >= end) - return -ETIME; - - k = poll(&pollfd, 1, (end - t) / USEC_PER_MSEC); - if (k < 0) - return -errno; - - if (k == 0) - return -ETIME; - - n = write(fd, p, left); - if (n < 0) { - if (errno == EAGAIN) - continue; - - return -errno; - } - - assert((size_t) n <= left); - - p += n; - left -= n; - } - - return 0; -} - -int utmp_wall(const char *message, const char *username, bool (*match_tty)(const char *tty)) { - _cleanup_free_ char *text = NULL, *hn = NULL, *un = NULL, *tty = NULL; - char date[FORMAT_TIMESTAMP_MAX]; - struct utmpx *u; - int r; - - hn = gethostname_malloc(); - if (!hn) - return -ENOMEM; - if (!username) { - un = getlogname_malloc(); - if (!un) - return -ENOMEM; - } - - getttyname_harder(STDIN_FILENO, &tty); - - if (asprintf(&text, - "\a\r\n" - "Broadcast message from %s@%s%s%s (%s):\r\n\r\n" - "%s\r\n\r\n", - un ?: username, hn, - tty ? " on " : "", strempty(tty), - format_timestamp(date, sizeof(date), now(CLOCK_REALTIME)), - message) < 0) - return -ENOMEM; - - setutxent(); - - r = 0; - - while ((u = getutxent())) { - _cleanup_free_ char *buf = NULL; - const char *path; - int q; - - if (u->ut_type != USER_PROCESS || u->ut_user[0] == 0) - continue; - - /* this access is fine, because strlen("/dev/") << 32 (UT_LINESIZE) */ - if (path_startswith(u->ut_line, "/dev/")) - path = u->ut_line; - else { - if (asprintf(&buf, "/dev/%.*s", (int) sizeof(u->ut_line), u->ut_line) < 0) - return -ENOMEM; - - path = buf; - } - - if (!match_tty || match_tty(path)) { - q = write_to_terminal(path, text); - if (q < 0) - r = q; - } - } - - return r; -} diff --git a/src/shared/utmp-wtmp.h b/src/shared/utmp-wtmp.h new file mode 100644 index 000000000..e0ceb873a --- /dev/null +++ b/src/shared/utmp-wtmp.h @@ -0,0 +1,72 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2010 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 . +***/ + +#include "util.h" + +#ifdef HAVE_UTMP +int utmp_get_runlevel(int *runlevel, int *previous); + +int utmp_put_shutdown(void); +int utmp_put_reboot(usec_t timestamp); +int utmp_put_runlevel(int runlevel, int previous); + +int utmp_put_dead_process(const char *id, pid_t pid, int code, int status); +int utmp_put_init_process(const char *id, pid_t pid, pid_t sid, const char *line, int ut_type, const char *user); + +int utmp_wall( + const char *message, + const char *username, + const char *origin_tty, + bool (*match_tty)(const char *tty, void *userdata), + void *userdata); + +#else /* HAVE_UTMP */ + +static inline int utmp_get_runlevel(int *runlevel, int *previous) { + return -ESRCH; +} +static inline int utmp_put_shutdown(void) { + return 0; +} +static inline int utmp_put_reboot(usec_t timestamp) { + return 0; +} +static inline int utmp_put_runlevel(int runlevel, int previous) { + return 0; +} +static inline int utmp_put_dead_process(const char *id, pid_t pid, int code, int status) { + return 0; +} +static inline int utmp_put_init_process(const char *id, pid_t pid, pid_t sid, const char *line, int ut_type, const char *user) { + return 0; +} +static inline int utmp_wall( + const char *message, + const char *username, + const char *origin_tty, + bool (*match_tty)(const char *tty, void *userdata), + void *userdata) { + return 0; +} + +#endif /* HAVE_UTMP */ diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h index fcb518317..a9a6b4eb7 100644 --- a/src/systemd/sd-bus.h +++ b/src/systemd/sd-bus.h @@ -156,6 +156,7 @@ void sd_bus_close(sd_bus *bus); sd_bus *sd_bus_ref(sd_bus *bus); sd_bus *sd_bus_unref(sd_bus *bus); +sd_bus *sd_bus_flush_close_unref(sd_bus *bus); // UNNEEDED int sd_bus_is_open(sd_bus *bus); @@ -204,7 +205,7 @@ sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot); // UNNEEDED void *sd_bus_slot_get_userdata(sd_bus_slot *slot); // UNNEEDED void *sd_bus_slot_set_userdata(sd_bus_slot *slot, void *userdata); // UNNEEDED int sd_bus_slot_set_description(sd_bus_slot *slot, const char *description); -// UNNEEDED int sd_bus_slot_get_description(sd_bus_slot *slot, char **description); +// UNNEEDED int sd_bus_slot_get_description(sd_bus_slot *slot, const char **description); // UNNEEDED sd_bus_message* sd_bus_slot_get_current_message(sd_bus_slot *slot); // UNNEEDED sd_bus_message_handler_t sd_bus_slot_get_current_handler(sd_bus_slot *bus); diff --git a/src/test/test-dns-domain.c b/src/test/test-dns-domain.c deleted file mode 100644 index 0042722c9..000000000 --- a/src/test/test-dns-domain.c +++ /dev/null @@ -1,268 +0,0 @@ -/*-*- 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 . - ***/ - -#include "macro.h" -#include "dns-domain.h" - -static void test_dns_label_unescape_one(const char *what, const char *expect, size_t buffer_sz, int ret) { - char buffer[buffer_sz]; - int r; - - r = dns_label_unescape(&what, buffer, buffer_sz); - assert_se(r == ret); - - if (r < 0) - return; - - assert_se(streq(buffer, expect)); -} - -static void test_dns_label_unescape(void) { - test_dns_label_unescape_one("hallo", "hallo", 6, 5); - test_dns_label_unescape_one("hallo", "hallo", 4, -ENOSPC); - test_dns_label_unescape_one("", "", 10, 0); - test_dns_label_unescape_one("hallo\\.foobar", "hallo.foobar", 20, 12); - test_dns_label_unescape_one("hallo.foobar", "hallo", 10, 5); - test_dns_label_unescape_one("hallo\n.foobar", "hallo", 20, -EINVAL); - test_dns_label_unescape_one("hallo\\", "hallo", 20, -EINVAL); - test_dns_label_unescape_one("hallo\\032 ", "hallo ", 20, 7); - test_dns_label_unescape_one(".", "", 20, 0); - test_dns_label_unescape_one("..", "", 20, -EINVAL); - test_dns_label_unescape_one(".foobar", "", 20, -EINVAL); - test_dns_label_unescape_one("foobar.", "foobar", 20, 6); -} - -static void test_dns_label_unescape_suffix_one(const char *what, const char *expect1, const char *expect2, size_t buffer_sz, int ret1, int ret2) { - char buffer[buffer_sz]; - const char *label; - int r; - - label = what + strlen(what); - - r = dns_label_unescape_suffix(what, &label, buffer, buffer_sz); - assert_se(r == ret1); - if (r >= 0) - assert_se(streq(buffer, expect1)); - - r = dns_label_unescape_suffix(what, &label, buffer, buffer_sz); - assert_se(r == ret2); - if (r >= 0) - assert_se(streq(buffer, expect2)); -} - -static void test_dns_label_unescape_suffix(void) { - test_dns_label_unescape_suffix_one("hallo", "hallo", "", 6, 5, 0); - test_dns_label_unescape_suffix_one("hallo", "hallo", "", 4, -ENOSPC, -ENOSPC); - test_dns_label_unescape_suffix_one("", "", "", 10, 0, 0); - test_dns_label_unescape_suffix_one("hallo\\.foobar", "hallo.foobar", "", 20, 12, 0); - test_dns_label_unescape_suffix_one("hallo.foobar", "foobar", "hallo", 10, 6, 5); - test_dns_label_unescape_suffix_one("hallo.foobar\n", "foobar", "foobar", 20, -EINVAL, -EINVAL); - test_dns_label_unescape_suffix_one("hallo\\", "hallo", "hallo", 20, -EINVAL, -EINVAL); - test_dns_label_unescape_suffix_one("hallo\\032 ", "hallo ", "", 20, 7, 0); - test_dns_label_unescape_suffix_one(".", "", "", 20, 0, 0); - test_dns_label_unescape_suffix_one("..", "", "", 20, 0, 0); - test_dns_label_unescape_suffix_one(".foobar", "foobar", "", 20, 6, -EINVAL); - test_dns_label_unescape_suffix_one("foobar.", "", "foobar", 20, 0, 6); - test_dns_label_unescape_suffix_one("foo\\\\bar", "foo\\bar", "", 20, 7, 0); - test_dns_label_unescape_suffix_one("foo.bar", "bar", "foo", 20, 3, 3); - test_dns_label_unescape_suffix_one("foo..bar", "bar", "", 20, 3, -EINVAL); - test_dns_label_unescape_suffix_one("foo...bar", "bar", "", 20, 3, -EINVAL); - test_dns_label_unescape_suffix_one("foo\\.bar", "foo.bar", "", 20, 7, 0); - test_dns_label_unescape_suffix_one("foo\\\\.bar", "bar", "foo\\", 20, 3, 4); - test_dns_label_unescape_suffix_one("foo\\\\\\.bar", "foo\\.bar", "", 20, 8, 0); -} - -static void test_dns_label_escape_one(const char *what, size_t l, const char *expect, int ret) { - _cleanup_free_ char *t = NULL; - int r; - - r = dns_label_escape(what, l, &t); - assert_se(r == ret); - - if (r < 0) - return; - - assert_se(streq_ptr(expect, t)); -} - -static void test_dns_label_escape(void) { - test_dns_label_escape_one("", 0, "", 0); - test_dns_label_escape_one("hallo", 5, "hallo", 5); - test_dns_label_escape_one("hallo", 6, NULL, -EINVAL); - test_dns_label_escape_one("hallo hallo.foobar,waldi", 24, "hallo\\032hallo\\.foobar\\044waldi", 31); -} - -static void test_dns_name_normalize_one(const char *what, const char *expect, int ret) { - _cleanup_free_ char *t = NULL; - int r; - - r = dns_name_normalize(what, &t); - assert_se(r == ret); - - if (r < 0) - return; - - assert_se(streq_ptr(expect, t)); -} - -static void test_dns_name_normalize(void) { - test_dns_name_normalize_one("", "", 0); - test_dns_name_normalize_one("f", "f", 0); - test_dns_name_normalize_one("f.waldi", "f.waldi", 0); - test_dns_name_normalize_one("f \\032.waldi", "f\\032\\032.waldi", 0); - test_dns_name_normalize_one("\\000", NULL, -EINVAL); - test_dns_name_normalize_one("..", NULL, -EINVAL); - test_dns_name_normalize_one(".foobar", NULL, -EINVAL); - test_dns_name_normalize_one("foobar.", "foobar", 0); - test_dns_name_normalize_one(".", "", 0); -} - -static void test_dns_name_equal_one(const char *a, const char *b, int ret) { - int r; - - r = dns_name_equal(a, b); - assert_se(r == ret); - - r = dns_name_equal(b, a); - assert_se(r == ret); -} - -static void test_dns_name_equal(void) { - test_dns_name_equal_one("", "", true); - test_dns_name_equal_one("x", "x", true); - test_dns_name_equal_one("x", "x.", true); - test_dns_name_equal_one("abc.def", "abc.def", true); - test_dns_name_equal_one("abc.def", "ABC.def", true); - test_dns_name_equal_one("abc.def", "CBA.def", false); - test_dns_name_equal_one("", "xxx", false); - test_dns_name_equal_one("ab", "a", false); - test_dns_name_equal_one("\\000", "xxxx", -EINVAL); - test_dns_name_equal_one(".", "", true); - test_dns_name_equal_one(".", ".", true); - test_dns_name_equal_one("..", "..", -EINVAL); -} - -static void test_dns_name_between_one(const char *a, const char *b, const char *c, int ret) { - int r; - - r = dns_name_between(a, b, c); - assert_se(r == ret); - - r = dns_name_between(c, b, a); - if (ret >= 0) - assert_se(r == 0); - else - assert_se(r == ret); -} - -static void test_dns_name_between(void) { - /* see https://tools.ietf.org/html/rfc4034#section-6.1 - Note that we use "\033.z.example" in stead of "\001.z.example" as we - consider the latter invalid */ - test_dns_name_between_one("example", "a.example", "yljkjljk.a.example", true); - test_dns_name_between_one("a.example", "yljkjljk.a.example", "Z.a.example", true); - test_dns_name_between_one("yljkjljk.a.example", "Z.a.example", "zABC.a.EXAMPLE", true); - test_dns_name_between_one("Z.a.example", "zABC.a.EXAMPLE", "z.example", true); - test_dns_name_between_one("zABC.a.EXAMPLE", "z.example", "\\033.z.example", true); - test_dns_name_between_one("z.example", "\\033.z.example", "*.z.example", true); - test_dns_name_between_one("\\033.z.example", "*.z.example", "\\200.z.example", true); - test_dns_name_between_one("*.z.example", "\\200.z.example", "example", true); - test_dns_name_between_one("\\200.z.example", "example", "a.example", true); - - test_dns_name_between_one("example", "a.example", "example", -EINVAL); - test_dns_name_between_one("example", "example", "yljkjljk.a.example", false); - test_dns_name_between_one("example", "yljkjljk.a.example", "yljkjljk.a.example", false); -} - -static void test_dns_name_endswith_one(const char *a, const char *b, int ret) { - assert_se(dns_name_endswith(a, b) == ret); -} - -static void test_dns_name_endswith(void) { - test_dns_name_endswith_one("", "", true); - test_dns_name_endswith_one("", "xxx", false); - test_dns_name_endswith_one("xxx", "", true); - test_dns_name_endswith_one("x", "x", true); - test_dns_name_endswith_one("x", "y", false); - test_dns_name_endswith_one("x.y", "y", true); - test_dns_name_endswith_one("x.y", "Y", true); - test_dns_name_endswith_one("x.y", "x", false); - test_dns_name_endswith_one("x.y.z", "Z", true); - test_dns_name_endswith_one("x.y.z", "y.Z", true); - test_dns_name_endswith_one("x.y.z", "x.y.Z", true); - test_dns_name_endswith_one("x.y.z", "waldo", false); - test_dns_name_endswith_one("x.y.z.u.v.w", "y.z", false); - test_dns_name_endswith_one("x.y.z.u.v.w", "u.v.w", true); - test_dns_name_endswith_one("x.y\001.z", "waldo", -EINVAL); -} - -static void test_dns_name_root(void) { - assert_se(dns_name_root("") == true); - assert_se(dns_name_root(".") == true); - assert_se(dns_name_root("xxx") == false); - assert_se(dns_name_root("xxx.") == false); - assert_se(dns_name_root("..") == -EINVAL); -} - -static void test_dns_name_single_label(void) { - assert_se(dns_name_single_label("") == false); - assert_se(dns_name_single_label(".") == false); - assert_se(dns_name_single_label("..") == -EINVAL); - assert_se(dns_name_single_label("x") == true); - assert_se(dns_name_single_label("x.") == true); - assert_se(dns_name_single_label("xx.yy") == false); -} - -static void test_dns_name_reverse_one(const char *address, const char *name) { - _cleanup_free_ char *p = NULL; - union in_addr_union a, b = {}; - int familya, familyb; - - assert_se(in_addr_from_string_auto(address, &familya, &a) >= 0); - assert_se(dns_name_reverse(familya, &a, &p) >= 0); - assert_se(streq(p, name)); - assert_se(dns_name_address(p, &familyb, &b) > 0); - assert_se(familya == familyb); - assert_se(in_addr_equal(familya, &a, &b)); -} - -static void test_dns_name_reverse(void) { - test_dns_name_reverse_one("47.11.8.15", "15.8.11.47.in-addr.arpa"); - test_dns_name_reverse_one("fe80::47", "7.4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.e.f.ip6.arpa"); - test_dns_name_reverse_one("127.0.0.1", "1.0.0.127.in-addr.arpa"); - test_dns_name_reverse_one("::1", "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa"); -} - -int main(int argc, char *argv[]) { - - test_dns_label_unescape(); - test_dns_label_unescape_suffix(); - test_dns_label_escape(); - test_dns_name_normalize(); - test_dns_name_equal(); - test_dns_name_endswith(); - test_dns_name_between(); - test_dns_name_root(); - test_dns_name_single_label(); - test_dns_name_reverse(); - - return 0; -} diff --git a/units/systemd-networkd.service.m4.in b/units/systemd-networkd.service.m4.in deleted file mode 100644 index 35be713ad..000000000 --- a/units/systemd-networkd.service.m4.in +++ /dev/null @@ -1,37 +0,0 @@ -# This file is part of systemd. -# -# 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. - -[Unit] -Description=Network Service -Documentation=man:systemd-networkd.service(8) -ConditionCapability=CAP_NET_ADMIN -DefaultDependencies=no -# dbus.service can be dropped once on kdbus, and systemd-udevd.service can be -# dropped once tuntap is moved to netlink -After=systemd-udevd.service dbus.service network-pre.target systemd-sysusers.service systemd-sysctl.service -Before=network.target multi-user.target shutdown.target -Conflicts=shutdown.target -Wants=network.target - -# On kdbus systems we pull in the busname explicitly, because it -# carries policy that allows the daemon to acquire its name. -Wants=org.freedesktop.network1.busname -After=org.freedesktop.network1.busname - -[Service] -Type=notify -Restart=on-failure -RestartSec=0 -ExecStart=@rootlibexecdir@/systemd-networkd -CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_BROADCAST CAP_NET_RAW CAP_SETUID CAP_SETGID CAP_SETPCAP CAP_CHOWN CAP_DAC_OVERRIDE CAP_FOWNER -ProtectSystem=full -ProtectHome=yes -WatchdogSec=1min - -[Install] -WantedBy=multi-user.target -Also=systemd-networkd.socket