X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Ffsckd%2Ffsckd.c;h=757b9f1143234d187309564662ce54574cf401ce;hp=cf823322a1c5622f2dc64ce6e9d6ddc0579fabdd;hb=7046313698e449415ab76c96af4ac0b0fdbf473c;hpb=705778ad6a0d1fd62bdb81fad0074199a3e25666 diff --git a/src/fsckd/fsckd.c b/src/fsckd/fsckd.c index cf823322a..757b9f114 100644 --- a/src/fsckd/fsckd.c +++ b/src/fsckd/fsckd.c @@ -34,16 +34,16 @@ #include #include +#include "sd-daemon.h" #include "build.h" #include "def.h" #include "event-util.h" -#include "fsckd.h" #include "log.h" #include "list.h" #include "macro.h" -#include "sd-daemon.h" #include "socket-util.h" #include "util.h" +#include "fsckd.h" #define IDLE_TIME_SECONDS 30 #define PLYMOUTH_REQUEST_KEY "K\2\2\3" @@ -72,7 +72,10 @@ typedef struct Manager { FILE *console; double percent; int numdevices; + int plymouth_fd; + sd_event_source *plymouth_event_source; + bool plymouth_cancel_sent; bool cancel_requested; } Manager; @@ -102,16 +105,21 @@ static double compute_percent(int pass, size_t cur, size_t max) { } static int request_cancel_client(Client *current) { - FsckdMessage cancel_msg; + FsckdMessage cancel_msg = { + .cancel = 1, + }; + ssize_t n; - cancel_msg.cancel = 1; n = send(current->fd, &cancel_msg, sizeof(FsckdMessage), 0); - if (n < 0 || (size_t) n < sizeof(FsckdMessage)) - return log_warning_errno(n, "Cannot send cancel to fsck on (%u, %u): %m", - major(current->devnum), minor(current->devnum)); - else - current->cancelled = true; + if (n < 0) + return log_warning_errno(errno, "Cannot send cancel to fsck on (%u:%u): %m", major(current->devnum), minor(current->devnum)); + if ((size_t) n < sizeof(FsckdMessage)) { + log_warning("Short send when sending cancel to fsck on (%u:%u).", major(current->devnum), minor(current->devnum)); + return -EIO; + } + + current->cancelled = true; return 0; } @@ -121,7 +129,10 @@ static void remove_client(Client **first, Client *item) { free(item); } -static void on_plymouth_disconnect(Manager *m) { +static void plymouth_disconnect(Manager *m) { + assert(m); + + m->plymouth_event_source = sd_event_source_unref(m->plymouth_event_source); m->plymouth_fd = safe_close(m->plymouth_fd); m->plymouth_cancel_sent = false; } @@ -130,24 +141,31 @@ static int plymouth_feedback_handler(sd_event_source *s, int fd, uint32_t revent Manager *m = userdata; Client *current; char buffer[6]; - int r; + ssize_t l; assert(m); - r = read(m->plymouth_fd, buffer, sizeof(buffer)); - if (r <= 0) - on_plymouth_disconnect(m); - else { - if (buffer[0] == '\15') - log_error("Message update to plymouth wasn't delivered successfully"); - - /* the only answer support type we requested is a key interruption */ - if (buffer[0] == '\2' && buffer[5] == '\3') { - m->cancel_requested = true; - /* cancel all connected clients */ - LIST_FOREACH(clients, current, m->clients) - request_cancel_client(current); - } + l = read(m->plymouth_fd, buffer, sizeof(buffer)); + if (l < 0) { + log_warning_errno(errno, "Got error while reading from plymouth: %m"); + plymouth_disconnect(m); + return -errno; + } + if (l == 0) { + plymouth_disconnect(m); + return 0; + } + + if (buffer[0] == '\15') + log_error("Message update to plymouth wasn't delivered successfully"); + + /* the only answer support type we requested is a key interruption */ + if (buffer[0] == '\2' && buffer[5] == '\3') { + m->cancel_requested = true; + + /* cancel all connected clients */ + LIST_FOREACH(clients, current, m->clients) + request_cancel_client(current); } return 0; @@ -155,7 +173,7 @@ static int plymouth_feedback_handler(sd_event_source *s, int fd, uint32_t revent static int send_message_plymouth_socket(int plymouth_fd, const char *message, bool update) { _cleanup_free_ char *packet = NULL; - int r, n; + int n; char mode = 'M'; if (update) @@ -163,31 +181,37 @@ static int send_message_plymouth_socket(int plymouth_fd, const char *message, bo if (asprintf(&packet, "%c\002%c%s%n", mode, (int) (strlen(message) + 1), message, &n) < 0) return log_oom(); - r = loop_write(plymouth_fd, packet, n + 1, true); - return r; -} + return loop_write(plymouth_fd, packet, n + 1, true); +} static int send_message_plymouth(Manager *m, const char *message) { - int r; const char *plymouth_cancel_message = NULL; + int r; r = connect_plymouth(m); if (r < 0) return r; if (!m->plymouth_cancel_sent) { - /* indicate to plymouth that we listen to Ctrl+C */ + + /* Indicate to plymouth that we listen to Ctrl+C */ r = loop_write(m->plymouth_fd, PLYMOUTH_REQUEST_KEY, sizeof(PLYMOUTH_REQUEST_KEY), true); if (r < 0) - return log_warning_errno(errno, "Can't send to plymouth cancel key: %m"); + return log_warning_errno(r, "Can't send to plymouth cancel key: %m"); + m->plymouth_cancel_sent = true; + plymouth_cancel_message = strjoina("fsckd-cancel-msg:", _("Press Ctrl+C to cancel all filesystem checks in progress")); + r = send_message_plymouth_socket(m->plymouth_fd, plymouth_cancel_message, false); if (r < 0) log_warning_errno(r, "Can't send filesystem cancel message to plymouth: %m"); + } else if (m->numdevices == 0) { + m->plymouth_cancel_sent = false; + r = send_message_plymouth_socket(m->plymouth_fd, "", false); if (r < 0) log_warning_errno(r, "Can't clear plymouth filesystem cancel message: %m"); @@ -195,7 +219,7 @@ static int send_message_plymouth(Manager *m, const char *message) { r = send_message_plymouth_socket(m->plymouth_fd, message, true); if (r < 0) - return log_warning_errno(errno, "Couldn't send \"%s\" to plymouth: %m", message); + return log_warning_errno(r, "Couldn't send \"%s\" to plymouth: %m", message); return 0; } @@ -265,7 +289,7 @@ static int connect_plymouth(Manager *m) { goto fail; } - r = sd_event_add_io(m->event, NULL, m->plymouth_fd, EPOLLIN, plymouth_feedback_handler, m); + r = sd_event_add_io(m->event, &m->plymouth_event_source, m->plymouth_fd, EPOLLIN, plymouth_feedback_handler, m); if (r < 0) { log_warning_errno(r, "Can't listen to plymouth socket: %m"); goto fail; @@ -274,7 +298,7 @@ static int connect_plymouth(Manager *m) { return 0; fail: - on_plymouth_disconnect(m); + plymouth_disconnect(m); return r; } @@ -384,8 +408,10 @@ static void manager_free(Manager *m) { fflush(m->console); } + plymouth_disconnect(m); + safe_close(m->connection_fd); - safe_close(m->plymouth_fd); + if (m->console) fclose(m->console);