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
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue