]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
conf-parser: return mtime in config_parse() and friends 16048/head
authorLennart Poettering <lennart@poettering.net>
Tue, 2 Jun 2020 12:55:12 +0000 (14:55 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 2 Jun 2020 17:32:20 +0000 (19:32 +0200)
This is a follow-up for 9f83091e3cceb646a66fa9df89de6d9a77c21d86.

Instead of reading the mtime off the configuration files after reading,
let's do so before reading, but with the fd we read the data from. This
is not only cleaner (as it allows us to save one stat()), but also has
the benefit that we'll detect changes that happen while we read the
files.

This also reworks unit file drop-ins to use the common code for
determining drop-in mtime, instead of reading system clock for that.

27 files changed:
src/core/load-dropin.c
src/core/load-fragment.c
src/core/main.c
src/coredump/coredump.c
src/fuzz/fuzz-unit-file.c
src/home/homed-conf.c
src/journal-remote/journal-remote-main.c
src/journal-remote/journal-upload.c
src/journal/journald-server.c
src/login/logind-core.c
src/network/netdev/netdev.c
src/network/networkd-conf.c
src/network/networkd-network.c
src/nspawn/nspawn-settings.c
src/partition/repart.c
src/pstore/pstore.c
src/resolve/resolved-conf.c
src/resolve/resolved-dnssd.c
src/shared/conf-parser.c
src/shared/conf-parser.h
src/shared/install.c
src/shared/sleep-config.c
src/test/test-conf-parser.c
src/timesync/timesyncd-conf.c
src/tty-ask-password-agent/tty-ask-password-agent.c
src/udev/net/link-config.c
src/xdg-autostart-generator/xdg-autostart-service.c

index f61e9da6f281d2deaad55f11ba869424ed555a09..0da3eafb12947e25e2dbd4a80a75549699cc9e7a 100644 (file)
@@ -114,12 +114,13 @@ int unit_load_dropin(Unit *u) {
         }
 
         STRV_FOREACH(f, u->dropin_paths)
-                (void) config_parse(u->id, *f, NULL,
-                                    UNIT_VTABLE(u)->sections,
-                                    config_item_perf_lookup, load_fragment_gperf_lookup,
-                                    0, u);
-
-        u->dropin_mtime = now(CLOCK_REALTIME);
+                (void) config_parse(
+                                u->id, *f, NULL,
+                                UNIT_VTABLE(u)->sections,
+                                config_item_perf_lookup, load_fragment_gperf_lookup,
+                                0,
+                                u,
+                                &u->dropin_mtime);
 
         return 0;
 }
index a967627946c716b38337cc137d7df75f8e69c746..780692ce0eb2d4cfd8daee3baae7948775ead26a 100644 (file)
@@ -4864,7 +4864,9 @@ int unit_load_fragment(Unit *u) {
                         r = config_parse(u->id, fragment, f,
                                          UNIT_VTABLE(u)->sections,
                                          config_item_perf_lookup, load_fragment_gperf_lookup,
-                                         CONFIG_PARSE_ALLOW_INCLUDE, u);
+                                         CONFIG_PARSE_ALLOW_INCLUDE,
+                                         u,
+                                         NULL);
                         if (r == -ENOEXEC)
                                 log_unit_notice_errno(u, r, "Unit configuration has fatal error, unit will not be started.");
                         if (r < 0)
