Example #1
0
File: fs.c Project: P4N74/radare2
static void
read_blocklist (grub_disk_addr_t sector, unsigned offset,
		unsigned length, void *closure)
{
  struct read_blocklist_closure *c = closure;

  sector = ((sector - c->part_start) << GRUB_DISK_SECTOR_BITS) + offset;

  if ((c->num) &&
      (c->blocks[c->num - 1].offset + c->blocks[c->num - 1].length == sector))
    {
      c->blocks[c->num - 1].length += length;
      goto quit;
    }

  if ((c->num & (BLOCKLIST_INC_STEP - 1)) == 0)
    {
      c->blocks = grub_realloc (c->blocks, (c->num + BLOCKLIST_INC_STEP) *
				sizeof (struct grub_fs_block));
      if (! c->blocks)
	return;
    }

  c->blocks[c->num].offset = sector;
  c->blocks[c->num].length = length;
  c->num++;

 quit:
  c->total_size += length;
}
Example #2
0
static char *
grub_getline (void)
{
  int i;
  char *line;
  char *tmp;
  char c;

  i = 0;
  line = grub_malloc (1 + i + sizeof('\0'));
  if (! line)
    return NULL;

  while (1)
    {
      c = grub_getkey ();
      if ((c == '\n') || (c == '\r'))
	break;

      line[i] = c;
      if (grub_isprint (c))
	grub_putchar (c);
      i++;
      tmp = grub_realloc (line, 1 + i + sizeof('\0'));
      if (! tmp)
	{
	  grub_free (line);
	  return NULL;
	}
      line = tmp;
    }
  line[i] = '\0';

  return line;
}
Example #3
0
grub_err_t
grub_uitree_set_prop (grub_uitree_t node, const char *name, const char *value)
{
  int ofs, len;
  grub_uiprop_t p, *ptr, next;

  ofs = grub_strlen (name) + 1;
  len = ofs + grub_strlen (value) + 1;

  next = 0;
  ptr = &node->prop;
  while (*ptr)
    {
      if (! grub_strcmp ((*ptr)->name, name))
	{
	  next = (*ptr)->next;
	  break;
	}
      ptr = &((*ptr)->next);
    }

  p = grub_realloc (*ptr, sizeof (struct grub_uiprop) + len);
  if (! p)
    return grub_errno;

  *ptr = p;
  p->next = next;
  grub_strcpy (p->name, name);
  grub_strcpy (p->name + ofs, value);
  p->value = &p->name[ofs];

  return grub_errno;
}
Example #4
0
char *
grub_partition_get_name (const grub_partition_t partition)
{
  char *out = 0;
  int curlen = 0;
  grub_partition_t part;
  for (part = partition; part; part = part->parent)
    {
      /* Even on 64-bit machines this buffer is enough to hold
	 longest number.  */
      char buf[grub_strlen (part->partmap->name) + 25];
      int strl;
      grub_snprintf (buf, sizeof (buf), "%s%d", part->partmap->name,
		     part->number + 1);
      strl = grub_strlen (buf);
      if (curlen)
	{
	  out = grub_realloc (out, curlen + strl + 2);
	  grub_memcpy (out + strl + 1, out, curlen);
	  out[curlen + 1 + strl] = 0;
	  grub_memcpy (out, buf, strl);
	  out[strl] = ',';
	  curlen = curlen + 1 + strl;
	}
      else
	{
	  curlen = strl;
	  out = grub_strdup (buf);
	}
    }
  return out;
}
Example #5
0
/* Add a memory region to map*/
static grub_err_t
grub_efiemu_add_to_mmap (grub_uint64_t start, grub_uint64_t size,
			 grub_efi_memory_type_t type)
{
  grub_uint64_t page_start, npages;

  /* Extend map if necessary*/
  if (mmap_num >= mmap_reserved_size)
    {
      efiemu_mmap = (grub_efi_memory_descriptor_t *)
	grub_realloc (efiemu_mmap, (++mmap_reserved_size)
		      * sizeof (grub_efi_memory_descriptor_t));
      if (!efiemu_mmap)
	return grub_error (GRUB_ERR_OUT_OF_MEMORY,
			   "not enough space for memory map");
    }

  /* Fill slot*/
  page_start = start - (start % GRUB_EFIEMU_PAGESIZE);
  npages = (size + (start % GRUB_EFIEMU_PAGESIZE) + GRUB_EFIEMU_PAGESIZE - 1)
    / GRUB_EFIEMU_PAGESIZE;
  efiemu_mmap[mmap_num].physical_start = page_start;
  efiemu_mmap[mmap_num].virtual_start = page_start;
  efiemu_mmap[mmap_num].num_pages = npages;
  efiemu_mmap[mmap_num].type = type;
  mmap_num++;

  return GRUB_ERR_NONE;
}
Example #6
0
/* Helper for match_devices.  */
static int
match_devices_iter (const char *name, void *data)
{
  struct match_devices_ctx *ctx = data;
  char **t;
  char *buffer;

  /* skip partitions if asked to. */
  if (ctx->noparts && grub_strchr (name, ','))
    return 0;

  buffer = grub_xasprintf ("(%s)", name);
  if (! buffer)
    return 1;

  grub_dprintf ("expand", "matching: %s\n", buffer);
  if (regexec (ctx->regexp, buffer, 0, 0, 0))
    {
      grub_dprintf ("expand", "not matched\n");
      grub_free (buffer);
      return 0;
    }

  t = grub_realloc (ctx->devs, sizeof (char*) * (ctx->ndev + 2));
  if (! t)
    {
      grub_free (buffer);
      return 1;
    }

  ctx->devs = t;
  ctx->devs[ctx->ndev++] = buffer;
  ctx->devs[ctx->ndev] = 0;
  return 0;
}
Example #7
0
File: efi.c Project: Arvian/GRUB2
char *
grub_efi_get_filename (grub_efi_device_path_t *dp)
{
  char *name = 0;

  while (1)
    {
      grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
      grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);

      if (type == GRUB_EFI_END_DEVICE_PATH_TYPE)
	break;
      else if (type == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE
	       && subtype == GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE)
	{
	  grub_efi_file_path_device_path_t *fp;
	  grub_efi_uint16_t len;
	  char *p;
	  grub_size_t size;

	  if (name)
	    {
	      size = grub_strlen (name);
	      name[size] = '/';
	      size++;
	    }
	  else
	    size = 0;

	  len = ((GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4)
		 / sizeof (grub_efi_char16_t));
	  p = grub_realloc (name, size + len * 4 + 1);
	  if (! p)
	    {
	      grub_free (name);
	      return 0;
	    }

	  name = p;
	  fp = (grub_efi_file_path_device_path_t *) dp;
	  *grub_utf16_to_utf8 ((grub_uint8_t *) name + size,
			       fp->path_name, len) = '\0';
	}

      dp = GRUB_EFI_NEXT_DEVICE_PATH (dp);
    }

  if (name)
    {
      /* EFI breaks paths with backslashes.  */
      char *p;

      for (p = name; *p; p++)
	if (*p == '\\')
	  *p = '/';
    }

  return name;
}
Example #8
0
static inline void
get_space(grub_size_t need)
{
    need += out_used;
    if (need > out_size) {
	out_size = need * 2;
	out_buff = grub_realloc(out_buff, out_size*sizeof(char));
	/* FIX ME! handle out_buff == 0.  */
    }
}
Example #9
0
  /* Extend the symlink.  */
