HFS: Convert to fshelp.
HFS doesn't handle "." and ".." properly. Convert it to fshelp to reuse the logic.
This commit is contained in:
parent
bfb5b33e96
commit
5fb1e859f7
1 changed files with 78 additions and 99 deletions
|
@ -29,6 +29,7 @@
|
|||
#include <grub/types.h>
|
||||
#include <grub/hfs.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/fshelp.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
|
@ -1125,90 +1126,81 @@ utf8_to_macroman (grub_uint8_t *to, const char *from)
|
|||
return optr - to;
|
||||
}
|
||||
|
||||
union grub_hfs_anyrec {
|
||||
struct grub_hfs_filerec frec;
|
||||
struct grub_hfs_dirrec dir;
|
||||
};
|
||||
|
||||
struct grub_fshelp_node
|
||||
{
|
||||
struct grub_hfs_data *data;
|
||||
union grub_hfs_anyrec fdrec;
|
||||
grub_uint32_t inode;
|
||||
};
|
||||
|
||||
static grub_err_t
|
||||
lookup_file (grub_fshelp_node_t dir,
|
||||
const char *name,
|
||||
grub_fshelp_node_t *foundnode,
|
||||
enum grub_fshelp_filetype *foundtype)
|
||||
{
|
||||
struct grub_hfs_catalog_key key;
|
||||
grub_ssize_t slen;
|
||||
union grub_hfs_anyrec fdrec;
|
||||
|
||||
key.parent_dir = grub_cpu_to_be32 (dir->inode);
|
||||
slen = utf8_to_macroman (key.str, name);
|
||||
if (slen < 0)
|
||||
/* Not found */
|
||||
return GRUB_ERR_NONE;
|
||||
key.strlen = slen;
|
||||
|
||||
/* Lookup this node. */
|
||||
if (! grub_hfs_find_node (dir->data, (char *) &key, dir->data->cat_root,
|
||||
0, (char *) &fdrec.frec, sizeof (fdrec.frec)))
|
||||
/* Not found */
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
*foundnode = grub_malloc (sizeof (struct grub_fshelp_node));
|
||||
if (!*foundnode)
|
||||
return grub_errno;
|
||||
|
||||
(*foundnode)->inode = grub_be_to_cpu32 (fdrec.dir.dirid);
|
||||
(*foundnode)->fdrec = fdrec;
|
||||
(*foundnode)->data = dir->data;
|
||||
*foundtype = (fdrec.frec.type == GRUB_HFS_FILETYPE_DIR) ? GRUB_FSHELP_DIR : GRUB_FSHELP_REG;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
/* Find a file or directory with the pathname PATH in the filesystem
|
||||
DATA. Return the file record in RETDATA when it is non-zero.
|
||||
Return the directory number in RETINODE when it is non-zero. */
|
||||
static grub_err_t
|
||||
grub_hfs_find_dir (struct grub_hfs_data *data, const char *path,
|
||||
struct grub_hfs_filerec *retdata, int *retinode)
|
||||
grub_fshelp_node_t *found,
|
||||
enum grub_fshelp_filetype exptype)
|
||||
{
|
||||
int inode = data->rootdir;
|
||||
char *next;
|
||||
char *origpath;
|
||||
union {
|
||||
struct grub_hfs_filerec frec;
|
||||
struct grub_hfs_dirrec dir;
|
||||
} fdrec;
|
||||
|
||||
fdrec.frec.type = GRUB_HFS_FILETYPE_DIR;
|
||||
|
||||
if (path[0] != '/')
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FILENAME, N_("invalid file name `%s'"), path);
|
||||
return 0;
|
||||
struct grub_fshelp_node root = {
|
||||
.data = data,
|
||||
.inode = data->rootdir,
|
||||
.fdrec = {
|
||||
.frec = {
|
||||
.type = GRUB_HFS_FILETYPE_DIR
|
||||
}
|
||||
}
|
||||
};
|
||||
grub_err_t err;
|
||||
|
||||
origpath = grub_strdup (path);
|
||||
if (!origpath)
|
||||
return grub_errno;
|
||||
err = grub_fshelp_find_file_lookup (path, &root, found, lookup_file, NULL, exptype);
|
||||
|
||||
path = origpath;
|
||||
while (*path == '/')
|
||||
path++;
|
||||
|
||||
while (path && grub_strlen (path))
|
||||
if (&root == *found)
|
||||
{
|
||||
grub_ssize_t slen;
|
||||
if (fdrec.frec.type != GRUB_HFS_FILETYPE_DIR)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Isolate a part of the path. */
|
||||
next = grub_strchr (path, '/');
|
||||
if (next)
|
||||
{
|
||||
while (*next == '/')
|
||||
*(next++) = '\0';
|
||||
}
|
||||
|
||||
struct grub_hfs_catalog_key key;
|
||||
|
||||
key.parent_dir = grub_cpu_to_be32 (inode);
|
||||
slen = utf8_to_macroman (key.str, path);
|
||||
if (slen < 0)
|
||||
{
|
||||
grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path);
|
||||
goto fail;
|
||||
}
|
||||
key.strlen = slen;
|
||||
|
||||
/* Lookup this node. */
|
||||
if (! grub_hfs_find_node (data, (char *) &key, data->cat_root,
|
||||
0, (char *) &fdrec.frec, sizeof (fdrec.frec)))
|
||||
{
|
||||
grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), origpath);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (grub_errno)
|
||||
goto fail;
|
||||
|
||||
inode = grub_be_to_cpu32 (fdrec.dir.dirid);
|
||||
path = next;
|
||||
*found = grub_malloc (sizeof (root));
|
||||
if (!*found)
|
||||
return grub_errno;
|
||||
grub_memcpy (*found, &root, sizeof (root));
|
||||
}
|
||||
|
||||
if (retdata)
|
||||
grub_memcpy (retdata, &fdrec.frec, sizeof (fdrec.frec));
|
||||
|
||||
if (retinode)
|
||||
*retinode = inode;
|
||||
|
||||
fail:
|
||||
grub_free (origpath);
|
||||
return grub_errno;
|
||||
return err;
|
||||
}
|
||||
|
||||
struct grub_hfs_dir_hook_ctx
|
||||
|
@ -1266,16 +1258,14 @@ static grub_err_t
|
|||
grub_hfs_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook,
|
||||
void *hook_data)
|
||||
{
|
||||
int inode;
|
||||
|
||||
struct grub_hfs_data *data;
|
||||
struct grub_hfs_filerec frec;
|
||||
struct grub_hfs_dir_hook_ctx ctx =
|
||||
{
|
||||
.hook = hook,
|
||||
.hook_data = hook_data
|
||||
};
|
||||
|
||||
grub_fshelp_node_t found = NULL;
|
||||
|
||||
grub_dl_ref (my_mod);
|
||||
|
||||
data = grub_hfs_mount (device->disk);
|
||||
|
@ -1283,18 +1273,13 @@ grub_hfs_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook,
|
|||
goto fail;
|
||||
|
||||
/* First the directory ID for the directory. */
|
||||
if (grub_hfs_find_dir (data, path, &frec, &inode))
|
||||
if (grub_hfs_find_dir (data, path, &found, GRUB_FSHELP_DIR))
|
||||
goto fail;
|
||||
|
||||
if (frec.type != GRUB_HFS_FILETYPE_DIR)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
grub_hfs_iterate_dir (data, data->cat_root, inode, grub_hfs_dir_hook, &ctx);
|
||||
grub_hfs_iterate_dir (data, data->cat_root, found->inode, grub_hfs_dir_hook, &ctx);
|
||||
|
||||
fail:
|
||||
grub_free (found);
|
||||
grub_free (data);
|
||||
|
||||
grub_dl_unref (my_mod);
|
||||
|
@ -1308,8 +1293,8 @@ static grub_err_t
|
|||
grub_hfs_open (struct grub_file *file, const char *name)
|
||||
{
|
||||
struct grub_hfs_data *data;
|
||||
struct grub_hfs_filerec frec;
|
||||
|
||||
grub_fshelp_node_t found = NULL;
|
||||
|
||||
grub_dl_ref (my_mod);
|
||||
|
||||
data = grub_hfs_mount (file->device->disk);
|
||||
|
@ -1320,29 +1305,23 @@ grub_hfs_open (struct grub_file *file, const char *name)
|
|||
return grub_errno;
|
||||
}
|
||||
|
||||
if (grub_hfs_find_dir (data, name, &frec, 0))
|
||||
if (grub_hfs_find_dir (data, name, &found, GRUB_FSHELP_REG))
|
||||
{
|
||||
grub_free (data);
|
||||
grub_dl_unref (my_mod);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
if (frec.type != GRUB_HFS_FILETYPE_FILE)
|
||||
{
|
||||
grub_free (data);
|
||||
grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file"));
|
||||
grub_dl_unref (my_mod);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
grub_memcpy (data->extents, frec.extents, sizeof (grub_hfs_datarecord_t));
|
||||
file->size = grub_be_to_cpu32 (frec.size);
|
||||
data->size = grub_be_to_cpu32 (frec.size);
|
||||
data->fileid = grub_be_to_cpu32 (frec.fileid);
|
||||
grub_memcpy (data->extents, found->fdrec.frec.extents, sizeof (grub_hfs_datarecord_t));
|
||||
file->size = grub_be_to_cpu32 (found->fdrec.frec.size);
|
||||
data->size = grub_be_to_cpu32 (found->fdrec.frec.size);
|
||||
data->fileid = grub_be_to_cpu32 (found->fdrec.frec.fileid);
|
||||
file->offset = 0;
|
||||
|
||||
file->data = data;
|
||||
|
||||
grub_free (found);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue