⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 biosdisk.c

📁 最新的grub2源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
  #ifdef __linux__  if (sector == 0 && size > 1)    {      /* Work around a bug in linux's ez remapping.  Linux remaps all	 sectors that are read together with the MBR in one read.  It	 should only remap the MBR, so we split the read in two 	 parts. -jochen  */      if (nread (fd, buf, GRUB_DISK_SECTOR_SIZE) != GRUB_DISK_SECTOR_SIZE)	{	  grub_error (GRUB_ERR_READ_ERROR, "cannot read `%s'", map[disk->id]);	  close (fd);	  return grub_errno;	}            buf += GRUB_DISK_SECTOR_SIZE;      size--;    }#endif /* __linux__ */    if (nread (fd, buf, 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]);  close (fd);  return grub_errno;}static grub_err_tgrub_util_biosdisk_write (grub_disk_t disk, unsigned long sector,			  unsigned long size, const char *buf){  int fd;  fd = open_device (disk, sector, O_WRONLY);  if (fd < 0)    return grub_errno;    if (nwrite (fd, buf, 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]);  close (fd);  return grub_errno;}static struct grub_disk_dev grub_util_biosdisk_dev =  {    .name = "biosdisk",    .id = GRUB_DISK_DEVICE_BIOSDISK_ID,    .iterate = grub_util_biosdisk_iterate,    .open = grub_util_biosdisk_open,    .close = 0,    .read = grub_util_biosdisk_read,    .write = grub_util_biosdisk_write,    .next = 0  };static voidread_device_map (const char *dev_map){  FILE *fp;  char buf[1024];	/* XXX */  int lineno = 0;  auto void show_error (const char *msg);  void show_error (const char *msg)    {      grub_util_error ("%s:%d: %s", dev_map, lineno, msg);    }    fp = fopen (dev_map, "r");  if (! fp)    grub_util_error ("Cannot open `%s'", dev_map);  while (fgets (buf, sizeof (buf), fp))    {      char *p = buf;      char *e;      int drive;            lineno++;            /* Skip leading spaces.  */      while (*p && isspace (*p))	p++;      /* If the first character is `#' or NUL, skip this line.  */      if (*p == '\0' || *p == '#')	continue;      if (*p != '(')	show_error ("No open parenthesis found");      p++;      drive = get_drive (p);      if (drive < 0 || drive >= (int) (sizeof (map) / sizeof (map[0])))	show_error ("Bad device name");      p = strchr (p, ')');      if (! p)	show_error ("No close parenthesis found");      p++;      /* Skip leading spaces.  */      while (*p && isspace (*p))	p++;      if (*p == '\0')	show_error ("No filename found");      /* NUL-terminate the filename.  */      e = p;      while (*e && ! isspace (*e))	e++;      *e = '\0';      /* Multiple entries for a given drive is not allowed.  */      if (map[drive])	show_error ("Duplicated entry found");#ifdef __linux__      /* On Linux, the devfs uses symbolic links horribly, and that	 confuses the interface very much, so use realpath to expand	 symbolic links.  */      map[drive] = xmalloc (PATH_MAX);      if (! realpath (p, map[drive]))	grub_util_error ("Cannot get the real path of `%s'", p);#else      map[drive] = xstrdup (p);#endif    }  fclose (fp);}voidgrub_util_biosdisk_init (const char *dev_map){  read_device_map (dev_map);  grub_disk_dev_register (&grub_util_biosdisk_dev);}voidgrub_util_biosdisk_fini (void){  unsigned i;    for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)    free (map[i]);    grub_disk_dev_unregister (&grub_util_biosdisk_dev);}static char *make_device_name (int drive, int dos_part, int bsd_part){  char *p;  p = xmalloc (30);  sprintf (p, (drive & 0x80) ? "hd%d" : "fd%d", drive & ~0x80);    if (dos_part >= 0)    sprintf (p + strlen (p), ",%d", dos_part);    if (bsd_part >= 0)    sprintf (p + strlen (p), ",%c", bsd_part + 'a');    return p;}static char *get_os_disk (const char *os_dev){  char *path, *p;  #if defined(__linux__)  path = xmalloc (PATH_MAX);  if (! realpath (os_dev, path))    return 0;    if (strncmp ("/dev/", path, 5) == 0)    {      p = path + 5;      if (have_devfs ())	{	  /* If this is an IDE disk.  */	  if (strncmp ("/dev/ide/", p, 9) == 0)	    {	      p = strstr (p, "part");	      if (p)		strcpy (p, "disc");	      return path;	    }	  /* If this is a SCSI disk.  */	  if (strncmp ("/dev/scsi/", p, 10) == 0)	    {	      p = strstr (p, "part");	      if (p)		strcpy (p, "disc");	      return path;	    }	}            /* If this is a DAC960 disk.  */      if (strncmp ("rd/c", p, 4) == 0)	{	  /* /dev/rd/c[0-9]+d[0-9]+(p[0-9]+)? */	  p = strchr (p, 'p');	  if (p)	    *p = '\0';	  return path;	}            /* If this is an IDE disk or a SCSI disk.  */      if ((strncmp ("hd", p, 2) == 0	   || strncmp ("sd", p, 2) == 0)	  && p[2] >= 'a' && p[2] <= 'z')	{	  /* /dev/[hs]d[a-z][0-9]* */	  p[3] = '\0';	  return path;	}    }  return path;  #elif defined(__GNU__)  path = xstrdup (os_dev);  if (strncmp ("/dev/sd", path, 7) == 0 || strncmp ("/dev/hd", path, 7) == 0)    {      p = strchr (path, 's');      if (p)	*p = '\0';    }  return path;#else# warning "The function `get_os_disk' might not work on your OS correctly."  return xstrdup (os_dev);#endif}static intfind_drive (const char *os_dev){  int i;  char *os_disk;  os_disk = get_os_disk (os_dev);  if (! os_disk)    return -1;    for (i = 0; i < (int) (sizeof (map) / sizeof (map[0])); i++)    if (map[i] && strcmp (map[i], os_disk) == 0)      {	free (os_disk);	return i;      }  free (os_disk);  return -1;}char *grub_util_biosdisk_get_grub_dev (const char *os_dev){  struct stat st;  int drive;  if (stat (os_dev, &st) < 0)    {      grub_error (GRUB_ERR_BAD_DEVICE, "cannot stat `%s'", os_dev);      return 0;    }  drive = find_drive (os_dev);  if (drive < 0)    {      grub_error (GRUB_ERR_BAD_DEVICE,		  "no mapping exists for `%s'", os_dev);      return 0;    }    if (! S_ISBLK (st.st_mode))    return make_device_name (drive, -1, -1);  #if defined(__linux__)  /* Linux counts partitions uniformly, whether a BSD partition or a DOS     partition, so mapping them to GRUB devices is not trivial.     Here, get the start sector of a partition by HDIO_GETGEO, and     compare it with each partition GRUB recognizes.  */  {    char *name;    grub_disk_t disk;    int fd;    struct hd_geometry hdg;    int dos_part = -1;    int bsd_part = -1;    auto int find_partition (grub_disk_t disk,			     const grub_partition_t partition);        int find_partition (grub_disk_t disk __attribute__ ((unused)),			const grub_partition_t partition)      { 	struct grub_pc_partition *pcdata = 0;		if (strcmp (partition->partmap->name, "pc_partition_map") == 0)	  pcdata = partition->data;	  	if (pcdata)	  {	    if (pcdata->bsd_part < 0)	      grub_util_info ("DOS partition %d starts from %lu",			      pcdata->dos_part, partition->start);	    else	      grub_util_info ("BSD partition %d,%c starts from %lu",			      pcdata->dos_part, pcdata->bsd_part + 'a',			      partition->start);	  }		if (hdg.start == partition->start)	  {	    if (pcdata)	      {		dos_part = pcdata->dos_part;		bsd_part = pcdata->bsd_part;	      }	    else	      {		dos_part = 0;		bsd_part = 0;	      }	    return 1;	  }		return 0;      }        name = make_device_name (drive, -1, -1);        if (MAJOR (st.st_rdev) == FLOPPY_MAJOR)      return name;        fd = open (os_dev, O_RDONLY);    if (! fd)      {	grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s'", os_dev);	free (name);	return 0;      }        if (ioctl (fd, HDIO_GETGEO, &hdg))      {	grub_error (GRUB_ERR_BAD_DEVICE,		    "cannot get geometry of `%s'", os_dev);	close (fd);	free (name);	return 0;      }        close (fd);    grub_util_info ("%s starts from %lu", os_dev, hdg.start);        if (hdg.start == 0)      return name;    grub_util_info ("opening the device %s", name);    disk = grub_disk_open (name);    free (name);        if (! disk)      return 0;        if (grub_partition_iterate (disk, find_partition) != GRUB_ERR_NONE)      {	grub_disk_close (disk);	return 0;      }        if (dos_part < 0)      {	grub_disk_close (disk);	grub_error (GRUB_ERR_BAD_DEVICE,		    "cannot find the partition of `%s'", os_dev);	return 0;      }        return make_device_name (drive, dos_part, bsd_part);  }  #elif defined(__GNU__)  /* GNU uses "/dev/[hs]d[0-9]+(s[0-9]+[a-z]?)?".  */  {    char *p;    int dos_part = -1;    int bsd_part = -1;        p = strrchr (os_dev, 's');    if (p)      {	long int n;	char *q;		p++;	n = strtol (p, &q, 10);	if (p != q && n != LONG_MIN && n != LONG_MAX)	  {	    dos_part = (int) n;	    	    if (*q >= 'a' && *q <= 'g')	      bsd_part = *q - 'a';	  }      }        return make_device_name (drive, dos_part, bsd_part);  }  #else# warning "The function `grub_util_biosdisk_get_grub_dev' might not work on your OS correctly."  return make_device_name (drive, -1, -1);#endif}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -