diff --git a/libdm/ioctl/libdevmapper.c b/libdm/ioctl/libdevmapper.c index 4f11ad13c..e8f165ed7 100644 --- a/libdm/ioctl/libdevmapper.c +++ b/libdm/ioctl/libdevmapper.c @@ -51,10 +51,17 @@ int dm_task_get_info(struct dm_task *dmt, struct dm_info *info) info->open_count = dmt->dmi->open_count; info->major = dmt->dmi->major; info->minor = dmt->dmi->minor; + info->read_only = dmt->dmi->read_only; info->target_count = dmt->dmi->target_count; return 1; } +int dm_task_set_ro(struct dm_task *dmt) +{ + dmt->read_only = 1; + return 1; +} + struct target *create_target(uint64_t start, uint64_t len, const char *type, const char *params) @@ -156,6 +163,7 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt) dmi->suspend = (dmt->type == DM_DEVICE_SUSPEND) ? 1 : 0; dmi->open_count = 0; dmi->minor = -1; + dmi->read_only = dmt->read_only; dmi->target_count = count; diff --git a/libdm/ioctl/libdm-targets.h b/libdm/ioctl/libdm-targets.h index 884ea110c..72906c317 100644 --- a/libdm/ioctl/libdm-targets.h +++ b/libdm/ioctl/libdm-targets.h @@ -19,6 +19,7 @@ struct dm_task { struct target *head, *tail; + int read_only; struct dm_ioctl *dmi; }; diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h index 8a2428f88..7b095a515 100644 --- a/libdm/libdevmapper.h +++ b/libdm/libdevmapper.h @@ -57,11 +57,15 @@ struct dm_info { unsigned int open_count; int major; int minor; /* minor device number */ + int read_only; + unsigned int target_count; }; int dm_task_get_info(struct dm_task *dmt, struct dm_info *dmi); +int dm_task_set_ro(struct dm_task *dmt); + /* * Use these to prepare for a create or reload. */ diff --git a/libdm/libdm-common.c b/libdm/libdm-common.c index f108e91d2..679fd71e7 100644 --- a/libdm/libdm-common.c +++ b/libdm/libdm-common.c @@ -26,7 +26,7 @@ static char _dm_dir[PATH_MAX] = DEV_DIR DM_DIR; -/* +/* * Library users can provide their own logging * function. */ @@ -35,7 +35,7 @@ void _default_log(int level, const char *file, int line, { va_list ap; - va_start(ap, f); + va_start(ap, f); vfprintf(stderr, f, ap); va_end(ap); diff --git a/tools/dmsetup.c b/tools/dmsetup.c index 770e084aa..380bf01a4 100644 --- a/tools/dmsetup.c +++ b/tools/dmsetup.c @@ -16,11 +16,27 @@ #include #include #include +#include +#include #define LINE_SIZE 1024 #define err(msg, x...) fprintf(stderr, msg "\n", ##x) +/* + * We have only very simple switches ATM. + */ +enum { + READ_ONLY = 0, + NUM_SWITCHES +}; + +static int _switches[NUM_SWITCHES]; + + +/* + * Commands + */ static int _parse_file(struct dm_task *dmt, const char *file) { char buffer[LINE_SIZE], *ttype, *ptr, *comment; @@ -86,6 +102,9 @@ static int _load(int task, const char *name, const char *file) if (!_parse_file(dmt, file)) goto out; + if (_switches[READ_ONLY] && !dm_task_set_ro(dmt)) + goto out; + if (!dm_task_run(dmt)) goto out; @@ -221,7 +240,7 @@ static void _usage(FILE *out) return; } -struct command *_find_command(const char *name) +static struct command *_find_command(const char *name) { int i; @@ -232,29 +251,57 @@ struct command *_find_command(const char *name) return NULL; } +static int _process_switches(int *argc, char ***argv) +{ + int index; + char c; + + static struct option long_options[] = { + {"read-only", 0, NULL, READ_ONLY}, + }; + + /* + * Zero all the index counts. + */ + memset(&_switches, 0, sizeof(_switches)); + + while ((c = getopt_long(*argc, *argv, "r", + long_options, &index)) != -1) + if (c == 'r' || index == READ_ONLY) + _switches[READ_ONLY]++; + + *argv += optind; + *argc -= optind; + return 1; +} int main(int argc, char **argv) { struct command *c; + if (!_process_switches(&argc, &argv)) { + fprintf(stderr, "Couldn't process command line switches.\n"); + exit(1); + } + if (argc < 2) { _usage(stderr); exit(1); } - if (!(c = _find_command(argv[1]))) { + if (!(c = _find_command(argv[0]))) { fprintf(stderr, "Unknown command\n"); _usage(stderr); exit(1); } - if (argc != c->num_args + 2) { + if (argc != c->num_args + 1) { fprintf(stderr, "Incorrect number of arguments\n"); _usage(stderr); exit(1); } - if (!c->fn(argc - 1, argv + 1)) { + if (!c->fn(argc, argv)) { fprintf(stderr, "Command failed\n"); exit(1); }