#include <grub/types.h>
#include <grub/hfs.h>
#include <grub/i18n.h>
+#include <grub/fshelp.h>
GRUB_MOD_LICENSE ("GPLv3+");
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;
-
- path = origpath;
- while (*path == '/')
- path++;
+ err = grub_fshelp_find_file_lookup (path, &root, found, lookup_file, NULL, exptype);
- 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
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);
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);
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);
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;
}