X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flogind-user.c;h=19db746d8bc52228c0e715c8291d47fecc779de3;hb=14c3baca3eb8b32fc266e46127851585bee5aff2;hp=e0a38425461347a5df49ac9a69b213cc5a60fe43;hpb=5a3ab509b56bd79bf2be53cc259ce45c0be269e6;p=elogind.git diff --git a/src/logind-user.c b/src/logind-user.c index e0a384254..19db746d8 100644 --- a/src/logind-user.c +++ b/src/logind-user.c @@ -35,7 +35,7 @@ User* user_new(Manager *m, uid_t uid, gid_t gid, const char *name) { assert(m); assert(name); - u = new(User, 1); + u = new0(User, 1); if (!u) return NULL; @@ -68,6 +68,9 @@ User* user_new(Manager *m, uid_t uid, gid_t gid, const char *name) { void user_free(User *u) { assert(u); + if (u->in_gc_queue) + LIST_REMOVE(User, gc_queue, u->manager->user_gc_queue, u); + while (u->sessions) session_free(u->sessions); @@ -79,26 +82,35 @@ void user_free(User *u) { hashmap_remove(u->manager->users, ULONG_TO_PTR((unsigned long) u->uid)); free(u->name); - free(u->state_file); + + if (u->state_file) { + unlink(u->state_file); + free(u->state_file); + } + free(u); } int user_save(User *u) { FILE *f; int r; + char *temp_path; assert(u); assert(u->state_file); r = safe_mkdir("/run/systemd/user", 0755, 0, 0); if (r < 0) - return r; + goto finish; - f = fopen(u->state_file, "we"); - if (!f) - return -errno; + r = fopen_temporary(u->state_file, &f, &temp_path); + if (r < 0) + goto finish; + + fchmod(fileno(f), 0644); fprintf(f, + "# This is private data. Do not parse.\n" "NAME=%s\n" "STATE=%s\n", u->name, @@ -125,12 +137,20 @@ int user_save(User *u) { u->display->id); fflush(f); - if (ferror(f)) { + + if (ferror(f) || rename(temp_path, u->state_file) < 0) { r = -errno; unlink(u->state_file); + unlink(temp_path); } fclose(f); + free(temp_path); + +finish: + if (r < 0) + log_error("Failed to save user data for %s: %s", u->name, strerror(-r)); + return r; } @@ -260,6 +280,9 @@ int user_start(User *u) { if (r < 0) return r; + /* Save new user data */ + user_save(u); + dual_timestamp_get(&u->timestamp); return 0; @@ -395,6 +418,16 @@ int user_check_gc(User *u) { return 0; } +void user_add_to_gc_queue(User *u) { + assert(u); + + if (u->in_gc_queue) + return; + + LIST_PREPEND(User, gc_queue, u->manager->user_gc_queue, u); + u->in_gc_queue = true; +} + UserState user_get_state(User *u) { Session *i;