]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/portable/portable.c
Merge pull request #15623 from poettering/cmsg-cleanup
[thirdparty/systemd.git] / src / portable / portable.c
index 1017864b375c4a1caa4b17e73837351d01e5386d..a6aaa14ab6a1c59ab602b4594ba24f3f783f1e78 100644 (file)
@@ -1,5 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
+#include <linux/loop.h>
+
 #include "bus-common-errors.h"
 #include "bus-error.h"
 #include "conf-files.h"
@@ -10,6 +12,7 @@
 #include "fd-util.h"
 #include "fileio.h"
 #include "fs-util.h"
+#include "install.h"
 #include "io-util.h"
 #include "locale-util.h"
 #include "loop-util.h"
@@ -124,10 +127,7 @@ static int send_item(
                 const char *name,
                 int fd) {
 
-        union {
-                struct cmsghdr cmsghdr;
-                uint8_t buf[CMSG_SPACE(sizeof(int))];
-        } control = {};
+        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(int))) control = {};
         struct iovec iovec;
         struct msghdr mh = {
                 .msg_control = &control,
@@ -152,7 +152,6 @@ static int send_item(
         cmsg->cmsg_len = CMSG_LEN(sizeof(int));
         memcpy(CMSG_DATA(cmsg), &data_fd, sizeof(int));
 
-        mh.msg_controllen = CMSG_SPACE(sizeof(int));
         iovec = IOVEC_MAKE_STRING(name);
 
         if (sendmsg(socket_fd, &mh, MSG_NOSIGNAL) < 0)
@@ -166,10 +165,7 @@ static int recv_item(
                 char **ret_name,
                 int *ret_fd) {
 
-        union {
-                struct cmsghdr cmsghdr;
-                uint8_t buf[CMSG_SPACE(sizeof(int))];
-        } control = {};
+        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(int))) control;
         char buffer[PATH_MAX+2];
         struct iovec iov = IOVEC_INIT(buffer, sizeof(buffer)-1);
         struct msghdr mh = {
@@ -187,9 +183,9 @@ static int recv_item(
         assert(ret_name);
         assert(ret_fd);
 
-        n = recvmsg(socket_fd, &mh, MSG_CMSG_CLOEXEC);
+        n = recvmsg_safe(socket_fd, &mh, MSG_CMSG_CLOEXEC);
         if (n < 0)
-                return -errno;
+                return (int) n;
 
         CMSG_FOREACH(cmsg, &mh) {
                 if (cmsg->cmsg_level == SOL_SOCKET &&
@@ -325,7 +321,7 @@ static int extract_now(
                                 return -ENOMEM;
                         fd = -1;
 
-                        m->source = strjoin(resolved, "/", de->d_name);
+                        m->source = path_join(resolved, de->d_name);
                         if (!m->source)
                                 return -ENOMEM;
 
@@ -358,7 +354,7 @@ static int portable_extract_by_path(
 
         assert(path);
 
-        r = loop_device_make_by_path(path, O_RDONLY, &d);
+        r = loop_device_make_by_path(path, O_RDONLY, LO_FLAGS_PARTSCAN, &d);
         if (r == -EISDIR) {
                 /* We can't turn this into a loop-back block device, and this returns EISDIR? Then this is a directory
                  * tree and not a raw device. It's easy then. */
@@ -384,7 +380,7 @@ static int portable_extract_by_path(
                 if (r < 0)
                         return log_debug_errno(r, "Failed to create temporary directory: %m");
 
-                r = dissect_image(d->fd, NULL, 0, DISSECT_IMAGE_READ_ONLY|DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_DISCARD_ON_LOOP, &m);
+                r = dissect_image(d->fd, NULL, 0, DISSECT_IMAGE_READ_ONLY|DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_DISCARD_ON_LOOP|DISSECT_IMAGE_RELAX_VAR_CHECK, &m);
                 if (r == -ENOPKG)
                         sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Couldn't identify a suitable partition table or file system in '%s'.", path);
                 else if (r == -EADDRNOTAVAIL)
@@ -434,7 +430,7 @@ static int portable_extract_by_path(
                         if (r < 0)
                                 return log_debug_errno(r, "Failed to receive item: %m");
 
-                        /* We can't really distuingish a zero-length datagram without any fds from EOF (both are signalled the
+                        /* We can't really distinguish a zero-length datagram without any fds from EOF (both are signalled the
                          * same way by recvmsg()). Hence, accept either as end notification. */
                         if (isempty(name) && fd < 0)
                                 break;
@@ -653,10 +649,10 @@ static int portable_changes_add_with_prefix(
                 return 0;
 
         if (prefix) {
-                path = strjoina(prefix, "/", path);
+                path = prefix_roota(prefix, path);
 
                 if (source)
-                        source = strjoina(prefix, "/", source);
+                        source = prefix_roota(prefix, source);
         }
 
         return portable_changes_add(changes, n_changes, type, path, source);
@@ -691,7 +687,7 @@ static int install_chroot_dropin(
         assert(m);
         assert(dropin_dir);
 
-        dropin = strjoin(dropin_dir, "/20-portable.conf");
+        dropin = path_join(dropin_dir, "20-portable.conf");
         if (!dropin)
                 return -ENOMEM;
 
@@ -778,7 +774,7 @@ static int install_profile_dropin(
                 return 0;
         }
 
-        dropin = strjoin(dropin_dir, "/10-profile.conf");
+        dropin = path_join(dropin_dir, "10-profile.conf");
         if (!dropin)
                 return -ENOMEM;
 
@@ -847,7 +843,7 @@ static int attach_unit_file(
         } else
                 (void) portable_changes_add(changes, n_changes, PORTABLE_MKDIR, where, NULL);
 
-        path = strjoina(where, "/", m->name);
+        path = prefix_roota(where, m->name);
         dropin_dir = strjoin(path, ".d");
         if (!dropin_dir)
                 return -ENOMEM;
@@ -1089,10 +1085,9 @@ static int test_chroot_dropin(
                 return log_debug_errno(errno, "Failed to open %s/%s: %m", where, p);
         }
 
-        r = fdopen_unlocked(fd, "r", &f);
+        r = take_fdopen_unlocked(&fd, "r", &f);
         if (r < 0)
                 return log_debug_errno(r, "Failed to convert file handle: %m");
-        TAKE_FD(fd);
 
         r = read_line(f, LONG_LINE_MAX, &line);
         if (r < 0)
@@ -1154,10 +1149,6 @@ int portable_detach(
                 return log_debug_errno(errno, "Failed to open '%s' directory: %m", where);
         }
 
-        unit_files = set_new(&string_hash_ops);
-        if (!unit_files)
-                return -ENOMEM;
-
         markers = set_new(&path_hash_ops);
         if (!markers)
                 return -ENOMEM;
@@ -1170,7 +1161,7 @@ int portable_detach(
                         continue;
 
                 /* Filter out duplicates */
-                if (set_get(unit_files, de->d_name))
+                if (set_contains(unit_files, de->d_name))
                         continue;
 
                 dirent_ensure_type(d, de);
@@ -1186,7 +1177,7 @@ int portable_detach(
                 r = unit_file_lookup_state(UNIT_FILE_SYSTEM, &paths, de->d_name, &state);
                 if (r < 0)
                         return log_debug_errno(r, "Failed to determine unit file state of '%s': %m", de->d_name);
-                if (!IN_SET(state, UNIT_FILE_STATIC, UNIT_FILE_DISABLED, UNIT_FILE_LINKED, UNIT_FILE_RUNTIME))
+                if (!IN_SET(state, UNIT_FILE_STATIC, UNIT_FILE_DISABLED, UNIT_FILE_LINKED, UNIT_FILE_RUNTIME, UNIT_FILE_LINKED_RUNTIME))
                         return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit file '%s' is in state '%s', can't detach.", de->d_name, unit_file_state_to_string(state));
 
                 r = unit_file_is_active(bus, de->d_name, error);
@@ -1195,7 +1186,7 @@ int portable_detach(
                 if (r > 0)
                         return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit file '%s' is active, can't detach.", de->d_name);
 
-                r = set_put_strdup(unit_files, de->d_name);
+                r = set_put_strdup(&unit_files, de->d_name);
                 if (r < 0)
                         return log_debug_errno(r, "Failed to add unit name '%s' to set: %m", de->d_name);
 
@@ -1308,7 +1299,7 @@ static int portable_get_state_internal(
 
         _cleanup_(lookup_paths_free) LookupPaths paths = {};
         bool found_enabled = false, found_running = false;
-        _cleanup_set_free_free_ Set *unit_files = NULL;
+        _cleanup_set_free_ Set *unit_files = NULL;
         _cleanup_closedir_ DIR *d = NULL;
         const char *where;
         struct dirent *de;
@@ -1334,10 +1325,6 @@ static int portable_get_state_internal(
                 return log_debug_errno(errno, "Failed to open '%s' directory: %m", where);
         }
 
-        unit_files = set_new(&string_hash_ops);
-        if (!unit_files)
-                return -ENOMEM;
-
         FOREACH_DIRENT(de, d, return log_debug_errno(errno, "Failed to enumerate '%s' directory: %m", where)) {
                 UnitFileState state;
 
@@ -1345,7 +1332,7 @@ static int portable_get_state_internal(
                         continue;
 
                 /* Filter out duplicates */
-                if (set_get(unit_files, de->d_name))
+                if (set_contains(unit_files, de->d_name))
                         continue;
 
                 dirent_ensure_type(d, de);
@@ -1370,7 +1357,7 @@ static int portable_get_state_internal(
                 if (r > 0)
                         found_running = true;
 
-                r = set_put_strdup(unit_files, de->d_name);
+                r = set_put_strdup(&unit_files, de->d_name);
                 if (r < 0)
                         return log_debug_errno(r, "Failed to add unit name '%s' to set: %m", de->d_name);
         }