index 32b963d4a4f88b20e1a5e6630ba3a1942a3881ad..e1de821e665401907d75544938c0f1f11d7cedc9 100644 (file)
@@ -657,7 +657,13 @@ static int parse_config_file(void) {
                 CONF_PATHS_NULSTR("systemd/system.conf.d") :
                 CONF_PATHS_NULSTR("systemd/user.conf.d");
 
-        (void) config_parse_many_nulstr(fn, conf_dirs_nulstr, "Manager\0", config_item_table_lookup, items, CONFIG_PARSE_WARN, NULL);
+        (void) config_parse_many_nulstr(
+                        fn, conf_dirs_nulstr,
+                        "Manager\0",
+                        config_item_table_lookup, items,
+                        CONFIG_PARSE_WARN,
+                        NULL,
+                        NULL);
 
         /* Traditionally "0" was used to turn off the default unit timeouts. Fix this up so that we used USEC_INFINITY
          * like everywhere else. */
index 42231dbd6b679d05205849690ee71491051bc3cc..d156d98efcd41b3ddf07bc4c2d7ba5d66a8263b8 100644 (file)
@@ -155,11 +155,14 @@ static int parse_config(void) {
                 {}
         };
 
-        return config_parse_many_nulstr(PKGSYSCONFDIR "/coredump.conf",
-                                        CONF_PATHS_NULSTR("systemd/coredump.conf.d"),
-                                        "Coredump\0",
-                                        config_item_table_lookup, items,
-                                        CONFIG_PARSE_WARN, NULL);
+        return config_parse_many_nulstr(
+                        PKGSYSCONFDIR "/coredump.conf",
+                        CONF_PATHS_NULSTR("systemd/coredump.conf.d"),
+                        "Coredump\0",
+                        config_item_table_lookup, items,
+                        CONFIG_PARSE_WARN,
+                        NULL,
+                        NULL);
 }
 
 static uint64_t storage_size_max(void) {
index d3993cf123f67c93f1a9f041e525a943c1c68295..34f59a44372c4b07eb5d1d8cfa28e85a35a6f88f 100644 (file)
@@ -70,10 +70,13 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
         name = strjoina("a.", unit_type_to_string(t));
         assert_se(unit_new_for_name(m, unit_vtable[t]->object_size, name, &u) >= 0);
 
-        (void) config_parse(name, name, f,
-                            UNIT_VTABLE(u)->sections,
-                            config_item_perf_lookup, load_fragment_gperf_lookup,
-                            CONFIG_PARSE_ALLOW_INCLUDE, u);
+        (void) config_parse(
+                        name, name, f,
+                        UNIT_VTABLE(u)->sections,
+                        config_item_perf_lookup, load_fragment_gperf_lookup,
+                        CONFIG_PARSE_ALLOW_INCLUDE,
+                        u,
+                        NULL);
 
         g = open_memstream_unlocked(&out, &out_size);
         assert_se(g);
index 14ec8b336d48eb84c6449592ce758284d9c6f9e5..df3a17358bb7b8c33f572b15f591e996c995c670 100644 (file)
@@ -10,11 +10,14 @@ int manager_parse_config_file(Manager *m) {
 
         assert(m);
 
-        r = config_parse_many_nulstr(PKGSYSCONFDIR "/homed.conf",
-                                     CONF_PATHS_NULSTR("systemd/homed.conf.d"),
-                                     "Home\0",
-                                     config_item_perf_lookup, homed_gperf_lookup,
-                                     CONFIG_PARSE_WARN, m);
+        r = config_parse_many_nulstr(
+                        PKGSYSCONFDIR "/homed.conf",
+                        CONF_PATHS_NULSTR("systemd/homed.conf.d"),
+                        "Home\0",
+                        config_item_perf_lookup, homed_gperf_lookup,
+                        CONFIG_PARSE_WARN,
+                        m,
+                        NULL);
         if (r < 0)
                 return r;
 
index 551b84130dd34ac521d14f68f01dce9a6d7c5ca8..948b2d2fce60583117021410966d2859aec6a782 100644 (file)
@@ -762,10 +762,14 @@ static int parse_config(void) {
                 {}
         };
 
-        return config_parse_many_nulstr(PKGSYSCONFDIR "/journal-remote.conf",
-                                        CONF_PATHS_NULSTR("systemd/journal-remote.conf.d"),
-                                        "Remote\0", config_item_table_lookup, items,
-                                        CONFIG_PARSE_WARN, NULL);
+        return config_parse_many_nulstr(
+                        PKGSYSCONFDIR "/journal-remote.conf",
+                        CONF_PATHS_NULSTR("systemd/journal-remote.conf.d"),
+                        "Remote\0",
+                        config_item_table_lookup, items,
+                        CONFIG_PARSE_WARN,
+                        NULL,
+                        NULL);
 }
 
 static int help(void) {
index bf656ac670617c7ff740450c73ef30d168b1ee0d..bd58fdbcdfb7f0ee3263998513776b93a3c1b290 100644 (file)
@@ -562,12 +562,17 @@ static int parse_config(void) {
                 { "Upload",  "ServerKeyFile",          config_parse_path_or_ignore, 0, &arg_key    },
                 { "Upload",  "ServerCertificateFile",  config_parse_path_or_ignore, 0, &arg_cert   },
                 { "Upload",  "TrustedCertificateFile", config_parse_path_or_ignore, 0, &arg_trust  },
-                {}};
+                {}
+        };
 
-        return config_parse_many_nulstr(PKGSYSCONFDIR "/journal-upload.conf",
-                                        CONF_PATHS_NULSTR("systemd/journal-upload.conf.d"),
-                                        "Upload\0", config_item_table_lookup, items,
-                                        CONFIG_PARSE_WARN, NULL);
+        return config_parse_many_nulstr(
+                        PKGSYSCONFDIR "/journal-upload.conf",
+                        CONF_PATHS_NULSTR("systemd/journal-upload.conf.d"),
+                        "Upload\0",
+                        config_item_table_lookup, items,
+                        CONFIG_PARSE_WARN,
+                        NULL,
+                        NULL);
 }
 
 static int help(void) {
index 9efa65a29427d88882b567411edda70218431e50..5865bf980962e7a73b7608fd54afcb090b61ff80 100644 (file)
@@ -1633,23 +1633,24 @@ static int server_parse_config_file(Server *s) {
                 /* If we are running in namespace mode, load the namespace specific configuration file, and nothing else */
                 namespaced = strjoina(PKGSYSCONFDIR "/journald@", s->namespace, ".conf");
 
-                r = config_parse(
-                                NULL,
-                                namespaced, NULL,
-                                "Journal\0",
-                                config_item_perf_lookup, journald_gperf_lookup,
-                                CONFIG_PARSE_WARN, s);
+                r = config_parse(NULL,
+                                 namespaced, NULL,
+                                 "Journal\0",
+                                 config_item_perf_lookup, journald_gperf_lookup,
+                                 CONFIG_PARSE_WARN, s,
+                                 NULL);
                 if (r < 0)
                         return r;
 
                 return 0;
         }
 
-        return config_parse_many_nulstr(PKGSYSCONFDIR "/journald.conf",
-                                        CONF_PATHS_NULSTR("systemd/journald.conf.d"),
-                                        "Journal\0",
-                                        config_item_perf_lookup, journald_gperf_lookup,
-                                        CONFIG_PARSE_WARN, s);
+        return config_parse_many_nulstr(
+                        PKGSYSCONFDIR "/journald.conf",
+                        CONF_PATHS_NULSTR("systemd/journald.conf.d"),
+                        "Journal\0",
+                        config_item_perf_lookup, journald_gperf_lookup,
+                        CONFIG_PARSE_WARN, s, NULL);
 }
 
 static int server_dispatch_sync(sd_event_source *es, usec_t t, void *userdata) {
index 1375f438e4be893885859cf84d50e4534a88d9e6..4289461df6872fa602e3a691c8cc705f7a5df744 100644 (file)
@@ -69,11 +69,13 @@ void manager_reset_config(Manager *m) {
 int manager_parse_config_file(Manager *m) {
         assert(m);
 
-        return config_parse_many_nulstr(PKGSYSCONFDIR "/logind.conf",
-                                        CONF_PATHS_NULSTR("systemd/logind.conf.d"),
-                                        "Login\0",
-                                        config_item_perf_lookup, logind_gperf_lookup,
-                                        CONFIG_PARSE_WARN, m);
+        return config_parse_many_nulstr(
+                        PKGSYSCONFDIR "/logind.conf",
+                        CONF_PATHS_NULSTR("systemd/logind.conf.d"),
+                        "Login\0",
+                        config_item_perf_lookup, logind_gperf_lookup,
+                        CONFIG_PARSE_WARN, m,
+                        NULL);
 }
 
 int manager_add_device(Manager *m, const char *sysfs, bool master, Device **ret_device) {
index a990c64b55f6af64c7ca736078125b2315ce74f8..1889f6f13c9073f1767fd9c9aa1c5103a4fe524f 100644 (file)
@@ -686,10 +686,13 @@ int netdev_load_one(Manager *manager, const char *filename) {
         };
 
         dropin_dirname = strjoina(basename(filename), ".d");
-        r = config_parse_many(filename, NETWORK_DIRS, dropin_dirname,
-                              NETDEV_COMMON_SECTIONS NETDEV_OTHER_SECTIONS,
-                              config_item_perf_lookup, network_netdev_gperf_lookup,
-                              CONFIG_PARSE_WARN, netdev_raw, NULL);
+        r = config_parse_many(
+                        filename, NETWORK_DIRS, dropin_dirname,
+                        NETDEV_COMMON_SECTIONS NETDEV_OTHER_SECTIONS,
+                        config_item_perf_lookup, network_netdev_gperf_lookup,
+                        CONFIG_PARSE_WARN,
+                        netdev_raw,
+                        NULL);
         if (r < 0)
                 return r;
 
@@ -726,10 +729,12 @@ int netdev_load_one(Manager *manager, const char *filename) {
         if (NETDEV_VTABLE(netdev)->init)
                 NETDEV_VTABLE(netdev)->init(netdev);
 
-        r = config_parse_many(filename, NETWORK_DIRS, dropin_dirname,
-                              NETDEV_VTABLE(netdev)->sections,
-                              config_item_perf_lookup, network_netdev_gperf_lookup,
-                              CONFIG_PARSE_WARN, netdev, NULL);
+        r = config_parse_many(
+                        filename, NETWORK_DIRS, dropin_dirname,
+                        NETDEV_VTABLE(netdev)->sections,
+                        config_item_perf_lookup, network_netdev_gperf_lookup,
+                        CONFIG_PARSE_WARN,
+                        netdev, NULL);
         if (r < 0)
                 return r;
 
index 350fea634c6741056dbd80267ba0ff941d4dbebc..30625117e40fba3b5c258fa58f9bb366033a618e 100644 (file)
@@ -23,11 +23,15 @@ int manager_parse_config_file(Manager *m) {
 
         assert(m);
 
-        r = config_parse_many_nulstr(PKGSYSCONFDIR "/networkd.conf",
-                                     CONF_PATHS_NULSTR("systemd/networkd.conf.d"),
-                                     "Network\0DHCP\0",
-                                     config_item_perf_lookup, networkd_gperf_lookup,
-                                     CONFIG_PARSE_WARN, m);
+        r = config_parse_many_nulstr(
+                        PKGSYSCONFDIR "/networkd.conf",
+                        CONF_PATHS_NULSTR("systemd/networkd.conf.d"),
+                        "Network\0"
+                        "DHCP\0",
+                        config_item_perf_lookup, networkd_gperf_lookup,
+                        CONFIG_PARSE_WARN,
+                        m,
+                        NULL);
         if (r < 0)
                 return r;
 
index b928f7585c39ff4a2171c4598cc18a07cbd00b6e..50e50fd945b44a6b1707876601ddf4e427132b40 100644 (file)
@@ -335,7 +335,6 @@ int network_verify(Network *network) {
 int network_load_one(Manager *manager, OrderedHashmap **networks, const char *filename) {
         _cleanup_free_ char *fname = NULL, *name = NULL;
         _cleanup_(network_unrefp) Network *network = NULL;
-        _cleanup_strv_free_ char **dropins = NULL;
         _cleanup_fclose_ FILE *file = NULL;
         const char *dropin_dirname;
         char *d;
@@ -477,54 +476,57 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
                 .ip_service_type = -1,
         };
 
-        r = config_parse_many(filename, NETWORK_DIRS, dropin_dirname,
-                              "Match\0"
-                              "Link\0"
-                              "Network\0"
-                              "Address\0"
-                              "Neighbor\0"
-                              "IPv6AddressLabel\0"
-                              "RoutingPolicyRule\0"
-                              "Route\0"
-                              "NextHop\0"
-                              "DHCP\0" /* compat */
-                              "DHCPv4\0"
-                              "DHCPv6\0"
-                              "DHCPServer\0"
-                              "IPv6AcceptRA\0"
-                              "IPv6NDPProxyAddress\0"
-                              "Bridge\0"
-                              "BridgeFDB\0"
-                              "BridgeVLAN\0"
-                              "IPv6PrefixDelegation\0"
-                              "IPv6Prefix\0"
-                              "IPv6RoutePrefix\0"
-                              "LLDP\0"
-                              "TrafficControlQueueingDiscipline\0"
-                              "CAN\0"
-                              "QDisc\0"
-                              "BFIFO\0"
-                              "CAKE\0"
-                              "ControlledDelay\0"
-                              "DeficitRoundRobinScheduler\0"
-                              "DeficitRoundRobinSchedulerClass\0"
-                              "PFIFO\0"
-                              "PFIFOFast\0"
-                              "PFIFOHeadDrop\0"
-                              "FairQueueing\0"
-                              "FairQueueingControlledDelay\0"
-                              "GenericRandomEarlyDetection\0"
-                              "HeavyHitterFilter\0"
-                              "HierarchyTokenBucket\0"
-                              "HierarchyTokenBucketClass\0"
-                              "NetworkEmulator\0"
-                              "PIE\0"
-                              "StochasticFairBlue\0"
-                              "StochasticFairnessQueueing\0"
-                              "TokenBucketFilter\0"
-                              "TrivialLinkEqualizer\0",
-                              config_item_perf_lookup, network_network_gperf_lookup,
-                              CONFIG_PARSE_WARN, network, &dropins);
+        r = config_parse_many(
+                        filename, NETWORK_DIRS, dropin_dirname,
+                        "Match\0"
+                        "Link\0"
+                        "Network\0"
+                        "Address\0"
+                        "Neighbor\0"
+                        "IPv6AddressLabel\0"
+                        "RoutingPolicyRule\0"
+                        "Route\0"
+                        "NextHop\0"
+                        "DHCP\0" /* compat */
+                        "DHCPv4\0"
+                        "DHCPv6\0"
+                        "DHCPServer\0"
+                        "IPv6AcceptRA\0"
+                        "IPv6NDPProxyAddress\0"
+                        "Bridge\0"
+                        "BridgeFDB\0"
+                        "BridgeVLAN\0"
+                        "IPv6PrefixDelegation\0"
+                        "IPv6Prefix\0"
+                        "IPv6RoutePrefix\0"
+                        "LLDP\0"
+                        "TrafficControlQueueingDiscipline\0"
+                        "CAN\0"
+                        "QDisc\0"
+                        "BFIFO\0"
+                        "CAKE\0"
+                        "ControlledDelay\0"
+                        "DeficitRoundRobinScheduler\0"
+                        "DeficitRoundRobinSchedulerClass\0"
+                        "PFIFO\0"
+                        "PFIFOFast\0"
+                        "PFIFOHeadDrop\0"
+                        "FairQueueing\0"
+                        "FairQueueingControlledDelay\0"
+                        "GenericRandomEarlyDetection\0"
+                        "HeavyHitterFilter\0"
+                        "HierarchyTokenBucket\0"
+                        "HierarchyTokenBucketClass\0"
+                        "NetworkEmulator\0"
+                        "PIE\0"
+                        "StochasticFairBlue\0"
+                        "StochasticFairnessQueueing\0"
+                        "TokenBucketFilter\0"
+                        "TrivialLinkEqualizer\0",
+                        config_item_perf_lookup, network_network_gperf_lookup,
+                        CONFIG_PARSE_WARN,
+                        network,
+                        &network->timestamp);
         if (r < 0)
                 return r;
 
@@ -539,24 +541,6 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
                 log_warning_errno(r, "%s: Failed to add default route on device, ignoring: %m",
                                   network->filename);
 
-        struct stat stats;
-        if (stat(filename, &stats) >= 0)
-                network->timestamp = timespec_load(&stats.st_mtim);
-
-        char **f;
-        STRV_FOREACH(f, dropins) {
-                usec_t t;
-
-                if (stat(*f, &stats) < 0) {
-                        network->timestamp = 0;
-                        break;
-                }
-
-                t = timespec_load(&stats.st_mtim);
-                if (t > network->timestamp)
-                        network->timestamp = t;
-        }
-
         if (network_verify(network) < 0)
                 /* Ignore .network files that do not match the conditions. */
                 return 0;
index 4e1cb3835c67b38c5b5c363ef095bdd15f2b117e..996c0027c386210eea2c7580c30b4d95319d1464 100644 (file)
@@ -78,7 +78,7 @@ int settings_load(FILE *f, const char *path, Settings **ret) {
                          "Files\0",
                          config_item_perf_lookup, nspawn_gperf_lookup,
                          CONFIG_PARSE_WARN,
-                         s);
+                         s, NULL);
         if (r < 0)
                 return r;
 
index 16cb5e45c451e6df3c090d9b1637c0f97c550f82..4c6e459529957c28a49dd685cb3910009ecb07e5 100644 (file)
@@ -976,7 +976,12 @@ static int partition_read_definition(Partition *p, const char *path) {
         };
         int r;
 
-        r = config_parse(NULL, path, NULL, "Partition\0", config_item_table_lookup, table, CONFIG_PARSE_WARN, p);
+        r = config_parse(NULL, path, NULL,
+                         "Partition\0",
+                         config_item_table_lookup, table,
+                         CONFIG_PARSE_WARN,
+                         p,
+                         NULL);
         if (r < 0)
                 return r;
 
index 5c812b5d5b49b9768e0a0ae9d884d65ca0b6f765..59d0b5b74e8b0637afcdff9f688b36821eb34f93 100644 (file)
@@ -78,11 +78,14 @@ static int parse_config(void) {
                 {}
         };
 
-        return config_parse_many_nulstr(PKGSYSCONFDIR "/pstore.conf",
-                                        CONF_PATHS_NULSTR("systemd/pstore.conf.d"),
-                                        "PStore\0",
-                                        config_item_table_lookup, items,
-                                        CONFIG_PARSE_WARN, NULL);
+        return config_parse_many_nulstr(
+                        PKGSYSCONFDIR "/pstore.conf",
+                        CONF_PATHS_NULSTR("systemd/pstore.conf.d"),
+                        "PStore\0",
+                        config_item_table_lookup, items,
+                        CONFIG_PARSE_WARN,
+                        NULL,
+                        NULL);
 }
 
 /* File list handling - PStoreEntry is the struct and
index e915343c01216051e85e8bf5692d7c5c14e1e34b..9a6b1e88e17d29c86c0d08e022cffbeb0e218e7e 100644 (file)
@@ -381,11 +381,14 @@ int manager_parse_config_file(Manager *m) {
 
         assert(m);
 
-        r = config_parse_many_nulstr(PKGSYSCONFDIR "/resolved.conf",
-                                     CONF_PATHS_NULSTR("systemd/resolved.conf.d"),
-                                     "Resolve\0",
-                                     config_item_perf_lookup, resolved_gperf_lookup,
-                                     CONFIG_PARSE_WARN, m);
+        r = config_parse_many_nulstr(
+                        PKGSYSCONFDIR "/resolved.conf",
+                        CONF_PATHS_NULSTR("systemd/resolved.conf.d"),
+                        "Resolve\0",
+                        config_item_perf_lookup, resolved_gperf_lookup,
+                        CONFIG_PARSE_WARN,
+                        m,
+                        NULL);
         if (r < 0)
                 return r;
 
index c331b2d94c9453bea2ec93e3e9a3b7c9afffdca6..4458ad1d2d47554c95d37e8082bb4096b8aa497b 100644 (file)
@@ -86,10 +86,13 @@ static int dnssd_service_load(Manager *manager, const char *filename) {
 
         dropin_dirname = strjoina(service->name, ".dnssd.d");
 
-        r = config_parse_many(filename, DNSSD_SERVICE_DIRS, dropin_dirname,
-                              "Service\0",
-                              config_item_perf_lookup, resolved_dnssd_gperf_lookup,
-                              false, service, NULL);
+        r = config_parse_many(
+                        filename, DNSSD_SERVICE_DIRS, dropin_dirname,
+                        "Service\0",
+                        config_item_perf_lookup, resolved_dnssd_gperf_lookup,
+                        CONFIG_PARSE_WARN,
+                        service,
+                        NULL);
         if (r < 0)
                 return r;
 
index 2eda6ae03ac9418f725399d6f4e92a5f5de47069..21226573428f615b7d8815bfe5e55d9458568569 100644 (file)
@@ -199,7 +199,7 @@ static int parse_line(
                 if (!fn)
                         return -ENOMEM;
 
-                return config_parse(unit, fn, NULL, sections, lookup, table, flags, userdata);
+                return config_parse(unit, fn, NULL, sections, lookup, table, flags, userdata, NULL);
         }
 
         if (!utf8_is_valid(l))
@@ -289,13 +289,15 @@ int config_parse(const char *unit,
                  ConfigItemLookup lookup,
                  const void *table,
                  ConfigParseFlags flags,
-                 void *userdata) {
+                 void *userdata,
+                 usec_t *ret_mtime) {
 
         _cleanup_free_ char *section = NULL, *continuation = NULL;
         _cleanup_fclose_ FILE *ours = NULL;
         unsigned line = 0, section_line = 0;
         bool section_ignored = false, bom_seen = false;
         int r, fd;
+        usec_t mtime;
 
         assert(filename);
         assert(lookup);
@@ -313,8 +315,16 @@ int config_parse(const char *unit,
         }
 
         fd = fileno(f);
-        if (fd >= 0) /* stream might not have an fd, let's be careful hence */
-                fd_warn_permissions(filename, fd);
+        if (fd >= 0) { /* stream might not have an fd, let's be careful hence */
+                struct stat st;
+
+                if (fstat(fd, &st) < 0)
+                        return log_full_errno(FLAGS_SET(flags, CONFIG_PARSE_WARN) ? LOG_ERR : LOG_DEBUG, errno,
+                                              "Failed to fstat(%s): %m", filename);
+
+                (void) stat_warn_permissions(filename, &st);
+                mtime = timespec_load(&st.st_mtim);
+        }
 
         for (;;) {
                 _cleanup_free_ char *buf = NULL;
@@ -434,6 +444,9 @@ int config_parse(const char *unit,
                 }
         }
 
+        if (ret_mtime)
+                *ret_mtime = mtime;
+
         return 0;
 }
 
@@ -444,23 +457,32 @@ static int config_parse_many_files(
                 ConfigItemLookup lookup,
                 const void *table,
                 ConfigParseFlags flags,
-                void *userdata) {
+                void *userdata,
+                usec_t *ret_mtime) {
 
+        usec_t mtime = 0;
         char **fn;
         int r;
 
         if (conf_file) {
-                r = config_parse(NULL, conf_file, NULL, sections, lookup, table, flags, userdata);
+                r = config_parse(NULL, conf_file, NULL, sections, lookup, table, flags, userdata, &mtime);
                 if (r < 0)
                         return r;
         }
 
         STRV_FOREACH(fn, files) {
-                r = config_parse(NULL, *fn, NULL, sections, lookup, table, flags, userdata);
+                usec_t t;
+
+                r = config_parse(NULL, *fn, NULL, sections, lookup, table, flags, userdata, &t);
                 if (r < 0)
                         return r;
+                if (t > mtime) /* Find the newest */
+                        mtime = t;
         }
 
+        if (ret_mtime)
+                *ret_mtime = mtime;
+
         return 0;
 }
 
@@ -472,7 +494,8 @@ int config_parse_many_nulstr(
                 ConfigItemLookup lookup,
                 const void *table,
                 ConfigParseFlags flags,
-                void *userdata) {
+                void *userdata,
+                usec_t *ret_mtime) {
 
         _cleanup_strv_free_ char **files = NULL;
         int r;
@@ -481,7 +504,7 @@ int config_parse_many_nulstr(
         if (r < 0)
                 return r;
 
-        return config_parse_many_files(conf_file, files, sections, lookup, table, flags, userdata);
+        return config_parse_many_files(conf_file, files, sections, lookup, table, flags, userdata, ret_mtime);
 }
 
 /* Parse each config file in the directories specified as strv. */
@@ -494,7 +517,7 @@ int config_parse_many(
                 const void *table,
                 ConfigParseFlags flags,
                 void *userdata,
-                char ***ret_dropins) {
+                usec_t *ret_mtime) {
 
         _cleanup_strv_free_ char **dropin_dirs = NULL;
         _cleanup_strv_free_ char **files = NULL;
@@ -510,14 +533,7 @@ int config_parse_many(
         if (r < 0)
                 return r;
 
-        r = config_parse_many_files(conf_file, files, sections, lookup, table, flags, userdata);
-        if (r < 0)
-                return r;
-
-        if (ret_dropins)
-                *ret_dropins = TAKE_PTR(files);
-
-        return 0;
+        return config_parse_many_files(conf_file, files, sections, lookup, table, flags, userdata, ret_mtime);
 }
 
 #define DEFINE_PARSER(type, vartype, conv_func)                         \
index 480988f392bf7c646c997b913f39b842c2ab9726..6c8c1092ea57ca0fcff620b6bddb241b2c986167 100644 (file)
@@ -10,6 +10,7 @@
 #include "alloc-util.h"
 #include "log.h"
 #include "macro.h"
+#include "time-util.h"
 
 /* An abstract parser for simple, line based, shallow configuration files consisting of variable assignments only. */
 
@@ -84,11 +85,12 @@ int config_parse(
                 const char *unit,
                 const char *filename,
                 FILE *f,
-                const char *sections,  /* nulstr */
+                const char *sections,       /* nulstr */
                 ConfigItemLookup lookup,
                 const void *table,
                 ConfigParseFlags flags,
-                void *userdata);
+                void *userdata,
+                usec_t *ret_mtime);         /* possibly NULL */
 
 int config_parse_many_nulstr(
                 const char *conf_file,      /* possibly NULL */
@@ -97,7 +99,8 @@ int config_parse_many_nulstr(
                 ConfigItemLookup lookup,
                 const void *table,
                 ConfigParseFlags flags,
-                void *userdata);
+                void *userdata,
+                usec_t *ret_mtime);         /* possibly NULL */
 
 int config_parse_many(
                 const char *conf_file,      /* possibly NULL */
@@ -108,7 +111,7 @@ int config_parse_many(
                 const void *table,
                 ConfigParseFlags flags,
                 void *userdata,
-                char ***ret_dropins);       /* possibly NULL */
+                usec_t *ret_mtime);         /* possibly NULL */
 
 CONFIG_PARSER_PROTOTYPE(config_parse_int);
 CONFIG_PARSER_PROTOTYPE(config_parse_unsigned);
index 60005967e79feb614e2f036671b36889f2e86414..5dd5d2aa9ae23147127f4a0df2c6e7e2b1a67c53 100644 (file)
@@ -1304,7 +1304,8 @@ static int unit_file_load(
                          "-Target\0"
                          "-Timer\0",
                          config_item_table_lookup, items,
-                         CONFIG_PARSE_ALLOW_INCLUDE, info);
+                         CONFIG_PARSE_ALLOW_INCLUDE, info,
+                         NULL);
         if (r < 0)
                 return log_debug_errno(r, "Failed to parse %s: %m", info->name);
 
index 5cee1ce1aa8d45e4f2b9625bc9f00355ca3ec883..81862c776d60401f959c6b07ac2dca824f91222f 100644 (file)
@@ -59,10 +59,14 @@ int parse_sleep_config(SleepConfig **ret_sleep_config) {
                 {}
         };
 
-        (void) config_parse_many_nulstr(PKGSYSCONFDIR "/sleep.conf",
-                                        CONF_PATHS_NULSTR("systemd/sleep.conf.d"),
-                                        "Sleep\0", config_item_table_lookup, items,
-                                        CONFIG_PARSE_WARN, NULL);
+        (void) config_parse_many_nulstr(
+                        PKGSYSCONFDIR "/sleep.conf",
+                        CONF_PATHS_NULSTR("systemd/sleep.conf.d"),
+                        "Sleep\0",
+                        config_item_table_lookup, items,
+                        CONFIG_PARSE_WARN,
+                        NULL,
+                        NULL);
 
         /* use default values unless set */
         sc->allow_suspend = allow_suspend != 0;
index 510b1de72d104aea2e38af2c6d5117b3098f3208..07edc17f92ef6d79b00540115f873f8e24f92ab8 100644 (file)
@@ -335,13 +335,17 @@ static void test_config_parse(unsigned i, const char *s) {
                          ConfigItemLookup lookup,
                          const void *table,
                          ConfigParseFlags flags,
-                         void *userdata)
+                         void *userdata,
+                         usec_t *ret_mtime)
         */
 
         r = config_parse(NULL, name, f,
-                         "Section\0-NoWarnSection\0",
+                         "Section\0"
+                         "-NoWarnSection\0",
                          config_item_table_lookup, items,
-                         CONFIG_PARSE_WARN, NULL);
+                         CONFIG_PARSE_WARN,
+                         NULL,
+                         NULL);
 
         switch (i) {
         case 0 ... 4:
index a26c2dad7fbd494de6628aa50b7b9682ae03d71c..532d6ea7ec00f594a525ce5e49c1266a8388a36d 100644 (file)
@@ -102,11 +102,14 @@ int manager_parse_config_file(Manager *m) {
 
         assert(m);
 
-        r = config_parse_many_nulstr(PKGSYSCONFDIR "/timesyncd.conf",
-                                     CONF_PATHS_NULSTR("systemd/timesyncd.conf.d"),
-                                     "Time\0",
-                                     config_item_perf_lookup, timesyncd_gperf_lookup,
-                                     CONFIG_PARSE_WARN, m);
+        r = config_parse_many_nulstr(
+                        PKGSYSCONFDIR "/timesyncd.conf",
+                        CONF_PATHS_NULSTR("systemd/timesyncd.conf.d"),
+                        "Time\0",
+                        config_item_perf_lookup, timesyncd_gperf_lookup,
+                        CONFIG_PARSE_WARN,
+                        m,
+                        NULL);
         if (r < 0)
                 return r;
 
index 0e33c0b48f01564792080235f43a98d692920a87..eb8471911130cb55e962d26505643feca5945d3c 100644 (file)
@@ -192,7 +192,9 @@ static int process_one_password_file(const char *filename) {
         r = config_parse(NULL, filename, NULL,
                          NULL,
                          config_item_table_lookup, items,
-                         CONFIG_PARSE_RELAXED|CONFIG_PARSE_WARN, NULL);
+                         CONFIG_PARSE_RELAXED|CONFIG_PARSE_WARN,
+                         NULL,
+                         NULL);
         if (r < 0)
                 return r;
 
index 806f4574581a69762b6ce028cea220c554dd1805..abe1276dfa17c1ccc3cc51b8fa5cfb0318017b75 100644 (file)
@@ -161,7 +161,8 @@ int link_load_one(link_config_ctx *ctx, const char *filename) {
         r = config_parse(NULL, filename, file,
                          "Match\0Link\0",
                          config_item_perf_lookup, link_config_gperf_lookup,
-                         CONFIG_PARSE_WARN, link);
+                         CONFIG_PARSE_WARN, link,
+                         NULL);
         if (r < 0)
                 return r;
 
index c99b6cc8839c698c971a2ad5cea61e8fa5ae5013..6d10d7052b5b7c88477450b0be4167138ac86bcd 100644 (file)
@@ -319,7 +319,8 @@ XdgAutostartService *xdg_autostart_service_parse_desktop(const char *path) {
         r = config_parse(NULL, service->path, NULL,
                          "Desktop Entry\0",
                          xdg_config_item_table_lookup, items,
-                         CONFIG_PARSE_WARN, service);
+                         CONFIG_PARSE_WARN, service,
+                         NULL);
         /* If parsing failed, only hide the file so it will still mask others. */
         if (r < 0) {
                 log_warning_errno(r, "Failed to parse %s, ignoring it", service->path);