]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Handle "." and ".." on squashfs.
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Sun, 27 May 2012 11:44:48 +0000 (13:44 +0200)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Sun, 27 May 2012 11:44:48 +0000 (13:44 +0200)
* grub-core/fs/squash4.c (grub_fshelp_node): New field stsize.
Make inode numbers into stack.
(grub_squash_read_symlink): Use stack.
(grub_squash_iterate_dir): Use stack. Create "." and ".." nodes.
(make_root_node): Fill stack.
(grub_squash_open): Use stack.

ChangeLog
grub-core/fs/squash4.c

index 1d76f8461343478730ad09185a7a00a5b1fb5c25..a18465ba4df77b4204a3ef6be05b85db0af9e613 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2012-05-27  Vladimir Serbinenko  <phcoder@gmail.com>
+
+       Handle "." and ".." on squashfs.
+
+       * grub-core/fs/squash4.c (grub_fshelp_node): New field stsize.
+       Make inode numbers into stack.
+       (grub_squash_read_symlink): Use stack.
+       (grub_squash_iterate_dir): Use stack. Create "." and ".." nodes.
+       (make_root_node): Fill stack.
+       (grub_squash_open): Use stack.
+
 2012-05-27  Vladimir Serbinenko  <phcoder@gmail.com>
 
        * grub-core/kern/emu/hostdisk.c (open_device): Set dest->dev to 0 after
index c46d29e69fa0101a1aa6bd9c59bbd197913fa276..44af0f82a28e1064b04ed28c83c57c7fddfa4a14 100644 (file)
@@ -208,8 +208,12 @@ struct grub_fshelp_node
 {
   struct grub_squash_data *data;
   struct grub_squash_inode ino;
-  grub_disk_addr_t ino_chunk;
-  grub_uint16_t        ino_offset;
+  grub_size_t stsize;
+  struct 
+  {
+    grub_disk_addr_t ino_chunk;
+    grub_uint16_t ino_offset;
+  } stack[1];
 };
 
 static grub_err_t
@@ -460,9 +464,9 @@ grub_squash_read_symlink (grub_fshelp_node_t node)
   err = read_chunk (node->data, ret,
                    grub_le_to_cpu32 (node->ino.symlink.namelen),
                    grub_le_to_cpu64 (node->data->sb.inodeoffset)
-                   + node->ino_chunk,
-                   node->ino_offset + (node->ino.symlink.name
-                                       - (char *) &node->ino));
+                   + node->stack[node->stsize - 1].ino_chunk,
+                   node->stack[node->stsize - 1].ino_offset
+                   + (node->ino.symlink.name - (char *) &node->ino));
   if (err)
     {
       grub_free (ret);
@@ -503,6 +507,40 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
       return 0;
     }
 
+  {
+    grub_fshelp_node_t node;
+    node = grub_malloc (sizeof (*node) + dir->stsize * sizeof (dir->stack[0]));
+    if (!node)
+      return 0;
+    grub_memcpy (node, dir,
+                sizeof (*node) + dir->stsize * sizeof (dir->stack[0]));
+    if (hook (".", GRUB_FSHELP_DIR, node))
+      return 1;
+
+    if (dir->stsize != 1)
+      {
+       grub_err_t err;
+
+       node = grub_malloc (sizeof (*node) + dir->stsize * sizeof (dir->stack[0]));
+       if (!node)
+         return 0;
+
+       grub_memcpy (node, dir,
+                    sizeof (*node) + dir->stsize * sizeof (dir->stack[0]));
+
+       node->stsize--;
+       err = read_chunk (dir->data, &node->ino, sizeof (node->ino),
+                         grub_le_to_cpu64 (dir->data->sb.inodeoffset)
+                         + node->stack[node->stsize - 1].ino_chunk,
+                         node->stack[node->stsize - 1].ino_offset);
+       if (err)
+         return 0;
+
+       if (hook ("..", GRUB_FSHELP_DIR, node))
+         return 1;
+      }
+  }
+
   while (off < endoff)
     {
       struct grub_squash_dirent_header dh;
@@ -554,14 +592,18 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
          if (grub_le_to_cpu16 (di.type) == SQUASH_TYPE_SYMLINK)
            filetype = GRUB_FSHELP_SYMLINK;
 
-         node = grub_malloc (sizeof (*node));
+         node = grub_malloc (sizeof (*node)
+                             + (dir->stsize + 1) * sizeof (dir->stack[0]));
          if (! node)
            return 0;
-         *node = *dir;
-         node->ino = ino;
-         node->ino_chunk = grub_le_to_cpu32 (dh.ino_chunk);
-         node->ino_offset = grub_le_to_cpu16 (di.ino_offset);
 
+         grub_memcpy (node, dir,
+                      sizeof (*node) + dir->stsize * sizeof (dir->stack[0]));
+
+         node->ino = ino;
+         node->stack[node->stsize].ino_chunk = grub_le_to_cpu32 (dh.ino_chunk);
+         node->stack[node->stsize].ino_offset = grub_le_to_cpu16 (di.ino_offset);
+         node->stsize++;
          r = hook (buf, filetype, node);
 
          grub_free (buf);
@@ -577,11 +619,13 @@ make_root_node (struct grub_squash_data *data, struct grub_fshelp_node *root)
 {
   grub_memset (root, 0, sizeof (*root));
   root->data = data;
+  root->stsize = 1;
+  root->stack[0].ino_chunk = grub_le_to_cpu32 (data->sb.root_ino_chunk);
+  root->stack[0].ino_offset = grub_cpu_to_le16 (data->sb.root_ino_offset);
  return read_chunk (data, &root->ino, sizeof (root->ino),
                    grub_le_to_cpu64 (data->sb.inodeoffset) 
-                   + grub_le_to_cpu32 (data->sb.root_ino_chunk),
-                   grub_cpu_to_le16 (data->sb.root_ino_offset));
+                   + root->stack[0].ino_chunk,
+                   root->stack[0].ino_offset);
 }
 
 static void
@@ -669,8 +713,8 @@ grub_squash_open (struct grub_file *file, const char *name)
   data->ino.ino = fdiro->ino;
   data->ino.block_sizes = NULL;
   data->ino.cumulated_block_sizes = NULL;
-  data->ino.ino_chunk = fdiro->ino_chunk;
-  data->ino.ino_offset = fdiro->ino_offset;
+  data->ino.ino_chunk = fdiro->stack[fdiro->stsize - 1].ino_chunk;
+  data->ino.ino_offset = fdiro->stack[fdiro->stsize - 1].ino_offset;
 
   switch (fdiro->ino.type)
     {