]> git.ipfire.org Git - pakfire.git/commitdiff
pty: Use our own buffer implementation
authorMichael Tremer <michael.tremer@ipfire.org>
Mon, 24 Mar 2025 16:49:40 +0000 (16:49 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Mon, 24 Mar 2025 16:49:40 +0000 (16:49 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/pakfire/buffer.c
src/pakfire/buffer.h
src/pakfire/log_stream.c
src/pakfire/pty.c

index ae8fd11342d381c58d997d606797f6e5ed13e484..ddf5543eeec17a8983d69fd2edafe5975e750e91 100644 (file)
@@ -34,6 +34,22 @@ void pakfire_buffer_set_max_length(struct pakfire_buffer* self, size_t max_lengt
        self->max_length = max_length;
 }
 
+size_t pakfire_buffer_length(struct pakfire_buffer* self) {
+       return self->used;
+}
+
+int pakfire_buffer_is_empty(struct pakfire_buffer* self) {
+       return (self->used == 0);
+}
+
+int pakfire_buffer_is_full(struct pakfire_buffer* self) {
+       // Cannot be full if we don't have no maximum size
+       if (!self->max_length)
+               return 0;
+
+       return (self->used >= self->max_length);
+}
+
 void pakfire_buffer_free(struct pakfire_buffer* buffer) {
        if (buffer->data)
                free(buffer->data);
@@ -108,7 +124,20 @@ int pakfire_buffer_push(struct pakfire_buffer* self, const char* data, size_t le
        return 0;
 }
 
-int pakfire_buffer_push_from_fd(struct pakfire_buffer* self, int fd) {
+int pakfire_buffer_pop(struct pakfire_buffer* self, size_t length) {
+       // Check if we actually have enough data
+       if (self->used < length)
+               return -EINVAL;
+
+       memmove(self->data, self->data + length, self->used - length);
+       self->used -= length;
+
+       // Shrink the buffer if we need to
+       return pakfire_buffer_shrink(self);
+}
+
+int pakfire_buffer_read(struct pakfire_buffer* self, int fd) {
+       ssize_t total_bytes_read = 0;
        ssize_t bytes_read = 0;
        int r;
 
@@ -122,7 +151,10 @@ int pakfire_buffer_push_from_fd(struct pakfire_buffer* self, int fd) {
                // Read into the buffer
                bytes_read = read(fd, self->data + self->used, self->length - self->used);
                if (bytes_read < 0)
-                       return bytes_read;
+                       return -errno;
+
+               // Update the total counter
+               total_bytes_read += bytes_read;
 
                // We now use more space
                self->used += bytes_read;
@@ -132,19 +164,28 @@ int pakfire_buffer_push_from_fd(struct pakfire_buffer* self, int fd) {
                        break;
        }
 
-       return 0;
+       return total_bytes_read;
 }
 
-int pakfire_buffer_pop(struct pakfire_buffer* self, size_t length) {
-       // Check if we actually have enough data
-       if (self->used < length)
-               return -EINVAL;
+int pakfire_buffer_write(struct pakfire_buffer* self, int fd) {
+       ssize_t bytes_written = 0;
+       int r;
 
-       memmove(self->data, self->data + length, self->used - length);
-       self->used -= length;
+       // Do nothing if the buffer is empty
+       if (!self->used)
+               return 0;
 
-       // Shrink the buffer if we need to
-       return pakfire_buffer_shrink(self);
+       // Write as much data as possible
+       bytes_written = write(fd, self->data, self->used);
+       if (bytes_written < 0)
+               return -errno;
+
+       // Remove any written data
+       r = pakfire_buffer_pop(self, bytes_written);
+       if (r < 0)
+               return r;
+
+       return bytes_written;
 }
 
 size_t pakfire_buffer_find_line(struct pakfire_buffer* self) {
index 6c69afdd71785463c428c58f4b4d0908e1bb929c..97a521a19bbdfa9e06b7f2e83559c104b4874d89 100644 (file)
@@ -34,13 +34,18 @@ struct pakfire_buffer {
 
 void pakfire_buffer_set_max_length(struct pakfire_buffer* buffer, size_t max_length);
 
+size_t pakfire_buffer_length(struct pakfire_buffer* self);
+int pakfire_buffer_is_empty(struct pakfire_buffer* self);
+int pakfire_buffer_is_full(struct pakfire_buffer* self);
+
 void pakfire_buffer_free(struct pakfire_buffer* buffer);
 
 int pakfire_buffer_push(struct pakfire_buffer* self, const char* data, size_t length);
-int pakfire_buffer_push_from_fd(struct pakfire_buffer* self, int fd);
-
 int pakfire_buffer_pop(struct pakfire_buffer* self, size_t length);
 
+int pakfire_buffer_read(struct pakfire_buffer* self, int fd);
+int pakfire_buffer_write(struct pakfire_buffer* self, int fd);
+
 size_t pakfire_buffer_find_line(struct pakfire_buffer* self);
 
 #endif /* PAKFIRE_BUFFER_H */
index 7148f0a79fab15bf800716ff8128846a3cca4dc4..01858bc20a12231a5221aff670f7c6dc6889bad6 100644 (file)
@@ -277,7 +277,7 @@ static int __pakfire_log_stream(sd_event_source* s, int fd, uint32_t events, voi
 
        if (events & EPOLLIN) {
                // Fill the buffer
-               r = pakfire_buffer_push_from_fd(&stream->buffer, fd);
+               r = pakfire_buffer_read(&stream->buffer, fd);
                if (r < 0)
                        return r;
 
index b830f84b2a0f3347ffdfaacce11141cfd677b315..8541c50dd4bcb1a9726f1c5a626f01d25829ad2c 100644 (file)
@@ -29,6 +29,7 @@
 
 #include <systemd/sd-event.h>
 
+#include <pakfire/buffer.h>
 #include <pakfire/ctx.h>
 #include <pakfire/file.h>
 #include <pakfire/filelist.h>
@@ -44,8 +45,7 @@ struct pakfire_pty_stdio {
        unsigned close_fd:1;
 
        // Buffer
-       char buffer[MAX_LINE_LENGTH];
-       size_t buffered;
+       struct pakfire_buffer buffer;
 
        // Terminal Attributes
        struct termios attrs;
@@ -197,20 +197,6 @@ static int pakfire_pty_store_attrs(struct pakfire_pty* pty,
        return 0;
 }
 
-static int pakfire_pty_buffer_is_full(struct pakfire_pty* pty, const struct pakfire_pty_stdio* stdio) {
-       if (stdio->buffered >= sizeof(stdio->buffer))
-               return 1;
-
-       return 0;
-}
-
-static int pakfire_pty_buffer_has_data(struct pakfire_pty* pty, const struct pakfire_pty_stdio* stdio) {
-       if (stdio->buffered)
-               return 1;
-
-       return 0;
-}
-
 static int pakfire_pty_disconnect(struct pakfire_pty* pty) {
        DEBUG(pty->ctx, "Disconnecting the PTY\n");
 
@@ -246,7 +232,7 @@ static int pakfire_pty_drained(struct pakfire_pty* pty) {
                return 1;
 
        // We still have data in the buffer
-       if (pakfire_pty_buffer_has_data(pty, &pty->stdout))
+       if (!pakfire_buffer_is_empty(&pty->stdout.buffer))
                return 0;
 
        // There is still data in the PTY buffer
@@ -299,45 +285,6 @@ static int pakfire_pty_done(struct pakfire_pty* pty, int code) {
        return 0;
 }
 
-/*
-       Reads as much data as possible into the buffer
-*/
-static int pakfire_pty_fill_buffer(struct pakfire_pty* pty, int fd, struct pakfire_pty_stdio* stdio) {
-       ssize_t bytes_read = 0;
-
-       // Read from the file descriptor
-       bytes_read = read(fd, stdio->buffer + stdio->buffered, sizeof(stdio->buffer) - stdio->buffered);
-
-       // Abort on errors
-       if (bytes_read < 0)
-               return -errno;
-
-       // Successful read
-       stdio->buffered += bytes_read;
-
-       return bytes_read;
-}
-
-/*
-       Writes as much data as possible from the buffer
-*/
-static int pakfire_pty_drain_buffer(struct pakfire_pty* pty, int fd, struct pakfire_pty_stdio* stdio) {
-       ssize_t bytes_written = 0;
-
-       // Write to the file descriptor
-       bytes_written = write(fd, stdio->buffer, stdio->buffered);
-
-       // Abort on error
-       if (bytes_written < 0)
-               return -errno;
-
-       // Successful write
-       memmove(stdio->buffer, stdio->buffer + bytes_written, stdio->buffered - bytes_written);
-       stdio->buffered -= bytes_written;
-
-       return bytes_written;
-}
-
 /*
        This function handles the forwarding between the different pipes...
 */
@@ -374,11 +321,8 @@ static int pakfire_pty_forward(struct pakfire_pty* pty) {
                // Read from standard input if we are asked to read and
                // there is still space in the buffer..
                if ((pty->stdin.io & PAKFIRE_PTY_READY_TO_READ)
-                               && !pakfire_pty_buffer_is_full(pty, &pty->stdin)) {
-                       DEBUG(pty->ctx, "Reading from standard input...\n");
-
-                       // Fill up the buffer
-                       r = pakfire_pty_fill_buffer(pty, pty->stdin.fd, &pty->stdin);
+                               && !pakfire_buffer_is_full(&pty->stdin.buffer)) {
+                       r = pakfire_buffer_read(&pty->stdin.buffer, pty->stdin.fd);
                        if (r < 0) {
                                switch (-r) {
                                        // We have been signaled, that currently there is no data available to read
@@ -429,11 +373,8 @@ static int pakfire_pty_forward(struct pakfire_pty* pty) {
 
                // Write to the master if there is any input data
                if ((pty->master.io & PAKFIRE_PTY_READY_TO_WRITE)
-                               && pakfire_pty_buffer_has_data(pty, &pty->stdin)) {
-                       DEBUG(pty->ctx, "Writing to master...\n");
-
-                       // Drain the input buffer...
-                       r = pakfire_pty_drain_buffer(pty, pty->master.fd, &pty->stdin);
+                               && !pakfire_buffer_is_empty(&pty->stdin.buffer)) {
+                       r = pakfire_buffer_write(&pty->stdin.buffer, pty->master.fd);
                        if (r < 0) {
                                switch (-r) {
                                        // We have been signaled that we cannot write any more data...
@@ -471,10 +412,8 @@ static int pakfire_pty_forward(struct pakfire_pty* pty) {
 
                // Read from the master until the buffer is full
                if ((pty->master.io & PAKFIRE_PTY_READY_TO_READ)
-                               && !pakfire_pty_buffer_is_full(pty, &pty->stdout)) {
-                       DEBUG(pty->ctx, "Reading from master...\n");
-
-                       r = pakfire_pty_fill_buffer(pty, pty->master.fd, &pty->stdout);
+                               && !pakfire_buffer_is_full(&pty->stdout.buffer)) {
+                       r = pakfire_buffer_read(&pty->stdout.buffer, pty->master.fd);
                        if (r < 0) {
                                switch (-r) {
                                        // We have been signalled that we cannot send any more data...
@@ -525,10 +464,8 @@ static int pakfire_pty_forward(struct pakfire_pty* pty) {
 
                // Write to standard output until the buffer is drained
                if ((pty->stdout.io & PAKFIRE_PTY_READY_TO_WRITE)
-                               && pakfire_pty_buffer_has_data(pty, &pty->stdout)) {
-                       DEBUG(pty->ctx, "Writing to standard output...\n");
-
-                       r = pakfire_pty_drain_buffer(pty, pty->stdout.fd, &pty->stdout);
+                               && !pakfire_buffer_is_empty(&pty->stdout.buffer)) {
+                       r = pakfire_buffer_write(&pty->stdout.buffer, pty->stdout.fd);
                        if (r < 0) {
                                switch (-r) {
                                        // We have been signalled that we are no longer able to write...
@@ -570,9 +507,9 @@ static int pakfire_pty_forward(struct pakfire_pty* pty) {
                DEBUG(pty->ctx, "Something hung up...\n");
 
                // Terminate the event loop after all buffers have been emptied or cannot be emptied
-               if ((!pakfire_pty_buffer_has_data(pty, &pty->stdout)
+               if ((pakfire_buffer_is_empty(&pty->stdout.buffer)
                                || (pty->stdout.io & PAKFIRE_PTY_HANGUP))
-                       && (!pakfire_pty_buffer_has_data(pty, &pty->stdin)
+                       && (pakfire_buffer_is_empty(&pty->stdin.buffer)
                                || (pty->stdin.io & PAKFIRE_PTY_HANGUP)))
                        return pakfire_pty_done(pty, 0);
        }
@@ -1092,6 +1029,10 @@ static void pakfire_pty_free(struct pakfire_pty* pty) {
        if (pty->exit_event)
                sd_event_source_unref(pty->exit_event);
 
+       // Free buffers
+       pakfire_buffer_free(&pty->stdin.buffer);
+       pakfire_buffer_free(&pty->stdout.buffer);
+
        if (pty->loop)
                sd_event_unref(pty->loop);
        if (pty->ctx)
@@ -1141,6 +1082,10 @@ int pakfire_pty_create(struct pakfire_pty** pty, struct pakfire_ctx* ctx, sd_eve
                goto ERROR;
        }
 
+       // Set buffer sizes
+       pakfire_buffer_set_max_length(&p->stdin.buffer, MAX_LINE_LENGTH);
+       pakfire_buffer_set_max_length(&p->stdout.buffer, MAX_LINE_LENGTH);
+
        // Return the pointer
        *pty = p;