static void
add_part (struct iterate_dir_ctx *ctx,
	  const char *part,
	  int len2)
{
  int size = ctx->symlink ? grub_strlen (ctx->symlink) : 0;

  ctx->symlink = grub_realloc (ctx->symlink, size + len2 + 1);
  if (! ctx->symlink)
    return;

  grub_memcpy (ctx->symlink + size, part, len2);
  ctx->symlink[size + len2] = 0;  
}
Example #10
0
void *
PREFIX (realloc) (void *relocator, grub_size_t size)
{
  char *playground;

  if (!relocator)
    return PREFIX (alloc) (size);

  playground = (char *) relocator - PRE_REGION_SIZE;

  playground = grub_realloc (playground, size + MAX_OVERHEAD);
  if (!playground)
    return 0;

  *(grub_size_t *) playground = size;

  return playground + PRE_REGION_SIZE;
}
Example #11
0
grub_err_t
grub_net_add_dns_server (const struct grub_net_network_level_address *s)
{
  if (dns_servers_alloc <= dns_nservers)
    {
      int na = dns_servers_alloc * 2;
      struct grub_net_network_level_address *ns;
      if (na < 8)
	na = 8;
      ns = grub_realloc (dns_servers, na * sizeof (ns[0]));
      if (!ns)
	return grub_errno;
      dns_servers_alloc = na;
      dns_servers = ns;
    }
  dns_servers[dns_nservers++] = *s;
  return GRUB_ERR_NONE;
}
Example #12
0
static grub_err_t
save_ref (struct grub_btrfs_leaf_descriptor *desc, 
	  grub_disk_addr_t addr, unsigned i, unsigned m, int l)
{
  desc->depth++;
  if (desc->allocated < desc->depth)
    {
      void *newdata;
      desc->allocated *= 2;
      newdata = grub_realloc (desc->data, sizeof (desc->data[0])
			      * desc->allocated);
      if (!newdata)
	return grub_errno;
      desc->data = newdata;
    }
  desc->data[desc->depth - 1].addr = addr;
  desc->data[desc->depth - 1].iter = i;
  desc->data[desc->depth - 1].maxiter = m;
  desc->data[desc->depth - 1].leaf = l;
  return GRUB_ERR_NONE;
}
Example #13
0
grub_err_t
grub_video_fb_set_palette (unsigned int start, unsigned int count,
			   struct grub_video_palette_data *palette_data)
{
  unsigned i;
  if (start + count > framebuffer.palette_size)
    {
      framebuffer.palette_size = start + count;
      framebuffer.palette = grub_realloc (framebuffer.palette,
					  sizeof (framebuffer.palette[0])
					  * framebuffer.palette_size);
      if (!framebuffer.palette)
	{
	  grub_video_fb_fini ();
	  return grub_errno;
	}
    }
  for (i = 0; (i < count) && ((i + start) < framebuffer.palette_size); i++)
    framebuffer.palette[start + i] = palette_data[i];
  return GRUB_ERR_NONE;
}
Example #14
0
/*
 * grub_ubootdisk_register():
 *   Called for each disk device enumerated as part of U-Boot initialization
 *   code.
 */
grub_err_t
grub_ubootdisk_register (struct device_info *newdev)
{
  struct ubootdisk_data *d;

#define STOR_TYPE(x) ((x) & 0x0ff0)
  switch (STOR_TYPE (newdev->type))
    {
    case DT_STOR_IDE:
    case DT_STOR_SATA:
    case DT_STOR_SCSI:
    case DT_STOR_MMC:
    case DT_STOR_USB:
      /* hd */
      if (hd_num == hd_max)
	{
	  int new_num;
	  new_num = (hd_max ? hd_max * 2 : 1);
	  d = grub_realloc(hd_devices,
			   sizeof (struct ubootdisk_data) * new_num);
	  if (!d)
	    return grub_errno;
	  hd_devices = d;
	  hd_max = new_num;
	}

      d = &hd_devices[hd_num];
      hd_num++;
      break;
    default:
      return GRUB_ERR_BAD_DEVICE;
      break;
    }

  d->dev = newdev;
  d->cookie = newdev->cookie;
  d->opencount = 0;

  return 0;
}
Example #15
0
File: http.c Project: Arvian/GRUB2
static grub_err_t
http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)),
	      struct grub_net_buff *nb,
	      void *f)
{
  grub_file_t file = f;
  http_data_t data = file->data;
  grub_err_t err;

  while (1)
    {
      char *ptr = (char *) nb->data;
      if ((!data->headers_recv || data->in_chunk_len) && data->current_line)
	{
	  int have_line = 1;
	  char *t;
	  ptr = grub_memchr (nb->data, '\n', nb->tail - nb->data);
	  if (ptr)
	    ptr++;
	  else
	    {
	      have_line = 0;
	      ptr = (char *) nb->tail;
	    }
	  t = grub_realloc (data->current_line,
			    data->current_line_len + (ptr - (char *) nb->data));
	  if (!t)
	    {
	      grub_netbuff_free (nb);
	      grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
	      return grub_errno;
	    }
	      
	  data->current_line = t;
	  grub_memcpy (data->current_line + data->current_line_len,
		       nb->data, ptr - (char *) nb->data);
	  data->current_line_len += ptr - (char *) nb->data;
	  if (!have_line)
	    {
	      grub_netbuff_free (nb);
	      return GRUB_ERR_NONE;
	    }
	  err = parse_line (file, data, data->current_line,
			    data->current_line_len);
	  grub_free (data->current_line);
	  data->current_line = 0;
	  data->current_line_len = 0;
	  if (err)
	    {
	      grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
	      grub_netbuff_free (nb);
	      return err;
	    }
	}

      while (ptr < (char *) nb->tail && (!data->headers_recv
					 || data->in_chunk_len))
	{
	  char *ptr2;
	  ptr2 = grub_memchr (ptr, '\n', (char *) nb->tail - ptr);
	  if (!ptr2)
	    {
	      data->current_line = grub_malloc ((char *) nb->tail - ptr);
	      if (!data->current_line)
		{
		  grub_netbuff_free (nb);
		  grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
		  return grub_errno;
		}
	      data->current_line_len = (char *) nb->tail - ptr;
	      grub_memcpy (data->current_line, ptr, data->current_line_len);
	      grub_netbuff_free (nb);
	      return GRUB_ERR_NONE;
	    }
	  err = parse_line (file, data, ptr, ptr2 - ptr);
	  if (err)
	    {
	      grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
	      grub_netbuff_free (nb);
	      return err;
	    }
	  ptr = ptr2 + 1;
	}

      if (((char *) nb->tail - ptr) <= 0)
	{
	  grub_netbuff_free (nb);
	  return GRUB_ERR_NONE;
	} 
      err = grub_netbuff_pull (nb, ptr - (char *) nb->data);
      if (err)
	{
	  grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
	  grub_netbuff_free (nb);
	  return err;
	}
      if (!(data->chunked && (grub_ssize_t) data->chunk_rem
	    < nb->tail - nb->data))
	{
	  grub_net_put_packet (&file->device->net->packs, nb);
	  if (file->device->net->packs.count >= 20)
	    file->device->net->stall = 1;

	  if (file->device->net->packs.count >= 100)
	    grub_net_tcp_stall (data->sock);

	  if (data->chunked)
	    data->chunk_rem -= nb->tail - nb->data;
	  return GRUB_ERR_NONE;
	}
      if (data->chunk_rem)
	{
	  struct grub_net_buff *nb2;
	  nb2 = grub_netbuff_alloc (data->chunk_rem);
	  if (!nb2)
	    return grub_errno;
	  grub_netbuff_put (nb2, data->chunk_rem);
	  grub_memcpy (nb2->data, nb->data, data->chunk_rem);
	  if (file->device->net->packs.count >= 20)
	    {
	      file->device->net->stall = 1;
	      grub_net_tcp_stall (data->sock);
	    }

	  grub_net_put_packet (&file->device->net->packs, nb2);
	  grub_netbuff_pull (nb, data->chunk_rem);
	}
      data->in_chunk_len = 1;
    }
}
Example #16
0
/*
 * Analyze the string to see how many parameters we need from the varargs list,
 * and what their types are.  We will only accept string parameters if they
 * appear as a %l or %s format following an explicit parameter reference (e.g.,
 * %p2%s).  All other parameters are numbers.
 *
 * 'number' counts coarsely the number of pop's we see in the string, and
 * 'popcount' shows the highest parameter number in the string.  We would like
 * to simply use the latter count, but if we are reading termcap strings, there
 * may be cases that we cannot see the explicit parameter numbers.
 */
static inline int
analyze(const char *string, char *p_is_s[NUM_PARM], int *popcount)
{
    grub_size_t len2;
    int i;
    int lastpop = -1;
    int len;
    int number = 0;
    const char *cp = string;
    static char dummy[] = "";

    *popcount = 0;

    if (cp == 0)
	return 0;

    if ((len2 = grub_strlen(cp)) > fmt_size) {
	fmt_size = len2 + fmt_size + 2;
	if ((fmt_buff = grub_realloc(fmt_buff, fmt_size*sizeof(char))) == 0)
	      return 0;
    }

    grub_memset(p_is_s, 0, sizeof(p_is_s[0]) * NUM_PARM);

    while ((cp - string) < (int) len2) {
	if (*cp == '%') {
	    cp++;
	    cp = parse_format(cp, fmt_buff, &len);
	    switch (*cp) {
	    default:
		break;

	    case 'd':		/* FALLTHRU */
	    case 'o':		/* FALLTHRU */
	    case 'x':		/* FALLTHRU */
	    case 'X':		/* FALLTHRU */
	    case 'c':		/* FALLTHRU */
		if (lastpop <= 0)
		    number++;
		lastpop = -1;
		break;

	    case 'l':
	    case 's':
		if (lastpop > 0)
		    p_is_s[lastpop - 1] = dummy;
		++number;
		break;

	    case 'p':
		cp++;
		i = (UChar(*cp) - '0');
		if (i >= 0 && i <= NUM_PARM) {
		    lastpop = i;
		    if (lastpop > *popcount)
			*popcount = lastpop;
		}
		break;

	    case 'P':
		++number;
		++cp;
		break;

	    case 'g':
		cp++;
		break;

	    case '\'':
		cp += 2;
		lastpop = -1;
		break;

	    case '{':
		cp++;
		while (isdigit(UChar(*cp))) {
		    cp++;
		}
		break;

	    case '+':
	    case '-':
	    case '*':
	    case '/':
	    case 'm':
	    case 'A':
	    case 'O':
	    case '&':
	    case '|':
	    case '^':
	    case '=':
	    case '<':
	    case '>':
		lastpop = -1;
		number += 2;
		break;

	    case '!':
	    case '~':
		lastpop = -1;
		++number;
		break;

	    case 'i':
		/* will add 1 to first (usually two) parameters */
		break;
	    }
	}
	if (*cp != '\0')
	    cp++;
    }

    if (number > NUM_PARM)
	number = NUM_PARM;
    return number;
}
Example #17
0
File: ldm.c Project: flihp/grub2
static struct grub_diskfilter_vg *
make_vg (grub_disk_t disk,
	 const struct grub_ldm_label *label)
{
  grub_disk_addr_t startsec, endsec, cursec;
  struct grub_diskfilter_vg *vg;
  grub_err_t err;

  /* First time we see this volume group. We've to create the
     whole volume group structure. */
  vg = grub_malloc (sizeof (*vg));
  if (! vg)
    return NULL;
  vg->extent_size = 1;
  vg->name = grub_malloc (LDM_NAME_STRLEN + 1);
  vg->uuid = grub_malloc (LDM_GUID_STRLEN + 1);
  if (! vg->uuid || !vg->name)
    {
      grub_free (vg->uuid);
      grub_free (vg->name);
      return NULL;
    }
  grub_memcpy (vg->uuid, label->group_guid, LDM_GUID_STRLEN);
  grub_memcpy (vg->name, label->group_name, LDM_NAME_STRLEN);
  vg->name[LDM_NAME_STRLEN] = 0;
  vg->uuid[LDM_GUID_STRLEN] = 0;
  vg->uuid_len = grub_strlen (vg->uuid);

  vg->lvs = NULL;
  vg->pvs = NULL;

  startsec = grub_be_to_cpu64 (label->config_start);
  endsec = startsec + grub_be_to_cpu64 (label->config_size);

  /* First find disks.  */
  for (cursec = startsec + 0x12; cursec < endsec; cursec++)
    {
      struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE
				/ sizeof (struct grub_ldm_vblk)];
      unsigned i;
      err = grub_disk_read (disk, cursec, 0,
			    sizeof(vblk), &vblk);
      if (err)
	goto fail2;

      for (i = 0; i < ARRAY_SIZE (vblk); i++)
	{
	  struct grub_diskfilter_pv *pv;
	  grub_uint8_t *ptr;
	  if (grub_memcmp (vblk[i].magic, LDM_VBLK_MAGIC,
			   sizeof (vblk[i].magic)) != 0)
	    continue;
	  if (grub_be_to_cpu16 (vblk[i].update_status)
	      != STATUS_CONSISTENT
	      && grub_be_to_cpu16 (vblk[i].update_status)
	      != STATUS_STILL_ACTIVE)
	    continue;
	  if (vblk[i].type != ENTRY_DISK)
	    continue;
	  pv = grub_zalloc (sizeof (*pv));
	  if (!pv)
	    goto fail2;

	  pv->disk = 0;
	  ptr = vblk[i].dynamic;
	  if (ptr + *ptr + 1 >= vblk[i].dynamic
	      + sizeof (vblk[i].dynamic))
	    {
	      grub_free (pv);
	      goto fail2;
	    }
	  pv->internal_id = grub_malloc (ptr[0] + 2);
	  if (!pv->internal_id)
	    {
	      grub_free (pv);
	      goto fail2;
	    }
	  grub_memcpy (pv->internal_id, ptr, (grub_size_t) ptr[0] + 1);
	  pv->internal_id[(grub_size_t) ptr[0] + 1] = 0;
	  
	  ptr += *ptr + 1;
	  if (ptr + *ptr + 1 >= vblk[i].dynamic
	      + sizeof (vblk[i].dynamic))
	    {
	      grub_free (pv);
	      goto fail2;
	    }
	  /* ptr = name.  */
	  ptr += *ptr + 1;
	  if (ptr + *ptr + 1
	      >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      grub_free (pv);
	      goto fail2;
	    }
	  pv->id.uuidlen = *ptr;
	  pv->id.uuid = grub_malloc (pv->id.uuidlen + 1);
	  grub_memcpy (pv->id.uuid, ptr + 1, pv->id.uuidlen);
	  pv->id.uuid[pv->id.uuidlen] = 0;

	  pv->next = vg->pvs;
	  vg->pvs = pv;
	}
    }

  /* Then find LVs.  */
  for (cursec = startsec + 0x12; cursec < endsec; cursec++)
    {
      struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE
				/ sizeof (struct grub_ldm_vblk)];
      unsigned i;
      err = grub_disk_read (disk, cursec, 0,
			    sizeof(vblk), &vblk);
      if (err)
	goto fail2;

      for (i = 0; i < ARRAY_SIZE (vblk); i++)
	{
	  struct grub_diskfilter_lv *lv;
	  grub_uint8_t *ptr;
	  if (grub_memcmp (vblk[i].magic, LDM_VBLK_MAGIC,
			   sizeof (vblk[i].magic)) != 0)
	    continue;
	  if (grub_be_to_cpu16 (vblk[i].update_status)
	      != STATUS_CONSISTENT
	      && grub_be_to_cpu16 (vblk[i].update_status)
	      != STATUS_STILL_ACTIVE)
	    continue;
	  if (vblk[i].type != ENTRY_VOLUME)
	    continue;
	  lv = grub_zalloc (sizeof (*lv));
	  if (!lv)
	    goto fail2;

	  lv->vg = vg;
	  lv->segment_count = 1;
	  lv->segment_alloc = 1;
	  lv->visible = 1;
	  lv->segments = grub_zalloc (sizeof (*lv->segments));
	  if (!lv->segments)
	    goto fail2;
	  lv->segments->start_extent = 0;
	  lv->segments->type = GRUB_DISKFILTER_MIRROR;
	  lv->segments->node_count = 0;
	  lv->segments->node_alloc = 8;
	  lv->segments->nodes = grub_zalloc (sizeof (*lv->segments->nodes)
					     * lv->segments->node_alloc);
	  if (!lv->segments->nodes)
	    goto fail2;
	  ptr = vblk[i].dynamic;
	  if (ptr + *ptr + 1 >= vblk[i].dynamic
	      + sizeof (vblk[i].dynamic))
	    {
	      grub_free (lv);
	      goto fail2;
	    }
	  lv->internal_id = grub_malloc ((grub_size_t) ptr[0] + 2);
	  if (!lv->internal_id)
	    {
	      grub_free (lv);
	      goto fail2;
	    }
	  grub_memcpy (lv->internal_id, ptr, ptr[0] + 1);
	  lv->internal_id[ptr[0] + 1] = 0;

	  ptr += *ptr + 1;
	  if (ptr + *ptr + 1 >= vblk[i].dynamic
	      + sizeof (vblk[i].dynamic))
	    {
	      grub_free (lv);
	      goto fail2;
	    }
	  lv->name = grub_malloc (*ptr + 1);
	  if (!lv->name)
	    {
	      grub_free (lv->internal_id);
	      grub_free (lv);
	      goto fail2;
	    }
	  grub_memcpy (lv->name, ptr + 1, *ptr);
	  lv->name[*ptr] = 0;
	  lv->fullname = grub_xasprintf ("ldm/%s/%s",
					 vg->uuid, lv->name);
	  if (!lv->fullname)
	    {
	      grub_free (lv->internal_id);
	      grub_free (lv->name);
	      grub_free (lv);
	      goto fail2;
	    }
	  ptr += *ptr + 1;
	  if (ptr + *ptr + 1
	      >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      grub_free (lv->internal_id);
	      grub_free (lv->name);
	      grub_free (lv);
	      goto fail2;
	    }
	  /* ptr = volume type.  */
	  ptr += *ptr + 1;
	  if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      grub_free (lv->internal_id);
	      grub_free (lv->name);
	      grub_free (lv);
	      goto fail2;
	    }
	  /* ptr = flags.  */
	  ptr += *ptr + 1;
	  if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      grub_free (lv->internal_id);
	      grub_free (lv->name);
	      grub_free (lv);
	      goto fail2;
	    }

	  /* Skip state, type, unknown, volume number, zeros, flags. */
	  ptr += 14 + 1 + 1 + 1 + 3 + 1;
	  /* ptr = number of children.  */
	  if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      grub_free (lv->internal_id);
	      grub_free (lv->name);
	      grub_free (lv);
	      goto fail2;
	    }
	  ptr += *ptr + 1;
	  if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      grub_free (lv->internal_id);
	      grub_free (lv->name);
	      grub_free (lv);
	      goto fail2;
	    }

	  /* Skip 2 more fields.  */
	  ptr += 8 + 8;
	  if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)
	      || ptr + *ptr + 1>= vblk[i].dynamic
	      + sizeof (vblk[i].dynamic))
	    {
	      grub_free (lv->internal_id);
	      grub_free (lv->name);
	      grub_free (lv);
	      goto fail2;
	    }
	  lv->size = read_int (ptr + 1, *ptr);
	  lv->segments->extent_count = lv->size;

	  lv->next = vg->lvs;
	  vg->lvs = lv;
	}
    }

  /* Now the components.  */
  for (cursec = startsec + 0x12; cursec < endsec; cursec++)
    {
      struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE
				/ sizeof (struct grub_ldm_vblk)];
      unsigned i;
      err = grub_disk_read (disk, cursec, 0,
			    sizeof(vblk), &vblk);
      if (err)
	goto fail2;

      for (i = 0; i < ARRAY_SIZE (vblk); i++)
	{
	  struct grub_diskfilter_lv *comp;
	  struct grub_diskfilter_lv *lv;
	  grub_uint8_t type;

	  grub_uint8_t *ptr;
	  if (grub_memcmp (vblk[i].magic, LDM_VBLK_MAGIC,
			   sizeof (vblk[i].magic)) != 0)
	    continue;
	  if (grub_be_to_cpu16 (vblk[i].update_status)
	      != STATUS_CONSISTENT
	      && grub_be_to_cpu16 (vblk[i].update_status)
	      != STATUS_STILL_ACTIVE)
	    continue;
	  if (vblk[i].type != ENTRY_COMPONENT)
	    continue;
	  comp = grub_zalloc (sizeof (*comp));
	  if (!comp)
	    goto fail2;
	  comp->visible = 0;
	  comp->name = 0;
	  comp->fullname = 0;

	  ptr = vblk[i].dynamic;
	  if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      goto fail2;
	    }
	  comp->internal_id = grub_malloc ((grub_size_t) ptr[0] + 2);
	  if (!comp->internal_id)
	    {
	      grub_free (comp);
	      goto fail2;
	    }
	  grub_memcpy (comp->internal_id, ptr, ptr[0] + 1);
	  comp->internal_id[ptr[0] + 1] = 0;

	  ptr += *ptr + 1;
	  if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      grub_free (comp->internal_id);
	      grub_free (comp);
	      goto fail2;
	    }
	  /* ptr = name.  */
	  ptr += *ptr + 1;
	  if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      grub_free (comp->internal_id);
	      grub_free (comp);
	      goto fail2;
	    }
	  /* ptr = state.  */
	  ptr += *ptr + 1;
	  type = *ptr++;
	  /* skip zeros.  */
	  ptr += 4;
	  if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      grub_free (comp->internal_id);
	      grub_free (comp);
	      goto fail2;
	    }

	  /* ptr = number of children. */
	  ptr += *ptr + 1;
	  if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      grub_free (comp->internal_id);
	      grub_free (comp);
	      goto fail2;
	    }
	  ptr += 8 + 8;
	  if (ptr + *ptr + 1 >= vblk[i].dynamic
	      + sizeof (vblk[i].dynamic))
	    {
	      grub_free (comp->internal_id);
	      grub_free (comp);
	      goto fail2;
	    }
	  for (lv = vg->lvs; lv; lv = lv->next)
	    {
	      if (lv->internal_id[0] == ptr[0]
		  && grub_memcmp (lv->internal_id + 1, ptr + 1, ptr[0]) == 0)
		break;
	    }
	  if (!lv)
	    {
	      grub_free (comp->internal_id);
	      grub_free (comp);
	      continue;
	    }
	  comp->size = lv->size;
	  if (type == SPANNED)
	    {
	      comp->segment_alloc = 8;
	      comp->segment_count = 0;
	      comp->segments = grub_malloc (sizeof (*comp->segments)
					    * comp->segment_alloc);
	      if (!comp->segments)
		goto fail2;
	    }
	  else
	    {
	      comp->segment_alloc = 1;
	      comp->segment_count = 1;
	      comp->segments = grub_malloc (sizeof (*comp->segments));
	      if (!comp->segments)
		goto fail2;
	      comp->segments->start_extent = 0;
	      comp->segments->extent_count = lv->size;
	      comp->segments->layout = 0;
	      if (type == STRIPE)
		comp->segments->type = GRUB_DISKFILTER_STRIPED;
	      else if (type == RAID5)
		{
		  comp->segments->type = GRUB_DISKFILTER_RAID5;
		  comp->segments->layout = GRUB_RAID_LAYOUT_SYMMETRIC_MASK;
		}
	      else
		goto fail2;
	      ptr += *ptr + 1;
	      ptr++;
	      if (!(vblk[i].flags & 0x10))
		goto fail2;
	      if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)
		  || ptr + *ptr + 1 >= vblk[i].dynamic
		  + sizeof (vblk[i].dynamic))
		{
		  grub_free (comp->internal_id);
		  grub_free (comp);
		  goto fail2;
		}
	      comp->segments->stripe_size = read_int (ptr + 1, *ptr);
	      ptr += *ptr + 1;
	      if (ptr + *ptr + 1 >= vblk[i].dynamic
		  + sizeof (vblk[i].dynamic))
		{
		  grub_free (comp->internal_id);
		  grub_free (comp);
		  goto fail2;
		}
	      comp->segments->node_count = read_int (ptr + 1, *ptr);
	      comp->segments->node_alloc = comp->segments->node_count;
	      comp->segments->nodes = grub_zalloc (sizeof (*comp->segments->nodes)
						   * comp->segments->node_alloc);
	      if (!lv->segments->nodes)
		goto fail2;
	    }

	  if (lv->segments->node_alloc == lv->segments->node_count)
	    {
	      void *t;
	      lv->segments->node_alloc *= 2; 
	      t = grub_realloc (lv->segments->nodes,
				sizeof (*lv->segments->nodes)
				* lv->segments->node_alloc);
	      if (!t)
		goto fail2;
	      lv->segments->nodes = t;
	    }
	  lv->segments->nodes[lv->segments->node_count].pv = 0;
	  lv->segments->nodes[lv->segments->node_count].start = 0;
	  lv->segments->nodes[lv->segments->node_count++].lv = comp;
	  comp->next = vg->lvs;
	  vg->lvs = comp;
	}
    }
  /* Partitions.  */
  for (cursec = startsec + 0x12; cursec < endsec; cursec++)
    {
      struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE
				/ sizeof (struct grub_ldm_vblk)];
      unsigned i;
      err = grub_disk_read (disk, cursec, 0,
			    sizeof(vblk), &vblk);
      if (err)
	goto fail2;

      for (i = 0; i < ARRAY_SIZE (vblk); i++)
	{
	  struct grub_diskfilter_lv *comp;
	  struct grub_diskfilter_node part;
	  grub_disk_addr_t start, size;

	  grub_uint8_t *ptr;
	  part.name = 0;
	  if (grub_memcmp (vblk[i].magic, LDM_VBLK_MAGIC,
			   sizeof (vblk[i].magic)) != 0)
	    continue;
	  if (grub_be_to_cpu16 (vblk[i].update_status)
	      != STATUS_CONSISTENT
	      && grub_be_to_cpu16 (vblk[i].update_status)
	      != STATUS_STILL_ACTIVE)
	    continue;
	  if (vblk[i].type != ENTRY_PARTITION)
	    continue;
	  part.lv = 0;
	  part.pv = 0;

	  ptr = vblk[i].dynamic;
	  if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      goto fail2;
	    }
	  /* ID */
	  ptr += *ptr + 1;
	  if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      goto fail2;
	    }
	  /* ptr = name.  */
	  ptr += *ptr + 1;
	  if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      goto fail2;
	    }

	  /* skip zeros and logcommit id.  */
	  ptr += 4 + 8;
	  if (ptr + 16 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      goto fail2;
	    }
	  part.start = read_int (ptr, 8);
	  start = read_int (ptr + 8, 8);
	  ptr += 16;
	  if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)
	      || ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      goto fail2;
	    }
	  size = read_int (ptr + 1, *ptr);
	  ptr += *ptr + 1;
	  if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)
	      || ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      goto fail2;
	    }

	  for (comp = vg->lvs; comp; comp = comp->next)
	    if (comp->internal_id[0] == ptr[0]
		&& grub_memcmp (ptr + 1, comp->internal_id + 1,
				comp->internal_id[0]) == 0)
	      goto out;
	  continue;
	out:
	  if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)
	      || ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      goto fail2;
	    }
	  ptr += *ptr + 1;
	  struct grub_diskfilter_pv *pv;
	  for (pv = vg->pvs; pv; pv = pv->next)
	    if (pv->internal_id[0] == ptr[0]
		&& grub_memcmp (pv->internal_id + 1, ptr + 1, ptr[0]) == 0)
	      part.pv = pv;

	  if (comp->segment_alloc == 1)
	    {
	      unsigned node_index;
	      ptr += *ptr + 1;
	      if (ptr + *ptr + 1 >= vblk[i].dynamic
		  + sizeof (vblk[i].dynamic))
		{
		  goto fail2;
		}
	      node_index = read_int (ptr + 1, *ptr);
	      if (node_index < comp->segments->node_count)
		comp->segments->nodes[node_index] = part;
	    }
	  else
	    {
	      if (comp->segment_alloc == comp->segment_count)
		{
		  void *t;
		  comp->segment_alloc *= 2;
		  t = grub_realloc (comp->segments,
				    comp->segment_alloc
				    * sizeof (*comp->segments));
		  if (!t)
		    goto fail2;
		  comp->segments = t;
		}
	      comp->segments[comp->segment_count].start_extent = start;
	      comp->segments[comp->segment_count].extent_count = size;
	      comp->segments[comp->segment_count].type = GRUB_DISKFILTER_STRIPED;
	      comp->segments[comp->segment_count].node_count = 1;
	      comp->segments[comp->segment_count].node_alloc = 1;
	      comp->segments[comp->segment_count].nodes
		= grub_malloc (sizeof (*comp->segments[comp->segment_count].nodes));
	      if (!comp->segments[comp->segment_count].nodes)
		goto fail2;
	      comp->segments[comp->segment_count].nodes[0] = part;
	      comp->segment_count++;
	    }
	}
    }
  if (grub_diskfilter_vg_register (vg))
    goto fail2;
  return vg;
 fail2:
  {
    struct grub_diskfilter_lv *lv, *next_lv;
    struct grub_diskfilter_pv *pv, *next_pv;
    for (lv = vg->lvs; lv; lv = next_lv)
      {
	unsigned i;
	for (i = 0; i < lv->segment_count; i++)
	  grub_free (lv->segments[i].nodes);

	next_lv = lv->next;
	grub_free (lv->segments);
	grub_free (lv->internal_id);
	grub_free (lv->name);
	grub_free (lv->fullname);
	grub_free (lv);
      }
    for (pv = vg->pvs; pv; pv = next_pv)
      {
	next_pv = pv->next;
	grub_free (pv->id.uuid);
	grub_free (pv);
      }
  }
  grub_free (vg->uuid);
  grub_free (vg);
  return NULL;
}
Example #18
0
static int
grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
			  grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
{
  struct grub_iso9660_dir dirent;
  grub_off_t offset = 0;
  grub_off_t len;
  struct iterate_dir_ctx ctx;

  len = get_node_size (dir);

  for (; offset < len; offset += dirent.len)
    {
      ctx.symlink = 0;
      ctx.was_continue = 0;

      if (read_node (dir, offset, sizeof (dirent), (char *) &dirent))
	return 0;

      /* The end of the block, skip to the next one.  */
      if (!dirent.len)
	{
	  offset = (offset / GRUB_ISO9660_BLKSZ + 1) * GRUB_ISO9660_BLKSZ;
	  continue;
	}

      {
	char name[MAX_NAMELEN + 1];
	int nameoffset = offset + sizeof (dirent);
	struct grub_fshelp_node *node;
	int sua_off = (sizeof (dirent) + dirent.namelen + 1
		       - (dirent.namelen % 2));
	int sua_size = dirent.len - sua_off;

	sua_off += offset + dir->data->susp_skip;

	ctx.filename = 0;
	ctx.filename_alloc = 0;
	ctx.type = GRUB_FSHELP_UNKNOWN;

	if (dir->data->rockridge
	    && grub_iso9660_susp_iterate (dir, sua_off, sua_size,
					  susp_iterate_dir, &ctx))
	  return 0;

	/* Read the name.  */
	if (read_node (dir, nameoffset, dirent.namelen, (char *) name))
	  return 0;

	node = grub_malloc (sizeof (struct grub_fshelp_node));
	if (!node)
	  return 0;

	node->alloc_dirents = ARRAY_SIZE (node->dirents);
	node->have_dirents = 1;

	/* Setup a new node.  */
	node->data = dir->data;
	node->have_symlink = 0;

	/* If the filetype was not stored using rockridge, use
	   whatever is stored in the iso9660 filesystem.  */
	if (ctx.type == GRUB_FSHELP_UNKNOWN)
	  {
	    if ((dirent.flags & FLAG_TYPE) == FLAG_TYPE_DIR)
	      ctx.type = GRUB_FSHELP_DIR;
	    else
	      ctx.type = GRUB_FSHELP_REG;
	  }

	/* . and .. */
	if (!ctx.filename && dirent.namelen == 1 && name[0] == 0)
	  ctx.filename = (char *) ".";

	if (!ctx.filename && dirent.namelen == 1 && name[0] == 1)
	  ctx.filename = (char *) "..";

	/* The filename was not stored in a rock ridge entry.  Read it
	   from the iso9660 filesystem.  */
	if (!dir->data->joliet && !ctx.filename)
	  {
	    char *ptr;
	    name[dirent.namelen] = '\0';
	    ctx.filename = grub_strrchr (name, ';');
	    if (ctx.filename)
	      *ctx.filename = '\0';
	    /* ISO9660 names are not case-preserving.  */
	    ctx.type |= GRUB_FSHELP_CASE_INSENSITIVE;
	    for (ptr = name; *ptr; ptr++)
	      *ptr = grub_tolower (*ptr);
	    if (ptr != name && *(ptr - 1) == '.')
	      *(ptr - 1) = 0;
	    ctx.filename = name;
	  }

        if (dir->data->joliet && !ctx.filename)
          {
            char *semicolon;

            ctx.filename = grub_iso9660_convert_string
                  ((grub_uint8_t *) name, dirent.namelen >> 1);

	    semicolon = grub_strrchr (ctx.filename, ';');
	    if (semicolon)
	      *semicolon = '\0';

            ctx.filename_alloc = 1;
          }

	node->dirents[0] = dirent;
	while (dirent.flags & FLAG_MORE_EXTENTS)
	  {
	    offset += dirent.len;
	    if (read_node (dir, offset, sizeof (dirent), (char *) &dirent))
	      {
		if (ctx.filename_alloc)
		  grub_free (ctx.filename);
		grub_free (node);
		return 0;
	      }
	    if (node->have_dirents >= node->alloc_dirents)
	      {
		struct grub_fshelp_node *new_node;
		node->alloc_dirents *= 2;
		new_node = grub_realloc (node, 
					 sizeof (struct grub_fshelp_node)
					 + ((node->alloc_dirents
					     - ARRAY_SIZE (node->dirents))
					    * sizeof (node->dirents[0])));
		if (!new_node)
		  {
		    if (ctx.filename_alloc)
		      grub_free (ctx.filename);
		    grub_free (node);
		    return 0;
		  }
		node = new_node;
	      }
	    node->dirents[node->have_dirents++] = dirent;
	  }
	if (ctx.symlink)
	  {
	    if ((node->alloc_dirents - node->have_dirents)
		* sizeof (node->dirents[0]) < grub_strlen (ctx.symlink) + 1)
	      {
		struct grub_fshelp_node *new_node;
		new_node = grub_realloc (node,
					 sizeof (struct grub_fshelp_node)
					 + ((node->alloc_dirents
					     - ARRAY_SIZE (node->dirents))
					    * sizeof (node->dirents[0]))
					 + grub_strlen (ctx.symlink) + 1);
		if (!new_node)
		  {
		    if (ctx.filename_alloc)
		      grub_free (ctx.filename);
		    grub_free (node);
		    return 0;
		  }
		node = new_node;
	      }
	    node->have_symlink = 1;
	    grub_strcpy (node->symlink
			 + node->have_dirents * sizeof (node->dirents[0])
			 - sizeof (node->dirents), ctx.symlink);
	    grub_free (ctx.symlink);
	    ctx.symlink = 0;
	    ctx.was_continue = 0;
	  }
	if (hook (ctx.filename, ctx.type, node, hook_data))
	  {
	    if (ctx.filename_alloc)
	      grub_free (ctx.filename);
	    return 1;
	  }
	if (ctx.filename_alloc)
	  grub_free (ctx.filename);
      }
    }
Example #19
0
static grub_err_t
susp_iterate_dir (struct grub_iso9660_susp_entry *entry,
		  void *_ctx)
{
  struct iterate_dir_ctx *ctx = _ctx;

  /* The filename in the rock ridge entry.  */
  if (grub_strncmp ("NM", (char *) entry->sig, 2) == 0)
    {
      /* The flags are stored at the data position 0, here the
	 filename type is stored.  */
      /* FIXME: Fix this slightly improper cast.  */
      if (entry->data[0] & GRUB_ISO9660_RR_DOT)
	ctx->filename = (char *) ".";
      else if (entry->data[0] & GRUB_ISO9660_RR_DOTDOT)
	ctx->filename = (char *) "..";
      else if (entry->len >= 5)
	{
	  grub_size_t off = 0, csize = 1;
	  char *old;
	  csize = entry->len - 5;
	  old = ctx->filename;
	  if (ctx->filename_alloc)
	    {
	      off = grub_strlen (ctx->filename);
	      ctx->filename = grub_realloc (ctx->filename, csize + off + 1);
	    }
	  else
	    {
	      off = 0;
	      ctx->filename = grub_zalloc (csize + 1);
	    }
	  if (!ctx->filename)
	    {
	      ctx->filename = old;
	      return grub_errno;
	    }
	  ctx->filename_alloc = 1;
	  grub_memcpy (ctx->filename + off, (char *) &entry->data[1], csize);
	  ctx->filename[off + csize] = '\0';
	}
    }
  /* The mode information (st_mode).  */
  else if (grub_strncmp ((char *) entry->sig, "PX", 2) == 0)
    {
      /* At position 0 of the PX record the st_mode information is
	 stored (little-endian).  */
      grub_uint32_t mode = ((entry->data[0] + (entry->data[1] << 8))
			    & GRUB_ISO9660_FSTYPE_MASK);

      switch (mode)
	{
	case GRUB_ISO9660_FSTYPE_DIR:
	  ctx->type = GRUB_FSHELP_DIR;
	  break;
	case GRUB_ISO9660_FSTYPE_REG:
	  ctx->type = GRUB_FSHELP_REG;
	  break;
	case GRUB_ISO9660_FSTYPE_SYMLINK:
	  ctx->type = GRUB_FSHELP_SYMLINK;
	  break;
	default:
	  ctx->type = GRUB_FSHELP_UNKNOWN;
	}
    }
  else if (grub_strncmp ("SL", (char *) entry->sig, 2) == 0)
    {
      unsigned int pos = 1;

      /* The symlink is not stored as a POSIX symlink, translate it.  */
      while (pos + sizeof (*entry) < entry->len)
	{
	  /* The current position is the `Component Flag'.  */
	  switch (entry->data[pos] & 30)
	    {
	    case 0:
	      {
		/* The data on pos + 2 is the actual data, pos + 1
		   is the length.  Both are part of the `Component
		   Record'.  */
		if (ctx->symlink && !ctx->was_continue)
		  add_part (ctx, "/", 1);
		add_part (ctx, (char *) &entry->data[pos + 2],
			  entry->data[pos + 1]);
		ctx->was_continue = (entry->data[pos] & 1);
		break;
	      }

	    case 2:
	      add_part (ctx, "./", 2);
	      break;

	    case 4:
	      add_part (ctx, "../", 3);
	      break;

	    case 8:
	      add_part (ctx, "/", 1);
	      break;
	    }
	  /* In pos + 1 the length of the `Component Record' is
	     stored.  */
	  pos += entry->data[pos + 1] + 2;
	}

      /* Check if `grub_realloc' failed.  */
      if (grub_errno)
	return grub_errno;
    }

  return 0;
}
Example #20
0
static grub_err_t
interactive (void)
{
  const char *ps1 = "lua> ";
  const char *ps2 = "lua>> ";
  const char *prompt = ps1;
  char *line;
  char *chunk = NULL;
  size_t len;
  size_t oldlen = 0;
  int r;

  grub_printf ("%s", N_ ("Welcome to lua, press the escape key to exit."));

  while ((line = grub_cmdline_get (prompt)) != NULL)
    {
      /* len = lenght of chunk + line + newline character */
      len = oldlen + grub_strlen (line) + 1;
      chunk = grub_realloc (chunk, len + 1);
      grub_strcpy (chunk + oldlen , line);
      chunk[len - 1] = '\n';
      chunk[len] = '\0';
      grub_free (line);

      r = luaL_loadbuffer (state, chunk, len, "stdin");
      if (!r)
	{
	  /* No error: Execute this chunk and prepare to read another */
	  r = lua_pcall (state, 0, 0, 0);
	  if (r)
	    {
	      handle_lua_error ("Lua");
	      grub_print_error ();
	    }

	  grub_free (chunk);
	  chunk = NULL;
	  len = 0;
	  prompt = ps1;
	}
      else if (incomplete (state, r))
	{
	  /* Chunk is incomplete, try reading another line */
	  prompt = ps2;
	}
      else if (r == LUA_ERRSYNTAX)
	{
	  handle_lua_error ("Lua");
	  grub_print_error ();

	  /* This chunk is garbage, try starting another one */
	  grub_free (chunk);
	  chunk = NULL;
	  len = 0;
	  prompt = ps1;
	}
      else
	{
	  /* Handle errors other than syntax errors (out of memory, etc.) */
	  grub_free (chunk);
	  handle_lua_error ("Lua parser failed");
	  return grub_errno;
	}

      oldlen = len;
    }

  grub_free (chunk);
  lua_gc (state, LUA_GCCOLLECT, 0);

  return grub_errno;
}
Example #21
0
/* Read a line from the file FILE.  */
char *
grub_file_getline (grub_file_t file)
{
  char c;
  int pos = 0;
  int literal = 0;
  char *cmdline;
  int max_len = 64;

  /* Initially locate some space.  */
  cmdline = grub_malloc (max_len);
  if (! cmdline)
    return 0;

  while (1)
    {
      if (grub_file_read (file, &c, 1) != 1)
	break;

      /* Skip all carriage returns.  */
      if (c == '\r')
	continue;

      /* Replace tabs with spaces.  */
      if (c == '\t')
	c = ' ';

      /* The previous is a backslash, then...  */
      if (literal)
	{
	  /* If it is a newline, replace it with a space and continue.  */
	  if (c == '\n')
	    {
	      c = ' ';

	      /* Go back to overwrite the backslash.  */
	      if (pos > 0)
		pos--;
	    }

	  literal = 0;
	}

      if (c == '\\')
	literal = 1;

      if (pos == 0)
	{
	  if (! grub_isspace (c))
	    cmdline[pos++] = c;
	}
      else
	{
	  if (pos >= max_len)
	    {
	      char *old_cmdline = cmdline;
	      max_len = max_len * 2;
	      cmdline = grub_realloc (cmdline, max_len);
	      if (! cmdline)
		{
		  grub_free (old_cmdline);
		  return 0;
		}
	    }

	  if (c == '\n')
	    break;

	  cmdline[pos++] = c;
	}
    }

  cmdline[pos] = '\0';

  /* If the buffer is empty, don't return anything at all.  */
  if (pos == 0)
    {
      grub_free (cmdline);
      cmdline = 0;
    }

  return cmdline;
}
Example #22
0
static struct grub_biosdisk_data *
get_drive_geom (int drive)
{
  int i;
  struct grub_biosdisk_data *data = grub_biosdisk_geom;
  grub_uint64_t total_sectors = 0;
  unsigned long cylinders;
  int is_fb = 0;
  struct fb_mbr *m;

  for (i = 0; i < grub_biosdisk_num; i++, data++)
    if (data->drive == drive)
      return data;

  m = (struct fb_mbr *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
  if (drive != cd_drive)
    {
      if (grub_biosdisk_rw_standard (0x02, drive, 0, 0, 1, 1,
				     GRUB_MEMORY_MACHINE_SCRATCH_SEG) != 0)
	return 0;
      is_fb = ((m->fb_magic == FB_MAGIC_LONG) && (m->end_magic == 0xaa55));
    }
  else
    is_fb = 0;

  if ((grub_biosdisk_num & (DISK_NUM_INC - 1)) == 0)
    {
      grub_biosdisk_geom = grub_realloc (grub_biosdisk_geom,
					 (grub_biosdisk_num + DISK_NUM_INC) *
					 sizeof (*data));
      if (! grub_biosdisk_geom)
	return 0;
    }

  data = &grub_biosdisk_geom[grub_biosdisk_num++];
  grub_memset (data, 0, sizeof (*data));
  data->drive = drive;

  if (drive == cd_drive)
    {
      data->flags = GRUB_BIOSDISK_FLAG_LBA | GRUB_BIOSDISK_FLAG_CDROM;
      data->max_sectors = data->sectors = 32;
      data->total_sectors = GRUB_ULONG_MAX;  /* TODO: get the correct size.  */
      return data;
    }

  if (drive & 0x80)
    {
      /* HDD */
      int version;

      version = grub_biosdisk_check_int13_extensions (drive);
      if (version)
	{
	  struct grub_biosdisk_drp *drp
	    = (struct grub_biosdisk_drp *)
	    (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + 512);

	  /* Clear out the DRP.  */
	  grub_memset (drp, 0, sizeof (*drp));
	  drp->size = sizeof (*drp);
	  if (! grub_biosdisk_get_diskinfo_int13_extensions (drive, drp))
	    {
	      data->flags = GRUB_BIOSDISK_FLAG_LBA;

	      if (drp->cylinders == 65535)
		total_sectors = GRUB_ULONG_MAX;
	      else if (drp->total_sectors)
		total_sectors = drp->total_sectors;
	      else
                /* Some buggy BIOSes doesn't return the total sectors
                   correctly but returns zero. So if it is zero, compute
                   it by C/H/S returned by the LBA BIOS call.  */
                total_sectors = drp->cylinders * drp->heads * drp->sectors;
	    }
	}

      data->sectors = 63;
      data->heads = 255;
      cylinders = 0;
      grub_biosdisk_get_diskinfo_standard (drive, &cylinders,
					   &data->heads, &data->sectors);
    }
  else
    {
      grub_uint16_t t;

      t = *((grub_uint16_t *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + 0x18));
      data->sectors = ((t > 0) && (t <= 63)) ? t : 18;
      t = *((grub_uint16_t *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + 0x1a));
      data->heads = ((t > 0) && (t <= 255)) ? t : 2;
      cylinders = 1024;
    }

  data->max_sectors = 63;
  if (is_fb)
    {
      grub_uint16_t ofs = m->lba;

      data->max_sectors = m->max_sec;
      if (data->max_sectors >= 0x80)
	{
	  data->max_sectors &= 0x7f;
	  data->flags &= ~GRUB_BIOSDISK_FLAG_LBA;
	}

      if (! (data->flags & GRUB_BIOSDISK_FLAG_LBA))
	{
	  grub_uint16_t lba;

	  if (grub_biosdisk_rw_standard (0x02, drive,
					 0, 1, 1, 1,
					 GRUB_MEMORY_MACHINE_SCRATCH_SEG))
	    goto next;

	  lba = m->end_magic;
	  if (lba == 0xaa55)
	    {
	      if (m->fb_magic != FB_MAGIC_LONG)
		goto next;
	      else
		lba = m->lba;
	    }

	  data->sectors = lba - ofs;

	  if (grub_biosdisk_rw_standard (0x02, drive,
					 1, 0, 1, 1,
					 GRUB_MEMORY_MACHINE_SCRATCH_SEG))
	    goto next;

	  lba = m->end_magic;
	  if (lba == 0xaa55)
	    goto next;

	  data->heads = (lba - ofs) / data->sectors;
	}

      data->flags |= GRUB_BIOSDISK_FLAG_FB;
    }

  if ((data->flags & GRUB_BIOSDISK_FLAG_LBA) &&
      (data->max_sectors == 63))
    data->max_sectors = GRUB_BIOSDISK_MAX_SECTORS;

 next:
  cylinders *= data->heads * data->sectors;
  if (total_sectors < cylinders)
    total_sectors = cylinders;

  data->total_sectors = total_sectors;
  return data;
}