Esempio n. 1
0
static grub_err_t
grub_cpio_open (grub_file_t file, const char *name_in)
{
  struct grub_cpio_data *data;
  grub_disk_addr_t ofs;
  char *fn;
  char *name = grub_strdup (name_in + 1);
  int symlinknest = 0;

  if (!name)
    return grub_errno;

  canonicalize (name);

  grub_dl_ref (my_mod);

  data = grub_cpio_mount (file->device->disk);
  if (!data)
    {
      grub_free (name);
      return grub_errno;
    }

  data->hofs = 0;
  while (1)
    {
      grub_uint32_t mode;
      int restart;
      
      if (grub_cpio_find_file (data, &fn, NULL, &ofs, &mode))
	goto fail;

      if (!ofs)
	{
	  grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), name_in);
	  break;
	}

      if (handle_symlink (data, fn, &name, mode, &restart))
	{
	  grub_free (fn);
	  goto fail;
	}

      if (restart)
	{
	  ofs = 0;
	  if (++symlinknest == 8)
	    {
	      grub_error (GRUB_ERR_SYMLINK_LOOP,
			  N_("too deep nesting of symlinks"));
	      goto fail;
	    }
	  goto no_match;
	}

      if (grub_strcmp (name, fn) != 0)
	goto no_match;

      file->data = data;
      file->size = data->size;
      grub_free (fn);
      grub_free (name);

      return GRUB_ERR_NONE;

    no_match:

      grub_free (fn);
      data->hofs = ofs;
    }

fail:
#ifdef MODE_USTAR
  grub_free (data->linkname);
#endif
  grub_free (data);
  grub_free (name);

  grub_dl_unref (my_mod);

  return grub_errno;
}
Esempio n. 2
0
static grub_err_t
grub_cpio_dir (grub_device_t device, const char *path_in,
	       int (*hook) (const char *filename,
			    const struct grub_dirhook_info *info))
{
  struct grub_cpio_data *data;
  grub_disk_addr_t ofs;
  char *prev, *name, *path, *ptr;
  grub_size_t len;
  int symlinknest = 0;

  path = grub_strdup (path_in + 1);
  if (!path)
    return grub_errno;
  canonicalize (path);
  for (ptr = path + grub_strlen (path) - 1; ptr >= path && *ptr == '/'; ptr--)
    *ptr = 0;

  grub_dl_ref (my_mod);

  prev = 0;

  data = grub_cpio_mount (device->disk);
  if (!data)
    {
      grub_free (path);
      return grub_errno;
    }

  len = grub_strlen (path);
  data->hofs = 0;
  while (1)
    {
      grub_int32_t mtime;
      grub_uint32_t mode;
      grub_err_t err;

      if (grub_cpio_find_file (data, &name, &mtime, &ofs, &mode))
	goto fail;

      if (!ofs)
	break;

      if (grub_memcmp (path, name, len) == 0
	  && (name[len] == 0 || name[len] == '/' || len == 0))
	{
	  char *p, *n;

	  n = name + len;
	  while (*n == '/')
	    n++;

	  p = grub_strchr (n, '/');
	  if (p)
	    *p = 0;

	  if (((!prev) || (grub_strcmp (prev, name) != 0)) && *n != 0)
	    {
	      struct grub_dirhook_info info;
	      grub_memset (&info, 0, sizeof (info));
	      info.dir = (p != NULL) || ((mode & ATTR_TYPE) == ATTR_DIR);
	      info.mtime = mtime;
	      info.mtimeset = 1;

	      if (hook (n, &info))
		{
		  grub_free (name);
		  goto fail;
		}
	      grub_free (prev);
	      prev = name;
	    }
	  else
	    {
	      int restart = 0;
	      err = handle_symlink (data, name, &path, mode, &restart);
	      grub_free (name);
	      if (err)
		goto fail;
	      if (restart)
		{
		  len = grub_strlen (path);
		  if (++symlinknest == 8)
		    {
		      grub_error (GRUB_ERR_SYMLINK_LOOP,
				  N_("too deep nesting of symlinks"));
		      goto fail;
		    }
		  ofs = 0;
		}
	    }
	}
      else
	grub_free (name);
      data->hofs = ofs;
    }

fail:

  grub_free (path);
  grub_free (prev);
#ifdef MODE_USTAR
  grub_free (data->linkname);
#endif
  grub_free (data);

  grub_dl_unref (my_mod);

  return grub_errno;
}
Esempio n. 3
0
grub_err_t
grub_archelp_open (struct grub_archelp_data *data,
		   struct grub_archelp_ops *arcops,
		   const char *name_in)
{
  char *fn;
  char *name = grub_strdup (name_in + 1);
  int symlinknest = 0;

  if (!name)
    return grub_errno;

  canonicalize (name);

  while (1)
    {
      grub_uint32_t mode;
      grub_int32_t mtime;
      int restart;
      
      if (arcops->find_file (data, &fn, &mtime, &mode))
	goto fail;

      if (mode == GRUB_ARCHELP_ATTR_END)
	{
	  grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), name_in);
	  break;
	}

      canonicalize (fn);

      if (handle_symlink (data, arcops, fn, &name, mode, &restart))
	{
	  grub_free (fn);
	  goto fail;
	}

      if (restart)
	{
	  arcops->rewind (data);
	  if (++symlinknest == 8)
	    {
	      grub_error (GRUB_ERR_SYMLINK_LOOP,
			  N_("too deep nesting of symlinks"));
	      goto fail;
	    }
	  goto no_match;
	}

      if (grub_strcmp (name, fn) != 0)
	goto no_match;

      grub_free (fn);
      grub_free (name);

      return GRUB_ERR_NONE;

    no_match:

      grub_free (fn);
    }

