Exemple #1
0
void
grub_blocklist_convert (grub_file_t file)
{
  struct read_blocklist_closure c;

  if ((file->fs == &grub_fs_blocklist) || (! file->device->disk) ||
      (! file->size))
    return;

  file->offset = 0;
  file->flags = 1;

  c.num = 0;
  c.blocks = 0;
  c.total_size = 0;
  c.part_start = grub_partition_get_start (file->device->disk->partition);
  file->read_hook = read_blocklist;
  file->closure = &c;
  grub_file_read (file, 0, file->size);
  file->read_hook = 0;
  if ((grub_errno) || (c.total_size != file->size))
    {
      grub_errno = 0;
      grub_free (c.blocks);
    }
  else
    {
      if (file->fs->close)
	(file->fs->close) (file);
      file->fs = &grub_fs_blocklist;
      file->data = c.blocks;
    }

  file->offset = 0;
}
Exemple #2
0
/* Helper for scan_disk.  */
static int
scan_disk_partition_iter (grub_disk_t disk, grub_partition_t p, void *data)
{
  const char *name = data;
  struct grub_diskfilter_vg *arr;
  grub_disk_addr_t start_sector;
  struct grub_diskfilter_pv_id id;
  grub_diskfilter_t diskfilter;

  grub_dprintf ("diskfilter", "Scanning for DISKFILTER devices on disk %s\n",
		name);
#ifdef GRUB_UTIL
  grub_util_info ("Scanning for DISKFILTER devices on disk %s", name);
#endif

  disk->partition = p;
  
  for (arr = array_list; arr != NULL; arr = arr->next)
    {
      struct grub_diskfilter_pv *m;
      for (m = arr->pvs; m; m = m->next)
	if (m->disk && m->disk->id == disk->id
	    && m->disk->dev->id == disk->dev->id
	    && m->part_start == grub_partition_get_start (disk->partition)
	    && m->part_size == grub_disk_get_size (disk))
	  return 0;
    }

  for (diskfilter = grub_diskfilter_list; diskfilter; diskfilter = diskfilter->next)
    {
#ifdef GRUB_UTIL
      grub_util_info ("Scanning for %s devices on disk %s", 
		      diskfilter->name, name);
#endif
      id.uuid = 0;
      id.uuidlen = 0;
      arr = diskfilter->detect (disk, &id, &start_sector);
      if (arr &&
	  (! insert_array (disk, &id, arr, start_sector, diskfilter)))
	{
	  if (id.uuidlen)
	    grub_free (id.uuid);
	  return 0;
	}
      if (arr && id.uuidlen)
	grub_free (id.uuid);

      /* This error usually means it's not diskfilter, no need to display
	 it.  */
      if (grub_errno != GRUB_ERR_OUT_OF_RANGE)
	grub_print_error ();

      grub_errno = GRUB_ERR_NONE;
    }

  return 0;
}
Exemple #3
0
static PyObject *bits_file_data_and_disk_blocks(PyObject *self, PyObject *args)
{
    PyObject *pyfile, *pystr;
    grub_file_t file;
    grub_ssize_t bytes_read;

    if (!PyArg_ParseTuple(args, "O!:file_data_and_disk_blocks", &PyFile_Type, &pyfile))
        return NULL;

    file = PyFile_AsFile(pyfile);
    if (!file->device->disk)
        return PyErr_Format(PyExc_RuntimeError, "Can't get disk blocks from non-disk-backed file");

    partition_start_sector = grub_partition_get_start(file->device->disk->partition);

    pyblocklist = PyList_New(0);
    if (!pyblocklist)
        return NULL;
    pystr = PyString_FromStringAndSize(NULL, grub_file_size(file));
    if (!pystr) {
        Py_CLEAR(pyblocklist);
        return NULL;
    }

    file->read_hook = disk_blocks_read_hook;
    bytes_read = grub_file_read(file, PyString_AsString(pystr), grub_file_size(file));
    file->read_hook = NULL;
    if ((grub_off_t)bytes_read != grub_file_size(file)) {
        Py_CLEAR(pyblocklist);
        Py_DECREF(pystr);
        return PyErr_Format(PyExc_RuntimeError, "Failed to read from file");
    }
    if (!pyblocklist) {
        Py_DECREF(pystr);
        return PyErr_NoMemory();
    }

    return Py_BuildValue("(NN)", pystr, pyblocklist);
}
Exemple #4
0
static grub_err_t
grub_cmd_blocklist (grub_command_t cmd __attribute__ ((unused)),
		    int argc, char **args)
{
  grub_file_t file;
  char buf[GRUB_DISK_SECTOR_SIZE];
  unsigned long start_sector = 0;
  unsigned num_sectors = 0;
  int num_entries = 0;
  grub_disk_addr_t part_start = 0;
  auto void NESTED_FUNC_ATTR read_blocklist (grub_disk_addr_t sector, unsigned offset,
			    unsigned length);
  auto void NESTED_FUNC_ATTR print_blocklist (grub_disk_addr_t sector, unsigned num,
			     unsigned offset, unsigned length);

  void NESTED_FUNC_ATTR read_blocklist (grub_disk_addr_t sector, unsigned offset,
		       unsigned length)
    {
      if (num_sectors > 0)
	{
	  if (start_sector + num_sectors == sector
	      && offset == 0 && length == GRUB_DISK_SECTOR_SIZE)
	    {
	      num_sectors++;
	      return;
	    }

	  print_blocklist (start_sector, num_sectors, 0, 0);
	  num_sectors = 0;
	}

      if (offset == 0 && length == GRUB_DISK_SECTOR_SIZE)
	{
	  start_sector = sector;
	  num_sectors++;
	}
      else
	print_blocklist (sector, 0, offset, length);
    }

  void NESTED_FUNC_ATTR print_blocklist (grub_disk_addr_t sector, unsigned num,
			unsigned offset, unsigned length)
    {
      if (num_entries++)
	grub_printf (",");

      grub_printf ("%llu", (unsigned long long) (sector - part_start));
      if (num > 0)
	grub_printf ("+%u", num);
      if (offset != 0 || length != 0)
	grub_printf ("[%u-%u]", offset, offset + length);
    }

  if (argc < 1)
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");

  file = grub_file_open (args[0]);
  if (! file)
    return grub_errno;

  if (! file->device->disk)
    return grub_error (GRUB_ERR_BAD_DEVICE,
		       "this command is available only for disk devices");

  part_start = grub_partition_get_start (file->device->disk->partition);

  file->read_hook = read_blocklist;

  while (grub_file_read (file, buf, sizeof (buf)) > 0)
    ;

  if (num_sectors > 0)
    print_blocklist (start_sector, num_sectors, 0, 0);

  grub_file_close (file);

  return grub_errno;
}
Exemple #5
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;
}