]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Allow default creation info to to be stored in mdadm.conf
authorNeil Brown <neilb@suse.de>
Mon, 15 May 2006 06:02:41 +0000 (06:02 +0000)
committerNeil Brown <neilb@suse.de>
Mon, 15 May 2006 06:02:41 +0000 (06:02 +0000)
Default owner, group, mode and 'auto' flag can be given in a 'CREATE' line.

Signed-off-by: Neil Brown <neilb@suse.de>
ChangeLog
Makefile
config.c
mdadm.c
mdadm.conf.5
mdadm.h
mdopen.c

index e4f4dad9bde9c31ce63384adbe0312ba887c1deb..8f8d94994d199b3cf6b3fa27e3ea731b130fd4d7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -8,6 +8,8 @@ Changes Prior to this release
     -   When creating a bitmap file, choose a chunksize to limit number
        of bitmap chunks to 2 million.  More than this can cause kmalloc
        failure.
+    -   New 'CREATE' line in mdadm.conf for defaults such as owner, group,
+       mode and auto-flag
 
 Changes Prior to 2.4.1 release
     -   Honour --write-mostly when adding to an array without persistent
index 6b647134ae5e72ff9a519244e0235348601f9e77..8ddb997642ae3cb86235a59a5bde1b741235cc66 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -40,10 +40,17 @@ KLIBC_GCC = gcc -nostdinc -iwithprefix include -I$(KLIBC)/klibc/include -I$(KLIB
 CC = $(CROSS_COMPILE)gcc
 CXFLAGS = -ggdb
 CWFLAGS = -Wall -Werror -Wstrict-prototypes
+
+ifdef DEBIAN
+CPPFLAGS= -DDEBIAN
+else
+CPPFLAGS=
+endif
+
 SYSCONFDIR = /etc
 CONFFILE = $(SYSCONFDIR)/mdadm.conf
 MAILCMD =/usr/sbin/sendmail -t
-CFLAGS = $(CWFLAGS) -DCONFFILE=\"$(CONFFILE)\" $(CXFLAGS) -DSendmail=\""$(MAILCMD)"\"
+CFLAGS = $(CWFLAGS) $(STATIC) $(CPPFLAGS) -DCONFFILE=\"$(CONFFILE)\" $(CXFLAGS) -DSendmail=\""$(MAILCMD)"\"
 
 # If you want a static binary, you might uncomment these
 # LDFLAGS = -static
@@ -76,11 +83,14 @@ all : mdadm mdadm.man md.man mdadm.conf.man
 everything: all mdadm.static mdadm.uclibc swap_super test_stripe  mdassemble mdassemble.uclibc mdassemble.static mdassemble.man
 # mdadm.tcc doesn't work..
 
-mdadm : $(OBJS)
-       $(CC) $(LDFLAGS) -o mdadm $^
+mdadm : rmconf $(OBJS)
+       $(CC) $(LDFLAGS) -o mdadm $(OBJS)
 
-mdadm.static : $(OBJS)
-       $(CC) $(LDFLAGS) -static -o mdadm.static $^
+mdadm.static : STATIC=-DSTATIC
+mdadm.static : rmconf $(OBJS)
+       $(CC) $(LDFLAGS) -DSTATIC -static -o mdadm.static $(OBJS)
+rmconf:
+       rm -f config.o
 
 mdadm.tcc : $(SRCS) mdadm.h
        $(TCC) -o mdadm.tcc $(SRCS)
index 0388b5e45db8bc7a2bd354d89ef58f96e22ed75b..c48f88e2f5c0e3c5285cf69e8226d15e651e7176 100644 (file)
--- a/config.c
+++ b/config.c
@@ -33,6 +33,8 @@
 #include       <glob.h>
 #include       <fnmatch.h>
 #include       <ctype.h>
+#include       <pwd.h>
+#include       <grp.h>
 
 /*
  * Read the config file
 char DefaultConfFile[] = CONFFILE;
 char DefaultAltConfFile[] = CONFFILE2;
 
-char *keywords[] = { "device", "array", "mailaddr", "program", "mailfrom", NULL };
+char *keywords[] = { "devices", "array",
+                    "mailaddr", "program", "mailfrom",
+                    "create",
+                    NULL };
 
 /*
  * match_keyword returns an index into the keywords array, or -1 for no match
@@ -240,6 +245,112 @@ mddev_dev_t load_partitions(void)
        return rv;
 }
 
+struct createinfo createinfo = {
+#ifdef DEBIAN
+       .gid = 6, /* disk */
+       .mode = 0660,
+#else
+       .mode = 0600,
+#endif
+};
+
+int parse_auto(char *str, char *msg)
+{
+       int autof;
+       if (str == NULL || *str == 0)
+               autof = -2;
+       else if (strcasecmp(str,"no")==0)
+               autof = -3;
+       else if (strcasecmp(str,"yes")==0)
+               autof = -2;
+       else if (strcasecmp(str,"md")==0)
+               autof = -1;
+       else {
+               /* There might be digits, and maybe a hypen, at the end */
+               char *e = str + strlen(str);
+               int num = 4;
+               int len;
+               while (e > str && isdigit(e[-1]))
+                       e--;
+               if (*e) {
+                       num = atoi(e);
+                       if (num <= 0) num = 1;
+               }
+               if (e > str && e[-1] == '-')
+                       e--;
+               len = e - str;
+               if ((len == 3 && strncasecmp(str,"mdp",3)==0) ||
+                   (len == 1 && strncasecmp(str,"p",1)==0) ||
+                   (len >= 4 && strncasecmp(str,"part",4)==0))
+                       autof = num;
+               else {
+                       fprintf(stderr, Name ": %s arg of \"%s\" unrecognised: use no,yes,md,mdp,part\n"
+                               "        optionally followed by a number.\n",
+                               msg, str);
+                       exit(2);
+               }
+       }
+       return autof;
+}
+static void createline(char *line)
+{
+       char *w;
+       char *ep;
+
+       for (w=dl_next(line); w!=line; w=dl_next(w)) {
+               if (strncasecmp(w, "auto=", 5) == 0)
+                       createinfo.autof = parse_auto(w+5, "auto=");
+               else if (strncasecmp(w, "owner=", 6) == 0) {
+                       if (w[6] == 0) {
+                               fprintf(stderr, Name ": missing owner name\n");
+                               continue;
+                       }
+                       createinfo.uid = strtoul(w+6, &ep, 10);
+                       if (*ep != 0) {
+#ifndef STATIC
+                               struct passwd *pw;
+                               /* must be a name */
+                               pw = getpwnam(w+6);
+                               if (pw)
+                                       createinfo.uid = pw->pw_uid;
+                               else
+#endif /* STATIC */
+                                       fprintf(stderr, Name ": CREATE user %s not found\n", w+6);
+                       }
+               } else if (strncasecmp(w, "group=", 6) == 0) {
+                       if (w[6] == 0) {
+                               fprintf(stderr, Name ": missing group name\n");
+                               continue;
+                       }
+                       createinfo.gid = strtoul(w+6, &ep, 10);
+                       if (*ep != 0) {
+#ifndef STATIC
+                               struct group *gr;
+                               /* must be a name */
+                               gr = getgrnam(w+6);
+                               if (gr)
+                                       createinfo.gid = gr->gr_gid;
+                               else
+#endif /* STATIC */
+                                       fprintf(stderr, Name ": CREATE group %s not found\n", w+6);
+                       }
+               } else if (strncasecmp(w, "mode=", 5) == 0) {
+                       if (w[5] == 0) {
+                               fprintf(stderr, Name ": missing CREATE mode\n");
+                               continue;
+                       }
+                       createinfo.mode = strtoul(w+5, &ep, 8);
+                       if (*ep != 0) {
+                               createinfo.mode = 0600;
+                               fprintf(stderr, Name ": unrecognised CREATE mode %s\n",
+                                       w+5);
+                       }
+               } else {
+                       fprintf(stderr, Name ": unrecognised word on CREATE line: %s\n",
+                               w);
+               }
+       }
+}
 
 void devline(char *line) 
 {
@@ -364,32 +475,7 @@ void arrayline(char *line)
                                fprintf(stderr, Name ": metadata format %s unknown, ignored.\n", w+9);
                } else if (strncasecmp(w, "auto=", 5) == 0 ) {
                        /* whether to create device special files as needed */
-                       if (strcasecmp(w+5, "no")==0)
-                               mis.autof = 0;
-                       else if (strcasecmp(w+5,"yes")==0 || strcasecmp(w+5,"md")==0)
-                               mis.autof = -1;
-                       else {
-                               /* There might be digits, and maybe a hyphen, at the end */
-                               char *e = w+5 + strlen(w+5);
-                               int num = 4;
-                               int len;
-                               while (e > w+5 && isdigit(e[-1]))
-                                       e--;
-                               if (*e) {
-                                       num = atoi(e);
-                                       if (num <= 0) num = 1;
-                               }
-                               if (e > w+5 && e[-1] == '-')
-                                       e--;
-                               len = e - (w+5);
-                               if ((len == 3 && strncasecmp(w+5,"mdp",3)==0) ||
-                                   (len == 1 && strncasecmp(w+5,"p",1)==0) ||
-                                   (len >= 4 && strncasecmp(w+5,"part",4)==0))
-                                       mis.autof = num;
-                               else 
-                                       fprintf(stderr, Name ": auto type of \"%s\" ignored for %s\n",
-                                               w+5, mis.devname?mis.devname:"unlabeled-array");
-                       }
+                       mis.autof = parse_auto(w+5, "auto type");
                } else {
                        fprintf(stderr, Name ": unrecognised word on ARRAY line: %s\n",
                                w);
@@ -513,6 +599,9 @@ void load_conffile(char *conffile)
                case 4: /* MAILFROM */
                        mailfromline(line);
                        break;
+               case 5: /* CREATE */
+                       createline(line);
+                       break;
                default:
                        fprintf(stderr, Name ": Unknown keyword %s\n", line);
                }
