4778 lines
140 KiB
Diff
4778 lines
140 KiB
Diff
|
From 2bef9aff563a9d988b8203e53d715890c7ca9095 Mon Sep 17 00:00:00 2001
|
|||
|
From: Colin Watson <cjwatson@ubuntu.com>
|
|||
|
Date: Mon, 21 Jan 2013 01:33:46 +0000
|
|||
|
Subject: [PATCH 125/364] 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.
|
|||
|
---
|
|||
|
ChangeLog | 9 +
|
|||
|
grub-core/commands/ls.c | 204 +++++++++++----------
|
|||
|
grub-core/commands/test.c | 305 ++++++++++++++++---------------
|
|||
|
grub-core/commands/wildcard.c | 158 +++++++++-------
|
|||
|
grub-core/fs/affs.c | 201 ++++++++++----------
|
|||
|
grub-core/fs/bfs.c | 95 ++++++----
|
|||
|
grub-core/fs/btrfs.c | 5 +-
|
|||
|
grub-core/fs/cpio.c | 5 +-
|
|||
|
grub-core/fs/ext2.c | 91 ++++-----
|
|||
|
grub-core/fs/fat.c | 16 +-
|
|||
|
grub-core/fs/fshelp.c | 307 ++++++++++++++++---------------
|
|||
|
grub-core/fs/hfs.c | 9 +-
|
|||
|
grub-core/fs/hfsplus.c | 60 +++---
|
|||
|
grub-core/fs/iso9660.c | 54 +++---
|
|||
|
grub-core/fs/jfs.c | 5 +-
|
|||
|
grub-core/fs/minix.c | 5 +-
|
|||
|
grub-core/fs/nilfs2.c | 90 ++++-----
|
|||
|
grub-core/fs/ntfs.c | 67 +++----
|
|||
|
grub-core/fs/reiserfs.c | 54 +++---
|
|||
|
grub-core/fs/romfs.c | 51 +++---
|
|||
|
grub-core/fs/sfs.c | 137 +++++++-------
|
|||
|
grub-core/fs/squash4.c | 57 +++---
|
|||
|
grub-core/fs/udf.c | 109 +++++------
|
|||
|
grub-core/fs/ufs.c | 5 +-
|
|||
|
grub-core/fs/xfs.c | 140 +++++++-------
|
|||
|
grub-core/fs/zfs/zfs.c | 416 +++++++++++++++++++++++-------------------
|
|||
|
grub-core/kern/corecmd.c | 5 +-
|
|||
|
grub-core/kern/emu/hostfs.c | 5 +-
|
|||
|
grub-core/kern/fs.c | 13 +-
|
|||
|
grub-core/loader/xnu.c | 205 ++++++++++++---------
|
|||
|
grub-core/net/net.c | 4 +-
|
|||
|
grub-core/normal/completion.c | 5 +-
|
|||
|
include/grub/fs.h | 7 +-
|
|||
|
include/grub/fshelp.h | 15 +-
|
|||
|
util/grub-mount.c | 142 ++++++++------
|
|||
|
35 files changed, 1664 insertions(+), 1392 deletions(-)
|
|||
|
|
|||
|
diff --git a/ChangeLog b/ChangeLog
|
|||
|
index afc2d38..c975de1 100644
|
|||
|
--- a/ChangeLog
|
|||
|
+++ b/ChangeLog
|
|||
|
@@ -1,5 +1,14 @@
|
|||
|
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>
|
|||
|
+
|
|||
|
* docs/grub.texi (Multi-boot manual config): Fix typo for
|
|||
|
"recommended".
|
|||
|
|
|||
|
diff --git a/grub-core/commands/ls.c b/grub-core/commands/ls.c
|
|||
|
index 7929747..0b86619 100644
|
|||
|
--- a/grub-core/commands/ls.c
|
|||
|
+++ b/grub-core/commands/ls.c
|
|||
|
@@ -85,114 +85,126 @@ grub_ls_list_devices (int longlist)
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
-static grub_err_t
|
|||
|
-grub_ls_list_files (char *dirname, int longlist, int all, int human)
|
|||
|
+/* Context for grub_ls_list_files. */
|
|||
|
+struct grub_ls_list_files_ctx
|
|||
|
{
|
|||
|
- char *device_name;
|
|||
|
- grub_fs_t fs;
|
|||
|
- const char *path;
|
|||
|
- grub_device_t dev;
|
|||
|
+ char *dirname;
|
|||
|
+ int all;
|
|||
|
+ int human;
|
|||
|
+};
|
|||
|
+
|
|||
|
+/* Helper for grub_ls_list_files. */
|
|||
|
+static int
|
|||
|
+print_files (const char *filename, const struct grub_dirhook_info *info,
|
|||
|
+ void *data)
|
|||
|
+{
|
|||
|
+ struct grub_ls_list_files_ctx *ctx = data;
|
|||
|
|
|||
|
- auto int print_files (const char *filename,
|
|||
|
- const struct grub_dirhook_info *info);
|
|||
|
- auto int print_files_long (const char *filename,
|
|||
|
- const struct grub_dirhook_info *info);
|
|||
|
+ if (ctx->all || filename[0] != '.')
|
|||
|
+ grub_printf ("%s%s ", filename, info->dir ? "/" : "");
|
|||
|
|
|||
|
- int print_files (const char *filename, const struct grub_dirhook_info *info)
|
|||
|
- {
|
|||
|
- if (all || filename[0] != '.')
|
|||
|
- grub_printf ("%s%s ", filename, info->dir ? "/" : "");
|
|||
|
+ return 0;
|
|||
|
+}
|
|||
|
|
|||
|
- return 0;
|
|||
|
- }
|
|||
|
+/* Helper for grub_ls_list_files. */
|
|||
|
+static int
|
|||
|
+print_files_long (const char *filename, const struct grub_dirhook_info *info,
|
|||
|
+ void *data)
|
|||
|
+{
|
|||
|
+ struct grub_ls_list_files_ctx *ctx = data;
|
|||
|
+
|
|||
|
+ if ((! ctx->all) && (filename[0] == '.'))
|
|||
|
+ return 0;
|
|||
|
|
|||
|
- int print_files_long (const char *filename,
|
|||
|
- const struct grub_dirhook_info *info)
|
|||
|
+ if (! info->dir)
|
|||
|
{
|
|||
|
- if ((! all) && (filename[0] == '.'))
|
|||
|
- return 0;
|
|||
|
+ grub_file_t file;
|
|||
|
+ char *pathname;
|
|||
|
|
|||
|
- if (! info->dir)
|
|||
|
- {
|
|||
|
- grub_file_t file;
|
|||
|
- char *pathname;
|
|||
|
+ if (ctx->dirname[grub_strlen (ctx->dirname) - 1] == '/')
|
|||
|
+ pathname = grub_xasprintf ("%s%s", ctx->dirname, filename);
|
|||
|
+ else
|
|||
|
+ pathname = grub_xasprintf ("%s/%s", ctx->dirname, filename);
|
|||
|
|
|||
|
- if (dirname[grub_strlen (dirname) - 1] == '/')
|
|||
|
- pathname = grub_xasprintf ("%s%s", dirname, filename);
|
|||
|
- else
|
|||
|
- pathname = grub_xasprintf ("%s/%s", dirname, filename);
|
|||
|
+ if (!pathname)
|
|||
|
+ return 1;
|
|||
|
|
|||
|
- if (!pathname)
|
|||
|
- return 1;
|
|||
|
+ /* XXX: For ext2fs symlinks are detected as files while they
|
|||
|
+ should be reported as directories. */
|
|||
|
+ grub_file_filter_disable_compression ();
|
|||
|
+ file = grub_file_open (pathname);
|
|||
|
+ if (! file)
|
|||
|
+ {
|
|||
|
+ grub_errno = 0;
|
|||
|
+ grub_free (pathname);
|
|||
|
+ return 0;
|
|||
|
+ }
|
|||
|
|
|||
|
- /* XXX: For ext2fs symlinks are detected as files while they
|
|||
|
- should be reported as directories. */
|
|||
|
- grub_file_filter_disable_compression ();
|
|||
|
- file = grub_file_open (pathname);
|
|||
|
- if (! file)
|
|||
|
+ if (! ctx->human)
|
|||
|
+ grub_printf ("%-12llu", (unsigned long long) file->size);
|
|||
|
+ else
|
|||
|
+ {
|
|||
|
+ grub_uint64_t fsize = file->size * 100ULL;
|
|||
|
+ grub_uint64_t fsz = file->size;
|
|||
|
+ int units = 0;
|
|||
|
+ char buf[20];
|
|||
|
+
|
|||
|
+ while (fsz / 1024)
|
|||
|
{
|
|||
|
- grub_errno = 0;
|
|||
|
- grub_free (pathname);
|
|||
|
- return 0;
|
|||
|
+ fsize = (fsize + 512) / 1024;
|
|||
|
+ fsz /= 1024;
|
|||
|
+ units++;
|
|||
|
}
|
|||
|
|
|||
|
- if (! human)
|
|||
|
- grub_printf ("%-12llu", (unsigned long long) file->size);
|
|||
|
- else
|
|||
|
+ if (units)
|
|||
|
{
|
|||
|
- grub_uint64_t fsize = file->size * 100ULL;
|
|||
|
- grub_uint64_t fsz = file->size;
|
|||
|
- int units = 0;
|
|||
|
- char buf[20];
|
|||
|
-
|
|||
|
- while (fsz / 1024)
|
|||
|
- {
|
|||
|
- fsize = (fsize + 512) / 1024;
|
|||
|
- fsz /= 1024;
|
|||
|
- units++;
|
|||
|
- }
|
|||
|
-
|
|||
|
- if (units)
|
|||
|
- {
|
|||
|
- grub_uint64_t whole, fraction;
|
|||
|
-
|
|||
|
- whole = grub_divmod64 (fsize, 100, &fraction);
|
|||
|
- grub_snprintf (buf, sizeof (buf),
|
|||
|
- "%" PRIuGRUB_UINT64_T
|
|||
|
- ".%02" PRIuGRUB_UINT64_T "%c", whole, fraction,
|
|||
|
- grub_human_sizes[units]);
|
|||
|
- grub_printf ("%-12s", buf);
|
|||
|
- }
|
|||
|
- else
|
|||
|
- grub_printf ("%-12llu", (unsigned long long) file->size);
|
|||
|
-
|
|||
|
+ grub_uint64_t whole, fraction;
|
|||
|
+
|
|||
|
+ whole = grub_divmod64 (fsize, 100, &fraction);
|
|||
|
+ grub_snprintf (buf, sizeof (buf),
|
|||
|
+ "%" PRIuGRUB_UINT64_T
|
|||
|
+ ".%02" PRIuGRUB_UINT64_T "%c", whole, fraction,
|
|||
|
+ grub_human_sizes[units]);
|
|||
|
+ grub_printf ("%-12s", buf);
|
|||
|
}
|
|||
|
- grub_file_close (file);
|
|||
|
- grub_free (pathname);
|
|||
|
- }
|
|||
|
- else
|
|||
|
- grub_printf ("%-12s", _("DIR"));
|
|||
|
-
|
|||
|
- if (info->mtimeset)
|
|||
|
- {
|
|||
|
- struct grub_datetime datetime;
|
|||
|
- grub_unixtime2datetime (info->mtime, &datetime);
|
|||
|
- if (human)
|
|||
|
- grub_printf (" %d-%02d-%02d %02d:%02d:%02d %-11s ",
|
|||
|
- datetime.year, datetime.month, datetime.day,
|
|||
|
- datetime.hour, datetime.minute,
|
|||
|
- datetime.second,
|
|||
|
- grub_get_weekday_name (&datetime));
|
|||
|
else
|
|||
|
- grub_printf (" %04d%02d%02d%02d%02d%02d ",
|
|||
|
- datetime.year, datetime.month,
|
|||
|
- datetime.day, datetime.hour,
|
|||
|
- datetime.minute, datetime.second);
|
|||
|
+ grub_printf ("%-12llu", (unsigned long long) file->size);
|
|||
|
+
|
|||
|
}
|
|||
|
- grub_printf ("%s%s\n", filename, info->dir ? "/" : "");
|
|||
|
+ grub_file_close (file);
|
|||
|
+ grub_free (pathname);
|
|||
|
+ }
|
|||
|
+ else
|
|||
|
+ grub_printf ("%-12s", _("DIR"));
|
|||
|
|
|||
|
- return 0;
|
|||
|
+ if (info->mtimeset)
|
|||
|
+ {
|
|||
|
+ struct grub_datetime datetime;
|
|||
|
+ grub_unixtime2datetime (info->mtime, &datetime);
|
|||
|
+ if (ctx->human)
|
|||
|
+ grub_printf (" %d-%02d-%02d %02d:%02d:%02d %-11s ",
|
|||
|
+ datetime.year, datetime.month, datetime.day,
|
|||
|
+ datetime.hour, datetime.minute,
|
|||
|
+ datetime.second,
|
|||
|
+ grub_get_weekday_name (&datetime));
|
|||
|
+ else
|
|||
|
+ grub_printf (" %04d%02d%02d%02d%02d%02d ",
|
|||
|
+ datetime.year, datetime.month,
|
|||
|
+ datetime.day, datetime.hour,
|
|||
|
+ datetime.minute, datetime.second);
|
|||
|
}
|
|||
|
+ grub_printf ("%s%s\n", filename, info->dir ? "/" : "");
|
|||
|
+
|
|||
|
+ 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);
|
|||
|
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)
|
|||
|
{
|
|||
|
+ struct grub_ls_list_files_ctx ctx = {
|
|||
|
+ .dirname = dirname,
|
|||
|
+ .all = all,
|
|||
|
+ .human = human
|
|||
|
+ };
|
|||
|
+
|
|||
|
if (longlist)
|
|||
|
- (fs->dir) (dev, path, print_files_long);
|
|||
|
+ (fs->dir) (dev, path, print_files_long, &ctx);
|
|||
|
else
|
|||
|
- (fs->dir) (dev, path, print_files);
|
|||
|
+ (fs->dir) (dev, path, print_files, &ctx);
|
|||
|
|
|||
|
if (grub_errno == GRUB_ERR_BAD_FILE_TYPE
|
|||
|
&& path[grub_strlen (path) - 1] != '/')
|
|||
|
@@ -250,9 +268,9 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human)
|
|||
|
all = 1;
|
|||
|
grub_memset (&info, 0, sizeof (info));
|
|||
|
if (longlist)
|
|||
|
- print_files_long (p, &info);
|
|||
|
+ print_files_long (p, &info, &ctx);
|
|||
|
else
|
|||
|
- print_files (p, &info);
|
|||
|
+ print_files (p, &info, &ctx);
|
|||
|
|
|||
|
grub_free (dirname);
|
|||
|
}
|
|||
|
diff --git a/grub-core/commands/test.c b/grub-core/commands/test.c
|
|||
|
index 3a0e0e0..e3347ee 100644
|
|||
|
--- a/grub-core/commands/test.c
|
|||
|
+++ b/grub-core/commands/test.c
|
|||
|
@@ -38,114 +38,125 @@ grub_strtosl (char *arg, char **end, int base)
|
|||
|
return grub_strtoul (arg, end, base);
|
|||
|
}
|
|||
|
|
|||
|
-/* Parse a test expression starting from *argn. */
|
|||
|
-static int
|
|||
|
-test_parse (char **args, int *argn, int argc)
|
|||
|
+/* Context for test_parse. */
|
|||
|
+struct test_parse_ctx
|
|||
|
{
|
|||
|
- int ret = 0, discard = 0, invert = 0;
|
|||
|
+ int ret, discard, invert;
|
|||
|
int file_exists;
|
|||
|
struct grub_dirhook_info file_info;
|
|||
|
+ char *filename;
|
|||
|
+};
|
|||
|
+
|
|||
|
+/* Take care of discarding and inverting. */
|
|||
|
+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;
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* A hook for iterating directories. */
|
|||
|
+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)
|
|||
|
+ {
|
|||
|
+ ctx->file_info = *info;
|
|||
|
+ ctx->file_exists = 1;
|
|||
|
+ return 1;
|
|||
|
+ }
|
|||
|
+ return 0;
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* Check if file exists and fetch its information. */
|
|||
|
+static void
|
|||
|
+get_fileinfo (char *path, struct test_parse_ctx *ctx)
|
|||
|
+{
|
|||
|
+ char *pathname;
|
|||
|
+ char *device_name;
|
|||
|
+ grub_fs_t fs;
|
|||
|
+ grub_device_t dev;
|
|||
|
+
|
|||
|
+ ctx->file_exists = 0;
|
|||
|
+ device_name = grub_file_get_device_name (path);
|
|||
|
+ dev = grub_device_open (device_name);
|
|||
|
+ if (! dev)
|
|||
|
+ {
|
|||
|
+ grub_free (device_name);
|
|||
|
+ return;
|
|||
|
+ }
|
|||
|
|
|||
|
- auto void update_val (int val);
|
|||
|
- auto void get_fileinfo (char *pathname);
|
|||
|
-
|
|||
|
- /* Take care of discarding and inverting. */
|
|||
|
- void update_val (int val)
|
|||
|
- {
|
|||
|
- if (! discard)
|
|||
|
- ret = invert ? ! val : val;
|
|||
|
- invert = discard = 0;
|
|||
|
- }
|
|||
|
-
|
|||
|
- /* Check if file exists and fetch its information. */
|
|||
|
- void get_fileinfo (char *path)
|
|||
|
- {
|
|||
|
- char *filename, *pathname;
|
|||
|
- char *device_name;
|
|||
|
- grub_fs_t fs;
|
|||
|
- grub_device_t dev;
|
|||
|
-
|
|||
|
- /* A hook for iterating directories. */
|
|||
|
- 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)
|
|||
|
+ fs = grub_fs_probe (dev);
|
|||
|
+ if (! fs)
|
|||
|
{
|
|||
|
- if ((info->case_insensitive ? grub_strcasecmp (cur_filename, filename)
|
|||
|
- : grub_strcmp (cur_filename, filename)) == 0)
|
|||
|
+ grub_free (device_name);
|
|||
|
+ grub_device_close (dev);
|
|||
|
+ return;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ pathname = grub_strchr (path, ')');
|
|||
|
+ if (! pathname)
|
|||
|
+ pathname = path;
|
|||
|
+ else
|
|||
|
+ pathname++;
|
|||
|
+
|
|||
|
+ /* Remove trailing '/'. */
|
|||
|
+ while (*pathname && pathname[grub_strlen (pathname) - 1] == '/')
|
|||
|
+ pathname[grub_strlen (pathname) - 1] = 0;
|
|||
|
+
|
|||
|
+ /* Split into path and filename. */
|
|||
|
+ ctx->filename = grub_strrchr (pathname, '/');
|
|||
|
+ if (! ctx->filename)
|
|||
|
+ {
|
|||
|
+ path = grub_strdup ("/");
|
|||
|
+ ctx->filename = pathname;
|
|||
|
+ }
|
|||
|
+ else
|
|||
|
+ {
|
|||
|
+ ctx->filename++;
|
|||
|
+ path = grub_strdup (pathname);
|
|||
|
+ path[ctx->filename - pathname] = 0;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /* It's the whole device. */
|
|||
|
+ if (! *pathname)
|
|||
|
+ {
|
|||
|
+ ctx->file_exists = 1;
|
|||
|
+ grub_memset (&ctx->file_info, 0, sizeof (ctx->file_info));
|
|||
|
+ /* Root is always a directory. */
|
|||
|
+ ctx->file_info.dir = 1;
|
|||
|
+
|
|||
|
+ /* Fetch writing time. */
|
|||
|
+ ctx->file_info.mtimeset = 0;
|
|||
|
+ if (fs->mtime)
|
|||
|
{
|
|||
|
- file_info = *info;
|
|||
|
- file_exists = 1;
|
|||
|
- return 1;
|
|||
|
+ if (! fs->mtime (dev, &ctx->file_info.mtime))
|
|||
|
+ ctx->file_info.mtimeset = 1;
|
|||
|
+ grub_errno = GRUB_ERR_NONE;
|
|||
|
}
|
|||
|
- return 0;
|
|||
|
}
|
|||
|
+ else
|
|||
|
+ (fs->dir) (dev, path, find_file, ctx);
|
|||
|
+
|
|||
|
+ grub_device_close (dev);
|
|||
|
+ grub_free (path);
|
|||
|
+ grub_free (device_name);
|
|||
|
+}
|
|||
|
|
|||
|
- file_exists = 0;
|
|||
|
- device_name = grub_file_get_device_name (path);
|
|||
|
- dev = grub_device_open (device_name);
|
|||
|
- if (! dev)
|
|||
|
- {
|
|||
|
- grub_free (device_name);
|
|||
|
- return;
|
|||
|
- }
|
|||
|
-
|
|||
|
- fs = grub_fs_probe (dev);
|
|||
|
- if (! fs)
|
|||
|
- {
|
|||
|
- grub_free (device_name);
|
|||
|
- grub_device_close (dev);
|
|||
|
- return;
|
|||
|
- }
|
|||
|
-
|
|||
|
- pathname = grub_strchr (path, ')');
|
|||
|
- if (! pathname)
|
|||
|
- pathname = path;
|
|||
|
- else
|
|||
|
- pathname++;
|
|||
|
-
|
|||
|
- /* Remove trailing '/'. */
|
|||
|
- while (*pathname && pathname[grub_strlen (pathname) - 1] == '/')
|
|||
|
- pathname[grub_strlen (pathname) - 1] = 0;
|
|||
|
-
|
|||
|
- /* Split into path and filename. */
|
|||
|
- filename = grub_strrchr (pathname, '/');
|
|||
|
- if (! filename)
|
|||
|
- {
|
|||
|
- path = grub_strdup ("/");
|
|||
|
- filename = pathname;
|
|||
|
- }
|
|||
|
- else
|
|||
|
- {
|
|||
|
- filename++;
|
|||
|
- path = grub_strdup (pathname);
|
|||
|
- path[filename - pathname] = 0;
|
|||
|
- }
|
|||
|
-
|
|||
|
- /* It's the whole device. */
|
|||
|
- if (! *pathname)
|
|||
|
- {
|
|||
|
- file_exists = 1;
|
|||
|
- grub_memset (&file_info, 0, sizeof (file_info));
|
|||
|
- /* Root is always a directory. */
|
|||
|
- file_info.dir = 1;
|
|||
|
-
|
|||
|
- /* Fetch writing time. */
|
|||
|
- file_info.mtimeset = 0;
|
|||
|
- if (fs->mtime)
|
|||
|
- {
|
|||
|
- if (! fs->mtime (dev, &file_info.mtime))
|
|||
|
- file_info.mtimeset = 1;
|
|||
|
- grub_errno = GRUB_ERR_NONE;
|
|||
|
- }
|
|||
|
- }
|
|||
|
- else
|
|||
|
- (fs->dir) (dev, path, find_file);
|
|||
|
-
|
|||
|
- grub_device_close (dev);
|
|||
|
- grub_free (path);
|
|||
|
- 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. */
|
|||
|
while (*argn < argc)
|
|||
|
@@ -157,14 +168,16 @@ test_parse (char **args, int *argn, int argc)
|
|||
|
if (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;
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
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;
|
|||
|
continue;
|
|||
|
}
|
|||
|
@@ -172,28 +185,32 @@ test_parse (char **args, int *argn, int argc)
|
|||
|
/* GRUB extension: lexicographical sorting. */
|
|||
|
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;
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
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;
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
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;
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
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;
|
|||
|
continue;
|
|||
|
}
|
|||
|
@@ -202,7 +219,7 @@ test_parse (char **args, int *argn, int argc)
|
|||
|
if (grub_strcmp (args[*argn + 1], "-eq") == 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;
|
|||
|
continue;
|
|||
|
}
|
|||
|
@@ -210,7 +227,7 @@ test_parse (char **args, int *argn, int argc)
|
|||
|
if (grub_strcmp (args[*argn + 1], "-ge") == 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;
|
|||
|
continue;
|
|||
|
}
|
|||
|
@@ -218,7 +235,7 @@ test_parse (char **args, int *argn, int argc)
|
|||
|
if (grub_strcmp (args[*argn + 1], "-gt") == 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;
|
|||
|
continue;
|
|||
|
}
|
|||
|
@@ -226,7 +243,7 @@ test_parse (char **args, int *argn, int argc)
|
|||
|
if (grub_strcmp (args[*argn + 1], "-le") == 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;
|
|||
|
continue;
|
|||
|
}
|
|||
|
@@ -234,7 +251,7 @@ test_parse (char **args, int *argn, int argc)
|
|||
|
if (grub_strcmp (args[*argn + 1], "-lt") == 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;
|
|||
|
continue;
|
|||
|
}
|
|||
|
@@ -242,7 +259,7 @@ test_parse (char **args, int *argn, int argc)
|
|||
|
if (grub_strcmp (args[*argn + 1], "-ne") == 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;
|
|||
|
continue;
|
|||
|
}
|
|||
|
@@ -265,10 +282,10 @@ test_parse (char **args, int *argn, int argc)
|
|||
|
|
|||
|
if (grub_strcmp (args[*argn + 1], "-pgt") == 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
|
|||
|
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;
|
|||
|
continue;
|
|||
|
}
|
|||
|
@@ -283,22 +300,24 @@ test_parse (char **args, int *argn, int argc)
|
|||
|
int bias = 0;
|
|||
|
|
|||
|
/* Fetch fileinfo. */
|
|||
|
- get_fileinfo (args[*argn]);
|
|||
|
- file1 = file_info;
|
|||
|
- file1exists = file_exists;
|
|||
|
- get_fileinfo (args[*argn + 2]);
|
|||
|
+ get_fileinfo (args[*argn], &ctx);
|
|||
|
+ file1 = ctx.file_info;
|
|||
|
+ file1exists = ctx.file_exists;
|
|||
|
+ get_fileinfo (args[*argn + 2], &ctx);
|
|||
|
|
|||
|
if (args[*argn + 1][3])
|
|||
|
bias = grub_strtosl (args[*argn + 1] + 3, 0, 0);
|
|||
|
|
|||
|
if (grub_memcmp (args[*argn + 1], "-nt", 3) == 0)
|
|||
|
- update_val ((file1exists && ! file_exists)
|
|||
|
- || (file1.mtimeset && file_info.mtimeset
|
|||
|
- && file1.mtime + bias > file_info.mtime));
|
|||
|
+ update_val ((file1exists && ! ctx.file_exists)
|
|||
|
+ || (file1.mtimeset && ctx.file_info.mtimeset
|
|||
|
+ && file1.mtime + bias > ctx.file_info.mtime),
|
|||
|
+ &ctx);
|
|||
|
else
|
|||
|
- update_val ((! file1exists && file_exists)
|
|||
|
- || (file1.mtimeset && file_info.mtimeset
|
|||
|
- && file1.mtime + bias < file_info.mtime));
|
|||
|
+ update_val ((! file1exists && ctx.file_exists)
|
|||
|
+ || (file1.mtimeset && ctx.file_info.mtimeset
|
|||
|
+ && file1.mtime + bias < ctx.file_info.mtime),
|
|||
|
+ &ctx);
|
|||
|
(*argn) += 3;
|
|||
|
continue;
|
|||
|
}
|
|||
|
@@ -310,27 +329,27 @@ test_parse (char **args, int *argn, int argc)
|
|||
|
/* File tests. */
|
|||
|
if (grub_strcmp (args[*argn], "-d") == 0)
|
|||
|
{
|
|||
|
- get_fileinfo (args[*argn + 1]);
|
|||
|
- update_val (file_exists && file_info.dir);
|
|||
|
+ get_fileinfo (args[*argn + 1], &ctx);
|
|||
|
+ update_val (ctx.file_exists && ctx.file_info.dir, &ctx);
|
|||
|
(*argn) += 2;
|
|||
|
- return ret;
|
|||
|
+ return ctx.ret;
|
|||
|
}
|
|||
|
|
|||
|
if (grub_strcmp (args[*argn], "-e") == 0)
|
|||
|
{
|
|||
|
- get_fileinfo (args[*argn + 1]);
|
|||
|
- update_val (file_exists);
|
|||
|
+ get_fileinfo (args[*argn + 1], &ctx);
|
|||
|
+ update_val (ctx.file_exists, &ctx);
|
|||
|
(*argn) += 2;
|
|||
|
- return ret;
|
|||
|
+ return ctx.ret;
|
|||
|
}
|
|||
|
|
|||
|
if (grub_strcmp (args[*argn], "-f") == 0)
|
|||
|
{
|
|||
|
- get_fileinfo (args[*argn + 1]);
|
|||
|
+ get_fileinfo (args[*argn + 1], &ctx);
|
|||
|
/* FIXME: check for other types. */
|
|||
|
- update_val (file_exists && ! file_info.dir);
|
|||
|
+ update_val (ctx.file_exists && ! ctx.file_info.dir, &ctx);
|
|||
|
(*argn) += 2;
|
|||
|
- return ret;
|
|||
|
+ return ctx.ret;
|
|||
|
}
|
|||
|
|
|||
|
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_filter_disable_compression ();
|
|||
|
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)
|
|||
|
grub_file_close (file);
|
|||
|
grub_errno = GRUB_ERR_NONE;
|
|||
|
(*argn) += 2;
|
|||
|
- return ret;
|
|||
|
+ return ctx.ret;
|
|||
|
}
|
|||
|
|
|||
|
/* String tests. */
|
|||
|
if (grub_strcmp (args[*argn], "-n") == 0)
|
|||
|
{
|
|||
|
- update_val (args[*argn + 1][0]);
|
|||
|
+ update_val (args[*argn + 1][0], &ctx);
|
|||
|
|
|||
|
(*argn) += 2;
|
|||
|
continue;
|
|||
|
}
|
|||
|
if (grub_strcmp (args[*argn], "-z") == 0)
|
|||
|
{
|
|||
|
- update_val (! args[*argn + 1][0]);
|
|||
|
+ update_val (! args[*argn + 1][0], &ctx);
|
|||
|
(*argn) += 2;
|
|||
|
continue;
|
|||
|
}
|
|||
|
@@ -368,42 +387,42 @@ test_parse (char **args, int *argn, int argc)
|
|||
|
if (grub_strcmp (args[*argn], ")") == 0)
|
|||
|
{
|
|||
|
(*argn)++;
|
|||
|
- return ret;
|
|||
|
+ return ctx.ret;
|
|||
|
}
|
|||
|
/* Recursively invoke if parenthesis. */
|
|||
|
if (grub_strcmp (args[*argn], "(") == 0)
|
|||
|
{
|
|||
|
(*argn)++;
|
|||
|
- update_val (test_parse (args, argn, argc));
|
|||
|
+ update_val (test_parse (args, argn, argc), &ctx);
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if (grub_strcmp (args[*argn], "!") == 0)
|
|||
|
{
|
|||
|
- invert = ! invert;
|
|||
|
+ ctx.invert = ! ctx.invert;
|
|||
|
(*argn)++;
|
|||
|
continue;
|
|||
|
}
|
|||
|
if (grub_strcmp (args[*argn], "-a") == 0)
|
|||
|
{
|
|||
|
/* If current value is 0 second value is to be discarded. */
|
|||
|
- discard = ! ret;
|
|||
|
+ ctx.discard = ! ctx.ret;
|
|||
|
(*argn)++;
|
|||
|
continue;
|
|||
|
}
|
|||
|
if (grub_strcmp (args[*argn], "-o") == 0)
|
|||
|
{
|
|||
|
/* If current value is 1 second value is to be discarded. */
|
|||
|
- discard = ret;
|
|||
|
+ ctx.discard = ctx.ret;
|
|||
|
(*argn)++;
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
/* No test found. Interpret if as just a string. */
|
|||
|
- update_val (args[*argn][0]);
|
|||
|
+ update_val (args[*argn][0], &ctx);
|
|||
|
(*argn)++;
|
|||
|
}
|
|||
|
- return ret;
|
|||
|
+ return ctx.ret;
|
|||
|
}
|
|||
|
|
|||
|
static grub_err_t
|
|||
|
diff --git a/grub-core/commands/wildcard.c b/grub-core/commands/wildcard.c
|
|||
|
index 633de51..2807f80 100644
|
|||
|
--- a/grub-core/commands/wildcard.c
|
|||
|
+++ b/grub-core/commands/wildcard.c
|
|||
|
@@ -279,63 +279,75 @@ match_devices (const regex_t *regexp, int noparts)
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
-static char **
|
|||
|
-match_files (const char *prefix, const char *suffix, const char *end,
|
|||
|
- const regex_t *regexp)
|
|||
|
+/* Context for match_files. */
|
|||
|
+struct match_files_ctx
|
|||
|
{
|
|||
|
- int i;
|
|||
|
+ const regex_t *regexp;
|
|||
|
char **files;
|
|||
|
unsigned nfile;
|
|||
|
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);
|
|||
|
- int match (const char *name, const struct grub_dirhook_info *info)
|
|||
|
- {
|
|||
|
- char **t;
|
|||
|
- char *buffer;
|
|||
|
+/* Helper for match_files. */
|
|||
|
+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 *buffer;
|
|||
|
|
|||
|
- /* skip . and .. names */
|
|||
|
- if (grub_strcmp(".", name) == 0 || grub_strcmp("..", name) == 0)
|
|||
|
- return 0;
|
|||
|
+ /* skip . and .. names */
|
|||
|
+ if (grub_strcmp(".", name) == 0 || grub_strcmp("..", name) == 0)
|
|||
|
+ return 0;
|
|||
|
|
|||
|
- grub_dprintf ("expand", "matching: %s in %s\n", name, dir);
|
|||
|
- if (regexec (regexp, name, 0, 0, 0))
|
|||
|
- return 0;
|
|||
|
+ grub_dprintf ("expand", "matching: %s in %s\n", name, ctx->dir);
|
|||
|
+ if (regexec (ctx->regexp, name, 0, 0, 0))
|
|||
|
+ return 0;
|
|||
|
|
|||
|
- grub_dprintf ("expand", "matched\n");
|
|||
|
+ grub_dprintf ("expand", "matched\n");
|
|||
|
|
|||
|
- buffer = grub_xasprintf ("%s%s", dir, name);
|
|||
|
- if (! buffer)
|
|||
|
+ buffer = grub_xasprintf ("%s%s", ctx->dir, name);
|
|||
|
+ if (! buffer)
|
|||
|
+ return 1;
|
|||
|
+
|
|||
|
+ t = grub_realloc (ctx->files, sizeof (char*) * (ctx->nfile + 2));
|
|||
|
+ if (! t)
|
|||
|
+ {
|
|||
|
+ grub_free (buffer);
|
|||
|
return 1;
|
|||
|
+ }
|
|||
|
|
|||
|
- t = grub_realloc (files, sizeof (char*) * (nfile + 2));
|
|||
|
- if (! t)
|
|||
|
- {
|
|||
|
- grub_free (buffer);
|
|||
|
- return 1;
|
|||
|
- }
|
|||
|
+ ctx->files = t;
|
|||
|
+ ctx->files[ctx->nfile++] = buffer;
|
|||
|
+ ctx->files[ctx->nfile] = 0;
|
|||
|
+ return 0;
|
|||
|
+}
|
|||
|
|
|||
|
- files = t;
|
|||
|
- files[nfile++] = buffer;
|
|||
|
- files[nfile] = 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;
|
|||
|
device_name = 0;
|
|||
|
grub_error_push ();
|
|||
|
|
|||
|
- dir = make_dir (prefix, suffix, end);
|
|||
|
- if (! dir)
|
|||
|
+ ctx.dir = make_dir (prefix, suffix, end);
|
|||
|
+ if (! ctx.dir)
|
|||
|
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);
|
|||
|
if (! dev)
|
|||
|
goto fail;
|
|||
|
@@ -344,33 +356,33 @@ match_files (const char *prefix, const char *suffix, const char *end,
|
|||
|
if (! fs)
|
|||
|
goto fail;
|
|||
|
|
|||
|
- if (dir[0] == '(')
|
|||
|
+ if (ctx.dir[0] == '(')
|
|||
|
{
|
|||
|
- path = grub_strchr (dir, ')');
|
|||
|
+ path = grub_strchr (ctx.dir, ')');
|
|||
|
if (!path)
|
|||
|
goto fail;
|
|||
|
path++;
|
|||
|
}
|
|||
|
else
|
|||
|
- path = dir;
|
|||
|
+ path = ctx.dir;
|
|||
|
|
|||
|
- if (fs->dir (dev, path, match))
|
|||
|
+ if (fs->dir (dev, path, match_files_iter, &ctx))
|
|||
|
goto fail;
|
|||
|
|
|||
|
- grub_free (dir);
|
|||
|
+ grub_free (ctx.dir);
|
|||
|
grub_device_close (dev);
|
|||
|
grub_free (device_name);
|
|||
|
grub_error_pop ();
|
|||
|
- return files;
|
|||
|
+ return ctx.files;
|
|||
|
|
|||
|
fail:
|
|||
|
|
|||
|
- grub_free (dir);
|
|||
|
+ grub_free (ctx.dir);
|
|||
|
|
|||
|
- for (i = 0; files && files[i]; i++)
|
|||
|
- grub_free (files[i]);
|
|||
|
+ for (i = 0; ctx.files && ctx.files[i]; i++)
|
|||
|
+ grub_free (ctx.files[i]);
|
|||
|
|
|||
|
- grub_free (files);
|
|||
|
+ grub_free (ctx.files);
|
|||
|
|
|||
|
if (dev)
|
|||
|
grub_device_close (dev);
|
|||
|
@@ -381,28 +393,42 @@ match_files (const char *prefix, const char *suffix, const char *end,
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
+/* Context for check_file. */
|
|||
|
+struct check_file_ctx
|
|||
|
+{
|
|||
|
+ const char *basename;
|
|||
|
+ int found;
|
|||
|
+};
|
|||
|
+
|
|||
|
+/* Helper for check_file. */
|
|||
|
+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))
|
|||
|
+ {
|
|||
|
+ ctx->found = 1;
|
|||
|
+ return 1;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ 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;
|
|||
|
- int found = 0;
|
|||
|
const char *device_name, *path;
|
|||
|
|
|||
|
- auto int match (const char *name, const struct grub_dirhook_info *info);
|
|||
|
- int match (const char *name, const struct grub_dirhook_info *info)
|
|||
|
- {
|
|||
|
- if (basename[0] == 0
|
|||
|
- || (info->case_insensitive ? grub_strcasecmp (name, basename) == 0
|
|||
|
- : grub_strcmp (name, basename) == 0))
|
|||
|
- {
|
|||
|
- found = 1;
|
|||
|
- return 1;
|
|||
|
- }
|
|||
|
-
|
|||
|
- return 0;
|
|||
|
- }
|
|||
|
-
|
|||
|
device_name = grub_file_get_device_name (dir);
|
|||
|
dev = grub_device_open (device_name);
|
|||
|
if (! dev)
|
|||
|
@@ -422,14 +448,14 @@ check_file (const char *dir, const char *basename)
|
|||
|
else
|
|||
|
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)
|
|||
|
- found = 1;
|
|||
|
+ ctx.found = 1;
|
|||
|
|
|||
|
fail:
|
|||
|
grub_errno = 0;
|
|||
|
|
|||
|
- return found;
|
|||
|
+ return ctx.found;
|
|||
|
}
|
|||
|
|
|||
|
static void
|
|||
|
diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c
|
|||
|
index 848a455..6c49e5d 100644
|
|||
|
--- a/grub-core/fs/affs.c
|
|||
|
+++ b/grub-core/fs/affs.c
|
|||
|
@@ -316,93 +316,93 @@ grub_affs_read_symlink (grub_fshelp_node_t node)
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
+/* Helper for grub_affs_iterate_dir. */
|
|||
|
static int
|
|||
|
-grub_affs_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
- int NESTED_FUNC_ATTR
|
|||
|
- (*hook) (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node))
|
|||
|
+grub_affs_create_node (grub_fshelp_node_t dir,
|
|||
|
+ grub_fshelp_iterate_dir_hook_t hook, void *hook_data,
|
|||
|
+ struct grub_fshelp_node **node,
|
|||
|
+ grub_uint32_t **hashtable,
|
|||
|
+ grub_uint32_t block, const struct grub_affs_file *fil)
|
|||
|
{
|
|||
|
- 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;
|
|||
|
-
|
|||
|
- auto int NESTED_FUNC_ATTR grub_affs_create_node (grub_uint32_t block,
|
|||
|
- const struct grub_affs_file *fil);
|
|||
|
+ int type;
|
|||
|
+ grub_uint8_t name_u8[sizeof (fil->name) * GRUB_MAX_UTF8_PER_LATIN1 + 1];
|
|||
|
+ grub_size_t len;
|
|||
|
+ unsigned int nest;
|
|||
|
|
|||
|
- int NESTED_FUNC_ATTR grub_affs_create_node (grub_uint32_t block,
|
|||
|
- const struct grub_affs_file *fil)
|
|||
|
+ *node = grub_zalloc (sizeof (**node));
|
|||
|
+ if (!*node)
|
|||
|
{
|
|||
|
- int type;
|
|||
|
- grub_uint8_t name_u8[sizeof (fil->name) * GRUB_MAX_UTF8_PER_LATIN1 + 1];
|
|||
|
- grub_size_t len;
|
|||
|
- unsigned int nest;
|
|||
|
-
|
|||
|
- node = grub_zalloc (sizeof (*node));
|
|||
|
- if (!node)
|
|||
|
- {
|
|||
|
- grub_free (hashtable);
|
|||
|
- return 1;
|
|||
|
- }
|
|||
|
+ grub_free (*hashtable);
|
|||
|
+ return 1;
|
|||
|
+ }
|
|||
|
|
|||
|
- node->data = data;
|
|||
|
- node->block = block;
|
|||
|
- node->parent = dir;
|
|||
|
-
|
|||
|
- len = fil->namelen;
|
|||
|
- if (len > sizeof (fil->name))
|
|||
|
- len = sizeof (fil->name);
|
|||
|
- *grub_latin1_to_utf8 (name_u8, fil->name, len) = '\0';
|
|||
|
-
|
|||
|
- node->di = *fil;
|
|||
|
- for (nest = 0; nest < 8; nest++)
|
|||
|
+ (*node)->data = data;
|
|||
|
+ (*node)->block = block;
|
|||
|
+ (*node)->parent = dir;
|
|||
|
+
|
|||
|
+ len = fil->namelen;
|
|||
|
+ if (len > sizeof (fil->name))
|
|||
|
+ len = sizeof (fil->name);
|
|||
|
+ *grub_latin1_to_utf8 (name_u8, fil->name, len) = '\0';
|
|||
|
+
|
|||
|
+ (*node)->di = *fil;
|
|||
|
+ for (nest = 0; nest < 8; nest++)
|
|||
|
+ {
|
|||
|
+ switch ((*node)->di.type)
|
|||
|
{
|
|||
|
- switch (node->di.type)
|
|||
|
- {
|
|||
|
- case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_REG):
|
|||
|
- type = GRUB_FSHELP_REG;
|
|||
|
- break;
|
|||
|
- case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_DIR):
|
|||
|
- type = GRUB_FSHELP_DIR;
|
|||
|
- break;
|
|||
|
- case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_SYMLINK):
|
|||
|
- type = GRUB_FSHELP_SYMLINK;
|
|||
|
- break;
|
|||
|
- case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_HARDLINK):
|
|||
|
- {
|
|||
|
- grub_err_t err;
|
|||
|
- node->block = grub_be_to_cpu32 (node->di.hardlink);
|
|||
|
- err = grub_disk_read (data->disk,
|
|||
|
- (((grub_uint64_t) node->block + 1) << data->log_blocksize)
|
|||
|
- - 1,
|
|||
|
- GRUB_DISK_SECTOR_SIZE - GRUB_AFFS_FILE_LOCATION,
|
|||
|
- sizeof (node->di), (char *) &node->di);
|
|||
|
- if (err)
|
|||
|
- return 1;
|
|||
|
- continue;
|
|||
|
- }
|
|||
|
- default:
|
|||
|
- return 0;
|
|||
|
- }
|
|||
|
+ case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_REG):
|
|||
|
+ type = GRUB_FSHELP_REG;
|
|||
|
+ break;
|
|||
|
+ case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_DIR):
|
|||
|
+ type = GRUB_FSHELP_DIR;
|
|||
|
+ break;
|
|||
|
+ case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_SYMLINK):
|
|||
|
+ type = GRUB_FSHELP_SYMLINK;
|
|||
|
break;
|
|||
|
+ case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_HARDLINK):
|
|||
|
+ {
|
|||
|
+ grub_err_t err;
|
|||
|
+ (*node)->block = grub_be_to_cpu32 ((*node)->di.hardlink);
|
|||
|
+ err = grub_disk_read (data->disk,
|
|||
|
+ (((grub_uint64_t) (*node)->block + 1) << data->log_blocksize)
|
|||
|
+ - 1,
|
|||
|
+ GRUB_DISK_SECTOR_SIZE - GRUB_AFFS_FILE_LOCATION,
|
|||
|
+ sizeof ((*node)->di), (char *) &(*node)->di);
|
|||
|
+ if (err)
|
|||
|
+ return 1;
|
|||
|
+ continue;
|
|||
|
+ }
|
|||
|
+ default:
|
|||
|
+ return 0;
|
|||
|
}
|
|||
|
+ break;
|
|||
|
+ }
|
|||
|
|
|||
|
- if (nest == 8)
|
|||
|
- return 0;
|
|||
|
+ if (nest == 8)
|
|||
|
+ return 0;
|
|||
|
|
|||
|
- type |= GRUB_FSHELP_CASE_INSENSITIVE;
|
|||
|
+ type |= GRUB_FSHELP_CASE_INSENSITIVE;
|
|||
|
|
|||
|
- if (hook ((char *) name_u8, type, node))
|
|||
|
- {
|
|||
|
- grub_free (hashtable);
|
|||
|
- node = 0;
|
|||
|
- return 1;
|
|||
|
- }
|
|||
|
- node = 0;
|
|||
|
- return 0;
|
|||
|
+ if (hook ((char *) name_u8, type, *node, hook_data))
|
|||
|
+ {
|
|||
|
+ grub_free (*hashtable);
|
|||
|
+ *node = 0;
|
|||
|
+ return 1;
|
|||
|
}
|
|||
|
+ *node = 0;
|
|||
|
+ return 0;
|
|||
|
+}
|
|||
|
+
|
|||
|
+static int
|
|||
|
+grub_affs_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
+ 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 `..'. */
|
|||
|
node = grub_zalloc (sizeof (*node));
|
|||
|
@@ -410,7 +410,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
return 1;
|
|||
|
|
|||
|
*node = *dir;
|
|||
|
- if (hook (".", GRUB_FSHELP_DIR, node))
|
|||
|
+ if (hook (".", GRUB_FSHELP_DIR, node, hook_data))
|
|||
|
return 1;
|
|||
|
if (dir->parent)
|
|||
|
{
|
|||
|
@@ -418,7 +418,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
if (!node)
|
|||
|
return 1;
|
|||
|
*node = *dir->parent;
|
|||
|
- if (hook ("..", GRUB_FSHELP_DIR, node))
|
|||
|
+ if (hook ("..", GRUB_FSHELP_DIR, node, hook_data))
|
|||
|
return 1;
|
|||
|
}
|
|||
|
|
|||
|
@@ -454,7 +454,8 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
if (grub_errno)
|
|||
|
goto fail;
|
|||
|
|
|||
|
- if (grub_affs_create_node (next, &file))
|
|||
|
+ if (grub_affs_create_node (dir, hook, hook_data, &node, &hashtable,
|
|||
|
+ next, &file))
|
|||
|
return 1;
|
|||
|
|
|||
|
next = grub_be_to_cpu32 (file.next);
|
|||
|
@@ -545,31 +546,37 @@ aftime2ctime (const struct grub_affs_time *t)
|
|||
|
+ 8 * 365 * 86400 + 86400 * 2;
|
|||
|
}
|
|||
|
|
|||
|
+/* Context for grub_affs_dir. */
|
|||
|
+struct grub_affs_dir_ctx
|
|||
|
+{
|
|||
|
+ grub_fs_dir_hook_t hook;
|
|||
|
+ void *hook_data;
|
|||
|
+};
|
|||
|
+
|
|||
|
+/* Helper for grub_affs_dir. */
|
|||
|
+static int
|
|||
|
+grub_affs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
|
|||
|
+ grub_fshelp_node_t node, void *data)
|
|||
|
+{
|
|||
|
+ struct grub_affs_dir_ctx *ctx = data;
|
|||
|
+ struct grub_dirhook_info info;
|
|||
|
+
|
|||
|
+ grub_memset (&info, 0, sizeof (info));
|
|||
|
+ info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
|||
|
+ info.mtimeset = 1;
|
|||
|
+ info.mtime = aftime2ctime (&node->di.mtime);
|
|||
|
+ grub_free (node);
|
|||
|
+ return ctx->hook (filename, &info, ctx->hook_data);
|
|||
|
+}
|
|||
|
+
|
|||
|
static grub_err_t
|
|||
|
grub_affs_dir (grub_device_t device, const char *path,
|
|||
|
- int (*hook) (const char *filename,
|
|||
|
- const struct grub_dirhook_info *info))
|
|||
|
+ grub_fs_dir_hook_t hook, void *hook_data)
|
|||
|
{
|
|||
|
+ struct grub_affs_dir_ctx ctx = { hook, hook_data };
|
|||
|
struct grub_affs_data *data = 0;
|
|||
|
struct grub_fshelp_node *fdiro = 0;
|
|||
|
|
|||
|
- auto int NESTED_FUNC_ATTR iterate (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node);
|
|||
|
-
|
|||
|
- int NESTED_FUNC_ATTR iterate (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node)
|
|||
|
- {
|
|||
|
- struct grub_dirhook_info info;
|
|||
|
- grub_memset (&info, 0, sizeof (info));
|
|||
|
- info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
|||
|
- info.mtimeset = 1;
|
|||
|
- info.mtime = aftime2ctime (&node->di.mtime);
|
|||
|
- grub_free (node);
|
|||
|
- return hook (filename, &info);
|
|||
|
- }
|
|||
|
-
|
|||
|
grub_dl_ref (my_mod);
|
|||
|
|
|||
|
data = grub_affs_mount (device->disk);
|
|||
|
@@ -581,7 +588,7 @@ grub_affs_dir (grub_device_t device, const char *path,
|
|||
|
if (grub_errno)
|
|||
|
goto fail;
|
|||
|
|
|||
|
- grub_affs_iterate_dir (fdiro, iterate);
|
|||
|
+ grub_affs_iterate_dir (fdiro, grub_affs_dir_iter, &ctx);
|
|||
|
|
|||
|
fail:
|
|||
|
if (data && fdiro != &data->diropen)
|
|||
|
diff --git a/grub-core/fs/bfs.c b/grub-core/fs/bfs.c
|
|||
|
index 318dc3e..fa2fc3f 100644
|
|||
|
--- a/grub-core/fs/bfs.c
|
|||
|
+++ b/grub-core/fs/bfs.c
|
|||
|
@@ -173,6 +173,15 @@ struct grub_bfs_data
|
|||
|
struct grub_bfs_inode ino[0];
|
|||
|
};
|
|||
|
|
|||
|
+/* Context for grub_bfs_dir. */
|
|||
|
+struct grub_bfs_dir_ctx
|
|||
|
+{
|
|||
|
+ grub_device_t device;
|
|||
|
+ grub_fs_dir_hook_t hook;
|
|||
|
+ void *hook_data;
|
|||
|
+ struct grub_bfs_superblock sb;
|
|||
|
+};
|
|||
|
+
|
|||
|
static grub_err_t
|
|||
|
read_extent (grub_disk_t disk,
|
|||
|
const struct grub_bfs_superblock *sb,
|
|||
|
@@ -413,7 +422,9 @@ static int
|
|||
|
iterate_in_b_tree (grub_disk_t disk,
|
|||
|
const struct grub_bfs_superblock *sb,
|
|||
|
const struct grub_bfs_inode *ino,
|
|||
|
- int NESTED_FUNC_ATTR (*hook) (const char *name, grub_uint64_t value))
|
|||
|
+ int (*hook) (const char *name, grub_uint64_t value,
|
|||
|
+ struct grub_bfs_dir_ctx *ctx),
|
|||
|
+ struct grub_bfs_dir_ctx *ctx)
|
|||
|
{
|
|||
|
struct grub_bfs_btree_header head;
|
|||
|
grub_err_t err;
|
|||
|
@@ -496,7 +507,8 @@ iterate_in_b_tree (grub_disk_t disk,
|
|||
|
end = grub_bfs_to_cpu_treehead (node.total_key_len);
|
|||
|
c = key_data[end];
|
|||
|
key_data[end] = 0;
|
|||
|
- if (hook (key_data + start, grub_bfs_to_cpu64 (key_values[i])))
|
|||
|
+ if (hook (key_data + start, grub_bfs_to_cpu64 (key_values[i]),
|
|||
|
+ ctx))
|
|||
|
return 1;
|
|||
|
key_data[end] = c;
|
|||
|
}
|
|||
|
@@ -844,46 +856,52 @@ mount (grub_disk_t disk, struct grub_bfs_superblock *sb)
|
|||
|
return GRUB_ERR_NONE;
|
|||
|
}
|
|||
|
|
|||
|
-static grub_err_t
|
|||
|
-grub_bfs_dir (grub_device_t device, const char *path,
|
|||
|
- int (*hook_in) (const char *filename,
|
|||
|
- const struct grub_dirhook_info * info))
|
|||
|
+/* Helper for grub_bfs_dir. */
|
|||
|
+static int
|
|||
|
+grub_bfs_dir_iter (const char *name, grub_uint64_t value,
|
|||
|
+ 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;
|
|||
|
+ union
|
|||
|
{
|
|||
|
- grub_err_t err2;
|
|||
|
- union
|
|||
|
- {
|
|||
|
- struct grub_bfs_inode ino;
|
|||
|
- grub_uint8_t raw[grub_bfs_to_cpu32 (sb.bsize)];
|
|||
|
- } ino;
|
|||
|
- struct grub_dirhook_info info;
|
|||
|
+ struct grub_bfs_inode ino;
|
|||
|
+ grub_uint8_t raw[grub_bfs_to_cpu32 (ctx->sb.bsize)];
|
|||
|
+ } ino;
|
|||
|
+ struct grub_dirhook_info info;
|
|||
|
|
|||
|
- err2 = grub_disk_read (device->disk, value
|
|||
|
- << (grub_bfs_to_cpu32 (sb.log2_bsize)
|
|||
|
- - GRUB_DISK_SECTOR_BITS), 0,
|
|||
|
- grub_bfs_to_cpu32 (sb.bsize), (char *) ino.raw);
|
|||
|
- if (err2)
|
|||
|
- {
|
|||
|
- grub_print_error ();
|
|||
|
- return 0;
|
|||
|
- }
|
|||
|
+ err2 = grub_disk_read (ctx->device->disk, value
|
|||
|
+ << (grub_bfs_to_cpu32 (ctx->sb.log2_bsize)
|
|||
|
+ - GRUB_DISK_SECTOR_BITS), 0,
|
|||
|
+ grub_bfs_to_cpu32 (ctx->sb.bsize), (char *) ino.raw);
|
|||
|
+ if (err2)
|
|||
|
+ {
|
|||
|
+ grub_print_error ();
|
|||
|
+ return 0;
|
|||
|
+ }
|
|||
|
|
|||
|
- info.mtimeset = 1;
|
|||
|
+ info.mtimeset = 1;
|
|||
|
#ifdef MODE_AFS
|
|||
|
- info.mtime =
|
|||
|
- grub_divmod64 (grub_bfs_to_cpu64 (ino.ino.mtime), 1000000, 0);
|
|||
|
+ info.mtime =
|
|||
|
+ grub_divmod64 (grub_bfs_to_cpu64 (ino.ino.mtime), 1000000, 0);
|
|||
|
#else
|
|||
|
- info.mtime = grub_bfs_to_cpu64 (ino.ino.mtime) >> 16;
|
|||
|
+ info.mtime = grub_bfs_to_cpu64 (ino.ino.mtime) >> 16;
|
|||
|
#endif
|
|||
|
- info.dir = ((grub_bfs_to_cpu32 (ino.ino.mode) & ATTR_TYPE) == ATTR_DIR);
|
|||
|
- return hook_in (name, &info);
|
|||
|
- }
|
|||
|
- err = mount (device->disk, &sb);
|
|||
|
+ info.dir = ((grub_bfs_to_cpu32 (ino.ino.mode) & ATTR_TYPE) == ATTR_DIR);
|
|||
|
+ return ctx->hook (name, &info, ctx->hook_data);
|
|||
|
+}
|
|||
|
+
|
|||
|
+static grub_err_t
|
|||
|
+grub_bfs_dir (grub_device_t device, const char *path,
|
|||
|
+ 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)
|
|||
|
return err;
|
|||
|
|
|||
|
@@ -891,14 +909,15 @@ grub_bfs_dir (grub_device_t device, const char *path,
|
|||
|
union
|
|||
|
{
|
|||
|
struct grub_bfs_inode ino;
|
|||
|
- grub_uint8_t raw[grub_bfs_to_cpu32 (sb.bsize)];
|
|||
|
+ grub_uint8_t raw[grub_bfs_to_cpu32 (ctx.sb.bsize)];
|
|||
|
} ino;
|
|||
|
- err = find_file (path, device->disk, &sb, &ino.ino);
|
|||
|
+ err = find_file (path, device->disk, &ctx.sb, &ino.ino);
|
|||
|
if (err)
|
|||
|
return err;
|
|||
|
if (((grub_bfs_to_cpu32 (ino.ino.mode) & ATTR_TYPE) != ATTR_DIR))
|
|||
|
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
|
|||
|
- iterate_in_b_tree (device->disk, &sb, &ino.ino, hook);
|
|||
|
+ iterate_in_b_tree (device->disk, &ctx.sb, &ino.ino, grub_bfs_dir_iter,
|
|||
|
+ &ctx);
|
|||
|
}
|
|||
|
|
|||
|
return grub_errno;
|
|||
|
diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
|
|||
|
index bcc75ba..196f301 100644
|
|||
|
--- a/grub-core/fs/btrfs.c
|
|||
|
+++ b/grub-core/fs/btrfs.c
|
|||
|
@@ -1491,8 +1491,7 @@ find_path (struct grub_btrfs_data *data,
|
|||
|
|
|||
|
static grub_err_t
|
|||
|
grub_btrfs_dir (grub_device_t device, const char *path,
|
|||
|
- int (*hook) (const char *filename,
|
|||
|
- const struct grub_dirhook_info *info))
|
|||
|
+ grub_fs_dir_hook_t hook, void *hook_data)
|
|||
|
{
|
|||
|
struct grub_btrfs_data *data = grub_btrfs_mount (device);
|
|||
|
struct grub_btrfs_key key_in, key_out;
|
|||
|
@@ -1586,7 +1585,7 @@ grub_btrfs_dir (grub_device_t device, const char *path,
|
|||
|
c = cdirel->name[grub_le_to_cpu16 (cdirel->n)];
|
|||
|
cdirel->name[grub_le_to_cpu16 (cdirel->n)] = 0;
|
|||
|
info.dir = (cdirel->type == GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY);
|
|||
|
- if (hook (cdirel->name, &info))
|
|||
|
+ if (hook (cdirel->name, &info, hook_data))
|
|||
|
goto out;
|
|||
|
cdirel->name[grub_le_to_cpu16 (cdirel->n)] = c;
|
|||
|
}
|
|||
|
diff --git a/grub-core/fs/cpio.c b/grub-core/fs/cpio.c
|
|||
|
index e9236cd..71d7fa4 100644
|
|||
|
--- a/grub-core/fs/cpio.c
|
|||
|
+++ b/grub-core/fs/cpio.c
|
|||
|
@@ -513,8 +513,7 @@ handle_symlink (struct grub_cpio_data *data,
|
|||
|
|
|||
|
static grub_err_t
|
|||
|
grub_cpio_dir (grub_device_t device, const char *path_in,
|
|||
|
- int (*hook) (const char *filename,
|
|||
|
- const struct grub_dirhook_info *info))
|
|||
|
+ grub_fs_dir_hook_t hook, void *hook_data)
|
|||
|
{
|
|||
|
struct grub_cpio_data *data;
|
|||
|
grub_disk_addr_t ofs;
|
|||
|
@@ -575,7 +574,7 @@ grub_cpio_dir (grub_device_t device, const char *path_in,
|
|||
|
info.mtime = mtime;
|
|||
|
info.mtimeset = 1;
|
|||
|
|
|||
|
- if (hook (n, &info))
|
|||
|
+ if (hook (n, &info, hook_data))
|
|||
|
{
|
|||
|
grub_free (name);
|
|||
|
goto fail;
|
|||
|
diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c
|
|||
|
index cf2e2f4..0ebde35 100644
|
|||
|
--- a/grub-core/fs/ext2.c
|
|||
|
+++ b/grub-core/fs/ext2.c
|
|||
|
@@ -692,10 +692,7 @@ grub_ext2_read_symlink (grub_fshelp_node_t node)
|
|||
|
|
|||
|
static int
|
|||
|
grub_ext2_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
- int NESTED_FUNC_ATTR
|
|||
|
- (*hook) (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node))
|
|||
|
+ grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
|
|||
|
{
|
|||
|
unsigned int fpos = 0;
|
|||
|
struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir;
|
|||
|
@@ -777,7 +774,7 @@ grub_ext2_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
type = GRUB_FSHELP_REG;
|
|||
|
}
|
|||
|
|
|||
|
- if (hook (filename, type, fdiro))
|
|||
|
+ if (hook (filename, type, fdiro, hook_data))
|
|||
|
return 1;
|
|||
|
}
|
|||
|
|
|||
|
@@ -858,59 +855,69 @@ grub_ext2_read (grub_file_t file, char *buf, grub_size_t len)
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
-static grub_err_t
|
|||
|
-grub_ext2_dir (grub_device_t device, const char *path,
|
|||
|
- int (*hook) (const char *filename,
|
|||
|
- const struct grub_dirhook_info *info))
|
|||
|
+/* Context for grub_ext2_dir. */
|
|||
|
+struct grub_ext2_dir_ctx
|
|||
|
{
|
|||
|
- struct grub_ext2_data *data = 0;
|
|||
|
- struct grub_fshelp_node *fdiro = 0;
|
|||
|
+ grub_fs_dir_hook_t hook;
|
|||
|
+ void *hook_data;
|
|||
|
+ struct grub_ext2_data *data;
|
|||
|
+};
|
|||
|
|
|||
|
- auto int NESTED_FUNC_ATTR iterate (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node);
|
|||
|
+/* Helper for grub_ext2_dir. */
|
|||
|
+static int
|
|||
|
+grub_ext2_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
|
|||
|
+ grub_fshelp_node_t node, void *data)
|
|||
|
+{
|
|||
|
+ struct grub_ext2_dir_ctx *ctx = data;
|
|||
|
+ struct grub_dirhook_info info;
|
|||
|
|
|||
|
- int NESTED_FUNC_ATTR iterate (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node)
|
|||
|
+ grub_memset (&info, 0, sizeof (info));
|
|||
|
+ if (! node->inode_read)
|
|||
|
{
|
|||
|
- struct grub_dirhook_info info;
|
|||
|
- grub_memset (&info, 0, sizeof (info));
|
|||
|
- if (! node->inode_read)
|
|||
|
- {
|
|||
|
- grub_ext2_read_inode (data, node->ino, &node->inode);
|
|||
|
- if (!grub_errno)
|
|||
|
- node->inode_read = 1;
|
|||
|
- grub_errno = GRUB_ERR_NONE;
|
|||
|
- }
|
|||
|
- if (node->inode_read)
|
|||
|
- {
|
|||
|
- info.mtimeset = 1;
|
|||
|
- info.mtime = grub_le_to_cpu32 (node->inode.mtime);
|
|||
|
- }
|
|||
|
-
|
|||
|
- info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
|||
|
- grub_free (node);
|
|||
|
- return hook (filename, &info);
|
|||
|
+ grub_ext2_read_inode (ctx->data, node->ino, &node->inode);
|
|||
|
+ if (!grub_errno)
|
|||
|
+ node->inode_read = 1;
|
|||
|
+ grub_errno = GRUB_ERR_NONE;
|
|||
|
}
|
|||
|
+ if (node->inode_read)
|
|||
|
+ {
|
|||
|
+ info.mtimeset = 1;
|
|||
|
+ info.mtime = grub_le_to_cpu32 (node->inode.mtime);
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
|||
|
+ grub_free (node);
|
|||
|
+ return ctx->hook (filename, &info, ctx->hook_data);
|
|||
|
+}
|
|||
|
+
|
|||
|
+static grub_err_t
|
|||
|
+grub_ext2_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook,
|
|||
|
+ void *hook_data)
|
|||
|
+{
|
|||
|
+ struct grub_ext2_dir_ctx ctx = {
|
|||
|
+ .hook = hook,
|
|||
|
+ .hook_data = hook_data
|
|||
|
+ };
|
|||
|
+ struct grub_fshelp_node *fdiro = 0;
|
|||
|
|
|||
|
grub_dl_ref (my_mod);
|
|||
|
|
|||
|
- data = grub_ext2_mount (device->disk);
|
|||
|
- if (! data)
|
|||
|
+ ctx.data = grub_ext2_mount (device->disk);
|
|||
|
+ if (! ctx.data)
|
|||
|
goto fail;
|
|||
|
|
|||
|
- grub_fshelp_find_file (path, &data->diropen, &fdiro, grub_ext2_iterate_dir,
|
|||
|
- grub_ext2_read_symlink, GRUB_FSHELP_DIR);
|
|||
|
+ grub_fshelp_find_file (path, &ctx.data->diropen, &fdiro,
|
|||
|
+ grub_ext2_iterate_dir, grub_ext2_read_symlink,
|
|||
|
+ GRUB_FSHELP_DIR);
|
|||
|
if (grub_errno)
|
|||
|
goto fail;
|
|||
|
|
|||
|
- grub_ext2_iterate_dir (fdiro, iterate);
|
|||
|
+ grub_ext2_iterate_dir (fdiro, grub_ext2_dir_iter, &ctx);
|
|||
|
|
|||
|
fail:
|
|||
|
- if (fdiro != &data->diropen)
|
|||
|
+ if (fdiro != &ctx.data->diropen)
|
|||
|
grub_free (fdiro);
|
|||
|
- grub_free (data);
|
|||
|
+ grub_free (ctx.data);
|
|||
|
|
|||
|
grub_dl_unref (my_mod);
|
|||
|
|
|||
|
diff --git a/grub-core/fs/fat.c b/grub-core/fs/fat.c
|
|||
|
index 119fc94..7664153 100644
|
|||
|
--- a/grub-core/fs/fat.c
|
|||
|
+++ b/grub-core/fs/fat.c
|
|||
|
@@ -844,8 +844,7 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data,
|
|||
|
static char *
|
|||
|
grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
|
|||
|
const char *path, const char *origpath,
|
|||
|
- int (*hook) (const char *filename,
|
|||
|
- const struct grub_dirhook_info *info))
|
|||
|
+ grub_fs_dir_hook_t hook, void *hook_data)
|
|||
|
{
|
|||
|
char *dirname, *dirp;
|
|||
|
int call_hook;
|
|||
|
@@ -905,7 +904,7 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
|
|||
|
#endif
|
|||
|
if (*dirname == '\0' && call_hook)
|
|||
|
{
|
|||
|
- if (hook (ctxt.filename, &info))
|
|||
|
+ if (hook (ctxt.filename, &info, hook_data))
|
|||
|
break;
|
|||
|
else
|
|||
|
continue;
|
|||
|
@@ -926,7 +925,7 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
|
|||
|
data->cur_cluster_num = ~0U;
|
|||
|
|
|||
|
if (call_hook)
|
|||
|
- hook (ctxt.filename, &info);
|
|||
|
+ hook (ctxt.filename, &info, hook_data);
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
@@ -946,9 +945,8 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
|
|||
|
}
|
|||
|
|
|||
|
static grub_err_t
|
|||
|
-grub_fat_dir (grub_device_t device, const char *path,
|
|||
|
- int (*hook) (const char *filename,
|
|||
|
- const struct grub_dirhook_info *info))
|
|||
|
+grub_fat_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook,
|
|||
|
+ void *hook_data)
|
|||
|
{
|
|||
|
struct grub_fat_data *data = 0;
|
|||
|
grub_disk_t disk = device->disk;
|
|||
|
@@ -976,7 +974,7 @@ grub_fat_dir (grub_device_t device, const char *path,
|
|||
|
|
|||
|
do
|
|||
|
{
|
|||
|
- p = grub_fat_find_dir (disk, data, p, path, hook);
|
|||
|
+ p = grub_fat_find_dir (disk, data, p, path, hook, hook_data);
|
|||
|
}
|
|||
|
while (p && grub_errno == GRUB_ERR_NONE);
|
|||
|
|
|||
|
@@ -1004,7 +1002,7 @@ grub_fat_open (grub_file_t file, const char *name)
|
|||
|
|
|||
|
do
|
|||
|
{
|
|||
|
- p = grub_fat_find_dir (file->device->disk, data, p, name, 0);
|
|||
|
+ p = grub_fat_find_dir (file->device->disk, data, p, name, 0, 0);
|
|||
|
if (grub_errno != GRUB_ERR_NONE)
|
|||
|
goto fail;
|
|||
|
}
|
|||
|
diff --git a/grub-core/fs/fshelp.c b/grub-core/fs/fshelp.c
|
|||
|
index 21a72de..7e557c3 100644
|
|||
|
--- a/grub-core/fs/fshelp.c
|
|||
|
+++ b/grub-core/fs/fshelp.c
|
|||
|
@@ -27,199 +27,214 @@
|
|||
|
|
|||
|
GRUB_MOD_LICENSE ("GPLv3+");
|
|||
|
|
|||
|
-/* Lookup the node PATH. The node ROOTNODE describes the root of the
|
|||
|
- directory tree. The node found is returned in FOUNDNODE, which is
|
|||
|
- either a ROOTNODE or a new malloc'ed node. ITERATE_DIR is used to
|
|||
|
- iterate over all directory entries in the current node.
|
|||
|
- READ_SYMLINK is used to read the symlink if a node is a symlink.
|
|||
|
- EXPECTTYPE is the type node that is expected by the called, an
|
|||
|
- error is generated if the node is not of the expected type. Make
|
|||
|
- sure you use the NESTED_FUNC_ATTR macro for HOOK, this is required
|
|||
|
- because GCC has a nasty bug when using regparm=3. */
|
|||
|
-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)
|
|||
|
+typedef int (*iterate_dir_func) (grub_fshelp_node_t dir,
|
|||
|
+ grub_fshelp_iterate_dir_hook_t hook,
|
|||
|
+ void *data);
|
|||
|
+typedef char *(*read_symlink_func) (grub_fshelp_node_t node);
|
|||
|
+
|
|||
|
+/* Context for grub_fshelp_find_file. */
|
|||
|
+struct grub_fshelp_find_file_ctx
|
|||
|
{
|
|||
|
- grub_err_t err;
|
|||
|
- enum grub_fshelp_filetype foundtype = GRUB_FSHELP_DIR;
|
|||
|
- int symlinknest = 0;
|
|||
|
+ const char *path;
|
|||
|
+ grub_fshelp_node_t rootnode, currroot, currnode, oldnode;
|
|||
|
+ enum grub_fshelp_filetype foundtype;
|
|||
|
+ int symlinknest;
|
|||
|
+ char *name;
|
|||
|
+ enum grub_fshelp_filetype type;
|
|||
|
+};
|
|||
|
+
|
|||
|
+/* Helper for find_file_iter. */
|
|||
|
+static void
|
|||
|
+free_node (grub_fshelp_node_t node, struct grub_fshelp_find_file_ctx *ctx)
|
|||
|
+{
|
|||
|
+ if (node != ctx->rootnode && node != ctx->currroot)
|
|||
|
+ grub_free (node);
|
|||
|
+}
|
|||
|
|
|||
|
- auto grub_err_t NESTED_FUNC_ATTR find_file (const char *currpath,
|
|||
|
- grub_fshelp_node_t currroot,
|
|||
|
- grub_fshelp_node_t *currfound);
|
|||
|
+/* 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;
|
|||
|
|
|||
|
- grub_err_t NESTED_FUNC_ATTR find_file (const char *currpath,
|
|||
|
- grub_fshelp_node_t currroot,
|
|||
|
- grub_fshelp_node_t *currfound)
|
|||
|
+ if (filetype == GRUB_FSHELP_UNKNOWN ||
|
|||
|
+ (grub_strcmp (ctx->name, filename) &&
|
|||
|
+ (! (filetype & GRUB_FSHELP_CASE_INSENSITIVE) ||
|
|||
|
+ grub_strcasecmp (ctx->name, filename))))
|
|||
|
{
|
|||
|
- 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;
|
|||
|
+ grub_free (node);
|
|||
|
+ return 0;
|
|||
|
+ }
|
|||
|
|
|||
|
- auto int NESTED_FUNC_ATTR iterate (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node);
|
|||
|
+ /* The node is found, stop iterating over the nodes. */
|
|||
|
+ ctx->type = filetype & ~GRUB_FSHELP_CASE_INSENSITIVE;
|
|||
|
+ ctx->oldnode = ctx->currnode;
|
|||
|
+ ctx->currnode = node;
|
|||
|
|
|||
|
- auto void free_node (grub_fshelp_node_t node);
|
|||
|
+ return 1;
|
|||
|
+}
|
|||
|
|
|||
|
- void free_node (grub_fshelp_node_t node)
|
|||
|
- {
|
|||
|
- if (node != rootnode && node != currroot)
|
|||
|
- grub_free (node);
|
|||
|
- }
|
|||
|
+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;
|
|||
|
|
|||
|
- int NESTED_FUNC_ATTR iterate (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node)
|
|||
|
- {
|
|||
|
- if (filetype == GRUB_FSHELP_UNKNOWN ||
|
|||
|
- (grub_strcmp (name, filename) &&
|
|||
|
- (! (filetype & GRUB_FSHELP_CASE_INSENSITIVE) ||
|
|||
|
- grub_strcasecmp (name, filename))))
|
|||
|
- {
|
|||
|
- grub_free (node);
|
|||
|
- return 0;
|
|||
|
- }
|
|||
|
+ ctx->currroot = currroot;
|
|||
|
+ ctx->name = fpath;
|
|||
|
+ ctx->type = GRUB_FSHELP_DIR;
|
|||
|
+ ctx->currnode = currroot;
|
|||
|
+ ctx->oldnode = currroot;
|
|||
|
|
|||
|
- /* The node is found, stop iterating over the nodes. */
|
|||
|
- type = filetype & ~GRUB_FSHELP_CASE_INSENSITIVE;
|
|||
|
- oldnode = currnode;
|
|||
|
- currnode = node;
|
|||
|
+ grub_strncpy (fpath, currpath, grub_strlen (currpath) + 1);
|
|||
|
|
|||
|
- return 1;
|
|||
|
- }
|
|||
|
+ /* Remove all leading slashes. */
|
|||
|
+ while (*ctx->name == '/')
|
|||
|
+ ctx->name++;
|
|||
|
|
|||
|
- grub_strncpy (fpath, currpath, grub_strlen (currpath) + 1);
|
|||
|
+ if (! *ctx->name)
|
|||
|
+ {
|
|||
|
+ *currfound = ctx->currnode;
|
|||
|
+ return 0;
|
|||
|
+ }
|
|||
|
|
|||
|
- /* Remove all leading slashes. */
|
|||
|
- while (*name == '/')
|
|||
|
- name++;
|
|||
|
+ for (;;)
|
|||
|
+ {
|
|||
|
+ int found;
|
|||
|
|
|||
|
- if (! *name)
|
|||
|
+ /* Extract the actual part from the pathname. */
|
|||
|
+ next = grub_strchr (ctx->name, '/');
|
|||
|
+ if (next)
|
|||
|
{
|
|||
|
- *currfound = currnode;
|
|||
|
- return 0;
|
|||
|
+ /* Remove all leading slashes. */
|
|||
|
+ while (*next == '/')
|
|||
|
+ *(next++) = '\0';
|
|||
|
}
|
|||
|
|
|||
|
- for (;;)
|
|||
|
+ /* At this point it is expected that the current node is a
|
|||
|
+ directory, check if this is true. */
|
|||
|
+ if (ctx->type != GRUB_FSHELP_DIR)
|
|||
|
{
|
|||
|
- int found;
|
|||
|
+ free_node (ctx->currnode, ctx);
|
|||
|
+ ctx->currnode = 0;
|
|||
|
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
|
|||
|
+ }
|
|||
|
|
|||
|
- /* Extract the actual part from the pathname. */
|
|||
|
- next = grub_strchr (name, '/');
|
|||
|
- if (next)
|
|||
|
- {
|
|||
|
- /* Remove all leading slashes. */
|
|||
|
- while (*next == '/')
|
|||
|
- *(next++) = '\0';
|
|||
|
- }
|
|||
|
+ /* Iterate over the directory. */
|
|||
|
+ found = iterate_dir (ctx->currnode, find_file_iter, ctx);
|
|||
|
+ if (! found)
|
|||
|
+ {
|
|||
|
+ free_node (ctx->currnode, ctx);
|
|||
|
+ ctx->currnode = 0;
|
|||
|
+ if (grub_errno)
|
|||
|
+ return grub_errno;
|
|||
|
+
|
|||
|
+ break;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /* Read in the symlink and follow it. */
|
|||
|
+ if (ctx->type == GRUB_FSHELP_SYMLINK)
|
|||
|
+ {
|
|||
|
+ char *symlink;
|
|||
|
|
|||
|
- /* At this point it is expected that the current node is a
|
|||
|
- directory, check if this is true. */
|
|||
|
- if (type != GRUB_FSHELP_DIR)
|
|||
|
+ /* Test if the symlink does not loop. */
|
|||
|
+ if (++ctx->symlinknest == 8)
|
|||
|
{
|
|||
|
- free_node (currnode);
|
|||
|
- currnode = 0;
|
|||
|
- return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
|
|||
|
+ free_node (ctx->currnode, ctx);
|
|||
|
+ free_node (ctx->oldnode, ctx);
|
|||
|
+ ctx->currnode = 0;
|
|||
|
+ return grub_error (GRUB_ERR_SYMLINK_LOOP,
|
|||
|
+ N_("too deep nesting of symlinks"));
|
|||
|
}
|
|||
|
|
|||
|
- /* Iterate over the directory. */
|
|||
|
- found = iterate_dir (currnode, iterate);
|
|||
|
- if (! found)
|
|||
|
- {
|
|||
|
- free_node (currnode);
|
|||
|
- currnode = 0;
|
|||
|
- if (grub_errno)
|
|||
|
- return grub_errno;
|
|||
|
+ symlink = read_symlink (ctx->currnode);
|
|||
|
+ free_node (ctx->currnode, ctx);
|
|||
|
+ ctx->currnode = 0;
|
|||
|
|
|||
|
- break;
|
|||
|
+ if (!symlink)
|
|||
|
+ {
|
|||
|
+ free_node (ctx->oldnode, ctx);
|
|||
|
+ return grub_errno;
|
|||
|
}
|
|||
|
|
|||
|
- /* Read in the symlink and follow it. */
|
|||
|
- if (type == GRUB_FSHELP_SYMLINK)
|
|||
|
+ /* The symlink is an absolute path, go back to the root inode. */
|
|||
|
+ if (symlink[0] == '/')
|
|||
|
{
|
|||
|
- char *symlink;
|
|||
|
-
|
|||
|
- /* Test if the symlink does not loop. */
|
|||
|
- if (++symlinknest == 8)
|
|||
|
- {
|
|||
|
- free_node (currnode);
|
|||
|
- free_node (oldnode);
|
|||
|
- currnode = 0;
|
|||
|
- return grub_error (GRUB_ERR_SYMLINK_LOOP,
|
|||
|
- N_("too deep nesting of symlinks"));
|
|||
|
- }
|
|||
|
-
|
|||
|
- symlink = read_symlink (currnode);
|
|||
|
- free_node (currnode);
|
|||
|
- currnode = 0;
|
|||
|
-
|
|||
|
- if (!symlink)
|
|||
|
- {
|
|||
|
- free_node (oldnode);
|
|||
|
- return grub_errno;
|
|||
|
- }
|
|||
|
-
|
|||
|
- /* The symlink is an absolute path, go back to the root inode. */
|
|||
|
- if (symlink[0] == '/')
|
|||
|
- {
|
|||
|
- free_node (oldnode);
|
|||
|
- oldnode = rootnode;
|
|||
|
- }
|
|||
|
-
|
|||
|
- /* Lookup the node the symlink points to. */
|
|||
|
- find_file (symlink, oldnode, &currnode);
|
|||
|
- type = foundtype;
|
|||
|
- grub_free (symlink);
|
|||
|
-
|
|||
|
- if (grub_errno)
|
|||
|
- {
|
|||
|
- free_node (oldnode);
|
|||
|
- return grub_errno;
|
|||
|
- }
|
|||
|
+ free_node (ctx->oldnode, ctx);
|
|||
|
+ ctx->oldnode = ctx->rootnode;
|
|||
|
}
|
|||
|
|
|||
|
- if (oldnode != currnode)
|
|||
|
- free_node (oldnode);
|
|||
|
+ /* Lookup the node the symlink points to. */
|
|||
|
+ find_file (symlink, ctx->oldnode, &ctx->currnode,
|
|||
|
+ iterate_dir, read_symlink, ctx);
|
|||
|
+ ctx->type = ctx->foundtype;
|
|||
|
+ grub_free (symlink);
|
|||
|
|
|||
|
- /* Found the node! */
|
|||
|
- if (! next || *next == '\0')
|
|||
|
+ if (grub_errno)
|
|||
|
{
|
|||
|
- *currfound = currnode;
|
|||
|
- foundtype = type;
|
|||
|
- return 0;
|
|||
|
+ free_node (ctx->oldnode, ctx);
|
|||
|
+ return grub_errno;
|
|||
|
}
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ if (ctx->oldnode != ctx->currnode)
|
|||
|
+ free_node (ctx->oldnode, ctx);
|
|||
|
|
|||
|
- name = next;
|
|||
|
+ /* Found the node! */
|
|||
|
+ if (! next || *next == '\0')
|
|||
|
+ {
|
|||
|
+ *currfound = ctx->currnode;
|
|||
|
+ ctx->foundtype = ctx->type;
|
|||
|
+ return 0;
|
|||
|
}
|
|||
|
|
|||
|
- return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path);
|
|||
|
+ ctx->name = next;
|
|||
|
}
|
|||
|
|
|||
|
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"),
|
|||
|
+ ctx->path);
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* Lookup the node PATH. The node ROOTNODE describes the root of the
|
|||
|
+ directory tree. The node found is returned in FOUNDNODE, which is
|
|||
|
+ either a ROOTNODE or a new malloc'ed node. ITERATE_DIR is used to
|
|||
|
+ iterate over all directory entries in the current node.
|
|||
|
+ READ_SYMLINK is used to read the symlink if a node is a symlink.
|
|||
|
+ EXPECTTYPE is the type node that is expected by the called, an
|
|||
|
+ error is generated if the node is not of the expected type. */
|
|||
|
+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] != '/')
|
|||
|
{
|
|||
|
grub_error (GRUB_ERR_BAD_FILENAME, N_("invalid file name `%s'"), path);
|
|||
|
return grub_errno;
|
|||
|
}
|
|||
|
|
|||
|
- err = find_file (path, rootnode, foundnode);
|
|||
|
+ err = find_file (path, rootnode, foundnode, iterate_dir, read_symlink, &ctx);
|
|||
|
if (err)
|
|||
|
return err;
|
|||
|
|
|||
|
/* Check if the node that was found was of the expected type. */
|
|||
|
- if (expecttype == GRUB_FSHELP_REG && foundtype != expecttype)
|
|||
|
+ if (expecttype == GRUB_FSHELP_REG && ctx.foundtype != expecttype)
|
|||
|
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file"));
|
|||
|
- else if (expecttype == GRUB_FSHELP_DIR && foundtype != expecttype)
|
|||
|
+ else if (expecttype == GRUB_FSHELP_DIR && ctx.foundtype != expecttype)
|
|||
|
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
|
|||
|
|
|||
|
return 0;
|
|||
|
diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c
|
|||
|
index 0a249cc..9ed3330 100644
|
|||
|
--- a/grub-core/fs/hfs.c
|
|||
|
+++ b/grub-core/fs/hfs.c
|
|||
|
@@ -1151,9 +1151,8 @@ grub_hfs_find_dir (struct grub_hfs_data *data, const char *path,
|
|||
|
|
|||
|
|
|||
|
static grub_err_t
|
|||
|
-grub_hfs_dir (grub_device_t device, const char *path,
|
|||
|
- int (*hook) (const char *filename,
|
|||
|
- const struct grub_dirhook_info *info))
|
|||
|
+grub_hfs_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook,
|
|||
|
+ void *hook_data)
|
|||
|
{
|
|||
|
int inode;
|
|||
|
|
|||
|
@@ -1184,14 +1183,14 @@ grub_hfs_dir (grub_device_t device, const char *path,
|
|||
|
info.dir = 1;
|
|||
|
info.mtimeset = 1;
|
|||
|
info.mtime = grub_be_to_cpu32 (drec->mtime) - 2082844800;
|
|||
|
- return hook (fname, &info);
|
|||
|
+ return hook (fname, &info, hook_data);
|
|||
|
}
|
|||
|
if (frec->type == GRUB_HFS_FILETYPE_FILE)
|
|||
|
{
|
|||
|
info.dir = 0;
|
|||
|
info.mtimeset = 1;
|
|||
|
info.mtime = grub_be_to_cpu32 (frec->mtime) - 2082844800;
|
|||
|
- return hook (fname, &info);
|
|||
|
+ return hook (fname, &info, hook_data);
|
|||
|
}
|
|||
|
|
|||
|
return 0;
|
|||
|
diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c
|
|||
|
index 9812464..dcca581 100644
|
|||
|
--- a/grub-core/fs/hfsplus.c
|
|||
|
+++ b/grub-core/fs/hfsplus.c
|
|||
|
@@ -766,10 +766,7 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree,
|
|||
|
|
|||
|
static int
|
|||
|
grub_hfsplus_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
- int NESTED_FUNC_ATTR
|
|||
|
- (*hook) (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node))
|
|||
|
+ grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
|
|||
|
{
|
|||
|
int ret = 0;
|
|||
|
|
|||
|
@@ -825,7 +822,7 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
node->size = 0;
|
|||
|
node->fileid = grub_be_to_cpu32 (fileinfo->parentid);
|
|||
|
|
|||
|
- ret = hook ("..", GRUB_FSHELP_DIR, node);
|
|||
|
+ ret = hook ("..", GRUB_FSHELP_DIR, node, hook_data);
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
@@ -878,7 +875,7 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
node->size = grub_be_to_cpu64 (fileinfo->data.size);
|
|||
|
node->fileid = grub_be_to_cpu32 (fileinfo->fileid);
|
|||
|
|
|||
|
- ret = hook (filename, type, node);
|
|||
|
+ ret = hook (filename, type, node, hook_data);
|
|||
|
|
|||
|
grub_free (filename);
|
|||
|
|
|||
|
@@ -895,7 +892,7 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
if (!fsnode)
|
|||
|
return 1;
|
|||
|
*fsnode = *dir;
|
|||
|
- if (hook (".", GRUB_FSHELP_DIR, fsnode))
|
|||
|
+ if (hook (".", GRUB_FSHELP_DIR, fsnode, hook_data))
|
|||
|
return 1;
|
|||
|
}
|
|||
|
|
|||
|
@@ -978,32 +975,39 @@ grub_hfsplus_read (grub_file_t file, char *buf, grub_size_t len)
|
|||
|
file->offset, len, buf);
|
|||
|
}
|
|||
|
|
|||
|
+/* Context for grub_hfsplus_dir. */
|
|||
|
+struct grub_hfsplus_dir_ctx
|
|||
|
+{
|
|||
|
+ grub_fs_dir_hook_t hook;
|
|||
|
+ void *hook_data;
|
|||
|
+};
|
|||
|
+
|
|||
|
+/* Helper for grub_hfsplus_dir. */
|
|||
|
+static int
|
|||
|
+grub_hfsplus_dir_iter (const char *filename,
|
|||
|
+ enum grub_fshelp_filetype filetype,
|
|||
|
+ grub_fshelp_node_t node, void *data)
|
|||
|
+{
|
|||
|
+ struct grub_hfsplus_dir_ctx *ctx = data;
|
|||
|
+ struct grub_dirhook_info info;
|
|||
|
+
|
|||
|
+ grub_memset (&info, 0, sizeof (info));
|
|||
|
+ info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
|||
|
+ info.mtimeset = 1;
|
|||
|
+ info.mtime = node->mtime;
|
|||
|
+ info.case_insensitive = !! (filetype & GRUB_FSHELP_CASE_INSENSITIVE);
|
|||
|
+ grub_free (node);
|
|||
|
+ return ctx->hook (filename, &info, ctx->hook_data);
|
|||
|
+}
|
|||
|
+
|
|||
|
static grub_err_t
|
|||
|
grub_hfsplus_dir (grub_device_t device, const char *path,
|
|||
|
- int (*hook) (const char *filename,
|
|||
|
- const struct grub_dirhook_info *info))
|
|||
|
+ grub_fs_dir_hook_t hook, void *hook_data)
|
|||
|
{
|
|||
|
+ struct grub_hfsplus_dir_ctx ctx = { hook, hook_data };
|
|||
|
struct grub_hfsplus_data *data = 0;
|
|||
|
struct grub_fshelp_node *fdiro = 0;
|
|||
|
|
|||
|
- auto int NESTED_FUNC_ATTR iterate (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node);
|
|||
|
-
|
|||
|
- int NESTED_FUNC_ATTR iterate (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node)
|
|||
|
- {
|
|||
|
- struct grub_dirhook_info info;
|
|||
|
- grub_memset (&info, 0, sizeof (info));
|
|||
|
- info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
|||
|
- info.mtimeset = 1;
|
|||
|
- info.mtime = node->mtime;
|
|||
|
- info.case_insensitive = !! (filetype & GRUB_FSHELP_CASE_INSENSITIVE);
|
|||
|
- grub_free (node);
|
|||
|
- return hook (filename, &info);
|
|||
|
- }
|
|||
|
-
|
|||
|
grub_dl_ref (my_mod);
|
|||
|
|
|||
|
data = grub_hfsplus_mount (device->disk);
|
|||
|
@@ -1018,7 +1022,7 @@ grub_hfsplus_dir (grub_device_t device, const char *path,
|
|||
|
goto fail;
|
|||
|
|
|||
|
/* Iterate over all entries in this directory. */
|
|||
|
- grub_hfsplus_iterate_dir (fdiro, iterate);
|
|||
|
+ grub_hfsplus_iterate_dir (fdiro, grub_hfsplus_dir_iter, &ctx);
|
|||
|
|
|||
|
fail:
|
|||
|
if (data && fdiro != &data->dirroot)
|
|||
|
diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c
|
|||
|
index 547e156..e37553d 100644
|
|||
|
--- a/grub-core/fs/iso9660.c
|
|||
|
+++ b/grub-core/fs/iso9660.c
|
|||
|
@@ -521,10 +521,7 @@ get_node_size (grub_fshelp_node_t node)
|
|||
|
|
|||
|
static int
|
|||
|
grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
- int NESTED_FUNC_ATTR
|
|||
|
- (*hook) (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node))
|
|||
|
+ grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
|
|||
|
{
|
|||
|
struct grub_iso9660_dir dirent;
|
|||
|
grub_off_t offset = 0;
|
|||
|
@@ -828,7 +825,7 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
symlink = 0;
|
|||
|
was_continue = 0;
|
|||
|
}
|
|||
|
- if (hook (filename, type, node))
|
|||
|
+ if (hook (filename, type, node, hook_data))
|
|||
|
{
|
|||
|
if (filename_alloc)
|
|||
|
grub_free (filename);
|
|||
|
@@ -844,32 +841,39 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
|
|||
|
|
|||
|
|
|||
|
+/* Context for grub_iso9660_dir. */
|
|||
|
+struct grub_iso9660_dir_ctx
|
|||
|
+{
|
|||
|
+ grub_fs_dir_hook_t hook;
|
|||
|
+ void *hook_data;
|
|||
|
+};
|
|||
|
+
|
|||
|
+/* Helper for grub_iso9660_dir. */
|
|||
|
+static int
|
|||
|
+grub_iso9660_dir_iter (const char *filename,
|
|||
|
+ enum grub_fshelp_filetype filetype,
|
|||
|
+ grub_fshelp_node_t node, void *data)
|
|||
|
+{
|
|||
|
+ struct grub_iso9660_dir_ctx *ctx = data;
|
|||
|
+ struct grub_dirhook_info info;
|
|||
|
+
|
|||
|
+ grub_memset (&info, 0, sizeof (info));
|
|||
|
+ info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
|||
|
+ info.mtimeset = !!iso9660_to_unixtime2 (&node->dirents[0].mtime, &info.mtime);
|
|||
|
+
|
|||
|
+ grub_free (node);
|
|||
|
+ return ctx->hook (filename, &info, ctx->hook_data);
|
|||
|
+}
|
|||
|
+
|
|||
|
static grub_err_t
|
|||
|
grub_iso9660_dir (grub_device_t device, const char *path,
|
|||
|
- int (*hook) (const char *filename,
|
|||
|
- const struct grub_dirhook_info *info))
|
|||
|
+ grub_fs_dir_hook_t hook, void *hook_data)
|
|||
|
{
|
|||
|
+ struct grub_iso9660_dir_ctx ctx = { hook, hook_data };
|
|||
|
struct grub_iso9660_data *data = 0;
|
|||
|
struct grub_fshelp_node rootnode;
|
|||
|
struct grub_fshelp_node *foundnode;
|
|||
|
|
|||
|
- auto int NESTED_FUNC_ATTR iterate (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node);
|
|||
|
-
|
|||
|
- int NESTED_FUNC_ATTR iterate (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node)
|
|||
|
- {
|
|||
|
- struct grub_dirhook_info info;
|
|||
|
- grub_memset (&info, 0, sizeof (info));
|
|||
|
- info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
|||
|
- info.mtimeset = !!iso9660_to_unixtime2 (&node->dirents[0].mtime, &info.mtime);
|
|||
|
-
|
|||
|
- grub_free (node);
|
|||
|
- return hook (filename, &info);
|
|||
|
- }
|
|||
|
-
|
|||
|
grub_dl_ref (my_mod);
|
|||
|
|
|||
|
data = grub_iso9660_mount (device->disk);
|
|||
|
@@ -891,7 +895,7 @@ grub_iso9660_dir (grub_device_t device, const char *path,
|
|||
|
goto fail;
|
|||
|
|
|||
|
/* List the files in the directory. */
|
|||
|
- grub_iso9660_iterate_dir (foundnode, iterate);
|
|||
|
+ grub_iso9660_iterate_dir (foundnode, grub_iso9660_dir_iter, &ctx);
|
|||
|
|
|||
|
if (foundnode != &rootnode)
|
|||
|
grub_free (foundnode);
|
|||
|
diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c
|
|||
|
index b98a5a3..7c17192 100644
|
|||
|
--- a/grub-core/fs/jfs.c
|
|||
|
+++ b/grub-core/fs/jfs.c
|
|||
|
@@ -799,8 +799,7 @@ grub_jfs_lookup_symlink (struct grub_jfs_data *data, grub_uint32_t ino)
|
|||
|
|
|||
|
static grub_err_t
|
|||
|
grub_jfs_dir (grub_device_t device, const char *path,
|
|||
|
- int (*hook) (const char *filename,
|
|||
|
- const struct grub_dirhook_info *info))
|
|||
|
+ grub_fs_dir_hook_t hook, void *hook_data)
|
|||
|
{
|
|||
|
struct grub_jfs_data *data = 0;
|
|||
|
struct grub_jfs_diropen *diro = 0;
|
|||
|
@@ -832,7 +831,7 @@ grub_jfs_dir (grub_device_t device, const char *path,
|
|||
|
& GRUB_JFS_FILETYPE_MASK) == GRUB_JFS_FILETYPE_DIR;
|
|||
|
info.mtimeset = 1;
|
|||
|
info.mtime = grub_le_to_cpu32 (inode.mtime.sec);
|
|||
|
- if (hook (diro->name, &info))
|
|||
|
+ if (hook (diro->name, &info, hook_data))
|
|||
|
goto fail;
|
|||
|
}
|
|||
|
|
|||
|
diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c
|
|||
|
index a622533..9655211 100644
|
|||
|
--- a/grub-core/fs/minix.c
|
|||
|
+++ b/grub-core/fs/minix.c
|
|||
|
@@ -536,8 +536,7 @@ grub_minix_mount (grub_disk_t disk)
|
|||
|
|
|||
|
static grub_err_t
|
|||
|
grub_minix_dir (grub_device_t device, const char *path,
|
|||
|
- int (*hook) (const char *filename,
|
|||
|
- const struct grub_dirhook_info *info))
|
|||
|
+ grub_fs_dir_hook_t hook, void *hook_data)
|
|||
|
{
|
|||
|
struct grub_minix_data *data = 0;
|
|||
|
unsigned int pos = 0;
|
|||
|
@@ -590,7 +589,7 @@ grub_minix_dir (grub_device_t device, const char *path,
|
|||
|
info.mtimeset = 1;
|
|||
|
info.mtime = grub_minix_to_cpu32 (data->inode.mtime);
|
|||
|
|
|||
|
- if (hook (filename, &info) ? 1 : 0)
|
|||
|
+ if (hook (filename, &info, hook_data) ? 1 : 0)
|
|||
|
break;
|
|||
|
|
|||
|
/* Load the old inode back in. */
|
|||
|
diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c
|
|||
|
index 5b34486..9bd4444 100644
|
|||
|
--- a/grub-core/fs/nilfs2.c
|
|||
|
+++ b/grub-core/fs/nilfs2.c
|
|||
|
@@ -870,10 +870,7 @@ grub_nilfs2_read_symlink (grub_fshelp_node_t node)
|
|||
|
|
|||
|
static int
|
|||
|
grub_nilfs2_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
- int NESTED_FUNC_ATTR
|
|||
|
- (*hook) (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node))
|
|||
|
+ grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
|
|||
|
{
|
|||
|
grub_off_t fpos = 0;
|
|||
|
struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir;
|
|||
|
@@ -957,7 +954,7 @@ grub_nilfs2_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
type = GRUB_FSHELP_REG;
|
|||
|
}
|
|||
|
|
|||
|
- if (hook (filename, type, fdiro))
|
|||
|
+ if (hook (filename, type, fdiro, hook_data))
|
|||
|
return 1;
|
|||
|
}
|
|||
|
|
|||
|
@@ -1032,60 +1029,69 @@ grub_nilfs2_read (grub_file_t file, char *buf, grub_size_t len)
|
|||
|
file->offset, len, buf);
|
|||
|
}
|
|||
|
|
|||
|
+/* Context for grub_nilfs2_dir. */
|
|||
|
+struct grub_nilfs2_dir_ctx
|
|||
|
+{
|
|||
|
+ grub_fs_dir_hook_t hook;
|
|||
|
+ void *hook_data;
|
|||
|
+ struct grub_nilfs2_data *data;
|
|||
|
+};
|
|||
|
+
|
|||
|
+/* Helper for grub_nilfs2_dir. */
|
|||
|
+static int
|
|||
|
+grub_nilfs2_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
|
|||
|
+ grub_fshelp_node_t node, void *data)
|
|||
|
+{
|
|||
|
+ struct grub_nilfs2_dir_ctx *ctx = data;
|
|||
|
+ struct grub_dirhook_info info;
|
|||
|
+
|
|||
|
+ grub_memset (&info, 0, sizeof (info));
|
|||
|
+ if (!node->inode_read)
|
|||
|
+ {
|
|||
|
+ grub_nilfs2_read_inode (ctx->data, node->ino, &node->inode);
|
|||
|
+ if (!grub_errno)
|
|||
|
+ node->inode_read = 1;
|
|||
|
+ grub_errno = GRUB_ERR_NONE;
|
|||
|
+ }
|
|||
|
+ if (node->inode_read)
|
|||
|
+ {
|
|||
|
+ info.mtimeset = 1;
|
|||
|
+ info.mtime = grub_le_to_cpu64 (node->inode.i_mtime);
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
|||
|
+ grub_free (node);
|
|||
|
+ return ctx->hook (filename, &info, ctx->hook_data);
|
|||
|
+}
|
|||
|
+
|
|||
|
static grub_err_t
|
|||
|
grub_nilfs2_dir (grub_device_t device, const char *path,
|
|||
|
- int (*hook) (const char *filename,
|
|||
|
- const struct grub_dirhook_info * info))
|
|||
|
+ grub_fs_dir_hook_t hook, void *hook_data)
|
|||
|
{
|
|||
|
- struct grub_nilfs2_data *data = 0;
|
|||
|
+ struct grub_nilfs2_dir_ctx ctx = {
|
|||
|
+ .hook = hook,
|
|||
|
+ .hook_data = hook_data
|
|||
|
+ };
|
|||
|
struct grub_fshelp_node *fdiro = 0;
|
|||
|
|
|||
|
- auto int NESTED_FUNC_ATTR iterate (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node);
|
|||
|
-
|
|||
|
- int NESTED_FUNC_ATTR iterate (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node)
|
|||
|
- {
|
|||
|
- struct grub_dirhook_info info;
|
|||
|
- grub_memset (&info, 0, sizeof (info));
|
|||
|
- if (!node->inode_read)
|
|||
|
- {
|
|||
|
- grub_nilfs2_read_inode (data, node->ino, &node->inode);
|
|||
|
- if (!grub_errno)
|
|||
|
- node->inode_read = 1;
|
|||
|
- grub_errno = GRUB_ERR_NONE;
|
|||
|
- }
|
|||
|
- if (node->inode_read)
|
|||
|
- {
|
|||
|
- info.mtimeset = 1;
|
|||
|
- info.mtime = grub_le_to_cpu64 (node->inode.i_mtime);
|
|||
|
- }
|
|||
|
-
|
|||
|
- info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
|||
|
- grub_free (node);
|
|||
|
- return hook (filename, &info);
|
|||
|
- }
|
|||
|
-
|
|||
|
grub_dl_ref (my_mod);
|
|||
|
|
|||
|
- data = grub_nilfs2_mount (device->disk);
|
|||
|
- if (!data)
|
|||
|
+ ctx.data = grub_nilfs2_mount (device->disk);
|
|||
|
+ if (!ctx.data)
|
|||
|
goto fail;
|
|||
|
|
|||
|
- grub_fshelp_find_file (path, &data->diropen, &fdiro,
|
|||
|
+ grub_fshelp_find_file (path, &ctx.data->diropen, &fdiro,
|
|||
|
grub_nilfs2_iterate_dir, grub_nilfs2_read_symlink,
|
|||
|
GRUB_FSHELP_DIR);
|
|||
|
if (grub_errno)
|
|||
|
goto fail;
|
|||
|
|
|||
|
- grub_nilfs2_iterate_dir (fdiro, iterate);
|
|||
|
+ grub_nilfs2_iterate_dir (fdiro, grub_nilfs2_dir_iter, &ctx);
|
|||
|
|
|||
|
fail:
|
|||
|
- if (fdiro != &data->diropen)
|
|||
|
+ if (fdiro != &ctx.data->diropen)
|
|||
|
grub_free (fdiro);
|
|||
|
- grub_free (data);
|
|||
|
+ grub_free (ctx.data);
|
|||
|
|
|||
|
grub_dl_unref (my_mod);
|
|||
|
|
|||
|
diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
|
|||
|
index e7861d8..7ac46f9 100644
|
|||
|
--- a/grub-core/fs/ntfs.c
|
|||
|
+++ b/grub-core/fs/ntfs.c
|
|||
|
@@ -600,10 +600,7 @@ free_file (struct grub_ntfs_file *mft)
|
|||
|
|
|||
|
static int
|
|||
|
list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos,
|
|||
|
- int NESTED_FUNC_ATTR
|
|||
|
- (*hook) (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node))
|
|||
|
+ grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
|
|||
|
{
|
|||
|
grub_uint8_t *np;
|
|||
|
int ns;
|
|||
|
@@ -667,7 +664,7 @@ list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos,
|
|||
|
if (namespace)
|
|||
|
type |= GRUB_FSHELP_CASE_INSENSITIVE;
|
|||
|
|
|||
|
- if (hook (ustr, type, fdiro))
|
|||
|
+ if (hook (ustr, type, fdiro, hook_data))
|
|||
|
{
|
|||
|
grub_free (ustr);
|
|||
|
return 1;
|
|||
|
@@ -778,10 +775,7 @@ grub_ntfs_read_symlink (grub_fshelp_node_t node)
|
|||
|
|
|||
|
static int
|
|||
|
grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
- int NESTED_FUNC_ATTR
|
|||
|
- (*hook) (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node))
|
|||
|
+ grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
|
|||
|
{
|
|||
|
grub_uint8_t *bitmap;
|
|||
|
struct grub_ntfs_attr attr, *at;
|
|||
|
@@ -824,7 +818,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
}
|
|||
|
|
|||
|
cur_pos += 0x10; /* Skip index root */
|
|||
|
- ret = list_file (mft, cur_pos + u16at (cur_pos, 0), hook);
|
|||
|
+ ret = list_file (mft, cur_pos + u16at (cur_pos, 0), hook, hook_data);
|
|||
|
if (ret)
|
|||
|
goto done;
|
|||
|
|
|||
|
@@ -909,7 +903,8 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
|| (fixup (indx, mft->data->idx_size,
|
|||
|
(const grub_uint8_t *) "INDX")))
|
|||
|
goto done;
|
|||
|
- ret = list_file (mft, &indx[0x18 + u16at (indx, 0x18)], hook);
|
|||
|
+ ret = list_file (mft, &indx[0x18 + u16at (indx, 0x18)],
|
|||
|
+ hook, hook_data);
|
|||
|
if (ret)
|
|||
|
goto done;
|
|||
|
}
|
|||
|
@@ -1017,33 +1012,39 @@ fail:
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
+/* Context for grub_ntfs_dir. */
|
|||
|
+struct grub_ntfs_dir_ctx
|
|||
|
+{
|
|||
|
+ grub_fs_dir_hook_t hook;
|
|||
|
+ void *hook_data;
|
|||
|
+};
|
|||
|
+
|
|||
|
+/* Helper for grub_ntfs_dir. */
|
|||
|
+static int
|
|||
|
+grub_ntfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
|
|||
|
+ grub_fshelp_node_t node, void *data)
|
|||
|
+{
|
|||
|
+ struct grub_ntfs_dir_ctx *ctx = data;
|
|||
|
+ struct grub_dirhook_info info;
|
|||
|
+
|
|||
|
+ grub_memset (&info, 0, sizeof (info));
|
|||
|
+ info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
|||
|
+ info.mtimeset = 1;
|
|||
|
+ info.mtime = grub_divmod64 (node->mtime, 10000000, 0)
|
|||
|
+ - 86400ULL * 365 * (1970 - 1601)
|
|||
|
+ - 86400ULL * ((1970 - 1601) / 4) + 86400ULL * ((1970 - 1601) / 100);
|
|||
|
+ grub_free (node);
|
|||
|
+ return ctx->hook (filename, &info, ctx->hook_data);
|
|||
|
+}
|
|||
|
+
|
|||
|
static grub_err_t
|
|||
|
grub_ntfs_dir (grub_device_t device, const char *path,
|
|||
|
- int (*hook) (const char *filename,
|
|||
|
- const struct grub_dirhook_info *info))
|
|||
|
+ grub_fs_dir_hook_t hook, void *hook_data)
|
|||
|
{
|
|||
|
+ struct grub_ntfs_dir_ctx ctx = { hook, hook_data };
|
|||
|
struct grub_ntfs_data *data = 0;
|
|||
|
struct grub_fshelp_node *fdiro = 0;
|
|||
|
|
|||
|
- auto int NESTED_FUNC_ATTR iterate (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node);
|
|||
|
-
|
|||
|
- int NESTED_FUNC_ATTR iterate (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node)
|
|||
|
- {
|
|||
|
- struct grub_dirhook_info info;
|
|||
|
- grub_memset (&info, 0, sizeof (info));
|
|||
|
- info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
|||
|
- info.mtimeset = 1;
|
|||
|
- info.mtime = grub_divmod64 (node->mtime, 10000000, 0)
|
|||
|
- - 86400ULL * 365 * (1970 - 1601)
|
|||
|
- - 86400ULL * ((1970 - 1601) / 4) + 86400ULL * ((1970 - 1601) / 100);
|
|||
|
- grub_free (node);
|
|||
|
- return hook (filename, &info);
|
|||
|
- }
|
|||
|
-
|
|||
|
grub_dl_ref (my_mod);
|
|||
|
|
|||
|
data = grub_ntfs_mount (device->disk);
|
|||
|
@@ -1056,7 +1057,7 @@ grub_ntfs_dir (grub_device_t device, const char *path,
|
|||
|
if (grub_errno)
|
|||
|
goto fail;
|
|||
|
|
|||
|
- grub_ntfs_iterate_dir (fdiro, iterate);
|
|||
|
+ grub_ntfs_iterate_dir (fdiro, grub_ntfs_dir_iter, &ctx);
|
|||
|
|
|||
|
fail:
|
|||
|
if ((fdiro) && (fdiro != &data->cmft))
|
|||
|
diff --git a/grub-core/fs/reiserfs.c b/grub-core/fs/reiserfs.c
|
|||
|
index 26adf23..686e4da 100644
|
|||
|
--- a/grub-core/fs/reiserfs.c
|
|||
|
+++ b/grub-core/fs/reiserfs.c
|
|||
|
@@ -718,10 +718,8 @@ grub_reiserfs_mount (grub_disk_t disk)
|
|||
|
/* Call HOOK for each file in directory ITEM. */
|
|||
|
static int
|
|||
|
grub_reiserfs_iterate_dir (grub_fshelp_node_t item,
|
|||
|
- int NESTED_FUNC_ATTR
|
|||
|
- (*hook) (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node))
|
|||
|
+ grub_fshelp_iterate_dir_hook_t hook,
|
|||
|
+ void *hook_data)
|
|||
|
{
|
|||
|
struct grub_reiserfs_data *data = item->data;
|
|||
|
struct grub_reiserfs_block_header *block_header = 0;
|
|||
|
@@ -946,7 +944,7 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item,
|
|||
|
goto next;
|
|||
|
}
|
|||
|
}
|
|||
|
- if (hook (entry_name, entry_type, entry_item))
|
|||
|
+ if (hook (entry_name, entry_type, entry_item, hook_data))
|
|||
|
{
|
|||
|
grub_dprintf ("reiserfs", "Found : %s, type=%d\n",
|
|||
|
entry_name, entry_type);
|
|||
|
@@ -1254,32 +1252,40 @@ grub_reiserfs_close (grub_file_t file)
|
|||
|
return GRUB_ERR_NONE;
|
|||
|
}
|
|||
|
|
|||
|
+/* Context for grub_reiserfs_dir. */
|
|||
|
+struct grub_reiserfs_dir_ctx
|
|||
|
+{
|
|||
|
+ grub_fs_dir_hook_t hook;
|
|||
|
+ void *hook_data;
|
|||
|
+};
|
|||
|
+
|
|||
|
+/* Helper for grub_reiserfs_dir. */
|
|||
|
+static int
|
|||
|
+grub_reiserfs_dir_iter (const char *filename,
|
|||
|
+ enum grub_fshelp_filetype filetype,
|
|||
|
+ grub_fshelp_node_t node, void *data)
|
|||
|
+{
|
|||
|
+ struct grub_reiserfs_dir_ctx *ctx = data;
|
|||
|
+ struct grub_dirhook_info info;
|
|||
|
+
|
|||
|
+ grub_memset (&info, 0, sizeof (info));
|
|||
|
+ info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
|||
|
+ info.mtimeset = 1;
|
|||
|
+ info.mtime = node->mtime;
|
|||
|
+ grub_free (node);
|
|||
|
+ return ctx->hook (filename, &info, ctx->hook_data);
|
|||
|
+}
|
|||
|
+
|
|||
|
/* Call HOOK with each file under DIR. */
|
|||
|
static grub_err_t
|
|||
|
grub_reiserfs_dir (grub_device_t device, const char *path,
|
|||
|
- int (*hook) (const char *filename,
|
|||
|
- const struct grub_dirhook_info *info))
|
|||
|
+ grub_fs_dir_hook_t hook, void *hook_data)
|
|||
|
{
|
|||
|
+ struct grub_reiserfs_dir_ctx ctx = { hook, hook_data };
|
|||
|
struct grub_reiserfs_data *data = 0;
|
|||
|
struct grub_fshelp_node root, *found;
|
|||
|
struct grub_reiserfs_key root_key;
|
|||
|
|
|||
|
- auto int NESTED_FUNC_ATTR iterate (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node);
|
|||
|
-
|
|||
|
- int NESTED_FUNC_ATTR iterate (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node)
|
|||
|
- {
|
|||
|
- struct grub_dirhook_info info;
|
|||
|
- grub_memset (&info, 0, sizeof (info));
|
|||
|
- info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
|||
|
- info.mtimeset = 1;
|
|||
|
- info.mtime = node->mtime;
|
|||
|
- grub_free (node);
|
|||
|
- return hook (filename, &info);
|
|||
|
- }
|
|||
|
grub_dl_ref (my_mod);
|
|||
|
data = grub_reiserfs_mount (device->disk);
|
|||
|
if (! data)
|
|||
|
@@ -1300,7 +1306,7 @@ grub_reiserfs_dir (grub_device_t device, const char *path,
|
|||
|
grub_reiserfs_read_symlink, GRUB_FSHELP_DIR);
|
|||
|
if (grub_errno)
|
|||
|
goto fail;
|
|||
|
- grub_reiserfs_iterate_dir (found, iterate);
|
|||
|
+ grub_reiserfs_iterate_dir (found, grub_reiserfs_dir_iter, &ctx);
|
|||
|
grub_free (data);
|
|||
|
grub_dl_unref (my_mod);
|
|||
|
return GRUB_ERR_NONE;
|
|||
|
diff --git a/grub-core/fs/romfs.c b/grub-core/fs/romfs.c
|
|||
|
index b30caef..b79b1e1 100644
|
|||
|
--- a/grub-core/fs/romfs.c
|
|||
|
+++ b/grub-core/fs/romfs.c
|
|||
|
@@ -171,10 +171,7 @@ grub_romfs_read_symlink (grub_fshelp_node_t node)
|
|||
|
|
|||
|
static int
|
|||
|
grub_romfs_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
- int NESTED_FUNC_ATTR
|
|||
|
- (*hook) (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node))
|
|||
|
+ grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
|
|||
|
{
|
|||
|
grub_disk_addr_t caddr;
|
|||
|
struct grub_romfs_file_header hdr;
|
|||
|
@@ -306,7 +303,7 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
- if (hook ((char *) name, filetype, node))
|
|||
|
+ if (hook ((char *) name, filetype, node, hook_data))
|
|||
|
{
|
|||
|
grub_free (name);
|
|||
|
return 1;
|
|||
|
@@ -316,30 +313,36 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
+/* Context for grub_romfs_dir. */
|
|||
|
+struct grub_romfs_dir_ctx
|
|||
|
+{
|
|||
|
+ grub_fs_dir_hook_t hook;
|
|||
|
+ void *hook_data;
|
|||
|
+};
|
|||
|
+
|
|||
|
+/* Helper for grub_romfs_dir. */
|
|||
|
+static int
|
|||
|
+grub_romfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
|
|||
|
+ grub_fshelp_node_t node, void *data)
|
|||
|
+{
|
|||
|
+ struct grub_romfs_dir_ctx *ctx = data;
|
|||
|
+ struct grub_dirhook_info info;
|
|||
|
+
|
|||
|
+ grub_memset (&info, 0, sizeof (info));
|
|||
|
+
|
|||
|
+ info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
|||
|
+ grub_free (node);
|
|||
|
+ return ctx->hook (filename, &info, ctx->hook_data);
|
|||
|
+}
|
|||
|
+
|
|||
|
static grub_err_t
|
|||
|
grub_romfs_dir (grub_device_t device, const char *path,
|
|||
|
- int (*hook) (const char *filename,
|
|||
|
- const struct grub_dirhook_info *info))
|
|||
|
+ grub_fs_dir_hook_t hook, void *hook_data)
|
|||
|
{
|
|||
|
+ struct grub_romfs_dir_ctx ctx = { hook, hook_data };
|
|||
|
struct grub_romfs_data *data = 0;
|
|||
|
struct grub_fshelp_node *fdiro = 0, start;
|
|||
|
|
|||
|
- auto int NESTED_FUNC_ATTR iterate (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node);
|
|||
|
-
|
|||
|
- int NESTED_FUNC_ATTR iterate (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node)
|
|||
|
- {
|
|||
|
- struct grub_dirhook_info info;
|
|||
|
- grub_memset (&info, 0, sizeof (info));
|
|||
|
-
|
|||
|
- info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
|||
|
- grub_free (node);
|
|||
|
- return hook (filename, &info);
|
|||
|
- }
|
|||
|
-
|
|||
|
data = grub_romfs_mount (device);
|
|||
|
if (! data)
|
|||
|
goto fail;
|
|||
|
@@ -352,7 +355,7 @@ grub_romfs_dir (grub_device_t device, const char *path,
|
|||
|
if (grub_errno)
|
|||
|
goto fail;
|
|||
|
|
|||
|
- grub_romfs_iterate_dir (fdiro, iterate);
|
|||
|
+ grub_romfs_iterate_dir (fdiro, grub_romfs_dir_iter, &ctx);
|
|||
|
|
|||
|
fail:
|
|||
|
grub_free (data);
|
|||
|
diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c
|
|||
|
index f7cdb08..fed17d3 100644
|
|||
|
--- a/grub-core/fs/sfs.c
|
|||
|
+++ b/grub-core/fs/sfs.c
|
|||
|
@@ -460,12 +460,48 @@ grub_sfs_read_symlink (grub_fshelp_node_t node)
|
|||
|
return symlink;
|
|||
|
}
|
|||
|
|
|||
|
+/* Helper for grub_sfs_iterate_dir. */
|
|||
|
+static int
|
|||
|
+grub_sfs_create_node (struct grub_fshelp_node **node,
|
|||
|
+ struct grub_sfs_data *data,
|
|||
|
+ const char *name,
|
|||
|
+ grub_uint32_t block, grub_uint32_t size, int type,
|
|||
|
+ grub_uint32_t mtime,
|
|||
|
+ grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
|
|||
|
+{
|
|||
|
+ grub_size_t len = grub_strlen (name);
|
|||
|
+ grub_uint8_t *name_u8;
|
|||
|
+ int ret;
|
|||
|
+ *node = grub_malloc (sizeof (**node));
|
|||
|
+ if (!*node)
|
|||
|
+ return 1;
|
|||
|
+ name_u8 = grub_malloc (len * GRUB_MAX_UTF8_PER_LATIN1 + 1);
|
|||
|
+ if (!name_u8)
|
|||
|
+ {
|
|||
|
+ grub_free (*node);
|
|||
|
+ return 1;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ (*node)->data = data;
|
|||
|
+ (*node)->size = size;
|
|||
|
+ (*node)->block = block;
|
|||
|
+ (*node)->mtime = mtime;
|
|||
|
+ (*node)->cache = 0;
|
|||
|
+ (*node)->cache_off = 0;
|
|||
|
+ (*node)->next_extent = block;
|
|||
|
+ (*node)->cache_size = 0;
|
|||
|
+ (*node)->cache_allocated = 0;
|
|||
|
+
|
|||
|
+ *grub_latin1_to_utf8 (name_u8, (const grub_uint8_t *) name, len) = '\0';
|
|||
|
+
|
|||
|
+ ret = hook ((char *) name_u8, type | data->fshelp_flags, *node, hook_data);
|
|||
|
+ grub_free (name_u8);
|
|||
|
+ return ret;
|
|||
|
+}
|
|||
|
+
|
|||
|
static int
|
|||
|
grub_sfs_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
- int NESTED_FUNC_ATTR
|
|||
|
- (*hook) (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node))
|
|||
|
+ grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
|
|||
|
{
|
|||
|
struct grub_fshelp_node *node = 0;
|
|||
|
struct grub_sfs_data *data = dir->data;
|
|||
|
@@ -474,46 +510,6 @@ grub_sfs_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
unsigned int next = dir->block;
|
|||
|
grub_uint32_t pos;
|
|||
|
|
|||
|
- auto int NESTED_FUNC_ATTR grub_sfs_create_node (const char *name,
|
|||
|
- grub_uint32_t block,
|
|||
|
- grub_uint32_t size, int type,
|
|||
|
- grub_uint32_t mtime);
|
|||
|
-
|
|||
|
- int NESTED_FUNC_ATTR grub_sfs_create_node (const char *name,
|
|||
|
- grub_uint32_t block,
|
|||
|
- grub_uint32_t size, int type,
|
|||
|
- grub_uint32_t mtime)
|
|||
|
- {
|
|||
|
- grub_size_t len = grub_strlen (name);
|
|||
|
- grub_uint8_t *name_u8;
|
|||
|
- int ret;
|
|||
|
- node = grub_malloc (sizeof (*node));
|
|||
|
- if (!node)
|
|||
|
- return 1;
|
|||
|
- name_u8 = grub_malloc (len * GRUB_MAX_UTF8_PER_LATIN1 + 1);
|
|||
|
- if (!name_u8)
|
|||
|
- {
|
|||
|
- grub_free (node);
|
|||
|
- return 1;
|
|||
|
- }
|
|||
|
-
|
|||
|
- node->data = data;
|
|||
|
- node->size = size;
|
|||
|
- node->block = block;
|
|||
|
- node->mtime = mtime;
|
|||
|
- node->cache = 0;
|
|||
|
- node->cache_off = 0;
|
|||
|
- node->next_extent = block;
|
|||
|
- node->cache_size = 0;
|
|||
|
- node->cache_allocated = 0;
|
|||
|
-
|
|||
|
- *grub_latin1_to_utf8 (name_u8, (const grub_uint8_t *) name, len) = '\0';
|
|||
|
-
|
|||
|
- ret = hook ((char *) name_u8, type | data->fshelp_flags, node);
|
|||
|
- grub_free (name_u8);
|
|||
|
- return ret;
|
|||
|
- }
|
|||
|
-
|
|||
|
objc_data = grub_malloc (GRUB_DISK_SECTOR_SIZE << data->log_blocksize);
|
|||
|
if (!objc_data)
|
|||
|
goto fail;
|
|||
|
@@ -570,9 +566,10 @@ grub_sfs_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
else
|
|||
|
block = grub_be_to_cpu32 (obj->file_dir.file.first_block);
|
|||
|
|
|||
|
- if (grub_sfs_create_node (filename, block,
|
|||
|
+ if (grub_sfs_create_node (&node, data, filename, block,
|
|||
|
grub_be_to_cpu32 (obj->file_dir.file.size),
|
|||
|
- type, grub_be_to_cpu32 (obj->mtime)))
|
|||
|
+ type, grub_be_to_cpu32 (obj->mtime),
|
|||
|
+ hook, hook_data))
|
|||
|
{
|
|||
|
grub_free (objc_data);
|
|||
|
return 1;
|
|||
|
@@ -654,32 +651,38 @@ grub_sfs_read (grub_file_t file, char *buf, grub_size_t len)
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
+/* Context for grub_sfs_dir. */
|
|||
|
+struct grub_sfs_dir_ctx
|
|||
|
+{
|
|||
|
+ grub_fs_dir_hook_t hook;
|
|||
|
+ void *hook_data;
|
|||
|
+};
|
|||
|
+
|
|||
|
+/* Helper for grub_sfs_dir. */
|
|||
|
+static int
|
|||
|
+grub_sfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
|
|||
|
+ grub_fshelp_node_t node, void *data)
|
|||
|
+{
|
|||
|
+ struct grub_sfs_dir_ctx *ctx = data;
|
|||
|
+ struct grub_dirhook_info info;
|
|||
|
+
|
|||
|
+ grub_memset (&info, 0, sizeof (info));
|
|||
|
+ info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
|||
|
+ info.mtime = node->mtime + 8 * 365 * 86400 + 86400 * 2;
|
|||
|
+ info.mtimeset = 1;
|
|||
|
+ grub_free (node->cache);
|
|||
|
+ grub_free (node);
|
|||
|
+ return ctx->hook (filename, &info, ctx->hook_data);
|
|||
|
+}
|
|||
|
+
|
|||
|
static grub_err_t
|
|||
|
grub_sfs_dir (grub_device_t device, const char *path,
|
|||
|
- int (*hook) (const char *filename,
|
|||
|
- const struct grub_dirhook_info *info))
|
|||
|
+ grub_fs_dir_hook_t hook, void *hook_data)
|
|||
|
{
|
|||
|
+ struct grub_sfs_dir_ctx ctx = { hook, hook_data };
|
|||
|
struct grub_sfs_data *data = 0;
|
|||
|
struct grub_fshelp_node *fdiro = 0;
|
|||
|
|
|||
|
- auto int NESTED_FUNC_ATTR iterate (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node);
|
|||
|
-
|
|||
|
- int NESTED_FUNC_ATTR iterate (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node)
|
|||
|
- {
|
|||
|
- struct grub_dirhook_info info;
|
|||
|
- grub_memset (&info, 0, sizeof (info));
|
|||
|
- info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
|||
|
- info.mtime = node->mtime + 8 * 365 * 86400 + 86400 * 2;
|
|||
|
- info.mtimeset = 1;
|
|||
|
- grub_free (node->cache);
|
|||
|
- grub_free (node);
|
|||
|
- return hook (filename, &info);
|
|||
|
- }
|
|||
|
-
|
|||
|
grub_dl_ref (my_mod);
|
|||
|
|
|||
|
data = grub_sfs_mount (device->disk);
|
|||
|
@@ -691,7 +694,7 @@ grub_sfs_dir (grub_device_t device, const char *path,
|
|||
|
if (grub_errno)
|
|||
|
goto fail;
|
|||
|
|
|||
|
- grub_sfs_iterate_dir (fdiro, iterate);
|
|||
|
+ grub_sfs_iterate_dir (fdiro, grub_sfs_dir_iter, &ctx);
|
|||
|
|
|||
|
fail:
|
|||
|
if (data && fdiro != &data->diropen)
|
|||
|
diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c
|
|||
|
index 44af0f8..cb3cc3a 100644
|
|||
|
--- a/grub-core/fs/squash4.c
|
|||
|
+++ b/grub-core/fs/squash4.c
|
|||
|
@@ -478,10 +478,7 @@ grub_squash_read_symlink (grub_fshelp_node_t node)
|
|||
|
|
|||
|
static int
|
|||
|
grub_squash_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
- int NESTED_FUNC_ATTR
|
|||
|
- (*hook) (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node))
|
|||
|
+ grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
|
|||
|
{
|
|||
|
grub_uint32_t off;
|
|||
|
grub_uint32_t endoff;
|
|||
|
@@ -514,7 +511,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
return 0;
|
|||
|
grub_memcpy (node, dir,
|
|||
|
sizeof (*node) + dir->stsize * sizeof (dir->stack[0]));
|
|||
|
- if (hook (".", GRUB_FSHELP_DIR, node))
|
|||
|
+ if (hook (".", GRUB_FSHELP_DIR, node, hook_data))
|
|||
|
return 1;
|
|||
|
|
|||
|
if (dir->stsize != 1)
|
|||
|
@@ -536,7 +533,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
if (err)
|
|||
|
return 0;
|
|||
|
|
|||
|
- if (hook ("..", GRUB_FSHELP_DIR, node))
|
|||
|
+ if (hook ("..", GRUB_FSHELP_DIR, node, hook_data))
|
|||
|
return 1;
|
|||
|
}
|
|||
|
}
|
|||
|
@@ -604,7 +601,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
node->stack[node->stsize].ino_chunk = grub_le_to_cpu32 (dh.ino_chunk);
|
|||
|
node->stack[node->stsize].ino_offset = grub_le_to_cpu16 (di.ino_offset);
|
|||
|
node->stsize++;
|
|||
|
- r = hook (buf, filetype, node);
|
|||
|
+ r = hook (buf, filetype, node, hook_data);
|
|||
|
|
|||
|
grub_free (buf);
|
|||
|
if (r)
|
|||
|
@@ -640,28 +637,34 @@ squash_unmount (struct grub_squash_data *data)
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
-static grub_err_t
|
|||
|
-grub_squash_dir (grub_device_t device, const char *path,
|
|||
|
- int (*hook) (const char *filename,
|
|||
|
- const struct grub_dirhook_info *info))
|
|||
|
+/* Context for grub_squash_dir. */
|
|||
|
+struct grub_squash_dir_ctx
|
|||
|
{
|
|||
|
- auto int NESTED_FUNC_ATTR iterate (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node);
|
|||
|
+ grub_fs_dir_hook_t hook;
|
|||
|
+ void *hook_data;
|
|||
|
+};
|
|||
|
|
|||
|
- int NESTED_FUNC_ATTR iterate (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node)
|
|||
|
- {
|
|||
|
- struct grub_dirhook_info info;
|
|||
|
- grub_memset (&info, 0, sizeof (info));
|
|||
|
- info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
|||
|
- info.mtimeset = 1;
|
|||
|
- info.mtime = grub_le_to_cpu32 (node->ino.mtime);
|
|||
|
- grub_free (node);
|
|||
|
- return hook (filename, &info);
|
|||
|
- }
|
|||
|
+/* Helper for grub_squash_dir. */
|
|||
|
+static int
|
|||
|
+grub_squash_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
|
|||
|
+ grub_fshelp_node_t node, void *data)
|
|||
|
+{
|
|||
|
+ struct grub_squash_dir_ctx *ctx = data;
|
|||
|
+ struct grub_dirhook_info info;
|
|||
|
+
|
|||
|
+ grub_memset (&info, 0, sizeof (info));
|
|||
|
+ info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
|||
|
+ info.mtimeset = 1;
|
|||
|
+ info.mtime = grub_le_to_cpu32 (node->ino.mtime);
|
|||
|
+ grub_free (node);
|
|||
|
+ return ctx->hook (filename, &info, ctx->hook_data);
|
|||
|
+}
|
|||
|
|
|||
|
+static grub_err_t
|
|||
|
+grub_squash_dir (grub_device_t device, const char *path,
|
|||
|
+ 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_fshelp_node *fdiro = 0;
|
|||
|
struct grub_fshelp_node root;
|
|||
|
@@ -678,7 +681,7 @@ grub_squash_dir (grub_device_t device, const char *path,
|
|||
|
grub_fshelp_find_file (path, &root, &fdiro, grub_squash_iterate_dir,
|
|||
|
grub_squash_read_symlink, GRUB_FSHELP_DIR);
|
|||
|
if (!grub_errno)
|
|||
|
- grub_squash_iterate_dir (fdiro, iterate);
|
|||
|
+ grub_squash_iterate_dir (fdiro, grub_squash_dir_iter, &ctx);
|
|||
|
|
|||
|
squash_unmount (data);
|
|||
|
|
|||
|
diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c
|
|||
|
index 8e28d41..b7f3afb 100644
|
|||
|
--- a/grub-core/fs/udf.c
|
|||
|
+++ b/grub-core/fs/udf.c
|
|||
|
@@ -843,10 +843,7 @@ read_string (const grub_uint8_t *raw, grub_size_t sz, char *outbuf)
|
|||
|
|
|||
|
static int
|
|||
|
grub_udf_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
- int NESTED_FUNC_ATTR
|
|||
|
- (*hook) (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node))
|
|||
|
+ grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
|
|||
|
{
|
|||
|
grub_fshelp_node_t child;
|
|||
|
struct grub_udf_file_ident dirent;
|
|||
|
@@ -859,7 +856,7 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
/* The current directory is not stored. */
|
|||
|
grub_memcpy (child, dir, get_fshelp_size (dir->data));
|
|||
|
|
|||
|
- if (hook (".", GRUB_FSHELP_DIR, child))
|
|||
|
+ if (hook (".", GRUB_FSHELP_DIR, child, hook_data))
|
|||
|
return 1;
|
|||
|
|
|||
|
while (offset < U64 (dir->block.fe.file_size))
|
|||
|
@@ -887,7 +884,7 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
if (dirent.characteristics & GRUB_UDF_FID_CHAR_PARENT)
|
|||
|
{
|
|||
|
/* This is the parent directory. */
|
|||
|
- if (hook ("..", GRUB_FSHELP_DIR, child))
|
|||
|
+ if (hook ("..", GRUB_FSHELP_DIR, child, hook_data))
|
|||
|
return 1;
|
|||
|
}
|
|||
|
else
|
|||
|
@@ -911,7 +908,7 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
if (!filename)
|
|||
|
grub_print_error ();
|
|||
|
|
|||
|
- if (filename && hook (filename, type, child))
|
|||
|
+ if (filename && hook (filename, type, child, hook_data))
|
|||
|
{
|
|||
|
grub_free (filename);
|
|||
|
return 1;
|
|||
|
@@ -1012,58 +1009,64 @@ grub_udf_read_symlink (grub_fshelp_node_t node)
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
+/* Context for grub_udf_dir. */
|
|||
|
+struct grub_udf_dir_ctx
|
|||
|
+{
|
|||
|
+ grub_fs_dir_hook_t hook;
|
|||
|
+ void *hook_data;
|
|||
|
+};
|
|||
|
+
|
|||
|
+/* Helper for grub_udf_dir. */
|
|||
|
+static int
|
|||
|
+grub_udf_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
|
|||
|
+ grub_fshelp_node_t node, void *data)
|
|||
|
+{
|
|||
|
+ struct grub_udf_dir_ctx *ctx = data;
|
|||
|
+ struct grub_dirhook_info info;
|
|||
|
+ const struct grub_udf_timestamp *tstamp = NULL;
|
|||
|
+
|
|||
|
+ grub_memset (&info, 0, sizeof (info));
|
|||
|
+ info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
|||
|
+ if (U16 (node->block.fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_FE)
|
|||
|
+ tstamp = &node->block.fe.modification_time;
|
|||
|
+ else if (U16 (node->block.fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_EFE)
|
|||
|
+ tstamp = &node->block.efe.modification_time;
|
|||
|
+
|
|||
|
+ if (tstamp && (U16 (tstamp->type_and_timezone) & 0xf000) == 0x1000)
|
|||
|
+ {
|
|||
|
+ grub_int16_t tz;
|
|||
|
+ struct grub_datetime datetime;
|
|||
|
+
|
|||
|
+ datetime.year = U16 (tstamp->year);
|
|||
|
+ datetime.month = tstamp->month;
|
|||
|
+ datetime.day = tstamp->day;
|
|||
|
+ datetime.hour = tstamp->hour;
|
|||
|
+ datetime.minute = tstamp->minute;
|
|||
|
+ datetime.second = tstamp->second;
|
|||
|
+
|
|||
|
+ tz = U16 (tstamp->type_and_timezone) & 0xfff;
|
|||
|
+ if (tz & 0x800)
|
|||
|
+ tz |= 0xf000;
|
|||
|
+ if (tz == -2047)
|
|||
|
+ tz = 0;
|
|||
|
+
|
|||
|
+ info.mtimeset = !!grub_datetime2unixtime (&datetime, &info.mtime);
|
|||
|
+
|
|||
|
+ info.mtime -= 60 * tz;
|
|||
|
+ }
|
|||
|
+ grub_free (node);
|
|||
|
+ return ctx->hook (filename, &info, ctx->hook_data);
|
|||
|
+}
|
|||
|
+
|
|||
|
static grub_err_t
|
|||
|
grub_udf_dir (grub_device_t device, const char *path,
|
|||
|
- int (*hook) (const char *filename,
|
|||
|
- const struct grub_dirhook_info *info))
|
|||
|
+ grub_fs_dir_hook_t hook, void *hook_data)
|
|||
|
{
|
|||
|
+ struct grub_udf_dir_ctx ctx = { hook, hook_data };
|
|||
|
struct grub_udf_data *data = 0;
|
|||
|
struct grub_fshelp_node *rootnode = 0;
|
|||
|
struct grub_fshelp_node *foundnode = 0;
|
|||
|
|
|||
|
- auto int NESTED_FUNC_ATTR iterate (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node);
|
|||
|
-
|
|||
|
- int NESTED_FUNC_ATTR iterate (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node)
|
|||
|
- {
|
|||
|
- struct grub_dirhook_info info;
|
|||
|
- const struct grub_udf_timestamp *tstamp = NULL;
|
|||
|
- grub_memset (&info, 0, sizeof (info));
|
|||
|
- info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
|||
|
- if (U16 (node->block.fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_FE)
|
|||
|
- tstamp = &node->block.fe.modification_time;
|
|||
|
- else if (U16 (node->block.fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_EFE)
|
|||
|
- tstamp = &node->block.efe.modification_time;
|
|||
|
-
|
|||
|
- if (tstamp && (U16 (tstamp->type_and_timezone) & 0xf000) == 0x1000)
|
|||
|
- {
|
|||
|
- grub_int16_t tz;
|
|||
|
- struct grub_datetime datetime;
|
|||
|
-
|
|||
|
- datetime.year = U16 (tstamp->year);
|
|||
|
- datetime.month = tstamp->month;
|
|||
|
- datetime.day = tstamp->day;
|
|||
|
- datetime.hour = tstamp->hour;
|
|||
|
- datetime.minute = tstamp->minute;
|
|||
|
- datetime.second = tstamp->second;
|
|||
|
-
|
|||
|
- tz = U16 (tstamp->type_and_timezone) & 0xfff;
|
|||
|
- if (tz & 0x800)
|
|||
|
- tz |= 0xf000;
|
|||
|
- if (tz == -2047)
|
|||
|
- tz = 0;
|
|||
|
-
|
|||
|
- info.mtimeset = !!grub_datetime2unixtime (&datetime, &info.mtime);
|
|||
|
-
|
|||
|
- info.mtime -= 60 * tz;
|
|||
|
- }
|
|||
|
- grub_free (node);
|
|||
|
- return hook (filename, &info);
|
|||
|
- }
|
|||
|
-
|
|||
|
grub_dl_ref (my_mod);
|
|||
|
|
|||
|
data = grub_udf_mount (device->disk);
|
|||
|
@@ -1083,7 +1086,7 @@ grub_udf_dir (grub_device_t device, const char *path,
|
|||
|
GRUB_FSHELP_DIR))
|
|||
|
goto fail;
|
|||
|
|
|||
|
- grub_udf_iterate_dir (foundnode, iterate);
|
|||
|
+ grub_udf_iterate_dir (foundnode, grub_udf_dir_iter, &ctx);
|
|||
|
|
|||
|
if (foundnode != rootnode)
|
|||
|
grub_free (foundnode);
|
|||
|
diff --git a/grub-core/fs/ufs.c b/grub-core/fs/ufs.c
|
|||
|
index 74a4a40..089a5c6 100644
|
|||
|
--- a/grub-core/fs/ufs.c
|
|||
|
+++ b/grub-core/fs/ufs.c
|
|||
|
@@ -625,8 +625,7 @@ grub_ufs_mount (grub_disk_t disk)
|
|||
|
|
|||
|
static grub_err_t
|
|||
|
grub_ufs_dir (grub_device_t device, const char *path,
|
|||
|
- int (*hook) (const char *filename,
|
|||
|
- const struct grub_dirhook_info *info))
|
|||
|
+ grub_fs_dir_hook_t hook, void *hook_data)
|
|||
|
{
|
|||
|
struct grub_ufs_data *data;
|
|||
|
unsigned int pos = 0;
|
|||
|
@@ -697,7 +696,7 @@ grub_ufs_dir (grub_device_t device, const char *path,
|
|||
|
#endif
|
|||
|
info.mtimeset = 1;
|
|||
|
|
|||
|
- if (hook (filename, &info))
|
|||
|
+ if (hook (filename, &info, hook_data))
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
|
|||
|
index 1ed048f..49d2a89 100644
|
|||
|
--- a/grub-core/fs/xfs.c
|
|||
|
+++ b/grub-core/fs/xfs.c
|
|||
|
@@ -443,47 +443,57 @@ grub_xfs_mode_to_filetype (grub_uint16_t mode)
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
-static int
|
|||
|
-grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
- int NESTED_FUNC_ATTR
|
|||
|
- (*hook) (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node))
|
|||
|
+/* Context for grub_xfs_iterate_dir. */
|
|||
|
+struct grub_xfs_iterate_dir_ctx
|
|||
|
{
|
|||
|
- struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir;
|
|||
|
- auto int NESTED_FUNC_ATTR call_hook (grub_uint64_t ino, const char *filename);
|
|||
|
+ grub_fshelp_iterate_dir_hook_t hook;
|
|||
|
+ void *hook_data;
|
|||
|
+ struct grub_fshelp_node *diro;
|
|||
|
+};
|
|||
|
|
|||
|
- int NESTED_FUNC_ATTR call_hook (grub_uint64_t ino, const char *filename)
|
|||
|
- {
|
|||
|
- struct grub_fshelp_node *fdiro;
|
|||
|
- grub_err_t err;
|
|||
|
-
|
|||
|
- fdiro = grub_malloc (sizeof (struct grub_fshelp_node)
|
|||
|
- - sizeof (struct grub_xfs_inode)
|
|||
|
- + (1 << diro->data->sblock.log2_inode));
|
|||
|
- if (!fdiro)
|
|||
|
- {
|
|||
|
- grub_print_error ();
|
|||
|
- return 0;
|
|||
|
- }
|
|||
|
+/* Helper for grub_xfs_iterate_dir. */
|
|||
|
+static int iterate_dir_call_hook (grub_uint64_t ino, const char *filename,
|
|||
|
+ struct grub_xfs_iterate_dir_ctx *ctx)
|
|||
|
+{
|
|||
|
+ struct grub_fshelp_node *fdiro;
|
|||
|
+ grub_err_t err;
|
|||
|
|
|||
|
- /* The inode should be read, otherwise the filetype can
|
|||
|
- not be determined. */
|
|||
|
- fdiro->ino = ino;
|
|||
|
- fdiro->inode_read = 1;
|
|||
|
- fdiro->data = diro->data;
|
|||
|
- err = grub_xfs_read_inode (diro->data, ino, &fdiro->inode);
|
|||
|
- if (err)
|
|||
|
- {
|
|||
|
- grub_print_error ();
|
|||
|
- return 0;
|
|||
|
- }
|
|||
|
+ fdiro = grub_malloc (sizeof (struct grub_fshelp_node)
|
|||
|
+ - sizeof (struct grub_xfs_inode)
|
|||
|
+ + (1 << ctx->diro->data->sblock.log2_inode));
|
|||
|
+ if (!fdiro)
|
|||
|
+ {
|
|||
|
+ grub_print_error ();
|
|||
|
+ return 0;
|
|||
|
+ }
|
|||
|
|
|||
|
- return hook (filename,
|
|||
|
- grub_xfs_mode_to_filetype (fdiro->inode.mode),
|
|||
|
- fdiro);
|
|||
|
+ /* The inode should be read, otherwise the filetype can
|
|||
|
+ not be determined. */
|
|||
|
+ fdiro->ino = ino;
|
|||
|
+ fdiro->inode_read = 1;
|
|||
|
+ fdiro->data = ctx->diro->data;
|
|||
|
+ err = grub_xfs_read_inode (ctx->diro->data, ino, &fdiro->inode);
|
|||
|
+ if (err)
|
|||
|
+ {
|
|||
|
+ grub_print_error ();
|
|||
|
+ return 0;
|
|||
|
}
|
|||
|
|
|||
|
+ return ctx->hook (filename, grub_xfs_mode_to_filetype (fdiro->inode.mode),
|
|||
|
+ fdiro, ctx->hook_data);
|
|||
|
+}
|
|||
|
+
|
|||
|
+static int
|
|||
|
+grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
+ 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)
|
|||
|
{
|
|||
|
case XFS_INODE_FORMAT_INO:
|
|||
|
@@ -508,10 +518,10 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
}
|
|||
|
|
|||
|
/* Synthesize the direntries for `.' and `..'. */
|
|||
|
- if (call_hook (diro->ino, "."))
|
|||
|
+ if (iterate_dir_call_hook (diro->ino, ".", &ctx))
|
|||
|
return 1;
|
|||
|
|
|||
|
- if (call_hook (parent, ".."))
|
|||
|
+ if (iterate_dir_call_hook (parent, "..", &ctx))
|
|||
|
return 1;
|
|||
|
|
|||
|
for (i = 0; i < diro->inode.data.dir.dirhead.count; i++)
|
|||
|
@@ -541,7 +551,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
|
|||
|
grub_memcpy (name, de->name, de->len);
|
|||
|
name[de->len] = '\0';
|
|||
|
- if (call_hook (ino, name))
|
|||
|
+ if (iterate_dir_call_hook (ino, name, &ctx))
|
|||
|
return 1;
|
|||
|
|
|||
|
de = ((struct grub_xfs_dir_entry *)
|
|||
|
@@ -619,7 +629,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
is not used by GRUB. So it can be overwritten. */
|
|||
|
filename[direntry->len] = '\0';
|
|||
|
|
|||
|
- if (call_hook (direntry->inode, filename))
|
|||
|
+ if (iterate_dir_call_hook (direntry->inode, filename, &ctx))
|
|||
|
{
|
|||
|
grub_free (dirblock);
|
|||
|
return 1;
|
|||
|
@@ -703,33 +713,39 @@ grub_xfs_mount (grub_disk_t disk)
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
-static grub_err_t
|
|||
|
-grub_xfs_dir (grub_device_t device, const char *path,
|
|||
|
- int (*hook) (const char *filename,
|
|||
|
- const struct grub_dirhook_info *info))
|
|||
|
+/* Context for grub_xfs_dir. */
|
|||
|
+struct grub_xfs_dir_ctx
|
|||
|
{
|
|||
|
- struct grub_xfs_data *data = 0;
|
|||
|
- struct grub_fshelp_node *fdiro = 0;
|
|||
|
+ grub_fs_dir_hook_t hook;
|
|||
|
+ void *hook_data;
|
|||
|
+};
|
|||
|
|
|||
|
- auto int NESTED_FUNC_ATTR iterate (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node);
|
|||
|
+/* Helper for grub_xfs_dir. */
|
|||
|
+static int
|
|||
|
+grub_xfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
|
|||
|
+ grub_fshelp_node_t node, void *data)
|
|||
|
+{
|
|||
|
+ struct grub_xfs_dir_ctx *ctx = data;
|
|||
|
+ struct grub_dirhook_info info;
|
|||
|
|
|||
|
- int NESTED_FUNC_ATTR iterate (const char *filename,
|
|||
|
- enum grub_fshelp_filetype filetype,
|
|||
|
- grub_fshelp_node_t node)
|
|||
|
+ grub_memset (&info, 0, sizeof (info));
|
|||
|
+ if (node->inode_read)
|
|||
|
{
|
|||
|
- struct grub_dirhook_info info;
|
|||
|
- grub_memset (&info, 0, sizeof (info));
|
|||
|
- if (node->inode_read)
|
|||
|
- {
|
|||
|
- info.mtimeset = 1;
|
|||
|
- info.mtime = grub_be_to_cpu32 (node->inode.mtime.sec);
|
|||
|
- }
|
|||
|
- info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
|||
|
- grub_free (node);
|
|||
|
- return hook (filename, &info);
|
|||
|
+ info.mtimeset = 1;
|
|||
|
+ info.mtime = grub_be_to_cpu32 (node->inode.mtime.sec);
|
|||
|
}
|
|||
|
+ info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
|||
|
+ grub_free (node);
|
|||
|
+ return ctx->hook (filename, &info, ctx->hook_data);
|
|||
|
+}
|
|||
|
+
|
|||
|
+static grub_err_t
|
|||
|
+grub_xfs_dir (grub_device_t device, const char *path,
|
|||
|
+ 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);
|
|||
|
|
|||
|
@@ -742,7 +758,7 @@ grub_xfs_dir (grub_device_t device, const char *path,
|
|||
|
if (grub_errno)
|
|||
|
goto fail;
|
|||
|
|
|||
|
- grub_xfs_iterate_dir (fdiro, iterate);
|
|||
|
+ grub_xfs_iterate_dir (fdiro, grub_xfs_dir_iter, &ctx);
|
|||
|
|
|||
|
fail:
|
|||
|
if (fdiro != &data->diropen)
|
|||
|
diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c
|
|||
|
index 6ef6db3..822d65b 100644
|
|||
|
--- a/grub-core/fs/zfs/zfs.c
|
|||
|
+++ b/grub-core/fs/zfs/zfs.c
|
|||
|
@@ -253,6 +253,14 @@ struct grub_zfs_data
|
|||
|
grub_uint64_t guid;
|
|||
|
};
|
|||
|
|
|||
|
+/* Context for grub_zfs_dir. */
|
|||
|
+struct grub_zfs_dir_ctx
|
|||
|
+{
|
|||
|
+ grub_fs_dir_hook_t hook;
|
|||
|
+ void *hook_data;
|
|||
|
+ struct grub_zfs_data *data;
|
|||
|
+};
|
|||
|
+
|
|||
|
grub_err_t (*grub_zfs_decrypt) (grub_crypto_cipher_handle_t cipher,
|
|||
|
grub_uint64_t algo,
|
|||
|
void *nonce,
|
|||
|
@@ -1790,8 +1798,9 @@ mzap_lookup (mzap_phys_t * zapobj, grub_zfs_endian_t endian,
|
|||
|
|
|||
|
static int
|
|||
|
mzap_iterate (mzap_phys_t * zapobj, grub_zfs_endian_t endian, int objsize,
|
|||
|
- int NESTED_FUNC_ATTR (*hook) (const char *name,
|
|||
|
- grub_uint64_t val))
|
|||
|
+ int (*hook) (const char *name, grub_uint64_t val,
|
|||
|
+ struct grub_zfs_dir_ctx *ctx),
|
|||
|
+ struct grub_zfs_dir_ctx *ctx)
|
|||
|
{
|
|||
|
int i, chunks;
|
|||
|
mzap_ent_phys_t *mzap_ent = zapobj->mz_chunk;
|
|||
|
@@ -1803,7 +1812,7 @@ mzap_iterate (mzap_phys_t * zapobj, grub_zfs_endian_t endian, int objsize,
|
|||
|
mzap_ent[i].mze_name, (long long)mzap_ent[i].mze_value,
|
|||
|
(int)mzap_ent[i].mze_cd);
|
|||
|
if (hook (mzap_ent[i].mze_name,
|
|||
|
- grub_zfs_to_cpu64 (mzap_ent[i].mze_value, endian)))
|
|||
|
+ grub_zfs_to_cpu64 (mzap_ent[i].mze_value, endian), ctx))
|
|||
|
return 1;
|
|||
|
}
|
|||
|
|
|||
|
@@ -2054,12 +2063,11 @@ fzap_lookup (dnode_end_t * zap_dnode, zap_phys_t * zap,
|
|||
|
static int
|
|||
|
fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap,
|
|||
|
grub_size_t name_elem_length,
|
|||
|
- int NESTED_FUNC_ATTR (*hook) (const void *name,
|
|||
|
- grub_size_t name_length,
|
|||
|
- const void *val_in,
|
|||
|
- grub_size_t nelem,
|
|||
|
- grub_size_t elemsize),
|
|||
|
- struct grub_zfs_data *data)
|
|||
|
+ int (*hook) (const void *name, grub_size_t name_length,
|
|||
|
+ const void *val_in,
|
|||
|
+ grub_size_t nelem, grub_size_t elemsize,
|
|||
|
+ void *data),
|
|||
|
+ void *hook_data, struct grub_zfs_data *data)
|
|||
|
{
|
|||
|
zap_leaf_phys_t *l;
|
|||
|
void *l_in;
|
|||
|
@@ -2158,7 +2166,7 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap,
|
|||
|
}
|
|||
|
|
|||
|
if (hook (buf, le->le_name_length,
|
|||
|
- val, le->le_value_length, le->le_int_size))
|
|||
|
+ val, le->le_value_length, le->le_int_size, hook_data))
|
|||
|
{
|
|||
|
grub_free (l);
|
|||
|
return 1;
|
|||
|
@@ -2221,11 +2229,35 @@ zap_lookup (dnode_end_t * zap_dnode, const char *name, grub_uint64_t *val,
|
|||
|
return grub_error (GRUB_ERR_BAD_FS, "unknown ZAP type");
|
|||
|
}
|
|||
|
|
|||
|
+/* Context for zap_iterate_u64. */
|
|||
|
+struct zap_iterate_u64_ctx
|
|||
|
+{
|
|||
|
+ int (*hook) (const char *, grub_uint64_t, struct grub_zfs_dir_ctx *);
|
|||
|
+ struct grub_zfs_dir_ctx *dir_ctx;
|
|||
|
+};
|
|||
|
+
|
|||
|
+/* Helper for zap_iterate_u64. */
|
|||
|
+static int
|
|||
|
+zap_iterate_u64_transform (const void *name,
|
|||
|
+ grub_size_t namelen __attribute__ ((unused)),
|
|||
|
+ const void *val_in,
|
|||
|
+ grub_size_t nelem,
|
|||
|
+ grub_size_t elemsize,
|
|||
|
+ void *data)
|
|||
|
+{
|
|||
|
+ struct zap_iterate_u64_ctx *ctx = data;
|
|||
|
+
|
|||
|
+ if (elemsize != sizeof (grub_uint64_t) || nelem != 1)
|
|||
|
+ return 0;
|
|||
|
+ return ctx->hook (name, grub_be_to_cpu64 (*(const grub_uint64_t *) val_in),
|
|||
|
+ ctx->dir_ctx);
|
|||
|
+}
|
|||
|
+
|
|||
|
static int
|
|||
|
zap_iterate_u64 (dnode_end_t * zap_dnode,
|
|||
|
- int NESTED_FUNC_ATTR (*hook) (const char *name,
|
|||
|
- grub_uint64_t val),
|
|||
|
- struct grub_zfs_data *data)
|
|||
|
+ int (*hook) (const char *name, grub_uint64_t val,
|
|||
|
+ struct grub_zfs_dir_ctx *ctx),
|
|||
|
+ struct grub_zfs_data *data, struct grub_zfs_dir_ctx *ctx)
|
|||
|
{
|
|||
|
grub_uint64_t block_type;
|
|||
|
int size;
|
|||
|
@@ -2234,23 +2266,6 @@ zap_iterate_u64 (dnode_end_t * zap_dnode,
|
|||
|
int ret;
|
|||
|
grub_zfs_endian_t endian;
|
|||
|
|
|||
|
- auto int NESTED_FUNC_ATTR transform (const void *name,
|
|||
|
- grub_size_t namelen,
|
|||
|
- const void *val_in,
|
|||
|
- grub_size_t nelem,
|
|||
|
- grub_size_t elemsize);
|
|||
|
-
|
|||
|
- int NESTED_FUNC_ATTR transform (const void *name,
|
|||
|
- grub_size_t namelen __attribute__ ((unused)),
|
|||
|
- const void *val_in,
|
|||
|
- grub_size_t nelem,
|
|||
|
- grub_size_t elemsize)
|
|||
|
- {
|
|||
|
- if (elemsize != sizeof (grub_uint64_t) || nelem != 1)
|
|||
|
- return 0;
|
|||
|
- return hook (name, grub_be_to_cpu64 (*(const grub_uint64_t *) val_in));
|
|||
|
- }
|
|||
|
-
|
|||
|
/* Read in the first block of the zap object data. */
|
|||
|
size = grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, zap_dnode->endian) << SPA_MINBLOCKSHIFT;
|
|||
|
err = dmu_read (zap_dnode, 0, &zapbuf, &endian, data);
|
|||
|
@@ -2263,15 +2278,21 @@ zap_iterate_u64 (dnode_end_t * zap_dnode,
|
|||
|
if (block_type == ZBT_MICRO)
|
|||
|
{
|
|||
|
grub_dprintf ("zfs", "micro zap\n");
|
|||
|
- ret = mzap_iterate (zapbuf, endian, size, hook);
|
|||
|
+ ret = mzap_iterate (zapbuf, endian, size, hook, ctx);
|
|||
|
grub_free (zapbuf);
|
|||
|
return ret;
|
|||
|
}
|
|||
|
else if (block_type == ZBT_HEADER)
|
|||
|
{
|
|||
|
+ struct zap_iterate_u64_ctx transform_ctx = {
|
|||
|
+ .hook = hook,
|
|||
|
+ .dir_ctx = ctx
|
|||
|
+ };
|
|||
|
+
|
|||
|
grub_dprintf ("zfs", "fat zap\n");
|
|||
|
/* this is a fat zap */
|
|||
|
- ret = fzap_iterate (zap_dnode, zapbuf, 1, transform, data);
|
|||
|
+ ret = fzap_iterate (zap_dnode, zapbuf, 1,
|
|||
|
+ zap_iterate_u64_transform, &transform_ctx, data);
|
|||
|
grub_free (zapbuf);
|
|||
|
return ret;
|
|||
|
}
|
|||
|
@@ -2282,12 +2303,11 @@ zap_iterate_u64 (dnode_end_t * zap_dnode,
|
|||
|
static int
|
|||
|
zap_iterate (dnode_end_t * zap_dnode,
|
|||
|
grub_size_t nameelemlen,
|
|||
|
- int NESTED_FUNC_ATTR (*hook) (const void *name,
|
|||
|
- grub_size_t namelen,
|
|||
|
- const void *val_in,
|
|||
|
- grub_size_t nelem,
|
|||
|
- grub_size_t elemsize),
|
|||
|
- struct grub_zfs_data *data)
|
|||
|
+ int (*hook) (const void *name, grub_size_t namelen,
|
|||
|
+ const void *val_in,
|
|||
|
+ grub_size_t nelem, grub_size_t elemsize,
|
|||
|
+ void *data),
|
|||
|
+ void *hook_data, struct grub_zfs_data *data)
|
|||
|
{
|
|||
|
grub_uint64_t block_type;
|
|||
|
void *zapbuf;
|
|||
|
@@ -2312,7 +2332,8 @@ zap_iterate (dnode_end_t * zap_dnode,
|
|||
|
{
|
|||
|
grub_dprintf ("zfs", "fat zap\n");
|
|||
|
/* this is a fat zap */
|
|||
|
- ret = fzap_iterate (zap_dnode, zapbuf, nameelemlen, hook, data);
|
|||
|
+ ret = fzap_iterate (zap_dnode, zapbuf, nameelemlen, hook, hook_data,
|
|||
|
+ data);
|
|||
|
grub_free (zapbuf);
|
|||
|
return ret;
|
|||
|
}
|
|||
|
@@ -2826,6 +2847,61 @@ make_mdn (dnode_end_t * mdn, struct grub_zfs_data *data)
|
|||
|
return GRUB_ERR_NONE;
|
|||
|
}
|
|||
|
|
|||
|
+/* Context for dnode_get_fullpath. */
|
|||
|
+struct dnode_get_fullpath_ctx
|
|||
|
+{
|
|||
|
+ struct subvolume *subvol;
|
|||
|
+ grub_uint64_t salt;
|
|||
|
+ int keyn;
|
|||
|
+};
|
|||
|
+
|
|||
|
+/* Helper for dnode_get_fullpath. */
|
|||
|
+static int
|
|||
|
+count_zap_keys (const void *name __attribute__ ((unused)),
|
|||
|
+ grub_size_t namelen __attribute__ ((unused)),
|
|||
|
+ const void *val_in __attribute__ ((unused)),
|
|||
|
+ grub_size_t nelem __attribute__ ((unused)),
|
|||
|
+ grub_size_t elemsize __attribute__ ((unused)),
|
|||
|
+ void *data)
|
|||
|
+{
|
|||
|
+ struct dnode_get_fullpath_ctx *ctx = data;
|
|||
|
+
|
|||
|
+ ctx->subvol->nkeys++;
|
|||
|
+ return 0;
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* Helper for dnode_get_fullpath. */
|
|||
|
+static int
|
|||
|
+load_zap_key (const void *name, grub_size_t namelen, const void *val_in,
|
|||
|
+ grub_size_t nelem, grub_size_t elemsize, void *data)
|
|||
|
+{
|
|||
|
+ struct dnode_get_fullpath_ctx *ctx = data;
|
|||
|
+
|
|||
|
+ if (namelen != 1)
|
|||
|
+ {
|
|||
|
+ grub_dprintf ("zfs", "Unexpected key index size %" PRIuGRUB_SIZE "\n",
|
|||
|
+ namelen);
|
|||
|
+ return 0;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ if (elemsize != 1)
|
|||
|
+ {
|
|||
|
+ grub_dprintf ("zfs", "Unexpected key element size %" PRIuGRUB_SIZE "\n",
|
|||
|
+ elemsize);
|
|||
|
+ return 0;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ ctx->subvol->keyring[ctx->keyn].txg =
|
|||
|
+ grub_be_to_cpu64 (*(grub_uint64_t *) name);
|
|||
|
+ ctx->subvol->keyring[ctx->keyn].algo =
|
|||
|
+ grub_le_to_cpu64 (*(grub_uint64_t *) val_in);
|
|||
|
+ ctx->subvol->keyring[ctx->keyn].cipher =
|
|||
|
+ grub_zfs_load_key (val_in, nelem, ctx->salt,
|
|||
|
+ ctx->subvol->keyring[ctx->keyn].algo);
|
|||
|
+ ctx->keyn++;
|
|||
|
+ return 0;
|
|||
|
+}
|
|||
|
+
|
|||
|
static grub_err_t
|
|||
|
dnode_get_fullpath (const char *fullpath, struct subvolume *subvol,
|
|||
|
dnode_end_t * dn, int *isfs,
|
|||
|
@@ -2835,57 +2911,7 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol,
|
|||
|
const char *ptr_at, *filename;
|
|||
|
grub_uint64_t headobj;
|
|||
|
grub_uint64_t keychainobj;
|
|||
|
- grub_uint64_t salt;
|
|||
|
grub_err_t err;
|
|||
|
- int keyn = 0;
|
|||
|
-
|
|||
|
- auto int NESTED_FUNC_ATTR count_zap_keys (const void *name,
|
|||
|
- grub_size_t namelen,
|
|||
|
- const void *val_in,
|
|||
|
- grub_size_t nelem,
|
|||
|
- grub_size_t elemsize);
|
|||
|
- int NESTED_FUNC_ATTR count_zap_keys (const void *name __attribute__ ((unused)),
|
|||
|
- grub_size_t namelen __attribute__ ((unused)),
|
|||
|
- const void *val_in __attribute__ ((unused)),
|
|||
|
- grub_size_t nelem __attribute__ ((unused)),
|
|||
|
- grub_size_t elemsize __attribute__ ((unused)))
|
|||
|
- {
|
|||
|
- subvol->nkeys++;
|
|||
|
- return 0;
|
|||
|
- }
|
|||
|
-
|
|||
|
- auto int NESTED_FUNC_ATTR load_zap_key (const void *name,
|
|||
|
- grub_size_t namelen,
|
|||
|
- const void *val_in,
|
|||
|
- grub_size_t nelem,
|
|||
|
- grub_size_t elemsize);
|
|||
|
- int NESTED_FUNC_ATTR load_zap_key (const void *name,
|
|||
|
- grub_size_t namelen,
|
|||
|
- const void *val_in,
|
|||
|
- grub_size_t nelem,
|
|||
|
- grub_size_t elemsize)
|
|||
|
- {
|
|||
|
- if (namelen != 1)
|
|||
|
- {
|
|||
|
- grub_dprintf ("zfs", "Unexpected key index size %" PRIuGRUB_SIZE "\n",
|
|||
|
- namelen);
|
|||
|
- return 0;
|
|||
|
- }
|
|||
|
-
|
|||
|
- if (elemsize != 1)
|
|||
|
- {
|
|||
|
- grub_dprintf ("zfs", "Unexpected key element size %" PRIuGRUB_SIZE "\n",
|
|||
|
- elemsize);
|
|||
|
- return 0;
|
|||
|
- }
|
|||
|
-
|
|||
|
- subvol->keyring[keyn].txg = grub_be_to_cpu64 (*(grub_uint64_t *) name);
|
|||
|
- subvol->keyring[keyn].algo = grub_le_to_cpu64 (*(grub_uint64_t *) val_in);
|
|||
|
- subvol->keyring[keyn].cipher = grub_zfs_load_key (val_in, nelem, salt,
|
|||
|
- subvol->keyring[keyn].algo);
|
|||
|
- keyn++;
|
|||
|
- return 0;
|
|||
|
- }
|
|||
|
|
|||
|
ptr_at = grub_strchr (fullpath, '@');
|
|||
|
if (! ptr_at)
|
|||
|
@@ -2953,6 +2979,10 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol,
|
|||
|
keychainobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&dn->dn))->keychain, dn->endian);
|
|||
|
if (grub_zfs_load_key && keychainobj)
|
|||
|
{
|
|||
|
+ struct dnode_get_fullpath_ctx ctx = {
|
|||
|
+ .subvol = subvol,
|
|||
|
+ .keyn = 0
|
|||
|
+ };
|
|||
|
dnode_end_t keychain_dn, props_dn;
|
|||
|
grub_uint64_t propsobj;
|
|||
|
propsobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&dn->dn))->dd_props_zapobj, dn->endian);
|
|||
|
@@ -2966,12 +2996,12 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol,
|
|||
|
return err;
|
|||
|
}
|
|||
|
|
|||
|
- err = zap_lookup (&props_dn, "salt", &salt, data, 0);
|
|||
|
+ err = zap_lookup (&props_dn, "salt", &ctx.salt, data, 0);
|
|||
|
if (err == GRUB_ERR_FILE_NOT_FOUND)
|
|||
|
{
|
|||
|
err = 0;
|
|||
|
grub_errno = 0;
|
|||
|
- salt = 0;
|
|||
|
+ ctx.salt = 0;
|
|||
|
}
|
|||
|
if (err)
|
|||
|
{
|
|||
|
@@ -2988,7 +3018,7 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol,
|
|||
|
return err;
|
|||
|
}
|
|||
|
subvol->nkeys = 0;
|
|||
|
- zap_iterate (&keychain_dn, 8, count_zap_keys, data);
|
|||
|
+ zap_iterate (&keychain_dn, 8, count_zap_keys, &ctx, data);
|
|||
|
subvol->keyring = grub_zalloc (subvol->nkeys * sizeof (subvol->keyring[0]));
|
|||
|
if (!subvol->keyring)
|
|||
|
{
|
|||
|
@@ -2996,7 +3026,7 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol,
|
|||
|
grub_free (snapname);
|
|||
|
return err;
|
|||
|
}
|
|||
|
- zap_iterate (&keychain_dn, 8, load_zap_key, data);
|
|||
|
+ zap_iterate (&keychain_dn, 8, load_zap_key, &ctx, data);
|
|||
|
}
|
|||
|
|
|||
|
if (snapname)
|
|||
|
@@ -3748,108 +3778,122 @@ fill_fs_info (struct grub_dirhook_info *info,
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
-static grub_err_t
|
|||
|
-grub_zfs_dir (grub_device_t device, const char *path,
|
|||
|
- int (*hook) (const char *, const struct grub_dirhook_info *))
|
|||
|
+/* Helper for grub_zfs_dir. */
|
|||
|
+static int
|
|||
|
+iterate_zap (const char *name, grub_uint64_t val, struct grub_zfs_dir_ctx *ctx)
|
|||
|
{
|
|||
|
- struct grub_zfs_data *data;
|
|||
|
grub_err_t err;
|
|||
|
- int isfs;
|
|||
|
- auto int NESTED_FUNC_ATTR iterate_zap (const char *name, grub_uint64_t val);
|
|||
|
- auto int NESTED_FUNC_ATTR iterate_zap_fs (const char *name,
|
|||
|
- grub_uint64_t val);
|
|||
|
- auto int NESTED_FUNC_ATTR iterate_zap_snap (const char *name,
|
|||
|
- grub_uint64_t val);
|
|||
|
+ struct grub_dirhook_info info;
|
|||
|
|
|||
|
- int NESTED_FUNC_ATTR iterate_zap (const char *name, grub_uint64_t val)
|
|||
|
- {
|
|||
|
- struct grub_dirhook_info info;
|
|||
|
- dnode_end_t dn;
|
|||
|
- grub_memset (&info, 0, sizeof (info));
|
|||
|
+ dnode_end_t dn;
|
|||
|
+ 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)
|
|||
|
- {
|
|||
|
- void *sahdrp;
|
|||
|
- int hdrsize;
|
|||
|
+ if (dn.dn.dn_bonustype == DMU_OT_SA)
|
|||
|
+ {
|
|||
|
+ void *sahdrp;
|
|||
|
+ int hdrsize;
|
|||
|
|
|||
|
- if (dn.dn.dn_bonuslen != 0)
|
|||
|
- {
|
|||
|
- sahdrp = (sa_hdr_phys_t *) DN_BONUS (&data->dnode.dn);
|
|||
|
- }
|
|||
|
- else if (dn.dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR)
|
|||
|
- {
|
|||
|
- blkptr_t *bp = &dn.dn.dn_spill;
|
|||
|
+ if (dn.dn.dn_bonuslen != 0)
|
|||
|
+ {
|
|||
|
+ sahdrp = (sa_hdr_phys_t *) DN_BONUS (&ctx->data->dnode.dn);
|
|||
|
+ }
|
|||
|
+ else if (dn.dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR)
|
|||
|
+ {
|
|||
|
+ blkptr_t *bp = &dn.dn.dn_spill;
|
|||
|
|
|||
|
- err = zio_read (bp, dn.endian, &sahdrp, NULL, data);
|
|||
|
- if (err)
|
|||
|
- {
|
|||
|
- grub_print_error ();
|
|||
|
- return 0;
|
|||
|
- }
|
|||
|
- }
|
|||
|
- else
|
|||
|
- {
|
|||
|
- grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt");
|
|||
|
- grub_print_error ();
|
|||
|
- return 0;
|
|||
|
- }
|
|||
|
+ err = zio_read (bp, dn.endian, &sahdrp, NULL, ctx->data);
|
|||
|
+ if (err)
|
|||
|
+ {
|
|||
|
+ grub_print_error ();
|
|||
|
+ return 0;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+ else
|
|||
|
+ {
|
|||
|
+ grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt");
|
|||
|
+ grub_print_error ();
|
|||
|
+ return 0;
|
|||
|
+ }
|
|||
|
|
|||
|
- hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp));
|
|||
|
- info.mtimeset = 1;
|
|||
|
- info.mtime = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian);
|
|||
|
- info.case_insensitive = data->subvol.case_insensitive;
|
|||
|
- }
|
|||
|
-
|
|||
|
- if (dn.dn.dn_bonustype == DMU_OT_ZNODE)
|
|||
|
- {
|
|||
|
- info.mtimeset = 1;
|
|||
|
- info.mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0],
|
|||
|
- dn.endian);
|
|||
|
- }
|
|||
|
- info.dir = (dn.dn.dn_type == DMU_OT_DIRECTORY_CONTENTS);
|
|||
|
- grub_dprintf ("zfs", "type=%d, name=%s\n",
|
|||
|
- (int)dn.dn.dn_type, (char *)name);
|
|||
|
- return hook (name, &info);
|
|||
|
- }
|
|||
|
+ hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp));
|
|||
|
+ info.mtimeset = 1;
|
|||
|
+ info.mtime = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian);
|
|||
|
+ info.case_insensitive = ctx->data->subvol.case_insensitive;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ if (dn.dn.dn_bonustype == DMU_OT_ZNODE)
|
|||
|
+ {
|
|||
|
+ info.mtimeset = 1;
|
|||
|
+ info.mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0],
|
|||
|
+ dn.endian);
|
|||
|
+ }
|
|||
|
+ info.dir = (dn.dn.dn_type == DMU_OT_DIRECTORY_CONTENTS);
|
|||
|
+ grub_dprintf ("zfs", "type=%d, name=%s\n",
|
|||
|
+ (int)dn.dn.dn_type, (char *)name);
|
|||
|
+ return ctx->hook (name, &info, ctx->hook_data);
|
|||
|
+}
|
|||
|
|
|||
|
- int NESTED_FUNC_ATTR iterate_zap_fs (const char *name, grub_uint64_t val)
|
|||
|
- {
|
|||
|
- struct grub_dirhook_info info;
|
|||
|
- dnode_end_t mdn;
|
|||
|
- err = dnode_get (&(data->mos), val, 0, &mdn, data);
|
|||
|
- if (err)
|
|||
|
- return 0;
|
|||
|
- if (mdn.dn.dn_type != DMU_OT_DSL_DIR)
|
|||
|
- return 0;
|
|||
|
+/* 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;
|
|||
|
|
|||
|
- fill_fs_info (&info, mdn, data);
|
|||
|
- return hook (name, &info);
|
|||
|
- }
|
|||
|
- int NESTED_FUNC_ATTR iterate_zap_snap (const char *name, grub_uint64_t val)
|
|||
|
- {
|
|||
|
- struct grub_dirhook_info info;
|
|||
|
- char *name2;
|
|||
|
- int ret;
|
|||
|
- dnode_end_t mdn;
|
|||
|
+ dnode_end_t mdn;
|
|||
|
+ err = dnode_get (&(ctx->data->mos), val, 0, &mdn, ctx->data);
|
|||
|
+ if (err)
|
|||
|
+ return 0;
|
|||
|
+ if (mdn.dn.dn_type != DMU_OT_DSL_DIR)
|
|||
|
+ return 0;
|
|||
|
|
|||
|
- err = dnode_get (&(data->mos), val, 0, &mdn, data);
|
|||
|
- if (err)
|
|||
|
- return 0;
|
|||
|
+ fill_fs_info (&info, mdn, ctx->data);
|
|||
|
+ return ctx->hook (name, &info, ctx->hook_data);
|
|||
|
+}
|
|||
|
|
|||
|
- if (mdn.dn.dn_type != DMU_OT_DSL_DATASET)
|
|||
|
- return 0;
|
|||
|
+/* Helper for grub_zfs_dir. */
|
|||
|
+static int
|
|||
|
+iterate_zap_snap (const char *name, grub_uint64_t val,
|
|||
|
+ struct grub_zfs_dir_ctx *ctx)
|
|||
|
+{
|
|||
|
+ grub_err_t err;
|
|||
|
+ struct grub_dirhook_info info;
|
|||
|
+ char *name2;
|
|||
|
+ int ret;
|
|||
|
+
|
|||
|
+ dnode_end_t mdn;
|
|||
|
|
|||
|
- fill_fs_info (&info, mdn, data);
|
|||
|
+ err = dnode_get (&(ctx->data->mos), val, 0, &mdn, ctx->data);
|
|||
|
+ if (err)
|
|||
|
+ return 0;
|
|||
|
|
|||
|
- name2 = grub_malloc (grub_strlen (name) + 2);
|
|||
|
- name2[0] = '@';
|
|||
|
- grub_memcpy (name2 + 1, name, grub_strlen (name) + 1);
|
|||
|
- ret = hook (name2, &info);
|
|||
|
- grub_free (name2);
|
|||
|
- return ret;
|
|||
|
- }
|
|||
|
+ if (mdn.dn.dn_type != DMU_OT_DSL_DATASET)
|
|||
|
+ return 0;
|
|||
|
+
|
|||
|
+ fill_fs_info (&info, mdn, ctx->data);
|
|||
|
+
|
|||
|
+ name2 = grub_malloc (grub_strlen (name) + 2);
|
|||
|
+ name2[0] = '@';
|
|||
|
+ grub_memcpy (name2 + 1, name, grub_strlen (name) + 1);
|
|||
|
+ ret = ctx->hook (name2, &info, ctx->hook_data);
|
|||
|
+ grub_free (name2);
|
|||
|
+ return ret;
|
|||
|
+}
|
|||
|
+
|
|||
|
+static grub_err_t
|
|||
|
+grub_zfs_dir (grub_device_t device, const char *path,
|
|||
|
+ 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);
|
|||
|
if (! data)
|
|||
|
@@ -3860,6 +3904,8 @@ grub_zfs_dir (grub_device_t device, const char *path,
|
|||
|
zfs_unmount (data);
|
|||
|
return err;
|
|||
|
}
|
|||
|
+ ctx.data = data;
|
|||
|
+
|
|||
|
if (isfs)
|
|||
|
{
|
|||
|
grub_uint64_t childobj, headobj;
|
|||
|
@@ -3868,7 +3914,7 @@ grub_zfs_dir (grub_device_t device, const char *path,
|
|||
|
struct grub_dirhook_info info;
|
|||
|
|
|||
|
fill_fs_info (&info, data->dnode, data);
|
|||
|
- hook ("@", &info);
|
|||
|
+ hook ("@", &info, hook_data);
|
|||
|
|
|||
|
childobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&data->dnode.dn))->dd_child_dir_zapobj, data->dnode.endian);
|
|||
|
headobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&data->dnode.dn))->dd_head_dataset_obj, data->dnode.endian);
|
|||
|
@@ -3880,7 +3926,7 @@ grub_zfs_dir (grub_device_t device, const char *path,
|
|||
|
return err;
|
|||
|
}
|
|||
|
|
|||
|
- zap_iterate_u64 (&dn, iterate_zap_fs, data);
|
|||
|
+ zap_iterate_u64 (&dn, iterate_zap_fs, data, &ctx);
|
|||
|
|
|||
|
err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, &dn, data);
|
|||
|
if (err)
|
|||
|
@@ -3899,7 +3945,7 @@ grub_zfs_dir (grub_device_t device, const char *path,
|
|||
|
return err;
|
|||
|
}
|
|||
|
|
|||
|
- zap_iterate_u64 (&dn, iterate_zap_snap, data);
|
|||
|
+ zap_iterate_u64 (&dn, iterate_zap_snap, data, &ctx);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
@@ -3908,7 +3954,7 @@ grub_zfs_dir (grub_device_t device, const char *path,
|
|||
|
zfs_unmount (data);
|
|||
|
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
|
|||
|
}
|
|||
|
- zap_iterate_u64 (&(data->dnode), iterate_zap, data);
|
|||
|
+ zap_iterate_u64 (&(data->dnode), iterate_zap, data, &ctx);
|
|||
|
}
|
|||
|
zfs_unmount (data);
|
|||
|
return grub_errno;
|
|||
|
diff --git a/grub-core/kern/corecmd.c b/grub-core/kern/corecmd.c
|
|||
|
index 3441ccb..0dc4d00 100644
|
|||
|
--- a/grub-core/kern/corecmd.c
|
|||
|
+++ b/grub-core/kern/corecmd.c
|
|||
|
@@ -105,7 +105,8 @@ grub_mini_print_devices (const char *name, void *data __attribute__ ((unused)))
|
|||
|
|
|||
|
static int
|
|||
|
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 ? "/" : "");
|
|||
|
|
|||
|
@@ -160,7 +161,7 @@ grub_core_cmd_ls (struct grub_command *cmd __attribute__ ((unused)),
|
|||
|
}
|
|||
|
else if (fs)
|
|||
|
{
|
|||
|
- (fs->dir) (dev, path, grub_mini_print_files);
|
|||
|
+ (fs->dir) (dev, path, grub_mini_print_files, NULL);
|
|||
|
grub_xputs ("\n");
|
|||
|
grub_refresh ();
|
|||
|
}
|
|||
|
diff --git a/grub-core/kern/emu/hostfs.c b/grub-core/kern/emu/hostfs.c
|
|||
|
index 3cb089c..46bf5e8 100644
|
|||
|
--- a/grub-core/kern/emu/hostfs.c
|
|||
|
+++ b/grub-core/kern/emu/hostfs.c
|
|||
|
@@ -65,8 +65,7 @@ struct grub_hostfs_data
|
|||
|
|
|||
|
static grub_err_t
|
|||
|
grub_hostfs_dir (grub_device_t device, const char *path,
|
|||
|
- int (*hook) (const char *filename,
|
|||
|
- const struct grub_dirhook_info *info))
|
|||
|
+ grub_fs_dir_hook_t hook, void *hook_data)
|
|||
|
{
|
|||
|
DIR *dir;
|
|||
|
|
|||
|
@@ -91,7 +90,7 @@ grub_hostfs_dir (grub_device_t device, const char *path,
|
|||
|
break;
|
|||
|
|
|||
|
info.dir = !! is_dir (path, de->d_name);
|
|||
|
- hook (de->d_name, &info);
|
|||
|
+ hook (de->d_name, &info, hook_data);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
diff --git a/grub-core/kern/fs.c b/grub-core/kern/fs.c
|
|||
|
index 7e150f2..9085895 100644
|
|||
|
--- a/grub-core/kern/fs.c
|
|||
|
+++ b/grub-core/kern/fs.c
|
|||
|
@@ -35,10 +35,11 @@ grub_fs_autoload_hook_t grub_fs_autoload_hook = 0;
|
|||
|
/* Helper for grub_fs_probe. */
|
|||
|
static int
|
|||
|
probe_dummy_iter (const char *filename __attribute__ ((unused)),
|
|||
|
- const struct grub_dirhook_info *info __attribute__ ((unused)))
|
|||
|
- {
|
|||
|
- return 1;
|
|||
|
- }
|
|||
|
+ const struct grub_dirhook_info *info __attribute__ ((unused)),
|
|||
|
+ void *data __attribute__ ((unused)))
|
|||
|
+{
|
|||
|
+ return 1;
|
|||
|
+}
|
|||
|
|
|||
|
grub_fs_t
|
|||
|
grub_fs_probe (grub_device_t device)
|
|||
|
@@ -69,7 +70,7 @@ grub_fs_probe (grub_device_t device)
|
|||
|
}
|
|||
|
else
|
|||
|
#endif
|
|||
|
- (p->dir) (device, "/", probe_dummy_iter);
|
|||
|
+ (p->dir) (device, "/", probe_dummy_iter, NULL);
|
|||
|
if (grub_errno == GRUB_ERR_NONE)
|
|||
|
return p;
|
|||
|
|
|||
|
@@ -93,7 +94,7 @@ grub_fs_probe (grub_device_t device)
|
|||
|
{
|
|||
|
p = grub_fs_list;
|
|||
|
|
|||
|
- (p->dir) (device, "/", probe_dummy_iter);
|
|||
|
+ (p->dir) (device, "/", probe_dummy_iter, NULL);
|
|||
|
if (grub_errno == GRUB_ERR_NONE)
|
|||
|
{
|
|||
|
count--;
|
|||
|
diff --git a/grub-core/loader/xnu.c b/grub-core/loader/xnu.c
|
|||
|
index ed3fc72..8c522f5 100644
|
|||
|
--- a/grub-core/loader/xnu.c
|
|||
|
+++ b/grub-core/loader/xnu.c
|
|||
|
@@ -1017,49 +1017,66 @@ grub_xnu_check_os_bundle_required (char *plistname,
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
+/* Context for grub_xnu_scan_dir_for_kexts. */
|
|||
|
+struct grub_xnu_scan_dir_for_kexts_ctx
|
|||
|
+{
|
|||
|
+ char *dirname;
|
|||
|
+ const char *osbundlerequired;
|
|||
|
+ int maxrecursion;
|
|||
|
+};
|
|||
|
+
|
|||
|
+/* Helper for grub_xnu_scan_dir_for_kexts. */
|
|||
|
+static int
|
|||
|
+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;
|
|||
|
+
|
|||
|
+ if (! info->dir)
|
|||
|
+ return 0;
|
|||
|
+ if (filename[0] == '.')
|
|||
|
+ return 0;
|
|||
|
+
|
|||
|
+ if (grub_strlen (filename) < 5 ||
|
|||
|
+ grub_memcmp (filename + grub_strlen (filename) - 5, ".kext", 5) != 0)
|
|||
|
+ return 0;
|
|||
|
+
|
|||
|
+ newdirname
|
|||
|
+ = grub_malloc (grub_strlen (ctx->dirname) + grub_strlen (filename) + 2);
|
|||
|
+
|
|||
|
+ /* It's a .kext. Try to load it. */
|
|||
|
+ if (newdirname)
|
|||
|
+ {
|
|||
|
+ grub_strcpy (newdirname, ctx->dirname);
|
|||
|
+ newdirname[grub_strlen (newdirname) + 1] = 0;
|
|||
|
+ newdirname[grub_strlen (newdirname)] = '/';
|
|||
|
+ grub_strcpy (newdirname + grub_strlen (newdirname), filename);
|
|||
|
+ grub_xnu_load_kext_from_dir (newdirname, ctx->osbundlerequired,
|
|||
|
+ ctx->maxrecursion);
|
|||
|
+ if (grub_errno == GRUB_ERR_BAD_OS)
|
|||
|
+ grub_errno = GRUB_ERR_NONE;
|
|||
|
+ grub_free (newdirname);
|
|||
|
+ }
|
|||
|
+ 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;
|
|||
|
|
|||
|
- auto int load_hook (const char *filename,
|
|||
|
- const struct grub_dirhook_info *info);
|
|||
|
- int load_hook (const char *filename, const struct grub_dirhook_info *info)
|
|||
|
- {
|
|||
|
- char *newdirname;
|
|||
|
- if (! info->dir)
|
|||
|
- return 0;
|
|||
|
- if (filename[0] == '.')
|
|||
|
- return 0;
|
|||
|
-
|
|||
|
- if (grub_strlen (filename) < 5 ||
|
|||
|
- grub_memcmp (filename + grub_strlen (filename) - 5, ".kext", 5) != 0)
|
|||
|
- return 0;
|
|||
|
-
|
|||
|
- newdirname
|
|||
|
- = grub_malloc (grub_strlen (dirname) + grub_strlen (filename) + 2);
|
|||
|
-
|
|||
|
- /* It's a .kext. Try to load it. */
|
|||
|
- if (newdirname)
|
|||
|
- {
|
|||
|
- grub_strcpy (newdirname, dirname);
|
|||
|
- newdirname[grub_strlen (newdirname) + 1] = 0;
|
|||
|
- newdirname[grub_strlen (newdirname)] = '/';
|
|||
|
- grub_strcpy (newdirname + grub_strlen (newdirname), filename);
|
|||
|
- grub_xnu_load_kext_from_dir (newdirname, osbundlerequired,
|
|||
|
- maxrecursion);
|
|||
|
- if (grub_errno == GRUB_ERR_BAD_OS)
|
|||
|
- grub_errno = GRUB_ERR_NONE;
|
|||
|
- grub_free (newdirname);
|
|||
|
- }
|
|||
|
- return 0;
|
|||
|
- }
|
|||
|
-
|
|||
|
if (! grub_xnu_heap_size)
|
|||
|
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++;
|
|||
|
|
|||
|
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_free (device_name);
|
|||
|
@@ -1083,60 +1100,78 @@ grub_xnu_scan_dir_for_kexts (char *dirname, const char *osbundlerequired,
|
|||
|
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) */
|
|||
|
grub_err_t
|
|||
|
grub_xnu_load_kext_from_dir (char *dirname, const char *osbundlerequired,
|
|||
|
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;
|
|||
|
- char *plistname = 0;
|
|||
|
- char *newdirname;
|
|||
|
char *newpath;
|
|||
|
char *device_name;
|
|||
|
grub_fs_t fs;
|
|||
|
const char *path;
|
|||
|
char *binsuffix;
|
|||
|
- int usemacos = 0;
|
|||
|
grub_file_t binfile;
|
|||
|
|
|||
|
- auto int load_hook (const char *filename,
|
|||
|
- const struct grub_dirhook_info *info);
|
|||
|
-
|
|||
|
- 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)
|
|||
|
+ ctx.newdirname = grub_malloc (grub_strlen (dirname) + 20);
|
|||
|
+ if (! ctx.newdirname)
|
|||
|
return grub_errno;
|
|||
|
- grub_strcpy (newdirname, dirname);
|
|||
|
- newdirname[grub_strlen (dirname)] = '/';
|
|||
|
- newdirname[grub_strlen (dirname) + 1] = 0;
|
|||
|
+ grub_strcpy (ctx.newdirname, dirname);
|
|||
|
+ ctx.newdirname[grub_strlen (dirname)] = '/';
|
|||
|
+ ctx.newdirname[grub_strlen (dirname) + 1] = 0;
|
|||
|
device_name = grub_file_get_device_name (dirname);
|
|||
|
dev = grub_device_open (device_name);
|
|||
|
if (dev)
|
|||
|
@@ -1148,18 +1183,18 @@ grub_xnu_load_kext_from_dir (char *dirname, const char *osbundlerequired,
|
|||
|
else
|
|||
|
path++;
|
|||
|
|
|||
|
- newpath = grub_strchr (newdirname, ')');
|
|||
|
+ newpath = grub_strchr (ctx.newdirname, ')');
|
|||
|
if (! newpath)
|
|||
|
- newpath = newdirname;
|
|||
|
+ newpath = ctx.newdirname;
|
|||
|
else
|
|||
|
newpath++;
|
|||
|
|
|||
|
/* Look at the directory. */
|
|||
|
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
|
|||
|
- (plistname, osbundlerequired, &binsuffix))
|
|||
|
+ if (ctx.plistname && grub_xnu_check_os_bundle_required
|
|||
|
+ (ctx.plistname, osbundlerequired, &binsuffix))
|
|||
|
{
|
|||
|
if (binsuffix)
|
|||
|
{
|
|||
|
@@ -1168,29 +1203,29 @@ grub_xnu_load_kext_from_dir (char *dirname, const char *osbundlerequired,
|
|||
|
+ grub_strlen (binsuffix)
|
|||
|
+ sizeof ("/MacOS/"));
|
|||
|
grub_strcpy (binname, dirname);
|
|||
|
- if (usemacos)
|
|||
|
+ if (ctx.usemacos)
|
|||
|
grub_strcpy (binname + grub_strlen (binname), "/MacOS/");
|
|||
|
else
|
|||
|
grub_strcpy (binname + grub_strlen (binname), "/");
|
|||
|
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);
|
|||
|
if (! binfile)
|
|||
|
grub_errno = GRUB_ERR_NONE;
|
|||
|
|
|||
|
/* Load the extension. */
|
|||
|
- grub_xnu_load_driver (plistname, binfile,
|
|||
|
+ grub_xnu_load_driver (ctx.plistname, binfile,
|
|||
|
binname);
|
|||
|
grub_free (binname);
|
|||
|
grub_free (binsuffix);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
- grub_dprintf ("xnu", "%s:0\n", plistname);
|
|||
|
- grub_xnu_load_driver (plistname, 0, 0);
|
|||
|
+ grub_dprintf ("xnu", "%s:0\n", ctx.plistname);
|
|||
|
+ grub_xnu_load_driver (ctx.plistname, 0, 0);
|
|||
|
}
|
|||
|
}
|
|||
|
- grub_free (plistname);
|
|||
|
+ grub_free (ctx.plistname);
|
|||
|
grub_device_close (dev);
|
|||
|
}
|
|||
|
grub_free (device_name);
|
|||
|
diff --git a/grub-core/net/net.c b/grub-core/net/net.c
|
|||
|
index 01c5d32..aebbe4b 100644
|
|||
|
--- a/grub-core/net/net.c
|
|||
|
+++ b/grub-core/net/net.c
|
|||
|
@@ -1253,8 +1253,8 @@ grub_net_open_real (const char *name)
|
|||
|
|
|||
|
static grub_err_t
|
|||
|
grub_net_fs_dir (grub_device_t device, const char *path __attribute__ ((unused)),
|
|||
|
- int (*hook) (const char *filename,
|
|||
|
- const struct grub_dirhook_info *info) __attribute__ ((unused)))
|
|||
|
+ grub_fs_dir_hook_t hook __attribute__ ((unused)),
|
|||
|
+ void *hook_data __attribute__ ((unused)))
|
|||
|
{
|
|||
|
if (!device->net)
|
|||
|
return grub_error (GRUB_ERR_BUG, "invalid net device");
|
|||
|
diff --git a/grub-core/normal/completion.c b/grub-core/normal/completion.c
|
|||
|
index 367a2b7..71c083c 100644
|
|||
|
--- a/grub-core/normal/completion.c
|
|||
|
+++ b/grub-core/normal/completion.c
|
|||
|
@@ -123,7 +123,8 @@ iterate_partition (grub_disk_t disk, const grub_partition_t p,
|
|||
|
}
|
|||
|
|
|||
|
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)
|
|||
|
{
|
|||
|
@@ -295,7 +296,7 @@ complete_file (void)
|
|||
|
dirfile[1] = '\0';
|
|||
|
|
|||
|
/* Iterate the directory. */
|
|||
|
- (fs->dir) (dev, dir, iterate_dir);
|
|||
|
+ (fs->dir) (dev, dir, iterate_dir, NULL);
|
|||
|
|
|||
|
grub_free (dir);
|
|||
|
|
|||
|
diff --git a/include/grub/fs.h b/include/grub/fs.h
|
|||
|
index 503d1a9..e451797 100644
|
|||
|
--- a/include/grub/fs.h
|
|||
|
+++ b/include/grub/fs.h
|
|||
|
@@ -41,6 +41,10 @@ struct grub_dirhook_info
|
|||
|
grub_int32_t mtime;
|
|||
|
};
|
|||
|
|
|||
|
+typedef int (*grub_fs_dir_hook_t) (const char *filename,
|
|||
|
+ const struct grub_dirhook_info *info,
|
|||
|
+ void *data);
|
|||
|
+
|
|||
|
/* Filesystem descriptor. */
|
|||
|
struct grub_fs
|
|||
|
{
|
|||
|
@@ -53,8 +57,7 @@ struct grub_fs
|
|||
|
|
|||
|
/* Call HOOK with each file under DIR. */
|
|||
|
grub_err_t (*dir) (grub_device_t device, const char *path,
|
|||
|
- int (*hook) (const char *filename,
|
|||
|
- const struct grub_dirhook_info *info));
|
|||
|
+ grub_fs_dir_hook_t hook, void *hook_data);
|
|||
|
|
|||
|
/* Open a file named NAME and initialize FILE. */
|
|||
|
grub_err_t (*open) (struct grub_file *file, const char *name);
|
|||
|
diff --git a/include/grub/fshelp.h b/include/grub/fshelp.h
|
|||
|
index 4838fca..e437d4c 100644
|
|||
|
--- a/include/grub/fshelp.h
|
|||
|
+++ b/include/grub/fshelp.h
|
|||
|
@@ -38,24 +38,25 @@ enum grub_fshelp_filetype
|
|||
|
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
|
|||
|
directory tree. The node found is returned in FOUNDNODE, which is
|
|||
|
either a ROOTNODE or a new malloc'ed node. ITERATE_DIR is used to
|
|||
|
iterate over all directory entries in the current node.
|
|||
|
READ_SYMLINK is used to read the symlink if a node is a symlink.
|
|||
|
EXPECTTYPE is the type node that is expected by the called, an
|
|||
|
- error is generated if the node is not of the expected type. Make
|
|||
|
- sure you use the NESTED_FUNC_ATTR macro for HOOK, this is required
|
|||
|
- because GCC has a nasty bug when using regparm=3. */
|
|||
|
+ error is generated if the node is not of the expected type. */
|
|||
|
grub_err_t
|
|||
|
EXPORT_FUNC(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)),
|
|||
|
+ grub_fshelp_iterate_dir_hook_t hook,
|
|||
|
+ void *hook_data),
|
|||
|
char *(*read_symlink) (grub_fshelp_node_t node),
|
|||
|
enum grub_fshelp_filetype expect);
|
|||
|
|
|||
|
diff --git a/util/grub-mount.c b/util/grub-mount.c
|
|||
|
index e3eb1d7..d0ab6a2 100644
|
|||
|
--- a/util/grub-mount.c
|
|||
|
+++ b/util/grub-mount.c
|
|||
|
@@ -116,30 +116,38 @@ translate_error (void)
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
+/* Context for fuse_getattr. */
|
|||
|
+struct fuse_getattr_ctx
|
|||
|
+{
|
|||
|
+ char *filename;
|
|||
|
+ struct grub_dirhook_info file_info;
|
|||
|
+ int file_exists;
|
|||
|
+};
|
|||
|
+
|
|||
|
+/* A hook for iterating directories. */
|
|||
|
+static int
|
|||
|
+fuse_getattr_find_file (const char *cur_filename,
|
|||
|
+ const struct grub_dirhook_info *info, void *data)
|
|||
|
+{
|
|||
|
+ struct fuse_getattr_ctx *ctx = data;
|
|||
|
+
|
|||
|
+ if ((info->case_insensitive ? grub_strcasecmp (cur_filename, ctx->filename)
|
|||
|
+ : grub_strcmp (cur_filename, ctx->filename)) == 0)
|
|||
|
+ {
|
|||
|
+ ctx->file_info = *info;
|
|||
|
+ ctx->file_exists = 1;
|
|||
|
+ return 1;
|
|||
|
+ }
|
|||
|
+ return 0;
|
|||
|
+}
|
|||
|
+
|
|||
|
static int
|
|||
|
fuse_getattr (const char *path, struct stat *st)
|
|||
|
{
|
|||
|
- char *filename, *pathname, *path2;
|
|||
|
+ struct fuse_getattr_ctx ctx;
|
|||
|
+ char *pathname, *path2;
|
|||
|
const char *pathname_t;
|
|||
|
- struct grub_dirhook_info file_info;
|
|||
|
- int file_exists = 0;
|
|||
|
|
|||
|
- /* A hook for iterating directories. */
|
|||
|
- 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;
|
|||
|
- }
|
|||
|
-
|
|||
|
if (path[0] == '/' && path[1] == 0)
|
|||
|
{
|
|||
|
st->st_dev = 0;
|
|||
|
@@ -155,7 +163,7 @@ fuse_getattr (const char *path, struct stat *st)
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
- file_exists = 0;
|
|||
|
+ ctx.file_exists = 0;
|
|||
|
|
|||
|
pathname_t = grub_strchr (path, ')');
|
|||
|
if (! pathname_t)
|
|||
|
@@ -169,35 +177,35 @@ fuse_getattr (const char *path, struct stat *st)
|
|||
|
pathname[grub_strlen (pathname) - 1] = 0;
|
|||
|
|
|||
|
/* Split into path and filename. */
|
|||
|
- filename = grub_strrchr (pathname, '/');
|
|||
|
- if (! filename)
|
|||
|
+ ctx.filename = grub_strrchr (pathname, '/');
|
|||
|
+ if (! ctx.filename)
|
|||
|
{
|
|||
|
path2 = grub_strdup ("/");
|
|||
|
- filename = pathname;
|
|||
|
+ ctx.filename = pathname;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
- filename++;
|
|||
|
+ ctx.filename++;
|
|||
|
path2 = grub_strdup (pathname);
|
|||
|
- path2[filename - pathname] = 0;
|
|||
|
+ path2[ctx.filename - pathname] = 0;
|
|||
|
}
|
|||
|
|
|||
|
/* It's the whole device. */
|
|||
|
- (fs->dir) (dev, path2, find_file);
|
|||
|
+ (fs->dir) (dev, path2, fuse_getattr_find_file, &ctx);
|
|||
|
|
|||
|
grub_free (path2);
|
|||
|
- if (!file_exists)
|
|||
|
+ if (!ctx.file_exists)
|
|||
|
{
|
|||
|
grub_errno = GRUB_ERR_NONE;
|
|||
|
return -ENOENT;
|
|||
|
}
|
|||
|
st->st_dev = 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_gid = 0;
|
|||
|
st->st_rdev = 0;
|
|||
|
- if (!file_info.dir)
|
|||
|
+ if (!ctx.file_info.dir)
|
|||
|
{
|
|||
|
grub_file_t file;
|
|||
|
file = grub_file_open (path);
|
|||
|
@@ -210,8 +218,8 @@ fuse_getattr (const char *path, struct stat *st)
|
|||
|
st->st_size = 0;
|
|||
|
st->st_blksize = 512;
|
|||
|
st->st_blocks = (st->st_size + 511) >> 9;
|
|||
|
- st->st_atime = st->st_mtime = st->st_ctime = file_info.mtimeset
|
|||
|
- ? file_info.mtime : 0;
|
|||
|
+ st->st_atime = st->st_mtime = st->st_ctime = ctx.file_info.mtimeset
|
|||
|
+ ? ctx.file_info.mtime : 0;
|
|||
|
grub_errno = GRUB_ERR_NONE;
|
|||
|
return 0;
|
|||
|
}
|
|||
|
@@ -271,39 +279,55 @@ fuse_release (const char *path, struct fuse_file_info *fi)
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
+/* Context for fuse_readdir. */
|
|||
|
+struct fuse_readdir_ctx
|
|||
|
+{
|
|||
|
+ const char *path;
|
|||
|
+ void *buf;
|
|||
|
+ fuse_fill_dir_t fill;
|
|||
|
+};
|
|||
|
+
|
|||
|
+/* Helper for fuse_readdir. */
|
|||
|
+static int
|
|||
|
+fuse_readdir_call_fill (const char *filename,
|
|||
|
+ const struct grub_dirhook_info *info, void *data)
|
|||
|
+{
|
|||
|
+ struct fuse_readdir_ctx *ctx = data;
|
|||
|
+ struct stat st;
|
|||
|
+
|
|||
|
+ grub_memset (&st, 0, sizeof (st));
|
|||
|
+ st.st_mode = info->dir ? (0555 | S_IFDIR) : (0444 | S_IFREG);
|
|||
|
+ if (!info->dir)
|
|||
|
+ {
|
|||
|
+ grub_file_t file;
|
|||
|
+ char *tmp;
|
|||
|
+ tmp = xasprintf ("%s/%s", ctx->path, filename);
|
|||
|
+ file = grub_file_open (tmp);
|
|||
|
+ free (tmp);
|
|||
|
+ if (! file)
|
|||
|
+ return translate_error ();
|
|||
|
+ st.st_size = file->size;
|
|||
|
+ grub_file_close (file);
|
|||
|
+ }
|
|||
|
+ st.st_blksize = 512;
|
|||
|
+ st.st_blocks = (st.st_size + 511) >> 9;
|
|||
|
+ st.st_atime = st.st_mtime = st.st_ctime
|
|||
|
+ = info->mtimeset ? info->mtime : 0;
|
|||
|
+ ctx->fill (ctx->buf, filename, &st, 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;
|
|||
|
|
|||
|
- auto int call_fill (const char *filename,
|
|||
|
- const struct grub_dirhook_info *info);
|
|||
|
- int call_fill (const char *filename, const struct grub_dirhook_info *info)
|
|||
|
- {
|
|||
|
- struct stat st;
|
|||
|
- grub_memset (&st, 0, sizeof (st));
|
|||
|
- st.st_mode = info->dir ? (0555 | S_IFDIR) : (0444 | S_IFREG);
|
|||
|
- if (!info->dir)
|
|||
|
- {
|
|||
|
- grub_file_t file;
|
|||
|
- char *tmp;
|
|||
|
- tmp = xasprintf ("%s/%s", path, filename);
|
|||
|
- file = grub_file_open (tmp);
|
|||
|
- free (tmp);
|
|||
|
- if (! file)
|
|||
|
- return translate_error ();
|
|||
|
- st.st_size = file->size;
|
|||
|
- grub_file_close (file);
|
|||
|
- }
|
|||
|
- st.st_blksize = 512;
|
|||
|
- st.st_blocks = (st.st_size + 511) >> 9;
|
|||
|
- st.st_atime = st.st_mtime = st.st_ctime
|
|||
|
- = info->mtimeset ? info->mtime : 0;
|
|||
|
- fill (buf, filename, &st, 0);
|
|||
|
- return 0;
|
|||
|
- }
|
|||
|
-
|
|||
|
pathname = xstrdup (path);
|
|||
|
|
|||
|
/* Remove trailing '/'. */
|
|||
|
@@ -311,7 +335,7 @@ fuse_readdir (const char *path, void *buf,
|
|||
|
&& pathname[grub_strlen (pathname) - 1] == '/')
|
|||
|
pathname[grub_strlen (pathname) - 1] = 0;
|
|||
|
|
|||
|
- (fs->dir) (dev, pathname, call_fill);
|
|||
|
+ (fs->dir) (dev, pathname, fuse_readdir_call_fill, &ctx);
|
|||
|
free (pathname);
|
|||
|
grub_errno = GRUB_ERR_NONE;
|
|||
|
return 0;
|
|||
|
--
|
|||
|
1.8.1.4
|
|||
|
|