Remove nested functions from filesystem directory iterators.
* include/grub/fs.h (grub_fs_dir_hook_t): New type. (struct grub_fs.dir): Add hook_data argument. Update all implementations and callers.
This commit is contained in:
parent
53d3e4e3df
commit
fc524edf65
35 changed files with 1723 additions and 1451 deletions
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue