Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.sbin/sysinst Untangle disk enumeration a bit more.



details:   https://anonhg.NetBSD.org/src/rev/d6f2610b6760
branches:  trunk
changeset: 445673:d6f2610b6760
user:      martin <martin%NetBSD.org@localhost>
date:      Thu Nov 08 11:56:56 2018 +0000

description:
Untangle disk enumeration a bit more.

diffstat:

 usr.sbin/sysinst/disks.c |  276 ++++++++++++++++++++++++++--------------------
 1 files changed, 155 insertions(+), 121 deletions(-)

diffs (truncated from 335 to 300 lines):

diff -r ffb4784bd18f -r d6f2610b6760 usr.sbin/sysinst/disks.c
--- a/usr.sbin/sysinst/disks.c  Thu Nov 08 11:15:58 2018 +0000
+++ b/usr.sbin/sysinst/disks.c  Thu Nov 08 11:56:56 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: disks.c,v 1.20 2018/11/08 11:15:58 martin Exp $ */
+/*     $NetBSD: disks.c,v 1.21 2018/11/08 11:56:56 martin Exp $ */
 
 /*
  * Copyright 1997 Piermont Information Systems Inc.
@@ -110,6 +110,8 @@
 static void fixsb(const char *, const char *, char);
 static bool is_gpt(const char *);
 static int incoregpt(pm_devs_t *, partinfo *);
+static bool enumerate_disks(void *state,
+       bool (*func)(void *state, const char *dev));
 
 
 static bool tmpfs_on_var_shm(void);
@@ -351,46 +353,48 @@
                strcpy(dd->dd_descr, dd->dd_name);
 }
 
-/* disknames - contains device names without partition letters
- * cdrom_devices - contains devices including partition letters
- * returns the first entry in hw.disknames matching a cdrom_device, or
- * first entry on error or no match
+/*
+ * State for helper callback for get_default_cdrom
+ */
+struct default_cdrom_data {
+       char *device;
+       size_t max_len;
+       bool found;
+};
+
+/*
+ * Helper function for get_default_cdrom, gets passed a device
+ * name and a void pointer to default_cdrom_data.
+ */
+static bool
+get_default_cdrom_helper(void *state, const char *dev)
+{
+       struct default_cdrom_data *data = state;
+
+       strlcpy(data->device, dev, data->max_len);
+       data->found = true;
+
+       return false;   /* one is enough, stop iteration */
+}
+
+/*
+ * Set the argument to the name of the first CD devices actually
+ * available, leave it unmodified otherwise.
+ * Return true if a device has been found.
  */
 bool
 get_default_cdrom(char *cd, size_t max_len)
 {
-       static const char *cdrom_devices[] = { CD_NAMES, 0 };
-       static const char mib_name[] = "hw.disknames";
-       size_t len;
-       char *disknames;
-       char *last;
-       char *name;
-       const char **arg;
-       const char *cd_dev;
-
-       /* On error just use first entry in cdrom_devices */
-       if (sysctlbyname(mib_name, NULL, &len, NULL, 0) == -1)
-               return cdrom_devices[0];
-       if ((disknames = malloc(len + 2)) == 0) /* skip on malloc fail */
-               return cdrom_devices[0];
+       struct default_cdrom_data state;
 
-       (void)sysctlbyname(mib_name, disknames, &len, NULL, 0);
-       for ((name = strtok_r(disknames, " ", &last)); name;
-           (name = strtok_r(NULL, " ", &last))) {
-               for (arg = cdrom_devices; *arg; ++arg) {
-                       cd_dev = *arg;
-                       /* skip unit and partition */
-                       if (strncmp(cd_dev, name, strlen(cd_dev) - 2) != 0)
-                               continue;
-                       if (name != disknames)
-                               strcpy(disknames, name);
-                       strcat(disknames, "a");
-                       /* XXX: leaks, but so what? */
-                       return disknames;
-               }
-       }
-       free(disknames);
-       return cdrom_devices[0];
+       state.device = cd;
+       state.max_len = max_len;
+       state.found = false;
+
+       if (enumerate_disks(&state, get_default_cdrom_helper))
+               return state.found;
+
+       return false;
 }
 
 static void
@@ -520,109 +524,139 @@
 
 /*
  * Multi-purpose helper function:
- * iterate all known disks, either
- *  - skip all CD devices
- *  - recognize the first available CD device and set its name
- * When doing non-CDs, optionally skip non-partionable devices
- * (i.e. wedges).
+ * iterate all known disks, invoke a callback for each.
+ * Stop iteration when the callback returns false.
+ * Return true when iteration actually happend, false on error.
  */
