]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #28611 from yuwata/meson-use-template
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 1 Aug 2023 12:32:48 +0000 (21:32 +0900)
committerGitHub <noreply@github.com>
Tue, 1 Aug 2023 12:32:48 +0000 (21:32 +0900)
meson: use template (part 4)

15 files changed:
.github/workflows/cifuzz.yml
.github/workflows/codeql.yml
man/repart.d.xml
man/systemd-repart.xml
src/core/dbus-cgroup.c
src/core/dbus-execute.c
src/core/load-fragment.c
src/core/manager.c
src/journal/journald-context.c
src/partition/repart.c
src/shared/creds-util.c
src/shared/creds-util.h
src/udev/udev-builtin-net_id.c
test/units/testsuite-58.sh
units/systemd-repart.service.in

index 41dc498b943eab265cca4937dc4d4678d057832f..ca1ccf7fea5ad033c452bf1762701c27a4180938 100644 (file)
@@ -67,7 +67,7 @@ jobs:
           path: ./out/artifacts
       - name: Upload Sarif
         if: always() && steps.build.outcome == 'success'
-        uses: github/codeql-action/upload-sarif@f6e388ebf0efc915c6c5b165b019ee61a6746a38
+        uses: github/codeql-action/upload-sarif@0ba4244466797eb048eb91a6cd43d5c03ca8bd05
         with:
           # Path to SARIF file relative to the root of the repository
           sarif_file: cifuzz-sarif/results.sarif
index b712c8f12b2f525b2e623657393cc3af9e8d21e5..82c64db687716abc005fd3d45fef8f2ea427aa1d 100644 (file)
@@ -45,7 +45,7 @@ jobs:
       uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
 
     - name: Initialize CodeQL
-      uses: github/codeql-action/init@f6e388ebf0efc915c6c5b165b019ee61a6746a38
+      uses: github/codeql-action/init@0ba4244466797eb048eb91a6cd43d5c03ca8bd05
       with:
         languages: ${{ matrix.language }}
         config-file: ./.github/codeql-config.yml
@@ -53,7 +53,7 @@ jobs:
     - run: sudo -E .github/workflows/unit_tests.sh SETUP
 
     - name: Autobuild
-      uses: github/codeql-action/autobuild@f6e388ebf0efc915c6c5b165b019ee61a6746a38
+      uses: github/codeql-action/autobuild@0ba4244466797eb048eb91a6cd43d5c03ca8bd05
 
     - name: Perform CodeQL Analysis
-      uses: github/codeql-action/analyze@f6e388ebf0efc915c6c5b165b019ee61a6746a38
+      uses: github/codeql-action/analyze@0ba4244466797eb048eb91a6cd43d5c03ca8bd05
index a79724a93ea1c271e601cf5a9d0dda26299c27e3..7e4fe93cfcb41205a2eb6746659ada62ad53b44c 100644 (file)
         data is never overwritten. Note that the data is copied in before the partition table is updated,
         i.e. before the partition actually is persistently created. This provides robustness: it is
         guaranteed that the partition either doesn't exist or exists fully populated; it is not possible that
-        the partition exists but is not or only partially populated.</para>
-
-        <para>This option cannot be combined with <varname>Format=</varname> or
-        <varname>CopyFiles=</varname>.</para></listitem>
+        the partition exists but is not or only partially populated.</para></listitem>
       </varlistentry>
 
       <varlistentry>
 
         <para>Similarly to the behaviour of <varname>CopyBlocks=</varname>, the file system is formatted
         before the partition is created, ensuring that the partition only ever exists with a fully
-        initialized file system.</para>
-
-        <para>This option cannot be combined with <varname>CopyBlocks=</varname>.</para></listitem>
+        initialized file system.</para></listitem>
       </varlistentry>
 
       <varlistentry>
         <citerefentry project='man-pages'><refentrytitle>mkfs.xfs</refentrytitle><manvolnum>8</manvolnum></citerefentry>
         due to limitations of its protofile format.</para>
 
-        <para>This option cannot be combined with <varname>CopyBlocks=</varname>.</para>
+        <para>When this option is used in combination with <varname>CopyBlocks=</varname>,
+        <command>systemd-repart</command> will first try the <varname>CopyBlocks=</varname> logic and will
+        only fall back to the <varname>CopyFiles=</varname> logic if the <varname>CopyBlocks=</varname> logic
+        cannot be used.</para>
 
         <para>When
         <citerefentry><refentrytitle>systemd-repart</refentrytitle><manvolnum>8</manvolnum></citerefentry>
         into their original state by removing partitions and creating them anew. Defaults to off.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>OEM=</varname></term>
+
+        <listitem><para>Takes a boolean argument. If specified the partition is marked as an OEM partition.
+        When the <option>--oem</option> is used, only OEM partitions are written to the partition table.
+        Unless configured explicitly with <varname>OEM=</varname>, a partition is an OEM partition if
+        <varname>FactoryReset=no</varname>.</para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>Flags=</varname></term>
 
index 1799961527dc79aa30e222282a59ff94ac9818f4..39912052a4bf6960a4d250c4e771d985132fbc18 100644 (file)
         due to missing permissions.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--oem=</option><arg>BOOL</arg></term>
+
+        <listitem><para>Instructs <command>systemd-repart</command> to only include OEM partitions into the
+        image. Takes a boolean and is off by default. OEM partitions can be configured using the
+        <varname>OEM=</varname> setting.</para></listitem>
+      </varlistentry>
+
       <xi:include href="standard-options.xml" xpointer="help" />
       <xi:include href="standard-options.xml" xpointer="version" />
       <xi:include href="standard-options.xml" xpointer="no-pager" />
index 9ab806b22d7bbabc37222c4e903bf3c6f05fc771..5347525844e27e7e8bfa55bdb79c1eef82529076 100644 (file)
@@ -2159,7 +2159,7 @@ int bus_cgroup_set_property(
 
                         if (strv_isempty(l)) {
                                 c->restrict_network_interfaces_is_allow_list = false;
-                                c->restrict_network_interfaces = set_free(c->restrict_network_interfaces);
+                                c->restrict_network_interfaces = set_free_free(c->restrict_network_interfaces);
 
                                 unit_write_settingf(u, flags, name, "%s=", name);
                                 return 1;
index c3255398c6fdb4eb43ace1a5cb1ab88f3f04178a..52964390ae85fa4069694cd3eba7bb1db415db98 100644 (file)
@@ -1915,8 +1915,8 @@ int bus_exec_context_set_transient_property(
 
                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         if (strv_isempty(allow_list) && strv_isempty(deny_list)) {
-                                c->log_filter_allowed_patterns = set_free(c->log_filter_allowed_patterns);
-                                c->log_filter_denied_patterns = set_free(c->log_filter_denied_patterns);
+                                c->log_filter_allowed_patterns = set_free_free(c->log_filter_allowed_patterns);
+                                c->log_filter_denied_patterns = set_free_free(c->log_filter_denied_patterns);
                                 unit_write_settingf(u, flags, name, "%s=", name);
                         } else {
                                 r = set_put_strdupv(&c->log_filter_allowed_patterns, allow_list);
@@ -2124,7 +2124,7 @@ int bus_exec_context_set_transient_property(
 
                         if (strv_isempty(l)) {
                                 c->restrict_filesystems_allow_list = false;
-                                c->restrict_filesystems = set_free(c->restrict_filesystems);
+                                c->restrict_filesystems = set_free_free(c->restrict_filesystems);
 
                                 unit_write_setting(u, flags, name, "RestrictFileSystems=");
                                 return 1;
@@ -2374,7 +2374,7 @@ int bus_exec_context_set_transient_property(
                         return r;
 
                 if (!UNIT_WRITE_FLAGS_NOOP(flags) && isempty) {
-                        c->import_credentials = set_free(c->import_credentials);
+                        c->import_credentials = set_free_free(c->import_credentials);
                         (void) unit_write_settingf(u, flags, name, "%s=", name);
                 }
 
index c69d47c22842f6b304c3001552ec59ac5c9718e9..219a84a234df7e280b40ff2bad1bceb5ea0fbe86 100644 (file)
@@ -3664,7 +3664,7 @@ int config_parse_restrict_filesystems(
 
         if (isempty(rvalue)) {
                 /* Empty assignment resets the list */
-                c->restrict_filesystems = set_free(c->restrict_filesystems);
+                c->restrict_filesystems = set_free_free(c->restrict_filesystems);
                 c->restrict_filesystems_allow_list = false;
                 return 0;
         }
@@ -4977,7 +4977,7 @@ int config_parse_import_credential(
 
         if (isempty(rvalue)) {
                 /* Empty assignment resets the list */
-                *import_credentials = set_free(*import_credentials);
+                *import_credentials = set_free_free(*import_credentials);
                 return 0;
         }
 
@@ -6053,7 +6053,7 @@ int config_parse_restrict_network_interfaces(
 
         if (isempty(rvalue)) {
                 /* Empty assignment resets the list */
-                c->restrict_network_interfaces = set_free(c->restrict_network_interfaces);
+                c->restrict_network_interfaces = set_free_free(c->restrict_network_interfaces);
                 return 0;
         }
 
@@ -6647,8 +6647,8 @@ int config_parse_log_filter_patterns(
 
         if (isempty(pattern)) {
                 /* Empty assignment resets the lists. */
-                c->log_filter_allowed_patterns = set_free(c->log_filter_allowed_patterns);
-                c->log_filter_denied_patterns = set_free(c->log_filter_denied_patterns);
+                c->log_filter_allowed_patterns = set_free_free(c->log_filter_allowed_patterns);
+                c->log_filter_denied_patterns = set_free_free(c->log_filter_denied_patterns);
                 return 0;
         }
 
index b7af1594497bee989ae0dfd94788b65e61ce7a06..29bb7cca1ab2801b1db5df4af64baf564d5f581b 100644 (file)
@@ -3419,7 +3419,7 @@ usec_t manager_get_watchdog(Manager *m, WatchdogType t) {
         if (MANAGER_IS_USER(m))
                 return USEC_INFINITY;
 
-        if (timestamp_is_set(m->watchdog_overridden[t]))
+        if (m->watchdog_overridden[t] != USEC_INFINITY)
                 return m->watchdog_overridden[t];
 
         return m->watchdog[t];
@@ -3435,17 +3435,18 @@ void manager_set_watchdog(Manager *m, WatchdogType t, usec_t timeout) {
         if (m->watchdog[t] == timeout)
                 return;
 
-        if (t == WATCHDOG_RUNTIME) {
-                if (!timestamp_is_set(m->watchdog_overridden[WATCHDOG_RUNTIME]))
+        if (m->watchdog_overridden[t] == USEC_INFINITY) {
+                if (t == WATCHDOG_RUNTIME)
                         (void) watchdog_setup(timeout);
-        } else if (t == WATCHDOG_PRETIMEOUT)
-                if (m->watchdog_overridden[WATCHDOG_PRETIMEOUT] == USEC_INFINITY)
+                else if (t == WATCHDOG_PRETIMEOUT)
                         (void) watchdog_setup_pretimeout(timeout);
+        }
 
         m->watchdog[t] = timeout;
 }
 
 void manager_override_watchdog(Manager *m, WatchdogType t, usec_t timeout) {
+        usec_t usec;
 
         assert(m);
 
@@ -3455,12 +3456,11 @@ void manager_override_watchdog(Manager *m, WatchdogType t, usec_t timeout) {
         if (m->watchdog_overridden[t] == timeout)
                 return;
 
-        if (t == WATCHDOG_RUNTIME) {
-                usec_t usec = timestamp_is_set(timeout) ? timeout : m->watchdog[t];
-
+        usec = (timeout == USEC_INFINITY) ? m->watchdog[t] : timeout;
+        if (t == WATCHDOG_RUNTIME)
                 (void) watchdog_setup(usec);
-        else if (t == WATCHDOG_PRETIMEOUT)
-                (void) watchdog_setup_pretimeout(timeout);
+        else if (t == WATCHDOG_PRETIMEOUT)
+                (void) watchdog_setup_pretimeout(usec);
 
         m->watchdog_overridden[t] = timeout;
 }
index 9a09d544533b0058240fe31e173c34c99c032909..7274f5f3e93661843a0a47f9bc3c43ffc5c8f3f8 100644 (file)
@@ -182,8 +182,8 @@ static void client_context_reset(Server *s, ClientContext *c) {
         c->log_ratelimit_interval = s->ratelimit_interval;
         c->log_ratelimit_burst = s->ratelimit_burst;
 
-        c->log_filter_allowed_patterns = set_free(c->log_filter_allowed_patterns);
-        c->log_filter_denied_patterns = set_free(c->log_filter_denied_patterns);
+        c->log_filter_allowed_patterns = set_free_free(c->log_filter_allowed_patterns);
+        c->log_filter_denied_patterns = set_free_free(c->log_filter_denied_patterns);
 }
 
 static ClientContext* client_context_free(Server *s, ClientContext *c) {
index 6c39ee804c200734c82e9d22e49a54f1d2cb785d..9ae8ed4c117009046a2bb4801fc0626fbd9a220a 100644 (file)
@@ -24,6 +24,7 @@
 #include "conf-files.h"
 #include "conf-parser.h"
 #include "constants.h"
+#include "creds-util.h"
 #include "cryptsetup-util.h"
 #include "device-util.h"
 #include "devnum-util.h"
@@ -153,6 +154,7 @@ static uint64_t arg_sector_size = 0;
 static ImagePolicy *arg_image_policy = NULL;
 static Architecture arg_architecture = _ARCHITECTURE_INVALID;
 static int arg_offline = -1;
+static bool arg_oem = false;
 
 STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
@@ -205,6 +207,7 @@ typedef struct Partition {
 
         bool dropped;
         bool factory_reset;
+        int oem;
         int32_t priority;
 
         uint32_t weight, padding_weight;
@@ -350,6 +353,7 @@ static Partition *partition_new(void) {
                 .no_auto = -1,
                 .read_only = -1,
                 .growfs = -1,
+                .oem = -1,
         };
 
         return p;
@@ -423,9 +427,16 @@ static void partition_foreignize(Partition *p) {
         p->verity = VERITY_OFF;
 }
 
+static bool partition_is_oem(const Partition *p) {
+        return p->oem > 0 || (p->oem < 0 && !p->factory_reset);
+}
+
 static bool partition_exclude(const Partition *p) {
         assert(p);
 
+        if (arg_oem && !partition_is_oem(p))
+                return true;
+
         if (arg_filter_partitions_type == FILTER_PARTITIONS_NONE)
                 return false;
 
@@ -1631,6 +1642,7 @@ static int partition_read_definition(Partition *p, const char *path, const char
                 { "Partition", "GrowFileSystem",     config_parse_tristate,      0, &p->growfs               },
                 { "Partition", "SplitName",          config_parse_string,        0, &p->split_name_format    },
                 { "Partition", "Minimize",           config_parse_minimize,      0, &p->minimize             },
+                { "Partition", "OEM",                config_parse_tristate,      0, &p->oem                  },
                 {}
         };
         int r;
@@ -1672,11 +1684,6 @@ static int partition_read_definition(Partition *p, const char *path, const char
                 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
                                   "Type= not defined, refusing.");
 
-        if ((p->copy_blocks_path || p->copy_blocks_auto) &&
-            (p->format || !strv_isempty(p->copy_files) || !strv_isempty(p->make_directories)))
-                return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
-                                  "Format=/CopyFiles=/MakeDirectories= and CopyBlocks= cannot be combined, refusing.");
-
         if ((!strv_isempty(p->copy_files) || !strv_isempty(p->make_directories)) && streq_ptr(p->format, "swap"))
                 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
                                   "Format=swap and CopyFiles= cannot be combined, refusing.");
@@ -5387,19 +5394,6 @@ static int resolve_copy_blocks_auto(
         dev_t devno, found = 0;
         int r;
 
-        /* Enforce some security restrictions: CopyBlocks=auto should not be an avenue to get outside of the
-         * --root=/--image= confinement. Specifically, refuse CopyBlocks= in combination with --root= at all,
-         * and restrict block device references in the --image= case to loopback block device we set up.
-         *
-         * restrict_devno contain the dev_t of the loop back device we operate on in case of --image=, and
-         * thus declares which device (and its partition subdevices) we shall limit access to. If
-         * restrict_devno is zero no device probing access shall be allowed at all (used for --root=) and if
-         * it is (dev_t) -1 then free access shall be allowed (if neither switch is used). */
-
-        if (restrict_devno == 0)
-                return log_error_errno(SYNTHETIC_ERRNO(EPERM),
-                                       "Automatic discovery of backing block devices not permitted in --root= mode, refusing.");
-
         /* Handles CopyBlocks=auto, and finds the right source partition to copy from. We look for matching
          * partitions in the host, using the appropriate directory as key and ensuring that the partition
          * type matches. */
@@ -5492,17 +5486,13 @@ static int resolve_copy_blocks_auto(
                         found = devno;
         }
 
-        if (found == 0)
-                return log_error_errno(SYNTHETIC_ERRNO(ENXIO),
-                                       "Unable to automatically discover suitable partition to copy blocks from.");
-
         if (ret_devno)
                 *ret_devno = found;
 
         if (ret_uuid)
                 *ret_uuid = found_uuid;
 
-        return 0;
+        return found != 0;
 }
 
 static int context_open_copy_block_paths(
@@ -5544,9 +5534,35 @@ static int context_open_copy_block_paths(
                 } else if (p->copy_blocks_auto) {
                         dev_t devno = 0;  /* Fake initialization to appease gcc. */
 
+                        /* Enforce some security restrictions: CopyBlocks=auto should not be an avenue to get
+                         * outside of the --root=/--image= confinement. Specifically, refuse CopyBlocks= in
+                         * combination with --root= at all, and restrict block device references in the
+                         * --image= case to loopback block device we set up.
+                         *
+                         * restrict_devno contain the dev_t of the loop back device we operate on in case of
+                         * --image=, and thus declares which device (and its partition subdevices) we shall
+                         * limit access to. If restrict_devno is zero no device probing access shall be
+                         * allowed at all (used for --root=) and if it is (dev_t) -1 then free access shall
+                         * be allowed (if neither switch is used). */
+
+                        if (restrict_devno == 0) {
+                                if (!p->format && strv_isempty(p->copy_files) && strv_isempty(p->make_directories))
+                                        return log_error_errno(SYNTHETIC_ERRNO(EPERM),
+                                                               "Automatic discovery of backing block devices not permitted in --root= mode, refusing.");
+
+                                continue;
+                        }
+
                         r = resolve_copy_blocks_auto(p->type, p->copy_blocks_root, restrict_devno, &devno, &uuid);
                         if (r < 0)
                                 return r;
+                        if (r == 0) {
+                                if (!p->format && strv_isempty(p->copy_files) && strv_isempty(p->make_directories))
+                                        return log_error_errno(SYNTHETIC_ERRNO(ENXIO),
+                                                               "Unable to automatically discover suitable partition to copy blocks from.");
+
+                                continue;
+                        }
                         assert(devno != 0);
 
                         source_fd = r = device_open_from_devnum(S_IFBLK, devno, O_RDONLY|O_CLOEXEC|O_NONBLOCK, &opened);
@@ -5684,6 +5700,9 @@ static int context_minimize(Context *context) {
                 if (!p->format)
                         continue;
 
+                if (p->copy_blocks_fd >= 0)
+                        continue;
+
                 if (p->minimize == MINIMIZE_OFF)
                         continue;
 
@@ -5760,7 +5779,13 @@ static int context_minimize(Context *context) {
                 if (fstype_is_ro(p->format)) {
                         struct stat st;
 
-                        if (stat(temp, &st) < 0)
+                        assert(fd < 0);
+
+                        fd = open(temp, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
+                        if (fd < 0)
+                                return log_error_errno(errno, "Failed to open temporary file %s: %m", temp);
+
+                        if (fstat(fd, &st) < 0)
                                 return log_error_errno(errno, "Failed to stat temporary file: %m");
 
                         log_info("Minimal partition size of %s filesystem of partition %s is %s",
@@ -5768,6 +5793,8 @@ static int context_minimize(Context *context) {
 
                         p->copy_blocks_path = TAKE_PTR(temp);
                         p->copy_blocks_path_is_our_file = true;
+                        p->copy_blocks_fd = TAKE_FD(fd);
+                        p->copy_blocks_size = st.st_size;
                         continue;
                 }
 
@@ -5830,8 +5857,12 @@ static int context_minimize(Context *context) {
                                 return r;
                 }
 
+                assert(fd >= 0);
+
                 p->copy_blocks_path = TAKE_PTR(temp);
                 p->copy_blocks_path_is_our_file = true;
+                p->copy_blocks_fd = TAKE_FD(fd);
+                p->copy_blocks_size = fsz;
         }
 
         /* Now that we've done the data partitions, do the verity hash partitions. We do these in a separate
@@ -5840,6 +5871,7 @@ static int context_minimize(Context *context) {
         LIST_FOREACH(partitions, p, context->partitions) {
                 _cleanup_(unlink_and_freep) char *temp = NULL;
                 _cleanup_free_ char *hint = NULL;
+                _cleanup_close_ int fd = -EBADF;
                 struct stat st;
                 Partition *dp;
 
@@ -5882,7 +5914,11 @@ static int context_minimize(Context *context) {
                 if (r < 0)
                         return r;
 
-                if (stat(temp, &st) < 0)
+                fd = open(temp, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
+                if (fd < 0)
+                        return log_error_errno(errno, "Failed to open temporary file %s: %m", temp);
+
+                if (fstat(fd, &st) < 0)
                         return log_error_errno(r, "Failed to stat temporary file: %m");
 
                 log_info("Minimal partition size of verity hash partition %s is %s",
@@ -5890,6 +5926,8 @@ static int context_minimize(Context *context) {
 
                 p->copy_blocks_path = TAKE_PTR(temp);
                 p->copy_blocks_path_is_our_file = true;
+                p->copy_blocks_fd = TAKE_FD(fd);
+                p->copy_blocks_size = st.st_size;
         }
 
         return 0;
@@ -5978,6 +6016,7 @@ static int help(void) {
                "     --sector-size=SIZE   Set the logical sector size for the image\n"
                "     --architecture=ARCH  Set the generic architecture for the image\n"
                "     --offline=BOOL       Whether to build the image offline\n"
+               "     --oem=BOOL           Whether to only include OEM partitions\n"
                "\nSee the %s for details.\n",
                program_invocation_short_name,
                ansi_highlight(),
@@ -5987,6 +6026,17 @@ static int help(void) {
         return 0;
 }
 
+static int parse_credentials(void) {
+        int r;
+
+        r = read_credential_bool("repart.oem");
+        if (r < 0)
+                return log_error_errno(r, "Failed to read repart.oem credential: %m");
+        arg_oem = r;
+
+        return 0;
+}
+
 static int parse_argv(int argc, char *argv[]) {
 
         enum {
@@ -6021,6 +6071,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_SKIP_PARTITIONS,
                 ARG_ARCHITECTURE,
                 ARG_OFFLINE,
+                ARG_OEM,
         };
 
         static const struct option options[] = {
@@ -6055,6 +6106,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "sector-size",          required_argument, NULL, ARG_SECTOR_SIZE          },
                 { "architecture",         required_argument, NULL, ARG_ARCHITECTURE         },
                 { "offline",              required_argument, NULL, ARG_OFFLINE              },
+                { "oem",                  required_argument, NULL, ARG_OEM                  },
                 {}
         };
 
@@ -6376,6 +6428,13 @@ static int parse_argv(int argc, char *argv[]) {
 
                         break;
 
+                case ARG_OEM:
+                        r = parse_boolean_argument("--oem=", optarg, &arg_oem);
+                        if (r < 0)
+                                return r;
+
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -6872,6 +6931,10 @@ static int run(int argc, char *argv[]) {
         log_parse_environment();
         log_open();
 
+        r = parse_credentials();
+        if (r < 0)
+                return r;
+
         r = parse_argv(argc, argv);
         if (r <= 0)
                 return r;
@@ -7004,12 +7067,6 @@ static int run(int argc, char *argv[]) {
         if (r < 0)
                 return r;
 
-        /* We might have gotten more copy blocks paths to open during the minimize process, so let's make
-         * sure we open those as well. These should all be regular files, so don't allow any block devices. */
-        r = context_open_copy_block_paths(context, 0);
-        if (r < 0)
-                return r;
-
         if (arg_size_auto) {
                 r = determine_auto_size(context);
                 if (r < 0)
index 573900f870427e095f71be2512b9f8f937bbb213..16df01b9ca82808ac46435bf502d54470f3e9d25 100644 (file)
@@ -22,6 +22,7 @@
 #include "memory-util.h"
 #include "mkdir.h"
 #include "openssl-util.h"
+#include "parse-util.h"
 #include "path-util.h"
 #include "random-util.h"
 #include "sparse-endian.h"
@@ -253,6 +254,17 @@ int read_credential_strings_many_internal(
         return ret;
 }
 
+int read_credential_bool(const char *name) {
+        _cleanup_free_ void *data = NULL;
+        int r;
+
+        r = read_credential(name, &data, NULL);
+        if (r < 0)
+                return IN_SET(r, -ENXIO, -ENOENT) ? 0 : r;
+
+        return parse_boolean(data);
+}
+
 int get_credential_user_password(const char *username, char **ret_password, bool *ret_is_hashed) {
         _cleanup_(erase_and_freep) char *creds_password = NULL;
         _cleanup_free_ char *cn = NULL;
index 8fbd61e9fe6b48780e0a1cc145116d27aa8f73fd..5e39a6a022f6dc159e2b50627dbf9ec8b8412229 100644 (file)
@@ -43,6 +43,8 @@ int read_credential_strings_many_internal(const char *first_name, char **first_v
 #define read_credential_strings_many(first_name, first_value, ...) \
         read_credential_strings_many_internal(first_name, first_value, __VA_ARGS__, NULL)
 
+int read_credential_bool(const char *name);
+
 typedef enum CredentialSecretFlags {
         CREDENTIAL_SECRET_GENERATE             = 1 << 0,
         CREDENTIAL_SECRET_WARN_NOT_ENCRYPTED   = 1 << 1,
index a1aba19cba1a33eacef9705bc0055faa6518331b..e538fc7d9415c487fa11af0e0c692bfc350915f6 100644 (file)
@@ -67,8 +67,6 @@ typedef struct LinkInfo {
         int ifindex;
         int iflink;
         int iftype;
-        int vf_representor_id;
-        const char *phys_port_name;
 } LinkInfo;
 
 /* skip intermediate virtio devices */
@@ -138,7 +136,101 @@ static int get_virtfn_info(sd_device *pcidev, sd_device **ret_physfn_pcidev, cha
         return -ENOENT;
 }
 
-static bool is_valid_onboard_index(unsigned long idx) {
+static int get_dev_port(sd_device *dev, bool fallback_to_dev_id, unsigned *ret) {
+        unsigned v;
+        int r;
+
+        assert(dev);
+        assert(ret);
+
+        /* Get kernel provided port index for the case when multiple ports on a single PCI function. */
+
+        r = device_get_sysattr_unsigned(dev, "dev_port", &v);
+        if (r < 0)
+                return r;
+        if (r > 0) {
+                /* Found a positive index. Let's use it. */
+                *ret = v;
+                return 1; /* positive */
+        }
+        assert(v == 0);
+
+        /* With older kernels IP-over-InfiniBand network interfaces sometimes erroneously provide the port
+         * number in the 'dev_id' sysfs attribute instead of 'dev_port', which thus stays initialized as 0. */
+
+        if (fallback_to_dev_id) {
+                unsigned iftype;
+
+                r = device_get_sysattr_unsigned(dev, "type", &iftype);
+                if (r < 0)
+                        return r;
+
+                fallback_to_dev_id = (iftype == ARPHRD_INFINIBAND);
+        }
+
+        if (fallback_to_dev_id)
+                return device_get_sysattr_unsigned(dev, "dev_id", ret);
+
+        /* Otherwise, return the original index 0. */
+        *ret = 0;
+        return 0; /* zero */
+}
+
+static int get_port_specifier(sd_device *dev, bool fallback_to_dev_id, char **ret) {
+        const char *phys_port_name;
+        unsigned dev_port;
+        char *buf;
+        int r;
+
+        assert(dev);
+        assert(ret);
+
+        /* First, try to use the kernel provided front panel port name for multiple port PCI device. */
+        r = sd_device_get_sysattr_value(dev, "phys_port_name", &phys_port_name);
+        if (r >= 0 && !isempty(phys_port_name)) {
+                if (naming_scheme_has(NAMING_SR_IOV_R)) {
+                        int vf_id = -1;
+
+                        /* Check if phys_port_name indicates virtual device representor. */
+                        (void) sscanf(phys_port_name, "pf%*uvf%d", &vf_id);
+
+                        if (vf_id >= 0) {
+                                /* For VF representor append 'r<VF_NUM>'. */
+                                if (asprintf(&buf, "r%d", vf_id) < 0)
+                                        return -ENOMEM;
+
+                                *ret = buf;
+                                return 1;
+                        }
+                }
+
+                /* Otherwise, use phys_port_name as is. */
+                if (asprintf(&buf, "n%s", phys_port_name) < 0)
+                        return -ENOMEM;
+
+                *ret = buf;
+                return 1;
+        }
+
+        /* Then, try to use the kernel provided port index for the case when multiple ports on a single PCI
+         * function. */
+        r = get_dev_port(dev, fallback_to_dev_id, &dev_port);
+        if (r < 0)
+                return r;
+        if (r > 0) {
+                assert(dev_port > 0);
+                if (asprintf(&buf, "d%u", dev_port) < 0)
+                        return -ENOMEM;
+
+                *ret = buf;
+                return 1;
+        }
+
+        *ret = NULL;
+        return 0;
+}
+
+static bool is_valid_onboard_index(unsigned idx) {
         /* Some BIOSes report rubbish indexes that are excessively high (2^24-1 is an index VMware likes to
          * report for example). Let's define a cut-off where we don't consider the index reliable anymore. We
          * pick some arbitrary cut-off, which is somewhere beyond the realistic number of physical network
@@ -148,63 +240,55 @@ static bool is_valid_onboard_index(unsigned long idx) {
         return idx <= (naming_scheme_has(NAMING_16BIT_INDEX) ? ONBOARD_16BIT_INDEX_MAX : ONBOARD_14BIT_INDEX_MAX);
 }
 
-/* retrieve on-board index number and label from firmware */
-static int dev_pci_onboard(sd_device *dev, const LinkInfo *info, NetNames *names) {
-        unsigned long idx, dev_port = 0;
-        const char *attr;
-        size_t l;
-        char *s;
+static int pci_get_onboard_index(sd_device *dev, unsigned *ret) {
+        unsigned idx;
         int r;
 
         assert(dev);
-        assert(info);
-        assert(names);
+        assert(ret);
 
         /* ACPI _DSM — device specific method for naming a PCI or PCI Express device */
-        if (sd_device_get_sysattr_value(names->pcidev, "acpi_index", &attr) >= 0)
-                log_device_debug(names->pcidev, "acpi_index=%s", attr);
-        else {
+        r = device_get_sysattr_unsigned(dev, "acpi_index", &idx);
+        if (r < 0)
                 /* SMBIOS type 41 — Onboard Devices Extended Information */
-                r = sd_device_get_sysattr_value(names->pcidev, "index", &attr);
-                if (r < 0)
-                        return r;
-                log_device_debug(names->pcidev, "index=%s", attr);
-        }
-
-        r = safe_atolu(attr, &idx);
+                r = device_get_sysattr_unsigned(dev, "index", &idx);
         if (r < 0)
-                return log_device_debug_errno(names->pcidev, r,
-                                              "Failed to parse onboard index \"%s\": %m", attr);
+                return r;
+
         if (idx == 0 && !naming_scheme_has(NAMING_ZERO_ACPI_INDEX))
-                return log_device_debug_errno(names->pcidev, SYNTHETIC_ERRNO(EINVAL),
+                return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EINVAL),
                                               "Naming scheme does not allow onboard index==0.");
         if (!is_valid_onboard_index(idx))
-                return log_device_debug_errno(names->pcidev, SYNTHETIC_ERRNO(ENOENT),
-                                              "Not a valid onboard index: %lu", idx);
+                return log_device_debug_errno(dev, SYNTHETIC_ERRNO(ENOENT),
+                                              "Not a valid onboard index: %u", idx);
 
-        /* kernel provided port index for multiple ports on a single PCI function */
-        if (sd_device_get_sysattr_value(dev, "dev_port", &attr) >= 0) {
-                r = safe_atolu_full(attr, 10, &dev_port);
-                if (r < 0)
-                        log_device_debug_errno(dev, r, "Failed to parse dev_port, ignoring: %m");
-                log_device_debug(dev, "dev_port=%lu", dev_port);
-        }
+        *ret = idx;
+        return 0;
+}
 
-        s = names->pci_onboard;
-        l = sizeof(names->pci_onboard);
-        l = strpcpyf(&s, l, "o%lu", idx);
-        if (naming_scheme_has(NAMING_SR_IOV_R) && info->vf_representor_id >= 0)
-                /* For VF representor append 'r<VF_NUM>' and not phys_port_name */
-                l = strpcpyf(&s, l, "r%d", info->vf_representor_id);
-        else if (!isempty(info->phys_port_name))
-                /* kernel provided front panel port name for multiple port PCI device */
-                l = strpcpyf(&s, l, "n%s", info->phys_port_name);
-        else if (dev_port > 0)
-                l = strpcpyf(&s, l, "d%lu", dev_port);
-        if (l == 0)
+static int dev_pci_onboard(sd_device *dev, const LinkInfo *info, NetNames *names) {
+        _cleanup_free_ char *port = NULL;
+        unsigned idx = 0;  /* avoid false maybe-uninitialized warning */
+        int r;
+
+        assert(dev);
+        assert(info);
+        assert(names);
+
+        /* retrieve on-board index number and label from firmware */
+        r = pci_get_onboard_index(names->pcidev, &idx);
+        if (r < 0)
+                return r;
+
+        r = get_port_specifier(dev, /* fallback_to_dev_id = */ false, &port);
+        if (r < 0)
+                return r;
+
+        if (!snprintf_ok(names->pci_onboard, sizeof(names->pci_onboard), "o%u%s", idx, strempty(port)))
                 names->pci_onboard[0] = '\0';
-        log_device_debug(dev, "Onboard index identifier: index=%lu phys_port=%s dev_port=%lu %s %s",
-                         idx, strempty(info->phys_port_name), dev_port,
+
+        log_device_debug(dev, "Onboard index identifier: index=%u port=%s %s %s",
+                         idx, strna(port),
                          special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), empty_to_na(names->pci_onboard));
 
         if (sd_device_get_sysattr_value(names->pcidev, "label", &names->pci_onboard_label) >= 0)
@@ -320,180 +404,206 @@ static int parse_hotplug_slot_from_function_id(sd_device *dev, int slots_dirfd,
         return 1; /* Found. We should ignore domain part. */
 }
 
-static int dev_pci_slot(sd_device *dev, const LinkInfo *info, NetNames *names) {
-        const char *sysname, *attr;
-        _cleanup_(sd_device_unrefp) sd_device *pci = NULL;
-        _cleanup_closedir_ DIR *dir = NULL;
-        unsigned domain, bus, slot, func;
-        sd_device *hotplug_slot_dev;
-        unsigned long dev_port = 0;
-        uint32_t hotplug_slot = 0;
-        size_t l;
-        char *s;
+static int pci_get_hotplug_slot_from_address(
+                sd_device *dev,
+                sd_device *pci,
+                DIR *dir,
+                uint32_t *ret) {
+
+        const char *sysname;
         int r;
 
         assert(dev);
-        assert(info);
-        assert(names);
+        assert(pci);
+        assert(dir);
+        assert(ret);
 
-        r = sd_device_get_sysname(names->pcidev, &sysname);
+        r = sd_device_get_sysname(dev, &sysname);
         if (r < 0)
-                return log_device_debug_errno(names->pcidev, r, "Failed to get sysname: %m");
+                return log_device_debug_errno(dev, r, "Failed to get sysname: %m");
 
-        r = sscanf(sysname, "%x:%x:%x.%u", &domain, &bus, &slot, &func);
-        log_device_debug(dev, "Parsing slot information from PCI device sysname \"%s\": %s",
-                         sysname, r == 4 ? "success" : "failure");
-        if (r != 4)
-                return -ENOENT;
+        rewinddir(dir);
+        FOREACH_DIRENT_ALL(de, dir, break) {
+                _cleanup_free_ char *path = NULL;
+                const char *address;
+                uint32_t slot;
 
-        if (naming_scheme_has(NAMING_NPAR_ARI) &&
-            is_pci_ari_enabled(names->pcidev))
-                /* ARI devices support up to 256 functions on a single device ("slot"), and interpret the
-                 * traditional 5-bit slot and 3-bit function number as a single 8-bit function number,
-                 * where the slot makes up the upper 5 bits. */
-                func += slot * 8;
+                if (dot_or_dot_dot(de->d_name))
+                        continue;
+
+                if (de->d_type != DT_DIR)
+                        continue;
 
-        /* kernel provided port index for multiple ports on a single PCI function */
-        if (sd_device_get_sysattr_value(dev, "dev_port", &attr) >= 0) {
-                log_device_debug(dev, "dev_port=%s", attr);
+                r = safe_atou32(de->d_name, &slot);
+                if (r < 0 || slot <= 0)
+                        continue;
 
-                r = safe_atolu_full(attr, 10, &dev_port);
-                if (r < 0)
-                        log_device_debug_errno(dev, r, "Failed to parse attribute dev_port, ignoring: %m");
+                path = path_join("slots", de->d_name, "address");
+                if (!path)
+                        return -ENOMEM;
 
-                /* With older kernels IP-over-InfiniBand network interfaces sometimes erroneously
-                 * provide the port number in the 'dev_id' sysfs attribute instead of 'dev_port',
-                 * which thus stays initialized as 0. */
-                if (dev_port == 0 &&
-                    info->iftype == ARPHRD_INFINIBAND &&
-                    sd_device_get_sysattr_value(dev, "dev_id", &attr) >= 0) {
-                        log_device_debug(dev, "dev_id=%s", attr);
+                if (sd_device_get_sysattr_value(pci, path, &address) < 0)
+                        continue;
 
-                        r = safe_atolu_full(attr, 10, &dev_port);
-                        if (r < 0)
-                                log_device_debug_errno(dev, r, "Failed to parse attribute dev_id, ignoring: %m");
-                }
+                /* match slot address with device by stripping the function */
+                if (!startswith(sysname, address))
+                        continue;
+
+                *ret = slot;
+                return 1; /* found */
         }
 
-        /* compose a name based on the raw kernel's PCI bus, slot numbers */
-        s = names->pci_path;
-        l = sizeof(names->pci_path);
-        if (domain > 0)
-                l = strpcpyf(&s, l, "P%u", domain);
-        l = strpcpyf(&s, l, "p%us%u", bus, slot);
-        if (func > 0 || is_pci_multifunction(names->pcidev) > 0)
-                l = strpcpyf(&s, l, "f%u", func);
-        if (naming_scheme_has(NAMING_SR_IOV_R) && info->vf_representor_id >= 0)
-                /* For VF representor append 'r<VF_NUM>' and not phys_port_name */
-                l = strpcpyf(&s, l, "r%d", info->vf_representor_id);
-        else if (!isempty(info->phys_port_name))
-                /* kernel provided front panel port name for multi-port PCI device */
-                l = strpcpyf(&s, l, "n%s", info->phys_port_name);
-        else if (dev_port > 0)
-                l = strpcpyf(&s, l, "d%lu", dev_port);
-        if (l == 0)
-                names->pci_path[0] = '\0';
+        *ret = 0;
+        return 0; /* not found */
+}
 
-        log_device_debug(dev, "PCI path identifier: domain=%u bus=%u slot=%u func=%u phys_port=%s dev_port=%lu %s %s",
-                         domain, bus, slot, func, strempty(info->phys_port_name), dev_port,
-                         special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), empty_to_na(names->pci_path));
+static int pci_get_hotplug_slot(sd_device *dev, uint32_t *ret) {
+        _cleanup_(sd_device_unrefp) sd_device *pci = NULL;
+        _cleanup_closedir_ DIR *dir = NULL;
+        int r;
+
+        assert(dev);
+        assert(ret);
 
         /* ACPI _SUN — slot user number */
         r = sd_device_new_from_subsystem_sysname(&pci, "subsystem", "pci");
         if (r < 0)
-                return log_debug_errno(r, "sd_device_new_from_subsystem_sysname() failed: %m");
+                return log_debug_errno(r, "Failed to create sd_device object for pci subsystem: %m");
 
         r = device_opendir(pci, "slots", &dir);
         if (r < 0)
-                return log_device_debug_errno(dev, r, "Cannot access 'slots' subdirectory: %m");
+                return log_device_debug_errno(dev, r, "Cannot open 'slots' subdirectory: %m");
+
+        for (sd_device *slot_dev = dev; slot_dev; ) {
+                uint32_t slot = 0;  /* avoid false maybe-uninitialized warning */
 
-        hotplug_slot_dev = names->pcidev;
-        while (hotplug_slot_dev) {
-                r = parse_hotplug_slot_from_function_id(hotplug_slot_dev, dirfd(dir), &hotplug_slot);
+                r = parse_hotplug_slot_from_function_id(slot_dev, dirfd(dir), &slot);
                 if (r < 0)
-                        return 0;
+                        return r;
                 if (r > 0) {
-                        domain = 0; /* See comments in parse_hotplug_slot_from_function_id(). */
-                        break;
+                        *ret = slot;
+                        return 1; /* domain should be ignored. */
                 }
 
-                r = sd_device_get_sysname(hotplug_slot_dev, &sysname);
+                r = pci_get_hotplug_slot_from_address(slot_dev, pci, dir, &slot);
                 if (r < 0)
-                        return log_device_debug_errno(hotplug_slot_dev, r, "Failed to get sysname: %m");
+                        return r;
+                if (r > 0) {
+                        /* We found the match between PCI device and slot. However, we won't use the slot
+                         * index if the device is a PCI bridge, because it can have other child devices that
+                         * will try to claim the same index and that would create name collision. */
+                        if (naming_scheme_has(NAMING_BRIDGE_NO_SLOT) && is_pci_bridge(slot_dev)) {
+                                if (naming_scheme_has(NAMING_BRIDGE_MULTIFUNCTION_SLOT) && is_pci_multifunction(dev) <= 0)
+                                        return log_device_debug_errno(dev, SYNTHETIC_ERRNO(ESTALE),
+                                                                      "Not using slot information because the PCI device associated with "
+                                                                      "the hotplug slot is a bridge and the PCI device has a single function.");
+
+                                if (!naming_scheme_has(NAMING_BRIDGE_MULTIFUNCTION_SLOT))
+                                        return log_device_debug_errno(dev, SYNTHETIC_ERRNO(ESTALE),
+                                                                      "Not using slot information because the PCI device is a bridge.");
+                        }
 
-                FOREACH_DIRENT_ALL(de, dir, break) {
-                        _cleanup_free_ char *path = NULL;
-                        const char *address;
-                        uint32_t i;
+                        *ret = slot;
+                        return 0; /* domain can be still used. */
+                }
 
-                        if (dot_or_dot_dot(de->d_name))
-                                continue;
+                if (sd_device_get_parent_with_subsystem_devtype(slot_dev, "pci", NULL, &slot_dev) < 0)
+                        break;
+        }
 
-                        r = safe_atou32(de->d_name, &i);
-                        if (r < 0 || i <= 0)
-                                continue;
+        return -ENOENT;
+}
 
-                        path = path_join("slots", de->d_name, "address");
-                        if (!path)
-                                return -ENOMEM;
+static int get_pci_slot_specifiers(
+                sd_device *dev,
+                char **ret_domain,
+                char **ret_bus_and_slot,
+                char **ret_func) {
 
-                        if (sd_device_get_sysattr_value(pci, path, &address) < 0)
-                                continue;
+        _cleanup_free_ char *domain_spec = NULL, *bus_and_slot_spec = NULL, *func_spec = NULL;
+        unsigned domain, bus, slot, func;
+        const char *sysname;
+        int r;
 
-                        /* match slot address with device by stripping the function */
-                        if (!startswith(sysname, address))
-                                continue;
+        assert(dev);
+        assert(ret_domain);
+        assert(ret_bus_and_slot);
+        assert(ret_func);
 
-                        hotplug_slot = i;
+        r = sd_device_get_sysname(dev, &sysname);
+        if (r < 0)
+                return log_device_debug_errno(dev, r, "Failed to get sysname: %m");
 
-                        /* We found the match between PCI device and slot. However, we won't use the slot
-                         * index if the device is a PCI bridge, because it can have other child devices that
-                         * will try to claim the same index and that would create name collision. */
-                        if (naming_scheme_has(NAMING_BRIDGE_NO_SLOT) && is_pci_bridge(hotplug_slot_dev)) {
-                                if (naming_scheme_has(NAMING_BRIDGE_MULTIFUNCTION_SLOT) && is_pci_multifunction(names->pcidev) <= 0) {
-                                        log_device_debug(dev,
-                                                         "Not using slot information because the PCI device associated with "
-                                                         "the hotplug slot is a bridge and the PCI device has a single function.");
-                                        return 0;
-                                }
-
-                                if (!naming_scheme_has(NAMING_BRIDGE_MULTIFUNCTION_SLOT)) {
-                                        log_device_debug(dev, "Not using slot information because the PCI device is a bridge.");
-                                        return 0;
-                                }
-                        }
+        r = sscanf(sysname, "%x:%x:%x.%u", &domain, &bus, &slot, &func);
+        log_device_debug(dev, "Parsing slot information from PCI device sysname \"%s\": %s",
+                         sysname, r == 4 ? "success" : "failure");
+        if (r != 4)
+                return -EINVAL;
 
-                        break;
-                }
-                if (hotplug_slot > 0)
-                        break;
-                if (sd_device_get_parent_with_subsystem_devtype(hotplug_slot_dev, "pci", NULL, &hotplug_slot_dev) < 0)
-                        break;
-                rewinddir(dir);
-        }
+        if (naming_scheme_has(NAMING_NPAR_ARI) &&
+            is_pci_ari_enabled(dev))
+                /* ARI devices support up to 256 functions on a single device ("slot"), and interpret the
+                 * traditional 5-bit slot and 3-bit function number as a single 8-bit function number,
+                 * where the slot makes up the upper 5 bits. */
+                func += slot * 8;
 
-        if (hotplug_slot > 0) {
-                s = names->pci_slot;
-                l = sizeof(names->pci_slot);
-                if (domain > 0)
-                        l = strpcpyf(&s, l, "P%u", domain);
-                l = strpcpyf(&s, l, "s%"PRIu32, hotplug_slot);
-                if (func > 0 || is_pci_multifunction(names->pcidev) > 0)
-                        l = strpcpyf(&s, l, "f%u", func);
-                if (naming_scheme_has(NAMING_SR_IOV_R) && info->vf_representor_id >= 0)
-                        /* For VF representor append 'r<VF_NUM>' and not phys_port_name */
-                        l = strpcpyf(&s, l, "r%d", info->vf_representor_id);
-                else if (!isempty(info->phys_port_name))
-                        l = strpcpyf(&s, l, "n%s", info->phys_port_name);
-                else if (dev_port > 0)
-                        l = strpcpyf(&s, l, "d%lu", dev_port);
-                if (l == 0)
-                        names->pci_slot[0] = '\0';
-
-                log_device_debug(dev, "Slot identifier: domain=%u slot=%"PRIu32" func=%u phys_port=%s dev_port=%lu %s %s",
-                                 domain, hotplug_slot, func, strempty(info->phys_port_name), dev_port,
-                                 special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), empty_to_na(names->pci_slot));
-        }
+        if (domain > 0 && asprintf(&domain_spec, "P%u", domain) < 0)
+                return -ENOMEM;
+
+        if (asprintf(&bus_and_slot_spec, "p%us%u", bus, slot) < 0)
+                return -ENOMEM;
+
+        if ((func > 0 || is_pci_multifunction(dev) > 0) &&
+            asprintf(&func_spec, "f%u", func) < 0)
+                return -ENOMEM;
+
+        *ret_domain = TAKE_PTR(domain_spec);
+        *ret_bus_and_slot = TAKE_PTR(bus_and_slot_spec);
+        *ret_func = TAKE_PTR(func_spec);
+        return 0;
+}
+
+static int dev_pci_slot(sd_device *dev, const LinkInfo *info, NetNames *names) {
+        _cleanup_free_ char *domain = NULL, *bus_and_slot = NULL, *func = NULL, *port = NULL;
+        uint32_t hotplug_slot = 0;  /* avoid false maybe-uninitialized warning */
+        int r;
+
+        assert(dev);
+        assert(info);
+        assert(names);
+
+        r = get_pci_slot_specifiers(names->pcidev, &domain, &bus_and_slot, &func);
+        if (r < 0)
+                return r;
+
+        r = get_port_specifier(dev, /* fallback_to_dev_id = */ true, &port);
+        if (r < 0)
+                return r;
+
+        /* compose a name based on the raw kernel's PCI bus, slot numbers */
+        if (!snprintf_ok(names->pci_path, sizeof(names->pci_path), "%s%s%s%s",
+                         strempty(domain), bus_and_slot, strempty(func), strempty(port)))
+                names->pci_path[0] = '\0';
+
+        log_device_debug(dev, "PCI path identifier: domain=%s bus_and_slot=%s func=%s port=%s %s %s",
+                         strna(domain), bus_and_slot, strna(func), strna(port),
+                         special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), empty_to_na(names->pci_path));
+
+        r = pci_get_hotplug_slot(names->pcidev, &hotplug_slot);
+        if (r < 0)
+                return r;
+        if (r > 0)
+                /* If the hotplug slot is found through the function ID, then drop the domain from the name.
+                 * See comments in parse_hotplug_slot_from_function_id(). */
+                domain = mfree(domain);
+
+        if (!snprintf_ok(names->pci_slot, sizeof(names->pci_slot), "%ss%"PRIu32"%s%s",
+                         strempty(domain), hotplug_slot, strempty(func), strempty(port)))
+                names->pci_slot[0] = '\0';
+
+        log_device_debug(dev, "Slot identifier: domain=%s slot=%"PRIu32" func=%s port=%s %s %s",
+                         strna(domain), hotplug_slot, strna(func), strna(port),
+                         special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), empty_to_na(names->pci_slot));
 
         return 0;
 }
@@ -1198,11 +1308,6 @@ static int get_link_info(sd_device *dev, LinkInfo *info) {
         if (r < 0)
                 return r;
 
-        r = sd_device_get_sysattr_value(dev, "phys_port_name", &info->phys_port_name);
-        if (r >= 0)
-                /* Check if phys_port_name indicates virtual device representor */
-                (void) sscanf(info->phys_port_name, "pf%*uvf%d", &info->vf_representor_id);
-
         return 0;
 }
 
@@ -1210,9 +1315,7 @@ static int builtin_net_id(UdevEvent *event, int argc, char *argv[], bool test) {
         sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
         const char *prefix;
         NetNames names = {};
-        LinkInfo info = {
-                .vf_representor_id = -1,
-        };
+        LinkInfo info = {};
         int r;
 
         r = get_link_info(dev, &info);
index 13e40bd82ab9aa6290c73d16b4dfc65f2c9f48e3..f90c3b1b4efa09f0ecd8583db0d5d23a442708f5 100755 (executable)
@@ -132,6 +132,9 @@ EOF
 Type=home
 Label=home-first
 Label=home-always-too-long-xxxxxxxxxxxxxx-%v
+# Test that OEM=yes makes sure that a partition is OEM even if FactoryReset=yes is set.
+FactoryReset=yes
+OEM=yes
 EOF
 
     tee "$defs/swap.conf" <<EOF
@@ -139,6 +142,8 @@ EOF
 Type=swap
 SizeMaxBytes=64M
 PaddingMinBytes=92M
+# No OEM=yes here so this should not be considered an OEM partition since FactoryReset=yes.
+FactoryReset=yes
 EOF
 
     systemd-repart --offline="$OFFLINE" \
@@ -160,6 +165,26 @@ last-lba: 2097118
 $imgs/zzz1 : start=        2048, size=     1775576, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\"
 $imgs/zzz2 : start=     1777624, size=      131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=78C92DB8-3D2B-4823-B0DC-792B78F66F1E, name=\"swap\""
 
+    systemd-repart --offline="$OFFLINE" \
+                   --definitions="$defs" \
+                   --dry-run=no \
+                   --seed="$seed" \
+                   --empty=force \
+                   --include-partitions=home,swap \
+                   --oem=yes \
+                   --offline="$OFFLINE" \
+                   "$imgs/zzz"
+
+    output=$(sfdisk -d "$imgs/zzz" | grep -v -e 'sector-size' -e '^$')
+
+    assert_eq "$output" "label: gpt
+label-id: 1D2CE291-7CCE-4F7D-BC83-FDB49AD74EBD
+device: $imgs/zzz
+unit: sectors
+first-lba: 2048
+last-lba: 2097118
+$imgs/zzz1 : start=        2048, size=     2095064, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\""
+
     systemd-repart --offline="$OFFLINE" \
                    --definitions="$defs" \
                    --dry-run=no \
@@ -268,6 +293,9 @@ Type=linux-generic
 Label=block-copy
 UUID=2a1d97e1d0a346cca26eadc643926617
 CopyBlocks=$imgs/block-copy
+# Test that these are ignored
+CopyFiles=abc
+Format=ext4
 EOF
 
     systemd-repart --offline="$OFFLINE" \
@@ -903,6 +931,8 @@ CopyFiles=/
 CopyFiles=/zzz:/
 CopyFiles=/:/oiu
 ExcludeFilesTarget=/oiu/usr
+# Test that this is just ignored
+CopyBlocks=auto
 EOF
 
     tee "$defs/10-usr.conf" <<EOF
index b1322a159befd3c380939967c9220fd84a6dec09..bf10fa0b93728693e467e875223bb28645b94a85 100644 (file)
@@ -30,6 +30,7 @@ Before=shutdown.target initrd-switch-root.target
 Type=oneshot
 RemainAfterExit=yes
 ExecStart={{BINDIR}}/systemd-repart --dry-run=no
+ImportCredential=repart.*
 
 # The tool returns 77 if there's no existing GPT partition table
 SuccessExitStatus=77