]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
* grub-core/fs/affs.c (grub_affs_file): New field hardlink.
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Sat, 26 May 2012 22:45:41 +0000 (00:45 +0200)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Sat, 26 May 2012 22:45:41 +0000 (00:45 +0200)
(GRUB_AFFS_FILETYPE_HARDLINK): New enum value.
(grub_affs_iterate_dir): Handle hardlinks.

ChangeLog
grub-core/fs/affs.c

index 20dd6860a5f8ae29e2e85ff31ff4208f46e787d5..77a2c482033fba0638d078c3a1097ebe22d4b888 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2012-05-27  Vladimir Serbinenko  <phcoder@gmail.com>
+
+       * grub-core/fs/affs.c (grub_affs_file): New field hardlink.
+       (GRUB_AFFS_FILETYPE_HARDLINK): New enum value.
+       (grub_affs_iterate_dir): Handle hardlinks.
+
 2012-05-26  Matthew Garrett  <mjg@redhat.com>
 
        * grub-core/term/efi/console.c (grub_efi_console_init): Set text mode.
index 6d7577be5858f76ec5fc8d2ac187e3ab093409ba..ef654791c86e78226fa0b0c4d5ebd61cbe24576e 100644 (file)
@@ -69,7 +69,9 @@ struct grub_affs_file
   struct grub_affs_time mtime;
   grub_uint8_t namelen;
   grub_uint8_t name[30];
-  grub_uint8_t unused3[33];
+  grub_uint8_t unused3[5];
+  grub_uint32_t hardlink;
+  grub_uint32_t unused4[6];
   grub_uint32_t next;
   grub_uint32_t parent;
   grub_uint32_t extension;
@@ -86,9 +88,13 @@ struct grub_affs_file
 #define GRUB_AFFS_BLOCKPTR_OFFSET      24
 #define GRUB_AFFS_SYMLINK_OFFSET       24
 
-#define GRUB_AFFS_FILETYPE_REG         0xfffffffd
-#define GRUB_AFFS_FILETYPE_DIR         2
-#define GRUB_AFFS_FILETYPE_SYMLINK     3
+enum
+  {
+    GRUB_AFFS_FILETYPE_DIR = 2,
+    GRUB_AFFS_FILETYPE_SYMLINK = 3,
+    GRUB_AFFS_FILETYPE_HARDLINK = 0xfffffffc,
+    GRUB_AFFS_FILETYPE_REG = 0xfffffffd
+  };
 
 #define AFFS_MAX_LOG_BLOCK_SIZE 4
 
@@ -333,6 +339,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
       int type;
       grub_uint8_t name_u8[sizeof (fil->name) * GRUB_MAX_UTF8_PER_LATIN1 + 1];
       grub_size_t len;
+      unsigned int nest;
 
       node = grub_zalloc (sizeof (*node));
       if (!node)
@@ -341,20 +348,8 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
          return 1;
        }
 
-      if (grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_REG)
-       type = GRUB_FSHELP_REG;
-      else if (grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_DIR)
-       type = GRUB_FSHELP_DIR;
-      else if (grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_SYMLINK)
-       type = GRUB_FSHELP_SYMLINK;
-      else
-       type = GRUB_FSHELP_UNKNOWN;
-
-      type |= GRUB_FSHELP_CASE_INSENSITIVE;
-
       node->data = data;
       node->block = block;
-      node->di = *fil;
       node->parent = dir;
 
       len = fil->namelen;
@@ -362,6 +357,44 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
        len = sizeof (fil->name);
       *grub_latin1_to_utf8 (name_u8, fil->name, len) = '\0';
       
+      node->di = *fil;
+      for (nest = 0; nest < 8; nest++)
+       {
+         switch (node->di.type)
+           {
+           case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_REG):
+             type = GRUB_FSHELP_REG;
+             break;
+           case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_DIR):
+             type = GRUB_FSHELP_DIR;
+             break;
+           case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_SYMLINK):
+             type = GRUB_FSHELP_SYMLINK;
+             break;
+           case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_HARDLINK):
+             {
+               grub_err_t err;
+               node->block = grub_be_to_cpu32 (node->di.hardlink);
+               err = grub_disk_read (data->disk,
+                                     (((grub_uint64_t) node->block + 1) << data->log_blocksize)
+                                     - 1,
+                                     GRUB_DISK_SECTOR_SIZE - GRUB_AFFS_FILE_LOCATION,
+                                     sizeof (node->di), (char *) &node->di);
+               if (err)
+                 return 1;
+               continue;
+             }
+           default:
+             return 0;
+           }
+         break;
+       }
+
+      if (nest == 8)
+       return 0;
+
+      type |= GRUB_FSHELP_CASE_INSENSITIVE;
+
       if (hook ((char *) name_u8, type, node))
        {
          grub_free (hashtable);