along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <pwd.h>
+#include <getopt.h>
#include <grp.h>
-#include <shadow.h>
#include <gshadow.h>
-#include <getopt.h>
+#include <pwd.h>
+#include <shadow.h>
#include <utmp.h>
-#include "util.h"
-#include "hashmap.h"
-#include "specifier.h"
-#include "path-util.h"
-#include "build.h"
-#include "strv.h"
+#include "alloc-util.h"
#include "conf-files.h"
#include "copy.h"
-#include "utf8.h"
+#include "def.h"
+#include "fd-util.h"
#include "fileio-label.h"
-#include "uid-range.h"
-#include "selinux-util.h"
#include "formats-util.h"
+#include "hashmap.h"
+#include "path-util.h"
+#include "selinux-util.h"
+#include "smack-util.h"
+#include "specifier.h"
+#include "string-util.h"
+#include "strv.h"
+#include "uid-range.h"
+#include "user-util.h"
+#include "utf8.h"
+#include "util.h"
typedef enum ItemType {
ADD_USER = 'u',
static char *arg_root = NULL;
-static const char conf_file_dirs[] = CONF_DIRS_NULSTR("sysusers");
+static const char conf_file_dirs[] = CONF_PATHS_NULSTR("sysusers.d");
static Hashmap *users = NULL, *groups = NULL;
static Hashmap *todo_uids = NULL, *todo_gids = NULL;
if (r < 0)
return r;
- r = copy_bytes(src, fileno(dst), (off_t) -1, true);
+ r = copy_bytes(src, fileno(dst), (uint64_t) -1, true);
if (r < 0)
goto fail;
errno = 0;
if (putgrent(&t, group) != 0)
- return errno ? -errno : -EIO;
+ return errno > 0 ? -errno : -EIO;
return 1;
}
errno = 0;
if (putgrent(gr, group) != 0)
- return errno ? -errno : -EIO;
+ return errno > 0 ? -errno : -EIO;
return 0;
}
errno = 0;
if (putsgent(&t, gshadow) != 0)
- return errno ? -errno : -EIO;
+ return errno > 0 ? -errno : -EIO;
return 1;
}
errno = 0;
if (putsgent(sg, gshadow) != 0)
- return errno ? -errno : -EIO;
+ return errno > 0 ? -errno : -EIO;
return 0;
}
return 0;
}
+static int rename_and_apply_smack(const char *temp_path, const char *dest_path) {
+ int r = 0;
+ if (rename(temp_path, dest_path) < 0)
+ return -errno;
+
+#ifdef SMACK_RUN_LABEL
+ r = mac_smack_apply(dest_path, SMACK_ATTR_ACCESS, SMACK_FLOOR_LABEL);
+ if (r < 0)
+ return r;
+#endif
+ return r;
+}
+
static int write_files(void) {
_cleanup_fclose_ FILE *passwd = NULL, *group = NULL, *shadow = NULL, *gshadow = NULL;
i = hashmap_get(groups, gr->gr_name);
if (i && i->todo_group) {
+ log_error("%s: Group \"%s\" already exists.", group_path, gr->gr_name);
r = -EEXIST;
goto finish;
}
if (hashmap_contains(todo_gids, GID_TO_PTR(gr->gr_gid))) {
+ log_error("%s: Detected collision for GID %d.", group_path, gr->gr_gid);
r = -EEXIST;
goto finish;
}
i = hashmap_get(groups, sg->sg_namp);
if (i && i->todo_group) {
+ log_error("%s: Group \"%s\" already exists.", gshadow_path, sg->sg_namp);
r = -EEXIST;
goto finish;
}
i = hashmap_get(users, pw->pw_name);
if (i && i->todo_user) {
+ log_error("%s: User \"%s\" already exists.", passwd_path, pw->pw_name);
r = -EEXIST;
goto finish;
}
if (hashmap_contains(todo_uids, UID_TO_PTR(pw->pw_uid))) {
+ log_error("%s: Detected collision for UID %d.", passwd_path, pw->pw_uid);
r = -EEXIST;
goto finish;
}
/* And make the new files count */
if (group_changed) {
if (group) {
- if (rename(group_tmp, group_path) < 0) {
- r = -errno;
+ r = rename_and_apply_smack(group_tmp, group_path);
+ if (r < 0)
goto finish;
- }
group_tmp = mfree(group_tmp);
}
if (gshadow) {
- if (rename(gshadow_tmp, gshadow_path) < 0) {
- r = -errno;
+ r = rename_and_apply_smack(gshadow_tmp, gshadow_path);
+ if (r < 0)
goto finish;
- }
gshadow_tmp = mfree(gshadow_tmp);
}
}
if (passwd) {
- if (rename(passwd_tmp, passwd_path) < 0) {
- r = -errno;
+ r = rename_and_apply_smack(passwd_tmp, passwd_path);
+ if (r < 0)
goto finish;
- }
passwd_tmp = mfree(passwd_tmp);
}
if (shadow) {
- if (rename(shadow_tmp, shadow_path) < 0) {
- r = -errno;
+ r = rename_and_apply_smack(shadow_tmp, shadow_path);
+ if (r < 0)
goto finish;
- }
shadow_tmp = mfree(shadow_tmp);
}
}
}
- /* Otherwise try to reuse the group ID */
+ /* Otherwise, try to reuse the group ID */
if (!i->uid_set && i->gid_set) {
r = uid_is_ok((uid_t) i->gid, i->name);
if (r < 0)
/* Parse columns */
p = buffer;
- r = unquote_many_words(&p, 0, &action, &name, &id, &description, &home, NULL);
+ r = extract_many_words(&p, NULL, EXTRACT_QUOTES, &action, &name, &id, &description, &home, NULL);
if (r < 0) {
log_error("[%s:%u] Syntax error.", fname, line);
return r;
log_error("[%s:%u] Missing action and name columns.", fname, line);
return -EINVAL;
}
- if (*p != 0) {
+ if (!isempty(p)) {
log_error("[%s:%u] Trailing garbage.", fname, line);
return -EINVAL;
}
{}
};
- int c;
+ int c, r;
assert(argc >= 0);
assert(argv);
return 0;
case ARG_VERSION:
- puts(PACKAGE_STRING);
- puts(SYSTEMD_FEATURES);
- return 0;
+ return version();
case ARG_ROOT:
- free(arg_root);
- arg_root = path_make_absolute_cwd(optarg);
- if (!arg_root)
- return log_oom();
-
- path_kill_slashes(arg_root);
+ r = parse_path_argument_and_warn(optarg, true, &arg_root);
+ if (r < 0)
+ return r;
break;
case '?':
if (r < 0)
goto finish;
- lock = take_password_lock(arg_root);
+ lock = take_etc_passwd_lock(arg_root);
if (lock < 0) {
log_error_errno(lock, "Failed to take lock: %m");
goto finish;