grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] mtools-like FAT-label behaviour


From: phcoder
Subject: [PATCH] mtools-like FAT-label behaviour
Date: Wed, 11 Feb 2009 13:14:25 +0100
User-agent: Thunderbird 2.0.0.19 (X11/20090105)

Hello. Now the handling of FAT-labels keeps the trailing spaces and ignores VFAT label generated by mlabel tool. Here is the patch to correct this. Unfortunately m$ when user set a mixed case label only uppercase one is saved to FS, moreover m$ keeps the mixed case label in the registry fooling the user. So no way to read these. To test mixed case labels be sure that mlabel reports it as mixed case.
Thanks
Vladimir 'phcoder' Serbinenko
Index: ChangeLog
===================================================================
--- ChangeLog   (revision 1989)
+++ ChangeLog   (working copy)
@@ -1,0 +1,8 @@
+2009-02-11  Vladimir Serbinenko  <address@hidden>
+
+       Trim trailing spaces in FAT label and support mtools-like labels
+       
+       * fs/fat.c (grub_fat_iterate_dir): New function based 
+       on grub_fat_find_dir
+       (grub_fat_find_dir): use grub_fat_iterate_dir
+       (grub_fat_label): likewise
Index: fs/fat.c
===================================================================
--- fs/fat.c    (revision 1989)
+++ fs/fat.c    (working copy)
@@ -45,7 +45,8 @@
                                 | GRUB_FAT_ATTR_HIDDEN \
                                 | GRUB_FAT_ATTR_SYSTEM \
                                 | GRUB_FAT_ATTR_DIRECTORY \
-                                | GRUB_FAT_ATTR_ARCHIVE)
+                                | GRUB_FAT_ATTR_ARCHIVE \
+                                | GRUB_FAT_ATTR_VOLUME_ID)
 
 struct grub_fat_bpb
 {
@@ -467,51 +468,21 @@
   return ret;
 }
 
-/* Find the underlying directory or file in PATH and return the
-   next path. If there is no next path or an error occurs, return NULL.
-   If HOOK is specified, call it with each file name.  */
-static char *
-grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
-                  const char *path,
-                  int (*hook) (const char *filename, int dir))
+static grub_err_t
+grub_fat_iterate_dir (grub_disk_t disk, struct grub_fat_data *data,
+                     int (*hook) (const char *filename, 
+                                  struct grub_fat_dir_entry *dir))
 {
   struct grub_fat_dir_entry dir;
-  char *dirname, *dirp;
   char *filename, *filep = 0;
   grub_uint16_t *unibuf;
   int slot = -1, slots = -1;
   int checksum = -1;
   grub_ssize_t offset = -sizeof(dir);
-  int call_hook;
   
   if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY))
-    {
-      grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
-      return 0;
-    }
+    return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
   
-  /* Extract a directory name.  */
-  while (*path == '/')
-    path++;
-
-  dirp = grub_strchr (path, '/');
-  if (dirp)
-    {
-      unsigned len = dirp - path;
-      
-      dirname = grub_malloc (len + 1);
-      if (! dirname)
-       return 0;
-
-      grub_memcpy (dirname, path, len);
-      dirname[len] = '\0';
-    }
-  else
-    /* This is actually a file.  */
-    dirname = grub_strdup (path);
-
-  call_hook = (! dirp && hook);
-  
   /* Allocate space enough to hold a long name.  */
   filename = grub_malloc (0x40 * 13 * 4 + 1);
   unibuf = (grub_uint16_t *) grub_malloc (0x40 * 13 * 2);
@@ -519,7 +490,6 @@
     {
       grub_free (filename);
       grub_free (unibuf);
-      grub_free (dirname);
       return 0;
     }
       
@@ -533,15 +503,8 @@
       /* Read a directory entry.  */
       if ((grub_fat_read_data (disk, data, 0,
                               offset, sizeof (dir), (char *) &dir)
-          != sizeof (dir))
-         || dir.name[0] == 0)
-       {
-         if (grub_errno == GRUB_ERR_NONE && ! call_hook)
-           grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
-
-         break;
-       }
-
+          != sizeof (dir) || dir.name[0] == 0))
+       break;
       /* Handle long name entries.  */
       if (dir.attr == GRUB_FAT_ATTR_LONG_NAME)
        {
@@ -594,22 +557,11 @@
              *grub_utf16_to_utf8 ((grub_uint8_t *) filename, unibuf,
                                   slots * 13) = '\0';
              
-             if (*dirname == '\0' && call_hook)
-               {
-                 if (hook (filename, dir.attr & GRUB_FAT_ATTR_DIRECTORY))
-                   break;
-                 
-                 checksum = -1;
-                 continue;
-               }
-
-             if (grub_strcmp (dirname, filename) == 0)
-               {
-                 if (call_hook)
-                   hook (filename, dir.attr & GRUB_FAT_ATTR_DIRECTORY);
-                 
-                 break;
-               }
+             if (hook (filename, &dir))
+               break;
+             
+             checksum = -1;
+             continue;
            }
 
          checksum = -1;
@@ -617,44 +569,109 @@
 
       /* Convert the 8.3 file name.  */
       filep = filename;
-      
-      for (i = 0; i < 8 && dir.name[i] && ! grub_isspace (dir.name[i]); i++)
-       *filep++ = grub_tolower (dir.name[i]);
-      
-      *filep = '.';
-      
-      for (i = 8; i < 11 && dir.name[i] && ! grub_isspace (dir.name[i]); i++)
-       *++filep = grub_tolower (dir.name[i]);
-
-      if (*filep != '.')
-       filep++;
-      
-      *filep = '\0';
-
-      if (*dirname == '\0' && call_hook)
+      if (dir.attr & GRUB_FAT_ATTR_VOLUME_ID)
        {
-         if (hook (filename, dir.attr & GRUB_FAT_ATTR_DIRECTORY))
-           break;
+         for (i = 0; i < sizeof (dir.name) && dir.name[i] 
+                && ! grub_isspace (dir.name[i]); i++)
+           *filep++ = dir.name[i];
        }
-      else if (grub_strncasecmp (dirname, filename, GRUB_FAT_MAXFILE) == 0)
+      else
        {
-         if (call_hook)
-           hook (filename, dir.attr & GRUB_FAT_ATTR_DIRECTORY);
+         for (i = 0; i < 8 && dir.name[i] && ! grub_isspace (dir.name[i]); i++)
+           *filep++ = grub_tolower (dir.name[i]);
+      
+         *filep = '.';
+         
+         for (i = 8; i < 11 && dir.name[i] && ! grub_isspace (dir.name[i]); 
i++)
+           *++filep = grub_tolower (dir.name[i]);
 
-         break;
+         if (*filep != '.')
+           filep++;
        }
+      *filep = '\0';
+
+      if (hook (filename, &dir))
+       break;
     }
 
   grub_free (filename);
-  grub_free (dirname);
 
-  data->attr = dir.attr;
-  data->file_size = grub_le_to_cpu32 (dir.file_size);
-  data->file_cluster = ((grub_le_to_cpu16 (dir.first_cluster_high) << 16)
-                       | grub_le_to_cpu16 (dir.first_cluster_low));
-  data->cur_cluster_num = ~0U;
+  return grub_errno;
+}
+
+
+/* Find the underlying directory or file in PATH and return the
+   next path. If there is no next path or an error occurs, return NULL.
+   If HOOK is specified, call it with each file name.  */
+static char *
+grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
+                  const char *path,
+                  int (*hook) (const char *filename, int dir))
+{
+  char *dirname, *dirp;
+  int call_hook;
+  int found = 0;
+
+  auto int iter_hook (const char *filename, struct grub_fat_dir_entry *dir);
+  int iter_hook (const char *filename, struct grub_fat_dir_entry *dir)
+  {
+    if (dir->attr & GRUB_FAT_ATTR_VOLUME_ID)
+      return 0;
+    if (*dirname == '\0' && call_hook)
+      return hook (filename, dir->attr & GRUB_FAT_ATTR_DIRECTORY);
+
+    if (grub_strcmp (dirname, filename) == 0)
+      {
+       found = 1;
+       data->attr = dir->attr;
+       data->file_size = grub_le_to_cpu32 (dir->file_size);
+       data->file_cluster = ((grub_le_to_cpu16 (dir->first_cluster_high) << 16)
+                             | grub_le_to_cpu16 (dir->first_cluster_low));
+       data->cur_cluster_num = ~0U;
+
+       if (call_hook)
+         hook (filename, dir->attr & GRUB_FAT_ATTR_DIRECTORY);
+           
+       return 1;
+      }
+    return 0;
+  }
   
-  return dirp;
+  if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY))
+    {
+      grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
+      return 0;
+    }
+  
+  /* Extract a directory name.  */
+  while (*path == '/')
+    path++;
+
+  dirp = grub_strchr (path, '/');
+  if (dirp)
+    {
+      unsigned len = dirp - path;
+      
+      dirname = grub_malloc (len + 1);
+      if (! dirname)
+       return 0;
+
+      grub_memcpy (dirname, path, len);
+      dirname[len] = '\0';
+    }
+  else
+    /* This is actually a file.  */
+    dirname = grub_strdup (path);
+
+  call_hook = (! dirp && hook);
+  
+  grub_fat_iterate_dir (disk, data, iter_hook);
+  if (grub_errno == GRUB_ERR_NONE && ! found && !call_hook)
+    grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
+
+  grub_free (dirname);
+
+  return found ? dirp : 0;
 }
 
 static grub_err_t
@@ -773,8 +790,17 @@
 {
   struct grub_fat_data *data;
   grub_disk_t disk = device->disk;
-  grub_ssize_t offset = -sizeof(struct grub_fat_dir_entry);
 
+  auto int iter_hook (const char *filename, struct grub_fat_dir_entry *dir);
+  int iter_hook (const char *filename, struct grub_fat_dir_entry *dir)
+  {
+    if (dir->attr == GRUB_FAT_ATTR_VOLUME_ID)
+      {
+       *label = grub_strdup (filename);
+       return 1;
+      }
+    return 0;
+  }
 
 #ifndef GRUB_UTIL
   grub_dl_ref (my_mod);
@@ -790,37 +816,10 @@
       return 0;
     }
 
-  while (1)
-    {
-      struct grub_fat_dir_entry dir;
-
-      /* Adjust the offset.  */
-      offset += sizeof (dir);
-      
-      /* Read a directory entry.  */
-      if ((grub_fat_read_data (disk, data, 0,
-                              offset, sizeof (dir), (char *) &dir)
-          != sizeof (dir))
-         || dir.name[0] == 0)
-       {
-         if (grub_errno != GRUB_ERR_NONE)
-           goto fail;
-         else
-           {
-             *label = 0;
-             return GRUB_ERR_NONE;
-           }
-       }
-
-      if (dir.attr == GRUB_FAT_ATTR_VOLUME_ID)
-       {
-         *label = grub_strndup ((char *) dir.name, 11);
-         return GRUB_ERR_NONE;
-       }
-    }
-
   *label = 0;
   
+  grub_fat_iterate_dir (disk, data, iter_hook);
+
  fail:
 
 #ifndef GRUB_UTIL

reply via email to

[Prev in Thread] Current Thread [Next in Thread]