From 02bc46456453e8530a3c9f1289dfce7e71371945 Mon Sep 17 00:00:00 2001 From: Jeremy Attali Date: Sun, 29 Dec 2019 16:48:13 -0500 Subject: [PATCH] feat(buffer): ability to read from stdin --- .vscode/launch.json | 24 ++++++++++++++++++++++ include/file.h | 1 + src/application.c | 22 +++++++------------- src/buffer.c | 7 ++++++- src/file.c | 49 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 87 insertions(+), 16 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 49fb65b..17a5cab 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -51,6 +51,30 @@ "ignoreFailures": true } ] + }, + { + "name": "swappy - stdin", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/build/meson-out/swappy", + "args": ["-f", "-"], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [ + { + "name": "G_MESSAGES_DEBUG", + "value": "all" + } + ], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] } ] } diff --git a/include/file.h b/include/file.h index f895fed..2e30c6a 100644 --- a/include/file.h +++ b/include/file.h @@ -2,3 +2,4 @@ bool folder_exists(const char *path); bool file_exists(const char *path); +char *file_dump_stdin_into_a_temp_file(); diff --git a/src/application.c b/src/application.c index 612341c..e39137f 100644 --- a/src/application.c +++ b/src/application.c @@ -157,6 +157,7 @@ void application_finish(struct swappy_state *state) { cairo_surface_destroy(state->cairo_surface); cairo_surface_destroy(state->image_surface); g_free(state->storage_path); + g_free(state->file_str); g_free(state->geometry_str); g_free(state->geometry); g_free(state->ui); @@ -531,19 +532,8 @@ static gboolean has_option_file(struct swappy_state *state) { return (state->file_str != NULL); } -static gboolean is_file_valid(const char *file) { - cairo_surface_t *surface = cairo_image_surface_create_from_png(file); - cairo_status_t status = cairo_surface_status(surface); - - if (status) { - g_warning("error while loading: %s - cairo status: %s", file, - cairo_status_to_string(status)); - return false; - } - - cairo_surface_destroy(surface); - - return true; +static gboolean is_file_from_stdin(const char *file) { + return (strcmp(file, "-") == 0); } static gint command_line_handler(GtkApplication *app, @@ -560,8 +550,10 @@ static gint command_line_handler(GtkApplication *app, } if (has_option_file(state)) { - if (!is_file_valid(state->file_str)) { - return EXIT_FAILURE; + if (is_file_from_stdin(state->file_str)) { + char *new_file_str = file_dump_stdin_into_a_temp_file(); + g_free(state->file_str); + state->file_str = new_file_str; } if (!buffer_init_from_file(state)) { diff --git a/src/buffer.c b/src/buffer.c index 3904a6d..f6e4731 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -178,8 +178,13 @@ bool buffer_init_from_file(struct swappy_state *state) { char *file = state->file_str; cairo_surface_t *surface = cairo_image_surface_create_from_png(file); + cairo_status_t status = cairo_surface_status(surface); - g_assert(surface); + if (status) { + g_warning("error while loading png file: %s - cairo status: %s", file, + cairo_status_to_string(status)); + return false; + } int width = cairo_image_surface_get_width(surface); int height = cairo_image_surface_get_height(surface); diff --git a/src/file.c b/src/file.c index c678bbf..058b064 100644 --- a/src/file.c +++ b/src/file.c @@ -1,7 +1,15 @@ #define _POSIX_C_SOURCE 200112L +#include +#include +#include +#include #include #include +#include +#include + +#define BLOCK_SIZE 1024 bool folder_exists(const char *path) { struct stat sb; @@ -18,3 +26,44 @@ bool file_exists(const char *path) { return (stat(path, &sb) == 0 && S_ISREG(sb.st_mode)); } + +char *file_dump_stdin_into_a_temp_file() { + char buf[BLOCK_SIZE]; + GError *error = NULL; + + if (isatty(STDIN_FILENO)) { + g_warning("stdin is a tty"); + return NULL; + } + + // Reopen stdin as binary mode + g_freopen(NULL, "rb", stdin); + + const gchar *tempdir = g_get_tmp_dir(); + gchar filename[] = "swappy-stdin-XXXXXX.png"; + gchar *ret = g_build_filename(tempdir, filename, NULL); + gint fd = g_mkstemp(ret); + + if (fd == -1) { + g_warning("unable to dump stdin into temporary file"); + return NULL; + } + + g_info("writing stdin content into filepath: %s", ret); + + size_t count = 1; + while (count > 0) { + count = fread(buf, 1, sizeof(buf), stdin); + write(fd, &buf, count); + } + + g_close(fd, &error); + + if (error) { + g_warning("unable to close temporary file: %s", error->message); + g_error_free(error); + return NULL; + } + + return ret; +} \ No newline at end of file