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; }
/* * 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; }