fail:
  grub_free (name);

  return grub_errno;
}
Esempio n. 4
0
static int hash_dir(const char *dirname)
{
	struct bucket_info *bi, *nextbi;
	struct entry_info *ei, *nextei;
	struct dirent *de;
	struct stat st;
	unsigned char idmask[MAX_COLLISIONS / 8];
	int i, n, nextid, buflen, ret = -1;
	const char *pathsep;
	char *buf;
	DIR *d;

	if (access(dirname, R_OK|W_OK|X_OK) != 0) {
		fprintf(stderr,
			"ERROR: Access denied '%s'\n",
			dirname);
		return -1;
	}

	buflen = strlen(dirname);
	pathsep = (buflen && dirname[buflen-1] == '/') ? "" : "/";
	buflen += NAME_MAX + 2;
	buf = malloc(buflen);
	if (buf == NULL)
		goto err;

	if (do_verbose) printf("Doing %s\n", dirname);
	d = opendir(dirname);
	if (!d) goto err;

	while ((de = readdir(d)) != NULL) {
		if (snprintf(buf, buflen, "%s%s%s", dirname, pathsep, de->d_name) >= buflen)
			continue;
		if (lstat(buf, &st) < 0)
			continue;
		if (S_ISLNK(st.st_mode) && handle_symlink(de->d_name, buf) == 0)
			continue;
		handle_certificate(de->d_name, buf);
	}
	closedir(d);

	for (i = 0; i < countof(hash_table); i++) {
		for (bi = hash_table[i]; bi; bi = nextbi) {
			nextbi = bi->next;
			DEBUG("Type %d, hash %08x, num entries %d:\n", bi->type, bi->hash, bi->num_needed);

			nextid = 0;
			memset(idmask, 0, (bi->num_needed+7)/8);
			for (ei = bi->first_entry; ei; ei = ei->next)
				if (ei->old_id < bi->num_needed)
					bit_set(idmask, ei->old_id);

			for (ei = bi->first_entry; ei; ei = nextei) {
				nextei = ei->next;
				DEBUG("\t(old_id %d, need_symlink %d) Cert %s\n",
					ei->old_id, ei->need_symlink,
					ei->filename);

				if (ei->old_id < bi->num_needed) {
					/* Link exists, and is used as-is */
					snprintf(buf, buflen, "%08x.%s%d", bi->hash, symlink_extensions[bi->type], ei->old_id);
					if (do_verbose) printf("link %s -> %s\n", ei->filename, buf);
				} else if (ei->need_symlink) {
					/* New link needed (it may replace something) */
					while (bit_isset(idmask, nextid))
						nextid++;

					snprintf(buf, buflen, "%s%s%n%08x.%s%d",
						 dirname, pathsep, &n, bi->hash,
						 symlink_extensions[bi->type],
						 nextid);
					if (do_verbose) printf("link %s -> %s\n", ei->filename, &buf[n]);
					unlink(buf);
					symlink(ei->filename, buf);
				} else if (do_remove_links) {
					/* Link to be deleted */
					snprintf(buf, buflen, "%s%s%n%08x.%s%d",
						 dirname, pathsep, &n, bi->hash,
						 symlink_extensions[bi->type],
						 ei->old_id);
					if (do_verbose) printf("unlink %s\n", &buf[n]);
					unlink(buf);
				}
				free(ei->filename);
				free(ei);
			}
			free(bi);
		}
		hash_table[i] = NULL;
	}

	ret = 0;
err:
	free(buf);
	return ret;
}
Esempio n. 5
0
grub_err_t
grub_archelp_dir (struct grub_archelp_data *data,
		  struct grub_archelp_ops *arcops,
		  const char *path_in,
		  grub_fs_dir_hook_t hook, void *hook_data)
{
  char *prev, *name, *path, *ptr;
  grub_size_t len;
  int symlinknest = 0;

  path = grub_strdup (path_in + 1);
  if (!path)
    return grub_errno;
  canonicalize (path);
  for (ptr = path + grub_strlen (path) - 1; ptr >= path && *ptr == '/'; ptr--)
    *ptr = 0;

  prev = 0;

  len = grub_strlen (path);
  while (1)
    {
      grub_int32_t mtime;
      grub_uint32_t mode;
      grub_err_t err;

      if (arcops->find_file (data, &name, &mtime, &mode))
	goto fail;

      if (mode == GRUB_ARCHELP_ATTR_END)
	break;

      canonicalize (name);

      if (grub_memcmp (path, name, len) == 0
	  && (name[len] == 0 || name[len] == '/' || len == 0))
	{
	  char *p, *n;

	  n = name + len;
	  while (*n == '/')
	    n++;

	  p = grub_strchr (n, '/');
	  if (p)
	    *p = 0;

	  if (((!prev) || (grub_strcmp (prev, name) != 0)) && *n != 0)
	    {
	      struct grub_dirhook_info info;
	      grub_memset (&info, 0, sizeof (info));
	      info.dir = (p != NULL) || ((mode & GRUB_ARCHELP_ATTR_TYPE)
					 == GRUB_ARCHELP_ATTR_DIR);
	      info.symlink = (p != NULL) || ((mode & GRUB_ARCHELP_ATTR_TYPE)
					 == GRUB_ARCHELP_ATTR_LNK);
	      if (!(mode & GRUB_ARCHELP_ATTR_NOTIME))
		{
		  info.mtime = mtime;
		  info.mtimeset = 1;
		}
	      if (hook (n, &info, hook_data))
		{
		  grub_free (name);
		  goto fail;
		}
	      grub_free (prev);
	      prev = name;
	    }
	  else
	    {
	      int restart = 0;
	      err = handle_symlink (data, arcops, name,
				    &path, mode, &restart);
	      grub_free (name);
	      if (err)
		goto fail;
	      if (restart)
		{
		  len = grub_strlen (path);
		  if (++symlinknest == 8)
		    {
		      grub_error (GRUB_ERR_SYMLINK_LOOP,
				  N_("too deep nesting of symlinks"));
		      goto fail;
		    }
		  arcops->rewind (data);
		}
	    }
	}
      else
	grub_free (name);
    }

fail:

  grub_free (path);
  grub_free (prev);

  return grub_errno;
}