Created
March 7, 2023 09:41
-
-
Save angstyloop/2b887221706376f7933f15c4227acb6d to your computer and use it in GitHub Desktop.
Select a file using a GTK file chooser, and copy it into /tmp (Unix only) using copy_file_range.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** import_file.c | |
* | |
* Import a file to be used by threshold.c and friends. | |
* | |
* COMPILE | |
* gcc -Wall -o import_file import_file.c `pkg-config gtk+-3.0 --libs --cflags` | |
* | |
* EXAMPLE | |
* ./import_file source.png | |
*/ | |
#define _GNU_SOURCE | |
#include <fcntl.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <sys/stat.h> | |
#include <sys/syscall.h> | |
#include <unistd.h> | |
#include <gtk/gtk.h> | |
#define GCC_VERSION (__GNUC__*10000 + __GNUC_MINOR__*100 + __gnuc_patchlevel__) | |
#if GCC_VERSION < 22700 | |
static loff_t copy_file_range(int in, | |
loff_t* off_in, | |
int out, | |
loff_t* off_out, | |
size_t s, | |
unsigned int flags) { | |
return syscall(__NR_copy_file_range, | |
in, | |
off_in, | |
fout, | |
off_out, | |
s, | |
flags); | |
} | |
#endif | |
static gboolean copy_file(char* source, char* target) { | |
int fd_in = 0, fd_out = 0; | |
struct stat stat = {0}; | |
if ((fd_in = open(source, O_RDONLY)) == -1 || | |
fstat(fd_in, &stat) == -1 || | |
(fd_out = open(target, | |
O_CREAT | O_WRONLY | O_TRUNC, | |
0644)) == -1) { | |
printf("fd_in: %d, fd_out: %d, target: %s", fd_in, fd_out, target); | |
return FALSE; | |
} | |
loff_t ret = {0}; | |
loff_t len = stat.st_size; | |
do { | |
if ((ret = copy_file_range(fd_in, | |
NULL, | |
fd_out, | |
NULL, | |
len, 0)) == -1) { | |
perror("copy_file_range"); | |
exit(EXIT_FAILURE); | |
} | |
len -= ret; | |
} while (len > 0 && ret > 0); | |
close(fd_in); | |
close(fd_out); | |
return TRUE; | |
} | |
static gboolean import_file(char* source, char* target) { | |
int fd = -1; | |
if ((fd = open(source, O_RDONLY) == -1)) { | |
return FALSE; | |
} else { | |
close(fd); | |
copy_file(source, target); | |
return TRUE; | |
} | |
} | |
#define IMPORT_TARGET "/tmp/input_image" | |
static void on_response(GtkFileChooserDialog* chooser, int response) { | |
if (response == GTK_RESPONSE_ACCEPT) { | |
GFile* file = gtk_file_chooser_get_file(GTK_FILE_CHOOSER(chooser)); | |
gchar* source_file_path = g_file_get_path(file); | |
if(import_file(source_file_path, IMPORT_TARGET)) { | |
puts("Imported file."); | |
} else { | |
puts("Failed to import file."); | |
} | |
puts(source_file_path); | |
g_free(source_file_path); | |
g_object_unref(file); | |
} | |
g_object_unref(chooser); | |
} | |
int main(int argc, char** argv) { | |
gtk_init(&argc, &argv); | |
GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | |
GtkWidget* chooser = | |
gtk_file_chooser_dialog_new("Open File", | |
(GtkWindow*) window, | |
GTK_FILE_CHOOSER_ACTION_OPEN, | |
"Cancel", | |
GTK_RESPONSE_CANCEL, | |
"Open", | |
GTK_RESPONSE_ACCEPT, | |
NULL); | |
g_signal_connect(chooser, "response", G_CALLBACK(on_response), NULL); | |
gtk_widget_show(chooser); | |
gtk_main(); | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment