diff options
Diffstat (limited to 'ubi-utils')
-rw-r--r-- | ubi-utils/src/libmtd.c | 103 | ||||
-rw-r--r-- | ubi-utils/src/libmtd_legacy.c | 9 | ||||
-rw-r--r-- | ubi-utils/src/mtdinfo.c | 7 |
3 files changed, 95 insertions, 24 deletions
diff --git a/ubi-utils/src/libmtd.c b/ubi-utils/src/libmtd.c index b050bea..4f1ef41 100644 --- a/ubi-utils/src/libmtd.c +++ b/ubi-utils/src/libmtd.c @@ -472,9 +472,88 @@ static int dev_node2num(struct libmtd *lib, const char *node, int *dev_num) return -1; } +/** + * sysfs_is_supported - check whether the MTD sub-system supports MTD. + * @lib: MTD library descriptor + * + * The Linux kernel MTD subsystem gained MTD support starting from kernel + * 2.6.30 and libmtd tries to use sysfs interface if possible, because the NAND + * sub-page size is available there (and not available at all in pre-sysfs + * kernels). + * + * Very old kernels did not have "/sys/class/mtd" directory. Not very old + * kernels (e.g., 2.6.29) did have "/sys/class/mtd/mtdX" directories, by there + * were no files there, e.g., the "name" file was not present. So all we can do + * is to check for a "/sys/class/mtd/mtdX/name" file. But this is not a + * reliable check, because if this is a new system with no MTD devices - we'll + * treat it as a pre-sysfs system. + */ +static int sysfs_is_supported(struct libmtd *lib) +{ + int fd, num = -1; + DIR *sysfs_mtd; + char file[strlen(lib->mtd_name) + 10]; + + sysfs_mtd = opendir(lib->sysfs_mtd); + if (!sysfs_mtd) { + if (errno == ENOENT) { + errno = 0; + return 0; + } + return sys_errmsg("cannot open \"%s\"", lib->sysfs_mtd); + } + + /* + * First of all find an "mtdX" directory. This is needed because there + * may be, for example, mtd1 but no mtd0. + */ + while (1) { + int ret, dev_num; + char tmp_buf[256]; + struct dirent *dirent; + + dirent = readdir(sysfs_mtd); + if (!dirent) + break; + + if (strlen(dirent->d_name) >= 255) { + errmsg("invalid entry in %s: \"%s\"", + lib->sysfs_mtd, dirent->d_name); + errno = EINVAL; + closedir(sysfs_mtd); + return -1; + } + + ret = sscanf(dirent->d_name, MTD_NAME_PATT"%s", + &dev_num, tmp_buf); + if (ret == 1) { + num = dev_num; + break; + } + } + + if (closedir(sysfs_mtd)) + return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_mtd); + + if (num == -1) + /* No mtd device, treat this as pre-sysfs system */ + return 0; + + sprintf(file, lib->mtd_name, num); + fd = open(file, O_RDONLY); + if (fd == -1) + return 0; + + if (close(fd)) { + sys_errmsg("close failed on \"%s\"", file); + return -1; + } + + return 1; +} + libmtd_t libmtd_open(void) { - int fd; struct libmtd *lib; lib = calloc(1, sizeof(struct libmtd)); @@ -489,28 +568,18 @@ libmtd_t libmtd_open(void) if (!lib->mtd) goto out_error; - /* Make sure MTD is recent enough and supports sysfs */ - fd = open(lib->sysfs_mtd, O_RDONLY); - if (fd == -1) { + lib->mtd_name = mkpath(lib->mtd, MTD_NAME); + if (!lib->mtd_name) + goto out_error; + + if (!sysfs_is_supported(lib)) { free(lib->mtd); free(lib->sysfs_mtd); - if (errno != ENOENT || legacy_libmtd_open()) { - free(lib); - return NULL; - } + free(lib->mtd_name); lib->mtd_name = lib->mtd = lib->sysfs_mtd = NULL; return lib; } - if (close(fd)) { - sys_errmsg("close failed on \"%s\"", lib->sysfs_mtd); - goto out_error; - } - - lib->mtd_name = mkpath(lib->mtd, MTD_NAME); - if (!lib->mtd_name) - goto out_error; - lib->mtd_dev = mkpath(lib->mtd, MTD_DEV); if (!lib->mtd_dev) goto out_error; diff --git a/ubi-utils/src/libmtd_legacy.c b/ubi-utils/src/libmtd_legacy.c index cd474b1..b477a4f 100644 --- a/ubi-utils/src/libmtd_legacy.c +++ b/ubi-utils/src/libmtd_legacy.c @@ -218,8 +218,13 @@ int legacy_get_dev_info(const char *node, struct mtd_dev_info *mtd) loff_t offs = 0; struct proc_parse_info pi; - if (stat(node, &st)) - return sys_errmsg("cannot open \"%s\"", node); + if (stat(node, &st)) { + sys_errmsg("cannot open \"%s\"", node); + if (errno == ENOENT) + normsg("MTD subsystem is old and does not support " + "sysfs, so MTD character device nodes have " + "to exist"); + } if (!S_ISCHR(st.st_mode)) { errno = EINVAL; diff --git a/ubi-utils/src/mtdinfo.c b/ubi-utils/src/mtdinfo.c index 849d165..a7ce834 100644 --- a/ubi-utils/src/mtdinfo.c +++ b/ubi-utils/src/mtdinfo.c @@ -238,23 +238,20 @@ static int print_general_info(libmtd_t libmtd, const struct mtd_info *mtd_info, if (mtd_info->dev_count == 0) return 0; - printf("Present MTD devices: "); for (i = mtd_info->lowest_dev_num; i <= mtd_info->highest_dev_num; i++) { err = mtd_get_dev_info1(libmtd, i, &mtd); if (err == -1) { if (errno == ENODEV) continue; - - printf("\n"); return sys_errmsg("libmtd failed get MTD device %d " - "information", i); + "information", i); } if (!first) printf(", mtd%d", i); else { - printf("mtd%d", i); + printf("Present MTD devices: mtd%d", i); first = 0; } } |