-static int
-get_disks(struct disk_desc *dd, bool with_non_partitionable,
-       char *cd_dev, size_t max_len)
+static bool
+enumerate_disks(void *state, bool (*func)(void *state, const char *dev))
 {
        static const int mib[] = { CTL_HW, HW_DISKNAMES };
        static const unsigned int miblen = __arraycount(mib);
        const char *xd;
-       struct disklabel l;
-       int numdisks;
+       char *disk_names;
        size_t len;
-       char *disk_names;
-
-       /* initialize */
-       numdisks = 0;
 
        if (sysctl(mib, miblen, NULL, &len, NULL, 0) == -1)
-               return 0;
+               return false;
+
        disk_names = malloc(len);
        if (disk_names == NULL)
-               return 0;
+               return false;
 
        if (sysctl(mib, miblen, disk_names, &len, NULL, 0) == -1) {
                free(disk_names);
-               return 0;
+               return false;
        }
 
        for (xd = strtok(disk_names, " "); xd != NULL; xd = strtok(NULL, " ")) {
-               /* is this a CD device? */
-               if (is_cdrom_device(xd)) {
-                       if (cd_dev && max_len) {
-                               /* return first found CD device name */
-                               strlcpy(cd_dev, xd, max_len);
-                               return 1;
-                       } else {
-                               /* skip this device */
-                               continue;
-                       }
-               }
-
-               strlcpy(dd->dd_name, xd, sizeof dd->dd_name - 2);
-               dd->dd_no_mbr = false;
-               dd->dd_no_part = false;
-
-               if (strncmp(xd, "dk", 2) == 0) {
-                       char *endp;
-                       int e;
-
-                       /* if this device is dkNNNN, no partitioning is possible */
-                       strtou(xd+2, &endp, 10, 0, INT_MAX, &e);
-                       if (endp && *endp == 0 && e == 0)
-                               dd->dd_no_part = true;
-               }
-               if (dd->dd_no_part && !with_non_partitionable)
-                       continue;
-
-               if (!get_geom(dd->dd_name, &l)) {
-                       if (errno == ENOENT)
-                               break;
-                       if (errno != ENOTTY || !dd->dd_no_part)
-                               /*
-                                * Allow plain partitions,
-                                * like already existing wedges
-                                * (like dk0) if marked as
-                                * non-partitioning device.
-                                * For all other cases, continue
-                                * with the next disk.
-                                */
-                               continue;
-                       if (!is_ffs_wedge(dd->dd_name))
-                               continue;
-               }
-
-               /*
-                * Exclude a disk mounted as root partition,
-                * in case of install-image on a USB memstick.
-                */
-               if (is_active_rootpart(dd->dd_name, 0))
-                       continue;
-
-               if (!dd->dd_no_part) {
-                       dd->dd_cyl = l.d_ncylinders;
-                       dd->dd_head = l.d_ntracks;
-                       dd->dd_sec = l.d_nsectors;
-                       dd->dd_secsize = l.d_secsize;
-                       dd->dd_totsec = l.d_secperunit;
-               }
-               if (dd->dd_no_part)
-                       get_wedge_descr(dd);
-               else
-                       get_descr(dd);
-               dd++;
-               numdisks++;
-               if (numdisks == MAX_DISKS)
+               if (!(*func)(state, xd))
                        break;
        }
        free(disk_names);
-       return numdisks;
+
+       return true;
+}
+
+/*
+ * Helper state for get_disks
+ */
+struct get_disks_state {
+       int numdisks;
+       struct disk_desc *dd;
+       bool with_non_partitionable;
+};
+
+/*
+ * Helper function for get_disks enumartion
+ */
+static bool
+get_disks_helper(void *arg, const char *dev)
+{
+       struct get_disks_state *state = arg;
+       struct disklabel l;
+
+       /* is this a CD device? */
+       if (is_cdrom_device(dev))
+               return true;
+
+       strlcpy(state->dd->dd_name, dev, sizeof state->dd->dd_name - 2);
+       state->dd->dd_no_mbr = false;
+       state->dd->dd_no_part = false;
+
+       if (strncmp(dev, "dk", 2) == 0) {
+               char *endp;
+               int e;
+
+               /* if this device is dkNNNN, no partitioning is possible */
+               strtou(dev+2, &endp, 10, 0, INT_MAX, &e);
+               if (endp && *endp == 0 && e == 0)
+                       state->dd->dd_no_part = true;
+       }
+       if (state->dd->dd_no_part && !state->with_non_partitionable)
+               return true;
+
+       if (!get_geom(state->dd->dd_name, &l)) {
+               if (errno == ENOENT)
+                       return true;
+               if (errno != ENOTTY || !state->dd->dd_no_part)
+                       /*
+                        * Allow plain partitions,
+                        * like already existing wedges
+                        * (like dk0) if marked as
+                        * non-partitioning device.
+                        * For all other cases, continue
+                        * with the next disk.
+                        */
+                       return true;
+               if (!is_ffs_wedge(state->dd->dd_name))
+                       return true;
+       }
+
+       /*
+        * Exclude a disk mounted as root partition,
+        * in case of install-image on a USB memstick.
+        */
+       if (is_active_rootpart(state->dd->dd_name, 0))
+               return true;
+
+       if (!state->dd->dd_no_part) {
+               state->dd->dd_cyl = l.d_ncylinders;
+               state->dd->dd_head = l.d_ntracks;
+               state->dd->dd_sec = l.d_nsectors;
+               state->dd->dd_secsize = l.d_secsize;
+               state->dd->dd_totsec = l.d_secperunit;
+       }
+       if (state->dd->dd_no_part)
+               get_wedge_descr(state->dd);
+       else
+               get_descr(state->dd);
+       state->dd++;
+       state->numdisks++;
+       if (state->numdisks == MAX_DISKS)



Home | Main Index | Thread Index | Old Index