2008-05-30 Robert Millan <rmh@aybabtu.com>

* util/biosdisk.c (map): Redefine structure to hold information
        about GRUB drive name.
        (get_drive): Reimplement without assuming (and verifiing) BIOS-like
        drive names.
        (call_hook): Remove.
        (grub_util_biosdisk_iterate): Access drive names via `.drive' struct
        member.  Assume drive has partitions.
        (grub_util_biosdisk_open): Access device names via `.device' struct
        member.
        (open_device): Likewise.
        (find_drive): Likewise.
        (read_device_map): Adjust map[] usage to match the new struct
        definition.  Don't check for duplicates (still possible, but not cheap
        anymore).
        (grub_util_biosdisk_fini): Free malloced buffers referenced by map[].
        (make_device_name): Remove assumption of BIOS-like drive names.
This commit is contained in:
robertmh 2008-05-30 10:50:00 +00:00
parent bbb64db0d3
commit 01b73ec8eb
2 changed files with 73 additions and 59 deletions

View file

@ -1,3 +1,22 @@
2008-05-30 Robert Millan <rmh@aybabtu.com>
* util/biosdisk.c (map): Redefine structure to hold information
about GRUB drive name.
(get_drive): Reimplement without assuming (and verifiing) BIOS-like
drive names.
(call_hook): Remove.
(grub_util_biosdisk_iterate): Access drive names via `.drive' struct
member. Assume drive has partitions.
(grub_util_biosdisk_open): Access device names via `.device' struct
member.
(open_device): Likewise.
(find_drive): Likewise.
(read_device_map): Adjust map[] usage to match the new struct
definition. Don't check for duplicates (still possible, but not cheap
anymore).
(grub_util_biosdisk_fini): Free malloced buffers referenced by map[].
(make_device_name): Remove assumption of BIOS-like drive names.
2008-05-30 Pavel Roskin <proski@gnu.org> 2008-05-30 Pavel Roskin <proski@gnu.org>
* conf/i386-efi.rmk (normal/execute.c_DEPENDENCIES): Remove, as * conf/i386-efi.rmk (normal/execute.c_DEPENDENCIES): Remove, as

View file

