libfstools: use container_of for volume private data
[project/fstools.git] / libfstools / ubi.c
index 866034a7cc84e4d06e495b18d87be85ec658ca8a..f9d6e0aaa718ef941862297cae84afaebf7440c8 100644 (file)
@@ -26,7 +26,8 @@
  * from sysfs */
 const char *const ubi_dir_name = "/sys/devices/virtual/ubi";
 
-struct ubi_priv {
+struct ubi_volume {
+       struct volume v;
        int             ubi_num;
        int             ubi_volid;
 };
@@ -98,12 +99,10 @@ test_open(char *filename)
 
 static int ubi_volume_init(struct volume *v)
 {
+       struct ubi_volume *p = container_of(v, struct ubi_volume, v);
        char voldir[BUFLEN], voldev[BUFLEN], *volname;
-       struct ubi_priv *p;
        unsigned int volsize;
 
-       p = (struct ubi_priv*)v->priv;
-
        snprintf(voldir, sizeof(voldir), "%s/ubi%u/ubi%u_%u",
                ubi_dir_name, p->ubi_num, p->ubi_num, p->ubi_volid);
 
@@ -125,10 +124,10 @@ static int ubi_volume_init(struct volume *v)
        return 0;
 }
 
-static int ubi_volume_match(struct volume *v, char *name, int ubi_num, int volid)
+static struct volume *ubi_volume_match(char *name, int ubi_num, int volid)
 {
        char voldir[BUFLEN], volblkdev[BUFLEN], *volname;
-       struct ubi_priv *p;
+       struct ubi_volume *p;
 
        snprintf(voldir, sizeof(voldir), "%s/ubi%u/ubi%u_%u",
                ubi_dir_name, ubi_num, ubi_num, volid);
@@ -138,53 +137,67 @@ static int ubi_volume_match(struct volume *v, char *name, int ubi_num, int volid
 
        /* skip if ubiblock device exists */
        if (test_open(volblkdev))
-               return -1;
+               return NULL;
 
        /* todo: skip existing gluebi device for legacy support */
 
        volname = read_string_from_file(voldir, "name");
+       if (!volname) {
+               ULOG_ERR("Couldn't read %s/name\n", voldir);
+               return NULL;
+       }
 
        if (strncmp(name, volname, strlen(volname) + 1))
-               return -1;
+               return NULL;
 
-       p = calloc(1, sizeof(struct ubi_priv));
+       p = calloc(1, sizeof(struct ubi_volume));
        if (!p)
-               return -1;
+               return NULL;
 
-       v->priv = p;
-       v->drv = &ubi_driver;
+       p->v.drv = &ubi_driver;
        p->ubi_num = ubi_num;
        p->ubi_volid = volid;
 
-       return ubi_volume_init(v);
+       return &p->v;
 }
 
-static int ubi_part_match(struct volume *v, char *name, unsigned int ubi_num)
+static struct volume *ubi_part_match(char *name, unsigned int ubi_num)
 {
-       unsigned int i, volumes_count;
+       DIR *ubi_dir;
+       struct dirent *ubi_dirent;
+       unsigned int volid;
        char devdir[BUFLEN];
+       struct volume *ret = NULL;
 
        snprintf(devdir, sizeof(devdir), "%s/ubi%u",
                ubi_dir_name, ubi_num);
 
-       if (read_uint_from_file(devdir, "volumes_count", &volumes_count))
-               return -1;
+       ubi_dir = opendir(devdir);
+       if (!ubi_dir)
+               return ret;
+
+       while ((ubi_dirent = readdir(ubi_dir)) != NULL) {
+               if (strncmp(ubi_dirent->d_name, "ubi", 3))
+                       continue;
 
-       for (i=0;i<volumes_count;i++) {
-               if (!ubi_volume_match(v, name, ubi_num, i)) {
-                       return 0;
-               }
+               if (sscanf(ubi_dirent->d_name, "ubi%*u_%u", &volid) != 1)
+                       continue;
+
+               ret = ubi_volume_match(name, ubi_num, volid);
+               if (ret)
+                       break;
        }
+       closedir(ubi_dir);
 
-       return -1;
+       return ret;
 }
 
-static int ubi_volume_find(struct volume *v, char *name)
+static struct volume *ubi_volume_find(char *name)
 {
+       struct volume *ret = NULL;
        DIR *ubi_dir;
        struct dirent *ubi_dirent;
        unsigned int ubi_num;
-       int ret = -1;
 
        if (find_filesystem("ubifs"))
                return ret;
@@ -200,10 +213,9 @@ static int ubi_volume_find(struct volume *v, char *name)
                        continue;
 
                sscanf(ubi_dirent->d_name, "ubi%u", &ubi_num);
-               if (!ubi_part_match(v, name, ubi_num)) {
-                       ret = 0;
+               ret = ubi_part_match(name, ubi_num);
+               if (ret)
                        break;
-               };
        }
        closedir(ubi_dir);
        return ret;