+ /* check if one of the comma separated patterns in devices
+ * matches devname
+ */
+
+ while (devices && *devices) {
+ char patn[1024];
+ char *p = devices;
+ devices = strchr(devices, ',');
+ if (!devices)
+ devices = p + strlen(p);
+ if (devices-p < 1024) {
+ strncpy(patn, p, devices-p);
+ patn[devices-p] = 0;
+ if (fnmatch(patn, devname, FNM_PATHNAME)==0)
+ return 1;
+ }
+ if (*devices == ',')
+ devices++;
+ }
+ return 0;
+}
+
+int devname_matches(char *name, char *match)
+{
+ /* See if the given array name matches the
+ * given match from config file.
+ *
+ * First strip and /dev/md/ or /dev/, then
+ * see if there might be a numeric match of
+ * mdNN with NN
+ * then just strcmp
+ */
+ if (strncmp(name, "/dev/md/", 8) == 0)
+ name += 8;
+ else if (strncmp(name, "/dev/", 5) == 0)
+ name += 5;
+
+ if (strncmp(match, "/dev/md/", 8) == 0)
+ match += 8;
+ else if (strncmp(match, "/dev/", 5) == 0)
+ match += 5;
+
+
+ if (strncmp(name, "md", 2) == 0 &&
+ isdigit(name[2]))
+ name += 2;
+ if (strncmp(match, "md", 2) == 0 &&
+ isdigit(match[2]))
+ match += 2;
+
+ return (strcmp(name, match) == 0);
+}
+
+int conf_name_is_free(char *name)
+{
+ /* Check if this name is already take by an ARRAY entry in
+ * the config file.
+ * It can be taken either by a match on devname, name, or
+ * even super-minor.
+ */
+ struct mddev_ident *dev;
+
+ load_conffile();
+ for (dev = mddevlist; dev; dev = dev->next) {
+ char nbuf[100];
+ if (dev->devname && devname_matches(name, dev->devname))
+ return 0;
+ if (dev->name[0] && devname_matches(name, dev->name))
+ return 0;
+ sprintf(nbuf, "%d", dev->super_minor);
+ if (dev->super_minor != UnSet &&
+ devname_matches(name, nbuf))
+ return 0;
+ }
+ return 1;
+}
+
+struct mddev_ident *conf_match(struct supertype *st,
+ struct mdinfo *info,
+ char *devname,
+ int verbose, int *rvp)
+{
+ struct mddev_ident *array_list, *match;
+ array_list = conf_get_ident(NULL);
+ match = NULL;
+ for (; array_list; array_list = array_list->next) {
+ if (array_list->uuid_set &&
+ same_uuid(array_list->uuid, info->uuid, st->ss->swapuuid)
+ == 0) {
+ if (verbose >= 2 && array_list->devname)
+ pr_err("UUID differs from %s.\n",
+ array_list->devname);
+ continue;
+ }
+ if (array_list->name[0] &&
+ strcasecmp(array_list->name, info->name) != 0) {
+ if (verbose >= 2 && array_list->devname)
+ pr_err("Name differs from %s.\n",
+ array_list->devname);
+ continue;
+ }
+ if (array_list->devices && devname &&
+ !match_oneof(array_list->devices, devname)) {
+ if (verbose >= 2 && array_list->devname)
+ pr_err("Not a listed device for %s.\n",
+ array_list->devname);
+ continue;
+ }
+ if (array_list->super_minor != UnSet &&
+ array_list->super_minor != info->array.md_minor) {
+ if (verbose >= 2 && array_list->devname)
+ pr_err("Different super-minor to %s.\n",
+ array_list->devname);
+ continue;
+ }
+ if (!array_list->uuid_set &&
+ !array_list->name[0] &&
+ !array_list->devices &&
+ array_list->super_minor == UnSet) {
+ if (verbose >= 2 && array_list->devname)
+ pr_err("%s doesn't have any identifying"
+ " information.\n",
+ array_list->devname);
+ continue;
+ }
+ /* FIXME, should I check raid_disks and level too?? */
+
+ if (match) {
+ if (verbose >= 0) {
+ if (match->devname && array_list->devname)
+ pr_err("we match both %s and %s - "
+ "cannot decide which to use.\n",
+ match->devname,
+ array_list->devname);
+ else
+ pr_err("multiple lines in mdadm.conf"
+ " match\n");
+ }
+ if (rvp)
+ *rvp = 2;
+ match = NULL;
+ break;
+ }
+ match = array_list;
+ }
+ return match;
+}
+
+int conf_verify_devnames(struct mddev_ident *array_list)
+{
+ struct mddev_ident *a1, *a2;
+
+ for (a1 = array_list; a1; a1 = a1->next) {
+ if (!a1->devname)
+ continue;
+ if (strcmp(a1->devname, "<ignore>") == 0)
+ continue;
+ for (a2 = a1->next; a2; a2 = a2->next) {
+ if (!a2->devname)
+ continue;
+ if (strcmp(a1->devname, a2->devname) != 0)
+ continue;
+
+ if (a1->uuid_set && a2->uuid_set) {
+ char nbuf[64];
+ __fname_from_uuid(a1->uuid, 0, nbuf, ':');
+ pr_err("Devices %s and ",
+ nbuf);
+ __fname_from_uuid(a2->uuid, 0, nbuf, ':');
+ fprintf(stderr,
+ "%s have the same name: %s\n",
+ nbuf, a1->devname);
+ } else
+ pr_err("Device %s given twice"
+ " in config file\n", a1->devname);