]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
* grub-core/commands/wildcard.c (+check_file): New function.
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Thu, 7 Jun 2012 21:18:04 +0000 (23:18 +0200)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Thu, 7 Jun 2012 21:18:04 +0000 (23:18 +0200)
(wildcard_expand): Don't expand to non-existing files, expand with
suffix and not attempt to expand if not needed.

ChangeLog
grub-core/commands/wildcard.c

index f1091ba9fc43530c75177beb82767135bdcbf1f4..31194e497d0c90ba043ddc4cd1aa7c7416d60041 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2012-06-07  Vladimir Serbinenko  <phcoder@gmail.com>
+
+       * grub-core/commands/wildcard.c (+check_file): New function.
+       (wildcard_expand): Don't expand to non-existing files, expand with
+       suffix and not attempt to expand if not needed.
+
 2012-06-07  Vladimir Serbinenko  <phcoder@gmail.com>
 
        * grub-core/disk/efi/efidisk.c (name_devices): Don't make disks
index 8afda3c99516e35218d7e6fd0876274eff511af2..2680ccdb6b480344cea0a7c56be354bc6d986432 100644 (file)
@@ -363,6 +363,57 @@ match_files (const char *prefix, const char *suffix, const char *end,
   return 0;
 }
 
+static int
+check_file (const char *dir, const char *basename)
+{
+  grub_fs_t fs;
+  grub_device_t dev;
+  int found = 0;
+  const char *device_name, *path;
+
+  auto int match (const char *name, const struct grub_dirhook_info *info);
+  int match (const char *name, const struct grub_dirhook_info *info)
+  {
+    if (basename[0] == 0
+       && (info->case_insensitive ? grub_strcasecmp (name, basename) == 0
+           : grub_strcmp (name, basename) == 0))
+      {
+       found = 1;
+       return 1;
+      }
+    
+    return 0;
+  }
+
+  device_name = grub_file_get_device_name (dir);
+  dev = grub_device_open (device_name);
+  if (! dev)
+    goto fail;
+
+  fs = grub_fs_probe (dev);
+  if (! fs)
+    goto fail;
+
+  if (dir[0] == '(')
+    {
+      path = grub_strchr (dir, ')');
+      if (!path)
+       goto fail;
+      path++;
+    }
+  else
+    path = dir;
+
+  fs->dir (dev, path, match);
+  if (grub_errno == 0 && basename[0] == 0)
+    found = 1;
+
+ fail:
+  grub_errno = 0;
+
+  return found;
+}
+
 static char*
 wildcard_escape (const char *s)
 {
@@ -419,18 +470,91 @@ wildcard_expand (const char *s, char ***strs)
   const char *regexop;
   const char *noregexop;
   char **paths = 0;
+  int had_regexp = 0;
 
   unsigned i;
   regex_t regexp;
 
+  if (s[0] != '/' && s[0] != '(' && s[0] != '*')
+    return 0;
+
   start = s;
   while (*start)
     {
       split_path (start, &noregexop, &regexop);
 
+      if (noregexop == regexop)
+       {
+         grub_dprintf ("expand", "no expansion needed\n");
+         if (paths == 0)
+           {
+             paths = grub_malloc (sizeof (char *) * 2);
+             if (!paths)
+               goto fail;
+             paths[0] = grub_malloc (regexop - start + 1);
+             if (!paths[0])
+               goto fail;
+             grub_memcpy (paths[0], start, regexop - start);
+             paths[0][regexop - start] = '\0';
+             paths[1] = 0;
+           }
+         else
+           {
+             int j = 0;
+             for (i = 0; paths[i]; i++)
+               {
+                 char *o, *oend;
+                 char *n;
+                 char *p;
+                 o = paths[i];
+                 oend = o + grub_strlen (o);
+                 n = grub_malloc ((oend - o) + (regexop - start) + 1);
+                 if (!n)
+                   goto fail;
+                 grub_memcpy (n, o, oend - o);
+                 grub_memcpy (n + (oend - o), start, regexop - start);
+                 n[(oend - o) + (regexop - start)] = '\0';
+                 if (had_regexp)
+                   p = grub_strrchr (n, '/');
+                 else
+                   p = 0;
+                 if (!p)
+                   {
+                     grub_free (o);
+                     paths[j++] = n;
+                     continue;
+                   }
+                 *p = 0;
+                 if (!check_file (n, p + 1))
+                   {
+                     grub_dprintf ("expand", "file <%s> not found\n",
+                                   start);
+                     grub_free (o);
+                     grub_free (n);
+                             continue;
+                   }
+                 *p = '/';
+                 grub_free (o);
+                 paths[j++] = n;
+               }
+             if (j == 0)
+               {
+                 grub_free (paths);
+                 paths = 0;
+                 goto done;
+               }
+             paths[j] = 0;
+           }
+         grub_dprintf ("expand", "paths[0] = `%s'\n", paths[0]);
+         start = regexop;
+         continue;
+       }
+
       if (make_regex (noregexop, regexop, &regexp))
        goto fail;
 
+      had_regexp = 1;
+
       if (paths == 0)
        {
          if (start == noregexop) /* device part has regexop */
@@ -448,6 +572,7 @@ wildcard_expand (const char *s, char ***strs)
              char **p;
 
              p = match_files (paths[i], start, noregexop, &regexp);
+             grub_free (paths[i]);
              if (! p)
                continue;
 
@@ -455,6 +580,7 @@ wildcard_expand (const char *s, char ***strs)
              if (! r)
                goto fail;
            }
+         grub_free (paths);
          paths = r;
        }