Remove nested functions from filesystem directory iterators.

* include/grub/fs.h (grub_fs_dir_hook_t): New type.
(struct grub_fs.dir): Add hook_data argument.

Update all implementations and callers.
This commit is contained in:
Colin Watson 2013-01-21 01:33:46 +00:00
parent 53d3e4e3df
commit fc524edf65
35 changed files with 1723 additions and 1451 deletions

View file

@ -279,63 +279,75 @@ match_devices (const regex_t *regexp, int noparts)
return 0;
}
/* Context for match_files. */
struct match_files_ctx
{
const regex_t *regexp;
char **files;
unsigned nfile;
char *dir;
};
/* 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;
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");
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;
}
ctx->files = t;
ctx->files[ctx->nfile++] = buffer;
ctx->files[ctx->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;
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;
/* 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", "matched\n");
buffer = grub_xasprintf ("%s%s", dir, name);
if (! buffer)
return 1;
t = grub_realloc (files, sizeof (char*) * (nfile + 2));
if (! t)
{
grub_free (buffer);
return 1;
}
files = t;
files[nfile++] = buffer;
files[nfile] = 0;
return 0;
}
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