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:
Colin Watson 2013-01-21 01:33:46 +00:00
parent 53d3e4e3df
commit fc524edf65
35 changed files with 1723 additions and 1451 deletions

View file

@ -1,3 +1,12 @@
2013-01-21 Colin Watson <cjwatson@ubuntu.com>
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.
2013-01-21 Colin Watson <cjwatson@ubuntu.com> 2013-01-21 Colin Watson <cjwatson@ubuntu.com>
* docs/grub.texi (Multi-boot manual config): Fix typo for * docs/grub.texi (Multi-boot manual config): Fix typo for

View file

@ -85,31 +85,35 @@ grub_ls_list_devices (int longlist)
return 0; return 0;
} }
static grub_err_t /* Context for grub_ls_list_files. */
grub_ls_list_files (char *dirname, int longlist, int all, int human) struct grub_ls_list_files_ctx
{ {
char *device_name; char *dirname;
grub_fs_t fs; int all;
const char *path; int human;
grub_device_t dev; };
auto int print_files (const char *filename, /* Helper for grub_ls_list_files. */
const struct grub_dirhook_info *info); static int
auto int print_files_long (const char *filename, print_files (const char *filename, const struct grub_dirhook_info *info,
const struct grub_dirhook_info *info); void *data)
{
struct grub_ls_list_files_ctx *ctx = data;
int print_files (const char *filename, const struct grub_dirhook_info *info) if (ctx->all || filename[0] != '.')
{
if (all || filename[0] != '.')
grub_printf ("%s%s ", filename, info->dir ? "/" : ""); grub_printf ("%s%s ", filename, info->dir ? "/" : "");
return 0; return 0;
} }
int print_files_long (const char *filename, /* Helper for grub_ls_list_files. */
const struct grub_dirhook_info *info) static int
{ print_files_long (const char *filename, const struct grub_dirhook_info *info,
if ((! all) && (filename[0] == '.')) void *data)
{
struct grub_ls_list_files_ctx *ctx = data;
if ((! ctx->all) && (filename[0] == '.'))
return 0; return 0;
if (! info->dir) if (! info->dir)
@ -117,10 +121,10 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human)
grub_file_t file; grub_file_t file;
char *pathname; char *pathname;
if (dirname[grub_strlen (dirname) - 1] == '/') if (ctx->dirname[grub_strlen (ctx->dirname) - 1] == '/')
pathname = grub_xasprintf ("%s%s", dirname, filename); pathname = grub_xasprintf ("%s%s", ctx->dirname, filename);
else else
pathname = grub_xasprintf ("%s/%s", dirname, filename); pathname = grub_xasprintf ("%s/%s", ctx->dirname, filename);
if (!pathname) if (!pathname)
return 1; return 1;
@ -136,7 +140,7 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human)
return 0; return 0;
} }
if (! human) if (! ctx->human)
grub_printf ("%-12llu", (unsigned long long) file->size); grub_printf ("%-12llu", (unsigned long long) file->size);
else else
{ {
@ -177,7 +181,7 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human)
{ {
struct grub_datetime datetime; struct grub_datetime datetime;
grub_unixtime2datetime (info->mtime, &datetime); grub_unixtime2datetime (info->mtime, &datetime);
if (human) if (ctx->human)
grub_printf (" %d-%02d-%02d %02d:%02d:%02d %-11s ", grub_printf (" %d-%02d-%02d %02d:%02d:%02d %-11s ",
datetime.year, datetime.month, datetime.day, datetime.year, datetime.month, datetime.day,
datetime.hour, datetime.minute, datetime.hour, datetime.minute,
@ -192,7 +196,15 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human)
grub_printf ("%s%s\n", filename, info->dir ? "/" : ""); grub_printf ("%s%s\n", filename, info->dir ? "/" : "");
return 0; return 0;
} }
static grub_err_t
grub_ls_list_files (char *dirname, int longlist, int all, int human)
{
char *device_name;
grub_fs_t fs;
const char *path;
grub_device_t dev;
device_name = grub_file_get_device_name (dirname); device_name = grub_file_get_device_name (dirname);
dev = grub_device_open (device_name); dev = grub_device_open (device_name);
@ -221,10 +233,16 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human)
} }
else if (fs) else if (fs)
{ {
struct grub_ls_list_files_ctx ctx = {
.dirname = dirname,
.all = all,
.human = human
};
if (longlist) if (longlist)
(fs->dir) (dev, path, print_files_long); (fs->dir) (dev, path, print_files_long, &ctx);
else else
(fs->dir) (dev, path, print_files); (fs->dir) (dev, path, print_files, &ctx);
if (grub_errno == GRUB_ERR_BAD_FILE_TYPE if (grub_errno == GRUB_ERR_BAD_FILE_TYPE
&& path[grub_strlen (path) - 1] != '/') && path[grub_strlen (path) - 1] != '/')
@ -250,9 +268,9 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human)
all = 1; all = 1;
grub_memset (&info, 0, sizeof (info)); grub_memset (&info, 0, sizeof (info));
if (longlist) if (longlist)
print_files_long (p, &info); print_files_long (p, &info, &ctx);
else else
print_files (p, &info); print_files (p, &info, &ctx);
grub_free (dirname); grub_free (dirname);
} }

View file

@ -38,50 +38,51 @@ grub_strtosl (char *arg, char **end, int base)
return grub_strtoul (arg, end, base); return grub_strtoul (arg, end, base);
} }
/* Parse a test expression starting from *argn. */ /* Context for test_parse. */
static int struct test_parse_ctx
test_parse (char **args, int *argn, int argc)
{ {
int ret = 0, discard = 0, invert = 0; int ret, discard, invert;
int file_exists; int file_exists;
struct grub_dirhook_info file_info; struct grub_dirhook_info file_info;
char *filename;
};
auto void update_val (int val); /* Take care of discarding and inverting. */
auto void get_fileinfo (char *pathname); static void
update_val (int val, struct test_parse_ctx *ctx)
{
if (! ctx->discard)
ctx->ret = ctx->invert ? ! val : val;
ctx->invert = ctx->discard = 0;
}
/* Take care of discarding and inverting. */ /* A hook for iterating directories. */
void update_val (int val) static int
find_file (const char *cur_filename, const struct grub_dirhook_info *info,
void *data)
{
struct test_parse_ctx *ctx = data;
if ((info->case_insensitive ? grub_strcasecmp (cur_filename, ctx->filename)
: grub_strcmp (cur_filename, ctx->filename)) == 0)
{ {
if (! discard) ctx->file_info = *info;
ret = invert ? ! val : val; ctx->file_exists = 1;
invert = discard = 0; return 1;
} }
return 0;
}
/* Check if file exists and fetch its information. */ /* Check if file exists and fetch its information. */
void get_fileinfo (char *path) static void
{ get_fileinfo (char *path, struct test_parse_ctx *ctx)
char *filename, *pathname; {
char *pathname;
char *device_name; char *device_name;
grub_fs_t fs; grub_fs_t fs;
grub_device_t dev; grub_device_t dev;
/* A hook for iterating directories. */ ctx->file_exists = 0;
auto int find_file (const char *cur_filename,
const struct grub_dirhook_info *info);
int find_file (const char *cur_filename,
const struct grub_dirhook_info *info)
{
if ((info->case_insensitive ? grub_strcasecmp (cur_filename, filename)
: grub_strcmp (cur_filename, filename)) == 0)
{
file_info = *info;
file_exists = 1;
return 1;
}
return 0;
}
file_exists = 0;
device_name = grub_file_get_device_name (path); device_name = grub_file_get_device_name (path);
dev = grub_device_open (device_name); dev = grub_device_open (device_name);
if (! dev) if (! dev)
@ -109,43 +110,53 @@ test_parse (char **args, int *argn, int argc)
pathname[grub_strlen (pathname) - 1] = 0; pathname[grub_strlen (pathname) - 1] = 0;
/* Split into path and filename. */ /* Split into path and filename. */
filename = grub_strrchr (pathname, '/'); ctx->filename = grub_strrchr (pathname, '/');
if (! filename) if (! ctx->filename)
{ {
path = grub_strdup ("/"); path = grub_strdup ("/");
filename = pathname; ctx->filename = pathname;
} }
else else
{ {
filename++; ctx->filename++;
path = grub_strdup (pathname); path = grub_strdup (pathname);
path[filename - pathname] = 0; path[ctx->filename - pathname] = 0;
} }
/* It's the whole device. */ /* It's the whole device. */
if (! *pathname) if (! *pathname)
{ {
file_exists = 1; ctx->file_exists = 1;
grub_memset (&file_info, 0, sizeof (file_info)); grub_memset (&ctx->file_info, 0, sizeof (ctx->file_info));
/* Root is always a directory. */ /* Root is always a directory. */
file_info.dir = 1; ctx->file_info.dir = 1;
/* Fetch writing time. */ /* Fetch writing time. */
file_info.mtimeset = 0; ctx->file_info.mtimeset = 0;
if (fs->mtime) if (fs->mtime)
{ {
if (! fs->mtime (dev, &file_info.mtime)) if (! fs->mtime (dev, &ctx->file_info.mtime))
file_info.mtimeset = 1; ctx->file_info.mtimeset = 1;
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
} }
} }
else else
(fs->dir) (dev, path, find_file); (fs->dir) (dev, path, find_file, ctx);
grub_device_close (dev); grub_device_close (dev);
grub_free (path); grub_free (path);
grub_free (device_name); grub_free (device_name);
} }
/* Parse a test expression starting from *argn. */
static int
test_parse (char **args, int *argn, int argc)
{
struct test_parse_ctx ctx = {
.ret = 0,
.discard = 0,
.invert = 0
};
/* Here we have the real parsing. */ /* Here we have the real parsing. */
while (*argn < argc) while (*argn < argc)
@ -157,14 +168,16 @@ test_parse (char **args, int *argn, int argc)
if (grub_strcmp (args[*argn + 1], "=") == 0 if (grub_strcmp (args[*argn + 1], "=") == 0
|| grub_strcmp (args[*argn + 1], "==") == 0) || grub_strcmp (args[*argn + 1], "==") == 0)
{ {
update_val (grub_strcmp (args[*argn], args[*argn + 2]) == 0); update_val (grub_strcmp (args[*argn], args[*argn + 2]) == 0,
&ctx);
(*argn) += 3; (*argn) += 3;
continue; continue;
} }
if (grub_strcmp (args[*argn + 1], "!=") == 0) if (grub_strcmp (args[*argn + 1], "!=") == 0)
{ {
update_val (grub_strcmp (args[*argn], args[*argn + 2]) != 0); update_val (grub_strcmp (args[*argn], args[*argn + 2]) != 0,
&ctx);
(*argn) += 3; (*argn) += 3;
continue; continue;
} }
@ -172,28 +185,32 @@ test_parse (char **args, int *argn, int argc)
/* GRUB extension: lexicographical sorting. */ /* GRUB extension: lexicographical sorting. */
if (grub_strcmp (args[*argn + 1], "<") == 0) if (grub_strcmp (args[*argn + 1], "<") == 0)
{ {
update_val (grub_strcmp (args[*argn], args[*argn + 2]) < 0); update_val (grub_strcmp (args[*argn], args[*argn + 2]) < 0,
&ctx);
(*argn) += 3; (*argn) += 3;
continue; continue;
} }
if (grub_strcmp (args[*argn + 1], "<=") == 0) if (grub_strcmp (args[*argn + 1], "<=") == 0)
{ {
update_val (grub_strcmp (args[*argn], args[*argn + 2]) <= 0); update_val (grub_strcmp (args[*argn], args[*argn + 2]) <= 0,
&ctx);
(*argn) += 3; (*argn) += 3;
continue; continue;
} }
if (grub_strcmp (args[*argn + 1], ">") == 0) if (grub_strcmp (args[*argn + 1], ">") == 0)
{ {
update_val (grub_strcmp (args[*argn], args[*argn + 2]) > 0); update_val (grub_strcmp (args[*argn], args[*argn + 2]) > 0,
&ctx);
(*argn) += 3; (*argn) += 3;
continue; continue;
} }
if (grub_strcmp (args[*argn + 1], ">=") == 0) if (grub_strcmp (args[*argn + 1], ">=") == 0)
{ {
update_val (grub_strcmp (args[*argn], args[*argn + 2]) >= 0); update_val (grub_strcmp (args[*argn], args[*argn + 2]) >= 0,
&ctx);
(*argn) += 3; (*argn) += 3;
continue; continue;
} }
@ -202,7 +219,7 @@ test_parse (char **args, int *argn, int argc)
if (grub_strcmp (args[*argn + 1], "-eq") == 0) if (grub_strcmp (args[*argn + 1], "-eq") == 0)
{ {
update_val (grub_strtosl (args[*argn], 0, 0) update_val (grub_strtosl (args[*argn], 0, 0)
== grub_strtosl (args[*argn + 2], 0, 0)); == grub_strtosl (args[*argn + 2], 0, 0), &ctx);
(*argn) += 3; (*argn) += 3;
continue; continue;
} }
@ -210,7 +227,7 @@ test_parse (char **args, int *argn, int argc)
if (grub_strcmp (args[*argn + 1], "-ge") == 0) if (grub_strcmp (args[*argn + 1], "-ge") == 0)
{ {
update_val (grub_strtosl (args[*argn], 0, 0) update_val (grub_strtosl (args[*argn], 0, 0)
>= grub_strtosl (args[*argn + 2], 0, 0)); >= grub_strtosl (args[*argn + 2], 0, 0), &ctx);
(*argn) += 3; (*argn) += 3;
continue; continue;
} }
@ -218,7 +235,7 @@ test_parse (char **args, int *argn, int argc)
if (grub_strcmp (args[*argn + 1], "-gt") == 0) if (grub_strcmp (args[*argn + 1], "-gt") == 0)
{ {
update_val (grub_strtosl (args[*argn], 0, 0) update_val (grub_strtosl (args[*argn], 0, 0)
> grub_strtosl (args[*argn + 2], 0, 0)); > grub_strtosl (args[*argn + 2], 0, 0), &ctx);
(*argn) += 3; (*argn) += 3;
continue; continue;
} }
@ -226,7 +243,7 @@ test_parse (char **args, int *argn, int argc)
if (grub_strcmp (args[*argn + 1], "-le") == 0) if (grub_strcmp (args[*argn + 1], "-le") == 0)
{ {
update_val (grub_strtosl (args[*argn], 0, 0) update_val (grub_strtosl (args[*argn], 0, 0)
<= grub_strtosl (args[*argn + 2], 0, 0)); <= grub_strtosl (args[*argn + 2], 0, 0), &ctx);
(*argn) += 3; (*argn) += 3;
continue; continue;
} }
@ -234,7 +251,7 @@ test_parse (char **args, int *argn, int argc)
if (grub_strcmp (args[*argn + 1], "-lt") == 0) if (grub_strcmp (args[*argn + 1], "-lt") == 0)
{ {
update_val (grub_strtosl (args[*argn], 0, 0) update_val (grub_strtosl (args[*argn], 0, 0)
< grub_strtosl (args[*argn + 2], 0, 0)); < grub_strtosl (args[*argn + 2], 0, 0), &ctx);
(*argn) += 3; (*argn) += 3;
continue; continue;
} }
@ -242,7 +259,7 @@ test_parse (char **args, int *argn, int argc)
if (grub_strcmp (args[*argn + 1], "-ne") == 0) if (grub_strcmp (args[*argn + 1], "-ne") == 0)
{ {
update_val (grub_strtosl (args[*argn], 0, 0) update_val (grub_strtosl (args[*argn], 0, 0)
!= grub_strtosl (args[*argn + 2], 0, 0)); != grub_strtosl (args[*argn + 2], 0, 0), &ctx);
(*argn) += 3; (*argn) += 3;
continue; continue;
} }
@ -265,10 +282,10 @@ test_parse (char **args, int *argn, int argc)
if (grub_strcmp (args[*argn + 1], "-pgt") == 0) if (grub_strcmp (args[*argn + 1], "-pgt") == 0)
update_val (grub_strtoul (args[*argn] + i, 0, 0) update_val (grub_strtoul (args[*argn] + i, 0, 0)
> grub_strtoul (args[*argn + 2] + i, 0, 0)); > grub_strtoul (args[*argn + 2] + i, 0, 0), &ctx);
else else
update_val (grub_strtoul (args[*argn] + i, 0, 0) update_val (grub_strtoul (args[*argn] + i, 0, 0)
< grub_strtoul (args[*argn + 2] + i, 0, 0)); < grub_strtoul (args[*argn + 2] + i, 0, 0), &ctx);
(*argn) += 3; (*argn) += 3;
continue; continue;
} }
@ -283,22 +300,24 @@ test_parse (char **args, int *argn, int argc)
int bias = 0; int bias = 0;
/* Fetch fileinfo. */ /* Fetch fileinfo. */
get_fileinfo (args[*argn]); get_fileinfo (args[*argn], &ctx);
file1 = file_info; file1 = ctx.file_info;
file1exists = file_exists; file1exists = ctx.file_exists;
get_fileinfo (args[*argn + 2]); get_fileinfo (args[*argn + 2], &ctx);
if (args[*argn + 1][3]) if (args[*argn + 1][3])
bias = grub_strtosl (args[*argn + 1] + 3, 0, 0); bias = grub_strtosl (args[*argn + 1] + 3, 0, 0);
if (grub_memcmp (args[*argn + 1], "-nt", 3) == 0) if (grub_memcmp (args[*argn + 1], "-nt", 3) == 0)
update_val ((file1exists && ! file_exists) update_val ((file1exists && ! ctx.file_exists)
|| (file1.mtimeset && file_info.mtimeset || (file1.mtimeset && ctx.file_info.mtimeset
&& file1.mtime + bias > file_info.mtime)); && file1.mtime + bias > ctx.file_info.mtime),
&ctx);
else else
update_val ((! file1exists && file_exists) update_val ((! file1exists && ctx.file_exists)
|| (file1.mtimeset && file_info.mtimeset || (file1.mtimeset && ctx.file_info.mtimeset
&& file1.mtime + bias < file_info.mtime)); && file1.mtime + bias < ctx.file_info.mtime),
&ctx);
(*argn) += 3; (*argn) += 3;
continue; continue;
} }
@ -310,27 +329,27 @@ test_parse (char **args, int *argn, int argc)
/* File tests. */ /* File tests. */
if (grub_strcmp (args[*argn], "-d") == 0) if (grub_strcmp (args[*argn], "-d") == 0)
{ {
get_fileinfo (args[*argn + 1]); get_fileinfo (args[*argn + 1], &ctx);
update_val (file_exists && file_info.dir); update_val (ctx.file_exists && ctx.file_info.dir, &ctx);
(*argn) += 2; (*argn) += 2;
return ret; return ctx.ret;
} }
if (grub_strcmp (args[*argn], "-e") == 0) if (grub_strcmp (args[*argn], "-e") == 0)
{ {
get_fileinfo (args[*argn + 1]); get_fileinfo (args[*argn + 1], &ctx);
update_val (file_exists); update_val (ctx.file_exists, &ctx);
(*argn) += 2; (*argn) += 2;
return ret; return ctx.ret;
} }
if (grub_strcmp (args[*argn], "-f") == 0) if (grub_strcmp (args[*argn], "-f") == 0)
{ {
get_fileinfo (args[*argn + 1]); get_fileinfo (args[*argn + 1], &ctx);
/* FIXME: check for other types. */ /* FIXME: check for other types. */
update_val (file_exists && ! file_info.dir); update_val (ctx.file_exists && ! ctx.file_info.dir, &ctx);
(*argn) += 2; (*argn) += 2;
return ret; return ctx.ret;
} }
if (grub_strcmp (args[*argn], "-s") == 0) if (grub_strcmp (args[*argn], "-s") == 0)
@ -338,25 +357,25 @@ test_parse (char **args, int *argn, int argc)
grub_file_t file; grub_file_t file;
grub_file_filter_disable_compression (); grub_file_filter_disable_compression ();
file = grub_file_open (args[*argn + 1]); file = grub_file_open (args[*argn + 1]);
update_val (file && (grub_file_size (file) != 0)); update_val (file && (grub_file_size (file) != 0), &ctx);
if (file) if (file)
grub_file_close (file); grub_file_close (file);
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
(*argn) += 2; (*argn) += 2;
return ret; return ctx.ret;
} }
/* String tests. */ /* String tests. */
if (grub_strcmp (args[*argn], "-n") == 0) if (grub_strcmp (args[*argn], "-n") == 0)
{ {
update_val (args[*argn + 1][0]); update_val (args[*argn + 1][0], &ctx);
(*argn) += 2; (*argn) += 2;
continue; continue;
} }
if (grub_strcmp (args[*argn], "-z") == 0) if (grub_strcmp (args[*argn], "-z") == 0)
{ {
update_val (! args[*argn + 1][0]); update_val (! args[*argn + 1][0], &ctx);
(*argn) += 2; (*argn) += 2;
continue; continue;
} }
@ -368,42 +387,42 @@ test_parse (char **args, int *argn, int argc)
if (grub_strcmp (args[*argn], ")") == 0) if (grub_strcmp (args[*argn], ")") == 0)
{ {
(*argn)++; (*argn)++;
return ret; return ctx.ret;
} }
/* Recursively invoke if parenthesis. */ /* Recursively invoke if parenthesis. */
if (grub_strcmp (args[*argn], "(") == 0) if (grub_strcmp (args[*argn], "(") == 0)
{ {
(*argn)++; (*argn)++;
update_val (test_parse (args, argn, argc)); update_val (test_parse (args, argn, argc), &ctx);
continue; continue;
} }
if (grub_strcmp (args[*argn], "!") == 0) if (grub_strcmp (args[*argn], "!") == 0)
{ {
invert = ! invert; ctx.invert = ! ctx.invert;
(*argn)++; (*argn)++;
continue; continue;
} }
if (grub_strcmp (args[*argn], "-a") == 0) if (grub_strcmp (args[*argn], "-a") == 0)
{ {
/* If current value is 0 second value is to be discarded. */ /* If current value is 0 second value is to be discarded. */
discard = ! ret; ctx.discard = ! ctx.ret;
(*argn)++; (*argn)++;
continue; continue;
} }
if (grub_strcmp (args[*argn], "-o") == 0) if (grub_strcmp (args[*argn], "-o") == 0)
{ {
/* If current value is 1 second value is to be discarded. */ /* If current value is 1 second value is to be discarded. */
discard = ret; ctx.discard = ctx.ret;
(*argn)++; (*argn)++;
continue; continue;
} }
/* No test found. Interpret if as just a string. */ /* No test found. Interpret if as just a string. */
update_val (args[*argn][0]); update_val (args[*argn][0], &ctx);
(*argn)++; (*argn)++;
} }
return ret; return ctx.ret;
} }
static grub_err_t static grub_err_t

