1
0
mirror of https://github.com/systemd/systemd synced 2026-04-10 09:04:50 +02:00

Compare commits

..

14 Commits

Author SHA1 Message Date
Дамјан Георгиевски
12caf72716 bootctl: optionally install .signed efi file
if /usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed exists
install that instead of /usr/lib/systemd/boot/efi/systemd-bootx64.efi

the idea is that SecureBoot tooling can create the efi.signed file
whenever /usr/lib/systemd/boot/efi/systemd-bootx64.efi from the package
is updated.
2021-12-08 22:21:34 +01:00
Yu Watanabe
0264c60d44
Merge pull request #21686 from yuwata/network-wlan-fix-reconfigure
network: do not reconfigure wireless interface when previously not connected to any APs
2021-12-09 05:57:12 +09:00
Daan De Meyer
8097f80500
Merge pull request #21637 from nabijaczleweli/EBA
kernel-install: export BOOT_ROOT instead of hacking it in hooks, note KERNEL_INSTALL_* ABI
2021-12-08 20:15:38 +00:00
Yu Watanabe
c923992c5c
Merge pull request #21678 from keszybz/sysusers-work
Make it easier to figure out what sysusers is doing and why
2021-12-09 04:35:50 +09:00
Yu Watanabe
d9910948eb network: do not reconfigure wireless interface when previously not connected to any APs
Follow-up for 6706ce2fd2a13df0ae5e469b72d688eaf643dac4.

Fixes #21685.
2021-12-09 03:04:24 +09:00
Yu Watanabe
da94e4ddf5 network: wifi: ssid may be NULL
This fixes the following log message:
systemd-networkd[888]: wlan0: nl80211: received new_interface(7) message: iftype=station, ssid=(null)
2021-12-09 02:43:29 +09:00
наб
b51e71b2d2
kernel-install: note $KERNEL_INSTALL_{MACHINE_ID,BOOT_ROOT}= ABI 2021-12-08 13:44:27 +01:00
наб
9e82a74cb0
kernel-install: export $BOOT_ROOT and use it in downstreams
The previous approach, to strip "$MACHINE_ID/$KERNEL_VERSION" from the
end, is pretty bad and encourages this for users, which makes them
inflexible to this being modified locally
2021-12-08 13:43:19 +01:00
Zbigniew Jędrzejewski-Szmek
5374bc7cb4 sysusers: raise level of message about UID/GID being already used
It can be quite important that a different value was used, so let's
log this by default.
2021-12-08 11:47:29 +01:00
Zbigniew Jędrzejewski-Szmek
9a5af4b7ac sysusers: improve message about conflicting entries
Without any markup, the sentence could be quite confusing:
g user 55
g user 56
→
"Two or more conflicting lines for user configured"
It also wasn't clear which line is ignored.

Inspired by https://github.com/systemd/systemd/pull/21156.
2021-12-08 11:47:15 +01:00
Zbigniew Jędrzejewski-Szmek
64fe10957b sysusers: add --dry-run 2021-12-08 11:46:33 +01:00
Zbigniew Jędrzejewski-Szmek
98167876a0 sysusers: use ordered_hashmap_isempty() 2021-12-08 11:46:33 +01:00
Zbigniew Jędrzejewski-Szmek
3f316701d7 sysusers: use uppercase UID/GID consistently in messages 2021-12-08 10:19:53 +01:00
Zbigniew Jędrzejewski-Szmek
21c7bc1dad gitignore: remove patterns for build files in source dir
Those made sense when autotoolz were used. With meson, everything
should land in the build dir, and this is only likely to obscure issues
with custom build rules.
C.f. https://github.com/systemd/systemd/pull/20429#issuecomment-988132332
2021-12-08 09:52:31 +01:00
11 changed files with 168 additions and 80 deletions

5
.gitignore vendored
View File

@ -1,11 +1,6 @@
*.a
*.cache
*.gch
*.log
*.o
*.plist
*.py[co]
*.stamp
*.swp
*.trs
*~

View File

@ -286,6 +286,14 @@
</variablelist>
</refsect1>
<refsect1>
<title>Signed .efi files</title>
<para><command>bootctl</command> <option>install</option> and <option>update</option> will look for a
<command>systemd-boot</command> file ending with the <literal>.efi.signed</literal> suffix first, and copy
that instead of the normal <literal>.efi</literal> file. This allows distributions or end-users to provide
signed images for UEFI SecureBoot.</para>
</refsect1>
<refsect1>
<title>Exit status</title>
<para>On success, 0 is returned, a non-zero failure code otherwise.</para>

View File

@ -167,6 +167,11 @@
<para>If <varname>MACHINE_ID=</varname> is set and not empty, it will be used as <replaceable>MACHINE-ID</replaceable>,
overriding any automatic detection attempts. The value must be a valid machine ID (32 hexadecimal characters).</para>
<para><varname>KERNEL_INSTALL_MACHINE_ID=</varname> is set for the plugins to the desired <replaceable>MACHINE-ID</replaceable>
either 32 hexadecimal characters or the special value <literal>Default</literal>.</para>
<para><varname>KERNEL_INSTALL_BOOT_ROOT=</varname> is set for the plugins to the root directory (mount point, usually) of the hierarchy
where boot-loader entries, kernel images, and associated resources should be placed. Can be overriden by setting <varname>BOOT_ROOT=</varname>.</para>
</refsect1>
<refsect1>

View File

@ -115,6 +115,12 @@
</listitem>
</varlistentry>
<varlistentry>
<term><option>--dry-run</option></term>
<listitem><para>Process the configuration and figure out what entries would be created, but don't
actually write anything.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--inline</option></term>
<listitem><para>Treat each positional argument as a separate configuration

View File

@ -628,14 +628,19 @@ static int create_subdirs(const char *root, const char * const *subdirs) {
static int copy_one_file(const char *esp_path, const char *name, bool force) {
const char *e;
char *p, *q;
char *p, *q, *dest_name, *s;
int r;
dest_name = strdupa_safe(name);
s = endswith_no_case(dest_name, ".signed");
if (s)
*s = 0;
p = strjoina(BOOTLIBDIR "/", name);
q = strjoina(esp_path, "/EFI/systemd/", name);
q = strjoina(esp_path, "/EFI/systemd/", dest_name);
r = copy_file_with_version_check(p, q, force);
e = startswith(name, "systemd-boot");
e = startswith(dest_name, "systemd-boot");
if (e) {
int k;
char *v;
@ -664,9 +669,18 @@ static int install_binaries(const char *esp_path, bool force) {
FOREACH_DIRENT(de, d, return log_error_errno(errno, "Failed to read \""BOOTLIBDIR"\": %m")) {
int k;
if (!endswith_no_case(de->d_name, ".efi"))
if (!endswith_no_case(de->d_name, ".efi") && !endswith_no_case(de->d_name, ".efi.signed"))
continue;
/* skip the .efi file, if there's a .signed version of it */
if (endswith_no_case(de->d_name, ".efi")) {
_cleanup_free_ const char *s = strjoin(BOOTLIBDIR, "/", de->d_name, ".signed");
if (!s)
return log_oom();
if (access(s, F_OK) >= 0)
continue;
}
k = copy_one_file(esp_path, de->d_name, force);
/* Don't propagate an error code if no update necessary, installed version already equal or
* newer version, or other boot loader in place. */

View File

@ -32,10 +32,9 @@ if [[ $COMMAND != add ]]; then
exit 0
fi
# If the boot dir exists (e.g. $ESP/<machine-id>),
# create the entry directory ($ESP/<machine-id>/<kernel-version>).
# This is the only function of this plugin.
MACHINE_ID_DIR="${ENTRY_DIR_ABS%/*}"
# Create the entry directory if its parent exists
# this is an administrative decision and the only function of this plugin.
MACHINE_ID_DIR="$KERNEL_INSTALL_BOOT_ROOT/$KERNEL_INSTALL_MACHINE_ID"
if ! [ -d "$MACHINE_ID_DIR" ]; then
exit 0
fi

View File

@ -32,14 +32,14 @@ if ! [[ -d "$ENTRY_DIR_ABS" ]]; then
exit 0
fi
MACHINE_ID=$KERNEL_INSTALL_MACHINE_ID
MACHINE_ID="$KERNEL_INSTALL_MACHINE_ID"
BOOT_ROOT="$KERNEL_INSTALL_BOOT_ROOT"
BOOT_ROOT=${ENTRY_DIR_ABS%/$MACHINE_ID/$KERNEL_VERSION}
BOOT_MNT=$(stat -c %m $BOOT_ROOT)
if [[ $BOOT_MNT == '/' ]]; then
ENTRY_DIR=$ENTRY_DIR_ABS
BOOT_MNT="$(stat -c %m "$BOOT_ROOT")"
if [[ "$BOOT_MNT" == '/' ]]; then
ENTRY_DIR="$ENTRY_DIR_ABS"
else
ENTRY_DIR=${ENTRY_DIR_ABS#$BOOT_MNT}
ENTRY_DIR="${ENTRY_DIR_ABS#$BOOT_MNT}"
fi
if [[ $COMMAND == remove ]]; then

View File

@ -93,21 +93,28 @@ fi
[ -z "$MACHINE_ID" ] && [ -f /etc/machine-id ] && [ "$(stat -fc %T /etc/machine-id)" != "tmpfs" ] && read -r MACHINE_ID < /etc/machine-id
[ -z "$MACHINE_ID" ] && MACHINE_ID="Default"
if [[ -d /efi/loader/entries ]] || [[ -d /efi/$MACHINE_ID ]]; then
ENTRY_DIR_ABS="/efi/$MACHINE_ID/$KERNEL_VERSION"
elif [[ -d /boot/loader/entries ]] || [[ -d /boot/$MACHINE_ID ]]; then
ENTRY_DIR_ABS="/boot/$MACHINE_ID/$KERNEL_VERSION"
elif [[ -d /boot/efi/loader/entries ]] || [[ -d /boot/efi/$MACHINE_ID ]]; then
ENTRY_DIR_ABS="/boot/efi/$MACHINE_ID/$KERNEL_VERSION"
elif mountpoint -q /efi; then
ENTRY_DIR_ABS="/efi/$MACHINE_ID/$KERNEL_VERSION"
elif mountpoint -q /boot/efi; then
ENTRY_DIR_ABS="/boot/efi/$MACHINE_ID/$KERNEL_VERSION"
else
ENTRY_DIR_ABS="/boot/$MACHINE_ID/$KERNEL_VERSION"
fi
[ -z "$BOOT_ROOT" ] && for suff in "$MACHINE_ID" "Default" "loader/entries"; do
for pref in "/efi" "/boot/efi" "/boot"; do
if [ -d "$pref/$suff" ]; then
BOOT_ROOT="$pref"
break 2
fi
done
done
[ -z "$BOOT_ROOT" ] && for pref in "/efi" "/boot/efi"; do
if mountpoint -q "$pref"; then
BOOT_ROOT="$pref"
break
fi
done
[ -z "$BOOT_ROOT" ] && BOOT_ROOT="/boot"
ENTRY_DIR_ABS="$BOOT_ROOT/$MACHINE_ID/$KERNEL_VERSION"
export KERNEL_INSTALL_MACHINE_ID="$MACHINE_ID"
export KERNEL_INSTALL_BOOT_ROOT="$BOOT_ROOT"
ret=0

View File

@ -1602,13 +1602,21 @@ static int link_carrier_gained(Link *link) {
if (r < 0)
log_link_warning_errno(link, r, "Failed to disable carrier lost timer, ignoring: %m");
/* If the SSID is changed, then the connected wireless network could be changed. So, always
* reconfigure the link. Which means e.g. the DHCP client will be restarted, and the correct
* network information will be gained.
/* If a wireless interface was connected to an access point, and the SSID is changed (that is,
* both previous_ssid and ssid are non-NULL), then the connected wireless network could be
* changed. So, always reconfigure the link. Which means e.g. the DHCP client will be
* restarted, and the correct network information will be gained.
*
* However, do not reconfigure the wireless interface forcibly if it was not connected to any
* access points previously (previous_ssid is NULL in this case). As, a .network file may be
* already assigned to the interface (in that case, the .network file does not have the SSID=
* setting in the [Match] section), and the interface is already being configured. Of course,
* there may exist another .network file with higher priority and a matching SSID= setting. But
* in that case, link_reconfigure_impl() can handle that without the force_reconfigure flag.
*
* For non-wireless interfaces, we have no way to detect the connected network change. So,
* setting force_reconfigure = false. Note, both ssid and previous_ssid should be NULL for
* non-wireless interfaces, and streq_ptr() returns true. */
force_reconfigure = !streq_ptr(link->previous_ssid, link->ssid);
* setting force_reconfigure = false. Note, both ssid and previous_ssid are NULL in that case. */
force_reconfigure = link->previous_ssid && !streq_ptr(link->previous_ssid, link->ssid);
link->previous_ssid = mfree(link->previous_ssid);
if (!IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_FAILED, LINK_STATE_LINGER)) {

View File

@ -130,7 +130,7 @@ int manager_genl_process_nl80211_config(sd_netlink *genl, sd_netlink_message *me
log_link_debug(link, "nl80211: received %s(%u) message: iftype=%s, ssid=%s",
strna(nl80211_cmd_to_string(cmd)), cmd,
strna(nl80211_iftype_to_string(wlan_iftype)), ssid);
strna(nl80211_iftype_to_string(wlan_iftype)), strna(ssid));
switch(cmd) {
case NL80211_CMD_SET_INTERFACE:

View File

@ -38,12 +38,27 @@
#include "util.h"
typedef enum ItemType {
ADD_USER = 'u',
ADD_GROUP = 'g',
ADD_USER = 'u',
ADD_GROUP = 'g',
ADD_MEMBER = 'm',
ADD_RANGE = 'r',
ADD_RANGE = 'r',
} ItemType;
static inline const char* item_type_to_string(ItemType t) {
switch (t) {
case ADD_USER:
return "user";
case ADD_GROUP:
return "group";
case ADD_MEMBER:
return "member";
case ADD_RANGE:
return "range";
default:
assert_not_reached();
}
}
typedef struct Item {
ItemType type;
@ -60,8 +75,8 @@ typedef struct Item {
bool gid_set:1;
/* When set the group with the specified gid must exist
* and the check if a uid clashes with the gid is skipped.
/* When set the group with the specified GID must exist
* and the check if a UID clashes with the GID is skipped.
*/
bool id_set_strict:1;
@ -75,6 +90,7 @@ static char *arg_root = NULL;
static char *arg_image = NULL;
static bool arg_cat_config = false;
static const char *arg_replace = NULL;
static bool arg_dry_run = false;
static bool arg_inline = false;
static PagerFlags arg_pager_flags = 0;
@ -387,9 +403,14 @@ static int write_temporary_passwd(const char *passwd_path, FILE **tmpfile, char
Item *i;
int r;
if (ordered_hashmap_size(todo_uids) == 0)
if (ordered_hashmap_isempty(todo_uids))
return 0;
if (arg_dry_run) {
log_info("Would write /etc/passwd…");
return 0;
}
r = fopen_temporary_label("/etc/passwd", passwd_path, &passwd, &passwd_tmp);
if (r < 0)
return log_debug_errno(r, "Failed to open temporary copy of %s: %m", passwd_path);
@ -506,9 +527,14 @@ static int write_temporary_shadow(const char *shadow_path, FILE **tmpfile, char
Item *i;
int r;
if (ordered_hashmap_size(todo_uids) == 0)
if (ordered_hashmap_isempty(todo_uids))
return 0;
if (arg_dry_run) {
log_info("Would write /etc/shadow…");
return 0;
}
r = fopen_temporary_label("/etc/shadow", shadow_path, &shadow, &shadow_tmp);
if (r < 0)
return log_debug_errno(r, "Failed to open temporary copy of %s: %m", shadow_path);
@ -639,9 +665,14 @@ static int write_temporary_group(const char *group_path, FILE **tmpfile, char **
Item *i;
int r;
if (ordered_hashmap_size(todo_gids) == 0 && ordered_hashmap_size(members) == 0)
if (ordered_hashmap_isempty(todo_gids) && ordered_hashmap_isempty(members))
return 0;
if (arg_dry_run) {
log_info("Would write /etc/group…");
return 0;
}
r = fopen_temporary_label("/etc/group", group_path, &group, &group_tmp);
if (r < 0)
return log_debug_errno(r, "Failed to open temporary copy of %s: %m", group_path);
@ -740,9 +771,14 @@ static int write_temporary_gshadow(const char * gshadow_path, FILE **tmpfile, ch
Item *i;
int r;
if (ordered_hashmap_size(todo_gids) == 0 && ordered_hashmap_size(members) == 0)
if (ordered_hashmap_isempty(todo_gids) && ordered_hashmap_isempty(members))
return 0;
if (arg_dry_run) {
log_info("Would write /etc/gshadow…");
return 0;
}
r = fopen_temporary_label("/etc/gshadow", gshadow_path, &gshadow, &gshadow_tmp);
if (r < 0)
return log_debug_errno(r, "Failed to open temporary copy of %s: %m", gshadow_path);
@ -969,13 +1005,13 @@ static int read_id_from_file(Item *i, uid_t *_uid, gid_t *_gid) {
assert(i);
/* First, try to get the gid directly */
/* First, try to get the GID directly */
if (_gid && i->gid_path && root_stat(i->gid_path, &st) >= 0) {
gid = st.st_gid;
found_gid = true;
}
/* Then, try to get the uid directly */
/* Then, try to get the UID directly */
if ((_uid || (_gid && !found_gid))
&& i->uid_path
&& root_stat(i->uid_path, &st) >= 0) {
@ -983,14 +1019,14 @@ static int read_id_from_file(Item *i, uid_t *_uid, gid_t *_gid) {
uid = st.st_uid;
found_uid = true;
/* If we need the gid, but had no success yet, also derive it from the uid path */
/* If we need the gid, but had no success yet, also derive it from the UID path */
if (_gid && !found_gid) {
gid = st.st_gid;
found_gid = true;
}
}
/* If that didn't work yet, then let's reuse the gid as uid */
/* If that didn't work yet, then let's reuse the GID as UID */
if (_uid && !found_uid && i->gid_path) {
if (found_gid) {
@ -1055,13 +1091,13 @@ static int add_user(Item *i) {
return log_error_errno(errno, "Failed to check if user %s already exists: %m", i->name);
}
/* Try to use the suggested numeric uid */
/* Try to use the suggested numeric UID */
if (i->uid_set) {
r = uid_is_ok(i->uid, i->name, !i->id_set_strict);
if (r < 0)
return log_error_errno(r, "Failed to verify uid " UID_FMT ": %m", i->uid);
return log_error_errno(r, "Failed to verify UID " UID_FMT ": %m", i->uid);
if (r == 0) {
log_debug("Suggested user ID " UID_FMT " for %s already used.", i->uid, i->name);
log_info("Suggested user ID " UID_FMT " for %s already used.", i->uid, i->name);
i->uid_set = false;
}
}
@ -1077,7 +1113,7 @@ static int add_user(Item *i) {
else {
r = uid_is_ok(c, i->name, true);
if (r < 0)
return log_error_errno(r, "Failed to verify uid " UID_FMT ": %m", i->uid);
return log_error_errno(r, "Failed to verify UID " UID_FMT ": %m", i->uid);
else if (r > 0) {
i->uid = c;
i->uid_set = true;
@ -1091,7 +1127,7 @@ static int add_user(Item *i) {
if (!i->uid_set && i->gid_set) {
r = uid_is_ok((uid_t) i->gid, i->name, true);
if (r < 0)
return log_error_errno(r, "Failed to verify uid " UID_FMT ": %m", i->uid);
return log_error_errno(r, "Failed to verify UID " UID_FMT ": %m", i->uid);
if (r > 0) {
i->uid = (uid_t) i->gid;
i->uid_set = true;
@ -1109,7 +1145,7 @@ static int add_user(Item *i) {
r = uid_is_ok(search_uid, i->name, true);
if (r < 0)
return log_error_errno(r, "Failed to verify uid " UID_FMT ": %m", i->uid);
return log_error_errno(r, "Failed to verify UID " UID_FMT ": %m", i->uid);
else if (r > 0)
break;
}
@ -1120,16 +1156,16 @@ static int add_user(Item *i) {
r = ordered_hashmap_ensure_put(&todo_uids, NULL, UID_TO_PTR(i->uid), i);
if (r == -EEXIST)
return log_error_errno(r, "Requested user %s with uid " UID_FMT " and gid" GID_FMT " to be created is duplicated "
return log_error_errno(r, "Requested user %s with UID " UID_FMT " and gid" GID_FMT " to be created is duplicated "
"or conflicts with another user.", i->name, i->uid, i->gid);
if (r == -ENOMEM)
return log_oom();
if (r < 0)
return log_error_errno(r, "Failed to store user %s with uid " UID_FMT " and gid " GID_FMT " to be created: %m",
return log_error_errno(r, "Failed to store user %s with UID " UID_FMT " and GID " GID_FMT " to be created: %m",
i->name, i->uid, i->gid);
i->todo_user = true;
log_info("Creating user %s (%s) with uid " UID_FMT " and gid " GID_FMT ".",
log_info("Creating user '%s' (%s) with UID " UID_FMT " and GID " GID_FMT ".",
i->name, strna(i->description), i->uid, i->gid);
return 0;
@ -1214,15 +1250,15 @@ static int add_group(Item *i) {
return 0;
}
/* Try to use the suggested numeric gid */
/* Try to use the suggested numeric GID */
if (i->gid_set) {
r = gid_is_ok(i->gid);
if (r < 0)
return log_error_errno(r, "Failed to verify gid " GID_FMT ": %m", i->gid);
return log_error_errno(r, "Failed to verify GID " GID_FMT ": %m", i->gid);
if (i->id_set_strict) {
/* If we require the gid to already exist we can return here:
* r > 0: means the gid does not exist -> fail
* r == 0: means the gid exists -> nothing more to do.
/* If we require the GID to already exist we can return here:
* r > 0: means the GID does not exist -> fail
* r == 0: means the GID exists -> nothing more to do.
*/
if (r > 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
@ -1232,7 +1268,7 @@ static int add_group(Item *i) {
return 0;
}
if (r == 0) {
log_debug("Suggested group ID " GID_FMT " for %s already used.", i->gid, i->name);
log_info("Suggested group ID " GID_FMT " for %s already used.", i->gid, i->name);
i->gid_set = false;
}
}
@ -1241,7 +1277,7 @@ static int add_group(Item *i) {
if (!i->gid_set && i->uid_set) {
r = gid_is_ok((gid_t) i->uid);
if (r < 0)
return log_error_errno(r, "Failed to verify gid " GID_FMT ": %m", i->gid);
return log_error_errno(r, "Failed to verify GID " GID_FMT ": %m", i->gid);
if (r > 0) {
i->gid = (gid_t) i->uid;
i->gid_set = true;
@ -1259,7 +1295,7 @@ static int add_group(Item *i) {
else {
r = gid_is_ok(c);
if (r < 0)
return log_error_errno(r, "Failed to verify gid " GID_FMT ": %m", i->gid);
return log_error_errno(r, "Failed to verify GID " GID_FMT ": %m", i->gid);
else if (r > 0) {
i->gid = c;
i->gid_set = true;
@ -1281,7 +1317,7 @@ static int add_group(Item *i) {
r = gid_is_ok(search_uid);
if (r < 0)
return log_error_errno(r, "Failed to verify gid " GID_FMT ": %m", i->gid);
return log_error_errno(r, "Failed to verify GID " GID_FMT ": %m", i->gid);
else if (r > 0)
break;
}
@ -1292,14 +1328,14 @@ static int add_group(Item *i) {
r = ordered_hashmap_ensure_put(&todo_gids, NULL, GID_TO_PTR(i->gid), i);
if (r == -EEXIST)
return log_error_errno(r, "Requested group %s with gid "GID_FMT " to be created is duplicated or conflicts with another user.", i->name, i->gid);
return log_error_errno(r, "Requested group %s with GID "GID_FMT " to be created is duplicated or conflicts with another user.", i->name, i->gid);
if (r == -ENOMEM)
return log_oom();
if (r < 0)
return log_error_errno(r, "Failed to store group %s with gid " GID_FMT " to be created: %m", i->name, i->gid);
return log_error_errno(r, "Failed to store group %s with GID " GID_FMT " to be created: %m", i->name, i->gid);
i->todo_group = true;
log_info("Creating group %s with gid " GID_FMT ".", i->name, i->gid);
log_info("Creating group '%s' with GID " GID_FMT ".", i->name, i->gid);
return 0;
}
@ -1463,7 +1499,6 @@ static bool item_equal(Item *a, Item *b) {
}
static int parse_line(const char *fname, unsigned line, const char *buffer) {
_cleanup_free_ char *action = NULL,
*name = NULL, *resolved_name = NULL,
*id = NULL, *resolved_id = NULL,
@ -1728,7 +1763,9 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
if (existing) {
/* Two identical items are fine */
if (!item_equal(existing, i))
log_warning("Two or more conflicting lines for %s configured, ignoring.", i->name);
log_warning("%s:%u: conflict with earlier configuration for %s '%s', ignoring line.",
fname, line,
item_type_to_string(i->type), i->name);
return 0;
}
@ -1825,6 +1862,7 @@ static int help(void) {
" --root=PATH Operate on an alternate filesystem root\n"
" --image=PATH Operate on disk image as filesystem root\n"
" --replace=PATH Treat arguments as replacement for PATH\n"
" --dry-run Just print what would be done\n"
" --inline Treat arguments as configuration lines\n"
" --no-pager Do not pipe output into a pager\n"
"\nSee the %s for details.\n",
@ -1842,6 +1880,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_ROOT,
ARG_IMAGE,
ARG_REPLACE,
ARG_DRY_RUN,
ARG_INLINE,
ARG_NO_PAGER,
};
@ -1851,8 +1890,9 @@ static int parse_argv(int argc, char *argv[]) {
{ "version", no_argument, NULL, ARG_VERSION },
{ "cat-config", no_argument, NULL, ARG_CAT_CONFIG },
{ "root", required_argument, NULL, ARG_ROOT },
{ "image", required_argument, NULL, ARG_IMAGE },
{ "image", required_argument, NULL, ARG_IMAGE },
{ "replace", required_argument, NULL, ARG_REPLACE },
{ "dry-run", no_argument, NULL, ARG_DRY_RUN },
{ "inline", no_argument, NULL, ARG_INLINE },
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
{}
@ -1903,6 +1943,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_replace = optarg;
break;
case ARG_DRY_RUN:
arg_dry_run = true;
break;
case ARG_INLINE:
arg_inline = true;
break;
@ -2061,7 +2105,7 @@ static int run(int argc, char *argv[]) {
login_defs_need_warning = true;
/* We pick a range that very conservative: we look at compiled-in maximum and the value in
* /etc/login.defs. That way the uids/gids which we allocate will be interpreted correctly,
* /etc/login.defs. That way the UIDs/GIDs which we allocate will be interpreted correctly,
* even if /etc/login.defs is removed later. (The bottom bound doesn't matter much, since
* it's only used during allocation, so we use the configured value directly). */
uid_t begin = login_defs.system_alloc_uid_min,
@ -2077,9 +2121,11 @@ static int run(int argc, char *argv[]) {
if (r < 0)
return r;
lock = take_etc_passwd_lock(arg_root);
if (lock < 0)
return log_error_errno(lock, "Failed to take /etc/passwd lock: %m");
if (!arg_dry_run) {
lock = take_etc_passwd_lock(arg_root);
if (lock < 0)
return log_error_errno(lock, "Failed to take /etc/passwd lock: %m");
}
r = load_user_database();
if (r < 0)