예제 #1
0
파일: btrfs.c 프로젝트: kissthink/os-grub2
static grub_device_t
find_device (struct grub_btrfs_data *data, grub_uint64_t id,
	     int do_rescan)
{
  grub_device_t dev_found = NULL;
  auto int hook (const char *name);
  int hook (const char *name)
  {
    grub_device_t dev;
    grub_err_t err;
    struct grub_btrfs_superblock sb;
    dev = grub_device_open (name);
    if (!dev)
      return 0;
    if (!dev->disk)
      {
	grub_device_close (dev);
	return 0;
      }
    err = read_sblock (dev->disk, &sb);
    if (err == GRUB_ERR_BAD_FS)
      {
	grub_device_close (dev);
	grub_errno = GRUB_ERR_NONE;
	return 0;
      }
    if (err)
      {
	grub_device_close (dev);
	grub_print_error ();
	return 0;
      }
    if (grub_memcmp (data->sblock.uuid, sb.uuid, sizeof (sb.uuid)) != 0
	|| sb.this_device.device_id != id)
      {
	grub_device_close (dev);
	return 0;
      }
    
    dev_found = dev;
    return 1;
  }
예제 #2
0
파일: ext2fs.c 프로젝트: ryo/netbsd-src
/*
 * Open a file.
 */
__compactcall int
ext2fs_open(const char *path, struct open_file *f)
{
#ifndef LIBSA_FS_SINGLECOMPONENT
	const char *cp, *ncp;
	int c;
#endif
	ino32_t inumber;
	struct file *fp;
	struct m_ext2fs *fs;
	int rc;
#ifndef LIBSA_NO_FS_SYMLINK
	ino32_t parent_inumber;
	int nlinks = 0;
	char namebuf[MAXPATHLEN+1];
	char *buf;
#endif

	/* allocate file system specific data structure */
	fp = alloc(sizeof(struct file));
	memset(fp, 0, sizeof(struct file));
	f->f_fsdata = (void *)fp;

	/* allocate space and read super block */
	fs = alloc(sizeof(*fs));
	memset(fs, 0, sizeof(*fs));
	fp->f_fs = fs;
	twiddle();

	rc = read_sblock(f, fs);
	if (rc)
		goto out;

#ifdef EXT2FS_DEBUG
	dump_sblock(fs);
#endif

	/* alloc a block sized buffer used for all fs transfers */
	fp->f_buf = alloc(fs->e2fs_bsize);

	/* read group descriptor blocks */
	fs->e2fs_gd = alloc(sizeof(struct ext2_gd) * fs->e2fs_ncg);
	rc = read_gdblock(f, fs);
	if (rc)
		goto out;

	/*
	 * Calculate indirect block levels.
	 */
	{
		indp_t mult;
		int ln2;

		/*
		 * We note that the number of indirect blocks is always
		 * a power of 2.  This lets us use shifts and masks instead
		 * of divide and remainder and avoinds pulling in the
		 * 64bit division routine into the boot code.
		 */
		mult = EXT2_NINDIR(fs);
#ifdef DEBUG
		if (!powerof2(mult)) {
			/* Hummm was't a power of 2 */
			rc = EINVAL;
			goto out;
		}
#endif
		for (ln2 = 0; mult != 1; ln2++)
			mult >>= 1;

		fp->f_nishift = ln2;
	}

	inumber = EXT2_ROOTINO;
	if ((rc = read_inode(inumber, f)) != 0)
		goto out;

#ifndef LIBSA_FS_SINGLECOMPONENT
	cp = path;
	while (*cp) {

		/*
		 * Remove extra separators
		 */
		while (*cp == '/')
			cp++;
		if (*cp == '\0')
			break;

		/*
		 * Check that current node is a directory.
		 */
		if ((fp->f_di.e2di_mode & EXT2_IFMT) != EXT2_IFDIR) {
			rc = ENOTDIR;
			goto out;
		}

		/*
		 * Get next component of path name.
		 */
		ncp = cp;
		while ((c = *cp) != '\0' && c != '/')
			cp++;

		/*
		 * Look up component in current directory.
		 * Save directory inumber in case we find a
		 * symbolic link.
		 */
#ifndef LIBSA_NO_FS_SYMLINK
		parent_inumber = inumber;
#endif
		rc = search_directory(ncp, cp - ncp, f, &inumber);
		if (rc)
			goto out;

		/*
		 * Open next component.
		 */
		if ((rc = read_inode(inumber, f)) != 0)
			goto out;

#ifndef LIBSA_NO_FS_SYMLINK
		/*
		 * Check for symbolic link.
		 */
		if ((fp->f_di.e2di_mode & EXT2_IFMT) == EXT2_IFLNK) {
			/* XXX should handle LARGEFILE */
			int link_len = fp->f_di.e2di_size;
			int len;

			len = strlen(cp);

			if (link_len + len > MAXPATHLEN ||
			    ++nlinks > MAXSYMLINKS) {
				rc = ENOENT;
				goto out;
			}

			memmove(&namebuf[link_len], cp, len + 1);

			if (link_len < EXT2_MAXSYMLINKLEN) {
				memcpy(namebuf, fp->f_di.e2di_blocks, link_len);
			} else {
				/*
				 * Read file for symbolic link
				 */
				size_t buf_size;
				indp_t	disk_block;

				buf = fp->f_buf;
				rc = block_map(f, (indp_t)0, &disk_block);
				if (rc)
					goto out;

				twiddle();
				rc = DEV_STRATEGY(f->f_dev)(f->f_devdata,
					F_READ, FSBTODB(fs, disk_block),
					fs->e2fs_bsize, buf, &buf_size);
				if (rc)
					goto out;

				memcpy(namebuf, buf, link_len);
			}

			/*
			 * If relative pathname, restart at parent directory.
			 * If absolute pathname, restart at root.
			 */
			cp = namebuf;
			if (*cp != '/')
				inumber = parent_inumber;
			else
				inumber = (ino32_t)EXT2_ROOTINO;

			if ((rc = read_inode(inumber, f)) != 0)
				goto out;
		}
#endif	/* !LIBSA_NO_FS_SYMLINK */
	}

	/*
	 * Found terminal component.
	 */
	rc = 0;

#else /* !LIBSA_FS_SINGLECOMPONENT */

	/* look up component in the current (root) directory */
	rc = search_directory(path, strlen(path), f, &inumber);
	if (rc)
		goto out;

	/* open it */
	rc = read_inode(inumber, f);

#endif /* !LIBSA_FS_SINGLECOMPONENT */

	fp->f_seekp = 0;		/* reset seek pointer */

out:
	if (rc)
		ext2fs_close(f);
	else
		fsmod = "ext2fs";
	return rc;
}