From 8b55b165f24e46d7e7528205bf89002a515478f1 Mon Sep 17 00:00:00 2001 From: okuji Date: Tue, 1 Jun 1999 14:59:50 +0000 Subject: [PATCH] improve the completion facility and fix some bugs. --- ChangeLog | 37 +++++++++++++ docs/.cvsignore | 3 ++ grub/asmstub.c | 71 +++++++++++++++++------- shared_src/char_io.c | 4 ++ shared_src/cmdline.c | 2 +- shared_src/disk_io.c | 114 +++++++++++++++++++++++++++++++++++++-- shared_src/fsys_ext2fs.c | 2 +- shared_src/fsys_fat.c | 2 +- shared_src/fsys_ffs.c | 2 +- shared_src/shared.h | 1 + shared_src/stage2.c | 2 +- 11 files changed, 212 insertions(+), 28 deletions(-) create mode 100644 docs/.cvsignore diff --git a/ChangeLog b/ChangeLog index a083d9fb4..73f537584 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,40 @@ +1999-06-01 OKUJI Yoshinori + + * grub/asmstub.c: Do not use I_AM_VERY_BRAVE any more. + (grub_stage2): Delete first_scsi_disk and add a variable + num_hd, which is used for counting how many drives are + detected. + Initialize the flags member of each element of disks to -1 + instead of 0, and check if it is equal to -1 instead of 0 when + close it. + (get_diskinfo): Treat -1 as non-caching state instead of 0. + +1999-06-01 OKUJI Yoshinori + + Reported from Klaus Reichl : + * docs/.cvsignore: New file. + * shared_src/disk_io.c (print_a_completion): New function + which saves what has been printed to UNIQUE_STRING and printf + it. + (unique) [!STAGE1_5]: New variable. + (unique_string): Likewise. + (print_completions): Use print_a_completion, and improve the + completion facility. + * shared_src/fsys_ext2fs.c (ext2fs_dir) [!STAGE1_5]: Use + print_a_completion instead of just printf. + * shared_src/fsys_ffs.c (ffs_dir) [!STAGE1_5]: Likewise. + * shared_src/fsys_fat.c (fat_dir) [!STAGE1_5]: Likewise. + * shared_src/shared.h (print_a_completion): Declared. + * shared_src/cmdline.c (enter_cmdline): Explicitly cast + int to pointer to char for grub_read. + * grub/asmstub.c (grub_stage2) [__linux__]: Don't use /dev/fd1. + Probe 4 IDE drives instead of 2. + (biosdisk) [__linux__]: Add a prototype for _llseek. + * shared_src/char_io.c (get_cmdline): Update LPOS and LLEN_OLD + when the functon print_completion modifies CMDLINE. + * shared_src/stage2.c (get_line_from_config): Fix LITERAL + handling. + 1999-05-25 OKUJI Yoshinori * grub/asmstub.c (grub_stage2): Fix a memory leak that FP is diff --git a/docs/.cvsignore b/docs/.cvsignore new file mode 100644 index 000000000..524b652fc --- /dev/null +++ b/docs/.cvsignore @@ -0,0 +1,3 @@ +*.info* +version.texi +stamp-vti diff --git a/grub/asmstub.c b/grub/asmstub.c index 844a05b28..e50fa4b71 100644 --- a/grub/asmstub.c +++ b/grub/asmstub.c @@ -38,6 +38,7 @@ int grub_stage2 (void); #include #include #include +#include #ifdef __linux__ # include /* ioctl */ @@ -78,8 +79,7 @@ grub_stage2 (void) /* These need to be static, because they survive our stack transitions. */ static int status = 0; static char *realstack; - int i; - int first_scsi_disk; + int i, num_hd = 0; char *scratch, *simstack; /* We need a nested function so that we get a clean stack frame, @@ -119,7 +119,7 @@ grub_stage2 (void) assert (disks); /* Initialize DISKS. */ for (i = 0; i < NUM_DISKS; i++) - disks[i].flags = 0; + disks[i].flags = -1; assert (device_map == 0); device_map = malloc (NUM_DISKS * sizeof (char *)); @@ -132,10 +132,14 @@ grub_stage2 (void) /* Floppies. */ device_map[0] = strdup ("/dev/fd0"); +#ifndef __linux__ + /* FIXME: leave linux out for now /dev/fd1 blocks for long time + if there is no second floppy ? */ device_map[1] = strdup ("/dev/fd1"); +#endif /* IDE disks. */ - for (i = 0; i < 2; i++) + for (i = 0; i < 4; i++) { char name[10]; FILE *fp; @@ -149,7 +153,30 @@ grub_stage2 (void) sprintf (name, "/dev/hd%c", unit); fp = fopen (name, "r"); if (! fp) - break; + { + switch (errno) + { +#ifdef ENOMEDIUM + case ENOMEDIUM: +#if 0 + /* At the moment, this finds only CDROMs, which can't be + read anyway, so leave it out. Code should be + reactivated if `removable disks' and CDROMs are + supported. */ + /* register it, it may be inserted. */ + device_map[num_hd++ + 0x80] = strdup (name); +#endif + break; +#endif /* ENOMEDIUM */ + default: + /* break case and leave */ + break; + } + /* continue: there may be more disks sitting sparse on the + controllers */ + continue; + } + /* Attempt to read the first sector. */ if (fread (buf, 1, 512, fp) != 512) { @@ -158,9 +185,8 @@ grub_stage2 (void) } fclose (fp); - device_map[i + 0x80] = strdup (name); + device_map[num_hd++ + 0x80] = strdup (name); } - first_scsi_disk = i + 0x80; /* The rest is SCSI disks. */ for (i = 0; i < 8; i++) @@ -173,7 +199,7 @@ grub_stage2 (void) #else sprintf (name, "/dev/sd%d", i); #endif - device_map[i + first_scsi_disk] = name; + device_map[num_hd++ + 0x80] = name; } /* Check some invariants. */ @@ -208,7 +234,7 @@ grub_stage2 (void) /* Close off the file descriptors we used. */ for (i = 0; i < NUM_DISKS; i ++) - if (disks[i].flags) + if (disks[i].flags != -1) close (disks[i].flags); /* Release memory. */ @@ -473,7 +499,7 @@ get_diskinfo (int drive, struct geometry *geometry) or my reputation would be ruined. --Gord */ /* See if we have a cached device. */ - if (! disks[drive].flags) + if (disks[drive].flags == -1) { /* The unpartitioned device name: /dev/XdX */ char *devname = device_map[drive]; @@ -484,18 +510,27 @@ get_diskinfo (int drive, struct geometry *geometry) /* Open read/write, or read-only if that failed. */ disks[drive].flags = open (devname, O_RDWR); - if (! disks[drive].flags) - disks[drive].flags = open (devname, O_RDONLY); + if (disks[drive].flags == -1) + { + if (errno == EACCES || errno == EROFS) + { + disks[drive].flags = open (devname, O_RDONLY); + if (disks[drive].flags == -1) + return -1; + } + else + return -1; + } /* Attempt to read the first sector. */ if (read (disks[drive].flags, buf, 512) != 512) { close (disks[drive].flags); - disks[drive].flags = 0; + disks[drive].flags = -1; return -1; } - if (disks[drive].flags) + if (disks[drive].flags != -1) { #ifdef __linux__ struct hd_geometry hdg; @@ -538,7 +573,7 @@ get_diskinfo (int drive, struct geometry *geometry) } } - if (! disks[drive].flags) + if (disks[drive].flags == -1) return -1; *geometry = disks[drive]; @@ -613,6 +648,7 @@ biosdisk (int subfunc, int drive, struct geometry *geometry, /* FIXME: only use this section if libc doesn't have large file support */ { loff_t offset, result; + static int _llseek (uint fd, ulong hi, ulong lo, loff_t *res, uint wh); _syscall5 (int, _llseek, uint, fd, ulong, hi, ulong, lo, loff_t *, res, uint, wh); @@ -633,15 +669,10 @@ biosdisk (int subfunc, int drive, struct geometry *geometry, if (nread (fd, buf, nsec * SECTOR_SIZE) != nsec * SECTOR_SIZE) return -1; break; - /* For now, I don't want to turn on this write code by default, - because a bug that I haven't known yet may destroy all disks - in the world. */ -#ifdef I_AM_VERY_BRAVE case BIOSDISK_WRITE: if (nwrite (fd, buf, nsec * SECTOR_SIZE) != nsec * SECTOR_SIZE) return -1; break; -#endif default: grub_printf ("unknown subfunc %d\n", subfunc); break; diff --git a/shared_src/char_io.c b/shared_src/char_io.c index 9805d120b..00658398d 100644 --- a/shared_src/char_io.c +++ b/shared_src/char_io.c @@ -276,6 +276,10 @@ get_cmdline (char *prompt, char *commands, char *cmdline, int maxlen, i = j + 1; /* print possible completions */ print_completions (cmdline + i); + /* if somebody in print_completions has added something, + account for that */ + while (cmdline[lpos]) + lpos++, llen_old++; } else if (commands) printf (commands); diff --git a/shared_src/cmdline.c b/shared_src/cmdline.c index 3da231fc9..461216b52 100644 --- a/shared_src/cmdline.c +++ b/shared_src/cmdline.c @@ -466,7 +466,7 @@ returnit: while ((*(str++) = *(ptr++)) != 0); /* do copy */ } - grub_read (RAW_ADDR (0x100000), -1); + grub_read ((char *) RAW_ADDR (0x100000), -1); buf_track = -1; diff --git a/shared_src/disk_io.c b/shared_src/disk_io.c index 8ccbfb272..a5cff39cb 100644 --- a/shared_src/disk_io.c +++ b/shared_src/disk_io.c @@ -574,6 +574,10 @@ open_partition (void) /* XX used for device completion in 'set_device' and 'print_completions' */ static int incomplete, disk_choice; +#ifndef STAGE1_5 +static int unique; +static char unique_string[128]; /* XXX Don't know yet */ +#endif static enum { PART_UNSPECIFIED = 0, @@ -595,12 +599,31 @@ set_device (char *device) current_drive = saved_drive; current_partition = 0xFFFFFF; + if (*device == '(' && !*(device + 1)) + /* user has given '(' only, let disk_choice handle what disks we have */ + return device + 1; + if (*device == '(' && *(++device)) { if (*device != ',' && *device != ')') { char ch = *device; + if (*device == 'f' || *device == 'h') + { + /* user has given '([fh]', check for resp. add 'd' and + let disk_choice handle what disks we have */ + if (!*(device + 1)) + { + device++; + *device++ = 'd'; + *device = '\0'; + return device; + } + else if (*(device + 1) == 'd' && !*(device + 2)) + return device + 2; + } + if ((*device == 'f' || *device == 'h') && (device += 2, (*(device - 1) != 'd'))) errnum = ERR_NUMBER_PARSING; @@ -879,6 +902,35 @@ print_fsys_type (void) #endif /* STAGE1_5 */ #ifndef STAGE1_5 +/* + * print_a_completion saves what has been printed to unique_string + * printf's with a leading ' '. + */ + +void +print_a_completion (char *filename) +{ + char *f = filename; + char *u = unique_string; + + if (! *u && unique == 0) + { + /* copy first string, this is unique. */ + while ((*u++ = *f++)) + ; + } + else + { + while (*u && (*u == *f)) + u++, f++; + /* mismatch, strip it. */ + *u = '\0'; + } + unique++; + + printf (" %s", filename); +} + /* * This lists the possible completions of a device string, filename, or * any sane combination of the two. @@ -889,6 +941,9 @@ print_completions (char *filename) { char *ptr = filename; + *unique_string = '\0'; + unique = 0; + if (*filename == '/' || (ptr = set_device (filename)) || incomplete) { errnum = 0; @@ -903,17 +958,45 @@ print_completions (char *filename) printf (" Possible disks are: "); - for (i = 0; i < 2; i++) + for (i = (ptr && (*(ptr-2) == 'h' && *(ptr-1) == 'd') ? 1 : 0); + i < (ptr && (*(ptr-2) == 'f' && *(ptr-1) == 'd') ? 1 : 2); + i++) { for (j = 0; j < 8; j++) { disk_no = (i * 0x80) + j; if ((disk_choice || disk_no == current_drive) && ! get_diskinfo (disk_no, &geom)) - printf (" %cd%d", (i ? 'h' : 'f'), j); + { + char dev_name[4]; + + dev_name[0] = (i ? 'h' : 'f'); + dev_name[1] = 'd'; + dev_name[2] = '0' + j; + dev_name[3] = '\0'; + print_a_completion (dev_name); + } } } + ptr = filename; + while (*ptr != '(') + ptr--; + ptr++; + { + char *u = unique_string; + while ((*ptr++ = *u++)) + ; + ptr--; + } + ptr--; + if ((*(ptr - 2) == 'h') && (*(ptr - 1) == 'd') + && ('0' <= *ptr && *ptr <= '8')) + *(ptr + 1) = ',', *(ptr + 2) = '\0'; + if ((*(ptr - 2) == 'f') && (*(ptr - 1) == 'd') + && ('0' <= *ptr && *ptr <= '8')) + *(ptr + 1) = ')', *(ptr + 2) = '\0'; + putchar ('\n'); } else @@ -927,7 +1010,18 @@ print_completions (char *filename) else { if (open_partition ()) - check_and_print_mount (); + { + check_and_print_mount (); + /* FIXME: Can talk about linux only, do we need + to know about syntax here? */ + ptr = filename; + while (*ptr) + ptr++; + if (*(ptr - 1) != ')') + *ptr++ = ')'; + *ptr++ = '/'; + *ptr = '\0'; + } } } } @@ -936,6 +1030,20 @@ print_completions (char *filename) /* filename completions */ printf (" Possible files are:"); dir (filename); + { + char *u = unique_string; + + if (*u) + { + while (*ptr++) + ; + while (*ptr != '/') + ptr--; + ptr++; + while ((*ptr++ = *u++)) + ; + } + } } else errnum = ERR_BAD_FILENAME; diff --git a/shared_src/fsys_ext2fs.c b/shared_src/fsys_ext2fs.c index 3b58d15eb..dadb4c158 100644 --- a/shared_src/fsys_ext2fs.c +++ b/shared_src/fsys_ext2fs.c @@ -757,7 +757,7 @@ ext2fs_dir (char *dirname) { if (print_possibilities > 0) print_possibilities = -print_possibilities; - printf (" %s", dp->name); + print_a_completion (dp->name); } # endif diff --git a/shared_src/fsys_fat.c b/shared_src/fsys_fat.c index 4567bb241..a50d30417 100644 --- a/shared_src/fsys_fat.c +++ b/shared_src/fsys_fat.c @@ -240,7 +240,7 @@ loop: { if (print_possibilities > 0) print_possibilities = -print_possibilities; - printf (" %s", filename); + print_a_completion (filename); } # endif /* STAGE1_5 */ } diff --git a/shared_src/fsys_ffs.c b/shared_src/fsys_ffs.c index aaa8e40c4..a45e1a1f9 100644 --- a/shared_src/fsys_ffs.c +++ b/shared_src/fsys_ffs.c @@ -252,7 +252,7 @@ loop: if (print_possibilities > 0) print_possibilities = -print_possibilities; - printf (" %s", dp->d_name); + print_a_completion (dp->d_name); } #endif /* STAGE1_5 */ } diff --git a/shared_src/shared.h b/shared_src/shared.h index 6aaddfed8..d08a30b02 100644 --- a/shared_src/shared.h +++ b/shared_src/shared.h @@ -512,6 +512,7 @@ int set_bootdev (int hdbias); void print_fsys_type (void); /* Display device and filename completions. */ +void print_a_completion (char *filename); void print_completions (char *filename); /* Copies the current partition data to the desired address. */ diff --git a/shared_src/stage2.c b/shared_src/stage2.c index 3eb1290b9..efe7258d7 100644 --- a/shared_src/stage2.c +++ b/shared_src/stage2.c @@ -470,7 +470,7 @@ get_line_from_config(char *cmdline, int maxlen) while (grub_read (&c, 1)) { /* translate characters first! */ - if (c == '\\') + if (c == '\\' && ! literal) { literal = 1; continue;