View file

@ -279,22 +279,21 @@ match_devices (const regex_t *regexp, int noparts)
return 0; return 0;
} }
static char ** /* Context for match_files. */
match_files (const char *prefix, const char *suffix, const char *end, struct match_files_ctx
const regex_t *regexp)
{ {
int i; const regex_t *regexp;
char **files; char **files;
unsigned nfile; unsigned nfile;
char *dir; char *dir;
const char *path; };
char *device_name;
grub_fs_t fs;
grub_device_t dev;
auto int match (const char *name, const struct grub_dirhook_info *info); /* Helper for match_files. */
int match (const char *name, const struct grub_dirhook_info *info) static int
{ match_files_iter (const char *name, const struct grub_dirhook_info *info,
void *data)
{
struct match_files_ctx *ctx = data;
char **t; char **t;
char *buffer; char *buffer;
@ -302,40 +301,53 @@ match_files (const char *prefix, const char *suffix, const char *end,
if (grub_strcmp(".", name) == 0 || grub_strcmp("..", name) == 0) if (grub_strcmp(".", name) == 0 || grub_strcmp("..", name) == 0)
return 0; return 0;
grub_dprintf ("expand", "matching: %s in %s\n", name, dir); grub_dprintf ("expand", "matching: %s in %s\n", name, ctx->dir);
if (regexec (regexp, name, 0, 0, 0)) if (regexec (ctx->regexp, name, 0, 0, 0))
return 0; return 0;
grub_dprintf ("expand", "matched\n"); grub_dprintf ("expand", "matched\n");
buffer = grub_xasprintf ("%s%s", dir, name); buffer = grub_xasprintf ("%s%s", ctx->dir, name);
if (! buffer) if (! buffer)
return 1; return 1;
t = grub_realloc (files, sizeof (char*) * (nfile + 2)); t = grub_realloc (ctx->files, sizeof (char*) * (ctx->nfile + 2));
if (! t) if (! t)
{ {
grub_free (buffer); grub_free (buffer);
return 1; return 1;
} }
files = t; ctx->files = t;
files[nfile++] = buffer; ctx->files[ctx->nfile++] = buffer;
files[nfile] = 0; ctx->files[ctx->nfile] = 0;
return 0; return 0;
} }
static char **
match_files (const char *prefix, const char *suffix, const char *end,
const regex_t *regexp)
{
struct match_files_ctx ctx = {
.regexp = regexp,
.nfile = 0,
.files = 0
};
int i;
const char *path;
char *device_name;
grub_fs_t fs;
grub_device_t dev;
nfile = 0;
files = 0;
dev = 0; dev = 0;
device_name = 0; device_name = 0;
grub_error_push (); grub_error_push ();
dir = make_dir (prefix, suffix, end); ctx.dir = make_dir (prefix, suffix, end);
if (! dir) if (! ctx.dir)
goto fail; goto fail;
device_name = grub_file_get_device_name (dir); device_name = grub_file_get_device_name (ctx.dir);
dev = grub_device_open (device_name); dev = grub_device_open (device_name);
if (! dev) if (! dev)
goto fail; goto fail;
@ -344,33 +356,33 @@ match_files (const char *prefix, const char *suffix, const char *end,
if (! fs) if (! fs)
goto fail; goto fail;
if (dir[0] == '(') if (ctx.dir[0] == '(')
{ {
path = grub_strchr (dir, ')'); path = grub_strchr (ctx.dir, ')');
if (!path) if (!path)
goto fail; goto fail;
path++; path++;
} }
else else
path = dir; path = ctx.dir;
if (fs->dir (dev, path, match)) if (fs->dir (dev, path, match_files_iter, &ctx))
goto fail; goto fail;
grub_free (dir); grub_free (ctx.dir);
grub_device_close (dev); grub_device_close (dev);
grub_free (device_name); grub_free (device_name);
grub_error_pop (); grub_error_pop ();
return files; return ctx.files;
fail: fail:
grub_free (dir); grub_free (ctx.dir);
for (i = 0; files && files[i]; i++) for (i = 0; ctx.files && ctx.files[i]; i++)
grub_free (files[i]); grub_free (ctx.files[i]);
grub_free (files); grub_free (ctx.files);
if (dev) if (dev)
grub_device_close (dev); grub_device_close (dev);
@ -381,27 +393,41 @@ match_files (const char *prefix, const char *suffix, const char *end,
return 0; return 0;
} }
static int /* Context for check_file. */
check_file (const char *dir, const char *basename) struct check_file_ctx
{ {
grub_fs_t fs; const char *basename;
grub_device_t dev; int found;
int found = 0; };
const char *device_name, *path;
auto int match (const char *name, const struct grub_dirhook_info *info); /* Helper for check_file. */
int match (const char *name, const struct grub_dirhook_info *info) static int
check_file_iter (const char *name, const struct grub_dirhook_info *info,
void *data)
{
struct check_file_ctx *ctx = data;
if (ctx->basename[0] == 0
|| (info->case_insensitive ? grub_strcasecmp (name, ctx->basename) == 0
: grub_strcmp (name, ctx->basename) == 0))
{ {
if (basename[0] == 0 ctx->found = 1;
|| (info->case_insensitive ? grub_strcasecmp (name, basename) == 0
: grub_strcmp (name, basename) == 0))
{
found = 1;
return 1; return 1;
} }
return 0; return 0;
} }
static int
check_file (const char *dir, const char *basename)
{
struct check_file_ctx ctx = {
.basename = basename,
.found = 0
};
grub_fs_t fs;
grub_device_t dev;
const char *device_name, *path;
device_name = grub_file_get_device_name (dir); device_name = grub_file_get_device_name (dir);
dev = grub_device_open (device_name); dev = grub_device_open (device_name);
@ -422,14 +448,14 @@ check_file (const char *dir, const char *basename)
else else
path = dir; path = dir;
fs->dir (dev, path[0] ? path : "/", match); fs->dir (dev, path[0] ? path : "/", check_file_iter, &ctx);
if (grub_errno == 0 && basename[0] == 0) if (grub_errno == 0 && basename[0] == 0)
found = 1; ctx.found = 1;
fail: fail:
grub_errno = 0; grub_errno = 0;
return found; return ctx.found;
} }
static void static void

View file

@ -316,50 +316,40 @@ grub_affs_read_symlink (grub_fshelp_node_t node)
} }
/* Helper for grub_affs_iterate_dir. */
static int static int
grub_affs_iterate_dir (grub_fshelp_node_t dir, grub_affs_create_node (grub_fshelp_node_t dir,
int NESTED_FUNC_ATTR grub_fshelp_iterate_dir_hook_t hook, void *hook_data,
(*hook) (const char *filename, struct grub_fshelp_node **node,
enum grub_fshelp_filetype filetype, grub_uint32_t **hashtable,
grub_fshelp_node_t node)) grub_uint32_t block, const struct grub_affs_file *fil)
{ {
unsigned int i;
struct grub_affs_file file;
struct grub_fshelp_node *node = 0;
struct grub_affs_data *data = dir->data; 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; int type;
grub_uint8_t name_u8[sizeof (fil->name) * GRUB_MAX_UTF8_PER_LATIN1 + 1]; grub_uint8_t name_u8[sizeof (fil->name) * GRUB_MAX_UTF8_PER_LATIN1 + 1];
grub_size_t len; grub_size_t len;
unsigned int nest; unsigned int nest;
node = grub_zalloc (sizeof (*node)); *node = grub_zalloc (sizeof (**node));
if (!node) if (!*node)
{ {
grub_free (hashtable); grub_free (*hashtable);
return 1; return 1;
} }
node->data = data; (*node)->data = data;
node->block = block; (*node)->block = block;
node->parent = dir; (*node)->parent = dir;
len = fil->namelen; len = fil->namelen;
if (len > sizeof (fil->name)) if (len > sizeof (fil->name))
len = sizeof (fil->name); len = sizeof (fil->name);
*grub_latin1_to_utf8 (name_u8, fil->name, len) = '\0'; *grub_latin1_to_utf8 (name_u8, fil->name, len) = '\0';
node->di = *fil; (*node)->di = *fil;
for (nest = 0; nest < 8; nest++) for (nest = 0; nest < 8; nest++)
{ {
switch (node->di.type) switch ((*node)->di.type)
{ {
case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_REG): case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_REG):
type = GRUB_FSHELP_REG; type = GRUB_FSHELP_REG;
@ -373,12 +363,12 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_HARDLINK): case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_HARDLINK):
{ {
grub_err_t err; grub_err_t err;
node->block = grub_be_to_cpu32 (node->di.hardlink); (*node)->block = grub_be_to_cpu32 ((*node)->di.hardlink);
err = grub_disk_read (data->disk, err = grub_disk_read (data->disk,
(((grub_uint64_t) node->block + 1) << data->log_blocksize) (((grub_uint64_t) (*node)->block + 1) << data->log_blocksize)
- 1, - 1,
GRUB_DISK_SECTOR_SIZE - GRUB_AFFS_FILE_LOCATION, GRUB_DISK_SECTOR_SIZE - GRUB_AFFS_FILE_LOCATION,
sizeof (node->di), (char *) &node->di); sizeof ((*node)->di), (char *) &(*node)->di);
if (err) if (err)
return 1; return 1;
continue; continue;
@ -394,15 +384,25 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
type |= GRUB_FSHELP_CASE_INSENSITIVE; type |= GRUB_FSHELP_CASE_INSENSITIVE;
if (hook ((char *) name_u8, type, node)) if (hook ((char *) name_u8, type, *node, hook_data))
{ {
grub_free (hashtable); grub_free (*hashtable);
node = 0; *node = 0;
return 1; return 1;
} }
node = 0; *node = 0;
return 0; return 0;
} }
static int
grub_affs_iterate_dir (grub_fshelp_node_t dir,
grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
{
unsigned int i;
struct grub_affs_file file;
struct grub_fshelp_node *node = 0;
struct grub_affs_data *data = dir->data;
grub_uint32_t *hashtable;
/* Create the directory entries for `.' and `..'. */ /* Create the directory entries for `.' and `..'. */
node = grub_zalloc (sizeof (*node)); node = grub_zalloc (sizeof (*node));
@ -410,7 +410,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
return 1; return 1;
*node = *dir; *node = *dir;
if (hook (".", GRUB_FSHELP_DIR, node)) if (hook (".", GRUB_FSHELP_DIR, node, hook_data))
return 1; return 1;
if (dir->parent) if (dir->parent)
{ {
@ -418,7 +418,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
if (!node) if (!node)
return 1; return 1;
*node = *dir->parent; *node = *dir->parent;
if (hook ("..", GRUB_FSHELP_DIR, node)) if (hook ("..", GRUB_FSHELP_DIR, node, hook_data))
return 1; return 1;
} }
@ -454,7 +454,8 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
if (grub_errno) if (grub_errno)
goto fail; goto fail;
if (grub_affs_create_node (next, &file)) if (grub_affs_create_node (dir, hook, hook_data, &node, &hashtable,
next, &file))
return 1; return 1;
next = grub_be_to_cpu32 (file.next); next = grub_be_to_cpu32 (file.next);
@ -545,30 +546,36 @@ aftime2ctime (const struct grub_affs_time *t)
+ 8 * 365 * 86400 + 86400 * 2; + 8 * 365 * 86400 + 86400 * 2;
} }
static grub_err_t /* Context for grub_affs_dir. */
grub_affs_dir (grub_device_t device, const char *path, struct grub_affs_dir_ctx
int (*hook) (const char *filename,
const struct grub_dirhook_info *info))
{ {
struct grub_affs_data *data = 0; grub_fs_dir_hook_t hook;
struct grub_fshelp_node *fdiro = 0; void *hook_data;
};
auto int NESTED_FUNC_ATTR iterate (const char *filename, /* Helper for grub_affs_dir. */
enum grub_fshelp_filetype filetype, static int
grub_fshelp_node_t node); grub_affs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node, void *data)
int NESTED_FUNC_ATTR iterate (const char *filename, {
enum grub_fshelp_filetype filetype, struct grub_affs_dir_ctx *ctx = data;
grub_fshelp_node_t node)
{
struct grub_dirhook_info info; struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info)); grub_memset (&info, 0, sizeof (info));
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
info.mtimeset = 1; info.mtimeset = 1;
info.mtime = aftime2ctime (&node->di.mtime); info.mtime = aftime2ctime (&node->di.mtime);
grub_free (node); grub_free (node);
return hook (filename, &info); return ctx->hook (filename, &info, ctx->hook_data);
} }
static grub_err_t
grub_affs_dir (grub_device_t device, const char *path,
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;
grub_dl_ref (my_mod); grub_dl_ref (my_mod);
@ -581,7 +588,7 @@ grub_affs_dir (grub_device_t device, const char *path,
if (grub_errno) if (grub_errno)
goto fail; goto fail;
grub_affs_iterate_dir (fdiro, iterate); grub_affs_iterate_dir (fdiro, grub_affs_dir_iter, &ctx);
fail: fail:
if (data && fdiro != &data->diropen) if (data && fdiro != &data->diropen)

View file

@ -173,6 +173,15 @@ struct grub_bfs_data
struct grub_bfs_inode ino[0]; 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 static grub_err_t
read_extent (grub_disk_t disk, read_extent (grub_disk_t disk,
const struct grub_bfs_superblock *sb, const struct grub_bfs_superblock *sb,
@ -413,7 +422,9 @@ static int
iterate_in_b_tree (grub_disk_t disk, iterate_in_b_tree (grub_disk_t disk,
const struct grub_bfs_superblock *sb, const struct grub_bfs_superblock *sb,
const struct grub_bfs_inode *ino, 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; struct grub_bfs_btree_header head;
grub_err_t err; 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); end = grub_bfs_to_cpu_treehead (node.total_key_len);
c = key_data[end]; c = key_data[end];
key_data[end] = 0; 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; return 1;
key_data[end] = c; key_data[end] = c;
} }
@ -844,29 +856,23 @@ mount (grub_disk_t disk, struct grub_bfs_superblock *sb)
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
static grub_err_t /* Helper for grub_bfs_dir. */
grub_bfs_dir (grub_device_t device, const char *path, static int
int (*hook_in) (const char *filename, grub_bfs_dir_iter (const char *name, grub_uint64_t value,
const struct grub_dirhook_info * info)) struct grub_bfs_dir_ctx *ctx)
{ {
struct grub_bfs_superblock sb;
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; grub_err_t err2;
union union
{ {
struct grub_bfs_inode ino; 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; } ino;
struct grub_dirhook_info info; struct grub_dirhook_info info;
err2 = grub_disk_read (device->disk, value err2 = grub_disk_read (ctx->device->disk, value
<< (grub_bfs_to_cpu32 (sb.log2_bsize) << (grub_bfs_to_cpu32 (ctx->sb.log2_bsize)
- GRUB_DISK_SECTOR_BITS), 0, - GRUB_DISK_SECTOR_BITS), 0,
grub_bfs_to_cpu32 (sb.bsize), (char *) ino.raw); grub_bfs_to_cpu32 (ctx->sb.bsize), (char *) ino.raw);
if (err2) if (err2)
{ {
grub_print_error (); grub_print_error ();
@ -881,9 +887,21 @@ grub_bfs_dir (grub_device_t device, const char *path,
info.mtime = grub_bfs_to_cpu64 (ino.ino.mtime) >> 16; info.mtime = grub_bfs_to_cpu64 (ino.ino.mtime) >> 16;
#endif #endif
info.dir = ((grub_bfs_to_cpu32 (ino.ino.mode) & ATTR_TYPE) == ATTR_DIR); info.dir = ((grub_bfs_to_cpu32 (ino.ino.mode) & ATTR_TYPE) == ATTR_DIR);
return hook_in (name, &info); return ctx->hook (name, &info, ctx->hook_data);
} }
err = mount (device->disk, &sb);
static grub_err_t
grub_bfs_dir (grub_device_t device, const char *path,
grub_fs_dir_hook_t hook, void *hook_data)
{
struct grub_bfs_dir_ctx ctx = {
.device = device,
.hook = hook,
.hook_data = hook_data
};
grub_err_t err;
err = mount (device->disk, &ctx.sb);
if (err) if (err)
return err; return err;
@ -891,14 +909,15 @@ grub_bfs_dir (grub_device_t device, const char *path,
union union
{ {
struct grub_bfs_inode ino; 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; } ino;
err = find_file (path, device->disk, &sb, &ino.ino); err = find_file (path, device->disk, &ctx.sb, &ino.ino);
if (err) if (err)
return err; return err;
if (((grub_bfs_to_cpu32 (ino.ino.mode) & ATTR_TYPE) != ATTR_DIR)) if (((grub_bfs_to_cpu32 (ino.ino.mode) & ATTR_TYPE) != ATTR_DIR))
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); 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; return grub_errno;

View file

@ -1491,8 +1491,7 @@ find_path (struct grub_btrfs_data *data,
static grub_err_t static grub_err_t
grub_btrfs_dir (grub_device_t device, const char *path, grub_btrfs_dir (grub_device_t device, const char *path,
int (*hook) (const char *filename, grub_fs_dir_hook_t hook, void *hook_data)
const struct grub_dirhook_info *info))
{ {
struct grub_btrfs_data *data = grub_btrfs_mount (device); struct grub_btrfs_data *data = grub_btrfs_mount (device);
struct grub_btrfs_key key_in, key_out; 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)]; c = cdirel->name[grub_le_to_cpu16 (cdirel->n)];
cdirel->name[grub_le_to_cpu16 (cdirel->n)] = 0; cdirel->name[grub_le_to_cpu16 (cdirel->n)] = 0;
info.dir = (cdirel->type == GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY); info.dir = (cdirel->type == GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY);
if (hook (cdirel->name, &info)) if (hook (cdirel->name, &info, hook_data))
goto out; goto out;
cdirel->name[grub_le_to_cpu16 (cdirel->n)] = c; cdirel->name[grub_le_to_cpu16 (cdirel->n)] = c;
} }

View file

@ -513,8 +513,7 @@ handle_symlink (struct grub_cpio_data *data,
static grub_err_t static grub_err_t
grub_cpio_dir (grub_device_t device, const char *path_in, grub_cpio_dir (grub_device_t device, const char *path_in,
int (*hook) (const char *filename, grub_fs_dir_hook_t hook, void *hook_data)
const struct grub_dirhook_info *info))
{ {
struct grub_cpio_data *data; struct grub_cpio_data *data;
grub_disk_addr_t ofs; grub_disk_addr_t ofs;
@ -575,7 +574,7 @@ grub_cpio_dir (grub_device_t device, const char *path_in,
info.mtime = mtime; info.mtime = mtime;
info.mtimeset = 1; info.mtimeset = 1;
if (hook (n, &info)) if (hook (n, &info, hook_data))
{ {
grub_free (name); grub_free (name);
goto fail; goto fail;

View file

@ -692,10 +692,7 @@ grub_ext2_read_symlink (grub_fshelp_node_t node)
static int static int
grub_ext2_iterate_dir (grub_fshelp_node_t dir, grub_ext2_iterate_dir (grub_fshelp_node_t dir,
int NESTED_FUNC_ATTR grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
(*hook) (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node))
{ {
unsigned int fpos = 0; unsigned int fpos = 0;
struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir; 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; type = GRUB_FSHELP_REG;
} }
if (hook (filename, type, fdiro)) if (hook (filename, type, fdiro, hook_data))
return 1; return 1;
} }
@ -858,27 +855,26 @@ grub_ext2_read (grub_file_t file, char *buf, grub_size_t len)
} }
static grub_err_t /* Context for grub_ext2_dir. */
grub_ext2_dir (grub_device_t device, const char *path, struct grub_ext2_dir_ctx
int (*hook) (const char *filename,
const struct grub_dirhook_info *info))
{ {
struct grub_ext2_data *data = 0; grub_fs_dir_hook_t hook;
struct grub_fshelp_node *fdiro = 0; void *hook_data;
struct grub_ext2_data *data;
};
auto int NESTED_FUNC_ATTR iterate (const char *filename, /* Helper for grub_ext2_dir. */
enum grub_fshelp_filetype filetype, static int
grub_fshelp_node_t node); grub_ext2_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node, void *data)
int NESTED_FUNC_ATTR iterate (const char *filename, {
enum grub_fshelp_filetype filetype, struct grub_ext2_dir_ctx *ctx = data;
grub_fshelp_node_t node)
{
struct grub_dirhook_info info; struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info)); grub_memset (&info, 0, sizeof (info));
if (! node->inode_read) if (! node->inode_read)
{ {
grub_ext2_read_inode (data, node->ino, &node->inode); grub_ext2_read_inode (ctx->data, node->ino, &node->inode);
if (!grub_errno) if (!grub_errno)
node->inode_read = 1; node->inode_read = 1;
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
@ -891,26 +887,37 @@ grub_ext2_dir (grub_device_t device, const char *path,
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
grub_free (node); grub_free (node);
return hook (filename, &info); 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); grub_dl_ref (my_mod);
data = grub_ext2_mount (device->disk); ctx.data = grub_ext2_mount (device->disk);
if (! data) if (! ctx.data)
goto fail; goto fail;
grub_fshelp_find_file (path, &data->diropen, &fdiro, grub_ext2_iterate_dir, grub_fshelp_find_file (path, &ctx.data->diropen, &fdiro,
grub_ext2_read_symlink, GRUB_FSHELP_DIR); grub_ext2_iterate_dir, grub_ext2_read_symlink,
GRUB_FSHELP_DIR);
if (grub_errno) if (grub_errno)
goto fail; goto fail;
grub_ext2_iterate_dir (fdiro, iterate); grub_ext2_iterate_dir (fdiro, grub_ext2_dir_iter, &ctx);
fail: fail:
if (fdiro != &data->diropen) if (fdiro != &ctx.data->diropen)
grub_free (fdiro); grub_free (fdiro);
grub_free (data); grub_free (ctx.data);
grub_dl_unref (my_mod); grub_dl_unref (my_mod);

View file

@ -844,8 +844,7 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data,
static char * static char *
grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data, grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
const char *path, const char *origpath, const char *path, const char *origpath,
int (*hook) (const char *filename, grub_fs_dir_hook_t hook, void *hook_data)
const struct grub_dirhook_info *info))
{ {
char *dirname, *dirp; char *dirname, *dirp;
int call_hook; int call_hook;
@ -905,7 +904,7 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
#endif #endif
if (*dirname == '\0' && call_hook) if (*dirname == '\0' && call_hook)
{ {
if (hook (ctxt.filename, &info)) if (hook (ctxt.filename, &info, hook_data))
break; break;
else else
continue; continue;
@ -926,7 +925,7 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
data->cur_cluster_num = ~0U; data->cur_cluster_num = ~0U;
if (call_hook) if (call_hook)
hook (ctxt.filename, &info); hook (ctxt.filename, &info, hook_data);
break; break;
} }
@ -946,9 +945,8 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
} }
static grub_err_t static grub_err_t
grub_fat_dir (grub_device_t device, const char *path, grub_fat_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook,
int (*hook) (const char *filename, void *hook_data)
const struct grub_dirhook_info *info))
{ {
struct grub_fat_data *data = 0; struct grub_fat_data *data = 0;
grub_disk_t disk = device->disk; grub_disk_t disk = device->disk;
@ -976,7 +974,7 @@ grub_fat_dir (grub_device_t device, const char *path,
do 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); while (p && grub_errno == GRUB_ERR_NONE);
@ -1004,7 +1002,7 @@ grub_fat_open (grub_file_t file, const char *name)
do 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) if (grub_errno != GRUB_ERR_NONE)
goto fail; goto fail;
} }

View file

@ -27,87 +27,78 @@
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
/* Lookup the node PATH. The node ROOTNODE describes the root of the typedef int (*iterate_dir_func) (grub_fshelp_node_t dir,
directory tree. The node found is returned in FOUNDNODE, which is grub_fshelp_iterate_dir_hook_t hook,
either a ROOTNODE or a new malloc'ed node. ITERATE_DIR is used to void *data);
iterate over all directory entries in the current node. typedef char *(*read_symlink_func) (grub_fshelp_node_t 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 /* Context for grub_fshelp_find_file. */
error is generated if the node is not of the expected type. Make struct grub_fshelp_find_file_ctx
sure you use the NESTED_FUNC_ATTR macro for HOOK, this is required
because GCC has a nasty bug when using regparm=3. */
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),
enum grub_fshelp_filetype expecttype)
{ {
grub_err_t err; const char *path;
enum grub_fshelp_filetype foundtype = GRUB_FSHELP_DIR; grub_fshelp_node_t rootnode, currroot, currnode, oldnode;
int symlinknest = 0; enum grub_fshelp_filetype foundtype;
int symlinknest;
char *name;
enum grub_fshelp_filetype type;
};
auto grub_err_t NESTED_FUNC_ATTR find_file (const char *currpath, /* Helper for find_file_iter. */
grub_fshelp_node_t currroot, static void
grub_fshelp_node_t *currfound); free_node (grub_fshelp_node_t node, struct grub_fshelp_find_file_ctx *ctx)
{
grub_err_t NESTED_FUNC_ATTR find_file (const char *currpath, if (node != ctx->rootnode && node != ctx->currroot)
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); 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;
int NESTED_FUNC_ATTR iterate (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node)
{
if (filetype == GRUB_FSHELP_UNKNOWN || if (filetype == GRUB_FSHELP_UNKNOWN ||
(grub_strcmp (name, filename) && (grub_strcmp (ctx->name, filename) &&
(! (filetype & GRUB_FSHELP_CASE_INSENSITIVE) || (! (filetype & GRUB_FSHELP_CASE_INSENSITIVE) ||
grub_strcasecmp (name, filename)))) grub_strcasecmp (ctx->name, filename))))
{ {
grub_free (node); grub_free (node);
return 0; return 0;
} }
/* The node is found, stop iterating over the nodes. */ /* The node is found, stop iterating over the nodes. */
type = filetype & ~GRUB_FSHELP_CASE_INSENSITIVE; ctx->type = filetype & ~GRUB_FSHELP_CASE_INSENSITIVE;
oldnode = currnode; ctx->oldnode = ctx->currnode;
currnode = node; ctx->currnode = node;
return 1; 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); grub_strncpy (fpath, currpath, grub_strlen (currpath) + 1);
/* Remove all leading slashes. */ /* Remove all leading slashes. */
while (*name == '/') while (*ctx->name == '/')
name++; ctx->name++;
if (! *name) if (! *ctx->name)
{ {
*currfound = currnode; *currfound = ctx->currnode;
return 0; return 0;
} }
@ -116,7 +107,7 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode,
int found; int found;
/* Extract the actual part from the pathname. */ /* Extract the actual part from the pathname. */
next = grub_strchr (name, '/'); next = grub_strchr (ctx->name, '/');
if (next) if (next)
{ {
/* Remove all leading slashes. */ /* Remove all leading slashes. */
@ -126,19 +117,19 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode,
/* At this point it is expected that the current node is a /* At this point it is expected that the current node is a
directory, check if this is true. */ directory, check if this is true. */
if (type != GRUB_FSHELP_DIR) if (ctx->type != GRUB_FSHELP_DIR)
{ {
free_node (currnode); free_node (ctx->currnode, ctx);
currnode = 0; ctx->currnode = 0;
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
} }
/* Iterate over the directory. */ /* Iterate over the directory. */
found = iterate_dir (currnode, iterate); found = iterate_dir (ctx->currnode, find_file_iter, ctx);
if (! found) if (! found)
{ {
free_node (currnode); free_node (ctx->currnode, ctx);
currnode = 0; ctx->currnode = 0;
if (grub_errno) if (grub_errno)
return grub_errno; return grub_errno;
@ -146,65 +137,89 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode,
} }
/* Read in the symlink and follow it. */ /* Read in the symlink and follow it. */
if (type == GRUB_FSHELP_SYMLINK) if (ctx->type == GRUB_FSHELP_SYMLINK)
{ {
char *symlink; char *symlink;
/* Test if the symlink does not loop. */ /* Test if the symlink does not loop. */
if (++symlinknest == 8) if (++ctx->symlinknest == 8)
{ {
free_node (currnode); free_node (ctx->currnode, ctx);
free_node (oldnode); free_node (ctx->oldnode, ctx);
currnode = 0; ctx->currnode = 0;
return grub_error (GRUB_ERR_SYMLINK_LOOP, return grub_error (GRUB_ERR_SYMLINK_LOOP,
N_("too deep nesting of symlinks")); N_("too deep nesting of symlinks"));
} }
symlink = read_symlink (currnode); symlink = read_symlink (ctx->currnode);
free_node (currnode); free_node (ctx->currnode, ctx);
currnode = 0; ctx->currnode = 0;
if (!symlink) if (!symlink)
{ {
free_node (oldnode); free_node (ctx->oldnode, ctx);
return grub_errno; return grub_errno;
} }
/* The symlink is an absolute path, go back to the root inode. */ /* The symlink is an absolute path, go back to the root inode. */
if (symlink[0] == '/') if (symlink[0] == '/')
{ {
free_node (oldnode); free_node (ctx->oldnode, ctx);
oldnode = rootnode; ctx->oldnode = ctx->rootnode;
} }
/* Lookup the node the symlink points to. */ /* Lookup the node the symlink points to. */
find_file (symlink, oldnode, &currnode); find_file (symlink, ctx->oldnode, &ctx->currnode,
type = foundtype; iterate_dir, read_symlink, ctx);
ctx->type = ctx->foundtype;
grub_free (symlink); grub_free (symlink);
if (grub_errno) if (grub_errno)
{ {
free_node (oldnode); free_node (ctx->oldnode, ctx);
return grub_errno; return grub_errno;
} }
} }
if (oldnode != currnode) if (ctx->oldnode != ctx->currnode)
free_node (oldnode); free_node (ctx->oldnode, ctx);
/* Found the node! */ /* Found the node! */
if (! next || *next == '\0') if (! next || *next == '\0')
{ {
*currfound = currnode; *currfound = ctx->currnode;
foundtype = type; ctx->foundtype = ctx->type;
return 0; return 0;
} }
name = next; ctx->name = next;
} }
return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path); 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. */
grub_err_t
grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode,
grub_fshelp_node_t *foundnode,
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;
if (!path || path[0] != '/') if (!path || path[0] != '/')
{ {
@ -212,14 +227,14 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode,
return grub_errno; return grub_errno;
} }
err = find_file (path, rootnode, foundnode); err = find_file (path, rootnode, foundnode, iterate_dir, read_symlink, &ctx);
if (err) if (err)
return err; return err;
/* Check if the node that was found was of the expected type. */ /* 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")); 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 grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
return 0; return 0;

View file

@ -1151,9 +1151,8 @@ grub_hfs_find_dir (struct grub_hfs_data *data, const char *path,
static grub_err_t static grub_err_t
grub_hfs_dir (grub_device_t device, const char *path, grub_hfs_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook,
int (*hook) (const char *filename, void *hook_data)
const struct grub_dirhook_info *info))
{ {
int inode; int inode;
@ -1184,14 +1183,14 @@ grub_hfs_dir (grub_device_t device, const char *path,
info.dir = 1; info.dir = 1;
info.mtimeset = 1; info.mtimeset = 1;
info.mtime = grub_be_to_cpu32 (drec->mtime) - 2082844800; 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) if (frec->type == GRUB_HFS_FILETYPE_FILE)
{ {
info.dir = 0; info.dir = 0;
info.mtimeset = 1; info.mtimeset = 1;
info.mtime = grub_be_to_cpu32 (frec->mtime) - 2082844800; info.mtime = grub_be_to_cpu32 (frec->mtime) - 2082844800;
return hook (fname, &info); return hook (fname, &info, hook_data);
} }
return 0; return 0;

View file

@ -766,10 +766,7 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree,
static int static int
grub_hfsplus_iterate_dir (grub_fshelp_node_t dir, grub_hfsplus_iterate_dir (grub_fshelp_node_t dir,
int NESTED_FUNC_ATTR grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
(*hook) (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node))
{ {
int ret = 0; int ret = 0;
@ -825,7 +822,7 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir,
node->size = 0; node->size = 0;
node->fileid = grub_be_to_cpu32 (fileinfo->parentid); node->fileid = grub_be_to_cpu32 (fileinfo->parentid);
ret = hook ("..", GRUB_FSHELP_DIR, node); ret = hook ("..", GRUB_FSHELP_DIR, node, hook_data);
return ret; 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->size = grub_be_to_cpu64 (fileinfo->data.size);
node->fileid = grub_be_to_cpu32 (fileinfo->fileid); node->fileid = grub_be_to_cpu32 (fileinfo->fileid);
ret = hook (filename, type, node); ret = hook (filename, type, node, hook_data);
grub_free (filename); grub_free (filename);
@ -895,7 +892,7 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir,
if (!fsnode) if (!fsnode)
return 1; return 1;
*fsnode = *dir; *fsnode = *dir;
if (hook (".", GRUB_FSHELP_DIR, fsnode)) if (hook (".", GRUB_FSHELP_DIR, fsnode, hook_data))
return 1; return 1;
} }
@ -978,31 +975,38 @@ grub_hfsplus_read (grub_file_t file, char *buf, grub_size_t len)
file->offset, len, buf); file->offset, len, buf);
} }
static grub_err_t /* Context for grub_hfsplus_dir. */
grub_hfsplus_dir (grub_device_t device, const char *path, struct grub_hfsplus_dir_ctx
int (*hook) (const char *filename,
const struct grub_dirhook_info *info))
{ {
struct grub_hfsplus_data *data = 0; grub_fs_dir_hook_t hook;
struct grub_fshelp_node *fdiro = 0; void *hook_data;
};
auto int NESTED_FUNC_ATTR iterate (const char *filename, /* Helper for grub_hfsplus_dir. */
static int
grub_hfsplus_dir_iter (const char *filename,
enum grub_fshelp_filetype filetype, enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node); grub_fshelp_node_t node, void *data)
{
int NESTED_FUNC_ATTR iterate (const char *filename, struct grub_hfsplus_dir_ctx *ctx = data;
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node)
{
struct grub_dirhook_info info; struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info)); grub_memset (&info, 0, sizeof (info));
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
info.mtimeset = 1; info.mtimeset = 1;
info.mtime = node->mtime; info.mtime = node->mtime;
info.case_insensitive = !! (filetype & GRUB_FSHELP_CASE_INSENSITIVE); info.case_insensitive = !! (filetype & GRUB_FSHELP_CASE_INSENSITIVE);
grub_free (node); grub_free (node);
return hook (filename, &info); return ctx->hook (filename, &info, ctx->hook_data);
} }
static grub_err_t
grub_hfsplus_dir (grub_device_t device, const char *path,
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;
grub_dl_ref (my_mod); grub_dl_ref (my_mod);
@ -1018,7 +1022,7 @@ grub_hfsplus_dir (grub_device_t device, const char *path,
goto fail; goto fail;
/* Iterate over all entries in this directory. */ /* Iterate over all entries in this directory. */
grub_hfsplus_iterate_dir (fdiro, iterate); grub_hfsplus_iterate_dir (fdiro, grub_hfsplus_dir_iter, &ctx);
fail: fail:
if (data && fdiro != &data->dirroot) if (data && fdiro != &data->dirroot)

View file

@ -521,10 +521,7 @@ get_node_size (grub_fshelp_node_t node)
static int static int
grub_iso9660_iterate_dir (grub_fshelp_node_t dir, grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
int NESTED_FUNC_ATTR grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
(*hook) (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node))
{ {
struct grub_iso9660_dir dirent; struct grub_iso9660_dir dirent;
grub_off_t offset = 0; grub_off_t offset = 0;
@ -828,7 +825,7 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
symlink = 0; symlink = 0;
was_continue = 0; was_continue = 0;
} }
if (hook (filename, type, node)) if (hook (filename, type, node, hook_data))
{ {
if (filename_alloc) if (filename_alloc)
grub_free (filename); grub_free (filename);
@ -844,31 +841,38 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
static grub_err_t /* Context for grub_iso9660_dir. */
grub_iso9660_dir (grub_device_t device, const char *path, struct grub_iso9660_dir_ctx
int (*hook) (const char *filename,
const struct grub_dirhook_info *info))
{ {
struct grub_iso9660_data *data = 0; grub_fs_dir_hook_t hook;
struct grub_fshelp_node rootnode; void *hook_data;
struct grub_fshelp_node *foundnode; };
auto int NESTED_FUNC_ATTR iterate (const char *filename, /* Helper for grub_iso9660_dir. */
static int
grub_iso9660_dir_iter (const char *filename,
enum grub_fshelp_filetype filetype, enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node); grub_fshelp_node_t node, void *data)
{
int NESTED_FUNC_ATTR iterate (const char *filename, struct grub_iso9660_dir_ctx *ctx = data;
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node)
{
struct grub_dirhook_info info; struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info)); grub_memset (&info, 0, sizeof (info));
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
info.mtimeset = !!iso9660_to_unixtime2 (&node->dirents[0].mtime, &info.mtime); info.mtimeset = !!iso9660_to_unixtime2 (&node->dirents[0].mtime, &info.mtime);
grub_free (node); grub_free (node);
return hook (filename, &info); return ctx->hook (filename, &info, ctx->hook_data);
} }
static grub_err_t
grub_iso9660_dir (grub_device_t device, const char *path,
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;
grub_dl_ref (my_mod); grub_dl_ref (my_mod);
@ -891,7 +895,7 @@ grub_iso9660_dir (grub_device_t device, const char *path,
goto fail; goto fail;
/* List the files in the directory. */ /* 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) if (foundnode != &rootnode)
grub_free (foundnode); grub_free (foundnode);

View file

@ -799,8 +799,7 @@ grub_jfs_lookup_symlink (struct grub_jfs_data *data, grub_uint32_t ino)
static grub_err_t static grub_err_t
grub_jfs_dir (grub_device_t device, const char *path, grub_jfs_dir (grub_device_t device, const char *path,
int (*hook) (const char *filename, grub_fs_dir_hook_t hook, void *hook_data)
const struct grub_dirhook_info *info))
{ {
struct grub_jfs_data *data = 0; struct grub_jfs_data *data = 0;
struct grub_jfs_diropen *diro = 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; & GRUB_JFS_FILETYPE_MASK) == GRUB_JFS_FILETYPE_DIR;
info.mtimeset = 1; info.mtimeset = 1;
info.mtime = grub_le_to_cpu32 (inode.mtime.sec); info.mtime = grub_le_to_cpu32 (inode.mtime.sec);
if (hook (diro->name, &info)) if (hook (diro->name, &info, hook_data))
goto fail; goto fail;
} }

View file

@ -536,8 +536,7 @@ grub_minix_mount (grub_disk_t disk)
static grub_err_t static grub_err_t
grub_minix_dir (grub_device_t device, const char *path, grub_minix_dir (grub_device_t device, const char *path,
int (*hook) (const char *filename, grub_fs_dir_hook_t hook, void *hook_data)
const struct grub_dirhook_info *info))
{ {
struct grub_minix_data *data = 0; struct grub_minix_data *data = 0;
unsigned int pos = 0; unsigned int pos = 0;
@ -590,7 +589,7 @@ grub_minix_dir (grub_device_t device, const char *path,
info.mtimeset = 1; info.mtimeset = 1;
info.mtime = grub_minix_to_cpu32 (data->inode.mtime); info.mtime = grub_minix_to_cpu32 (data->inode.mtime);
if (hook (filename, &info) ? 1 : 0) if (hook (filename, &info, hook_data) ? 1 : 0)
break; break;
/* Load the old inode back in. */ /* Load the old inode back in. */

View file

@ -870,10 +870,7 @@ grub_nilfs2_read_symlink (grub_fshelp_node_t node)
static int static int
grub_nilfs2_iterate_dir (grub_fshelp_node_t dir, grub_nilfs2_iterate_dir (grub_fshelp_node_t dir,
int NESTED_FUNC_ATTR grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
(*hook) (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node))
{ {
grub_off_t fpos = 0; grub_off_t fpos = 0;
struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir; 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; type = GRUB_FSHELP_REG;
} }
if (hook (filename, type, fdiro)) if (hook (filename, type, fdiro, hook_data))
return 1; return 1;
} }
@ -1032,27 +1029,26 @@ grub_nilfs2_read (grub_file_t file, char *buf, grub_size_t len)
file->offset, len, buf); file->offset, len, buf);
} }
static grub_err_t /* Context for grub_nilfs2_dir. */
grub_nilfs2_dir (grub_device_t device, const char *path, struct grub_nilfs2_dir_ctx
int (*hook) (const char *filename,
const struct grub_dirhook_info * info))
{ {
struct grub_nilfs2_data *data = 0; grub_fs_dir_hook_t hook;
struct grub_fshelp_node *fdiro = 0; void *hook_data;
struct grub_nilfs2_data *data;
};
auto int NESTED_FUNC_ATTR iterate (const char *filename, /* Helper for grub_nilfs2_dir. */
enum grub_fshelp_filetype filetype, static int
grub_fshelp_node_t node); grub_nilfs2_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node, void *data)
int NESTED_FUNC_ATTR iterate (const char *filename, {
enum grub_fshelp_filetype filetype, struct grub_nilfs2_dir_ctx *ctx = data;
grub_fshelp_node_t node)
{
struct grub_dirhook_info info; struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info)); grub_memset (&info, 0, sizeof (info));
if (!node->inode_read) if (!node->inode_read)
{ {
grub_nilfs2_read_inode (data, node->ino, &node->inode); grub_nilfs2_read_inode (ctx->data, node->ino, &node->inode);
if (!grub_errno) if (!grub_errno)
node->inode_read = 1; node->inode_read = 1;
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
@ -1065,27 +1061,37 @@ grub_nilfs2_dir (grub_device_t device, const char *path,
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
grub_free (node); grub_free (node);
return hook (filename, &info); return ctx->hook (filename, &info, ctx->hook_data);
} }
static grub_err_t
grub_nilfs2_dir (grub_device_t device, const char *path,
grub_fs_dir_hook_t hook, void *hook_data)
{
struct grub_nilfs2_dir_ctx ctx = {
.hook = hook,
.hook_data = hook_data
};
struct grub_fshelp_node *fdiro = 0;
grub_dl_ref (my_mod); grub_dl_ref (my_mod);
data = grub_nilfs2_mount (device->disk); ctx.data = grub_nilfs2_mount (device->disk);
if (!data) if (!ctx.data)
goto fail; 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_nilfs2_iterate_dir, grub_nilfs2_read_symlink,
GRUB_FSHELP_DIR); GRUB_FSHELP_DIR);
if (grub_errno) if (grub_errno)
goto fail; goto fail;
grub_nilfs2_iterate_dir (fdiro, iterate); grub_nilfs2_iterate_dir (fdiro, grub_nilfs2_dir_iter, &ctx);
fail: fail:
if (fdiro != &data->diropen) if (fdiro != &ctx.data->diropen)
grub_free (fdiro); grub_free (fdiro);
grub_free (data); grub_free (ctx.data);
grub_dl_unref (my_mod); grub_dl_unref (my_mod);

View file

@ -600,10 +600,7 @@ free_file (struct grub_ntfs_file *mft)
static int static int
list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos, list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos,
int NESTED_FUNC_ATTR grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
(*hook) (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node))
{ {
grub_uint8_t *np; grub_uint8_t *np;
int ns; int ns;
@ -667,7 +664,7 @@ list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos,
if (namespace) if (namespace)
type |= GRUB_FSHELP_CASE_INSENSITIVE; type |= GRUB_FSHELP_CASE_INSENSITIVE;
if (hook (ustr, type, fdiro)) if (hook (ustr, type, fdiro, hook_data))
{ {
grub_free (ustr); grub_free (ustr);
return 1; return 1;
@ -778,10 +775,7 @@ grub_ntfs_read_symlink (grub_fshelp_node_t node)
static int static int
grub_ntfs_iterate_dir (grub_fshelp_node_t dir, grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
int NESTED_FUNC_ATTR grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
(*hook) (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node))
{ {
grub_uint8_t *bitmap; grub_uint8_t *bitmap;
struct grub_ntfs_attr attr, *at; 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 */ 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) if (ret)
goto done; goto done;
@ -909,7 +903,8 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
|| (fixup (indx, mft->data->idx_size, || (fixup (indx, mft->data->idx_size,
(const grub_uint8_t *) "INDX"))) (const grub_uint8_t *) "INDX")))
goto done; 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) if (ret)
goto done; goto done;
} }
@ -1017,23 +1012,21 @@ fail:
return 0; return 0;
} }
static grub_err_t /* Context for grub_ntfs_dir. */
grub_ntfs_dir (grub_device_t device, const char *path, struct grub_ntfs_dir_ctx
int (*hook) (const char *filename,
const struct grub_dirhook_info *info))
{ {
struct grub_ntfs_data *data = 0; grub_fs_dir_hook_t hook;
struct grub_fshelp_node *fdiro = 0; void *hook_data;
};
auto int NESTED_FUNC_ATTR iterate (const char *filename, /* Helper for grub_ntfs_dir. */
enum grub_fshelp_filetype filetype, static int
grub_fshelp_node_t node); grub_ntfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node, void *data)
int NESTED_FUNC_ATTR iterate (const char *filename, {
enum grub_fshelp_filetype filetype, struct grub_ntfs_dir_ctx *ctx = data;
grub_fshelp_node_t node)
{
struct grub_dirhook_info info; struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info)); grub_memset (&info, 0, sizeof (info));
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
info.mtimeset = 1; info.mtimeset = 1;
@ -1041,8 +1034,16 @@ grub_ntfs_dir (grub_device_t device, const char *path,
- 86400ULL * 365 * (1970 - 1601) - 86400ULL * 365 * (1970 - 1601)
- 86400ULL * ((1970 - 1601) / 4) + 86400ULL * ((1970 - 1601) / 100); - 86400ULL * ((1970 - 1601) / 4) + 86400ULL * ((1970 - 1601) / 100);
grub_free (node); grub_free (node);
return hook (filename, &info); return ctx->hook (filename, &info, ctx->hook_data);
} }
static grub_err_t
grub_ntfs_dir (grub_device_t device, const char *path,
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;
grub_dl_ref (my_mod); grub_dl_ref (my_mod);
@ -1056,7 +1057,7 @@ grub_ntfs_dir (grub_device_t device, const char *path,
if (grub_errno) if (grub_errno)
goto fail; goto fail;
grub_ntfs_iterate_dir (fdiro, iterate); grub_ntfs_iterate_dir (fdiro, grub_ntfs_dir_iter, &ctx);
fail: fail:
if ((fdiro) && (fdiro != &data->cmft)) if ((fdiro) && (fdiro != &data->cmft))

View file

@ -718,10 +718,8 @@ grub_reiserfs_mount (grub_disk_t disk)
/* Call HOOK for each file in directory ITEM. */ /* Call HOOK for each file in directory ITEM. */
static int static int
grub_reiserfs_iterate_dir (grub_fshelp_node_t item, grub_reiserfs_iterate_dir (grub_fshelp_node_t item,
int NESTED_FUNC_ATTR grub_fshelp_iterate_dir_hook_t hook,
(*hook) (const char *filename, void *hook_data)
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node))
{ {
struct grub_reiserfs_data *data = item->data; struct grub_reiserfs_data *data = item->data;
struct grub_reiserfs_block_header *block_header = 0; struct grub_reiserfs_block_header *block_header = 0;
@ -946,7 +944,7 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item,
goto next; 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", grub_dprintf ("reiserfs", "Found : %s, type=%d\n",
entry_name, entry_type); entry_name, entry_type);
@ -1254,32 +1252,40 @@ grub_reiserfs_close (grub_file_t file)
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
/* Call HOOK with each file under DIR. */ /* Context for grub_reiserfs_dir. */
static grub_err_t struct grub_reiserfs_dir_ctx
grub_reiserfs_dir (grub_device_t device, const char *path,
int (*hook) (const char *filename,
const struct grub_dirhook_info *info))
{ {
struct grub_reiserfs_data *data = 0; grub_fs_dir_hook_t hook;
struct grub_fshelp_node root, *found; void *hook_data;
struct grub_reiserfs_key root_key; };
auto int NESTED_FUNC_ATTR iterate (const char *filename, /* Helper for grub_reiserfs_dir. */
static int
grub_reiserfs_dir_iter (const char *filename,
enum grub_fshelp_filetype filetype, enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node); grub_fshelp_node_t node, void *data)
{
int NESTED_FUNC_ATTR iterate (const char *filename, struct grub_reiserfs_dir_ctx *ctx = data;
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node)
{
struct grub_dirhook_info info; struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info)); grub_memset (&info, 0, sizeof (info));
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
info.mtimeset = 1; info.mtimeset = 1;
info.mtime = node->mtime; info.mtime = node->mtime;
grub_free (node); grub_free (node);
return hook (filename, &info); 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,
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;
grub_dl_ref (my_mod); grub_dl_ref (my_mod);
data = grub_reiserfs_mount (device->disk); data = grub_reiserfs_mount (device->disk);
if (! data) if (! data)
@ -1300,7 +1306,7 @@ grub_reiserfs_dir (grub_device_t device, const char *path,
grub_reiserfs_read_symlink, GRUB_FSHELP_DIR); grub_reiserfs_read_symlink, GRUB_FSHELP_DIR);
if (grub_errno) if (grub_errno)
goto fail; goto fail;
grub_reiserfs_iterate_dir (found, iterate); grub_reiserfs_iterate_dir (found, grub_reiserfs_dir_iter, &ctx);
grub_free (data); grub_free (data);
grub_dl_unref (my_mod); grub_dl_unref (my_mod);
return GRUB_ERR_NONE; return GRUB_ERR_NONE;

View file

@ -171,10 +171,7 @@ grub_romfs_read_symlink (grub_fshelp_node_t node)
static int static int
grub_romfs_iterate_dir (grub_fshelp_node_t dir, grub_romfs_iterate_dir (grub_fshelp_node_t dir,
int NESTED_FUNC_ATTR grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
(*hook) (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node))
{ {
grub_disk_addr_t caddr; grub_disk_addr_t caddr;
struct grub_romfs_file_header hdr; 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); grub_free (name);
return 1; return 1;
@ -316,29 +313,35 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir,
return 0; return 0;
} }
static grub_err_t /* Context for grub_romfs_dir. */
grub_romfs_dir (grub_device_t device, const char *path, struct grub_romfs_dir_ctx
int (*hook) (const char *filename,
const struct grub_dirhook_info *info))
{ {
struct grub_romfs_data *data = 0; grub_fs_dir_hook_t hook;
struct grub_fshelp_node *fdiro = 0, start; void *hook_data;
};
auto int NESTED_FUNC_ATTR iterate (const char *filename, /* Helper for grub_romfs_dir. */
enum grub_fshelp_filetype filetype, static int
grub_fshelp_node_t node); grub_romfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node, void *data)
int NESTED_FUNC_ATTR iterate (const char *filename, {
enum grub_fshelp_filetype filetype, struct grub_romfs_dir_ctx *ctx = data;
grub_fshelp_node_t node)
{
struct grub_dirhook_info info; struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info)); grub_memset (&info, 0, sizeof (info));
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
grub_free (node); grub_free (node);
return hook (filename, &info); return ctx->hook (filename, &info, ctx->hook_data);
} }
static grub_err_t
grub_romfs_dir (grub_device_t device, const char *path,
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;
data = grub_romfs_mount (device); data = grub_romfs_mount (device);
if (! data) if (! data)
@ -352,7 +355,7 @@ grub_romfs_dir (grub_device_t device, const char *path,
if (grub_errno) if (grub_errno)
goto fail; goto fail;
grub_romfs_iterate_dir (fdiro, iterate); grub_romfs_iterate_dir (fdiro, grub_romfs_dir_iter, &ctx);
fail: fail:
grub_free (data); grub_free (data);

View file

@ -460,12 +460,48 @@ grub_sfs_read_symlink (grub_fshelp_node_t node)
return symlink; 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 static int
grub_sfs_iterate_dir (grub_fshelp_node_t dir, grub_sfs_iterate_dir (grub_fshelp_node_t dir,
int NESTED_FUNC_ATTR grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
(*hook) (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node))
{ {
struct grub_fshelp_node *node = 0; struct grub_fshelp_node *node = 0;
struct grub_sfs_data *data = dir->data; 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; unsigned int next = dir->block;
grub_uint32_t pos; 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); objc_data = grub_malloc (GRUB_DISK_SECTOR_SIZE << data->log_blocksize);
if (!objc_data) if (!objc_data)
goto fail; goto fail;
@ -570,9 +566,10 @@ grub_sfs_iterate_dir (grub_fshelp_node_t dir,
else else
block = grub_be_to_cpu32 (obj->file_dir.file.first_block); 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), 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); grub_free (objc_data);
return 1; return 1;
@ -654,31 +651,37 @@ grub_sfs_read (grub_file_t file, char *buf, grub_size_t len)
} }
static grub_err_t /* Context for grub_sfs_dir. */
grub_sfs_dir (grub_device_t device, const char *path, struct grub_sfs_dir_ctx
int (*hook) (const char *filename,
const struct grub_dirhook_info *info))
{ {
struct grub_sfs_data *data = 0; grub_fs_dir_hook_t hook;
struct grub_fshelp_node *fdiro = 0; void *hook_data;
};
auto int NESTED_FUNC_ATTR iterate (const char *filename, /* Helper for grub_sfs_dir. */
enum grub_fshelp_filetype filetype, static int
grub_fshelp_node_t node); grub_sfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node, void *data)
int NESTED_FUNC_ATTR iterate (const char *filename, {
enum grub_fshelp_filetype filetype, struct grub_sfs_dir_ctx *ctx = data;
grub_fshelp_node_t node)
{
struct grub_dirhook_info info; struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info)); grub_memset (&info, 0, sizeof (info));
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
info.mtime = node->mtime + 8 * 365 * 86400 + 86400 * 2; info.mtime = node->mtime + 8 * 365 * 86400 + 86400 * 2;
info.mtimeset = 1; info.mtimeset = 1;
grub_free (node->cache); grub_free (node->cache);
grub_free (node); grub_free (node);
return hook (filename, &info); return ctx->hook (filename, &info, ctx->hook_data);
} }
static grub_err_t
grub_sfs_dir (grub_device_t device, const char *path,
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;
grub_dl_ref (my_mod); grub_dl_ref (my_mod);
@ -691,7 +694,7 @@ grub_sfs_dir (grub_device_t device, const char *path,
if (grub_errno) if (grub_errno)
goto fail; goto fail;
grub_sfs_iterate_dir (fdiro, iterate); grub_sfs_iterate_dir (fdiro, grub_sfs_dir_iter, &ctx);
fail: fail:
if (data && fdiro != &data->diropen) if (data && fdiro != &data->diropen)

View file

@ -478,10 +478,7 @@ grub_squash_read_symlink (grub_fshelp_node_t node)
static int static int
grub_squash_iterate_dir (grub_fshelp_node_t dir, grub_squash_iterate_dir (grub_fshelp_node_t dir,
int NESTED_FUNC_ATTR grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
(*hook) (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node))
{ {
grub_uint32_t off; grub_uint32_t off;
grub_uint32_t endoff; grub_uint32_t endoff;
@ -514,7 +511,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
return 0; return 0;
grub_memcpy (node, dir, grub_memcpy (node, dir,
sizeof (*node) + dir->stsize * sizeof (dir->stack[0])); sizeof (*node) + dir->stsize * sizeof (dir->stack[0]));
if (hook (".", GRUB_FSHELP_DIR, node)) if (hook (".", GRUB_FSHELP_DIR, node, hook_data))
return 1; return 1;
if (dir->stsize != 1) if (dir->stsize != 1)
@ -536,7 +533,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
if (err) if (err)
return 0; return 0;
if (hook ("..", GRUB_FSHELP_DIR, node)) if (hook ("..", GRUB_FSHELP_DIR, node, hook_data))
return 1; 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_chunk = grub_le_to_cpu32 (dh.ino_chunk);
node->stack[node->stsize].ino_offset = grub_le_to_cpu16 (di.ino_offset); node->stack[node->stsize].ino_offset = grub_le_to_cpu16 (di.ino_offset);
node->stsize++; node->stsize++;
r = hook (buf, filetype, node); r = hook (buf, filetype, node, hook_data);
grub_free (buf); grub_free (buf);
if (r) if (r)
@ -640,28 +637,34 @@ squash_unmount (struct grub_squash_data *data)
} }
static grub_err_t /* Context for grub_squash_dir. */
grub_squash_dir (grub_device_t device, const char *path, struct grub_squash_dir_ctx
int (*hook) (const char *filename,
const struct grub_dirhook_info *info))
{ {
auto int NESTED_FUNC_ATTR iterate (const char *filename, grub_fs_dir_hook_t hook;
enum grub_fshelp_filetype filetype, void *hook_data;
grub_fshelp_node_t node); };
int NESTED_FUNC_ATTR iterate (const char *filename, /* Helper for grub_squash_dir. */
enum grub_fshelp_filetype filetype, static int
grub_fshelp_node_t node) 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; struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info)); grub_memset (&info, 0, sizeof (info));
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
info.mtimeset = 1; info.mtimeset = 1;
info.mtime = grub_le_to_cpu32 (node->ino.mtime); info.mtime = grub_le_to_cpu32 (node->ino.mtime);
grub_free (node); grub_free (node);
return hook (filename, &info); return ctx->hook (filename, &info, ctx->hook_data);
} }
static grub_err_t
grub_squash_dir (grub_device_t device, const char *path,
grub_fs_dir_hook_t hook, void *hook_data)
{
struct grub_squash_dir_ctx ctx = { hook, hook_data };
struct grub_squash_data *data = 0; struct grub_squash_data *data = 0;
struct grub_fshelp_node *fdiro = 0; struct grub_fshelp_node *fdiro = 0;
struct grub_fshelp_node root; 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_fshelp_find_file (path, &root, &fdiro, grub_squash_iterate_dir,
grub_squash_read_symlink, GRUB_FSHELP_DIR); grub_squash_read_symlink, GRUB_FSHELP_DIR);
if (!grub_errno) if (!grub_errno)
grub_squash_iterate_dir (fdiro, iterate); grub_squash_iterate_dir (fdiro, grub_squash_dir_iter, &ctx);
squash_unmount (data); squash_unmount (data);

View file

@ -843,10 +843,7 @@ read_string (const grub_uint8_t *raw, grub_size_t sz, char *outbuf)
static int static int
grub_udf_iterate_dir (grub_fshelp_node_t dir, grub_udf_iterate_dir (grub_fshelp_node_t dir,
int NESTED_FUNC_ATTR grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
(*hook) (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node))
{ {
grub_fshelp_node_t child; grub_fshelp_node_t child;
struct grub_udf_file_ident dirent; 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. */ /* The current directory is not stored. */
grub_memcpy (child, dir, get_fshelp_size (dir->data)); 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; return 1;
while (offset < U64 (dir->block.fe.file_size)) 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) if (dirent.characteristics & GRUB_UDF_FID_CHAR_PARENT)
{ {
/* This is the parent directory. */ /* This is the parent directory. */
if (hook ("..", GRUB_FSHELP_DIR, child)) if (hook ("..", GRUB_FSHELP_DIR, child, hook_data))
return 1; return 1;
} }
else else
@ -911,7 +908,7 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir,
if (!filename) if (!filename)
grub_print_error (); grub_print_error ();
if (filename && hook (filename, type, child)) if (filename && hook (filename, type, child, hook_data))
{ {
grub_free (filename); grub_free (filename);
return 1; return 1;
@ -1012,25 +1009,22 @@ grub_udf_read_symlink (grub_fshelp_node_t node)
return NULL; return NULL;
} }
static grub_err_t /* Context for grub_udf_dir. */
grub_udf_dir (grub_device_t device, const char *path, struct grub_udf_dir_ctx
int (*hook) (const char *filename,
const struct grub_dirhook_info *info))
{ {
struct grub_udf_data *data = 0; grub_fs_dir_hook_t hook;
struct grub_fshelp_node *rootnode = 0; void *hook_data;
struct grub_fshelp_node *foundnode = 0; };
auto int NESTED_FUNC_ATTR iterate (const char *filename, /* Helper for grub_udf_dir. */
enum grub_fshelp_filetype filetype, static int
grub_fshelp_node_t node); grub_udf_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node, void *data)
int NESTED_FUNC_ATTR iterate (const char *filename, {
enum grub_fshelp_filetype filetype, struct grub_udf_dir_ctx *ctx = data;
grub_fshelp_node_t node)
{
struct grub_dirhook_info info; struct grub_dirhook_info info;
const struct grub_udf_timestamp *tstamp = NULL; const struct grub_udf_timestamp *tstamp = NULL;
grub_memset (&info, 0, sizeof (info)); grub_memset (&info, 0, sizeof (info));
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
if (U16 (node->block.fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_FE) if (U16 (node->block.fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_FE)
@ -1061,8 +1055,17 @@ grub_udf_dir (grub_device_t device, const char *path,
info.mtime -= 60 * tz; info.mtime -= 60 * tz;
} }
grub_free (node); grub_free (node);
return hook (filename, &info); return ctx->hook (filename, &info, ctx->hook_data);
} }
static grub_err_t
grub_udf_dir (grub_device_t device, const char *path,
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;
grub_dl_ref (my_mod); grub_dl_ref (my_mod);
@ -1083,7 +1086,7 @@ grub_udf_dir (grub_device_t device, const char *path,
GRUB_FSHELP_DIR)) GRUB_FSHELP_DIR))
goto fail; goto fail;
grub_udf_iterate_dir (foundnode, iterate); grub_udf_iterate_dir (foundnode, grub_udf_dir_iter, &ctx);
if (foundnode != rootnode) if (foundnode != rootnode)
grub_free (foundnode); grub_free (foundnode);

View file

@ -625,8 +625,7 @@ grub_ufs_mount (grub_disk_t disk)
static grub_err_t static grub_err_t
grub_ufs_dir (grub_device_t device, const char *path, grub_ufs_dir (grub_device_t device, const char *path,
int (*hook) (const char *filename, grub_fs_dir_hook_t hook, void *hook_data)
const struct grub_dirhook_info *info))
{ {
struct grub_ufs_data *data; struct grub_ufs_data *data;
unsigned int pos = 0; unsigned int pos = 0;
@ -697,7 +696,7 @@ grub_ufs_dir (grub_device_t device, const char *path,
#endif #endif
info.mtimeset = 1; info.mtimeset = 1;
if (hook (filename, &info)) if (hook (filename, &info, hook_data))
break; break;
} }

View file

@ -443,24 +443,24 @@ grub_xfs_mode_to_filetype (grub_uint16_t mode)
} }
static int /* Context for grub_xfs_iterate_dir. */
grub_xfs_iterate_dir (grub_fshelp_node_t dir, struct grub_xfs_iterate_dir_ctx
int NESTED_FUNC_ATTR
(*hook) (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node))
{ {
struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir; grub_fshelp_iterate_dir_hook_t hook;
auto int NESTED_FUNC_ATTR call_hook (grub_uint64_t ino, const char *filename); void *hook_data;
struct grub_fshelp_node *diro;
};
int NESTED_FUNC_ATTR call_hook (grub_uint64_t ino, const char *filename) /* 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; struct grub_fshelp_node *fdiro;
grub_err_t err; grub_err_t err;
fdiro = grub_malloc (sizeof (struct grub_fshelp_node) fdiro = grub_malloc (sizeof (struct grub_fshelp_node)
- sizeof (struct grub_xfs_inode) - sizeof (struct grub_xfs_inode)
+ (1 << diro->data->sblock.log2_inode)); + (1 << ctx->diro->data->sblock.log2_inode));
if (!fdiro) if (!fdiro)
{ {
grub_print_error (); grub_print_error ();
@ -471,18 +471,28 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
not be determined. */ not be determined. */
fdiro->ino = ino; fdiro->ino = ino;
fdiro->inode_read = 1; fdiro->inode_read = 1;
fdiro->data = diro->data; fdiro->data = ctx->diro->data;
err = grub_xfs_read_inode (diro->data, ino, &fdiro->inode); err = grub_xfs_read_inode (ctx->diro->data, ino, &fdiro->inode);
if (err) if (err)
{ {
grub_print_error (); grub_print_error ();
return 0; return 0;
} }
return hook (filename, return ctx->hook (filename, grub_xfs_mode_to_filetype (fdiro->inode.mode),
grub_xfs_mode_to_filetype (fdiro->inode.mode), fdiro, ctx->hook_data);
fdiro); }
}
static int
grub_xfs_iterate_dir (grub_fshelp_node_t dir,
grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
{
struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir;
struct grub_xfs_iterate_dir_ctx ctx = {
.hook = hook,
.hook_data = hook_data,
.diro = diro
};
switch (diro->inode.format) switch (diro->inode.format)
{ {
@ -508,10 +518,10 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
} }
/* Synthesize the direntries for `.' and `..'. */ /* Synthesize the direntries for `.' and `..'. */
if (call_hook (diro->ino, ".")) if (iterate_dir_call_hook (diro->ino, ".", &ctx))
return 1; return 1;
if (call_hook (parent, "..")) if (iterate_dir_call_hook (parent, "..", &ctx))
return 1; return 1;
for (i = 0; i < diro->inode.data.dir.dirhead.count; i++) 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); grub_memcpy (name, de->name, de->len);
name[de->len] = '\0'; name[de->len] = '\0';
if (call_hook (ino, name)) if (iterate_dir_call_hook (ino, name, &ctx))
return 1; return 1;
de = ((struct grub_xfs_dir_entry *) 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. */ is not used by GRUB. So it can be overwritten. */
filename[direntry->len] = '\0'; filename[direntry->len] = '\0';
if (call_hook (direntry->inode, filename)) if (iterate_dir_call_hook (direntry->inode, filename, &ctx))
{ {
grub_free (dirblock); grub_free (dirblock);
return 1; return 1;
@ -703,23 +713,21 @@ grub_xfs_mount (grub_disk_t disk)
} }
static grub_err_t /* Context for grub_xfs_dir. */
grub_xfs_dir (grub_device_t device, const char *path, struct grub_xfs_dir_ctx
int (*hook) (const char *filename,
const struct grub_dirhook_info *info))
{ {
struct grub_xfs_data *data = 0; grub_fs_dir_hook_t hook;
struct grub_fshelp_node *fdiro = 0; void *hook_data;
};
auto int NESTED_FUNC_ATTR iterate (const char *filename, /* Helper for grub_xfs_dir. */
enum grub_fshelp_filetype filetype, static int
grub_fshelp_node_t node); grub_xfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node, void *data)
int NESTED_FUNC_ATTR iterate (const char *filename, {
enum grub_fshelp_filetype filetype, struct grub_xfs_dir_ctx *ctx = data;
grub_fshelp_node_t node)
{
struct grub_dirhook_info info; struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info)); grub_memset (&info, 0, sizeof (info));
if (node->inode_read) if (node->inode_read)
{ {
@ -728,8 +736,16 @@ grub_xfs_dir (grub_device_t device, const char *path,
} }
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
grub_free (node); grub_free (node);
return hook (filename, &info); return ctx->hook (filename, &info, ctx->hook_data);
} }
static grub_err_t
grub_xfs_dir (grub_device_t device, const char *path,
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;
grub_dl_ref (my_mod); grub_dl_ref (my_mod);
@ -742,7 +758,7 @@ grub_xfs_dir (grub_device_t device, const char *path,
if (grub_errno) if (grub_errno)
goto fail; goto fail;
grub_xfs_iterate_dir (fdiro, iterate); grub_xfs_iterate_dir (fdiro, grub_xfs_dir_iter, &ctx);
fail: fail:
if (fdiro != &data->diropen) if (fdiro != &data->diropen)

View file

@ -253,6 +253,14 @@ struct grub_zfs_data
grub_uint64_t guid; 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_err_t (*grub_zfs_decrypt) (grub_crypto_cipher_handle_t cipher,
grub_uint64_t algo, grub_uint64_t algo,
void *nonce, void *nonce,
@ -1790,8 +1798,9 @@ mzap_lookup (mzap_phys_t * zapobj, grub_zfs_endian_t endian,
static int static int
mzap_iterate (mzap_phys_t * zapobj, grub_zfs_endian_t endian, int objsize, mzap_iterate (mzap_phys_t * zapobj, grub_zfs_endian_t endian, int objsize,
int NESTED_FUNC_ATTR (*hook) (const char *name, int (*hook) (const char *name, grub_uint64_t val,
grub_uint64_t val)) struct grub_zfs_dir_ctx *ctx),
struct grub_zfs_dir_ctx *ctx)
{ {
int i, chunks; int i, chunks;
mzap_ent_phys_t *mzap_ent = zapobj->mz_chunk; 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, mzap_ent[i].mze_name, (long long)mzap_ent[i].mze_value,
(int)mzap_ent[i].mze_cd); (int)mzap_ent[i].mze_cd);
if (hook (mzap_ent[i].mze_name, 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; return 1;
} }
@ -2054,12 +2063,11 @@ fzap_lookup (dnode_end_t * zap_dnode, zap_phys_t * zap,
static int static int
fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap,
grub_size_t name_elem_length, grub_size_t name_elem_length,
int NESTED_FUNC_ATTR (*hook) (const void *name, int (*hook) (const void *name, grub_size_t name_length,
grub_size_t name_length,
const void *val_in, const void *val_in,
grub_size_t nelem, grub_size_t nelem, grub_size_t elemsize,
grub_size_t elemsize), void *data),
struct grub_zfs_data *data) void *hook_data, struct grub_zfs_data *data)
{ {
zap_leaf_phys_t *l; zap_leaf_phys_t *l;
void *l_in; 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, 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); grub_free (l);
return 1; 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"); 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 static int
zap_iterate_u64 (dnode_end_t * zap_dnode, zap_iterate_u64 (dnode_end_t * zap_dnode,
int NESTED_FUNC_ATTR (*hook) (const char *name, int (*hook) (const char *name, grub_uint64_t val,
grub_uint64_t val), struct grub_zfs_dir_ctx *ctx),
struct grub_zfs_data *data) struct grub_zfs_data *data, struct grub_zfs_dir_ctx *ctx)
{ {
grub_uint64_t block_type; grub_uint64_t block_type;
int size; int size;
@ -2234,23 +2266,6 @@ zap_iterate_u64 (dnode_end_t * zap_dnode,
int ret; int ret;
grub_zfs_endian_t endian; 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. */ /* 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; size = grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, zap_dnode->endian) << SPA_MINBLOCKSHIFT;
err = dmu_read (zap_dnode, 0, &zapbuf, &endian, data); 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) if (block_type == ZBT_MICRO)
{ {
grub_dprintf ("zfs", "micro zap\n"); grub_dprintf ("zfs", "micro zap\n");
ret = mzap_iterate (zapbuf, endian, size, hook); ret = mzap_iterate (zapbuf, endian, size, hook, ctx);
grub_free (zapbuf); grub_free (zapbuf);
return ret; return ret;
} }
else if (block_type == ZBT_HEADER) else if (block_type == ZBT_HEADER)
{ {
struct zap_iterate_u64_ctx transform_ctx = {
.hook = hook,
.dir_ctx = ctx
};
grub_dprintf ("zfs", "fat zap\n"); grub_dprintf ("zfs", "fat zap\n");
/* this is a fat zap */ /* 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); grub_free (zapbuf);
return ret; return ret;
} }
@ -2282,12 +2303,11 @@ zap_iterate_u64 (dnode_end_t * zap_dnode,
static int static int
zap_iterate (dnode_end_t * zap_dnode, zap_iterate (dnode_end_t * zap_dnode,
grub_size_t nameelemlen, grub_size_t nameelemlen,
int NESTED_FUNC_ATTR (*hook) (const void *name, int (*hook) (const void *name, grub_size_t namelen,
grub_size_t namelen,
const void *val_in, const void *val_in,
grub_size_t nelem, grub_size_t nelem, grub_size_t elemsize,
grub_size_t elemsize), void *data),
struct grub_zfs_data *data) void *hook_data, struct grub_zfs_data *data)
{ {
grub_uint64_t block_type; grub_uint64_t block_type;
void *zapbuf; void *zapbuf;
@ -2312,7 +2332,8 @@ zap_iterate (dnode_end_t * zap_dnode,
{ {
grub_dprintf ("zfs", "fat zap\n"); grub_dprintf ("zfs", "fat zap\n");
/* this is a fat zap */ /* 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); grub_free (zapbuf);
return ret; return ret;
} }
@ -2826,45 +2847,36 @@ make_mdn (dnode_end_t * mdn, struct grub_zfs_data *data)
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
static grub_err_t /* Context for dnode_get_fullpath. */
dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, struct dnode_get_fullpath_ctx
dnode_end_t * dn, int *isfs,
struct grub_zfs_data *data)
{ {
char *fsname, *snapname; struct subvolume *subvol;
const char *ptr_at, *filename;
grub_uint64_t headobj;
grub_uint64_t keychainobj;
grub_uint64_t salt; grub_uint64_t salt;
grub_err_t err; int keyn;
int keyn = 0; };
auto int NESTED_FUNC_ATTR count_zap_keys (const void *name, /* Helper for dnode_get_fullpath. */
grub_size_t namelen, static int
const void *val_in, count_zap_keys (const void *name __attribute__ ((unused)),
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)), grub_size_t namelen __attribute__ ((unused)),
const void *val_in __attribute__ ((unused)), const void *val_in __attribute__ ((unused)),
grub_size_t nelem __attribute__ ((unused)), grub_size_t nelem __attribute__ ((unused)),
grub_size_t elemsize __attribute__ ((unused))) grub_size_t elemsize __attribute__ ((unused)),
{ void *data)
subvol->nkeys++; {
return 0; 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;
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) if (namelen != 1)
{ {
grub_dprintf ("zfs", "Unexpected key index size %" PRIuGRUB_SIZE "\n", grub_dprintf ("zfs", "Unexpected key index size %" PRIuGRUB_SIZE "\n",
@ -2879,13 +2891,27 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol,
return 0; return 0;
} }
subvol->keyring[keyn].txg = grub_be_to_cpu64 (*(grub_uint64_t *) name); ctx->subvol->keyring[ctx->keyn].txg =
subvol->keyring[keyn].algo = grub_le_to_cpu64 (*(grub_uint64_t *) val_in); grub_be_to_cpu64 (*(grub_uint64_t *) name);
subvol->keyring[keyn].cipher = grub_zfs_load_key (val_in, nelem, salt, ctx->subvol->keyring[ctx->keyn].algo =
subvol->keyring[keyn].algo); grub_le_to_cpu64 (*(grub_uint64_t *) val_in);
keyn++; 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; return 0;
} }
static grub_err_t
dnode_get_fullpath (const char *fullpath, struct subvolume *subvol,
dnode_end_t * dn, int *isfs,
struct grub_zfs_data *data)
{
char *fsname, *snapname;
const char *ptr_at, *filename;
grub_uint64_t headobj;
grub_uint64_t keychainobj;
grub_err_t err;
ptr_at = grub_strchr (fullpath, '@'); ptr_at = grub_strchr (fullpath, '@');
if (! ptr_at) 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); keychainobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&dn->dn))->keychain, dn->endian);
if (grub_zfs_load_key && keychainobj) if (grub_zfs_load_key && keychainobj)
{ {
struct dnode_get_fullpath_ctx ctx = {
.subvol = subvol,
.keyn = 0
};
dnode_end_t keychain_dn, props_dn; dnode_end_t keychain_dn, props_dn;
grub_uint64_t propsobj; grub_uint64_t propsobj;
propsobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&dn->dn))->dd_props_zapobj, dn->endian); 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; 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) if (err == GRUB_ERR_FILE_NOT_FOUND)
{ {
err = 0; err = 0;
grub_errno = 0; grub_errno = 0;
salt = 0; ctx.salt = 0;
} }
if (err) if (err)
{ {
@ -2988,7 +3018,7 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol,
return err; return err;
} }
subvol->nkeys = 0; 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])); subvol->keyring = grub_zalloc (subvol->nkeys * sizeof (subvol->keyring[0]));
if (!subvol->keyring) if (!subvol->keyring)
{ {
@ -2996,7 +3026,7 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol,
grub_free (snapname); grub_free (snapname);
return err; return err;
} }
zap_iterate (&keychain_dn, 8, load_zap_key, data); zap_iterate (&keychain_dn, 8, load_zap_key, &ctx, data);
} }
if (snapname) if (snapname)
@ -3748,26 +3778,17 @@ fill_fs_info (struct grub_dirhook_info *info,
return; return;
} }
static grub_err_t /* Helper for grub_zfs_dir. */
grub_zfs_dir (grub_device_t device, const char *path, static int
int (*hook) (const char *, const struct grub_dirhook_info *)) iterate_zap (const char *name, grub_uint64_t val, struct grub_zfs_dir_ctx *ctx)
{ {
struct grub_zfs_data *data;
grub_err_t err; 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; struct grub_dirhook_info info;
dnode_end_t dn; dnode_end_t dn;
grub_memset (&info, 0, sizeof (info)); grub_memset (&info, 0, sizeof (info));
dnode_get (&(data->subvol.mdn), val, 0, &dn, data); dnode_get (&(ctx->data->subvol.mdn), val, 0, &dn, ctx->data);
if (dn.dn.dn_bonustype == DMU_OT_SA) if (dn.dn.dn_bonustype == DMU_OT_SA)
{ {
@ -3776,13 +3797,13 @@ grub_zfs_dir (grub_device_t device, const char *path,
if (dn.dn.dn_bonuslen != 0) if (dn.dn.dn_bonuslen != 0)
{ {
sahdrp = (sa_hdr_phys_t *) DN_BONUS (&data->dnode.dn); sahdrp = (sa_hdr_phys_t *) DN_BONUS (&ctx->data->dnode.dn);
} }
else if (dn.dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR) else if (dn.dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR)
{ {
blkptr_t *bp = &dn.dn.dn_spill; blkptr_t *bp = &dn.dn.dn_spill;
err = zio_read (bp, dn.endian, &sahdrp, NULL, data); err = zio_read (bp, dn.endian, &sahdrp, NULL, ctx->data);
if (err) if (err)
{ {
grub_print_error (); grub_print_error ();
@ -3799,7 +3820,7 @@ grub_zfs_dir (grub_device_t device, const char *path,
hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp));
info.mtimeset = 1; info.mtimeset = 1;
info.mtime = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian); info.mtime = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian);
info.case_insensitive = data->subvol.case_insensitive; info.case_insensitive = ctx->data->subvol.case_insensitive;
} }
if (dn.dn.dn_bonustype == DMU_OT_ZNODE) if (dn.dn.dn_bonustype == DMU_OT_ZNODE)
@ -3811,45 +3832,68 @@ grub_zfs_dir (grub_device_t device, const char *path,
info.dir = (dn.dn.dn_type == DMU_OT_DIRECTORY_CONTENTS); info.dir = (dn.dn.dn_type == DMU_OT_DIRECTORY_CONTENTS);
grub_dprintf ("zfs", "type=%d, name=%s\n", grub_dprintf ("zfs", "type=%d, name=%s\n",
(int)dn.dn.dn_type, (char *)name); (int)dn.dn.dn_type, (char *)name);
return hook (name, &info); return ctx->hook (name, &info, ctx->hook_data);
} }
int NESTED_FUNC_ATTR iterate_zap_fs (const char *name, grub_uint64_t val) /* 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; struct grub_dirhook_info info;
dnode_end_t mdn; dnode_end_t mdn;
err = dnode_get (&(data->mos), val, 0, &mdn, data); err = dnode_get (&(ctx->data->mos), val, 0, &mdn, ctx->data);
if (err) if (err)
return 0; return 0;
if (mdn.dn.dn_type != DMU_OT_DSL_DIR) if (mdn.dn.dn_type != DMU_OT_DSL_DIR)
return 0; return 0;
fill_fs_info (&info, mdn, data); fill_fs_info (&info, mdn, ctx->data);
return hook (name, &info); return ctx->hook (name, &info, ctx->hook_data);
} }
int NESTED_FUNC_ATTR iterate_zap_snap (const char *name, grub_uint64_t val)
{ /* 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; struct grub_dirhook_info info;
char *name2; char *name2;
int ret; int ret;
dnode_end_t mdn; dnode_end_t mdn;
err = dnode_get (&(data->mos), val, 0, &mdn, data); err = dnode_get (&(ctx->data->mos), val, 0, &mdn, ctx->data);
if (err) if (err)
return 0; return 0;
if (mdn.dn.dn_type != DMU_OT_DSL_DATASET) if (mdn.dn.dn_type != DMU_OT_DSL_DATASET)
return 0; return 0;
fill_fs_info (&info, mdn, data); fill_fs_info (&info, mdn, ctx->data);
name2 = grub_malloc (grub_strlen (name) + 2); name2 = grub_malloc (grub_strlen (name) + 2);
name2[0] = '@'; name2[0] = '@';
grub_memcpy (name2 + 1, name, grub_strlen (name) + 1); grub_memcpy (name2 + 1, name, grub_strlen (name) + 1);
ret = hook (name2, &info); ret = ctx->hook (name2, &info, ctx->hook_data);
grub_free (name2); grub_free (name2);
return ret; return ret;
} }
static grub_err_t
grub_zfs_dir (grub_device_t device, const char *path,
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;
data = zfs_mount (device); data = zfs_mount (device);
if (! data) if (! data)
@ -3860,6 +3904,8 @@ grub_zfs_dir (grub_device_t device, const char *path,
zfs_unmount (data); zfs_unmount (data);
return err; return err;
} }
ctx.data = data;
if (isfs) if (isfs)
{ {
grub_uint64_t childobj, headobj; grub_uint64_t childobj, headobj;
@ -3868,7 +3914,7 @@ grub_zfs_dir (grub_device_t device, const char *path,
struct grub_dirhook_info info; struct grub_dirhook_info info;
fill_fs_info (&info, data->dnode, data); 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); 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); 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; 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); err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, &dn, data);
if (err) if (err)
@ -3899,7 +3945,7 @@ grub_zfs_dir (grub_device_t device, const char *path,
return err; return err;
} }
zap_iterate_u64 (&dn, iterate_zap_snap, data); zap_iterate_u64 (&dn, iterate_zap_snap, data, &ctx);
} }
else else
{ {
@ -3908,7 +3954,7 @@ grub_zfs_dir (grub_device_t device, const char *path,
zfs_unmount (data); zfs_unmount (data);
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); 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); zfs_unmount (data);
return grub_errno; return grub_errno;

View file

@ -105,7 +105,8 @@ grub_mini_print_devices (const char *name, void *data __attribute__ ((unused)))
static int static int
grub_mini_print_files (const char *filename, grub_mini_print_files (const char *filename,
const struct grub_dirhook_info *info) const struct grub_dirhook_info *info,
void *data __attribute__ ((unused)))
{ {
grub_printf ("%s%s ", filename, info->dir ? "/" : ""); grub_printf ("%s%s ", filename, info->dir ? "/" : "");
@ -160,7 +161,7 @@ grub_core_cmd_ls (struct grub_command *cmd __attribute__ ((unused)),
} }
else if (fs) else if (fs)
{ {
(fs->dir) (dev, path, grub_mini_print_files); (fs->dir) (dev, path, grub_mini_print_files, NULL);
grub_xputs ("\n"); grub_xputs ("\n");
grub_refresh (); grub_refresh ();
} }

View file

@ -65,8 +65,7 @@ struct grub_hostfs_data
static grub_err_t static grub_err_t
grub_hostfs_dir (grub_device_t device, const char *path, grub_hostfs_dir (grub_device_t device, const char *path,
int (*hook) (const char *filename, grub_fs_dir_hook_t hook, void *hook_data)
const struct grub_dirhook_info *info))
{ {
DIR *dir; DIR *dir;
@ -91,7 +90,7 @@ grub_hostfs_dir (grub_device_t device, const char *path,
break; break;
info.dir = !! is_dir (path, de->d_name); info.dir = !! is_dir (path, de->d_name);
hook (de->d_name, &info); hook (de->d_name, &info, hook_data);
} }

View file

@ -35,10 +35,11 @@ grub_fs_autoload_hook_t grub_fs_autoload_hook = 0;
/* Helper for grub_fs_probe. */ /* Helper for grub_fs_probe. */
static int static int
probe_dummy_iter (const char *filename __attribute__ ((unused)), probe_dummy_iter (const char *filename __attribute__ ((unused)),
const struct grub_dirhook_info *info __attribute__ ((unused))) const struct grub_dirhook_info *info __attribute__ ((unused)),
{ void *data __attribute__ ((unused)))
{
return 1; return 1;
} }
grub_fs_t grub_fs_t
grub_fs_probe (grub_device_t device) grub_fs_probe (grub_device_t device)
@ -69,7 +70,7 @@ grub_fs_probe (grub_device_t device)
} }
else else
#endif #endif
(p->dir) (device, "/", probe_dummy_iter); (p->dir) (device, "/", probe_dummy_iter, NULL);
if (grub_errno == GRUB_ERR_NONE) if (grub_errno == GRUB_ERR_NONE)
return p; return p;
@ -93,7 +94,7 @@ grub_fs_probe (grub_device_t device)
{ {
p = grub_fs_list; p = grub_fs_list;
(p->dir) (device, "/", probe_dummy_iter); (p->dir) (device, "/", probe_dummy_iter, NULL);
if (grub_errno == GRUB_ERR_NONE) if (grub_errno == GRUB_ERR_NONE)
{ {
count--; count--;

View file

@ -1017,21 +1017,23 @@ grub_xnu_check_os_bundle_required (char *plistname,
return ret; return ret;
} }
/* Load all loadable kexts placed under DIRNAME and matching OSBUNDLEREQUIRED */ /* Context for grub_xnu_scan_dir_for_kexts. */
grub_err_t struct grub_xnu_scan_dir_for_kexts_ctx
grub_xnu_scan_dir_for_kexts (char *dirname, const char *osbundlerequired,
int maxrecursion)
{ {
grub_device_t dev; char *dirname;
char *device_name; const char *osbundlerequired;
grub_fs_t fs; int maxrecursion;
const char *path; };
auto int load_hook (const char *filename, /* Helper for grub_xnu_scan_dir_for_kexts. */
const struct grub_dirhook_info *info); static int
int load_hook (const char *filename, const struct grub_dirhook_info *info) grub_xnu_scan_dir_for_kexts_load (const char *filename,
{ const struct grub_dirhook_info *info,
void *data)
{
struct grub_xnu_scan_dir_for_kexts_ctx *ctx = data;
char *newdirname; char *newdirname;
if (! info->dir) if (! info->dir)
return 0; return 0;
if (filename[0] == '.') if (filename[0] == '.')
@ -1042,23 +1044,38 @@ grub_xnu_scan_dir_for_kexts (char *dirname, const char *osbundlerequired,
return 0; return 0;
newdirname newdirname
= grub_malloc (grub_strlen (dirname) + grub_strlen (filename) + 2); = grub_malloc (grub_strlen (ctx->dirname) + grub_strlen (filename) + 2);
/* It's a .kext. Try to load it. */ /* It's a .kext. Try to load it. */
if (newdirname) if (newdirname)
{ {
grub_strcpy (newdirname, dirname); grub_strcpy (newdirname, ctx->dirname);
newdirname[grub_strlen (newdirname) + 1] = 0; newdirname[grub_strlen (newdirname) + 1] = 0;
newdirname[grub_strlen (newdirname)] = '/'; newdirname[grub_strlen (newdirname)] = '/';
grub_strcpy (newdirname + grub_strlen (newdirname), filename); grub_strcpy (newdirname + grub_strlen (newdirname), filename);
grub_xnu_load_kext_from_dir (newdirname, osbundlerequired, grub_xnu_load_kext_from_dir (newdirname, ctx->osbundlerequired,
maxrecursion); ctx->maxrecursion);
if (grub_errno == GRUB_ERR_BAD_OS) if (grub_errno == GRUB_ERR_BAD_OS)
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
grub_free (newdirname); grub_free (newdirname);
} }
return 0; return 0;
} }
/* Load all loadable kexts placed under DIRNAME and matching OSBUNDLEREQUIRED */
grub_err_t
grub_xnu_scan_dir_for_kexts (char *dirname, const char *osbundlerequired,
int maxrecursion)
{
struct grub_xnu_scan_dir_for_kexts_ctx ctx = {
.dirname = dirname,
.osbundlerequired = osbundlerequired,
.maxrecursion = maxrecursion
};
grub_device_t dev;
char *device_name;
grub_fs_t fs;
const char *path;
if (! grub_xnu_heap_size) if (! grub_xnu_heap_size)
return grub_error (GRUB_ERR_BAD_OS, N_("you need to load the kernel first")); return grub_error (GRUB_ERR_BAD_OS, N_("you need to load the kernel first"));
@ -1075,7 +1092,7 @@ grub_xnu_scan_dir_for_kexts (char *dirname, const char *osbundlerequired,
path++; path++;
if (fs) if (fs)
(fs->dir) (dev, path, load_hook); (fs->dir) (dev, path, grub_xnu_scan_dir_for_kexts_load, &ctx);
grub_device_close (dev); grub_device_close (dev);
} }
grub_free (device_name); grub_free (device_name);
@ -1083,60 +1100,78 @@ grub_xnu_scan_dir_for_kexts (char *dirname, const char *osbundlerequired,
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
/* Context for grub_xnu_load_kext_from_dir. */
struct grub_xnu_load_kext_from_dir_ctx
{
char *dirname;
const char *osbundlerequired;
int maxrecursion;
char *plistname;
char *newdirname;
int usemacos;
};
/* Helper for grub_xnu_load_kext_from_dir. */
static int
grub_xnu_load_kext_from_dir_load (const char *filename,
const struct grub_dirhook_info *info,
void *data)
{
struct grub_xnu_load_kext_from_dir_ctx *ctx = data;
if (grub_strlen (filename) > 15)
return 0;
grub_strcpy (ctx->newdirname + grub_strlen (ctx->dirname) + 1, filename);
/* If the kext contains directory "Contents" all real stuff is in
this directory. */
if (info->dir && grub_strcasecmp (filename, "Contents") == 0)
grub_xnu_load_kext_from_dir (ctx->newdirname, ctx->osbundlerequired,
ctx->maxrecursion - 1);
/* Directory "Plugins" contains nested kexts. */
if (info->dir && grub_strcasecmp (filename, "Plugins") == 0)
grub_xnu_scan_dir_for_kexts (ctx->newdirname, ctx->osbundlerequired,
ctx->maxrecursion - 1);
/* Directory "MacOS" contains executable, otherwise executable is
on the top. */
if (info->dir && grub_strcasecmp (filename, "MacOS") == 0)
ctx->usemacos = 1;
/* Info.plist is the file which governs our future actions. */
if (! info->dir && grub_strcasecmp (filename, "Info.plist") == 0
&& ! ctx->plistname)
ctx->plistname = grub_strdup (ctx->newdirname);
return 0;
}
/* Load extension DIRNAME. (extensions are directories in xnu) */ /* Load extension DIRNAME. (extensions are directories in xnu) */
grub_err_t grub_err_t
grub_xnu_load_kext_from_dir (char *dirname, const char *osbundlerequired, grub_xnu_load_kext_from_dir (char *dirname, const char *osbundlerequired,
int maxrecursion) int maxrecursion)
{ {
struct grub_xnu_load_kext_from_dir_ctx ctx = {
.dirname = dirname,
.osbundlerequired = osbundlerequired,
.maxrecursion = maxrecursion,
.plistname = 0,
.usemacos = 0
};
grub_device_t dev; grub_device_t dev;
char *plistname = 0;
char *newdirname;
char *newpath; char *newpath;
char *device_name; char *device_name;
grub_fs_t fs; grub_fs_t fs;
const char *path; const char *path;
char *binsuffix; char *binsuffix;
int usemacos = 0;
grub_file_t binfile; grub_file_t binfile;
auto int load_hook (const char *filename, ctx.newdirname = grub_malloc (grub_strlen (dirname) + 20);
const struct grub_dirhook_info *info); if (! ctx.newdirname)
int load_hook (const char *filename, const struct grub_dirhook_info *info)
{
if (grub_strlen (filename) > 15)
return 0;
grub_strcpy (newdirname + grub_strlen (dirname) + 1, filename);
/* If the kext contains directory "Contents" all real stuff is in
this directory. */
if (info->dir && grub_strcasecmp (filename, "Contents") == 0)
grub_xnu_load_kext_from_dir (newdirname, osbundlerequired,
maxrecursion - 1);
/* Directory "Plugins" contains nested kexts. */
if (info->dir && grub_strcasecmp (filename, "Plugins") == 0)
grub_xnu_scan_dir_for_kexts (newdirname, osbundlerequired,
maxrecursion - 1);
/* Directory "MacOS" contains executable, otherwise executable is
on the top. */
if (info->dir && grub_strcasecmp (filename, "MacOS") == 0)
usemacos = 1;
/* Info.plist is the file which governs our future actions. */
if (! info->dir && grub_strcasecmp (filename, "Info.plist") == 0
&& ! plistname)
plistname = grub_strdup (newdirname);
return 0;
}
newdirname = grub_malloc (grub_strlen (dirname) + 20);
if (! newdirname)
return grub_errno; return grub_errno;
grub_strcpy (newdirname, dirname); grub_strcpy (ctx.newdirname, dirname);
newdirname[grub_strlen (dirname)] = '/'; ctx.newdirname[grub_strlen (dirname)] = '/';
newdirname[grub_strlen (dirname) + 1] = 0; ctx.newdirname[grub_strlen (dirname) + 1] = 0;
device_name = grub_file_get_device_name (dirname); device_name = grub_file_get_device_name (dirname);
dev = grub_device_open (device_name); dev = grub_device_open (device_name);
if (dev) if (dev)
@ -1148,18 +1183,18 @@ grub_xnu_load_kext_from_dir (char *dirname, const char *osbundlerequired,
else else
path++; path++;
newpath = grub_strchr (newdirname, ')'); newpath = grub_strchr (ctx.newdirname, ')');
if (! newpath) if (! newpath)
newpath = newdirname; newpath = ctx.newdirname;
else else
newpath++; newpath++;
/* Look at the directory. */ /* Look at the directory. */
if (fs) if (fs)
(fs->dir) (dev, path, load_hook); (fs->dir) (dev, path, grub_xnu_load_kext_from_dir_load, &ctx);
if (plistname && grub_xnu_check_os_bundle_required if (ctx.plistname && grub_xnu_check_os_bundle_required
(plistname, osbundlerequired, &binsuffix)) (ctx.plistname, osbundlerequired, &binsuffix))
{ {
if (binsuffix) if (binsuffix)
{ {
@ -1168,29 +1203,29 @@ grub_xnu_load_kext_from_dir (char *dirname, const char *osbundlerequired,
+ grub_strlen (binsuffix) + grub_strlen (binsuffix)
+ sizeof ("/MacOS/")); + sizeof ("/MacOS/"));
grub_strcpy (binname, dirname); grub_strcpy (binname, dirname);
if (usemacos) if (ctx.usemacos)
grub_strcpy (binname + grub_strlen (binname), "/MacOS/"); grub_strcpy (binname + grub_strlen (binname), "/MacOS/");
else else
grub_strcpy (binname + grub_strlen (binname), "/"); grub_strcpy (binname + grub_strlen (binname), "/");
grub_strcpy (binname + grub_strlen (binname), binsuffix); grub_strcpy (binname + grub_strlen (binname), binsuffix);
grub_dprintf ("xnu", "%s:%s\n", plistname, binname); grub_dprintf ("xnu", "%s:%s\n", ctx.plistname, binname);
binfile = grub_file_open (binname); binfile = grub_file_open (binname);
if (! binfile) if (! binfile)
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
/* Load the extension. */ /* Load the extension. */
grub_xnu_load_driver (plistname, binfile, grub_xnu_load_driver (ctx.plistname, binfile,
binname); binname);
grub_free (binname); grub_free (binname);
grub_free (binsuffix); grub_free (binsuffix);
} }
else else
{ {
grub_dprintf ("xnu", "%s:0\n", plistname); grub_dprintf ("xnu", "%s:0\n", ctx.plistname);
grub_xnu_load_driver (plistname, 0, 0); grub_xnu_load_driver (ctx.plistname, 0, 0);
} }
} }
grub_free (plistname); grub_free (ctx.plistname);
grub_device_close (dev); grub_device_close (dev);
} }
grub_free (device_name); grub_free (device_name);

View file

@ -1253,8 +1253,8 @@ grub_net_open_real (const char *name)
static grub_err_t static grub_err_t
grub_net_fs_dir (grub_device_t device, const char *path __attribute__ ((unused)), grub_net_fs_dir (grub_device_t device, const char *path __attribute__ ((unused)),
int (*hook) (const char *filename, grub_fs_dir_hook_t hook __attribute__ ((unused)),
const struct grub_dirhook_info *info) __attribute__ ((unused))) void *hook_data __attribute__ ((unused)))
{ {
if (!device->net) if (!device->net)
return grub_error (GRUB_ERR_BUG, "invalid net device"); return grub_error (GRUB_ERR_BUG, "invalid net device");

View file

@ -123,7 +123,8 @@ iterate_partition (grub_disk_t disk, const grub_partition_t p,
} }
static int static int
iterate_dir (const char *filename, const struct grub_dirhook_info *info) iterate_dir (const char *filename, const struct grub_dirhook_info *info,
void *data __attribute__ ((unused)))
{ {
if (! info->dir) if (! info->dir)
{ {
@ -295,7 +296,7 @@ complete_file (void)
dirfile[1] = '\0'; dirfile[1] = '\0';
/* Iterate the directory. */ /* Iterate the directory. */
(fs->dir) (dev, dir, iterate_dir); (fs->dir) (dev, dir, iterate_dir, NULL);
grub_free (dir); grub_free (dir);

View file

@ -41,6 +41,10 @@ struct grub_dirhook_info
grub_int32_t mtime; grub_int32_t mtime;
}; };
typedef int (*grub_fs_dir_hook_t) (const char *filename,
const struct grub_dirhook_info *info,
void *data);
/* Filesystem descriptor. */ /* Filesystem descriptor. */
struct grub_fs struct grub_fs
{ {
@ -53,8 +57,7 @@ struct grub_fs
/* Call HOOK with each file under DIR. */ /* Call HOOK with each file under DIR. */
grub_err_t (*dir) (grub_device_t device, const char *path, grub_err_t (*dir) (grub_device_t device, const char *path,
int (*hook) (const char *filename, grub_fs_dir_hook_t hook, void *hook_data);
const struct grub_dirhook_info *info));
/* Open a file named NAME and initialize FILE. */ /* Open a file named NAME and initialize FILE. */
grub_err_t (*open) (struct grub_file *file, const char *name); grub_err_t (*open) (struct grub_file *file, const char *name);

View file

@ -38,24 +38,25 @@ enum grub_fshelp_filetype
GRUB_FSHELP_SYMLINK GRUB_FSHELP_SYMLINK
}; };
typedef int (*grub_fshelp_iterate_dir_hook_t) (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node,
void *data);
/* Lookup the node PATH. The node ROOTNODE describes the root of the /* Lookup the node PATH. The node ROOTNODE describes the root of the
directory tree. The node found is returned in FOUNDNODE, which is 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 either a ROOTNODE or a new malloc'ed node. ITERATE_DIR is used to
iterate over all directory entries in the current node. iterate over all directory entries in the current node.
READ_SYMLINK is used to read the symlink if a node is a symlink. 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 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 error is generated if the node is not of the expected type. */
sure you use the NESTED_FUNC_ATTR macro for HOOK, this is required
because GCC has a nasty bug when using regparm=3. */
grub_err_t grub_err_t
EXPORT_FUNC(grub_fshelp_find_file) (const char *path, EXPORT_FUNC(grub_fshelp_find_file) (const char *path,
grub_fshelp_node_t rootnode, grub_fshelp_node_t rootnode,
grub_fshelp_node_t *foundnode, grub_fshelp_node_t *foundnode,
int (*iterate_dir) (grub_fshelp_node_t dir, int (*iterate_dir) (grub_fshelp_node_t dir,
int NESTED_FUNC_ATTR grub_fshelp_iterate_dir_hook_t hook,
(*hook) (const char *filename, void *hook_data),
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node)),
char *(*read_symlink) (grub_fshelp_node_t node), char *(*read_symlink) (grub_fshelp_node_t node),
enum grub_fshelp_filetype expect); enum grub_fshelp_filetype expect);

View file

@ -116,29 +116,37 @@ translate_error (void)
return ret; return ret;
} }
static int /* Context for fuse_getattr. */
fuse_getattr (const char *path, struct stat *st) struct fuse_getattr_ctx
{ {
char *filename, *pathname, *path2; char *filename;
const char *pathname_t;
struct grub_dirhook_info file_info; struct grub_dirhook_info file_info;
int file_exists = 0; int file_exists;
};
/* A hook for iterating directories. */ /* A hook for iterating directories. */
auto int find_file (const char *cur_filename, static int
const struct grub_dirhook_info *info); fuse_getattr_find_file (const char *cur_filename,
int find_file (const char *cur_filename, const struct grub_dirhook_info *info, void *data)
const struct grub_dirhook_info *info) {
struct fuse_getattr_ctx *ctx = data;
if ((info->case_insensitive ? grub_strcasecmp (cur_filename, ctx->filename)
: grub_strcmp (cur_filename, ctx->filename)) == 0)
{ {
if ((info->case_insensitive ? grub_strcasecmp (cur_filename, filename) ctx->file_info = *info;
: grub_strcmp (cur_filename, filename)) == 0) ctx->file_exists = 1;
{
file_info = *info;
file_exists = 1;
return 1; return 1;
} }
return 0; return 0;
} }
static int
fuse_getattr (const char *path, struct stat *st)
{
struct fuse_getattr_ctx ctx;
char *pathname, *path2;
const char *pathname_t;
if (path[0] == '/' && path[1] == 0) if (path[0] == '/' && path[1] == 0)
{ {
@ -155,7 +163,7 @@ fuse_getattr (const char *path, struct stat *st)
return 0; return 0;
} }
file_exists = 0; ctx.file_exists = 0;
pathname_t = grub_strchr (path, ')'); pathname_t = grub_strchr (path, ')');
if (! pathname_t) if (! pathname_t)
@ -169,35 +177,35 @@ fuse_getattr (const char *path, struct stat *st)
pathname[grub_strlen (pathname) - 1] = 0; pathname[grub_strlen (pathname) - 1] = 0;
/* Split into path and filename. */ /* Split into path and filename. */
filename = grub_strrchr (pathname, '/'); ctx.filename = grub_strrchr (pathname, '/');
if (! filename) if (! ctx.filename)
{ {
path2 = grub_strdup ("/"); path2 = grub_strdup ("/");
filename = pathname; ctx.filename = pathname;
} }
else else
{ {
filename++; ctx.filename++;
path2 = grub_strdup (pathname); path2 = grub_strdup (pathname);
path2[filename - pathname] = 0; path2[ctx.filename - pathname] = 0;
} }
/* It's the whole device. */ /* It's the whole device. */
(fs->dir) (dev, path2, find_file); (fs->dir) (dev, path2, fuse_getattr_find_file, &ctx);
grub_free (path2); grub_free (path2);
if (!file_exists) if (!ctx.file_exists)
{ {
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
return -ENOENT; return -ENOENT;
} }
st->st_dev = 0; st->st_dev = 0;
st->st_ino = 0; st->st_ino = 0;
st->st_mode = file_info.dir ? (0555 | S_IFDIR) : (0444 | S_IFREG); st->st_mode = ctx.file_info.dir ? (0555 | S_IFDIR) : (0444 | S_IFREG);
st->st_uid = 0; st->st_uid = 0;
st->st_gid = 0; st->st_gid = 0;
st->st_rdev = 0; st->st_rdev = 0;
if (!file_info.dir) if (!ctx.file_info.dir)
{ {
grub_file_t file; grub_file_t file;
file = grub_file_open (path); file = grub_file_open (path);
@ -210,8 +218,8 @@ fuse_getattr (const char *path, struct stat *st)
st->st_size = 0; st->st_size = 0;
st->st_blksize = 512; st->st_blksize = 512;
st->st_blocks = (st->st_size + 511) >> 9; st->st_blocks = (st->st_size + 511) >> 9;
st->st_atime = st->st_mtime = st->st_ctime = file_info.mtimeset st->st_atime = st->st_mtime = st->st_ctime = ctx.file_info.mtimeset
? file_info.mtime : 0; ? ctx.file_info.mtime : 0;
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
return 0; return 0;
} }
@ -271,24 +279,29 @@ fuse_release (const char *path, struct fuse_file_info *fi)
return 0; return 0;
} }
static int /* Context for fuse_readdir. */
fuse_readdir (const char *path, void *buf, struct fuse_readdir_ctx
fuse_fill_dir_t fill, off_t off, struct fuse_file_info *fi)
{ {
char *pathname; const char *path;
void *buf;
fuse_fill_dir_t fill;
};
auto int call_fill (const char *filename, /* Helper for fuse_readdir. */
const struct grub_dirhook_info *info); static int
int call_fill (const char *filename, const struct grub_dirhook_info *info) fuse_readdir_call_fill (const char *filename,
{ const struct grub_dirhook_info *info, void *data)
{
struct fuse_readdir_ctx *ctx = data;
struct stat st; struct stat st;
grub_memset (&st, 0, sizeof (st)); grub_memset (&st, 0, sizeof (st));
st.st_mode = info->dir ? (0555 | S_IFDIR) : (0444 | S_IFREG); st.st_mode = info->dir ? (0555 | S_IFDIR) : (0444 | S_IFREG);
if (!info->dir) if (!info->dir)
{ {
grub_file_t file; grub_file_t file;
char *tmp; char *tmp;
tmp = xasprintf ("%s/%s", path, filename); tmp = xasprintf ("%s/%s", ctx->path, filename);
file = grub_file_open (tmp); file = grub_file_open (tmp);
free (tmp); free (tmp);
if (! file) if (! file)
@ -300,9 +313,20 @@ fuse_readdir (const char *path, void *buf,
st.st_blocks = (st.st_size + 511) >> 9; st.st_blocks = (st.st_size + 511) >> 9;
st.st_atime = st.st_mtime = st.st_ctime st.st_atime = st.st_mtime = st.st_ctime
= info->mtimeset ? info->mtime : 0; = info->mtimeset ? info->mtime : 0;
fill (buf, filename, &st, 0); ctx->fill (ctx->buf, filename, &st, 0);
return 0; return 0;
} }
static int
fuse_readdir (const char *path, void *buf,
fuse_fill_dir_t fill, off_t off, struct fuse_file_info *fi)
{
struct fuse_readdir_ctx ctx = {
.path = path,
.buf = buf,
.fill = fill
};
char *pathname;
pathname = xstrdup (path); pathname = xstrdup (path);
@ -311,7 +335,7 @@ fuse_readdir (const char *path, void *buf,
&& pathname[grub_strlen (pathname) - 1] == '/') && pathname[grub_strlen (pathname) - 1] == '/')
pathname[grub_strlen (pathname) - 1] = 0; pathname[grub_strlen (pathname) - 1] = 0;
(fs->dir) (dev, pathname, call_fill); (fs->dir) (dev, pathname, fuse_readdir_call_fill, &ctx);
free (pathname); free (pathname);
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
return 0; return 0;