chiark / gitweb /
fsck: use _cleanup_close_pair_ where appropriate
[elogind.git] / src / fsckd / fsckd.c
index 36b890a7de73763f474e397acb622228f70b401e..dedc828a890b014233a64d6c33dd785dc199dbac 100644 (file)
@@ -47,6 +47,7 @@
 
 #define IDLE_TIME_SECONDS 30
 #define PLYMOUTH_REQUEST_KEY "K\2\2\3"
+#define CLIENTS_MAX 128
 
 struct Manager;
 
@@ -64,6 +65,8 @@ typedef struct Client {
         size_t buflen;
         bool cancelled;
 
+        sd_event_source *event_source;
+
         LIST_FIELDS(struct Client, clients);
 } Client;
 
@@ -71,11 +74,15 @@ typedef struct Manager {
         sd_event *event;
 
         LIST_HEAD(Client, clients);
+        unsigned n_clients;
 
         int clear;
+
         int connection_fd;
+        sd_event_source *connection_event_source;
 
         FILE *console;
+
         double percent;
         int numdevices;
 
@@ -86,7 +93,10 @@ typedef struct Manager {
         bool cancel_requested;
 } Manager;
 
+static void client_free(Client *c);
 static void manager_free(Manager *m);
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(Client*, client_free);
 DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
 
 static double compute_percent(int pass, size_t cur, size_t max) {
@@ -134,8 +144,12 @@ static int client_request_cancel(Client *c) {
 static void client_free(Client *c) {
         assert(c);
 
-        if (c->manager)
+        if (c->manager) {
                 LIST_REMOVE(clients, c->manager->clients, c);
+                c->manager->n_clients--;
+        }
+
+        sd_event_source_unref(c->event_source);
 
         safe_close(c->fd);
         free(c);
@@ -372,9 +386,10 @@ static int client_progress_handler(sd_event_source *s, int fd, uint32_t revents,
 }
 
 static int manager_new_connection_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+        _cleanup_(client_freep) Client *c = NULL;
+        _cleanup_close_ int new_client_fd = -1;
         Manager *m = userdata;
-        Client *client = NULL;
-        int new_client_fd, r;
+        int r;
 
         assert(m);
 
@@ -383,23 +398,37 @@ static int manager_new_connection_handler(sd_event_source *s, int fd, uint32_t r
         if (new_client_fd < 0)
                 return log_error_errno(errno, "Couldn't accept a new connection: %m");
 
+        if (m->n_clients >= CLIENTS_MAX) {
+                log_error("Too many clients, refusing connection.");
+                return 0;
+        }
+
         log_debug("New fsck client connected to fd: %d", new_client_fd);
 
-        client = new0(Client, 1);
-        if (!client)
-                return log_oom();
-        client->fd = new_client_fd;
-        client->manager = m;
-        LIST_PREPEND(clients, m->clients, client);
-        r = sd_event_add_io(m->event, NULL, client->fd, EPOLLIN, client_progress_handler, client);
+        c = new0(Client, 1);
+        if (!c) {
+                log_oom();
+                return 0;
+        }
+
+        c->fd = new_client_fd;
+        new_client_fd = -1;
+
+        r = sd_event_add_io(m->event, &c->event_source, c->fd, EPOLLIN, client_progress_handler, c);
         if (r < 0) {
-                client_free(client);
-                return r;
+                log_oom();
+                return 0;
         }
+
+        LIST_PREPEND(clients, m->clients, c);
+        m->n_clients++;
+        c->manager = m;
+
         /* only request the client to cancel now in case the request is dropped by the client (chance to recancel) */
         if (m->cancel_requested)
-                client_request_cancel(client);
+                client_request_cancel(c);
 
+        c = NULL;
         return 0;
 }
 
@@ -418,6 +447,7 @@ static void manager_free(Manager *m) {
                 fflush(m->console);
         }
 
+        sd_event_source_unref(m->connection_event_source);
         safe_close(m->connection_fd);
 
         while (m->clients)
@@ -457,7 +487,7 @@ static int manager_new(Manager **ret, int fd) {
                         return -errno;
         }
 
-        r = sd_event_add_io(m->event, NULL, fd, EPOLLIN, manager_new_connection_handler, m);
+        r = sd_event_add_io(m->event, &m->connection_event_source, fd, EPOLLIN, manager_new_connection_handler, m);
         if (r < 0)
                 return r;