From 7103b9b88d8c27989e17c80d7296eda97370dc1e Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 4 Oct 2012 16:34:20 +1000 Subject: [PATCH] Handles spaces in array names better. 1/ When printing the "name=" entry for --brief output, enclose name in quotes if it contains spaces etc. Quotes are already supported for reading mdadm.conf 2/ When a name is used as a device name, translate spaces and tabs to '_', as well as the current translation of '/' to '-'. Signed-off-by: NeilBrown --- Detail.c | 14 ++++++++---- lib.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ mapfile.c | 2 +- mdadm.h | 2 ++ mdopen.c | 13 +++++++++-- super1.c | 19 ++++++++++++---- 6 files changed, 106 insertions(+), 12 deletions(-) diff --git a/Detail.c b/Detail.c index 9bf20618..8ca3a962 100644 --- a/Detail.c +++ b/Detail.c @@ -206,8 +206,11 @@ int Detail(char *dev, struct context *c) printf("MD_UUID=%s\n", nbuf+5); mp = map_by_uuid(&map, info->uuid); if (mp && mp->path && - strncmp(mp->path, "/dev/md/", 8) == 0) - printf("MD_DEVNAME=%s\n", mp->path+8); + strncmp(mp->path, "/dev/md/", 8) == 0) { + printf("MD_DEVNAME="); + print_escape(mp->path+8); + putchar('\n'); + } if (st->ss->export_detail_super) st->ss->export_detail_super(st); @@ -220,8 +223,11 @@ int Detail(char *dev, struct context *c) printf("MD_UUID=%s\n", nbuf+5); } if (mp && mp->path && - strncmp(mp->path, "/dev/md/", 8) == 0) - printf("MD_DEVNAME=%s\n", mp->path+8); + strncmp(mp->path, "/dev/md/", 8) == 0) { + printf("MD_DEVNAME="); + print_escape(mp->path+8); + putchar('\n'); + } } goto out; } diff --git a/lib.c b/lib.c index 082cff56..dc32c561 100644 --- a/lib.c +++ b/lib.c @@ -322,3 +322,71 @@ char *conf_word(FILE *file, int allow_key) } return word; } + +void print_quoted(char *str) +{ + /* Printf the string with surrounding quotes + * iff needed. + * If no space, tab, or quote - leave unchanged. + * Else print surrounded by " or ', swapping quotes + * when we find one that will cause confusion. + */ + + char first_quote = 0, q; + char *c; + + for (c = str; *c; c++) { + switch(*c) { + case '\'': + case '"': + first_quote = *c; + break; + case ' ': + case '\t': + first_quote = *c; + continue; + default: + continue; + } + break; + } + if (!first_quote) { + printf("%s", str); + return; + } + + if (first_quote == '"') + q = '\''; + else + q = '"'; + putchar(q); + for (c = str; *c; c++) { + if (*c == q) { + putchar(q); + q ^= '"' ^ '\''; + putchar(q); + } + putchar(*c); + } + putchar(q); +} + +void print_escape(char *str) +{ + /* print str, but change space and tab to '_' + * as is suitable for device names + */ + for (; *str ; str++) { + switch (*str) { + case ' ': + case '\t': + putchar('_'); + break; + case '/': + putchar('-'); + break; + default: + putchar(*str); + } + } +} diff --git a/mapfile.c b/mapfile.c index 6712733f..34ebdb54 100644 --- a/mapfile.c +++ b/mapfile.c @@ -422,7 +422,7 @@ void RebuildMap(void) * an MD_DEVNAME for udev. * The name needs to be unique both in /dev/md/ * and in this mapfile. - * It needs to match watch -I or -As would come + * It needs to match what -I or -As would come * up with. * That means: * Check if array is in mdadm.conf diff --git a/mdadm.h b/mdadm.h index 1390be8d..6980bfb8 100644 --- a/mdadm.h +++ b/mdadm.h @@ -1196,6 +1196,8 @@ extern char *conf_get_program(void); extern char *conf_get_homehost(int *require_homehostp); extern char *conf_line(FILE *file); extern char *conf_word(FILE *file, int allow_key); +extern void print_quoted(char *str); +extern void print_escape(char *str); extern int conf_name_is_free(char *name); extern int conf_verify_devnames(struct mddev_ident *array_list); extern int devname_matches(char *name, char *match); diff --git a/mdopen.c b/mdopen.c index 58e359aa..61eda812 100644 --- a/mdopen.c +++ b/mdopen.c @@ -286,8 +286,17 @@ int create_mddev(char *dev, char *name, int autof, int trustworthy, int cnlen; strncpy(cname, name, 200); cname[200] = 0; - while ((cp = strchr(cname, '/')) != NULL) - *cp = '-'; + for (cp = cname; *cp ; cp++) + switch (*cp) { + case '/': + *cp = '-'; + break; + case ' ': + case '\t': + *cp = '_'; + break; + } + if (trustworthy == LOCAL || (trustworthy == FOREIGN && strchr(cname, ':') != NULL)) { /* Only need suffix if there is a conflict */ diff --git a/super1.c b/super1.c index 3ace6fc7..96d5b1b0 100644 --- a/super1.c +++ b/super1.c @@ -485,7 +485,12 @@ static void brief_examine_super1(struct supertype *st, int verbose) else nm = NULL; - printf("ARRAY%s%s", nm ? " /dev/md/":"", nm); + printf("ARRAY "); + if (nm) { + printf("/dev/md/"); + print_escape(nm); + putchar(' '); + } if (verbose && c) printf(" level=%s", c); sb_offset = __le64_to_cpu(sb->super_offset); @@ -502,8 +507,10 @@ static void brief_examine_super1(struct supertype *st, int verbose) if ((i&3)==0 && i != 0) printf(":"); printf("%02x", sb->set_uuid[i]); } - if (sb->set_name[0]) - printf(" name=%.32s", sb->set_name); + if (sb->set_name[0]) { + printf(" name="); + print_quoted(sb->set_name); + } printf("\n"); } @@ -584,8 +591,10 @@ static void brief_detail_super1(struct supertype *st) struct mdp_superblock_1 *sb = st->sb; int i; - if (sb->set_name[0]) - printf(" name=%.32s", sb->set_name); + if (sb->set_name[0]) { + printf(" name="); + print_quoted(sb->set_name); + } printf(" UUID="); for (i=0; i<16; i++) { if ((i&3)==0 && i != 0) printf(":"); -- 2.39.2