summaryrefslogtreecommitdiff
path: root/ubi-utils/src/libubi.c
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2010-05-22 08:32:23 +0300
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2010-05-22 08:32:23 +0300
commit9afc1cd5c0b1e56cdd8192aadb68104aae30ae89 (patch)
treec26f904a6bac8a66d8255d959889f381540808f2 /ubi-utils/src/libubi.c
parent180c09de57d8e254716c562bd0537df543d12577 (diff)
parenta15b1a1409721c1d75c1ecaab90bdeca74c26fd4 (diff)
Merge branch 'master' of git://git.infradead.org/mtd-utils
Diffstat (limited to 'ubi-utils/src/libubi.c')
-rw-r--r--ubi-utils/src/libubi.c127
1 files changed, 114 insertions, 13 deletions
diff --git a/ubi-utils/src/libubi.c b/ubi-utils/src/libubi.c
index fd97774..2f19bd7 100644
--- a/ubi-utils/src/libubi.c
+++ b/ubi-utils/src/libubi.c
@@ -677,35 +677,120 @@ void libubi_close(libubi_t desc)
free(lib);
}
-int ubi_attach_mtd(libubi_t desc, const char *node,
- struct ubi_attach_request *req)
+/**
+ * do_attach - perform the actual attach operation.
+ * @node: name of the UBI control character device node
+ * @r: attach request
+ *
+ * This function performs the actual UBI attach operation. Returns %0 in case of
+ * success and %-1 in case of failure. @r->ubi_num contains newly created UBI
+ * device number.
+ */
+static int do_attach(const char *node, const struct ubi_attach_req *r)
{
int fd, ret;
- struct ubi_attach_req r;
-
- memset(&r, 0, sizeof(struct ubi_attach_req));
-
- desc = desc;
- r.ubi_num = req->dev_num;
- r.mtd_num = req->mtd_num;
- r.vid_hdr_offset = req->vid_hdr_offset;
fd = open(node, O_RDONLY);
if (fd == -1)
return sys_errmsg("cannot open \"%s\"", node);
- ret = ioctl(fd, UBI_IOCATT, &r);
+ ret = ioctl(fd, UBI_IOCATT, r);
close(fd);
if (ret == -1)
return -1;
- req->dev_num = r.ubi_num;
-
#ifdef UDEV_SETTLE_HACK
// if (system("udevsettle") == -1)
// return -1;
usleep(100000);
#endif
+ return ret;
+}
+
+int ubi_attach_mtd(libubi_t desc, const char *node,
+ struct ubi_attach_request *req)
+{
+ struct ubi_attach_req r;
+ int ret;
+
+ (void)desc;
+
+ memset(&r, 0, sizeof(struct ubi_attach_req));
+ r.ubi_num = req->dev_num;
+ r.mtd_num = req->mtd_num;
+ r.vid_hdr_offset = req->vid_hdr_offset;
+
+ ret = do_attach(node, &r);
+ if (ret == 0)
+ req->dev_num = r.ubi_num;
+
+ return ret;
+}
+
+#ifndef MTD_CHAR_MAJOR
+/*
+ * This is taken from kernel <linux/mtd/mtd.h> and is unlikely to change anytime
+ * soon.
+ */
+#define MTD_CHAR_MAJOR 90
+#endif
+
+/**
+ * dev_to_mtdnum - converts device node to MTD number.
+ * @dev: path to device node to convert
+ *
+ * This function converts given @dev to MTD device number. @dev should contain
+ * path to the MTD device node. Returns MTD device number in case of success and
+ * %-1 in case of failure (errno is set).
+ */
+static int dev_to_mtdnum(const char *dev)
+{
+ int major, minor;
+ struct stat sb;
+
+ if (stat(dev, &sb) < 0)
+ return sys_errmsg("cannot stat \"%s\"", dev);
+
+ if (!S_ISCHR(sb.st_mode)) {
+ errno = EINVAL;
+ return sys_errmsg("\"%s\" is not a character device", dev);
+ }
+
+ major = major(sb.st_rdev);
+ minor = minor(sb.st_rdev);
+
+ if (major != MTD_CHAR_MAJOR) {
+ errno = EINVAL;
+ return sys_errmsg("\"%s\" is not an MTD device", dev);
+ }
+
+ return minor / 2;
+}
+
+int ubi_attach(libubi_t desc, const char *node, struct ubi_attach_request *req)
+{
+ struct ubi_attach_req r;
+ int ret;
+
+ if (!req->dev)
+ /* Fallback to opening by mtd_num */
+ return ubi_attach_mtd(desc, node, req);
+
+ memset(&r, 0, sizeof(struct ubi_attach_req));
+ r.ubi_num = req->dev_num;
+ r.vid_hdr_offset = req->vid_hdr_offset;
+
+ /*
+ * User has passed path to device node. Lets find out MTD device number
+ * of the device and pass it to the kernel.
+ */
+ r.mtd_num = dev_to_mtdnum(req->dev);
+ if (r.mtd_num == -1)
+ return -1;
+
+ ret = do_attach(node, &r);
+ if (ret == 0)
+ req->dev_num = r.ubi_num;
return ret;
}
@@ -723,6 +808,22 @@ int ubi_detach_mtd(libubi_t desc, const char *node, int mtd_num)
return ubi_remove_dev(desc, node, ubi_dev);
}
+int ubi_detach(libubi_t desc, const char *node, const char *dev)
+{
+ int mtd_num;
+
+ if (!dev) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ mtd_num = dev_to_mtdnum(dev);
+ if (mtd_num == -1)
+ return -1;
+
+ return ubi_detach_mtd(desc, node, mtd_num);
+}
+
int ubi_remove_dev(libubi_t desc, const char *node, int ubi_dev)
{
int fd, ret;