Esempio n. 1
0
static grub_err_t
grub_cpio_find_file (struct grub_archelp_data *data, char **name,
		     grub_int32_t *mtime, grub_uint32_t *mode)
{
  struct head hd;
  grub_size_t namesize;
  grub_uint32_t modeval;

  data->hofs = data->next_hofs;

  if (grub_disk_read (data->disk, 0, data->hofs, sizeof (hd), &hd))
    return grub_errno;

  if (grub_memcmp (hd.magic, MAGIC, sizeof (hd.magic)) != 0
#ifdef MAGIC2
      && grub_memcmp (hd.magic, MAGIC2, sizeof (hd.magic)) != 0
#endif
      )
    return grub_error (GRUB_ERR_BAD_FS, "invalid cpio archive");
  data->size = read_number (hd.filesize, ARRAY_SIZE (hd.filesize));
  if (mtime)
    *mtime = read_number (hd.mtime, ARRAY_SIZE (hd.mtime));
  modeval = read_number (hd.mode, ARRAY_SIZE (hd.mode));
  namesize = read_number (hd.namesize, ARRAY_SIZE (hd.namesize));

  if (mode)
    *mode = modeval;

  *name = grub_malloc (namesize + 1);
  if (*name == NULL)
    return grub_errno;

  if (grub_disk_read (data->disk, 0, data->hofs + sizeof (hd),
		      namesize, *name))
    {
      grub_free (*name);
      return grub_errno;
    }
  (*name)[namesize] = 0;

  if (data->size == 0 && modeval == 0 && namesize == 11
      && grub_memcmp(*name, "TRAILER!!!", 11) == 0)
    {
      *mode = GRUB_ARCHELP_ATTR_END;
      grub_free (*name);
      return GRUB_ERR_NONE;
    }

  data->dofs = data->hofs + ALIGN_CPIO (sizeof (hd) + namesize);
  data->next_hofs = data->dofs + ALIGN_CPIO (data->size);
  return GRUB_ERR_NONE;
}
Esempio n. 2
0
static grub_err_t
grub_cpio_find_file (struct grub_cpio_data *data, char **name,
		     grub_int32_t *mtime, grub_disk_addr_t *ofs,
		     grub_uint32_t *mode)
{
#ifndef MODE_USTAR
  struct head hd;
  grub_size_t namesize;
  grub_uint32_t modeval;

  if (grub_disk_read (data->disk, 0, data->hofs, sizeof (hd), &hd))
    return grub_errno;

  if (grub_memcmp (hd.magic, MAGIC, sizeof (hd.magic)) != 0
#ifdef MAGIC2
      && grub_memcmp (hd.magic, MAGIC2, sizeof (hd.magic)) != 0
#endif
      )
    return grub_error (GRUB_ERR_BAD_FS, "invalid cpio archive");
  data->size = read_number (hd.filesize, ARRAY_SIZE (hd.filesize));
  if (mtime)
    *mtime = read_number (hd.mtime, ARRAY_SIZE (hd.mtime));
  modeval = read_number (hd.mode, ARRAY_SIZE (hd.mode));
  namesize = read_number (hd.namesize, ARRAY_SIZE (hd.namesize));

  if (mode)
    *mode = modeval;

  *name = grub_malloc (namesize + 1);
  if (*name == NULL)
    return grub_errno;

  if (grub_disk_read (data->disk, 0, data->hofs + sizeof (hd),
		      namesize, *name))
    {
      grub_free (*name);
      return grub_errno;
    }
  (*name)[namesize] = 0;

  if (data->size == 0 && modeval == 0 && namesize == 11
      && grub_memcmp(*name, "TRAILER!!!", 11) == 0)
    {
      *ofs = 0;
      grub_free (*name);
      return GRUB_ERR_NONE;
    }

  canonicalize (*name);

  data->dofs = data->hofs + ALIGN_CPIO (sizeof (hd) + namesize);
  *ofs = data->dofs + ALIGN_CPIO (data->size);
#else
  struct head hd;
  int reread = 0, have_longname = 0, have_longlink = 0;

  for (reread = 0; reread < 3; reread++)
    {
      if (grub_disk_read (data->disk, 0, data->hofs, sizeof (hd), &hd))
	return grub_errno;

      if (!hd.name[0] && !hd.prefix[0])
	{
	  *ofs = 0;
	  return GRUB_ERR_NONE;
	}

      if (grub_memcmp (hd.magic, MAGIC, sizeof (MAGIC) - 1))
	return grub_error (GRUB_ERR_BAD_FS, "invalid tar archive");

      if (hd.typeflag == 'L')
	{
	  grub_err_t err;
	  grub_size_t namesize = read_number (hd.size, sizeof (hd.size));
	  *name = grub_malloc (namesize + 1);
	  if (*name == NULL)
	    return grub_errno;
	  err = grub_disk_read (data->disk, 0,
				data->hofs + GRUB_DISK_SECTOR_SIZE, namesize,
				*name);
	  (*name)[namesize] = 0;
	  if (err)
	    return err;
	  data->hofs += GRUB_DISK_SECTOR_SIZE
	    + ((namesize + GRUB_DISK_SECTOR_SIZE - 1) &
	       ~(GRUB_DISK_SECTOR_SIZE - 1));
	  have_longname = 1;
	  continue;
	}

      if (hd.typeflag == 'K')
	{
	  grub_err_t err;
	  grub_size_t linksize = read_number (hd.size, sizeof (hd.size));
	  if (data->linkname_alloc < linksize + 1)
	    {
	      char *n;
	      n = grub_malloc (2 * (linksize + 1));
	      if (!n)
		return grub_errno;
	      grub_free (data->linkname);
	      data->linkname = n;
	      data->linkname_alloc = 2 * (linksize + 1);
	    }

	  err = grub_disk_read (data->disk, 0,
				data->hofs + GRUB_DISK_SECTOR_SIZE, linksize,
				data->linkname);
	  if (err)
	    return err;
	  data->linkname[linksize] = 0;
	  data->hofs += GRUB_DISK_SECTOR_SIZE
	    + ((linksize + GRUB_DISK_SECTOR_SIZE - 1) &
	       ~(GRUB_DISK_SECTOR_SIZE - 1));
	  have_longlink = 1;
	  continue;
	}

      if (!have_longname)
	{
	  grub_size_t extra_size = 0;

	  while (extra_size < sizeof (hd.prefix)
		 && hd.prefix[extra_size])
	    extra_size++;
	  *name = grub_malloc (sizeof (hd.name) + extra_size + 2);
	  if (*name == NULL)
	    return grub_errno;
	  if (hd.prefix[0])
	    {
	      grub_memcpy (*name, hd.prefix, extra_size);
	      (*name)[extra_size++] = '/';
	    }
	  grub_memcpy (*name + extra_size, hd.name, sizeof (hd.name));
	  (*name)[extra_size + sizeof (hd.name)] = 0;
	}

      data->size = read_number (hd.size, sizeof (hd.size));
      data->dofs = data->hofs + GRUB_DISK_SECTOR_SIZE;
      *ofs = data->dofs + ((data->size + GRUB_DISK_SECTOR_SIZE - 1) &
			   ~(GRUB_DISK_SECTOR_SIZE - 1));
      if (mtime)
	*mtime = read_number (hd.mtime, sizeof (hd.mtime));
      if (mode)
	{
	  *mode = read_number (hd.mode, sizeof (hd.mode));
	  switch (hd.typeflag)
	    {
	    case '2':
	      *mode |= ATTR_LNK;
	      break;
	    case '0':
	      *mode |= ATTR_FILE;
	      break;
	    case '5':
	      *mode |= ATTR_DIR;
	      break;
	    }
	}
      if (!have_longlink)
	{
	  if (data->linkname_alloc < 101)
	    {
	      char *n;
	      n = grub_malloc (101);
	      if (!n)
		return grub_errno;
	      grub_free (data->linkname);
	      data->linkname = n;
	      data->linkname_alloc = 101;
	    }
	  grub_memcpy (data->linkname, hd.linkname, sizeof (hd.linkname));
	  data->linkname[100] = 0;
	}

      canonicalize (*name);
      return GRUB_ERR_NONE;
    }
#endif
  return GRUB_ERR_NONE;
}