@@ -542,6 +631,11 @@ char *conf_get_program(char *conffile)
        return alert_program;
 }
 
+struct createinfo *conf_get_create_info(char *conffile)
+{
+       load_conffile(conffile);
+       return &createinfo;
+}
 
 mddev_ident_t conf_get_ident(char *conffile, char *dev)
 {
diff --git a/mdadm.c b/mdadm.c
index 7f109486a10d91c23c85f06b9c2d1fe5a1076711..119b7495f81b7a97284dbfcc2323e0ac6a26a8fa 100644 (file)
--- a/mdadm.c
+++ b/mdadm.c
@@ -75,7 +75,8 @@ int main(int argc, char *argv[])
        int force = 0;
        int test = 0;
        int assume_clean = 0;
-       int autof = 0; /* -2 means create device based on name:
+       int autof = 0; /* -3 means don't create anything,
+                       * -2 means create device based on name:
                        *    if it ends mdN, then non-partitioned array N
                        *    if it ends dN, then partitions array N
                        * -1 means create non-partitioned, choose N
@@ -482,39 +483,7 @@ int main(int argc, char *argv[])
                case O(CREATE,'a'):
                case O(BUILD,'a'):
                case O(ASSEMBLE,'a'): /* auto-creation of device node */
-                       if (optarg == NULL)
-                               autof = -2;
-                       else if (strcasecmp(optarg,"no")==0)
-                               autof = 0;
-                       else if (strcasecmp(optarg,"yes")==0)
-                               autof = -2;
-                       else if (strcasecmp(optarg,"md")==0)
-                               autof = -1;
-                       else {
-                               /* There might be digits, and maybe a hypen, at the end */
-                               char *e = optarg + strlen(optarg);
-                               int num = 4;
-                               int len;
-                               while (e > optarg && isdigit(e[-1]))
-                                       e--;
-                               if (*e) {
-                                       num = atoi(e);
-                                       if (num <= 0) num = 1;
-                               }
-                               if (e > optarg && e[-1] == '-')
-                                       e--;
-                               len = e - optarg;
-                               if ((len == 3 && strncasecmp(optarg,"mdp",3)==0) ||
-                                   (len == 1 && strncasecmp(optarg,"p",1)==0) ||
-                                   (len >= 4 && strncasecmp(optarg,"part",4)==0))
-                                       autof = num;
-                               else {
-                                       fprintf(stderr, Name ": --auto flag arg of \"%s\" unrecognised: use no,yes,md,mdp,part\n"
-                                               "        optionally followed by a number.\n",
-                                               optarg);
-                                       exit(2);
-                               }
-                       }
+                       autof = parse_auto(optarg, "--auto flag");
                        continue;
 
                case O(BUILD,'f'): /* force honouring '-n 1' */
index 56a5444c33aa5ba67e760320e826a5fbb62bdf61..b7d915e5f676b1d9b91c6f612181a95b47f6a681 100644 (file)
@@ -212,6 +212,41 @@ There should only be one
 .B program
 line and it should be give only one program.
 
+
+.TP
+.B CREATE
+The
+.B create
+line gives default values to be used when creating device entries for
+arrays.
+These include:
+
+.RS 4
+.TP
+.B owner=
+.TP
+.B group=
+These can give user/group ids or names to use instead of system
+defaults (root/wheel or root/disk).
+.TP
+.B mode=
+An octal file mode such as 0660 can be given to override the default
+of 0600.
+.TP
+.B auto=
+This corresponds to the
+.B --auto
+flag to mdadm.  Give
+.BR yes ,
+.BR md ,
+.BR mdp ,
+.B part
+- possibly followed by a number of partitions - to indicate how
+missing device entries should be created.
+
+.RE
+
+
 .SH EXAMPLE
 DEVICE /dev/sd[bcdjkl]1
 .br
@@ -254,7 +289,8 @@ ARRAY /dev/md/home UUID=9187a482:5dde19d9:eea3cc4a:d646ab8b
 MAILADDR root@mydomain.tld
 .br
 PROGRAM /usr/sbin/handle-mdadm-events
-
+.br
+CREATE group=system mode=0640 auto=part-8
 
 .SH SEE ALSO
 .BR mdadm (8),
diff --git a/mdadm.h b/mdadm.h
index cd5b185adfd2d0187f4e6374a2d50f02daeb3261..c53f9e91c44768b730ea1f70c131175b1f65b4c5 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -99,6 +99,13 @@ struct mdinfo {
        int                     new_level, delta_disks, new_layout, new_chunk;
 };
 
+struct createinfo {
+       int     uid;
+       int     gid;
+       int     autof;
+       int     mode;
+};
+
 #define Name "mdadm"
 
 enum mode {
@@ -366,9 +373,10 @@ extern int get_mdp_major(void);
 extern int dev_open(char *dev, int flags);
 extern int is_standard(char *dev, int *nump);
 
-
+extern int parse_auto(char *str, char *msg);
 extern mddev_ident_t conf_get_ident(char *conffile, char *dev);
 extern mddev_dev_t conf_get_devs(char *conffile);
+extern struct createinfo *conf_get_create_info(char *conffile);
 extern char *conf_get_mailaddr(char *conffile);
 extern char *conf_get_mailfrom(char *conffile);
 extern char *conf_get_program(char *conffile);
index 8c3eabb45d3148b99bcfb639bebb5b5367dd7af8..598c6a2ab8770decc113f080591425bb4026405e 100644 (file)
--- a/mdopen.c
+++ b/mdopen.c
@@ -82,7 +82,7 @@ void make_parts(char *dev, int cnt)
  * If it exists and is not an md device, is not the right type (partitioned or not),
  * or is currently in-use, we remove the device, but remember the owner and mode.
  * If it now doesn't exist, we find a new md array and create the device.
- * Default ownership is user=0, group=0 perm=0600
+ * Default ownership/mode comes from config file.
  */
 int open_mddev(char *dev, int autof)
 {
@@ -93,8 +93,12 @@ int open_mddev(char *dev, int autof)
        int must_remove = 0;
        struct mdstat_ent *mdlist;
        int num;
+       struct createinfo *ci = conf_get_create_info(NULL);
 
-       if (autof) {
+       if (autof == 0)
+               autof = ci->autof;
+
+       if (autof && autof != -3) {
                /* autof is set, so we need to check that the name is ok,
                 * and possibly create one if not
                 */
@@ -212,6 +216,11 @@ int open_mddev(char *dev, int autof)
                                        perror("chown");
                                if (chmod(dev, stb.st_mode & 07777))
                                        perror("chmod");
+                       } else {
+                               if (chown(dev, ci->uid, ci->gid))
+                                       perror("chown");
+                               if (chmod(dev, ci->mode))
+                                       perror("chmod");
                        }
                        stat(dev, &stb);
                        add_dev(dev, &stb, 0, NULL);