Remove nested functions from filesystem directory iterators.
* include/grub/fs.h (grub_fs_dir_hook_t): New type. (struct grub_fs.dir): Add hook_data argument. Update all implementations and callers.
This commit is contained in:
parent
53d3e4e3df
commit
fc524edf65
35 changed files with 1723 additions and 1451 deletions
|
@ -316,12 +316,87 @@ grub_affs_read_symlink (grub_fshelp_node_t node)
|
|||
}
|
||||
|
||||
|
||||
/* Helper for grub_affs_iterate_dir. */
|
||||
static int
|
||||
grub_affs_create_node (grub_fshelp_node_t dir,
|
||||
grub_fshelp_iterate_dir_hook_t hook, void *hook_data,
|
||||
struct grub_fshelp_node **node,
|
||||
grub_uint32_t **hashtable,
|
||||
grub_uint32_t block, const struct grub_affs_file *fil)
|
||||
{
|
||||
struct grub_affs_data *data = dir->data;
|
||||
int type;
|
||||
grub_uint8_t name_u8[sizeof (fil->name) * GRUB_MAX_UTF8_PER_LATIN1 + 1];
|
||||
grub_size_t len;
|
||||
unsigned int nest;
|
||||
|
||||
*node = grub_zalloc (sizeof (**node));
|
||||
if (!*node)
|
||||
{
|
||||
grub_free (*hashtable);
|
||||
return 1;
|
||||
}
|
||||
|
||||
(*node)->data = data;
|
||||
(*node)->block = block;
|
||||
(*node)->parent = dir;
|
||||
|
||||
len = fil->namelen;
|
||||
if (len > sizeof (fil->name))
|
||||
len = sizeof (fil->name);
|
||||
*grub_latin1_to_utf8 (name_u8, fil->name, len) = '\0';
|
||||
|
||||
(*node)->di = *fil;
|
||||
for (nest = 0; nest < 8; nest++)
|
||||
{
|
||||
switch ((*node)->di.type)
|
||||
{
|
||||
case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_REG):
|
||||
type = GRUB_FSHELP_REG;
|
||||
break;
|
||||
case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_DIR):
|
||||
type = GRUB_FSHELP_DIR;
|
||||
break;
|
||||
case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_SYMLINK):
|
||||
type = GRUB_FSHELP_SYMLINK;
|
||||
break;
|
||||
case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_HARDLINK):
|
||||
{
|
||||
grub_err_t err;
|
||||
(*node)->block = grub_be_to_cpu32 ((*node)->di.hardlink);
|
||||
err = grub_disk_read (data->disk,
|
||||
(((grub_uint64_t) (*node)->block + 1) << data->log_blocksize)
|
||||
- 1,
|
||||
GRUB_DISK_SECTOR_SIZE - GRUB_AFFS_FILE_LOCATION,
|
||||
sizeof ((*node)->di), (char *) &(*node)->di);
|
||||
if (err)
|
||||
return 1;
|
||||
continue;
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (nest == 8)
|
||||
return 0;
|
||||
|
||||
type |= GRUB_FSHELP_CASE_INSENSITIVE;
|
||||
|
||||
if (hook ((char *) name_u8, type, *node, hook_data))
|
||||
{
|
||||
grub_free (*hashtable);
|
||||
*node = 0;
|
||||
return 1;
|
||||
}
|
||||
*node = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
grub_affs_iterate_dir (grub_fshelp_node_t dir,
|
||||
int NESTED_FUNC_ATTR
|
||||
(*hook) (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node))
|
||||
grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
unsigned int i;
|
||||
struct grub_affs_file file;
|
||||
|
@ -329,88 +404,13 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
|
|||
struct grub_affs_data *data = dir->data;
|
||||
grub_uint32_t *hashtable;
|
||||
|
||||
auto int NESTED_FUNC_ATTR grub_affs_create_node (grub_uint32_t block,
|
||||
const struct grub_affs_file *fil);
|
||||
|
||||
int NESTED_FUNC_ATTR grub_affs_create_node (grub_uint32_t block,
|
||||
const struct grub_affs_file *fil)
|
||||
{
|
||||
int type;
|
||||
grub_uint8_t name_u8[sizeof (fil->name) * GRUB_MAX_UTF8_PER_LATIN1 + 1];
|
||||
grub_size_t len;
|
||||
unsigned int nest;
|
||||
|
||||
node = grub_zalloc (sizeof (*node));
|
||||
if (!node)
|
||||
{
|
||||
grub_free (hashtable);
|
||||
return 1;
|
||||
}
|
||||
|
||||
node->data = data;
|
||||
node->block = block;
|
||||
node->parent = dir;
|
||||
|
||||
len = fil->namelen;
|
||||
if (len > sizeof (fil->name))
|
||||
len = sizeof (fil->name);
|
||||
*grub_latin1_to_utf8 (name_u8, fil->name, len) = '\0';
|
||||
|
||||
node->di = *fil;
|
||||
for (nest = 0; nest < 8; nest++)
|
||||
{
|
||||
switch (node->di.type)
|
||||
{
|
||||
case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_REG):
|
||||
type = GRUB_FSHELP_REG;
|
||||
break;
|
||||
case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_DIR):
|
||||
type = GRUB_FSHELP_DIR;
|
||||
break;
|
||||
case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_SYMLINK):
|
||||
type = GRUB_FSHELP_SYMLINK;
|
||||
break;
|
||||
case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_HARDLINK):
|
||||
{
|
||||
grub_err_t err;
|
||||
node->block = grub_be_to_cpu32 (node->di.hardlink);
|
||||
err = grub_disk_read (data->disk,
|
||||
(((grub_uint64_t) node->block + 1) << data->log_blocksize)
|
||||
- 1,
|
||||
GRUB_DISK_SECTOR_SIZE - GRUB_AFFS_FILE_LOCATION,
|
||||
sizeof (node->di), (char *) &node->di);
|
||||
if (err)
|
||||
return 1;
|
||||
continue;
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (nest == 8)
|
||||
return 0;
|
||||
|
||||
type |= GRUB_FSHELP_CASE_INSENSITIVE;
|
||||
|
||||
if (hook ((char *) name_u8, type, node))
|
||||
{
|
||||
grub_free (hashtable);
|
||||
node = 0;
|
||||
return 1;
|
||||
}
|
||||
node = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create the directory entries for `.' and `..'. */
|
||||
node = grub_zalloc (sizeof (*node));
|
||||
if (!node)
|
||||
return 1;
|
||||
|
||||
*node = *dir;
|
||||
if (hook (".", GRUB_FSHELP_DIR, node))
|
||||
if (hook (".", GRUB_FSHELP_DIR, node, hook_data))
|
||||
return 1;
|
||||
if (dir->parent)
|
||||
{
|
||||
|
@ -418,7 +418,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
|
|||
if (!node)
|
||||
return 1;
|
||||
*node = *dir->parent;
|
||||
if (hook ("..", GRUB_FSHELP_DIR, node))
|
||||
if (hook ("..", GRUB_FSHELP_DIR, node, hook_data))
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -454,7 +454,8 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
|
|||
if (grub_errno)
|
||||
goto fail;
|
||||
|
||||
if (grub_affs_create_node (next, &file))
|
||||
if (grub_affs_create_node (dir, hook, hook_data, &node, &hashtable,
|
||||
next, &file))
|
||||
return 1;
|
||||
|
||||
next = grub_be_to_cpu32 (file.next);
|
||||
|
@ -545,31 +546,37 @@ aftime2ctime (const struct grub_affs_time *t)
|
|||
+ 8 * 365 * 86400 + 86400 * 2;
|
||||
}
|
||||
|
||||
/* Context for grub_affs_dir. */
|
||||
struct grub_affs_dir_ctx
|
||||
{
|
||||
grub_fs_dir_hook_t hook;
|
||||
void *hook_data;
|
||||
};
|
||||
|
||||
/* Helper for grub_affs_dir. */
|
||||
static int
|
||||
grub_affs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node, void *data)
|
||||
{
|
||||
struct grub_affs_dir_ctx *ctx = data;
|
||||
struct grub_dirhook_info info;
|
||||
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
info.mtimeset = 1;
|
||||
info.mtime = aftime2ctime (&node->di.mtime);
|
||||
grub_free (node);
|
||||
return ctx->hook (filename, &info, ctx->hook_data);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_affs_dir (grub_device_t device, const char *path,
|
||||
int (*hook) (const char *filename,
|
||||
const struct grub_dirhook_info *info))
|
||||
grub_fs_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
struct grub_affs_dir_ctx ctx = { hook, hook_data };
|
||||
struct grub_affs_data *data = 0;
|
||||
struct grub_fshelp_node *fdiro = 0;
|
||||
|
||||
auto int NESTED_FUNC_ATTR iterate (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node);
|
||||
|
||||
int NESTED_FUNC_ATTR iterate (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node)
|
||||
{
|
||||
struct grub_dirhook_info info;
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
info.mtimeset = 1;
|
||||
info.mtime = aftime2ctime (&node->di.mtime);
|
||||
grub_free (node);
|
||||
return hook (filename, &info);
|
||||
}
|
||||
|
||||
grub_dl_ref (my_mod);
|
||||
|
||||
data = grub_affs_mount (device->disk);
|
||||
|
@ -581,7 +588,7 @@ grub_affs_dir (grub_device_t device, const char *path,
|
|||
if (grub_errno)
|
||||
goto fail;
|
||||
|
||||
grub_affs_iterate_dir (fdiro, iterate);
|
||||
grub_affs_iterate_dir (fdiro, grub_affs_dir_iter, &ctx);
|
||||
|
||||
fail:
|
||||
if (data && fdiro != &data->diropen)
|
||||
|
|
|
@ -173,6 +173,15 @@ struct grub_bfs_data
|
|||
struct grub_bfs_inode ino[0];
|
||||
};
|
||||
|
||||
/* Context for grub_bfs_dir. */
|
||||
struct grub_bfs_dir_ctx
|
||||
{
|
||||
grub_device_t device;
|
||||
grub_fs_dir_hook_t hook;
|
||||
void *hook_data;
|
||||
struct grub_bfs_superblock sb;
|
||||
};
|
||||
|
||||
static grub_err_t
|
||||
read_extent (grub_disk_t disk,
|
||||
const struct grub_bfs_superblock *sb,
|
||||
|
@ -413,7 +422,9 @@ static int
|
|||
iterate_in_b_tree (grub_disk_t disk,
|
||||
const struct grub_bfs_superblock *sb,
|
||||
const struct grub_bfs_inode *ino,
|
||||
int NESTED_FUNC_ATTR (*hook) (const char *name, grub_uint64_t value))
|
||||
int (*hook) (const char *name, grub_uint64_t value,
|
||||
struct grub_bfs_dir_ctx *ctx),
|
||||
struct grub_bfs_dir_ctx *ctx)
|
||||
{
|
||||
struct grub_bfs_btree_header head;
|
||||
grub_err_t err;
|
||||
|
@ -496,7 +507,8 @@ iterate_in_b_tree (grub_disk_t disk,
|
|||
end = grub_bfs_to_cpu_treehead (node.total_key_len);
|
||||
c = key_data[end];
|
||||
key_data[end] = 0;
|
||||
if (hook (key_data + start, grub_bfs_to_cpu64 (key_values[i])))
|
||||
if (hook (key_data + start, grub_bfs_to_cpu64 (key_values[i]),
|
||||
ctx))
|
||||
return 1;
|
||||
key_data[end] = c;
|
||||
}
|
||||
|
@ -844,46 +856,52 @@ mount (grub_disk_t disk, struct grub_bfs_superblock *sb)
|
|||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
/* Helper for grub_bfs_dir. */
|
||||
static int
|
||||
grub_bfs_dir_iter (const char *name, grub_uint64_t value,
|
||||
struct grub_bfs_dir_ctx *ctx)
|
||||
{
|
||||
grub_err_t err2;
|
||||
union
|
||||
{
|
||||
struct grub_bfs_inode ino;
|
||||
grub_uint8_t raw[grub_bfs_to_cpu32 (ctx->sb.bsize)];
|
||||
} ino;
|
||||
struct grub_dirhook_info info;
|
||||
|
||||
err2 = grub_disk_read (ctx->device->disk, value
|
||||
<< (grub_bfs_to_cpu32 (ctx->sb.log2_bsize)
|
||||
- GRUB_DISK_SECTOR_BITS), 0,
|
||||
grub_bfs_to_cpu32 (ctx->sb.bsize), (char *) ino.raw);
|
||||
if (err2)
|
||||
{
|
||||
grub_print_error ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
info.mtimeset = 1;
|
||||
#ifdef MODE_AFS
|
||||
info.mtime =
|
||||
grub_divmod64 (grub_bfs_to_cpu64 (ino.ino.mtime), 1000000, 0);
|
||||
#else
|
||||
info.mtime = grub_bfs_to_cpu64 (ino.ino.mtime) >> 16;
|
||||
#endif
|
||||
info.dir = ((grub_bfs_to_cpu32 (ino.ino.mode) & ATTR_TYPE) == ATTR_DIR);
|
||||
return ctx->hook (name, &info, ctx->hook_data);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_bfs_dir (grub_device_t device, const char *path,
|
||||
int (*hook_in) (const char *filename,
|
||||
const struct grub_dirhook_info * info))
|
||||
grub_fs_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
struct grub_bfs_superblock sb;
|
||||
struct grub_bfs_dir_ctx ctx = {
|
||||
.device = device,
|
||||
.hook = hook,
|
||||
.hook_data = hook_data
|
||||
};
|
||||
grub_err_t err;
|
||||
auto int NESTED_FUNC_ATTR hook (const char *name, grub_uint64_t value);
|
||||
|
||||
int NESTED_FUNC_ATTR hook (const char *name, grub_uint64_t value)
|
||||
{
|
||||
grub_err_t err2;
|
||||
union
|
||||
{
|
||||
struct grub_bfs_inode ino;
|
||||
grub_uint8_t raw[grub_bfs_to_cpu32 (sb.bsize)];
|
||||
} ino;
|
||||
struct grub_dirhook_info info;
|
||||
|
||||
err2 = grub_disk_read (device->disk, value
|
||||
<< (grub_bfs_to_cpu32 (sb.log2_bsize)
|
||||
- GRUB_DISK_SECTOR_BITS), 0,
|
||||
grub_bfs_to_cpu32 (sb.bsize), (char *) ino.raw);
|
||||
if (err2)
|
||||
{
|
||||
grub_print_error ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
info.mtimeset = 1;
|
||||
#ifdef MODE_AFS
|
||||
info.mtime =
|
||||
grub_divmod64 (grub_bfs_to_cpu64 (ino.ino.mtime), 1000000, 0);
|
||||
#else
|
||||
info.mtime = grub_bfs_to_cpu64 (ino.ino.mtime) >> 16;
|
||||
#endif
|
||||
info.dir = ((grub_bfs_to_cpu32 (ino.ino.mode) & ATTR_TYPE) == ATTR_DIR);
|
||||
return hook_in (name, &info);
|
||||
}
|
||||
err = mount (device->disk, &sb);
|
||||
err = mount (device->disk, &ctx.sb);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -891,14 +909,15 @@ grub_bfs_dir (grub_device_t device, const char *path,
|
|||
union
|
||||
{
|
||||
struct grub_bfs_inode ino;
|
||||
grub_uint8_t raw[grub_bfs_to_cpu32 (sb.bsize)];
|
||||
grub_uint8_t raw[grub_bfs_to_cpu32 (ctx.sb.bsize)];
|
||||
} ino;
|
||||
err = find_file (path, device->disk, &sb, &ino.ino);
|
||||
err = find_file (path, device->disk, &ctx.sb, &ino.ino);
|
||||
if (err)
|
||||
return err;
|
||||
if (((grub_bfs_to_cpu32 (ino.ino.mode) & ATTR_TYPE) != ATTR_DIR))
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
|
||||
iterate_in_b_tree (device->disk, &sb, &ino.ino, hook);
|
||||
iterate_in_b_tree (device->disk, &ctx.sb, &ino.ino, grub_bfs_dir_iter,
|
||||
&ctx);
|
||||
}
|
||||
|
||||
return grub_errno;
|
||||
|
|
|
@ -1491,8 +1491,7 @@ find_path (struct grub_btrfs_data *data,
|
|||
|
||||
static grub_err_t
|
||||
grub_btrfs_dir (grub_device_t device, const char *path,
|
||||
int (*hook) (const char *filename,
|
||||
const struct grub_dirhook_info *info))
|
||||
grub_fs_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
struct grub_btrfs_data *data = grub_btrfs_mount (device);
|
||||
struct grub_btrfs_key key_in, key_out;
|
||||
|
@ -1586,7 +1585,7 @@ grub_btrfs_dir (grub_device_t device, const char *path,
|
|||
c = cdirel->name[grub_le_to_cpu16 (cdirel->n)];
|
||||
cdirel->name[grub_le_to_cpu16 (cdirel->n)] = 0;
|
||||
info.dir = (cdirel->type == GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY);
|
||||
if (hook (cdirel->name, &info))
|
||||
if (hook (cdirel->name, &info, hook_data))
|
||||
goto out;
|
||||
cdirel->name[grub_le_to_cpu16 (cdirel->n)] = c;
|
||||
}
|
||||
|
|
|
@ -513,8 +513,7 @@ handle_symlink (struct grub_cpio_data *data,
|
|||
|
||||
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))
|
||||
grub_fs_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
struct grub_cpio_data *data;
|
||||
grub_disk_addr_t ofs;
|
||||
|
@ -575,7 +574,7 @@ grub_cpio_dir (grub_device_t device, const char *path_in,
|
|||
info.mtime = mtime;
|
||||
info.mtimeset = 1;
|
||||
|
||||
if (hook (n, &info))
|
||||
if (hook (n, &info, hook_data))
|
||||
{
|
||||
grub_free (name);
|
||||
goto fail;
|
||||
|
|
|
@ -692,10 +692,7 @@ grub_ext2_read_symlink (grub_fshelp_node_t node)
|
|||
|
||||
static int
|
||||
grub_ext2_iterate_dir (grub_fshelp_node_t dir,
|
||||
int NESTED_FUNC_ATTR
|
||||
(*hook) (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node))
|
||||
grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
unsigned int fpos = 0;
|
||||
struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir;
|
||||
|
@ -777,7 +774,7 @@ grub_ext2_iterate_dir (grub_fshelp_node_t dir,
|
|||
type = GRUB_FSHELP_REG;
|
||||
}
|
||||
|
||||
if (hook (filename, type, fdiro))
|
||||
if (hook (filename, type, fdiro, hook_data))
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -858,59 +855,69 @@ grub_ext2_read (grub_file_t file, char *buf, grub_size_t len)
|
|||
}
|
||||
|
||||
|
||||
static grub_err_t
|
||||
grub_ext2_dir (grub_device_t device, const char *path,
|
||||
int (*hook) (const char *filename,
|
||||
const struct grub_dirhook_info *info))
|
||||
/* Context for grub_ext2_dir. */
|
||||
struct grub_ext2_dir_ctx
|
||||
{
|
||||
struct grub_ext2_data *data = 0;
|
||||
struct grub_fshelp_node *fdiro = 0;
|
||||
grub_fs_dir_hook_t hook;
|
||||
void *hook_data;
|
||||
struct grub_ext2_data *data;
|
||||
};
|
||||
|
||||
auto int NESTED_FUNC_ATTR iterate (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node);
|
||||
/* Helper for grub_ext2_dir. */
|
||||
static int
|
||||
grub_ext2_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node, void *data)
|
||||
{
|
||||
struct grub_ext2_dir_ctx *ctx = data;
|
||||
struct grub_dirhook_info info;
|
||||
|
||||
int NESTED_FUNC_ATTR iterate (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node)
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
if (! node->inode_read)
|
||||
{
|
||||
struct grub_dirhook_info info;
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
if (! node->inode_read)
|
||||
{
|
||||
grub_ext2_read_inode (data, node->ino, &node->inode);
|
||||
if (!grub_errno)
|
||||
node->inode_read = 1;
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
if (node->inode_read)
|
||||
{
|
||||
info.mtimeset = 1;
|
||||
info.mtime = grub_le_to_cpu32 (node->inode.mtime);
|
||||
}
|
||||
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
grub_free (node);
|
||||
return hook (filename, &info);
|
||||
grub_ext2_read_inode (ctx->data, node->ino, &node->inode);
|
||||
if (!grub_errno)
|
||||
node->inode_read = 1;
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
if (node->inode_read)
|
||||
{
|
||||
info.mtimeset = 1;
|
||||
info.mtime = grub_le_to_cpu32 (node->inode.mtime);
|
||||
}
|
||||
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
grub_free (node);
|
||||
return ctx->hook (filename, &info, ctx->hook_data);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_ext2_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook,
|
||||
void *hook_data)
|
||||
{
|
||||
struct grub_ext2_dir_ctx ctx = {
|
||||
.hook = hook,
|
||||
.hook_data = hook_data
|
||||
};
|
||||
struct grub_fshelp_node *fdiro = 0;
|
||||
|
||||
grub_dl_ref (my_mod);
|
||||
|
||||
data = grub_ext2_mount (device->disk);
|
||||
if (! data)
|
||||
ctx.data = grub_ext2_mount (device->disk);
|
||||
if (! ctx.data)
|
||||
goto fail;
|
||||
|
||||
grub_fshelp_find_file (path, &data->diropen, &fdiro, grub_ext2_iterate_dir,
|
||||
grub_ext2_read_symlink, GRUB_FSHELP_DIR);
|
||||
grub_fshelp_find_file (path, &ctx.data->diropen, &fdiro,
|
||||
grub_ext2_iterate_dir, grub_ext2_read_symlink,
|
||||
GRUB_FSHELP_DIR);
|
||||
if (grub_errno)
|
||||
goto fail;
|
||||
|
||||
grub_ext2_iterate_dir (fdiro, iterate);
|
||||
grub_ext2_iterate_dir (fdiro, grub_ext2_dir_iter, &ctx);
|
||||
|
||||
fail:
|
||||
if (fdiro != &data->diropen)
|
||||
if (fdiro != &ctx.data->diropen)
|
||||
grub_free (fdiro);
|
||||
grub_free (data);
|
||||
grub_free (ctx.data);
|
||||
|
||||
grub_dl_unref (my_mod);
|
||||
|
||||
|
|
|
@ -844,8 +844,7 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data,
|
|||
static char *
|
||||
grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
|
||||
const char *path, const char *origpath,
|
||||
int (*hook) (const char *filename,
|
||||
const struct grub_dirhook_info *info))
|
||||
grub_fs_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
char *dirname, *dirp;
|
||||
int call_hook;
|
||||
|
@ -905,7 +904,7 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
|
|||
#endif
|
||||
if (*dirname == '\0' && call_hook)
|
||||
{
|
||||
if (hook (ctxt.filename, &info))
|
||||
if (hook (ctxt.filename, &info, hook_data))
|
||||
break;
|
||||
else
|
||||
continue;
|
||||
|
@ -926,7 +925,7 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
|
|||
data->cur_cluster_num = ~0U;
|
||||
|
||||
if (call_hook)
|
||||
hook (ctxt.filename, &info);
|
||||
hook (ctxt.filename, &info, hook_data);
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -946,9 +945,8 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
|
|||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_fat_dir (grub_device_t device, const char *path,
|
||||
int (*hook) (const char *filename,
|
||||
const struct grub_dirhook_info *info))
|
||||
grub_fat_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook,
|
||||
void *hook_data)
|
||||
{
|
||||
struct grub_fat_data *data = 0;
|
||||
grub_disk_t disk = device->disk;
|
||||
|
@ -976,7 +974,7 @@ grub_fat_dir (grub_device_t device, const char *path,
|
|||
|
||||
do
|
||||
{
|
||||
p = grub_fat_find_dir (disk, data, p, path, hook);
|
||||
p = grub_fat_find_dir (disk, data, p, path, hook, hook_data);
|
||||
}
|
||||
while (p && grub_errno == GRUB_ERR_NONE);
|
||||
|
||||
|
@ -1004,7 +1002,7 @@ grub_fat_open (grub_file_t file, const char *name)
|
|||
|
||||
do
|
||||
{
|
||||
p = grub_fat_find_dir (file->device->disk, data, p, name, 0);
|
||||
p = grub_fat_find_dir (file->device->disk, data, p, name, 0, 0);
|
||||
if (grub_errno != GRUB_ERR_NONE)
|
||||
goto fail;
|
||||
}
|
||||
|
|
|
@ -27,184 +27,199 @@
|
|||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
typedef int (*iterate_dir_func) (grub_fshelp_node_t dir,
|
||||
grub_fshelp_iterate_dir_hook_t hook,
|
||||
void *data);
|
||||
typedef char *(*read_symlink_func) (grub_fshelp_node_t node);
|
||||
|
||||
/* Context for grub_fshelp_find_file. */
|
||||
struct grub_fshelp_find_file_ctx
|
||||
{
|
||||
const char *path;
|
||||
grub_fshelp_node_t rootnode, currroot, currnode, oldnode;
|
||||
enum grub_fshelp_filetype foundtype;
|
||||
int symlinknest;
|
||||
char *name;
|
||||
enum grub_fshelp_filetype type;
|
||||
};
|
||||
|
||||
/* Helper for find_file_iter. */
|
||||
static void
|
||||
free_node (grub_fshelp_node_t node, struct grub_fshelp_find_file_ctx *ctx)
|
||||
{
|
||||
if (node != ctx->rootnode && node != ctx->currroot)
|
||||
grub_free (node);
|
||||
}
|
||||
|
||||
/* Helper for grub_fshelp_find_file. */
|
||||
static int
|
||||
find_file_iter (const char *filename, enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node, void *data)
|
||||
{
|
||||
struct grub_fshelp_find_file_ctx *ctx = data;
|
||||
|
||||
if (filetype == GRUB_FSHELP_UNKNOWN ||
|
||||
(grub_strcmp (ctx->name, filename) &&
|
||||
(! (filetype & GRUB_FSHELP_CASE_INSENSITIVE) ||
|
||||
grub_strcasecmp (ctx->name, filename))))
|
||||
{
|
||||
grub_free (node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The node is found, stop iterating over the nodes. */
|
||||
ctx->type = filetype & ~GRUB_FSHELP_CASE_INSENSITIVE;
|
||||
ctx->oldnode = ctx->currnode;
|
||||
ctx->currnode = node;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
find_file (const char *currpath, grub_fshelp_node_t currroot,
|
||||
grub_fshelp_node_t *currfound,
|
||||
iterate_dir_func iterate_dir, read_symlink_func read_symlink,
|
||||
struct grub_fshelp_find_file_ctx *ctx)
|
||||
{
|
||||
char fpath[grub_strlen (currpath) + 1];
|
||||
char *next;
|
||||
|
||||
ctx->currroot = currroot;
|
||||
ctx->name = fpath;
|
||||
ctx->type = GRUB_FSHELP_DIR;
|
||||
ctx->currnode = currroot;
|
||||
ctx->oldnode = currroot;
|
||||
|
||||
grub_strncpy (fpath, currpath, grub_strlen (currpath) + 1);
|
||||
|
||||
/* Remove all leading slashes. */
|
||||
while (*ctx->name == '/')
|
||||
ctx->name++;
|
||||
|
||||
if (! *ctx->name)
|
||||
{
|
||||
*currfound = ctx->currnode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int found;
|
||||
|
||||
/* Extract the actual part from the pathname. */
|
||||
next = grub_strchr (ctx->name, '/');
|
||||
if (next)
|
||||
{
|
||||
/* Remove all leading slashes. */
|
||||
while (*next == '/')
|
||||
*(next++) = '\0';
|
||||
}
|
||||
|
||||
/* At this point it is expected that the current node is a
|
||||
directory, check if this is true. */
|
||||
if (ctx->type != GRUB_FSHELP_DIR)
|
||||
{
|
||||
free_node (ctx->currnode, ctx);
|
||||
ctx->currnode = 0;
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
|
||||
}
|
||||
|
||||
/* Iterate over the directory. */
|
||||
found = iterate_dir (ctx->currnode, find_file_iter, ctx);
|
||||
if (! found)
|
||||
{
|
||||
free_node (ctx->currnode, ctx);
|
||||
ctx->currnode = 0;
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Read in the symlink and follow it. */
|
||||
if (ctx->type == GRUB_FSHELP_SYMLINK)
|
||||
{
|
||||
char *symlink;
|
||||
|
||||
/* Test if the symlink does not loop. */
|
||||
if (++ctx->symlinknest == 8)
|
||||
{
|
||||
free_node (ctx->currnode, ctx);
|
||||
free_node (ctx->oldnode, ctx);
|
||||
ctx->currnode = 0;
|
||||
return grub_error (GRUB_ERR_SYMLINK_LOOP,
|
||||
N_("too deep nesting of symlinks"));
|
||||
}
|
||||
|
||||
symlink = read_symlink (ctx->currnode);
|
||||
free_node (ctx->currnode, ctx);
|
||||
ctx->currnode = 0;
|
||||
|
||||
if (!symlink)
|
||||
{
|
||||
free_node (ctx->oldnode, ctx);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
/* The symlink is an absolute path, go back to the root inode. */
|
||||
if (symlink[0] == '/')
|
||||
{
|
||||
free_node (ctx->oldnode, ctx);
|
||||
ctx->oldnode = ctx->rootnode;
|
||||
}
|
||||
|
||||
/* Lookup the node the symlink points to. */
|
||||
find_file (symlink, ctx->oldnode, &ctx->currnode,
|
||||
iterate_dir, read_symlink, ctx);
|
||||
ctx->type = ctx->foundtype;
|
||||
grub_free (symlink);
|
||||
|
||||
if (grub_errno)
|
||||
{
|
||||
free_node (ctx->oldnode, ctx);
|
||||
return grub_errno;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->oldnode != ctx->currnode)
|
||||
free_node (ctx->oldnode, ctx);
|
||||
|
||||
/* Found the node! */
|
||||
if (! next || *next == '\0')
|
||||
{
|
||||
*currfound = ctx->currnode;
|
||||
ctx->foundtype = ctx->type;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctx->name = next;
|
||||
}
|
||||
|
||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"),
|
||||
ctx->path);
|
||||
}
|
||||
|
||||
/* Lookup the node PATH. The node ROOTNODE describes the root of the
|
||||
directory tree. The node found is returned in FOUNDNODE, which is
|
||||
either a ROOTNODE or a new malloc'ed node. ITERATE_DIR is used to
|
||||
iterate over all directory entries in the current node.
|
||||
READ_SYMLINK is used to read the symlink if a node is a symlink.
|
||||
EXPECTTYPE is the type node that is expected by the called, an
|
||||
error is generated if the node is not of the expected type. Make
|
||||
sure you use the NESTED_FUNC_ATTR macro for HOOK, this is required
|
||||
because GCC has a nasty bug when using regparm=3. */
|
||||
error is generated if the node is not of the expected type. */
|
||||
grub_err_t
|
||||
grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode,
|
||||
grub_fshelp_node_t *foundnode,
|
||||
int (*iterate_dir) (grub_fshelp_node_t dir,
|
||||
int NESTED_FUNC_ATTR (*hook)
|
||||
(const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node)),
|
||||
char *(*read_symlink) (grub_fshelp_node_t node),
|
||||
iterate_dir_func iterate_dir,
|
||||
read_symlink_func read_symlink,
|
||||
enum grub_fshelp_filetype expecttype)
|
||||
{
|
||||
struct grub_fshelp_find_file_ctx ctx = {
|
||||
.path = path,
|
||||
.rootnode = rootnode,
|
||||
.foundtype = GRUB_FSHELP_DIR,
|
||||
.symlinknest = 0
|
||||
};
|
||||
grub_err_t err;
|
||||
enum grub_fshelp_filetype foundtype = GRUB_FSHELP_DIR;
|
||||
int symlinknest = 0;
|
||||
|
||||
auto grub_err_t NESTED_FUNC_ATTR find_file (const char *currpath,
|
||||
grub_fshelp_node_t currroot,
|
||||
grub_fshelp_node_t *currfound);
|
||||
|
||||
grub_err_t NESTED_FUNC_ATTR find_file (const char *currpath,
|
||||
grub_fshelp_node_t currroot,
|
||||
grub_fshelp_node_t *currfound)
|
||||
{
|
||||
char fpath[grub_strlen (currpath) + 1];
|
||||
char *name = fpath;
|
||||
char *next;
|
||||
enum grub_fshelp_filetype type = GRUB_FSHELP_DIR;
|
||||
grub_fshelp_node_t currnode = currroot;
|
||||
grub_fshelp_node_t oldnode = currroot;
|
||||
|
||||
auto int NESTED_FUNC_ATTR iterate (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node);
|
||||
|
||||
auto void free_node (grub_fshelp_node_t node);
|
||||
|
||||
void free_node (grub_fshelp_node_t node)
|
||||
{
|
||||
if (node != rootnode && node != currroot)
|
||||
grub_free (node);
|
||||
}
|
||||
|
||||
int NESTED_FUNC_ATTR iterate (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node)
|
||||
{
|
||||
if (filetype == GRUB_FSHELP_UNKNOWN ||
|
||||
(grub_strcmp (name, filename) &&
|
||||
(! (filetype & GRUB_FSHELP_CASE_INSENSITIVE) ||
|
||||
grub_strcasecmp (name, filename))))
|
||||
{
|
||||
grub_free (node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The node is found, stop iterating over the nodes. */
|
||||
type = filetype & ~GRUB_FSHELP_CASE_INSENSITIVE;
|
||||
oldnode = currnode;
|
||||
currnode = node;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
grub_strncpy (fpath, currpath, grub_strlen (currpath) + 1);
|
||||
|
||||
/* Remove all leading slashes. */
|
||||
while (*name == '/')
|
||||
name++;
|
||||
|
||||
if (! *name)
|
||||
{
|
||||
*currfound = currnode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int found;
|
||||
|
||||
/* Extract the actual part from the pathname. */
|
||||
next = grub_strchr (name, '/');
|
||||
if (next)
|
||||
{
|
||||
/* Remove all leading slashes. */
|
||||
while (*next == '/')
|
||||
*(next++) = '\0';
|
||||
}
|
||||
|
||||
/* At this point it is expected that the current node is a
|
||||
directory, check if this is true. */
|
||||
if (type != GRUB_FSHELP_DIR)
|
||||
{
|
||||
free_node (currnode);
|
||||
currnode = 0;
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
|
||||
}
|
||||
|
||||
/* Iterate over the directory. */
|
||||
found = iterate_dir (currnode, iterate);
|
||||
if (! found)
|
||||
{
|
||||
free_node (currnode);
|
||||
currnode = 0;
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Read in the symlink and follow it. */
|
||||
if (type == GRUB_FSHELP_SYMLINK)
|
||||
{
|
||||
char *symlink;
|
||||
|
||||
/* Test if the symlink does not loop. */
|
||||
if (++symlinknest == 8)
|
||||
{
|
||||
free_node (currnode);
|
||||
free_node (oldnode);
|
||||
currnode = 0;
|
||||
return grub_error (GRUB_ERR_SYMLINK_LOOP,
|
||||
N_("too deep nesting of symlinks"));
|
||||
}
|
||||
|
||||
symlink = read_symlink (currnode);
|
||||
free_node (currnode);
|
||||
currnode = 0;
|
||||
|
||||
if (!symlink)
|
||||
{
|
||||
free_node (oldnode);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
/* The symlink is an absolute path, go back to the root inode. */
|
||||
if (symlink[0] == '/')
|
||||
{
|
||||
free_node (oldnode);
|
||||
oldnode = rootnode;
|
||||
}
|
||||
|
||||
/* Lookup the node the symlink points to. */
|
||||
find_file (symlink, oldnode, &currnode);
|
||||
type = foundtype;
|
||||
grub_free (symlink);
|
||||
|
||||
if (grub_errno)
|
||||
{
|
||||
free_node (oldnode);
|
||||
return grub_errno;
|
||||
}
|
||||
}
|
||||
|
||||
if (oldnode != currnode)
|
||||
free_node (oldnode);
|
||||
|
||||
/* Found the node! */
|
||||
if (! next || *next == '\0')
|
||||
{
|
||||
*currfound = currnode;
|
||||
foundtype = type;
|
||||
return 0;
|
||||
}
|
||||
|
||||
name = next;
|
||||
}
|
||||
|
||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path);
|
||||
}
|
||||
|
||||
if (!path || path[0] != '/')
|
||||
{
|
||||
|
@ -212,14 +227,14 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode,
|
|||
return grub_errno;
|
||||
}
|
||||
|
||||
err = find_file (path, rootnode, foundnode);
|
||||
err = find_file (path, rootnode, foundnode, iterate_dir, read_symlink, &ctx);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Check if the node that was found was of the expected type. */
|
||||
if (expecttype == GRUB_FSHELP_REG && foundtype != expecttype)
|
||||
if (expecttype == GRUB_FSHELP_REG && ctx.foundtype != expecttype)
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file"));
|
||||
else if (expecttype == GRUB_FSHELP_DIR && foundtype != expecttype)
|
||||
else if (expecttype == GRUB_FSHELP_DIR && ctx.foundtype != expecttype)
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -1151,9 +1151,8 @@ grub_hfs_find_dir (struct grub_hfs_data *data, const char *path,
|
|||
|
||||
|
||||
static grub_err_t
|
||||
grub_hfs_dir (grub_device_t device, const char *path,
|
||||
int (*hook) (const char *filename,
|
||||
const struct grub_dirhook_info *info))
|
||||
grub_hfs_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook,
|
||||
void *hook_data)
|
||||
{
|
||||
int inode;
|
||||
|
||||
|
@ -1184,14 +1183,14 @@ grub_hfs_dir (grub_device_t device, const char *path,
|
|||
info.dir = 1;
|
||||
info.mtimeset = 1;
|
||||
info.mtime = grub_be_to_cpu32 (drec->mtime) - 2082844800;
|
||||
return hook (fname, &info);
|
||||
return hook (fname, &info, hook_data);
|
||||
}
|
||||
if (frec->type == GRUB_HFS_FILETYPE_FILE)
|
||||
{
|
||||
info.dir = 0;
|
||||
info.mtimeset = 1;
|
||||
info.mtime = grub_be_to_cpu32 (frec->mtime) - 2082844800;
|
||||
return hook (fname, &info);
|
||||
return hook (fname, &info, hook_data);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -766,10 +766,7 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree,
|
|||
|
||||
static int
|
||||
grub_hfsplus_iterate_dir (grub_fshelp_node_t dir,
|
||||
int NESTED_FUNC_ATTR
|
||||
(*hook) (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node))
|
||||
grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
|
@ -825,7 +822,7 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir,
|
|||
node->size = 0;
|
||||
node->fileid = grub_be_to_cpu32 (fileinfo->parentid);
|
||||
|
||||
ret = hook ("..", GRUB_FSHELP_DIR, node);
|
||||
ret = hook ("..", GRUB_FSHELP_DIR, node, hook_data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -878,7 +875,7 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir,
|
|||
node->size = grub_be_to_cpu64 (fileinfo->data.size);
|
||||
node->fileid = grub_be_to_cpu32 (fileinfo->fileid);
|
||||
|
||||
ret = hook (filename, type, node);
|
||||
ret = hook (filename, type, node, hook_data);
|
||||
|
||||
grub_free (filename);
|
||||
|
||||
|
@ -895,7 +892,7 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir,
|
|||
if (!fsnode)
|
||||
return 1;
|
||||
*fsnode = *dir;
|
||||
if (hook (".", GRUB_FSHELP_DIR, fsnode))
|
||||
if (hook (".", GRUB_FSHELP_DIR, fsnode, hook_data))
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -978,32 +975,39 @@ grub_hfsplus_read (grub_file_t file, char *buf, grub_size_t len)
|
|||
file->offset, len, buf);
|
||||
}
|
||||
|
||||
/* Context for grub_hfsplus_dir. */
|
||||
struct grub_hfsplus_dir_ctx
|
||||
{
|
||||
grub_fs_dir_hook_t hook;
|
||||
void *hook_data;
|
||||
};
|
||||
|
||||
/* Helper for grub_hfsplus_dir. */
|
||||
static int
|
||||
grub_hfsplus_dir_iter (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node, void *data)
|
||||
{
|
||||
struct grub_hfsplus_dir_ctx *ctx = data;
|
||||
struct grub_dirhook_info info;
|
||||
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
info.mtimeset = 1;
|
||||
info.mtime = node->mtime;
|
||||
info.case_insensitive = !! (filetype & GRUB_FSHELP_CASE_INSENSITIVE);
|
||||
grub_free (node);
|
||||
return ctx->hook (filename, &info, ctx->hook_data);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_hfsplus_dir (grub_device_t device, const char *path,
|
||||
int (*hook) (const char *filename,
|
||||
const struct grub_dirhook_info *info))
|
||||
grub_fs_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
struct grub_hfsplus_dir_ctx ctx = { hook, hook_data };
|
||||
struct grub_hfsplus_data *data = 0;
|
||||
struct grub_fshelp_node *fdiro = 0;
|
||||
|
||||
auto int NESTED_FUNC_ATTR iterate (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node);
|
||||
|
||||
int NESTED_FUNC_ATTR iterate (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node)
|
||||
{
|
||||
struct grub_dirhook_info info;
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
info.mtimeset = 1;
|
||||
info.mtime = node->mtime;
|
||||
info.case_insensitive = !! (filetype & GRUB_FSHELP_CASE_INSENSITIVE);
|
||||
grub_free (node);
|
||||
return hook (filename, &info);
|
||||
}
|
||||
|
||||
grub_dl_ref (my_mod);
|
||||
|
||||
data = grub_hfsplus_mount (device->disk);
|
||||
|
@ -1018,7 +1022,7 @@ grub_hfsplus_dir (grub_device_t device, const char *path,
|
|||
goto fail;
|
||||
|
||||
/* Iterate over all entries in this directory. */
|
||||
grub_hfsplus_iterate_dir (fdiro, iterate);
|
||||
grub_hfsplus_iterate_dir (fdiro, grub_hfsplus_dir_iter, &ctx);
|
||||
|
||||
fail:
|
||||
if (data && fdiro != &data->dirroot)
|
||||
|
|
|
@ -521,10 +521,7 @@ get_node_size (grub_fshelp_node_t node)
|
|||
|
||||
static int
|
||||
grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
|
||||
int NESTED_FUNC_ATTR
|
||||
(*hook) (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node))
|
||||
grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
struct grub_iso9660_dir dirent;
|
||||
grub_off_t offset = 0;
|
||||
|
@ -828,7 +825,7 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
|
|||
symlink = 0;
|
||||
was_continue = 0;
|
||||
}
|
||||
if (hook (filename, type, node))
|
||||
if (hook (filename, type, node, hook_data))
|
||||
{
|
||||
if (filename_alloc)
|
||||
grub_free (filename);
|
||||
|
@ -844,32 +841,39 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
||||
|
||||
|
||||
/* Context for grub_iso9660_dir. */
|
||||
struct grub_iso9660_dir_ctx
|
||||
{
|
||||
grub_fs_dir_hook_t hook;
|
||||
void *hook_data;
|
||||
};
|
||||
|
||||
/* Helper for grub_iso9660_dir. */
|
||||
static int
|
||||
grub_iso9660_dir_iter (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node, void *data)
|
||||
{
|
||||
struct grub_iso9660_dir_ctx *ctx = data;
|
||||
struct grub_dirhook_info info;
|
||||
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
info.mtimeset = !!iso9660_to_unixtime2 (&node->dirents[0].mtime, &info.mtime);
|
||||
|
||||
grub_free (node);
|
||||
return ctx->hook (filename, &info, ctx->hook_data);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_iso9660_dir (grub_device_t device, const char *path,
|
||||
int (*hook) (const char *filename,
|
||||
const struct grub_dirhook_info *info))
|
||||
grub_fs_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
struct grub_iso9660_dir_ctx ctx = { hook, hook_data };
|
||||
struct grub_iso9660_data *data = 0;
|
||||
struct grub_fshelp_node rootnode;
|
||||
struct grub_fshelp_node *foundnode;
|
||||
|
||||
auto int NESTED_FUNC_ATTR iterate (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node);
|
||||
|
||||
int NESTED_FUNC_ATTR iterate (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node)
|
||||
{
|
||||
struct grub_dirhook_info info;
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
info.mtimeset = !!iso9660_to_unixtime2 (&node->dirents[0].mtime, &info.mtime);
|
||||
|
||||
grub_free (node);
|
||||
return hook (filename, &info);
|
||||
}
|
||||
|
||||
grub_dl_ref (my_mod);
|
||||
|
||||
data = grub_iso9660_mount (device->disk);
|
||||
|
@ -891,7 +895,7 @@ grub_iso9660_dir (grub_device_t device, const char *path,
|
|||
goto fail;
|
||||
|
||||
/* List the files in the directory. */
|
||||
grub_iso9660_iterate_dir (foundnode, iterate);
|
||||
grub_iso9660_iterate_dir (foundnode, grub_iso9660_dir_iter, &ctx);
|
||||
|
||||
if (foundnode != &rootnode)
|
||||
grub_free (foundnode);
|
||||
|
|
|
@ -799,8 +799,7 @@ grub_jfs_lookup_symlink (struct grub_jfs_data *data, grub_uint32_t ino)
|
|||
|
||||
static grub_err_t
|
||||
grub_jfs_dir (grub_device_t device, const char *path,
|
||||
int (*hook) (const char *filename,
|
||||
const struct grub_dirhook_info *info))
|
||||
grub_fs_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
struct grub_jfs_data *data = 0;
|
||||
struct grub_jfs_diropen *diro = 0;
|
||||
|
@ -832,7 +831,7 @@ grub_jfs_dir (grub_device_t device, const char *path,
|
|||
& GRUB_JFS_FILETYPE_MASK) == GRUB_JFS_FILETYPE_DIR;
|
||||
info.mtimeset = 1;
|
||||
info.mtime = grub_le_to_cpu32 (inode.mtime.sec);
|
||||
if (hook (diro->name, &info))
|
||||
if (hook (diro->name, &info, hook_data))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
|
@ -536,8 +536,7 @@ grub_minix_mount (grub_disk_t disk)
|
|||
|
||||
static grub_err_t
|
||||
grub_minix_dir (grub_device_t device, const char *path,
|
||||
int (*hook) (const char *filename,
|
||||
const struct grub_dirhook_info *info))
|
||||
grub_fs_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
struct grub_minix_data *data = 0;
|
||||
unsigned int pos = 0;
|
||||
|
@ -590,7 +589,7 @@ grub_minix_dir (grub_device_t device, const char *path,
|
|||
info.mtimeset = 1;
|
||||
info.mtime = grub_minix_to_cpu32 (data->inode.mtime);
|
||||
|
||||
if (hook (filename, &info) ? 1 : 0)
|
||||
if (hook (filename, &info, hook_data) ? 1 : 0)
|
||||
break;
|
||||
|
||||
/* Load the old inode back in. */
|
||||
|
|
|
@ -870,10 +870,7 @@ grub_nilfs2_read_symlink (grub_fshelp_node_t node)
|
|||
|
||||
static int
|
||||
grub_nilfs2_iterate_dir (grub_fshelp_node_t dir,
|
||||
int NESTED_FUNC_ATTR
|
||||
(*hook) (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node))
|
||||
grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
grub_off_t fpos = 0;
|
||||
struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir;
|
||||
|
@ -957,7 +954,7 @@ grub_nilfs2_iterate_dir (grub_fshelp_node_t dir,
|
|||
type = GRUB_FSHELP_REG;
|
||||
}
|
||||
|
||||
if (hook (filename, type, fdiro))
|
||||
if (hook (filename, type, fdiro, hook_data))
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1032,60 +1029,69 @@ grub_nilfs2_read (grub_file_t file, char *buf, grub_size_t len)
|
|||
file->offset, len, buf);
|
||||
}
|
||||
|
||||
/* Context for grub_nilfs2_dir. */
|
||||
struct grub_nilfs2_dir_ctx
|
||||
{
|
||||
grub_fs_dir_hook_t hook;
|
||||
void *hook_data;
|
||||
struct grub_nilfs2_data *data;
|
||||
};
|
||||
|
||||
/* Helper for grub_nilfs2_dir. */
|
||||
static int
|
||||
grub_nilfs2_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node, void *data)
|
||||
{
|
||||
struct grub_nilfs2_dir_ctx *ctx = data;
|
||||
struct grub_dirhook_info info;
|
||||
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
if (!node->inode_read)
|
||||
{
|
||||
grub_nilfs2_read_inode (ctx->data, node->ino, &node->inode);
|
||||
if (!grub_errno)
|
||||
node->inode_read = 1;
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
if (node->inode_read)
|
||||
{
|
||||
info.mtimeset = 1;
|
||||
info.mtime = grub_le_to_cpu64 (node->inode.i_mtime);
|
||||
}
|
||||
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
grub_free (node);
|
||||
return ctx->hook (filename, &info, ctx->hook_data);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_nilfs2_dir (grub_device_t device, const char *path,
|
||||
int (*hook) (const char *filename,
|
||||
const struct grub_dirhook_info * info))
|
||||
grub_fs_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
struct grub_nilfs2_data *data = 0;
|
||||
struct grub_nilfs2_dir_ctx ctx = {
|
||||
.hook = hook,
|
||||
.hook_data = hook_data
|
||||
};
|
||||
struct grub_fshelp_node *fdiro = 0;
|
||||
|
||||
auto int NESTED_FUNC_ATTR iterate (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node);
|
||||
|
||||
int NESTED_FUNC_ATTR iterate (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node)
|
||||
{
|
||||
struct grub_dirhook_info info;
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
if (!node->inode_read)
|
||||
{
|
||||
grub_nilfs2_read_inode (data, node->ino, &node->inode);
|
||||
if (!grub_errno)
|
||||
node->inode_read = 1;
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
if (node->inode_read)
|
||||
{
|
||||
info.mtimeset = 1;
|
||||
info.mtime = grub_le_to_cpu64 (node->inode.i_mtime);
|
||||
}
|
||||
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
grub_free (node);
|
||||
return hook (filename, &info);
|
||||
}
|
||||
|
||||
grub_dl_ref (my_mod);
|
||||
|
||||
data = grub_nilfs2_mount (device->disk);
|
||||
if (!data)
|
||||
ctx.data = grub_nilfs2_mount (device->disk);
|
||||
if (!ctx.data)
|
||||
goto fail;
|
||||
|
||||
grub_fshelp_find_file (path, &data->diropen, &fdiro,
|
||||
grub_fshelp_find_file (path, &ctx.data->diropen, &fdiro,
|
||||
grub_nilfs2_iterate_dir, grub_nilfs2_read_symlink,
|
||||
GRUB_FSHELP_DIR);
|
||||
if (grub_errno)
|
||||
goto fail;
|
||||
|
||||
grub_nilfs2_iterate_dir (fdiro, iterate);
|
||||
grub_nilfs2_iterate_dir (fdiro, grub_nilfs2_dir_iter, &ctx);
|
||||
|
||||
fail:
|
||||
if (fdiro != &data->diropen)
|
||||
if (fdiro != &ctx.data->diropen)
|
||||
grub_free (fdiro);
|
||||
grub_free (data);
|
||||
grub_free (ctx.data);
|
||||
|
||||
grub_dl_unref (my_mod);
|
||||
|
||||
|
|
|
@ -600,10 +600,7 @@ free_file (struct grub_ntfs_file *mft)
|
|||
|
||||
static int
|
||||
list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos,
|
||||
int NESTED_FUNC_ATTR
|
||||
(*hook) (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node))
|
||||
grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
grub_uint8_t *np;
|
||||
int ns;
|
||||
|
@ -667,7 +664,7 @@ list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos,
|
|||
if (namespace)
|
||||
type |= GRUB_FSHELP_CASE_INSENSITIVE;
|
||||
|
||||
if (hook (ustr, type, fdiro))
|
||||
if (hook (ustr, type, fdiro, hook_data))
|
||||
{
|
||||
grub_free (ustr);
|
||||
return 1;
|
||||
|
@ -778,10 +775,7 @@ grub_ntfs_read_symlink (grub_fshelp_node_t node)
|
|||
|
||||
static int
|
||||
grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
|
||||
int NESTED_FUNC_ATTR
|
||||
(*hook) (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node))
|
||||
grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
grub_uint8_t *bitmap;
|
||||
struct grub_ntfs_attr attr, *at;
|
||||
|
@ -824,7 +818,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
|
|||
}
|
||||
|
||||
cur_pos += 0x10; /* Skip index root */
|
||||
ret = list_file (mft, cur_pos + u16at (cur_pos, 0), hook);
|
||||
ret = list_file (mft, cur_pos + u16at (cur_pos, 0), hook, hook_data);
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
|
@ -909,7 +903,8 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
|
|||
|| (fixup (indx, mft->data->idx_size,
|
||||
(const grub_uint8_t *) "INDX")))
|
||||
goto done;
|
||||
ret = list_file (mft, &indx[0x18 + u16at (indx, 0x18)], hook);
|
||||
ret = list_file (mft, &indx[0x18 + u16at (indx, 0x18)],
|
||||
hook, hook_data);
|
||||
if (ret)
|
||||
goto done;
|
||||
}
|
||||
|
@ -1017,33 +1012,39 @@ fail:
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Context for grub_ntfs_dir. */
|
||||
struct grub_ntfs_dir_ctx
|
||||
{
|
||||
grub_fs_dir_hook_t hook;
|
||||
void *hook_data;
|
||||
};
|
||||
|
||||
/* Helper for grub_ntfs_dir. */
|
||||
static int
|
||||
grub_ntfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node, void *data)
|
||||
{
|
||||
struct grub_ntfs_dir_ctx *ctx = data;
|
||||
struct grub_dirhook_info info;
|
||||
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
info.mtimeset = 1;
|
||||
info.mtime = grub_divmod64 (node->mtime, 10000000, 0)
|
||||
- 86400ULL * 365 * (1970 - 1601)
|
||||
- 86400ULL * ((1970 - 1601) / 4) + 86400ULL * ((1970 - 1601) / 100);
|
||||
grub_free (node);
|
||||
return ctx->hook (filename, &info, ctx->hook_data);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_ntfs_dir (grub_device_t device, const char *path,
|
||||
int (*hook) (const char *filename,
|
||||
const struct grub_dirhook_info *info))
|
||||
grub_fs_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
struct grub_ntfs_dir_ctx ctx = { hook, hook_data };
|
||||
struct grub_ntfs_data *data = 0;
|
||||
struct grub_fshelp_node *fdiro = 0;
|
||||
|
||||
auto int NESTED_FUNC_ATTR iterate (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node);
|
||||
|
||||
int NESTED_FUNC_ATTR iterate (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node)
|
||||
{
|
||||
struct grub_dirhook_info info;
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
info.mtimeset = 1;
|
||||
info.mtime = grub_divmod64 (node->mtime, 10000000, 0)
|
||||
- 86400ULL * 365 * (1970 - 1601)
|
||||
- 86400ULL * ((1970 - 1601) / 4) + 86400ULL * ((1970 - 1601) / 100);
|
||||
grub_free (node);
|
||||
return hook (filename, &info);
|
||||
}
|
||||
|
||||
grub_dl_ref (my_mod);
|
||||
|
||||
data = grub_ntfs_mount (device->disk);
|
||||
|
@ -1056,7 +1057,7 @@ grub_ntfs_dir (grub_device_t device, const char *path,
|
|||
if (grub_errno)
|
||||
goto fail;
|
||||
|
||||
grub_ntfs_iterate_dir (fdiro, iterate);
|
||||
grub_ntfs_iterate_dir (fdiro, grub_ntfs_dir_iter, &ctx);
|
||||
|
||||
fail:
|
||||
if ((fdiro) && (fdiro != &data->cmft))
|
||||
|
|
|
@ -718,10 +718,8 @@ grub_reiserfs_mount (grub_disk_t disk)
|
|||
/* Call HOOK for each file in directory ITEM. */
|
||||
static int
|
||||
grub_reiserfs_iterate_dir (grub_fshelp_node_t item,
|
||||
int NESTED_FUNC_ATTR
|
||||
(*hook) (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node))
|
||||
grub_fshelp_iterate_dir_hook_t hook,
|
||||
void *hook_data)
|
||||
{
|
||||
struct grub_reiserfs_data *data = item->data;
|
||||
struct grub_reiserfs_block_header *block_header = 0;
|
||||
|
@ -946,7 +944,7 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item,
|
|||
goto next;
|
||||
}
|
||||
}
|
||||
if (hook (entry_name, entry_type, entry_item))
|
||||
if (hook (entry_name, entry_type, entry_item, hook_data))
|
||||
{
|
||||
grub_dprintf ("reiserfs", "Found : %s, type=%d\n",
|
||||
entry_name, entry_type);
|
||||
|
@ -1254,32 +1252,40 @@ grub_reiserfs_close (grub_file_t file)
|
|||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
/* Context for grub_reiserfs_dir. */
|
||||
struct grub_reiserfs_dir_ctx
|
||||
{
|
||||
grub_fs_dir_hook_t hook;
|
||||
void *hook_data;
|
||||
};
|
||||
|
||||
/* Helper for grub_reiserfs_dir. */
|
||||
static int
|
||||
grub_reiserfs_dir_iter (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node, void *data)
|
||||
{
|
||||
struct grub_reiserfs_dir_ctx *ctx = data;
|
||||
struct grub_dirhook_info info;
|
||||
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
info.mtimeset = 1;
|
||||
info.mtime = node->mtime;
|
||||
grub_free (node);
|
||||
return ctx->hook (filename, &info, ctx->hook_data);
|
||||
}
|
||||
|
||||
/* Call HOOK with each file under DIR. */
|
||||
static grub_err_t
|
||||
grub_reiserfs_dir (grub_device_t device, const char *path,
|
||||
int (*hook) (const char *filename,
|
||||
const struct grub_dirhook_info *info))
|
||||
grub_fs_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
struct grub_reiserfs_dir_ctx ctx = { hook, hook_data };
|
||||
struct grub_reiserfs_data *data = 0;
|
||||
struct grub_fshelp_node root, *found;
|
||||
struct grub_reiserfs_key root_key;
|
||||
|
||||
auto int NESTED_FUNC_ATTR iterate (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node);
|
||||
|
||||
int NESTED_FUNC_ATTR iterate (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node)
|
||||
{
|
||||
struct grub_dirhook_info info;
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
info.mtimeset = 1;
|
||||
info.mtime = node->mtime;
|
||||
grub_free (node);
|
||||
return hook (filename, &info);
|
||||
}
|
||||
grub_dl_ref (my_mod);
|
||||
data = grub_reiserfs_mount (device->disk);
|
||||
if (! data)
|
||||
|
@ -1300,7 +1306,7 @@ grub_reiserfs_dir (grub_device_t device, const char *path,
|
|||
grub_reiserfs_read_symlink, GRUB_FSHELP_DIR);
|
||||
if (grub_errno)
|
||||
goto fail;
|
||||
grub_reiserfs_iterate_dir (found, iterate);
|
||||
grub_reiserfs_iterate_dir (found, grub_reiserfs_dir_iter, &ctx);
|
||||
grub_free (data);
|
||||
grub_dl_unref (my_mod);
|
||||
return GRUB_ERR_NONE;
|
||||
|
|
|
@ -171,10 +171,7 @@ grub_romfs_read_symlink (grub_fshelp_node_t node)
|
|||
|
||||
static int
|
||||
grub_romfs_iterate_dir (grub_fshelp_node_t dir,
|
||||
int NESTED_FUNC_ATTR
|
||||
(*hook) (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node))
|
||||
grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
grub_disk_addr_t caddr;
|
||||
struct grub_romfs_file_header hdr;
|
||||
|
@ -306,7 +303,7 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir,
|
|||
}
|
||||
}
|
||||
|
||||
if (hook ((char *) name, filetype, node))
|
||||
if (hook ((char *) name, filetype, node, hook_data))
|
||||
{
|
||||
grub_free (name);
|
||||
return 1;
|
||||
|
@ -316,30 +313,36 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Context for grub_romfs_dir. */
|
||||
struct grub_romfs_dir_ctx
|
||||
{
|
||||
grub_fs_dir_hook_t hook;
|
||||
void *hook_data;
|
||||
};
|
||||
|
||||
/* Helper for grub_romfs_dir. */
|
||||
static int
|
||||
grub_romfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node, void *data)
|
||||
{
|
||||
struct grub_romfs_dir_ctx *ctx = data;
|
||||
struct grub_dirhook_info info;
|
||||
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
grub_free (node);
|
||||
return ctx->hook (filename, &info, ctx->hook_data);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_romfs_dir (grub_device_t device, const char *path,
|
||||
int (*hook) (const char *filename,
|
||||
const struct grub_dirhook_info *info))
|
||||
grub_fs_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
struct grub_romfs_dir_ctx ctx = { hook, hook_data };
|
||||
struct grub_romfs_data *data = 0;
|
||||
struct grub_fshelp_node *fdiro = 0, start;
|
||||
|
||||
auto int NESTED_FUNC_ATTR iterate (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node);
|
||||
|
||||
int NESTED_FUNC_ATTR iterate (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node)
|
||||
{
|
||||
struct grub_dirhook_info info;
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
grub_free (node);
|
||||
return hook (filename, &info);
|
||||
}
|
||||
|
||||
data = grub_romfs_mount (device);
|
||||
if (! data)
|
||||
goto fail;
|
||||
|
@ -352,7 +355,7 @@ grub_romfs_dir (grub_device_t device, const char *path,
|
|||
if (grub_errno)
|
||||
goto fail;
|
||||
|
||||
grub_romfs_iterate_dir (fdiro, iterate);
|
||||
grub_romfs_iterate_dir (fdiro, grub_romfs_dir_iter, &ctx);
|
||||
|
||||
fail:
|
||||
grub_free (data);
|
||||
|
|
|
@ -460,12 +460,48 @@ grub_sfs_read_symlink (grub_fshelp_node_t node)
|
|||
return symlink;
|
||||
}
|
||||
|
||||
/* Helper for grub_sfs_iterate_dir. */
|
||||
static int
|
||||
grub_sfs_create_node (struct grub_fshelp_node **node,
|
||||
struct grub_sfs_data *data,
|
||||
const char *name,
|
||||
grub_uint32_t block, grub_uint32_t size, int type,
|
||||
grub_uint32_t mtime,
|
||||
grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
grub_size_t len = grub_strlen (name);
|
||||
grub_uint8_t *name_u8;
|
||||
int ret;
|
||||
*node = grub_malloc (sizeof (**node));
|
||||
if (!*node)
|
||||
return 1;
|
||||
name_u8 = grub_malloc (len * GRUB_MAX_UTF8_PER_LATIN1 + 1);
|
||||
if (!name_u8)
|
||||
{
|
||||
grub_free (*node);
|
||||
return 1;
|
||||
}
|
||||
|
||||
(*node)->data = data;
|
||||
(*node)->size = size;
|
||||
(*node)->block = block;
|
||||
(*node)->mtime = mtime;
|
||||
(*node)->cache = 0;
|
||||
(*node)->cache_off = 0;
|
||||
(*node)->next_extent = block;
|
||||
(*node)->cache_size = 0;
|
||||
(*node)->cache_allocated = 0;
|
||||
|
||||
*grub_latin1_to_utf8 (name_u8, (const grub_uint8_t *) name, len) = '\0';
|
||||
|
||||
ret = hook ((char *) name_u8, type | data->fshelp_flags, *node, hook_data);
|
||||
grub_free (name_u8);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
grub_sfs_iterate_dir (grub_fshelp_node_t dir,
|
||||
int NESTED_FUNC_ATTR
|
||||
(*hook) (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node))
|
||||
grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
struct grub_fshelp_node *node = 0;
|
||||
struct grub_sfs_data *data = dir->data;
|
||||
|
@ -474,46 +510,6 @@ grub_sfs_iterate_dir (grub_fshelp_node_t dir,
|
|||
unsigned int next = dir->block;
|
||||
grub_uint32_t pos;
|
||||
|
||||
auto int NESTED_FUNC_ATTR grub_sfs_create_node (const char *name,
|
||||
grub_uint32_t block,
|
||||
grub_uint32_t size, int type,
|
||||
grub_uint32_t mtime);
|
||||
|
||||
int NESTED_FUNC_ATTR grub_sfs_create_node (const char *name,
|
||||
grub_uint32_t block,
|
||||
grub_uint32_t size, int type,
|
||||
grub_uint32_t mtime)
|
||||
{
|
||||
grub_size_t len = grub_strlen (name);
|
||||
grub_uint8_t *name_u8;
|
||||
int ret;
|
||||
node = grub_malloc (sizeof (*node));
|
||||
if (!node)
|
||||
return 1;
|
||||
name_u8 = grub_malloc (len * GRUB_MAX_UTF8_PER_LATIN1 + 1);
|
||||
if (!name_u8)
|
||||
{
|
||||
grub_free (node);
|
||||
return 1;
|
||||
}
|
||||
|
||||
node->data = data;
|
||||
node->size = size;
|
||||
node->block = block;
|
||||
node->mtime = mtime;
|
||||
node->cache = 0;
|
||||
node->cache_off = 0;
|
||||
node->next_extent = block;
|
||||
node->cache_size = 0;
|
||||
node->cache_allocated = 0;
|
||||
|
||||
*grub_latin1_to_utf8 (name_u8, (const grub_uint8_t *) name, len) = '\0';
|
||||
|
||||
ret = hook ((char *) name_u8, type | data->fshelp_flags, node);
|
||||
grub_free (name_u8);
|
||||
return ret;
|
||||
}
|
||||
|
||||
objc_data = grub_malloc (GRUB_DISK_SECTOR_SIZE << data->log_blocksize);
|
||||
if (!objc_data)
|
||||
goto fail;
|
||||
|
@ -570,9 +566,10 @@ grub_sfs_iterate_dir (grub_fshelp_node_t dir,
|
|||
else
|
||||
block = grub_be_to_cpu32 (obj->file_dir.file.first_block);
|
||||
|
||||
if (grub_sfs_create_node (filename, block,
|
||||
if (grub_sfs_create_node (&node, data, filename, block,
|
||||
grub_be_to_cpu32 (obj->file_dir.file.size),
|
||||
type, grub_be_to_cpu32 (obj->mtime)))
|
||||
type, grub_be_to_cpu32 (obj->mtime),
|
||||
hook, hook_data))
|
||||
{
|
||||
grub_free (objc_data);
|
||||
return 1;
|
||||
|
@ -654,32 +651,38 @@ grub_sfs_read (grub_file_t file, char *buf, grub_size_t len)
|
|||
}
|
||||
|
||||
|
||||
/* Context for grub_sfs_dir. */
|
||||
struct grub_sfs_dir_ctx
|
||||
{
|
||||
grub_fs_dir_hook_t hook;
|
||||
void *hook_data;
|
||||
};
|
||||
|
||||
/* Helper for grub_sfs_dir. */
|
||||
static int
|
||||
grub_sfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node, void *data)
|
||||
{
|
||||
struct grub_sfs_dir_ctx *ctx = data;
|
||||
struct grub_dirhook_info info;
|
||||
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
info.mtime = node->mtime + 8 * 365 * 86400 + 86400 * 2;
|
||||
info.mtimeset = 1;
|
||||
grub_free (node->cache);
|
||||
grub_free (node);
|
||||
return ctx->hook (filename, &info, ctx->hook_data);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_sfs_dir (grub_device_t device, const char *path,
|
||||
int (*hook) (const char *filename,
|
||||
const struct grub_dirhook_info *info))
|
||||
grub_fs_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
struct grub_sfs_dir_ctx ctx = { hook, hook_data };
|
||||
struct grub_sfs_data *data = 0;
|
||||
struct grub_fshelp_node *fdiro = 0;
|
||||
|
||||
auto int NESTED_FUNC_ATTR iterate (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node);
|
||||
|
||||
int NESTED_FUNC_ATTR iterate (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node)
|
||||
{
|
||||
struct grub_dirhook_info info;
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
info.mtime = node->mtime + 8 * 365 * 86400 + 86400 * 2;
|
||||
info.mtimeset = 1;
|
||||
grub_free (node->cache);
|
||||
grub_free (node);
|
||||
return hook (filename, &info);
|
||||
}
|
||||
|
||||
grub_dl_ref (my_mod);
|
||||
|
||||
data = grub_sfs_mount (device->disk);
|
||||
|
@ -691,7 +694,7 @@ grub_sfs_dir (grub_device_t device, const char *path,
|
|||
if (grub_errno)
|
||||
goto fail;
|
||||
|
||||
grub_sfs_iterate_dir (fdiro, iterate);
|
||||
grub_sfs_iterate_dir (fdiro, grub_sfs_dir_iter, &ctx);
|
||||
|
||||
fail:
|
||||
if (data && fdiro != &data->diropen)
|
||||
|
|
|
@ -478,10 +478,7 @@ grub_squash_read_symlink (grub_fshelp_node_t node)
|
|||
|
||||
static int
|
||||
grub_squash_iterate_dir (grub_fshelp_node_t dir,
|
||||
int NESTED_FUNC_ATTR
|
||||
(*hook) (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node))
|
||||
grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
grub_uint32_t off;
|
||||
grub_uint32_t endoff;
|
||||
|
@ -514,7 +511,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
|
|||
return 0;
|
||||
grub_memcpy (node, dir,
|
||||
sizeof (*node) + dir->stsize * sizeof (dir->stack[0]));
|
||||
if (hook (".", GRUB_FSHELP_DIR, node))
|
||||
if (hook (".", GRUB_FSHELP_DIR, node, hook_data))
|
||||
return 1;
|
||||
|
||||
if (dir->stsize != 1)
|
||||
|
@ -536,7 +533,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
|
|||
if (err)
|
||||
return 0;
|
||||
|
||||
if (hook ("..", GRUB_FSHELP_DIR, node))
|
||||
if (hook ("..", GRUB_FSHELP_DIR, node, hook_data))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -604,7 +601,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
|
|||
node->stack[node->stsize].ino_chunk = grub_le_to_cpu32 (dh.ino_chunk);
|
||||
node->stack[node->stsize].ino_offset = grub_le_to_cpu16 (di.ino_offset);
|
||||
node->stsize++;
|
||||
r = hook (buf, filetype, node);
|
||||
r = hook (buf, filetype, node, hook_data);
|
||||
|
||||
grub_free (buf);
|
||||
if (r)
|
||||
|
@ -640,28 +637,34 @@ squash_unmount (struct grub_squash_data *data)
|
|||
}
|
||||
|
||||
|
||||
/* Context for grub_squash_dir. */
|
||||
struct grub_squash_dir_ctx
|
||||
{
|
||||
grub_fs_dir_hook_t hook;
|
||||
void *hook_data;
|
||||
};
|
||||
|
||||
/* Helper for grub_squash_dir. */
|
||||
static int
|
||||
grub_squash_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node, void *data)
|
||||
{
|
||||
struct grub_squash_dir_ctx *ctx = data;
|
||||
struct grub_dirhook_info info;
|
||||
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
info.mtimeset = 1;
|
||||
info.mtime = grub_le_to_cpu32 (node->ino.mtime);
|
||||
grub_free (node);
|
||||
return ctx->hook (filename, &info, ctx->hook_data);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_squash_dir (grub_device_t device, const char *path,
|
||||
int (*hook) (const char *filename,
|
||||
const struct grub_dirhook_info *info))
|
||||
grub_fs_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
auto int NESTED_FUNC_ATTR iterate (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node);
|
||||
|
||||
int NESTED_FUNC_ATTR iterate (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node)
|
||||
{
|
||||
struct grub_dirhook_info info;
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
info.mtimeset = 1;
|
||||
info.mtime = grub_le_to_cpu32 (node->ino.mtime);
|
||||
grub_free (node);
|
||||
return hook (filename, &info);
|
||||
}
|
||||
|
||||
struct grub_squash_dir_ctx ctx = { hook, hook_data };
|
||||
struct grub_squash_data *data = 0;
|
||||
struct grub_fshelp_node *fdiro = 0;
|
||||
struct grub_fshelp_node root;
|
||||
|
@ -678,7 +681,7 @@ grub_squash_dir (grub_device_t device, const char *path,
|
|||
grub_fshelp_find_file (path, &root, &fdiro, grub_squash_iterate_dir,
|
||||
grub_squash_read_symlink, GRUB_FSHELP_DIR);
|
||||
if (!grub_errno)
|
||||
grub_squash_iterate_dir (fdiro, iterate);
|
||||
grub_squash_iterate_dir (fdiro, grub_squash_dir_iter, &ctx);
|
||||
|
||||
squash_unmount (data);
|
||||
|
||||
|
|
|
@ -843,10 +843,7 @@ read_string (const grub_uint8_t *raw, grub_size_t sz, char *outbuf)
|
|||
|
||||
static int
|
||||
grub_udf_iterate_dir (grub_fshelp_node_t dir,
|
||||
int NESTED_FUNC_ATTR
|
||||
(*hook) (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node))
|
||||
grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
grub_fshelp_node_t child;
|
||||
struct grub_udf_file_ident dirent;
|
||||
|
@ -859,7 +856,7 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir,
|
|||
/* The current directory is not stored. */
|
||||
grub_memcpy (child, dir, get_fshelp_size (dir->data));
|
||||
|
||||
if (hook (".", GRUB_FSHELP_DIR, child))
|
||||
if (hook (".", GRUB_FSHELP_DIR, child, hook_data))
|
||||
return 1;
|
||||
|
||||
while (offset < U64 (dir->block.fe.file_size))
|
||||
|
@ -887,7 +884,7 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir,
|
|||
if (dirent.characteristics & GRUB_UDF_FID_CHAR_PARENT)
|
||||
{
|
||||
/* This is the parent directory. */
|
||||
if (hook ("..", GRUB_FSHELP_DIR, child))
|
||||
if (hook ("..", GRUB_FSHELP_DIR, child, hook_data))
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
|
@ -911,7 +908,7 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir,
|
|||
if (!filename)
|
||||
grub_print_error ();
|
||||
|
||||
if (filename && hook (filename, type, child))
|
||||
if (filename && hook (filename, type, child, hook_data))
|
||||
{
|
||||
grub_free (filename);
|
||||
return 1;
|
||||
|
@ -1012,58 +1009,64 @@ grub_udf_read_symlink (grub_fshelp_node_t node)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* Context for grub_udf_dir. */
|
||||
struct grub_udf_dir_ctx
|
||||
{
|
||||
grub_fs_dir_hook_t hook;
|
||||
void *hook_data;
|
||||
};
|
||||
|
||||
/* Helper for grub_udf_dir. */
|
||||
static int
|
||||
grub_udf_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node, void *data)
|
||||
{
|
||||
struct grub_udf_dir_ctx *ctx = data;
|
||||
struct grub_dirhook_info info;
|
||||
const struct grub_udf_timestamp *tstamp = NULL;
|
||||
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
if (U16 (node->block.fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_FE)
|
||||
tstamp = &node->block.fe.modification_time;
|
||||
else if (U16 (node->block.fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_EFE)
|
||||
tstamp = &node->block.efe.modification_time;
|
||||
|
||||
if (tstamp && (U16 (tstamp->type_and_timezone) & 0xf000) == 0x1000)
|
||||
{
|
||||
grub_int16_t tz;
|
||||
struct grub_datetime datetime;
|
||||
|
||||
datetime.year = U16 (tstamp->year);
|
||||
datetime.month = tstamp->month;
|
||||
datetime.day = tstamp->day;
|
||||
datetime.hour = tstamp->hour;
|
||||
datetime.minute = tstamp->minute;
|
||||
datetime.second = tstamp->second;
|
||||
|
||||
tz = U16 (tstamp->type_and_timezone) & 0xfff;
|
||||
if (tz & 0x800)
|
||||
tz |= 0xf000;
|
||||
if (tz == -2047)
|
||||
tz = 0;
|
||||
|
||||
info.mtimeset = !!grub_datetime2unixtime (&datetime, &info.mtime);
|
||||
|
||||
info.mtime -= 60 * tz;
|
||||
}
|
||||
grub_free (node);
|
||||
return ctx->hook (filename, &info, ctx->hook_data);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_udf_dir (grub_device_t device, const char *path,
|
||||
int (*hook) (const char *filename,
|
||||
const struct grub_dirhook_info *info))
|
||||
grub_fs_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
struct grub_udf_dir_ctx ctx = { hook, hook_data };
|
||||
struct grub_udf_data *data = 0;
|
||||
struct grub_fshelp_node *rootnode = 0;
|
||||
struct grub_fshelp_node *foundnode = 0;
|
||||
|
||||
auto int NESTED_FUNC_ATTR iterate (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node);
|
||||
|
||||
int NESTED_FUNC_ATTR iterate (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node)
|
||||
{
|
||||
struct grub_dirhook_info info;
|
||||
const struct grub_udf_timestamp *tstamp = NULL;
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
if (U16 (node->block.fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_FE)
|
||||
tstamp = &node->block.fe.modification_time;
|
||||
else if (U16 (node->block.fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_EFE)
|
||||
tstamp = &node->block.efe.modification_time;
|
||||
|
||||
if (tstamp && (U16 (tstamp->type_and_timezone) & 0xf000) == 0x1000)
|
||||
{
|
||||
grub_int16_t tz;
|
||||
struct grub_datetime datetime;
|
||||
|
||||
datetime.year = U16 (tstamp->year);
|
||||
datetime.month = tstamp->month;
|
||||
datetime.day = tstamp->day;
|
||||
datetime.hour = tstamp->hour;
|
||||
datetime.minute = tstamp->minute;
|
||||
datetime.second = tstamp->second;
|
||||
|
||||
tz = U16 (tstamp->type_and_timezone) & 0xfff;
|
||||
if (tz & 0x800)
|
||||
tz |= 0xf000;
|
||||
if (tz == -2047)
|
||||
tz = 0;
|
||||
|
||||
info.mtimeset = !!grub_datetime2unixtime (&datetime, &info.mtime);
|
||||
|
||||
info.mtime -= 60 * tz;
|
||||
}
|
||||
grub_free (node);
|
||||
return hook (filename, &info);
|
||||
}
|
||||
|
||||
grub_dl_ref (my_mod);
|
||||
|
||||
data = grub_udf_mount (device->disk);
|
||||
|
@ -1083,7 +1086,7 @@ grub_udf_dir (grub_device_t device, const char *path,
|
|||
GRUB_FSHELP_DIR))
|
||||
goto fail;
|
||||
|
||||
grub_udf_iterate_dir (foundnode, iterate);
|
||||
grub_udf_iterate_dir (foundnode, grub_udf_dir_iter, &ctx);
|
||||
|
||||
if (foundnode != rootnode)
|
||||
grub_free (foundnode);
|
||||
|
|
|
@ -625,8 +625,7 @@ grub_ufs_mount (grub_disk_t disk)
|
|||
|
||||
static grub_err_t
|
||||
grub_ufs_dir (grub_device_t device, const char *path,
|
||||
int (*hook) (const char *filename,
|
||||
const struct grub_dirhook_info *info))
|
||||
grub_fs_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
struct grub_ufs_data *data;
|
||||
unsigned int pos = 0;
|
||||
|
@ -697,7 +696,7 @@ grub_ufs_dir (grub_device_t device, const char *path,
|
|||
#endif
|
||||
info.mtimeset = 1;
|
||||
|
||||
if (hook (filename, &info))
|
||||
if (hook (filename, &info, hook_data))
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -443,46 +443,56 @@ grub_xfs_mode_to_filetype (grub_uint16_t mode)
|
|||
}
|
||||
|
||||
|
||||
/* Context for grub_xfs_iterate_dir. */
|
||||
struct grub_xfs_iterate_dir_ctx
|
||||
{
|
||||
grub_fshelp_iterate_dir_hook_t hook;
|
||||
void *hook_data;
|
||||
struct grub_fshelp_node *diro;
|
||||
};
|
||||
|
||||
/* Helper for grub_xfs_iterate_dir. */
|
||||
static int iterate_dir_call_hook (grub_uint64_t ino, const char *filename,
|
||||
struct grub_xfs_iterate_dir_ctx *ctx)
|
||||
{
|
||||
struct grub_fshelp_node *fdiro;
|
||||
grub_err_t err;
|
||||
|
||||
fdiro = grub_malloc (sizeof (struct grub_fshelp_node)
|
||||
- sizeof (struct grub_xfs_inode)
|
||||
+ (1 << ctx->diro->data->sblock.log2_inode));
|
||||
if (!fdiro)
|
||||
{
|
||||
grub_print_error ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The inode should be read, otherwise the filetype can
|
||||
not be determined. */
|
||||
fdiro->ino = ino;
|
||||
fdiro->inode_read = 1;
|
||||
fdiro->data = ctx->diro->data;
|
||||
err = grub_xfs_read_inode (ctx->diro->data, ino, &fdiro->inode);
|
||||
if (err)
|
||||
{
|
||||
grub_print_error ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ctx->hook (filename, grub_xfs_mode_to_filetype (fdiro->inode.mode),
|
||||
fdiro, ctx->hook_data);
|
||||
}
|
||||
|
||||
static int
|
||||
grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||
int NESTED_FUNC_ATTR
|
||||
(*hook) (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node))
|
||||
grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir;
|
||||
auto int NESTED_FUNC_ATTR call_hook (grub_uint64_t ino, const char *filename);
|
||||
|
||||
int NESTED_FUNC_ATTR call_hook (grub_uint64_t ino, const char *filename)
|
||||
{
|
||||
struct grub_fshelp_node *fdiro;
|
||||
grub_err_t err;
|
||||
|
||||
fdiro = grub_malloc (sizeof (struct grub_fshelp_node)
|
||||
- sizeof (struct grub_xfs_inode)
|
||||
+ (1 << diro->data->sblock.log2_inode));
|
||||
if (!fdiro)
|
||||
{
|
||||
grub_print_error ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The inode should be read, otherwise the filetype can
|
||||
not be determined. */
|
||||
fdiro->ino = ino;
|
||||
fdiro->inode_read = 1;
|
||||
fdiro->data = diro->data;
|
||||
err = grub_xfs_read_inode (diro->data, ino, &fdiro->inode);
|
||||
if (err)
|
||||
{
|
||||
grub_print_error ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return hook (filename,
|
||||
grub_xfs_mode_to_filetype (fdiro->inode.mode),
|
||||
fdiro);
|
||||
}
|
||||
struct grub_xfs_iterate_dir_ctx ctx = {
|
||||
.hook = hook,
|
||||
.hook_data = hook_data,
|
||||
.diro = diro
|
||||
};
|
||||
|
||||
switch (diro->inode.format)
|
||||
{
|
||||
|
@ -508,10 +518,10 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
|||
}
|
||||
|
||||
/* Synthesize the direntries for `.' and `..'. */
|
||||
if (call_hook (diro->ino, "."))
|
||||
if (iterate_dir_call_hook (diro->ino, ".", &ctx))
|
||||
return 1;
|
||||
|
||||
if (call_hook (parent, ".."))
|
||||
if (iterate_dir_call_hook (parent, "..", &ctx))
|
||||
return 1;
|
||||
|
||||
for (i = 0; i < diro->inode.data.dir.dirhead.count; i++)
|
||||
|
@ -541,7 +551,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
||||
grub_memcpy (name, de->name, de->len);
|
||||
name[de->len] = '\0';
|
||||
if (call_hook (ino, name))
|
||||
if (iterate_dir_call_hook (ino, name, &ctx))
|
||||
return 1;
|
||||
|
||||
de = ((struct grub_xfs_dir_entry *)
|
||||
|
@ -619,7 +629,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
|||
is not used by GRUB. So it can be overwritten. */
|
||||
filename[direntry->len] = '\0';
|
||||
|
||||
if (call_hook (direntry->inode, filename))
|
||||
if (iterate_dir_call_hook (direntry->inode, filename, &ctx))
|
||||
{
|
||||
grub_free (dirblock);
|
||||
return 1;
|
||||
|
@ -703,34 +713,40 @@ grub_xfs_mount (grub_disk_t disk)
|
|||
}
|
||||
|
||||
|
||||
/* Context for grub_xfs_dir. */
|
||||
struct grub_xfs_dir_ctx
|
||||
{
|
||||
grub_fs_dir_hook_t hook;
|
||||
void *hook_data;
|
||||
};
|
||||
|
||||
/* Helper for grub_xfs_dir. */
|
||||
static int
|
||||
grub_xfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node, void *data)
|
||||
{
|
||||
struct grub_xfs_dir_ctx *ctx = data;
|
||||
struct grub_dirhook_info info;
|
||||
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
if (node->inode_read)
|
||||
{
|
||||
info.mtimeset = 1;
|
||||
info.mtime = grub_be_to_cpu32 (node->inode.mtime.sec);
|
||||
}
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
grub_free (node);
|
||||
return ctx->hook (filename, &info, ctx->hook_data);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_xfs_dir (grub_device_t device, const char *path,
|
||||
int (*hook) (const char *filename,
|
||||
const struct grub_dirhook_info *info))
|
||||
grub_fs_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
struct grub_xfs_dir_ctx ctx = { hook, hook_data };
|
||||
struct grub_xfs_data *data = 0;
|
||||
struct grub_fshelp_node *fdiro = 0;
|
||||
|
||||
auto int NESTED_FUNC_ATTR iterate (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node);
|
||||
|
||||
int NESTED_FUNC_ATTR iterate (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node)
|
||||
{
|
||||
struct grub_dirhook_info info;
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
if (node->inode_read)
|
||||
{
|
||||
info.mtimeset = 1;
|
||||
info.mtime = grub_be_to_cpu32 (node->inode.mtime.sec);
|
||||
}
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
grub_free (node);
|
||||
return hook (filename, &info);
|
||||
}
|
||||
|
||||
grub_dl_ref (my_mod);
|
||||
|
||||
data = grub_xfs_mount (device->disk);
|
||||
|
@ -742,7 +758,7 @@ grub_xfs_dir (grub_device_t device, const char *path,
|
|||
if (grub_errno)
|
||||
goto fail;
|
||||
|
||||
grub_xfs_iterate_dir (fdiro, iterate);
|
||||
grub_xfs_iterate_dir (fdiro, grub_xfs_dir_iter, &ctx);
|
||||
|
||||
fail:
|
||||
if (fdiro != &data->diropen)
|
||||
|
|
|
@ -253,6 +253,14 @@ struct grub_zfs_data
|
|||
grub_uint64_t guid;
|
||||
};
|
||||
|
||||
/* Context for grub_zfs_dir. */
|
||||
struct grub_zfs_dir_ctx
|
||||
{
|
||||
grub_fs_dir_hook_t hook;
|
||||
void *hook_data;
|
||||
struct grub_zfs_data *data;
|
||||
};
|
||||
|
||||
grub_err_t (*grub_zfs_decrypt) (grub_crypto_cipher_handle_t cipher,
|
||||
grub_uint64_t algo,
|
||||
void *nonce,
|
||||
|
@ -1790,8 +1798,9 @@ mzap_lookup (mzap_phys_t * zapobj, grub_zfs_endian_t endian,
|
|||
|
||||
static int
|
||||
mzap_iterate (mzap_phys_t * zapobj, grub_zfs_endian_t endian, int objsize,
|
||||
int NESTED_FUNC_ATTR (*hook) (const char *name,
|
||||
grub_uint64_t val))
|
||||
int (*hook) (const char *name, grub_uint64_t val,
|
||||
struct grub_zfs_dir_ctx *ctx),
|
||||
struct grub_zfs_dir_ctx *ctx)
|
||||
{
|
||||
int i, chunks;
|
||||
mzap_ent_phys_t *mzap_ent = zapobj->mz_chunk;
|
||||
|
@ -1803,7 +1812,7 @@ mzap_iterate (mzap_phys_t * zapobj, grub_zfs_endian_t endian, int objsize,
|
|||
mzap_ent[i].mze_name, (long long)mzap_ent[i].mze_value,
|
||||
(int)mzap_ent[i].mze_cd);
|
||||
if (hook (mzap_ent[i].mze_name,
|
||||
grub_zfs_to_cpu64 (mzap_ent[i].mze_value, endian)))
|
||||
grub_zfs_to_cpu64 (mzap_ent[i].mze_value, endian), ctx))
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -2054,12 +2063,11 @@ fzap_lookup (dnode_end_t * zap_dnode, zap_phys_t * zap,
|
|||
static int
|
||||
fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap,
|
||||
grub_size_t name_elem_length,
|
||||
int NESTED_FUNC_ATTR (*hook) (const void *name,
|
||||
grub_size_t name_length,
|
||||
const void *val_in,
|
||||
grub_size_t nelem,
|
||||
grub_size_t elemsize),
|
||||
struct grub_zfs_data *data)
|
||||
int (*hook) (const void *name, grub_size_t name_length,
|
||||
const void *val_in,
|
||||
grub_size_t nelem, grub_size_t elemsize,
|
||||
void *data),
|
||||
void *hook_data, struct grub_zfs_data *data)
|
||||
{
|
||||
zap_leaf_phys_t *l;
|
||||
void *l_in;
|
||||
|
@ -2158,7 +2166,7 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap,
|
|||
}
|
||||
|
||||
if (hook (buf, le->le_name_length,
|
||||
val, le->le_value_length, le->le_int_size))
|
||||
val, le->le_value_length, le->le_int_size, hook_data))
|
||||
{
|
||||
grub_free (l);
|
||||
return 1;
|
||||
|
@ -2221,11 +2229,35 @@ zap_lookup (dnode_end_t * zap_dnode, const char *name, grub_uint64_t *val,
|
|||
return grub_error (GRUB_ERR_BAD_FS, "unknown ZAP type");
|
||||
}
|
||||
|
||||
/* Context for zap_iterate_u64. */
|
||||
struct zap_iterate_u64_ctx
|
||||
{
|
||||
int (*hook) (const char *, grub_uint64_t, struct grub_zfs_dir_ctx *);
|
||||
struct grub_zfs_dir_ctx *dir_ctx;
|
||||
};
|
||||
|
||||
/* Helper for zap_iterate_u64. */
|
||||
static int
|
||||
zap_iterate_u64_transform (const void *name,
|
||||
grub_size_t namelen __attribute__ ((unused)),
|
||||
const void *val_in,
|
||||
grub_size_t nelem,
|
||||
grub_size_t elemsize,
|
||||
void *data)
|
||||
{
|
||||
struct zap_iterate_u64_ctx *ctx = data;
|
||||
|
||||
if (elemsize != sizeof (grub_uint64_t) || nelem != 1)
|
||||
return 0;
|
||||
return ctx->hook (name, grub_be_to_cpu64 (*(const grub_uint64_t *) val_in),
|
||||
ctx->dir_ctx);
|
||||
}
|
||||
|
||||
static int
|
||||
zap_iterate_u64 (dnode_end_t * zap_dnode,
|
||||
int NESTED_FUNC_ATTR (*hook) (const char *name,
|
||||
grub_uint64_t val),
|
||||
struct grub_zfs_data *data)
|
||||
int (*hook) (const char *name, grub_uint64_t val,
|
||||
struct grub_zfs_dir_ctx *ctx),
|
||||
struct grub_zfs_data *data, struct grub_zfs_dir_ctx *ctx)
|
||||
{
|
||||
grub_uint64_t block_type;
|
||||
int size;
|
||||
|
@ -2234,23 +2266,6 @@ zap_iterate_u64 (dnode_end_t * zap_dnode,
|
|||
int ret;
|
||||
grub_zfs_endian_t endian;
|
||||
|
||||
auto int NESTED_FUNC_ATTR transform (const void *name,
|
||||
grub_size_t namelen,
|
||||
const void *val_in,
|
||||
grub_size_t nelem,
|
||||
grub_size_t elemsize);
|
||||
|
||||
int NESTED_FUNC_ATTR transform (const void *name,
|
||||
grub_size_t namelen __attribute__ ((unused)),
|
||||
const void *val_in,
|
||||
grub_size_t nelem,
|
||||
grub_size_t elemsize)
|
||||
{
|
||||
if (elemsize != sizeof (grub_uint64_t) || nelem != 1)
|
||||
return 0;
|
||||
return hook (name, grub_be_to_cpu64 (*(const grub_uint64_t *) val_in));
|
||||
}
|
||||
|
||||
/* Read in the first block of the zap object data. */
|
||||
size = grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, zap_dnode->endian) << SPA_MINBLOCKSHIFT;
|
||||
err = dmu_read (zap_dnode, 0, &zapbuf, &endian, data);
|
||||
|
@ -2263,15 +2278,21 @@ zap_iterate_u64 (dnode_end_t * zap_dnode,
|
|||
if (block_type == ZBT_MICRO)
|
||||
{
|
||||
grub_dprintf ("zfs", "micro zap\n");
|
||||
ret = mzap_iterate (zapbuf, endian, size, hook);
|
||||
ret = mzap_iterate (zapbuf, endian, size, hook, ctx);
|
||||
grub_free (zapbuf);
|
||||
return ret;
|
||||
}
|
||||
else if (block_type == ZBT_HEADER)
|
||||
{
|
||||
struct zap_iterate_u64_ctx transform_ctx = {
|
||||
.hook = hook,
|
||||
.dir_ctx = ctx
|
||||
};
|
||||
|
||||
grub_dprintf ("zfs", "fat zap\n");
|
||||
/* this is a fat zap */
|
||||
ret = fzap_iterate (zap_dnode, zapbuf, 1, transform, data);
|
||||
ret = fzap_iterate (zap_dnode, zapbuf, 1,
|
||||
zap_iterate_u64_transform, &transform_ctx, data);
|
||||
grub_free (zapbuf);
|
||||
return ret;
|
||||
}
|
||||
|
@ -2282,12 +2303,11 @@ zap_iterate_u64 (dnode_end_t * zap_dnode,
|
|||
static int
|
||||
zap_iterate (dnode_end_t * zap_dnode,
|
||||
grub_size_t nameelemlen,
|
||||
int NESTED_FUNC_ATTR (*hook) (const void *name,
|
||||
grub_size_t namelen,
|
||||
const void *val_in,
|
||||
grub_size_t nelem,
|
||||
grub_size_t elemsize),
|
||||
struct grub_zfs_data *data)
|
||||
int (*hook) (const void *name, grub_size_t namelen,
|
||||
const void *val_in,
|
||||
grub_size_t nelem, grub_size_t elemsize,
|
||||
void *data),
|
||||
void *hook_data, struct grub_zfs_data *data)
|
||||
{
|
||||
grub_uint64_t block_type;
|
||||
void *zapbuf;
|
||||
|
@ -2312,7 +2332,8 @@ zap_iterate (dnode_end_t * zap_dnode,
|
|||
{
|
||||
grub_dprintf ("zfs", "fat zap\n");
|
||||
/* this is a fat zap */
|
||||
ret = fzap_iterate (zap_dnode, zapbuf, nameelemlen, hook, data);
|
||||
ret = fzap_iterate (zap_dnode, zapbuf, nameelemlen, hook, hook_data,
|
||||
data);
|
||||
grub_free (zapbuf);
|
||||
return ret;
|
||||
}
|
||||
|
@ -2826,6 +2847,61 @@ make_mdn (dnode_end_t * mdn, struct grub_zfs_data *data)
|
|||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
/* Context for dnode_get_fullpath. */
|
||||
struct dnode_get_fullpath_ctx
|
||||
{
|
||||
struct subvolume *subvol;
|
||||
grub_uint64_t salt;
|
||||
int keyn;
|
||||
};
|
||||
|
||||
/* Helper for dnode_get_fullpath. */
|
||||
static int
|
||||
count_zap_keys (const void *name __attribute__ ((unused)),
|
||||
grub_size_t namelen __attribute__ ((unused)),
|
||||
const void *val_in __attribute__ ((unused)),
|
||||
grub_size_t nelem __attribute__ ((unused)),
|
||||
grub_size_t elemsize __attribute__ ((unused)),
|
||||
void *data)
|
||||
{
|
||||
struct dnode_get_fullpath_ctx *ctx = data;
|
||||
|
||||
ctx->subvol->nkeys++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Helper for dnode_get_fullpath. */
|
||||
static int
|
||||
load_zap_key (const void *name, grub_size_t namelen, const void *val_in,
|
||||
grub_size_t nelem, grub_size_t elemsize, void *data)
|
||||
{
|
||||
struct dnode_get_fullpath_ctx *ctx = data;
|
||||
|
||||
if (namelen != 1)
|
||||
{
|
||||
grub_dprintf ("zfs", "Unexpected key index size %" PRIuGRUB_SIZE "\n",
|
||||
namelen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (elemsize != 1)
|
||||
{
|
||||
grub_dprintf ("zfs", "Unexpected key element size %" PRIuGRUB_SIZE "\n",
|
||||
elemsize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctx->subvol->keyring[ctx->keyn].txg =
|
||||
grub_be_to_cpu64 (*(grub_uint64_t *) name);
|
||||
ctx->subvol->keyring[ctx->keyn].algo =
|
||||
grub_le_to_cpu64 (*(grub_uint64_t *) val_in);
|
||||
ctx->subvol->keyring[ctx->keyn].cipher =
|
||||
grub_zfs_load_key (val_in, nelem, ctx->salt,
|
||||
ctx->subvol->keyring[ctx->keyn].algo);
|
||||
ctx->keyn++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
dnode_get_fullpath (const char *fullpath, struct subvolume *subvol,
|
||||
dnode_end_t * dn, int *isfs,
|
||||
|
@ -2835,57 +2911,7 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol,
|
|||
const char *ptr_at, *filename;
|
||||
grub_uint64_t headobj;
|
||||
grub_uint64_t keychainobj;
|
||||
grub_uint64_t salt;
|
||||
grub_err_t err;
|
||||
int keyn = 0;
|
||||
|
||||
auto int NESTED_FUNC_ATTR count_zap_keys (const void *name,
|
||||
grub_size_t namelen,
|
||||
const void *val_in,
|
||||
grub_size_t nelem,
|
||||
grub_size_t elemsize);
|
||||
int NESTED_FUNC_ATTR count_zap_keys (const void *name __attribute__ ((unused)),
|
||||
grub_size_t namelen __attribute__ ((unused)),
|
||||
const void *val_in __attribute__ ((unused)),
|
||||
grub_size_t nelem __attribute__ ((unused)),
|
||||
grub_size_t elemsize __attribute__ ((unused)))
|
||||
{
|
||||
subvol->nkeys++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto int NESTED_FUNC_ATTR load_zap_key (const void *name,
|
||||
grub_size_t namelen,
|
||||
const void *val_in,
|
||||
grub_size_t nelem,
|
||||
grub_size_t elemsize);
|
||||
int NESTED_FUNC_ATTR load_zap_key (const void *name,
|
||||
grub_size_t namelen,
|
||||
const void *val_in,
|
||||
grub_size_t nelem,
|
||||
grub_size_t elemsize)
|
||||
{
|
||||
if (namelen != 1)
|
||||
{
|
||||
grub_dprintf ("zfs", "Unexpected key index size %" PRIuGRUB_SIZE "\n",
|
||||
namelen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (elemsize != 1)
|
||||
{
|
||||
grub_dprintf ("zfs", "Unexpected key element size %" PRIuGRUB_SIZE "\n",
|
||||
elemsize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
subvol->keyring[keyn].txg = grub_be_to_cpu64 (*(grub_uint64_t *) name);
|
||||
subvol->keyring[keyn].algo = grub_le_to_cpu64 (*(grub_uint64_t *) val_in);
|
||||
subvol->keyring[keyn].cipher = grub_zfs_load_key (val_in, nelem, salt,
|
||||
subvol->keyring[keyn].algo);
|
||||
keyn++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ptr_at = grub_strchr (fullpath, '@');
|
||||
if (! ptr_at)
|
||||
|
@ -2953,6 +2979,10 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol,
|
|||
keychainobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&dn->dn))->keychain, dn->endian);
|
||||
if (grub_zfs_load_key && keychainobj)
|
||||
{
|
||||
struct dnode_get_fullpath_ctx ctx = {
|
||||
.subvol = subvol,
|
||||
.keyn = 0
|
||||
};
|
||||
dnode_end_t keychain_dn, props_dn;
|
||||
grub_uint64_t propsobj;
|
||||
propsobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&dn->dn))->dd_props_zapobj, dn->endian);
|
||||
|
@ -2966,12 +2996,12 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol,
|
|||
return err;
|
||||
}
|
||||
|
||||
err = zap_lookup (&props_dn, "salt", &salt, data, 0);
|
||||
err = zap_lookup (&props_dn, "salt", &ctx.salt, data, 0);
|
||||
if (err == GRUB_ERR_FILE_NOT_FOUND)
|
||||
{
|
||||
err = 0;
|
||||
grub_errno = 0;
|
||||
salt = 0;
|
||||
ctx.salt = 0;
|
||||
}
|
||||
if (err)
|
||||
{
|
||||
|
@ -2988,7 +3018,7 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol,
|
|||
return err;
|
||||
}
|
||||
subvol->nkeys = 0;
|
||||
zap_iterate (&keychain_dn, 8, count_zap_keys, data);
|
||||
zap_iterate (&keychain_dn, 8, count_zap_keys, &ctx, data);
|
||||
subvol->keyring = grub_zalloc (subvol->nkeys * sizeof (subvol->keyring[0]));
|
||||
if (!subvol->keyring)
|
||||
{
|
||||
|
@ -2996,7 +3026,7 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol,
|
|||
grub_free (snapname);
|
||||
return err;
|
||||
}
|
||||
zap_iterate (&keychain_dn, 8, load_zap_key, data);
|
||||
zap_iterate (&keychain_dn, 8, load_zap_key, &ctx, data);
|
||||
}
|
||||
|
||||
if (snapname)
|
||||
|
@ -3748,108 +3778,122 @@ fill_fs_info (struct grub_dirhook_info *info,
|
|||
return;
|
||||
}
|
||||
|
||||
/* Helper for grub_zfs_dir. */
|
||||
static int
|
||||
iterate_zap (const char *name, grub_uint64_t val, struct grub_zfs_dir_ctx *ctx)
|
||||
{
|
||||
grub_err_t err;
|
||||
struct grub_dirhook_info info;
|
||||
|
||||
dnode_end_t dn;
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
|
||||
dnode_get (&(ctx->data->subvol.mdn), val, 0, &dn, ctx->data);
|
||||
|
||||
if (dn.dn.dn_bonustype == DMU_OT_SA)
|
||||
{
|
||||
void *sahdrp;
|
||||
int hdrsize;
|
||||
|
||||
if (dn.dn.dn_bonuslen != 0)
|
||||
{
|
||||
sahdrp = (sa_hdr_phys_t *) DN_BONUS (&ctx->data->dnode.dn);
|
||||
}
|
||||
else if (dn.dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR)
|
||||
{
|
||||
blkptr_t *bp = &dn.dn.dn_spill;
|
||||
|
||||
err = zio_read (bp, dn.endian, &sahdrp, NULL, ctx->data);
|
||||
if (err)
|
||||
{
|
||||
grub_print_error ();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt");
|
||||
grub_print_error ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp));
|
||||
info.mtimeset = 1;
|
||||
info.mtime = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian);
|
||||
info.case_insensitive = ctx->data->subvol.case_insensitive;
|
||||
}
|
||||
|
||||
if (dn.dn.dn_bonustype == DMU_OT_ZNODE)
|
||||
{
|
||||
info.mtimeset = 1;
|
||||
info.mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0],
|
||||
dn.endian);
|
||||
}
|
||||
info.dir = (dn.dn.dn_type == DMU_OT_DIRECTORY_CONTENTS);
|
||||
grub_dprintf ("zfs", "type=%d, name=%s\n",
|
||||
(int)dn.dn.dn_type, (char *)name);
|
||||
return ctx->hook (name, &info, ctx->hook_data);
|
||||
}
|
||||
|
||||
/* Helper for grub_zfs_dir. */
|
||||
static int
|
||||
iterate_zap_fs (const char *name, grub_uint64_t val,
|
||||
struct grub_zfs_dir_ctx *ctx)
|
||||
{
|
||||
grub_err_t err;
|
||||
struct grub_dirhook_info info;
|
||||
|
||||
dnode_end_t mdn;
|
||||
err = dnode_get (&(ctx->data->mos), val, 0, &mdn, ctx->data);
|
||||
if (err)
|
||||
return 0;
|
||||
if (mdn.dn.dn_type != DMU_OT_DSL_DIR)
|
||||
return 0;
|
||||
|
||||
fill_fs_info (&info, mdn, ctx->data);
|
||||
return ctx->hook (name, &info, ctx->hook_data);
|
||||
}
|
||||
|
||||
/* Helper for grub_zfs_dir. */
|
||||
static int
|
||||
iterate_zap_snap (const char *name, grub_uint64_t val,
|
||||
struct grub_zfs_dir_ctx *ctx)
|
||||
{
|
||||
grub_err_t err;
|
||||
struct grub_dirhook_info info;
|
||||
char *name2;
|
||||
int ret;
|
||||
|
||||
dnode_end_t mdn;
|
||||
|
||||
err = dnode_get (&(ctx->data->mos), val, 0, &mdn, ctx->data);
|
||||
if (err)
|
||||
return 0;
|
||||
|
||||
if (mdn.dn.dn_type != DMU_OT_DSL_DATASET)
|
||||
return 0;
|
||||
|
||||
fill_fs_info (&info, mdn, ctx->data);
|
||||
|
||||
name2 = grub_malloc (grub_strlen (name) + 2);
|
||||
name2[0] = '@';
|
||||
grub_memcpy (name2 + 1, name, grub_strlen (name) + 1);
|
||||
ret = ctx->hook (name2, &info, ctx->hook_data);
|
||||
grub_free (name2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_zfs_dir (grub_device_t device, const char *path,
|
||||
int (*hook) (const char *, const struct grub_dirhook_info *))
|
||||
grub_fs_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
struct grub_zfs_dir_ctx ctx = {
|
||||
.hook = hook,
|
||||
.hook_data = hook_data
|
||||
};
|
||||
struct grub_zfs_data *data;
|
||||
grub_err_t err;
|
||||
int isfs;
|
||||
auto int NESTED_FUNC_ATTR iterate_zap (const char *name, grub_uint64_t val);
|
||||
auto int NESTED_FUNC_ATTR iterate_zap_fs (const char *name,
|
||||
grub_uint64_t val);
|
||||
auto int NESTED_FUNC_ATTR iterate_zap_snap (const char *name,
|
||||
grub_uint64_t val);
|
||||
|
||||
int NESTED_FUNC_ATTR iterate_zap (const char *name, grub_uint64_t val)
|
||||
{
|
||||
struct grub_dirhook_info info;
|
||||
dnode_end_t dn;
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
|
||||
dnode_get (&(data->subvol.mdn), val, 0, &dn, data);
|
||||
|
||||
if (dn.dn.dn_bonustype == DMU_OT_SA)
|
||||
{
|
||||
void *sahdrp;
|
||||
int hdrsize;
|
||||
|
||||
if (dn.dn.dn_bonuslen != 0)
|
||||
{
|
||||
sahdrp = (sa_hdr_phys_t *) DN_BONUS (&data->dnode.dn);
|
||||
}
|
||||
else if (dn.dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR)
|
||||
{
|
||||
blkptr_t *bp = &dn.dn.dn_spill;
|
||||
|
||||
err = zio_read (bp, dn.endian, &sahdrp, NULL, data);
|
||||
if (err)
|
||||
{
|
||||
grub_print_error ();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt");
|
||||
grub_print_error ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp));
|
||||
info.mtimeset = 1;
|
||||
info.mtime = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian);
|
||||
info.case_insensitive = data->subvol.case_insensitive;
|
||||
}
|
||||
|
||||
if (dn.dn.dn_bonustype == DMU_OT_ZNODE)
|
||||
{
|
||||
info.mtimeset = 1;
|
||||
info.mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0],
|
||||
dn.endian);
|
||||
}
|
||||
info.dir = (dn.dn.dn_type == DMU_OT_DIRECTORY_CONTENTS);
|
||||
grub_dprintf ("zfs", "type=%d, name=%s\n",
|
||||
(int)dn.dn.dn_type, (char *)name);
|
||||
return hook (name, &info);
|
||||
}
|
||||
|
||||
int NESTED_FUNC_ATTR iterate_zap_fs (const char *name, grub_uint64_t val)
|
||||
{
|
||||
struct grub_dirhook_info info;
|
||||
dnode_end_t mdn;
|
||||
err = dnode_get (&(data->mos), val, 0, &mdn, data);
|
||||
if (err)
|
||||
return 0;
|
||||
if (mdn.dn.dn_type != DMU_OT_DSL_DIR)
|
||||
return 0;
|
||||
|
||||
fill_fs_info (&info, mdn, data);
|
||||
return hook (name, &info);
|
||||
}
|
||||
int NESTED_FUNC_ATTR iterate_zap_snap (const char *name, grub_uint64_t val)
|
||||
{
|
||||
struct grub_dirhook_info info;
|
||||
char *name2;
|
||||
int ret;
|
||||
dnode_end_t mdn;
|
||||
|
||||
err = dnode_get (&(data->mos), val, 0, &mdn, data);
|
||||
if (err)
|
||||
return 0;
|
||||
|
||||
if (mdn.dn.dn_type != DMU_OT_DSL_DATASET)
|
||||
return 0;
|
||||
|
||||
fill_fs_info (&info, mdn, data);
|
||||
|
||||
name2 = grub_malloc (grub_strlen (name) + 2);
|
||||
name2[0] = '@';
|
||||
grub_memcpy (name2 + 1, name, grub_strlen (name) + 1);
|
||||
ret = hook (name2, &info);
|
||||
grub_free (name2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
data = zfs_mount (device);
|
||||
if (! data)
|
||||
|
@ -3860,6 +3904,8 @@ grub_zfs_dir (grub_device_t device, const char *path,
|
|||
zfs_unmount (data);
|
||||
return err;
|
||||
}
|
||||
ctx.data = data;
|
||||
|
||||
if (isfs)
|
||||
{
|
||||
grub_uint64_t childobj, headobj;
|
||||
|
@ -3868,7 +3914,7 @@ grub_zfs_dir (grub_device_t device, const char *path,
|
|||
struct grub_dirhook_info info;
|
||||
|
||||
fill_fs_info (&info, data->dnode, data);
|
||||
hook ("@", &info);
|
||||
hook ("@", &info, hook_data);
|
||||
|
||||
childobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&data->dnode.dn))->dd_child_dir_zapobj, data->dnode.endian);
|
||||
headobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&data->dnode.dn))->dd_head_dataset_obj, data->dnode.endian);
|
||||
|
@ -3880,7 +3926,7 @@ grub_zfs_dir (grub_device_t device, const char *path,
|
|||
return err;
|
||||
}
|
||||
|
||||
zap_iterate_u64 (&dn, iterate_zap_fs, data);
|
||||
zap_iterate_u64 (&dn, iterate_zap_fs, data, &ctx);
|
||||
|
||||
err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, &dn, data);
|
||||
if (err)
|
||||
|
@ -3899,7 +3945,7 @@ grub_zfs_dir (grub_device_t device, const char *path,
|
|||
return err;
|
||||
}
|
||||
|
||||
zap_iterate_u64 (&dn, iterate_zap_snap, data);
|
||||
zap_iterate_u64 (&dn, iterate_zap_snap, data, &ctx);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3908,7 +3954,7 @@ grub_zfs_dir (grub_device_t device, const char *path,
|
|||
zfs_unmount (data);
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
|
||||
}
|
||||
zap_iterate_u64 (&(data->dnode), iterate_zap, data);
|
||||
zap_iterate_u64 (&(data->dnode), iterate_zap, data, &ctx);
|
||||
}
|
||||
zfs_unmount (data);
|
||||
return grub_errno;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue