static int write_temporary_passwd(const char *passwd_path, FILE **tmpfile, char **tmpfile_path) {
_cleanup_fclose_ FILE *original = NULL, *passwd = NULL;
_cleanup_(unlink_and_freep) char *passwd_tmp = NULL;
+ struct passwd *pw = NULL;
Iterator iterator;
Item *i;
int r;
original = fopen(passwd_path, "re");
if (original) {
- struct passwd *pw;
r = sync_rights(original, passwd);
if (r < 0)
return -EEXIST;
}
+ /* Make sure we keep the NIS entries (if any) at the end. */
+ if (IN_SET(pw->pw_name[0], '+', '-'))
+ break;
+
errno = 0;
if (putpwent(pw, passwd) < 0)
return errno ? -errno : -EIO;
return errno ? -errno : -EIO;
}
+ /* Append the remaining NIS entries if any */
+ while (pw) {
+ errno = 0;
+ if (putpwent(pw, passwd) < 0)
+ return errno ? -errno : -EIO;
+
+ pw = fgetpwent(original);
+ }
+ if (!IN_SET(errno, 0, ENOENT))
+ return -errno;
+
r = fflush_and_check(passwd);
if (r < 0)
return r;
static int write_temporary_shadow(const char *shadow_path, FILE **tmpfile, char **tmpfile_path) {
_cleanup_fclose_ FILE *original = NULL, *shadow = NULL;
_cleanup_(unlink_and_freep) char *shadow_tmp = NULL;
+ struct spwd *sp = NULL;
Iterator iterator;
long lstchg;
Item *i;
original = fopen(shadow_path, "re");
if (original) {
- struct spwd *sp;
r = sync_rights(original, shadow);
if (r < 0)
}
errno = 0;
+
+ /* Make sure we keep the NIS entries (if any) at the end. */
+ if (IN_SET(sp->sp_namp[0], '+', '-'))
+ break;
+
if (putspent(sp, shadow) < 0)
return errno ? -errno : -EIO;
if (putspent(&n, shadow) != 0)
return errno ? -errno : -EIO;
}
+ errno = 0;
+
+ /* Append the remaining NIS entries if any */
+ while (sp) {
+ errno = 0;
+ if (putspent(sp, shadow) < 0)
+ return errno ? -errno : -EIO;
+
+ errno = 0;
+ sp = fgetspent(original);
+ }
+ if (!IN_SET(errno, 0, ENOENT))
+ return -errno;
r = fflush_sync_and_check(shadow);
if (r < 0)
_cleanup_fclose_ FILE *original = NULL, *group = NULL;
_cleanup_(unlink_and_freep) char *group_tmp = NULL;
bool group_changed = false;
+ struct group *gr = NULL;
Iterator iterator;
Item *i;
int r;
original = fopen(group_path, "re");
if (original) {
- struct group *gr;
r = sync_rights(original, group);
if (r < 0)
return -EEXIST;
}
+ /* Make sure we keep the NIS entries (if any) at the end. */
+ if (IN_SET(gr->gr_name[0], '+', '-'))
+ break;
+
r = putgrent_with_members(gr, group);
if (r < 0)
return r;
group_changed = true;
}
+ /* Append the remaining NIS entries if any */
+ while (gr) {
+ errno = 0;
+ if (putgrent(gr, group) != 0)
+ return errno > 0 ? -errno : -EIO;
+
+ gr = fgetgrent(original);
+ }
+ if (!IN_SET(errno, 0, ENOENT))
+ return -errno;
+
r = fflush_sync_and_check(group);
if (r < 0)
return r;
switch (i->type) {
- case ADD_USER:
- r = add_group(i);
- if (r < 0)
- return r;
+ case ADD_USER: {
+ Item *j;
+
+ j = ordered_hashmap_get(groups, i->name);
+ if (j && j->todo_group) {
+ /* When the group with the same name is already in queue,
+ * use the information about the group and do not create
+ * duplicated group entry. */
+ i->gid_set = j->gid_set;
+ i->gid = j->gid;
+ i->id_set_strict = true;
+ } else {
+ r = add_group(i);
+ if (r < 0)
+ return r;
+ }
return add_user(i);
+ }
case ADD_GROUP:
return add_group(i);
int r;
/* Implicitly create additional users and groups, if they were listed in "m" lines */
-
ORDERED_HASHMAP_FOREACH_KEY(l, g, members, iterator) {
- Item *i;
char **m;
- i = ordered_hashmap_get(groups, g);
- if (!i) {
- _cleanup_(item_freep) Item *j = NULL;
-
- r = ordered_hashmap_ensure_allocated(&groups, &string_hash_ops);
- if (r < 0)
- return log_oom();
-
- j = new0(Item, 1);
- if (!j)
- return log_oom();
-
- j->type = ADD_GROUP;
- j->name = strdup(g);
- if (!j->name)
- return log_oom();
-
- r = ordered_hashmap_put(groups, j->name, j);
- if (r < 0)
- return log_oom();
-
- log_debug("Adding implicit group '%s' due to m line", j->name);
- j = NULL;
- }
-
- STRV_FOREACH(m, l) {
-
- i = ordered_hashmap_get(users, *m);
- if (!i) {
+ STRV_FOREACH(m, l)
+ if (!ordered_hashmap_get(users, *m)) {
_cleanup_(item_freep) Item *j = NULL;
r = ordered_hashmap_ensure_allocated(&users, &string_hash_ops);
log_debug("Adding implicit user '%s' due to m line", j->name);
j = NULL;
}
+
+ if (!(ordered_hashmap_get(users, g) ||
+ ordered_hashmap_get(groups, g))) {
+ _cleanup_(item_freep) Item *j = NULL;
+
+ r = ordered_hashmap_ensure_allocated(&groups, &string_hash_ops);
+ if (r < 0)
+ return log_oom();
+
+ j = new0(Item, 1);
+ if (!j)
+ return log_oom();
+
+ j->type = ADD_GROUP;
+ j->name = strdup(g);
+ if (!j->name)
+ return log_oom();
+
+ r = ordered_hashmap_put(groups, j->name, j);
+ if (r < 0)
+ return log_oom();
+
+ log_debug("Adding implicit group '%s' due to m line", j->name);
+ j = NULL;
}
}
i->id_set_strict = true;
free_and_replace(resolved_id, uid);
}
- r = parse_uid(resolved_id, &i->uid);
- if (r < 0)
- return log_error_errno(r, "Failed to parse UID: '%s': %m", id);
-
- i->uid_set = true;
+ if (!streq(resolved_id, "-")) {
+ r = parse_uid(resolved_id, &i->uid);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse UID: '%s': %m", id);
+ i->uid_set = true;
+ }
}
}