9 typedef struct sProperty
15 typedef struct sDevice
23 int parse_property(char *str, int size, Property *prop)
28 for(i=0; (equals<0 && i<size); ++i)
35 prop->name = malloc(equals+1);
36 strncpy(prop->name, str, equals);
37 prop->name[equals] = 0;
39 prop->value = malloc(size-equals);
40 strncpy(prop->value, str+equals+1, size-equals-1);
41 prop->value[size-equals-1] = 0;
46 Property *get_device_properties(char *node)
51 /*printf("Examining device %s\n", node);*/
61 execl("/sbin/udevadm", "udevadm", "info", "-q", "property", "-n", node, NULL);
69 Property *props = NULL;
84 len = read(pipe_fd[0], buf+pos, sizeof(buf)-pos);
93 for(i=0; (newline<0 && i<pos); ++i)
100 if(parse_property(buf, newline, &prop)==0)
102 /*printf("Got property '%s' = '%s'\n", prop.name, prop.value);*/
104 props = (Property *)realloc(props, (n_props*2)*sizeof(Property));
105 props[n_props] = prop;
108 memmove(buf, buf+newline+1, pos-newline-1);
115 props[n_props].name = NULL;
116 props[n_props].value = NULL;
118 waitpid(pid, NULL, 0);
132 char *get_property_value(Property *props, char *name)
135 for(i=0; props[i].name; ++i)
136 if(strcmp(props[i].name, name)==0)
137 return props[i].value;
141 int match_property_value(Property *props, char *name, char *value)
143 char *v = get_property_value(props, name);
146 return strcmp(v, value)==0;
149 void free_properties(Property *props)
154 for(i=0; props[i].name; ++i)
157 free(props[i].value);
162 Device *get_devices(void)
167 Device *devices = NULL;
170 dir = opendir("/dev/disk/by-id");
171 while((de = readdir(dir)))
173 if(de->d_name[0]=='.' && (de->d_name[1]==0 || (de->d_name[1]=='.' && de->d_name[2]==0)))
176 snprintf(fnbuf, sizeof(fnbuf), "/dev/disk/by-id/%s", de->d_name);
177 Property *props = get_device_properties(fnbuf);
178 if(match_property_value(props, "ID_BUS", "usb") && match_property_value(props, "DEVTYPE", "partition"))
187 /*printf("Using device %s\n", fnbuf);*/
189 label = get_property_value(props, "ID_FS_LABEL");
191 label = get_property_value(props, "ID_FS_UUID");
196 label = get_property_value(props, "DEVNAME");
197 for(ptr=label; *ptr; ++ptr)
201 vendor = get_property_value(props, "ID_VENDOR");
202 model = get_property_value(props, "ID_MODEL");
204 pos = snprintf(buf, sizeof(buf), "%s", label);
206 pos += snprintf(buf+pos, sizeof(buf)-pos, " (%s %s)", vendor, model);
210 devices = (Device *)realloc(devices, (n_devices+2)*sizeof(Device));
211 devices[n_devices].node = strdup(fnbuf);
212 devices[n_devices].label = strdup(label);
213 devices[n_devices].description = strdup(buf);
214 devices[n_devices].time = st.st_mtime;
217 free_properties(props);
220 devices[n_devices].node = NULL;
221 devices[n_devices].label = NULL;
226 void free_devices(Device *devices)
231 for(i=0; devices[i].node; ++i)
233 free(devices[i].node);
234 free(devices[i].label);
239 void row_activated(GtkTreeView *list, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data)
244 model = gtk_tree_view_get_model(list);
246 if(gtk_tree_model_get_iter(model, &iter, path))
251 gtk_tree_model_get(model, &iter, 1, &device, -1);
256 execl("/usr/bin/pmount", "pmount", device->node, device->label, NULL);
261 waitpid(pid, NULL, 0);
271 int main(int argc, char **argv)
277 GtkTreeSelection *selection;
283 gtk_init(&argc, &argv);
285 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
286 gtk_container_set_border_width(GTK_CONTAINER(window), 5);
287 g_signal_connect(window, "destroy", >k_main_quit, NULL);
289 viewport = gtk_viewport_new(NULL, NULL);
290 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_IN);
291 gtk_container_add(GTK_CONTAINER(window), viewport);
293 list = gtk_tree_view_new();
294 gtk_container_add(GTK_CONTAINER(viewport), list);
295 g_signal_connect(list, "row-activated", (GCallback)&row_activated, NULL);
297 store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER);
298 gtk_tree_view_set_model(GTK_TREE_VIEW(list), GTK_TREE_MODEL(store));
299 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(list),
300 -1, "Device", gtk_cell_renderer_text_new(), "text", 0, NULL);
302 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list));
304 devices = get_devices();
306 for(i=0; devices[i].node; ++i)
308 gtk_list_store_append(store, &iter);
309 gtk_list_store_set(store, &iter, 0, devices[i].description, 1, &devices[i], -1);
310 if(devices[i].time>latest)
312 latest = devices[i].time;
313 gtk_tree_selection_select_iter(selection, &iter);
317 gtk_widget_show_all(window);
320 free_devices(devices);