]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
HFS: Convert to fshelp.
authorVladimir Serbinenko <phcoder@gmail.com>
Mon, 27 Jul 2015 10:50:22 +0000 (12:50 +0200)
committerVladimir Serbinenko <phcoder@gmail.com>
Mon, 27 Jul 2015 10:50:22 +0000 (12:50 +0200)
HFS doesn't handle "." and ".." properly. Convert it to fshelp to reuse the
logic.

grub-core/fs/hfs.c

index 06cf0c7abbd1d4f4ab3489eb3586cf1990f143bb..0ebc71b6264567539af774bfcee9fd5fd2eab01d 100644 (file)
@@ -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;
-
-  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
@@ -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;
 }