]> www.infradead.org Git - mtd-utils.git/commitdiff
[MTD] UBI: Adaptations to new driver, reworked frontend
authordedekind@linutronix.de <dedekind@linutronix.de>
Fri, 30 Jun 2006 12:05:25 +0000 (14:05 +0200)
committerFrank Haverkamp <haver@vnet.ibm.com>
Tue, 31 Oct 2006 14:06:07 +0000 (15:06 +0100)
include/mtd/ubi-header.h
include/mtd/ubi-user.h
ubi-utils/src/config.h
ubi-utils/src/libubi.c
ubi-utils/src/libubi_int.h
ubi-utils/src/ubimkvol.c
ubi-utils/src/ubirmvol.c
ubi-utils/src/ubiupdatevol.c

index 12ce1c9e5b5210a97ed68b9e6b32e7904c3c1aa3..ca96fc90bd61261ec64de48f8e3293526c411d76 100644 (file)
@@ -41,7 +41,7 @@
 /* The initial CRC32 value used when calculating CRC checksums */
 #define UBI_CRC32_INIT 0xFFFFFFFFU
 
-/**
+/*
  * Magic numbers of the UBI headers.
  *
  * @UBI_EC_HDR_MAGIC: erase counter header magic number (ASCII "UBI#")
@@ -52,7 +52,7 @@ enum {
        UBI_VID_HDR_MAGIC = 0x55424921
 };
 
-/**
+/*
  * Molume type constants used in volume identifier headers.
  *
  * @UBI_VID_DYNAMIC: dynamic volume
@@ -63,23 +63,19 @@ enum {
        UBI_VID_STATIC  = 2
 };
 
-/**
+/*
  * Compatibility constants used by internal volumes.
  *
  * @UBI_COMPAT_DELETE: delete this internal volume before anything is written
  * to the flash
  * @UBI_COMPAT_RO: attach this device in read-only mode
- * @UBI_COMPAT_IGNORE: ignore this internal volume, but the UBI wear-leveling
- * unit may still move these logical eraseblocks to ensure wear-leveling
  * @UBI_COMPAT_PRESERVE: preserve this internal volume - do not touch its
- * physical eraseblocks, don't even allow the wear-leveling unit to move
- * them
+ * physical eraseblocks, don't allow the wear-leveling unit to move them
  * @UBI_COMPAT_REJECT: reject this UBI image
  */
 enum {
        UBI_COMPAT_DELETE   = 1,
        UBI_COMPAT_RO       = 2,
-       UBI_COMPAT_IGNORE   = 3,
        UBI_COMPAT_PRESERVE = 4,
        UBI_COMPAT_REJECT   = 5
 };
