Example #1
0
/* Open a file named NAME and initialize FILE.  */
static grub_err_t
grub_hostfs_open (struct grub_file *file, const char *name)
{
  grub_util_fd_t f;
  struct grub_hostfs_data *data;

  f = grub_util_fd_open (name, GRUB_UTIL_FD_O_RDONLY);
  if (! GRUB_UTIL_FD_IS_VALID (f))
    return grub_error (GRUB_ERR_BAD_FILENAME,
		       N_("can't open `%s': %s"), name,
		       strerror (errno));
  data = grub_malloc (sizeof (*data));
  if (!data)
    {
      grub_util_fd_close (f);
      return grub_errno;
    }
  data->filename = grub_strdup (name);
  if (!data->filename)
    {
      grub_free (data);
      grub_util_fd_close (f);
      return grub_errno;
    }

  data->f = f;  

  file->data = data;

  file->size = grub_util_get_fd_size (f, name, NULL);

  return GRUB_ERR_NONE;
}
Example #2
0
static grub_err_t
grub_util_biosdisk_open (const char *name, grub_disk_t disk)
{
  int drive;
  struct grub_util_hostdisk_data *data;

  drive = find_grub_drive (name);
  grub_util_info ("drive = %d", drive);
  if (drive < 0)
    return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
		       "no mapping exists for `%s'", name);

  disk->id = drive;
  disk->data = data = xmalloc (sizeof (struct grub_util_hostdisk_data));
  data->dev = NULL;
  data->access_mode = 0;
  data->fd = GRUB_UTIL_FD_INVALID;
  data->is_disk = 0;
  data->device_map = map[drive].device_map;

  /* Get the size.  */
  {
    grub_util_fd_t fd;

    fd = grub_util_fd_open (map[drive].device, GRUB_UTIL_FD_O_RDONLY);

    if (!GRUB_UTIL_FD_IS_VALID(fd))
      return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("cannot open `%s': %s"),
			 map[drive].device, grub_util_fd_strerror ());

    disk->total_sectors = grub_util_get_fd_size (fd, map[drive].device,
						 &disk->log_sector_size);
    disk->total_sectors >>= disk->log_sector_size;

#if GRUB_UTIL_FD_STAT_IS_FUNCTIONAL
    {
      struct stat st;
# if GRUB_DISK_DEVS_ARE_CHAR
      if (fstat (fd, &st) < 0 || ! S_ISCHR (st.st_mode))
# else
      if (fstat (fd, &st) < 0 || ! S_ISBLK (st.st_mode))
# endif
	data->is_disk = 1;
    }
#endif

    grub_util_fd_close (fd);

    grub_util_info ("the size of %s is %" PRIuGRUB_UINT64_T,
		    name, disk->total_sectors);

    return GRUB_ERR_NONE;
  }
}
Example #3
0
int
grub_util_fd_open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags,
			  grub_disk_addr_t *max)
{
  grub_util_fd_t fd;
  struct grub_util_hostdisk_data *data = disk->data;

  *max = ~0ULL;

#ifdef O_LARGEFILE
  flags |= O_LARGEFILE;
#endif
#ifdef O_SYNC
  flags |= O_SYNC;
#endif
#ifdef O_FSYNC
  flags |= O_FSYNC;
#endif
#ifdef O_BINARY
  flags |= O_BINARY;
#endif

  /* Linux has a bug that the disk cache for a whole disk is not consistent
     with the one for a partition of the disk.  */
  {
    int is_partition = 0;
    char dev[PATH_MAX];
    grub_disk_addr_t part_start = 0;

    part_start = grub_partition_get_start (disk->partition);

    strcpy (dev, grub_util_biosdisk_get_osdev (disk));
    if (disk->partition
	&& strncmp (dev, "/dev/", 5) == 0)
      {
	if (sector >= part_start)
	  is_partition = grub_hostdisk_linux_find_partition (dev, part_start);
	else
	  *max = part_start - sector;
      }

  reopen:

    if (data->dev && strcmp (data->dev, dev) == 0 &&
	data->access_mode == (flags & O_ACCMODE))
      {
	grub_dprintf ("hostdisk", "reusing open device `%s'\n", dev);
	fd = data->fd;
      }
    else
      {
	free (data->dev);
	data->dev = 0;
	if (data->fd != -1)
	  {
	    if (data->access_mode == O_RDWR || data->access_mode == O_WRONLY)
	      {
		fsync (data->fd);
		if (data->is_disk)
		  ioctl (data->fd, BLKFLSBUF, 0);
	      }

	    close (data->fd);
	    data->fd = -1;
	  }

	/* Open the partition.  */
	grub_dprintf ("hostdisk", "opening the device `%s' in open_device()\n", dev);
	fd = open (dev, flags);
	if (fd < 0)
	  {
	    grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot open `%s': %s"),
			dev, strerror (errno));
	    return -1;
	  }

	data->dev = xstrdup (dev);
	data->access_mode = (flags & O_ACCMODE);
	data->fd = fd;

	if (data->is_disk)
	  ioctl (data->fd, BLKFLSBUF, 0);
      }

    if (is_partition)
      {
	*max = grub_util_get_fd_size (fd, dev, 0);
	*max >>= disk->log_sector_size;
	if (sector - part_start >= *max)
	  {
	    *max = disk->partition->len - (sector - part_start);
	    if (*max == 0)
	      *max = ~0ULL;
	    is_partition = 0;
	    strcpy (dev, grub_util_biosdisk_get_osdev (disk));
	    goto reopen;
	  }
	sector -= part_start;
	*max -= sector;
      }
  }

  if (grub_util_fd_seek (fd, sector << disk->log_sector_size))
    {
      close (fd);
      grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot seek `%s': %s"),
		  grub_util_biosdisk_get_osdev (disk), strerror (errno));
      return -1;
    }

  return fd;
}