Avoid checking the same device more than once
authorMikko Rasa <tdb@tdb.fi>
Fri, 5 Oct 2012 22:41:07 +0000 (01:41 +0300)
committerMikko Rasa <tdb@tdb.fi>
Fri, 5 Oct 2012 22:41:07 +0000 (01:41 +0300)
main.c

diff --git a/main.c b/main.c
index 910983fb94498a7211fdc9f4921944294a4f9a48..ee55972c95d8570a7625e7e2c9cb638ca09a39e0 100644 (file)
--- a/main.c
+++ b/main.c
@@ -208,31 +208,99 @@ void free_mounted_devices(char **mounted)
        free(mounted);
 }
 
-Device *get_devices(void)
+char **get_device_nodes(char *dirname)
 {
        DIR *dir;
        struct dirent *de;
        char fnbuf[256];
-       Device *devices = NULL;
-       int n_devices = 0;
-       char **mounted = NULL;
-       
-       dir = opendir("/dev/disk/by-id");
+       char linkbuf[256];
+       struct stat st;
+       char **nodes = NULL;
+       int n_nodes = 0;
+       char **checked = NULL;
+       int n_checked = 0;
+       int i;
+
+       dir = opendir(dirname);
        if(!dir)
                return NULL;
 
-       mounted = get_mounted_devices();
-
        while((de = readdir(dir)))
        {
+               char *node;
+               int duplicate = 0;
+
                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);
+               snprintf(fnbuf, sizeof(fnbuf), "%s/%s", dirname, de->d_name);
+
+               node = fnbuf;
+               lstat(fnbuf, &st);
+               if(S_ISLNK(st.st_mode))
+               {
+                       int len;
+                       len = readlink(fnbuf, linkbuf, sizeof(linkbuf)-1);
+                       if(len!=-1)
+                       {
+                               linkbuf[len] = 0;
+                               node = linkbuf;
+                       }
+               }
+
+               if(checked)
+               {
+                       for(i=0; (!duplicate && i<n_checked); ++i)
+                               if(strcmp(node, checked[i])==0)
+                                       duplicate = 1;
+               }
+               if(duplicate)
+               {
+                       if(verbosity>=1)
+                               printf("Device %s is a duplicate\n", fnbuf);
+                       continue;
+               }
+
+               checked = (char **)realloc(checked, (n_checked+1)*sizeof(char *));
+               checked[n_checked] = strdup(node);
+               ++n_checked;
+
+               nodes = (char **)realloc(nodes, (n_nodes+2)*sizeof(char *));
+               nodes[n_nodes] = strdup(fnbuf);
+               ++n_nodes;
+       }
+
+       closedir(dir);
+       if(checked)
+       {
+               for(i=0; i<n_checked; ++i)
+                       free(checked[i]);
+               free(checked);
+       }
+
+       if(nodes)
+               nodes[n_nodes] = NULL;
+
+       return nodes;
+}
+
+Device *get_devices(void)
+{
+       char **nodes = NULL;
+       Device *devices = NULL;
+       int n_devices = 0;
+       char **mounted = NULL;
+       int i;
+
+       nodes = get_device_nodes("/dev/disk/by-id");
+       mounted = get_mounted_devices();
+
+       for(i=0; nodes[i]; ++i)
+       {
                if(verbosity>=1)
-                       printf("Examining device %s\n", fnbuf);
+                       printf("Examining device %s\n", nodes[i]);
 
-               Property *props = get_device_properties(fnbuf);
+               Property *props = get_device_properties(nodes[i]);
                if(!props)
                {
                        if(verbosity>=2)
@@ -242,9 +310,9 @@ Device *get_devices(void)
 
                if(verbosity>=2)
                {
-                       int i;
-                       for(i=0; props[i].name; ++i)
-                               printf("  %s = %s\n", props[i].name, props[i].value);
+                       int j;
+                       for(j=0; props[j].name; ++j)
+                               printf("  %s = %s\n", props[j].name, props[j].value);
                }
 
                if(match_property_value(props, "ID_BUS", "usb") && match_property_value(props, "DEVTYPE", "partition"))
@@ -282,20 +350,22 @@ Device *get_devices(void)
                        if(vendor && model)
                                pos += snprintf(buf+pos, sizeof(buf)-pos, " (%s %s)", vendor, model);
 
-                       stat(fnbuf, &st);
+                       stat(nodes[i], &st);
 
                        devices = (Device *)realloc(devices, (n_devices+2)*sizeof(Device));
-                       devices[n_devices].node = strdup(fnbuf);
+                       devices[n_devices].node = nodes[i];
                        devices[n_devices].label = strdup(label);
                        devices[n_devices].description = strdup(buf);
                        devices[n_devices].mounted = is_mounted(mounted, devname);
                        devices[n_devices].time = st.st_mtime;
                        ++n_devices;
                }
+               else
+                       free(nodes[i]);
                free_properties(props);
        }
 
-       closedir(dir);
+       free(nodes);
        free_mounted_devices(mounted);
 
        if(devices)