]> glassweightruler.freedombox.rocks Git - Ventoy.git/blobdiff - GRUB2/MOD_SRC/grub-2.04/grub-core/kern/file.c
1.0.66 release
[Ventoy.git] / GRUB2 / MOD_SRC / grub-2.04 / grub-core / kern / file.c
index b4d5238c9d5ea3d5c65ff48bca90cbae83079d48..61e02614c01815e1977d6e0fd98d5c696ccb5ebf 100644 (file)
@@ -106,19 +106,109 @@ int ventoy_check_file_exist(const char * fmt, ...)
     }
 }
 
+typedef struct grub_vlnk
+{
+    int srclen;
+    char src[512];
+    char dst[512];
+    struct grub_vlnk *next;
+}grub_vlnk;
+
+static grub_vlnk *g_vlnk_list;
+
+int grub_file_is_vlnk_suffix(const char *name, int len)
+{
+    grub_uint32_t suffix;
+
+    if (len > 9)
+    {
+        suffix = *(grub_uint32_t *)(name + len - 4);
+        if (grub_strncmp(name + len - 9, ".vlnk.", 6) == 0)
+        {
+            /* .iso .wim .img .vhd .efi .dat */
+            if (suffix == 0x6F73692E || suffix == 0x6D69772E || 
+                suffix == 0x676D692E || suffix == 0x6468762E ||
+                suffix == 0x6966652E || suffix == 0x7461642E)
+            {
+                return 1;
+            }
+        }
+        else if (len > 10 && grub_strncmp(name + len - 10, ".vlnk.", 6) == 0)
+        {
+            /* vhdx vtoy */
+            if (suffix == 0x78646876 || suffix == 0x796F7476)
+            {
+                return 1;
+            }
+        }
+    }
+
+    return 0;
+}
+
+int grub_file_add_vlnk(const char *src, const char *dst)
+{
+    grub_vlnk *node = NULL;
+    
+    if (src && dst)
+    {
+        node = grub_zalloc(sizeof(grub_vlnk));    
+        if (node)
+        {
+            node->srclen = (int)grub_strlen(src);
+            grub_strncpy(node->src, src, sizeof(node->src) - 1);
+            grub_strncpy(node->dst, dst, sizeof(node->dst) - 1);
+
+            node->next = g_vlnk_list;
+            g_vlnk_list = node;
+            return 0;            
+        }
+    }
+
+    return 1;
+}
+
+const char *grub_file_get_vlnk(const char *name, int *vlnk)
+{
+    int len;
+    grub_vlnk *node = g_vlnk_list;
+
+    len = grub_strlen(name);
+    if (!grub_file_is_vlnk_suffix(name, len))
+    {
+        return name;
+    }
+    
+    while (node)
+    {
+        if (node->srclen == len && grub_strcmp(name, node->src) == 0)
+        {
+            *vlnk = 1;
+            return node->dst;
+        }
+        node = node->next;
+    }
+
+    return name;
+}
+
 grub_file_t
 grub_file_open (const char *name, enum grub_file_type type)
 {
+  int vlnk = 0;
   grub_device_t device = 0;
   grub_file_t file = 0, last_file = 0;
   char *device_name;
   const char *file_name;
   grub_file_filter_id_t filter;
 
-  /* <DESC> : mem:xxx:size:xxx format in chainloader */
-  if (grub_strncmp(name, GRUB_MEMFILE_MEM, grub_strlen(GRUB_MEMFILE_MEM)) == 0) {
+  /* <DESC> : mem:xxx:size:xxx format in chainloader grub_strlen(GRUB_MEMFILE_MEM) */
+  if (grub_strncmp(name, GRUB_MEMFILE_MEM, 4) == 0) {
       return grub_memfile_open(name);
-  }  
+  }
+
+  if (g_vlnk_list && (type & GRUB_FILE_TYPE_NO_VLNK) == 0)
+    name = grub_file_get_vlnk(name, &vlnk);
 
   device_name = grub_file_get_device_name (name);
   if (grub_errno)
@@ -141,6 +231,7 @@ grub_file_open (const char *name, enum grub_file_type type)
     goto fail;
 
   file->device = device;
+  file->vlnk = vlnk;
 
   /* In case of relative pathnames and non-Unix systems (like Windows)
    * name of host files may not start with `/'. Blocklists for host files