@ -85,7 +85,11 @@ struct hd_geometry
# define FLOPPY_MAJOR 2 # define FLOPPY_MAJOR 2
#endif #endif
static char *map[256]; struct
{
char *drive;
char *device;
} map[256];
#ifdef __linux__ #ifdef __linux__
/* Check if we have devfs support. */ /* Check if we have devfs support. */
@ -108,45 +112,31 @@ have_devfs (void)
static int static int
get_drive (const char *name) get_drive (const char *name)
{ {
unsigned long drive; unsigned int i;
char *p;
if ((name[0] != 'f' && name[0] != 'h') || name[1] != 'd')
goto fail;
drive = strtoul (name + 2, &p, 10); if (name)
if (p == name + 2) {
goto fail; for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
if (! strcmp (map[i].drive, name))
return i;
}
else
{
for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
if (! map[i].drive)
return i;
}
if (name[0] == 'h')
drive += 0x80;
if (drive > sizeof (map) / sizeof (map[0]))
goto fail;
return (int) drive;
fail:
grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a biosdisk");
return -1; return -1;
} }
static int
call_hook (int (*hook) (const char *name), int drive)
{
char name[10];
sprintf (name, (drive & 0x80) ? "hd%d" : "fd%d", drive & (~0x80));
return hook (name);
}
static int static int
grub_util_biosdisk_iterate (int (*hook) (const char *name)) grub_util_biosdisk_iterate (int (*hook) (const char *name))
{ {
unsigned i; unsigned i;
for (i = 0; i < sizeof (map) / sizeof (map[0]); i++) for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
if (map[i] && call_hook (hook, i)) if (map[i].drive && hook (map[i].drive))
return 1; return 1;
return 0; return 0;
@ -160,13 +150,10 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
drive = get_drive (name); drive = get_drive (name);
if (drive < 0) if (drive < 0)
return grub_errno;
if (! map[drive])
return grub_error (GRUB_ERR_BAD_DEVICE, return grub_error (GRUB_ERR_BAD_DEVICE,
"no mapping exists for `%s'", name); "no mapping exists for `%s'", name);
disk->has_partitions = (drive & 0x80); disk->has_partitions = 1;
disk->id = drive; disk->id = drive;
/* Get the size. */ /* Get the size. */
@ -175,9 +162,9 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
unsigned long long nr; unsigned long long nr;
int fd; int fd;
fd = open (map[drive], O_RDONLY); fd = open (map[drive].device, O_RDONLY);
if (fd == -1) if (fd == -1)
return grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s'", map[drive]); return grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s'", map[drive].device);
if (fstat (fd, &st) < 0 || ! S_ISBLK (st.st_mode)) if (fstat (fd, &st) < 0 || ! S_ISBLK (st.st_mode))
{ {
@ -207,8 +194,8 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
#elif !defined (__GNU__) #elif !defined (__GNU__)
# warning "No special routine to get the size of a block device is implemented for your OS. This is not possibly fatal." # warning "No special routine to get the size of a block device is implemented for your OS. This is not possibly fatal."
#endif #endif
if (stat (map[drive], &st) < 0) if (stat (map[drive].device, &st) < 0)
return grub_error (GRUB_ERR_BAD_DEVICE, "cannot stat `%s'", map[drive]); return grub_error (GRUB_ERR_BAD_DEVICE, "cannot stat `%s'", map[drive].device);
disk->total_sectors = st.st_size >> GRUB_DISK_SECTOR_BITS; disk->total_sectors = st.st_size >> GRUB_DISK_SECTOR_BITS;
@ -325,8 +312,8 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
int is_partition = 0; int is_partition = 0;
char dev[PATH_MAX]; char dev[PATH_MAX];
strcpy (dev, map[disk->id]); strcpy (dev, map[disk->id].device);
if (disk->partition && strncmp (map[disk->id], "/dev/", 5) == 0) if (disk->partition && strncmp (map[disk->id].device, "/dev/", 5) == 0)
is_partition = linux_find_partition (dev, disk->partition->start); is_partition = linux_find_partition (dev, disk->partition->start);
/* Open the partition. */ /* Open the partition. */
@ -345,10 +332,10 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
sector -= disk->partition->start; sector -= disk->partition->start;
} }
#else /* ! __linux__ */ #else /* ! __linux__ */
fd = open (map[disk->id], flags); fd = open (map[disk->id].device, flags);
if (fd < 0) if (fd < 0)
{ {
grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s'", map[disk->id]); grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s'", map[disk->id].device);
return -1; return -1;
} }
#endif /* ! __linux__ */ #endif /* ! __linux__ */
@ -366,7 +353,7 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
offset = (loff_t) sector << GRUB_DISK_SECTOR_BITS; offset = (loff_t) sector << GRUB_DISK_SECTOR_BITS;
if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET)) if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
{ {
grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id]); grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id].device);
close (fd); close (fd);
return -1; return -1;
} }
@ -377,7 +364,7 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
if (lseek (fd, offset, SEEK_SET) != offset) if (lseek (fd, offset, SEEK_SET) != offset)
{ {
grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id]); grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id].device);
close (fd); close (fd);
return -1; return -1;
} }
@ -458,7 +445,7 @@ grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
parts. -jochen */ parts. -jochen */
if (nread (fd, buf, GRUB_DISK_SECTOR_SIZE) != GRUB_DISK_SECTOR_SIZE) if (nread (fd, buf, GRUB_DISK_SECTOR_SIZE) != GRUB_DISK_SECTOR_SIZE)
{ {
grub_error (GRUB_ERR_READ_ERROR, "cannot read `%s'", map[disk->id]); grub_error (GRUB_ERR_READ_ERROR, "cannot read `%s'", map[disk->id].device);
close (fd); close (fd);
return grub_errno; return grub_errno;
} }
@ -470,7 +457,7 @@ grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
if (nread (fd, buf, size << GRUB_DISK_SECTOR_BITS) if (nread (fd, buf, size << GRUB_DISK_SECTOR_BITS)
!= (ssize_t) (size << GRUB_DISK_SECTOR_BITS)) != (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", map[disk->id]); grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", map[disk->id].device);
close (fd); close (fd);
return grub_errno; return grub_errno;
@ -488,7 +475,7 @@ grub_util_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
if (nwrite (fd, buf, size << GRUB_DISK_SECTOR_BITS) if (nwrite (fd, buf, size << GRUB_DISK_SECTOR_BITS)
!= (ssize_t) (size << GRUB_DISK_SECTOR_BITS)) != (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
grub_error (GRUB_ERR_WRITE_ERROR, "cannot write to `%s'", map[disk->id]); grub_error (GRUB_ERR_WRITE_ERROR, "cannot write to `%s'", map[disk->id].device);
close (fd); close (fd);
return grub_errno; return grub_errno;
@ -544,14 +531,20 @@ read_device_map (const char *dev_map)
show_error ("No open parenthesis found"); show_error ("No open parenthesis found");
p++; p++;
drive = get_drive (p); /* Find a free slot. */
if (drive < 0 || drive >= (int) (sizeof (map) / sizeof (map[0]))) drive = get_drive (NULL);
show_error ("Bad device name"); if (drive < 0)
show_error ("Map table size exceeded");
e = p;
p = strchr (p, ')'); p = strchr (p, ')');
if (! p) if (! p)
show_error ("No close parenthesis found"); show_error ("No close parenthesis found");
map[drive].drive = xmalloc (p - e + sizeof ('\0'));
strncpy (map[drive].drive, e, p - e + sizeof ('\0'));
map[drive].drive[p - e] = '\0';
p++; p++;
/* Skip leading spaces. */ /* Skip leading spaces. */
while (*p && isspace (*p)) while (*p && isspace (*p))
@ -566,10 +559,6 @@ read_device_map (const char *dev_map)
e++; e++;
*e = '\0'; *e = '\0';
/* Multiple entries for a given drive is not allowed. */
if (map[drive])
show_error ("Duplicated entry found");
if (stat (p, &st) == -1) if (stat (p, &st) == -1)
{ {
grub_util_info ("Cannot stat `%s', skipping", p); grub_util_info ("Cannot stat `%s', skipping", p);
@ -580,11 +569,11 @@ read_device_map (const char *dev_map)
/* On Linux, the devfs uses symbolic links horribly, and that /* On Linux, the devfs uses symbolic links horribly, and that
confuses the interface very much, so use realpath to expand confuses the interface very much, so use realpath to expand
symbolic links. */ symbolic links. */
map[drive] = xmalloc (PATH_MAX); map[drive].device = xmalloc (PATH_MAX);
if (! realpath (p, map[drive])) if (! realpath (p, map[drive].device))
grub_util_error ("Cannot get the real path of `%s'", p); grub_util_error ("Cannot get the real path of `%s'", p);
#else #else
map[drive] = xstrdup (p); map[drive].device = xstrdup (p);
#endif #endif
} }
@ -604,7 +593,13 @@ grub_util_biosdisk_fini (void)
unsigned i; unsigned i;
for (i = 0; i < sizeof (map) / sizeof (map[0]); i++) for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
free (map[i]); {
if (map[i].drive)
free (map[i].drive);
if (map[i].device)
free (map[i].device);
map[i].drive = map[i].device = NULL;
}
grub_disk_dev_unregister (&grub_util_biosdisk_dev); grub_disk_dev_unregister (&grub_util_biosdisk_dev);
} }
@ -615,7 +610,7 @@ make_device_name (int drive, int dos_part, int bsd_part)
char *p; char *p;
p = xmalloc (30); p = xmalloc (30);
sprintf (p, (drive & 0x80) ? "hd%d" : "fd%d", drive & ~0x80); sprintf (p, "%s", map[drive].drive);
if (dos_part >= 0) if (dos_part >= 0)
sprintf (p + strlen (p), ",%d", dos_part + 1); sprintf (p + strlen (p), ",%d", dos_part + 1);
@ -746,7 +741,7 @@ find_drive (const char *os_dev)
return -1; return -1;
for (i = 0; i < (int) (sizeof (map) / sizeof (map[0])); i++) for (i = 0; i < (int) (sizeof (map) / sizeof (map[0])); i++)
if (map[i] && strcmp (map[i], os_disk) == 0) if (map[i].device && strcmp (map[i].device, os_disk) == 0)
{ {
free (os_disk); free (os_disk);
return i; return i;