--- Begin Message ---
Hi,
Hope this is the right way to do this ... submitted for your approval:
This patch adds /dev/ida/* and /dev/rd/* devices to fdisk_reread(),
and modifies the way device name patterns are encoded and expanded,
allowing a more reasonable representation for the ida and rd devices.
I have harness-tested the new code, but am unable to fully test it
in situ. I don't *think* there will be any problems ... would someone
please try it out on suitably-equipped systems?
I intend to improve the CD-ROM detection and will soon submit another
patch for that.
Regards,
Mark.
--- fdisk.c-1.29 Wed Dec 8 23:02:14 1999
+++ fdisk.c Wed Dec 8 23:29:19 1999
@@ -1,3 +1,4 @@
+#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
@@ -876,73 +877,126 @@
}
}
-static struct trylist {
- char *dev_pattern;
- char start, end;
-} trylist[] = {
- { "/dev/hd", 'a', 'h' },
- { "/dev/sd", 'a', 'h' },
-#if #cpu (i386)
- { "/dev/ed", 'a', 'd' },
-#endif
-#if #cpu (m68k)
- { "/dev/ad", 'a', 'h' },
-#endif
-/*
- * #ifdef DEBUG
- * { "/dev/loop", '0', '7' },
- * #endif
- */
-};
static int timed_out;
-static void alarmed(int signo)
+static void alarmed(int signo) { timed_out = 1; }
+
+
+/* is_disk: return true is device is a disk drive */
+static int is_disk(char *device, int fd)
{
- timed_out = 1;
+ struct cdrom_volctrl cdvol;
+
+ /** TODO *****************************************************************/
+ /* Erik thinks the CD-ROM test is inadequate. I'm inclined to agree. */
+ /* We could instead consult /proc/ide and /proc/scsi, which will allow */
+ /* us to eliminate IDE CD-ROMs (and CD-Rs) and non-random-access SCSI */
+ /* devices. See debian-boot list for discussion. */
+ /* I'm not sure how to check for such devices on dac960 or smart2. */
+ /* ***********************************************************************/
+
+ /* supposedly anything failing CDROMVOLREAD for the right reasons is ok */
+ return ioctl(fd, CDROMVOLREAD, &cdvol) && (errno == EINVAL ||
+ errno == EPERM ||
+ errno == EIO ||
+ errno == EBADRQC);
}
-void
-fdisk_reread(void)
+
+/* try_device: check specific device by name, add to disk/part lists if ok */
+static void try_device(char *device)
{
- struct trylist *p;
- struct cdrom_volctrl cdvol;
- int i, fd;
- char letter, device[12], *q;
- unsigned size;
-
- fdisk_init();
-
- for( p = trylist, i = 0; i < SIZE(trylist); ++p, ++i ) {
- strcpy( device, p->dev_pattern );
- q = device+strlen(device);
- q[1] = 0;
- for( letter = p->start; letter <= p->end; ++letter ) {
- *q = letter;
- signal( SIGALRM, alarmed );
- timed_out = 0;
- alarm( 30 );
- if ((fd = open( device, O_RDONLY )) >= 0 && !timed_out) {
- alarm( 0 );
- if (ioctl(fd, CDROMVOLREAD, &cdvol )!= 0) {
- /* if returns EINVAL or EPERM or EIO, this is not a CD-ROM drive */
- if ((errno==EINVAL)||(errno==EPERM)||(errno==EIO)) {
- if (ioctl(fd, BLKGETSIZE, &size))
- size = 0; /* don't complain, size not really
- used yet */
- size >>= 1; /* convert from 512-byte sectors to kB */
- fdisk_add_disk( device, size );
-
- parse_partition( device, fd );
- }
- }
- close( fd );
- }
- else {
- /* else: don't complain, ignore open errors */
- alarm( 0 );
+ int fd;
+
+ signal(SIGALRM, alarmed);
+ timed_out = 0;
+ alarm(30);
+ fd = open(device, O_RDONLY);
+ alarm(0);
+
+ if (fd >= 0) {
+ if (is_disk(device, fd)) {
+ unsigned int size;
+ if (ioctl(fd, BLKGETSIZE, &size))
+ size = 0; /* don't complain, size not really used yet */
+ size >>= 1; /* convert from 512-byte sectors to kB */
+ fdisk_add_disk(device, size);
+ parse_partition(device, fd);
+ }
+ close(fd);
+ }
+}
+
+
+/* walk - recursively walk pattern string, calling fn for every expansion */
+static void walk(char *pattern, char *expansion, char *p, void (*fn)(char *))
+{
+ while (*pattern) {
+ if (*pattern == '{') {
+ /* inside {..} can be either a character range or a number range */
+ pattern++;
+ if (isdigit(*pattern)) {
+ /* a digit may only be a (decimal) number range */
+ unsigned int min, max, pos, i;
+ char term;
+ int rc = sscanf(pattern, "%u-%u%c%n", &min, &max, &term, &pos);
+ assert(rc >= 3 && term == '}' && min <= max);
+ /* walk remainder of pattern for all possible values in range */
+ for (i = min; i <= max; i++)
+ walk(pattern + pos, expansion, p + sprintf(p, "%u", i), fn);
+ } else {
+ /* a non-digit must be a character range */
+ char min, max, term;
+ int rc = sscanf(pattern, "%c-%c%c", &min, &max, &term);
+ assert(rc == 3 && term == '}' && min <= max);
+ /* walk remainder of pattern for all possible chars in range */
+ for (*p = min; *p <= max; (*p)++)
+ walk(pattern + 4, expansion, p + 1, fn);
}
+ return;
}
+ *p++ = *pattern++;
+ }
+ /* reached end of pattern, so terminate expansion string and call fn() */
+ *p++ = '\0';
+ (*fn)(expansion);
+}
+
+
+/* fdisk_reread: scan for disk devices and build up disk and partition lists */
+void fdisk_reread(void)
+{
+ static char *patterns[] = {
+ "/dev/sd{a-h}",
+ "/dev/hd{a-h}",
+ "/dev/ida/c{0-7}d{0-15}",
+ "/dev/rd/c{0-7}d{0-31}",
+#if #cpu (i386)
+ "/dev/ed{a-d}",
+#elif #cpu (m68k)
+ "/dev/ad{a-h}",
+#endif
+/*
+ * #ifdef DEBUG
+ * "/dev/loop{0-7}",
+ * #endif
+ */
+ NULL
+ };
+ char **p;
+
+ fdisk_init();
+
+ for (p = patterns; *p; p++) {
+ char expansion[30]; /* storage for pattern expansions */
+
+ /* a pattern never expands to anything large than itself, so we can */
+ /* use the pattern length to make sure buffer is always big enough */
+ assert(strlen(*p) < sizeof expansion);
+
+ /* call try_device(expansion) for each expansion of current pattern */
+ walk(*p, expansion, expansion, try_device);
}
mounted_reread();
--- End Message ---