Skip to content

Instantly share code, notes, and snippets.

@angstyloop
Created March 7, 2023 09:41
Show Gist options
  • Save angstyloop/2b887221706376f7933f15c4227acb6d to your computer and use it in GitHub Desktop.
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.
/** 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