Exemple #1
0
grub_util_fd_t
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;

  flags |= GRUB_UTIL_FD_O_SYNC;

  if (data->dev && strcmp (data->dev, map[disk->id].device) == 0 &&
      data->access_mode == (flags & O_ACCMODE))
    {
      grub_dprintf ("hostdisk", "reusing open device `%s'\n", data->dev);
      fd = data->fd;
    }
  else
    {
      free (data->dev);
      data->dev = 0;
      if (GRUB_UTIL_FD_IS_VALID(data->fd))
	{
	    if (data->access_mode == O_RDWR || data->access_mode == O_WRONLY)
	      grub_util_fd_sync (data->fd);
	    grub_util_fd_close (data->fd);
	    data->fd = GRUB_UTIL_FD_INVALID;
	}

      fd = grub_util_fd_open (map[disk->id].device, flags);
      if (GRUB_UTIL_FD_IS_VALID(fd))
	{
	  data->dev = xstrdup (map[disk->id].device);
	  data->access_mode = (flags & O_ACCMODE);
	  data->fd = fd;
	}
    }

  if (!GRUB_UTIL_FD_IS_VALID(data->fd))
    {
      grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot open `%s': %s"),
		  map[disk->id].device, grub_util_fd_strerror ());
      return GRUB_UTIL_FD_INVALID;
    }

  if (grub_util_fd_seek (fd, sector << disk->log_sector_size))
    {
      grub_util_fd_close (fd);
      grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot seek `%s': %s"),
		  map[disk->id].device, grub_util_fd_strerror ());

      return GRUB_UTIL_FD_INVALID;
    }

  return fd;
}
Exemple #2
0
static grub_err_t
grub_util_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
			  grub_size_t size, const char *buf)
{
  while (size)
    {
      grub_util_fd_t fd;
      grub_disk_addr_t max = ~0ULL;
      fd = grub_util_fd_open_device (disk, sector, GRUB_UTIL_FD_O_WRONLY, &max);
      if (!GRUB_UTIL_FD_IS_VALID (fd))
	return grub_errno;

#ifdef __linux__
      if (sector == 0)
	/* Work around a bug in Linux ez remapping.  Linux remaps all
	   sectors that are write together with the MBR in one write.  It
	   should only remap the MBR, so we split the write in two
	   parts. -jochen  */
	max = 1;
#endif /* __linux__ */

      if (max > size)
	max = size;

      if (grub_util_fd_write (fd, buf, max << disk->log_sector_size)
	  != (ssize_t) (max << disk->log_sector_size))
	return grub_error (GRUB_ERR_WRITE_ERROR, N_("cannot write to `%s': %s"),
			   map[disk->id].device, grub_util_fd_strerror ());
      size -= max;
      buf += (max << disk->log_sector_size);
    }
  return GRUB_ERR_NONE;
}
/* 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;
}
Exemple #4
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;
  }
}
Exemple #5
0
grub_err_t
grub_util_biosdisk_flush (struct grub_disk *disk)
{
  struct grub_util_hostdisk_data *data = disk->data;

  if (disk->dev->id != GRUB_DISK_DEVICE_BIOSDISK_ID)
    return GRUB_ERR_NONE;
  if (!GRUB_UTIL_FD_IS_VALID (data->fd))
    {
      grub_disk_addr_t max;
      data->fd = grub_util_fd_open_device (disk, 0, GRUB_UTIL_FD_O_RDONLY, &max);
      if (!GRUB_UTIL_FD_IS_VALID (data->fd))
	return grub_errno;
    }
  grub_util_fd_sync (data->fd);
#ifdef __linux__
  if (data->is_disk)
    ioctl (data->fd, BLKFLSBUF, 0);
#endif
  return GRUB_ERR_NONE;
}
Exemple #6
0
static void
grub_util_biosdisk_close (struct grub_disk *disk)
{
  struct grub_util_hostdisk_data *data = disk->data;

  free (data->dev);
  if (GRUB_UTIL_FD_IS_VALID (data->fd))
    {
      if (data->access_mode == O_RDWR || data->access_mode == O_WRONLY)
	grub_util_biosdisk_flush (disk);
      grub_util_fd_close (data->fd);
    }
  free (data);
}
Exemple #7
0
static int
grub_util_check_file_presence (const char *p)
{
#if !GRUB_UTIL_FD_STAT_IS_FUNCTIONAL
  grub_util_fd_t h;
  h = grub_util_fd_open (p, GRUB_UTIL_FD_O_RDONLY);
  if (!GRUB_UTIL_FD_IS_VALID(h))
    return 0;
  grub_util_fd_close (h);
  return 1;
#else
  struct stat st;

  if (stat (p, &st) == -1)
    return 0;
  return 1;
#endif
}