Initial commit
authorMikko Rasa <tdb@tdb.fi>
Thu, 20 Oct 2011 11:48:04 +0000 (14:48 +0300)
committerMikko Rasa <mikko.rasa@movial.com>
Thu, 20 Oct 2011 12:12:25 +0000 (15:12 +0300)
Basic functionality is done

.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
main.c [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..ed33602
--- /dev/null
@@ -0,0 +1 @@
+/pmount-gui
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
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 (file)
index 0000000..10bf929
--- /dev/null
+++ b/main.c
@@ -0,0 +1,323 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <gtk/gtk.h>
+
+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 && i<size); ++i)
+               if(str[i]=='=')
+                       equals = i;
+
+       if(equals<0)
+               return -1;
+
+       prop->name = 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 && i<pos); ++i)
+                               if(buf[i]=='\n')
+                                       newline = i;
+
+                       if(newline<0)
+                               break;
+
+                       if(parse_property(buf, newline, &prop)==0)
+                       {
+                               /*printf("Got property '%s' = '%s'\n", prop.name, prop.value);*/
+
+                               props = (Property *)realloc(props, (n_props*2)*sizeof(Property));
+                               props[n_props] = prop;
+                               ++n_props;
+
+                               memmove(buf, buf+newline+1, pos-newline-1);
+                               pos -= newline+1;
+                       }
+                       else
+                               break;
+               }
+
+               props[n_props].name = NULL;
+               props[n_props].value = NULL;
+
+               waitpid(pid, NULL, 0);
+               close(pipe_fd[0]);
+
+               return props;
+       }
+       else
+       {
+               close(pipe_fd[0]);
+               close(pipe_fd[1]);
+
+               return NULL;
+       }
+}
+
+char *get_property_value(Property *props, char *name)
+{
+       int i;
+       for(i=0; props[i].name; ++i)
+               if(strcmp(props[i].name, name)==0)
+                       return props[i].value;
+       return NULL;
+}
+
+int match_property_value(Property *props, char *name, char *value)
+{
+       char *v = get_property_value(props, name);
+       if(!v)
+               return value==NULL;
+       return strcmp(v, value)==0;
+}
+
+void free_properties(Property *props)
+{
+       int i;
+       if(!props)
+               return;
+       for(i=0; props[i].name; ++i)
+       {
+               free(props[i].name);
+               free(props[i].value);
+       }
+       free(props);
+}
+
+Device *get_devices(void)
+{
+       DIR *dir;
+       struct dirent *de;
+       char fnbuf[256];
+       Device *devices = NULL;
+       int n_devices = 0;
+       
+       dir = opendir("/dev/disk/by-id");
+       while((de = readdir(dir)))
+       {
+               if(de->d_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", &gtk_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;
+}