@@ -281,7 +277,7 @@ struct ubi_vid_hdr {
  */
 struct ubi_vid_hdr_upd_vol {
        ubi32_t vol_id;
-       uint8_t padding[UBI_VID_HDR_IVOL_DATA_SIZE - 4];
+       uint8_t padding[UBI_VID_HDR_IVOL_DATA_SIZE-4];
 } __attribute__ ((packed));
 
 /*
@@ -295,13 +291,13 @@ struct ubi_vid_hdr_upd_vol {
  */
 #define UBI_INTERNAL_VOL_START (0x7FFFFFFF - 4096)
 
-/**
+/*
  * enum ubi_internal_volume_numbers - volume IDs of internal UBI volumes.
  *
  * %UBI_LAYOUT_VOL_ID: volume ID of the layout volume
  * %UBI_UPDATE_VOL_ID: volume ID of the update volume
  */
-enum ubi_internal_volume_ids {
+enum {
        UBI_LAYOUT_VOL_ID = UBI_INTERNAL_VOL_START,
        UBI_UPDATE_VOL_ID = UBI_INTERNAL_VOL_START + 1
 };
@@ -351,6 +347,7 @@ enum ubi_internal_volume_ids {
  * @alignment: volume alignment
  * @data_pad: how many bytes are not used at the end of the eraseblocks to
  * satisfy the requested alignment
+ * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
  * @padding1: reserved, zeroes
  * @name_len: the volume name length
  * @name: the volume name
@@ -382,7 +379,7 @@ struct ubi_vol_tbl_record {
        uint8_t vol_type;
        uint8_t padding1;
        ubi16_t name_len;
-       uint8_t name[UBI_VOL_NAME_MAX + 1];
+       uint8_t name[UBI_VOL_NAME_MAX+1];
        uint8_t padding2[24];
        ubi32_t crc;
 } __attribute__ ((packed));
index 161f674ef1d0d13debce64bb1abdcafdbcd9e18d..0eb147069e74278e20baf26a473cbb31432f6aed 100644 (file)
@@ -32,6 +32,9 @@
  */
 #define UBI_VOL_NUM_AUTO (-1)
 
+/* Maximum volume name length */
+#define UBI_MAX_VOLUME_NAME 127
+
 /*
  * IOCTL commands of UBI character devices
  */
@@ -56,7 +59,7 @@
 /* An eraseblock erasure command, used for debugging, disabled by dafault */
 #define UBI_IOCEBER _IOW(UBI_VOL_IOC_MAGIC, 0, int32_t)
 
-/**
+/*
  * UBI volume type constants.
  *
  * @UBI_DYNAMIC_VOLUME: dynamic volume
@@ -113,7 +116,7 @@ struct ubi_mkvol_req {
  *
  * @vol_id: ID of the volume to re-size
  * @bytes: new size of the volume in bytes
- * 
+ *
  * Re-sizing is possible for both dynamic and static volumes. But while dynamic
  * volumes may be re-sized arbitrarily, static volumes cannot be made to be
  * smaller then the number of bytes they bear. To arbitrarily shrink a static
index 746fa3cc3b67c4c558a9987975c50aa80f1eb6e5..b5bbd5bd2c739e5c30483f3a5bac339d1d1a1f30 100644 (file)
@@ -20,8 +20,8 @@
  * Author: Frank Haverkamp
  */
 
-#define PACKAGE_VERSION     "1.0"
-#define PACKAGE_BUGREPORT   "dedekind@oktetlabs.ru, haver@vnet.ibm.com, or tglx@linutronix.de"
+#define PACKAGE_VERSION     "1.1"
+#define PACKAGE_BUGREPORT   "haver@vnet.ibm.com, dedekind@linutronix.de, or tglx@linutronix.de"
 
 #define __unused __attribute__((unused))
 
index 9b9a793ccd783c2a1cd077c93c3bf2ae3a3a9392..979f157875d454b9b5d363193bf8c81e92f95bfe 100644 (file)
@@ -34,6 +34,7 @@
 #include <sys/ioctl.h>
 #include <stdint.h>
 #include <mtd/ubi-user.h>
+#include <mtd/ubi-header.h>
 
 #include "libubi.h"
 #include "libubi_int.h"
@@ -47,7 +48,6 @@
  * @sysfs_root     sysfs root directory
  * @ubi_root       UBI root directory in sysfs
  *
- * @nlen_max       full path to the "maximum volume name length" sysfs file
  * @version        full path to the "UBI version" sysfs file
  *
  * @cdev_path      path pattern to UBI character devices
@@ -85,7 +85,6 @@ struct ubi_lib
        char *sysfs_root;
        char *ubi_root;
 
-       char *nlen_max;
        char *version;
        char *cdev_path;
        int  cdev_path_len;
@@ -147,10 +146,6 @@ get_ubi_info(ubi_lib_t desc, struct ubi_info *ubi)
        if (err)
                return -1;
 
-       err = sysfs_read_int(desc->nlen_max, (int*) &ubi->nlen_max);
-       if (err)
-               return -1;
-
        /* Calculate number of UBI devices */
        do {
                char dir[20];
@@ -186,7 +181,6 @@ ubi_dump_handler(ubi_lib_t desc)
        ubi_lib_t d = desc;
        printf( "UBI Library Descriptor:\n"
                "ubi_root:       %s\n"
-               "nlen_max:       %s\n"
                "version:        %s\n"
                "cdev_path:      %s\n"
                "udev_path:      %s\n"
@@ -204,12 +198,12 @@ ubi_dump_handler(ubi_lib_t desc)
                "vol_type_path:  %s\n"
                "vol_name_path:  %s\n"
                "cdev_path_len:  %d\n\n",
-              d->ubi_root, d->nlen_max, d->version, d->cdev_path,
-              d->udev_path, d->wear_path, d->vol_count_path,
-              d->tot_ebs_path, d->avail_ebs_path, d->eb_size_path,
-              d->nums_path, d->vol_cdev_path, d->vdev_path,
-              d->vol_nums_path, d->vol_bytes_path, d->vol_ebs_path,
-              d->vol_type_path, d->vol_name_path, d->cdev_path_len);
+              d->ubi_root, d->version, d->cdev_path, d->udev_path,
+              d->wear_path, d->vol_count_path, d->tot_ebs_path,
+              d->avail_ebs_path, d->eb_size_path, d->nums_path,
+              d->vol_cdev_path, d->vdev_path, d->vol_nums_path,
+              d->vol_bytes_path, d->vol_ebs_path, d->vol_type_path,
+              d->vol_name_path, d->cdev_path_len);
 }
 
 int
@@ -281,11 +275,7 @@ ubi_open(ubi_lib_t *desc)
        if (!res->ubi_root)
                goto error;
 
-       res->nlen_max = mkpath(res->ubi_root, UBI_NLEN_MAX);
-       if (!res->nlen_max)
-               goto error;
-
-       res->version =  mkpath(res->ubi_root, UBI_VERSION);
+       res->version =  mkpath(res->ubi_root, UBI_VER);
        if (!res->version)
                goto error;
 
@@ -394,7 +384,6 @@ ubi_close(ubi_lib_t *desc)
        free(tmp->udev_path);
        free(tmp->cdev_path);
        free(tmp->version);
-       free(tmp->nlen_max);
        free(tmp->ubi_root);
        free(tmp->sysfs_root);
        free(tmp);
@@ -486,7 +475,7 @@ ubi_get_vol_info(ubi_lib_t desc, unsigned int devn, unsigned int vol_id,
        int err;
        int len;
        char buf1[10];
-       char buf2[desc->ubi.nlen_max];
+       char buf2[UBI_MAX_VOLUME_NAME];
 
        err = sysfs_read_dev_subst(desc->vol_nums_path, &req->major,
                                   &req->minor, 2, devn, vol_id);
@@ -523,7 +512,7 @@ ubi_get_vol_info(ubi_lib_t desc, unsigned int devn, unsigned int vol_id,
        }
 
        len = sysfs_read_data_subst(desc->vol_name_path, &buf2[0],
-                                   desc->ubi.nlen_max, 2,  devn, vol_id);
+                                   UBI_MAX_VOLUME_NAME, 2,  devn, vol_id);
        if (len == -1)
                return -1;
 
index ab387f5f01153897e87edfbf178ea7d11a091d45..830a6823242568b14becbc365e64e4c0f0fba150 100644 (file)
@@ -1,5 +1,3 @@
-#ifndef __UBI_INT_H__
-#define __UBI_INT_H__
 /*
  * Copyright (c) International Business Machines Corp., 2006
  *
@@ -24,6 +22,8 @@
  * Author: Artem B. Bityutskiy
  */
 
+#ifndef __UBI_INT_H__
+#define __UBI_INT_H__
 /*
  * Enable/disable UBI library debugging messages.
  */
@@ -58,7 +58,7 @@
  * @def UBI_NLEN_MAX
  *     @brief Name of syfs file containing the maximum UBI volume name length.
  *
- * @def UBI_VERSION
+ * @def UBI_VER
  *      @brief Name of sysfs file containing UBI version.
  *
  * @def UBI_WEAR
@@ -98,7 +98,7 @@
  **/
 #define UBI_ROOT       "ubi"
 #define UBI_NLEN_MAX   "volume_name_max"
-#define UBI_VERSION    "version"
+#define UBI_VER                "version"
 #define UBI_WEAR       "wear"
 #define UBI_VOL_COUNT  "volumes_count"
 #define UBI_TOT_EBS    "total_eraseblocks"
index 30c569c121328ca4be9820fefab0a7b30cf59c53..d35d2f3e6b82cc23bbb650e948c747cf0e83c7a4 100644 (file)
 /*
  * An utility to create UBI volumes.
  *
- * Author: Artem B. Bityutskiy <dedekind@oktetlabs.ru>
+ * Author: Artem B. Bityutskiy <dedekind@linutronix.de>
+ *         Frank Haverkamp <haver@vnet.ibm.com>
  *
  * 1.0 Initial release
  * 1.1 Does not support erase blocks anymore. This is replaced by
  *     the number of bytes.
+ * 1.2 Reworked the user-interface to use argp.
  */
 
+#include <argp.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <getopt.h>
 #include <string.h>
 #include <errno.h>
 
-#include "config.h"
+#include <config.h>
 #include <libubi.h>
 
-static void usage(void);
-static int param_sanity_check(ubi_lib_t lib);
-static int parse_options(int argc, char * const argv[]);
+#define VERSION "1.2"
 
 /*
- * The variables below  are set by command line arguments.
+ * The variables below are set by command line arguments.
  */
-static int vol_type = UBI_DYNAMIC_VOLUME;
-static int devn = -1;
-static long long bytes = 0;
-static int alignment = 1;
-static int vol_id = UBI_VOL_NUM_AUTO;
-static char *name = NULL;
-static int nlen = 0;
+struct args {
+       int devn;
+       int vol_id;
+       int vol_type;
+       long long bytes;
+       int alignment;
+       char *name;
+       int nlen;
 
-int main(int argc, char * const argv[])
-{
-       int err;
-       ubi_lib_t lib;
+       /* special stuff needed to get additional arguments */
+       char *arg1;
+       char **options;         /* [STRING...] */
+};
 
-       err = parse_options(argc, argv);
-       if (err) {
-               fprintf(stderr, "Wrong options ...\n");
-               return err == 1 ? 0 : -1;
-       }
+static struct args myargs = {
+       .vol_type = UBI_DYNAMIC_VOLUME,
+       .devn = -1,
+       .bytes = 0,
+       .alignment = 1,
+       .vol_id = UBI_VOL_NUM_AUTO,
+       .name = NULL,
+       .nlen = 0,
+};
 
-       if (devn == -1) {
-               fprintf(stderr, "Device number was not specified\n");
-               fprintf(stderr, "Use -h option for help\n");
-               return -1;
-       }
+static int param_sanity_check(struct args *args, ubi_lib_t lib);
+static error_t parse_opt(int key, char *optarg, struct argp_state *state);
+const char *argp_program_bug_address = PACKAGE_BUGREPORT;
 
-       err = ubi_open(&lib);
-       if (err) {
-               perror("Cannot open libubi");
-               return -1;
-       }
+static char doc[] = "\nVersion: " VERSION "\n\t"
+       BUILD_OS" "BUILD_CPU" at "__DATE__" "__TIME__"\n"
+       "\nMake UBI Volume.\n";
 
-       err = param_sanity_check(lib);
-       if (err) {
-               perror("Input parameters check");
-               fprintf(stderr, "Use -h option for help\n");
-               goto out_libubi;
-       }
+static struct argp_option options[] = {
+       { .name = "devn",
+         .key = 'd',
+         .arg = "<devn>",
+         .flags = 0,
+         .doc = "UBI device",
+         .group = OPTION_ARG_OPTIONAL },
 
-       err = ubi_mkvol(lib, devn, vol_id, vol_type, bytes, alignment, name);
-       if (err < 0) {
-               perror("Cannot create volume");
-               fprintf(stderr, "  err=%d\n", err);
-               goto out_libubi;
-       }
+       { .name = "vol_id",
+         .key = 'n',
+         .arg = "<volume id>",
+         .flags = 0,
+         .doc = "UBI volume id, if not specified, the volume ID will be "
+                "assigned automatically",
+         .group = OPTION_ARG_OPTIONAL },
 
-       /* printf("Created volume %d, %lld bytes, type %s, name %s\n",
-          vol_id, bytes, vol_type == UBI_DYNAMIC_VOLUME ?
-          "dynamic" : "static", name); */
+       { .name = "type",
+         .key = 't',
+         .arg = "<static|dynamic>",
+         .flags = 0,
+         .doc = "volume type (dynamic, static), default is dynamic",
+         .group = OPTION_ARG_OPTIONAL },
 
-       vol_id = err;
-       ubi_close(&lib);
-       return 0;
+       { .name = "size",
+         .key = 's',
+         .arg = "<bytes>",
+         .flags = 0,
+         .doc = "volume size volume size in bytes, "
+         "kilobytes (KiB) or megabytes (MiB)",
+         .group = OPTION_ARG_OPTIONAL },
 
-out_libubi:
-       ubi_close(&lib);
-       return -1;
-}
+       { .name = "name",
+         .key = 'N',
+         .arg = "<name>",
+         .flags = 0,
+         .doc = "volume name",
+         .group = OPTION_ARG_OPTIONAL },
+
+       { .name = "alignment",
+         .key = 'a',
+         .arg = "<alignment>",
+         .flags = 0,
+         .doc = "volume alignment (default is 1)",
+         .group = OPTION_ARG_OPTIONAL },
 
-/* 'getopt()' option string */
-static const char *optstring = "ht:s:n:N:d:a:";
+       { .name = NULL, .key = 0, .arg = NULL, .flags = 0,
+         .doc = NULL, .group = 0 },
+};
 
-static int parse_options(int argc, char * const argv[])
+static struct argp argp = {
+       .options = options,
+       .parser = parse_opt,
+       .args_doc = 0,
+       .doc =  doc,
+       .children = NULL,
+       .help_filter = NULL,
+       .argp_domain = NULL,
+};
+
+/*
+ * @brief Parse the arguments passed into the test case.
+ *
+ * @param key           The parameter.
+ * @param arg           Argument passed to parameter.
+ * @param state                 Location to put information on parameters.
+ *
+ * @return error
+ *
+ * Get the `input' argument from `argp_parse', which we know is a
+ * pointer to our arguments structure.
+ */
+static error_t
+parse_opt(int key, char *optarg, struct argp_state *state)
 {
-       int opt = 0;
-
-       while (opt != -1) {
-               char *endp;
-
-               opt = getopt(argc, argv, optstring);
-
-               switch (opt) {
-               case 'h':
-                       usage();
-                       return 1;
-               case 't':
-                       if (!strcmp(optarg, "dynamic"))
-                               vol_type = UBI_DYNAMIC_VOLUME;
-                       else if (!strcmp(optarg, "static"))
-                               vol_type = UBI_STATIC_VOLUME;
-                       else {
-                               fprintf(stderr, "Bad volume type: \"%s\"\n",
-                                       optarg);
-                               goto out;
-                       }
-                       break;
-               case 's':
-                       bytes = strtoull(optarg, &endp, 0);
-                       if (endp == optarg || bytes < 0) {
-                               fprintf(stderr, "Bad volume size: \"%s\"\n",
-                                       optarg);
-                               goto out;
-                       }
-                       if (endp != '\0') {
-                               if (strcmp(endp, "KiB") == 0)
-                                       bytes *= 1024;
-                               else if (strcmp(endp, "MiB") == 0)
-                                       bytes *= 1024*1024;
-                       }
-                       break;
-               case 'a':
-                       alignment = strtoul(optarg, &endp, 0);
-                       if (*endp != '\0' || endp == optarg ||
-                           alignment <= 0) {
-                               fprintf(stderr, "Bad volume alignment: "
-                                       "\"%s\"\n", optarg);
-                               goto out;
-                       }
-                       break;
-               case 'd':
-                       devn = strtoul(optarg, &endp, 0);
-                       if (*endp != '\0' || endp == optarg || devn < 0) {
-                               fprintf(stderr, "Bad UBI device number: "
-                                       "\"%s\"\n", optarg);
-                               goto out;
-                       }
-                       break;
-               case 'n':
-                       vol_id = strtoul(optarg, &endp, 0);
-                       if (*endp != '\0' || endp == optarg ||
-                           (vol_id < 0 && vol_id != UBI_DYNAMIC_VOLUME)) {
-                               fprintf(stderr, "Bad volume ID: "
-                                       "\"%s\"\n", optarg);
-                               goto out;
-                       }
-                       break;
-               case 'N':
-                       name = optarg;
-                       nlen = strlen(name);
-                       break;
-
-               case ':':
-                       fprintf(stderr, "Parameter is missing\n");
+       char *endp;
+       struct args *args = state->input;
+
+       switch (key) {
+       case 't':
+               if (!strcmp(optarg, "dynamic"))
+                       args->vol_type = UBI_DYNAMIC_VOLUME;
+               else if (!strcmp(optarg, "static"))
+                       args->vol_type = UBI_STATIC_VOLUME;
+               else {
+                       fprintf(stderr, "Bad volume type: \"%s\"\n",
+                               optarg);
                        goto out;
-               case '?':
-                       fprintf(stderr, "Unknown parameter\n");
+               }
+               break;
+       case 's':
+               args->bytes = strtoull(optarg, &endp, 0);
+               if (endp == optarg || args->bytes < 0) {
+                       fprintf(stderr, "Bad volume size: \"%s\"\n",
+                               optarg);
                        goto out;
-               case -1:
-                       break;
-               default:
-                       fprintf(stderr, "Internal error\n");
+               }
+               if (endp != '\0') {
+                       if (strcmp(endp, "KiB") == 0)
+                               args->bytes *= 1024;
+                       else if (strcmp(endp, "MiB") == 0)
+                               args->bytes *= 1024*1024;
+               }
+               break;
+       case 'a':
+               args->alignment = strtoul(optarg, &endp, 0);
+               if (*endp != '\0' || endp == optarg ||
+                   args->alignment <= 0) {
+                       fprintf(stderr, "Bad volume alignment: "
+                               "\"%s\"\n", optarg);
                        goto out;
                }
+               break;
+       case 'd': /* --devn=<device number> */
+               args->devn = strtoul(optarg, &endp, 0);
+               if (*endp != '\0' || endp == optarg || args->devn < 0) {
+                       fprintf(stderr, "Bad UBI device number: "
+                               "\"%s\"\n", optarg);
+                       goto out;
+               }
+               break;
+       case 'n': /* --volid=<volume id> */
+               args->vol_id = strtoul(optarg, &endp, 0);
+               if (*endp != '\0' || endp == optarg ||
+                   (args->vol_id < 0 && args->vol_id != UBI_DYNAMIC_VOLUME)) {
+                       fprintf(stderr, "Bad volume ID: "
+                               "\"%s\"\n", optarg);
+                       goto out;
+               }
+               break;
+       case 'N':
+               args->name = optarg;
+               args->nlen = strlen(args->name);
+               break;
+
+       case ':':
+               fprintf(stderr, "Parameter is missing\n");
+               goto out;
+
+       case ARGP_KEY_NO_ARGS:
+               /* argp_usage(state); */
+               break;
+
+       case ARGP_KEY_ARG:
+               args->arg1 = optarg;
+               /* Now we consume all the rest of the arguments.
+                  `state->next' is the index in `state->argv' of the
+                  next argument to be parsed, which is the first STRING
+                  we're interested in, so we can just use
+                  `&state->argv[state->next]' as the value for
+                  arguments->strings.
+
+                  _In addition_, by setting `state->next' to the end
+                  of the arguments, we can force argp to stop parsing
+                  here and return. */
+
+               args->options = &state->argv[state->next];
+               state->next = state->argc;
+               break;
+
+       case ARGP_KEY_END:
+               /* argp_usage(state); */
+               break;
+
+       default:
+               return(ARGP_ERR_UNKNOWN);
        }
 
        return 0;
-
  out:
-       errno = EINVAL;
-       return -1;
+       return(ARGP_ERR_UNKNOWN);
 }
 
-static int param_sanity_check(ubi_lib_t lib)
+static int param_sanity_check(struct args *args, ubi_lib_t lib)
 {
        int err, len;
        struct ubi_info ubi;
 
-       if (bytes == 0) {
+       if (args->bytes == 0) {
                fprintf(stderr, "Volume size was not specified\n");
                goto out;
        }
 
-       if (name == NULL) {
+       if (args->name == NULL) {
                fprintf(stderr, "Volume name was not specified\n");
                goto out;
        }
@@ -213,39 +267,72 @@ static int param_sanity_check(ubi_lib_t lib)
        if (err)
                return -1;
 
-       if (devn >= (int)ubi.dev_count) {
-               fprintf(stderr, "Device %d does not exist\n", devn);
+       if (args->devn >= (int)ubi.dev_count) {
+               fprintf(stderr, "Device %d does not exist\n", args->devn);
                goto out;
        }
 
-       len = strlen(name);
-       if (len > (int)ubi.nlen_max) {
+       len = strlen(args->name);
+       if (len > UBI_MAX_VOLUME_NAME) {
                fprintf(stderr, "Too long name (%d symbols), max is %d\n",
-                       len, ubi.nlen_max);
+                       len, UBI_MAX_VOLUME_NAME);
                goto out;
        }
 
        return 0;
-
 out:
        errno = EINVAL;
        return -1;
 }
 
-static void usage(void)
+int main(int argc, char * const argv[])
 {
-       printf("Usage: ubi_mkvol OPTIONS\n"
-              "Version: " PACKAGE_VERSION "\n"
-              "The command line options:\n"
-              "\t-h - this help message\n"
-              "\t-d - UBI device number\n"
-              "\t-t TYPE  - volume type (dynamic, static) "
-              "(default is dynamic)\n"
-              "\t-n VOLID - volume ID to assign to the new volume. If not"
-              "specified, \n"
-              "\t           the volume ID will be assigned automatically\n"
-              "\t-s BYTES - volume size in bytes, "
-              "kilobytes (KiB) or megabytes (MiB)\n"
-              "\t-N NAME  - volume name\n"
-              "\t-a ALIGNMENT - volume alignment (default is 1)\n");
+       int err;
+       ubi_lib_t lib;
+
+       err = argp_parse(&argp, argc, (char **)argv, ARGP_IN_ORDER, 0,
+                        &myargs);
+       if (err) {
+               fprintf(stderr, "Wrong options ...\n");
+               return err == 1 ? 0 : -1;
+       }
+
+       if (myargs.devn == -1) {
+               fprintf(stderr, "Device number was not specified\n");
+               fprintf(stderr, "Use -h option for help\n");
+               return -1;
+       }
+
+       err = ubi_open(&lib);
+       if (err) {
+               perror("Cannot open libubi");
+               return -1;
+       }
+
+       err = param_sanity_check(&myargs, lib);
+       if (err) {
+               perror("Input parameters check");
+               fprintf(stderr, "Use -h option for help\n");
+               goto out_libubi;
+       }
+
+       err = ubi_mkvol(lib, myargs.devn, myargs.vol_id, myargs.vol_type,
+                       myargs.bytes, myargs.alignment, myargs.name);
+       if (err < 0) {
+               perror("Cannot create volume");
+               fprintf(stderr, "  err=%d\n", err);
+               goto out_libubi;
+       }
+
+       /* printf("Created volume %d, %lld bytes, type %s, name %s\n",
+          vol_id, bytes, vol_type == UBI_DYNAMIC_VOLUME ?
+          "dynamic" : "static", name); */
+
+       myargs.vol_id = err;
+       ubi_close(&lib);
+       return 0;
+
+out_libubi:
+       ubi_close(&lib);
+       return -1;
 }
index cb47b6cb029427ab49546b4757dbaee70609fad8..f810263946ec09ac8acee4fbff993c87eee05b97 100644 (file)
  */
 
 /*
- * An utility to create UBI volumes.
+ * An utility to remove UBI volumes.
  *
- * Autor: Artem B. Bityutskiy <dedekind@oktetlabs.ru>
+ * Author: Artem B. Bityutskiy <dedekind@linutronix.de>
+ *         Frank Haverkamp <haver@vnet.ibm.com>
+ *
+ * 1.1 Reworked the userinterface to use argp.
  */
 
+#include <argp.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <getopt.h>
 #include <string.h>
 #include <errno.h>
 
-#include "config.h"
+#include <config.h>
 #include <libubi.h>
 
-static void usage(void);
-static int param_sanity_check(ubi_lib_t lib);
-static int parse_options(int argc, char * const argv[]);
+#define VERSION "1.1"
 
 /*
  * The below variables are set by command line options.
  */
-static int vol_id = -1;
-static int devn = -1;
+struct args {
+       int devn;
+       int vol_id;
+
+       /* special stuff needed to get additional arguments */
+       char *arg1;
+       char **options;         /* [STRING...] */
+};
+
+static struct args myargs = {
+       .devn = -1,
+       .vol_id = -1,
+
+       .arg1 = NULL,
+       .options = NULL,
+};
+
+static int param_sanity_check(struct args *args, ubi_lib_t lib);
+static error_t parse_opt(int key, char *optarg, struct argp_state *state);
+const char *argp_program_bug_address = PACKAGE_BUGREPORT;
+
+static char doc[] = "\nVersion: " VERSION "\n\t"
+       BUILD_OS" "BUILD_CPU" at "__DATE__" "__TIME__"\n"
+       "\nMake UBI Volume.\n";
+
+static struct argp_option options[] = {
+       { .name = "devn",
+         .key = 'd',
+         .arg = "<devn>",
+         .flags = 0,
+         .doc = "UBI device",
+         .group = OPTION_ARG_OPTIONAL },
+
+       { .name = "vol_id",
+         .key = 'n',
+         .arg = "<volume id>",
+         .flags = 0,
+         .doc = "UBI volume id, if not specified, the volume ID will be "
+                "assigned automatically",
+         .group = OPTION_ARG_OPTIONAL },
+
+       { .name = NULL, .key = 0, .arg = NULL, .flags = 0,
+         .doc = NULL, .group = 0 },
+};
+
+static struct argp argp = {
+       .options = options,
+       .parser = parse_opt,
+       .args_doc = 0,
+       .doc =  doc,
+       .children = NULL,
+       .help_filter = NULL,
+       .argp_domain = NULL,
+};
+
+/*
+ * @brief Parse the arguments passed into the test case.
+ *
+ * @param key           The parameter.
+ * @param arg           Argument passed to parameter.
+ * @param state                 Location to put information on parameters.
+ *
+ * @return error
+ *
+ * Get the `input' argument from `argp_parse', which we know is a
+ * pointer to our arguments structure.
+ */
+static error_t
+parse_opt(int key, char *optarg, struct argp_state *state)
+{
+       char *endp;
+       struct args *args = state->input;
+
+       switch (key) {
+       case 'd': /* --devn=<device number> */
+               args->devn = strtoul(optarg, &endp, 0);
+               if (*endp != '\0' || endp == optarg || args->devn < 0) {
+                       fprintf(stderr, "Bad UBI device number: "
+                               "\"%s\"\n", optarg);
+                       goto out;
+               }
+               break;
+       case 'n': /* --volid=<volume id> */
+               args->vol_id = strtoul(optarg, &endp, 0);
+               if (*endp != '\0' || endp == optarg ||
+                   (args->vol_id < 0 && args->vol_id != UBI_DYNAMIC_VOLUME)) {
+                       fprintf(stderr, "Bad volume ID: "
+                               "\"%s\"\n", optarg);
+                       goto out;
+               }
+               break;
+       case ':':
+               fprintf(stderr, "Parameter is missing\n");
+               goto out;
+
+       case ARGP_KEY_NO_ARGS:
+               /* argp_usage(state); */
+               break;
+
+       case ARGP_KEY_ARG:
+               args->arg1 = optarg;
+               /* Now we consume all the rest of the arguments.
+                  `state->next' is the index in `state->argv' of the
+                  next argument to be parsed, which is the first STRING
+                  we're interested in, so we can just use
+                  `&state->argv[state->next]' as the value for
+                  arguments->strings.
+
+                  _In addition_, by setting `state->next' to the end
+                  of the arguments, we can force argp to stop parsing
+                  here and return. */
+
+               args->options = &state->argv[state->next];
+               state->next = state->argc;
+               break;
+
+       case ARGP_KEY_END:
+               /* argp_usage(state); */
+               break;
+
+       default:
+               return(ARGP_ERR_UNKNOWN);
+       }
+
+       return 0;
+ out:
+       return(ARGP_ERR_UNKNOWN);
+}
+
+static int param_sanity_check(struct args *args, ubi_lib_t lib)
+{
+       int err;
+       struct ubi_info ubi;
+
+       if (args->vol_id == -1) {
+               fprintf(stderr, "Volume ID was not specified\n");
+               goto out;
+       }
+
+       err = ubi_get_info(lib, &ubi);
+       if (err)
+               return -1;
+
+       if (args->devn >= (int)ubi.dev_count) {
+               fprintf(stderr, "Device %d does not exist\n", args->devn);
+               goto out;
+       }
+
+       return 0;
+
+out:
+       errno = EINVAL;
+       return -1;
+}
 
 int main(int argc, char * const argv[])
 {
        int err, old_errno;
        ubi_lib_t lib;
 
-       err = parse_options(argc, argv);
+       err = argp_parse(&argp, argc, (char **)argv, ARGP_IN_ORDER, 0,
+                        &myargs);
        if (err)
                return err == 1 ? 0 : -1;
 
-       if (devn == -1) {
+       if (myargs.devn == -1) {
                fprintf(stderr, "Device number was not specified\n");
                fprintf(stderr, "Use -h option for help\n");
                return -1;
@@ -63,14 +218,14 @@ int main(int argc, char * const argv[])
                return -1;
        }
 
-       err = param_sanity_check(lib);
+       err = param_sanity_check(&myargs, lib);
        if (err) {
                perror("Input parameters check");
                fprintf(stderr, "Use -h option for help\n");
                goto out_libubi;
        }
 
-       err = ubi_rmvol(lib, devn, vol_id);
+       err = ubi_rmvol(lib, myargs.devn, myargs.vol_id);
        old_errno = errno;
        if (err < 0) {
                perror("Cannot remove volume");
@@ -84,91 +239,3 @@ out_libubi:
        ubi_close(&lib);
        return -1;
 }
-
-/* 'getopt()' option string */
-static const char *optstring = "hd:n:";
-
-static int parse_options(int argc, char * const argv[])
-{
-       int opt = 0;
-
-       while (opt != -1) {
-               char *endp;
-
-               opt = getopt(argc, argv, optstring);
-
-               switch (opt) {
-               case 'h':
-                       usage();
-                       return 1;
-               case 'n':
-                       vol_id = strtoul(optarg, &endp, 0);
-                       if (*endp != '\0' || endp == optarg || vol_id < 0) {
-                               fprintf(stderr, "Bad volume "
-                                       "number: \"%s\"\n", optarg);
-                               goto out;
-                       }
-                       break;
-               case 'd':
-                       devn = strtoul(optarg, &endp, 0);
-                       if (*endp != '\0' || endp == optarg || devn < 0) {
-                               fprintf(stderr, "Bad UBI device "
-                                       "number: \"%s\"\n", optarg);
-                               goto out;
-                       }
-                       break;
-               case ':':
-                       fprintf(stderr, "Parameter is missing\n");
-                       goto out;
-               case '?':
-                       fprintf(stderr, "Unknown parameter\n");
-                       goto out;
-               case -1:
-                       break;
-               default:
-                       fprintf(stderr, "Internal error\n");
-                       goto out;
-               }
-       }
-
-       return 0;
-
-out:
-       errno = EINVAL;
-       return -1;
-}
-
-static int param_sanity_check(ubi_lib_t lib)
-{
-       int err;
-       struct ubi_info ubi;
-
-       if (vol_id == -1) {
-               fprintf(stderr, "Volume ID was not specified\n");
-               goto out;
-       }
-
-       err = ubi_get_info(lib, &ubi);
-       if (err)
-               return -1;
-
-       if (devn >= (int)ubi.dev_count) {
-               fprintf(stderr, "Device %d does not exist\n", devn);
-               goto out;
-       }
-
-       return 0;
-
-out:
-       errno = EINVAL;
-       return -1;
-}
-
-static void usage(void)
-{
-       printf("Usage: ubi_rmvol OPTIONS\n"
-              "Command line options:\n"
-              "\t-h - this help message\n"
-              "\t-d - UBI device number\n"
-              "\t-n VOLNUM - volume number to remove\n");
-}
index 28e1e8f0f61e4dca105b1cd76c0da96ab65b60ff..fd68dd8865db06f12463d28e523b65982818a2e9 100644 (file)
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * An utility to update UBI volumes.
  *
  * Author: Frank Haverkamp
  *
- * An utility to update UBI volumes.
+ * 1.0 Reworked the userinterface to use argp.
  */
 
-#include <config.h>
-
 #include <argp.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 
+#include <config.h>
 #include <libubi.h>
 
+#define VERSION "1.0"
+
 #define MAXPATH                1024
 #define BUFSIZE                128 * 1024
 #define MIN(x,y)       ((x)<(y)?(x):(y))
 
 struct args {
-       int device;
-       int volume;
+       int devn;
+       int vol_id;
        int truncate;
        int broken_update;
        int bufsize;
@@ -55,8 +60,8 @@ struct args {
 };
 
 static struct args myargs = {
-       .device = -1,
-       .volume = -1,
+       .devn = -1,
+       .vol_id = -1,
        .truncate = 0,
        .broken_update = 0,
        .bufsize = BUFSIZE,
@@ -64,25 +69,24 @@ static struct args myargs = {
        .options = NULL,
 };
 
-static int verbose = 0;
-
 static error_t parse_opt (int key, char *arg, struct argp_state *state);
 
+static int verbose = 0;
 const char *argp_program_bug_address = PACKAGE_BUGREPORT;
 
-static char doc[] = "\nVersion: " PACKAGE_VERSION "\n\t"
+static char doc[] = "\nVersion: " VERSION "\n\t"
        BUILD_OS" "BUILD_CPU" at "__DATE__" "__TIME__"\n"
        "\nWrite to UBI Volume.\n";
 
 static struct argp_option options[] = {
-       { .name = "device",
+       { .name = "devn",
          .key = 'd',
-         .arg = "<device number>",
+         .arg = "<devn>",
          .flags = 0,
          .doc = "UBI device",
          .group = OPTION_ARG_OPTIONAL },
 
-       { .name = "volume",
+       { .name = "vol_id",
          .key = 'n',
          .arg = "<volume id>",
          .flags = 0,
@@ -139,8 +143,12 @@ parse_opt(int key, char *arg, struct argp_state *state)
                verbose = strtoul(arg, (char **)NULL, 0);
                break;
 
-       case 'd': /* --device=<device number> */
-               args->device = strtol(arg, (char **)NULL, 0);
+       case 'n': /* --vol_id=<volume id> */
+               args->vol_id = strtol(arg, (char **)NULL, 0);
+               break;
+
+       case 'd': /* --devn=<device number> */
+               args->devn = strtol(arg, (char **)NULL, 0);
                break;
 
        case 'b': /* --bufsize=<bufsize> */
@@ -157,10 +165,6 @@ parse_opt(int key, char *arg, struct argp_state *state)
                args->broken_update = 1;
                break;
 
-       case 'n': /* --volume=<volume id> */
-               args->volume = strtol(arg, (char **)NULL, 0);
-               break;
-
        case ARGP_KEY_NO_ARGS:
                /* argp_usage(state); */
                break;
@@ -175,8 +179,8 @@ parse_opt(int key, char *arg, struct argp_state *state)
                    arguments->strings.
 
                    _In addition_, by setting `state->next' to the end
-                   of the arguments, we can force argp to stop parsing here and
-                   return. */
+                   of the arguments, we can force argp to stop parsing
+                   here and return. */
 
                args->options = &state->argv[state->next];
                state->next = state->argc;
@@ -205,7 +209,7 @@ ubi_truncate_volume(struct args *args, int64_t bytes)
        char path[MAXPATH];
        int old_errno;
 
-       snprintf(path, MAXPATH-1, "/dev/ubi%d_%d", args->device, args->volume);
+       snprintf(path, MAXPATH-1, "/dev/ubi%d_%d", args->devn, args->vol_id);
        path[MAXPATH-1] = '\0';
 
        ofd = open(path, O_RDWR);
@@ -279,7 +283,7 @@ ubi_update_volume(struct args *args)
        if (!ifp)
                exit(EXIT_FAILURE);
 
-       snprintf(path, MAXPATH-1, "/dev/ubi%d_%d", args->device, args->volume);
+       snprintf(path, MAXPATH-1, "/dev/ubi%d_%d", args->devn, args->vol_id);
        path[MAXPATH-1] = '\0';
 
        ofd = open(path, O_RDWR);