X-Git-Url: http://git.archive.openwrt.org/?p=project%2Ffstools.git;a=blobdiff_plain;f=libfstools%2Fubi.c;h=0f6e37a2e66b58b8cdf18f8bf91bf1d53a118f31;hp=3051720f65d8df6fc58848ff2422eae5d3c88d17;hb=b0c455bfc34fc7c7ac392b18a6c09f016230216d;hpb=efacbcb4973161c12cc9630d243669845db41a17 diff --git a/libfstools/ubi.c b/libfstools/ubi.c index 3051720..0f6e37a 100644 --- a/libfstools/ubi.c +++ b/libfstools/ubi.c @@ -19,22 +19,25 @@ #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; + 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,23 +125,28 @@ 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 (!volname) { + fprintf(stderr, "Couldn't read %s/name\n", voldir); + return -1; + } if (strncmp(name, volname, strlen(volname) + 1)) return -1; @@ -148,29 +158,41 @@ 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); } static int ubi_part_match(struct volume *v, char *name, unsigned int ubi_num) { - unsigned int i, volumes_count; - char devdir[80]; + DIR *ubi_dir; + struct dirent *ubi_dirent; + unsigned int volid; + char devdir[BUFLEN]; + int ret = -1; 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;id_name, "ubi%*u_%u", &volid) != 1) + continue; + + if (!ubi_volume_match(v, name, ubi_num, volid)) { + ret = 0; + break; } } + closedir(ubi_dir); - return -1; + return ret; } static int ubi_volume_find(struct volume *v, char *name) @@ -205,6 +227,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; }