block: allow mounting UBIFS partition as extroot
[project/fstools.git] / libfstools / ubi.c
index 69f6406..866034a 100644 (file)
 #include "libfstools.h"
 #include "volume.h"
 
+/* fit for UBI_MAX_VOLUME_NAME and sysfs path lengths */
+#define BUFLEN         128
+
 /* could use libubi-tiny instead, but already had the code directly reading
  * from sysfs */
-char *ubi_dir_name = "/sys/devices/virtual/ubi";
+const char *const ubi_dir_name = "/sys/devices/virtual/ubi";
 
 struct ubi_priv {
        int             ubi_num;
-       int             ubi_volidx;
+       int             ubi_volid;
 };
 
 static struct driver ubi_driver;
 
-static unsigned int
+static int
 read_uint_from_file(char *dirname, char *filename, unsigned int *i)
 {
        FILE *f;
-       char fname[128];
+       char fname[BUFLEN];
        int ret = -1;
 
        snprintf(fname, sizeof(fname), "%s/%s", dirname, filename);
@@ -54,10 +57,9 @@ static char
 *read_string_from_file(char *dirname, char *filename)
 {
        FILE *f;
-       char fname[128];
-       char buf[128];
+       char fname[BUFLEN];
+       char buf[BUFLEN];
        int i;
-       char *str;
 
        snprintf(fname, sizeof(fname), "%s/%s", dirname, filename);
 
@@ -65,17 +67,20 @@ static char
        if (!f)
                return NULL;
 
-       if (fgets(buf, 128, f) == NULL)
+       if (fgets(buf, sizeof(buf), f) == NULL)
                return NULL;
 
-       i = strlen(buf);
-       do
-               buf[i--]='\0';
-       while (buf[i] == '\n');
-
-       str = strdup(buf);
        fclose(f);
-       return str;
+
+       /* make sure the string is \0 terminated */
+       buf[sizeof(buf) - 1] = '\0';
+
+       /* remove trailing whitespace */
+       i = strlen(buf) - 1;
+       while (i > 0 && buf[i] <= ' ')
+               buf[i--] = '\0';
+
+       return strdup(buf);
 }
 
 static unsigned int
@@ -93,17 +98,17 @@ test_open(char *filename)
 
 static int ubi_volume_init(struct volume *v)
 {
-       char voldir[40], voldev[32], *volname, *voltype;
+       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_volidx);
+               ubi_dir_name, p->ubi_num, p->ubi_num, p->ubi_volid);
 
        snprintf(voldev, sizeof(voldev), "/dev/ubi%u_%u",
-               p->ubi_num, p->ubi_volidx);
+               p->ubi_num, p->ubi_volid);
 
        volname = read_string_from_file(voldir, "name");
        if (!volname)
@@ -120,25 +125,26 @@ static int ubi_volume_init(struct volume *v)
        return 0;
 }
 
-
-static int ubi_volume_match(struct volume *v, char *name, int ubi_num, int volidx)
+static int ubi_volume_match(struct volume *v, char *name, int ubi_num, int volid)
 {
-       char voldir[40], volblkdev[40], *volname;
+       char voldir[BUFLEN], volblkdev[BUFLEN], *volname;
        struct ubi_priv *p;
 
        snprintf(voldir, sizeof(voldir), "%s/ubi%u/ubi%u_%u",
-               ubi_dir_name, ubi_num, ubi_num, volidx);
+               ubi_dir_name, ubi_num, ubi_num, volid);
 
        snprintf(volblkdev, sizeof(volblkdev), "/dev/ubiblock%u_%u",
-               ubi_num, volidx);
+               ubi_num, volid);
 
        /* skip if ubiblock device exists */
        if (test_open(volblkdev))
                return -1;
 
+       /* todo: skip existing gluebi device for legacy support */
+
        volname = read_string_from_file(voldir, "name");
 
-       if (strncmp(name, volname, strlen(volname)))
+       if (strncmp(name, volname, strlen(volname) + 1))
                return -1;
 
        p = calloc(1, sizeof(struct ubi_priv));
@@ -148,7 +154,7 @@ static int ubi_volume_match(struct volume *v, char *name, int ubi_num, int volid
        v->priv = p;
        v->drv = &ubi_driver;
        p->ubi_num = ubi_num;
-       p->ubi_volidx = volidx;
+       p->ubi_volid = volid;
 
        return ubi_volume_init(v);
 }
@@ -156,7 +162,7 @@ static int ubi_volume_match(struct volume *v, char *name, int ubi_num, int volid
 static int ubi_part_match(struct volume *v, char *name, unsigned int ubi_num)
 {
        unsigned int i, volumes_count;
-       char devdir[80];
+       char devdir[BUFLEN];
 
        snprintf(devdir, sizeof(devdir), "%s/ubi%u",
                ubi_dir_name, ubi_num);
@@ -180,6 +186,9 @@ static int ubi_volume_find(struct volume *v, char *name)
        unsigned int ubi_num;
        int ret = -1;
 
+       if (find_filesystem("ubifs"))
+               return ret;
+
        ubi_dir = opendir(ubi_dir_name);
        /* check for os ubi support */
        if (!ubi_dir)
@@ -202,6 +211,7 @@ static int ubi_volume_find(struct volume *v, char *name)
 
 static int ubi_volume_identify(struct volume *v)
 {
+       /* Todo: use libblkid-tiny on the ubi chardev */
        return FS_UBIFS;
 }