From fe4f027a26f5cb1213d21be45da3fc742dff7db5 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Thu, 20 Oct 2011 14:48:04 +0300 Subject: [PATCH 1/1] Initial commit Basic functionality is done --- .gitignore | 1 + Makefile | 2 + main.c | 323 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 326 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 main.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ed33602 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/pmount-gui diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..dd03d7c --- /dev/null +++ b/Makefile @@ -0,0 +1,2 @@ +pmount-gui: main.c + $(CC) -Wall -Wextra -o $@ $^ $(shell pkg-config --cflags --libs gtk+-2.0) diff --git a/main.c b/main.c new file mode 100644 index 0000000..10bf929 --- /dev/null +++ b/main.c @@ -0,0 +1,323 @@ +#include +#include +#include +#include +#include +#include +#include + +typedef struct sProperty +{ + char *name; + char *value; +} Property; + +typedef struct sDevice +{ + char *node; + char *label; + char *description; + time_t time; +} Device; + +int parse_property(char *str, int size, Property *prop) +{ + int equals = -1; + int i; + + for(i=0; (equals<0 && iname = malloc(equals+1); + strncpy(prop->name, str, equals); + prop->name[equals] = 0; + + prop->value = malloc(size-equals); + strncpy(prop->value, str+equals+1, size-equals-1); + prop->value[size-equals-1] = 0; + + return 0; +} + +Property *get_device_properties(char *node) +{ + int pid; + int pipe_fd[2]; + + /*printf("Examining device %s\n", node);*/ + + pipe(pipe_fd); + + pid = fork(); + if(pid==0) + { + close(pipe_fd[0]); + dup2(pipe_fd[1], 1); + + execl("/sbin/udevadm", "udevadm", "info", "-q", "property", "-n", node, NULL); + _exit(1); + } + else if(pid>0) + { + char buf[256]; + int pos = 0; + int eof = 0; + Property *props = NULL; + int n_props = 0; + + close(pipe_fd[1]); + + while(1) + { + int newline; + int i; + Property prop; + + if(!eof) + { + int len; + + len = read(pipe_fd[0], buf+pos, sizeof(buf)-pos); + if(len==0) + eof = 1; + else if(len==-1) + break; + pos += len; + } + + newline = -1; + for(i=0; (newline<0 && id_name[0]=='.' && (de->d_name[1]==0 || (de->d_name[1]=='.' && de->d_name[2]==0))) + continue; + + snprintf(fnbuf, sizeof(fnbuf), "/dev/disk/by-id/%s", de->d_name); + Property *props = get_device_properties(fnbuf); + if(match_property_value(props, "ID_BUS", "usb") && match_property_value(props, "DEVTYPE", "partition")) + { + char *label; + char *vendor; + char *model; + char buf[256]; + char pos; + struct stat st; + + /*printf("Using device %s\n", fnbuf);*/ + + label = get_property_value(props, "ID_FS_LABEL"); + if(!label) + label = get_property_value(props, "ID_FS_UUID"); + if(!label) + { + char *ptr; + + label = get_property_value(props, "DEVNAME"); + for(ptr=label; *ptr; ++ptr) + if(*ptr=='/') + label = ptr+1; + } + vendor = get_property_value(props, "ID_VENDOR"); + model = get_property_value(props, "ID_MODEL"); + + pos = snprintf(buf, sizeof(buf), "%s", label); + if(vendor && model) + pos += snprintf(buf+pos, sizeof(buf)-pos, " (%s %s)", vendor, model); + + stat(fnbuf, &st); + + devices = (Device *)realloc(devices, (n_devices+2)*sizeof(Device)); + devices[n_devices].node = strdup(fnbuf); + devices[n_devices].label = strdup(label); + devices[n_devices].description = strdup(buf); + devices[n_devices].time = st.st_mtime; + ++n_devices; + } + free_properties(props); + } + + devices[n_devices].node = NULL; + devices[n_devices].label = NULL; + + return devices; +} + +void free_devices(Device *devices) +{ + int i; + if(!devices) + return; + for(i=0; devices[i].node; ++i) + { + free(devices[i].node); + free(devices[i].label); + } + free(devices); +} + +void row_activated(GtkTreeView *list, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data) +{ + GtkTreeModel *model; + GtkTreeIter iter; + + model = gtk_tree_view_get_model(list); + + if(gtk_tree_model_get_iter(model, &iter, path)) + { + Device *device; + int pid; + + gtk_tree_model_get(model, &iter, 1, &device, -1); + + pid = fork(); + if(pid==0) + { + execl("/usr/bin/pmount", "pmount", device->node, device->label, NULL); + _exit(1); + } + else if(pid>0) + { + waitpid(pid, NULL, 0); + } + } + + (void)column; + (void)user_data; + + gtk_main_quit(); +} + +int main(int argc, char **argv) +{ + GtkWidget *window; + GtkWidget *viewport; + GtkWidget *list; + GtkListStore *store; + GtkTreeSelection *selection; + GtkTreeIter iter; + Device *devices; + int i; + time_t latest; + + gtk_init(&argc, &argv); + + window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_container_set_border_width(GTK_CONTAINER(window), 5); + g_signal_connect(window, "destroy", >k_main_quit, NULL); + + viewport = gtk_viewport_new(NULL, NULL); + gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_IN); + gtk_container_add(GTK_CONTAINER(window), viewport); + + list = gtk_tree_view_new(); + gtk_container_add(GTK_CONTAINER(viewport), list); + g_signal_connect(list, "row-activated", (GCallback)&row_activated, NULL); + + store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER); + gtk_tree_view_set_model(GTK_TREE_VIEW(list), GTK_TREE_MODEL(store)); + gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(list), + -1, "Device", gtk_cell_renderer_text_new(), "text", 0, NULL); + + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list)); + + devices = get_devices(); + latest = 0; + for(i=0; devices[i].node; ++i) + { + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, devices[i].description, 1, &devices[i], -1); + if(devices[i].time>latest) + { + latest = devices[i].time; + gtk_tree_selection_select_iter(selection, &iter); + } + } + + gtk_widget_show_all(window); + gtk_main(); + + free_devices(devices); + + return 0; +} -- 2.45.2