grub-devel
[Top][All Lists]
Advanced

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

[PATCH] FAT, UFS and mtime


From: phcoder
Subject: [PATCH] FAT, UFS and mtime
Date: Sun, 01 Mar 2009 17:25:10 +0100
User-agent: Thunderbird 2.0.0.19 (X11/20090105)

Hello all. It seems that gcc has trouble with -m32 when structure is passed as argument. So I replaced that part by a pointer. Also I made some improvements to ufs code to support solaris branch of ufs. I tested it also with freebsd and netbsd's branch and it works fine on it too. As my 3 FS patches: mtime, FAT and UFS are interdependent I submit a patch with all 3 features. If it's really necessary I can split them but it requires a lot of unnecessary work
--

Regards
Vladimir 'phcoder' Serbinenko
Index: conf/i386-coreboot.rmk
===================================================================
--- conf/i386-coreboot.rmk      (revision 2008)
+++ conf/i386-coreboot.rmk      (working copy)
@@ -75,6 +75,8 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c
        kern/loader.c kern/main.c kern/misc.c kern/parser.c             \
        grub_script.tab.c kern/partition.c kern/rescue.c kern/term.c    \
        normal/arg.c normal/cmdline.c normal/command.c normal/function.c\
+       normal/completion.c normal/datetime.c normal/main.c             \
+       normal/menu_text.c              \
        normal/completion.c normal/main.c normal/menu_text.c            \
        normal/menu.c normal/menu_entry.c normal/menu_viewer.c          \
        normal/misc.c normal/script.c                                   \
@@ -121,7 +123,7 @@ linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
 # keep it simpler to update to different architectures.
 #
 normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c    \
-       normal/completion.c normal/execute.c                            \
+       normal/completion.c normal/datetime.c normal/execute.c          \
        normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
        normal/menu_text.c                                              \
        normal/color.c                                                  \
Index: conf/i386-efi.rmk
===================================================================
--- conf/i386-efi.rmk   (revision 2008)
+++ conf/i386-efi.rmk   (working copy)
@@ -52,7 +52,8 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c
        kern/loader.c kern/main.c kern/misc.c kern/parser.c             \
        grub_script.tab.c kern/partition.c kern/rescue.c kern/term.c    \
        normal/arg.c normal/cmdline.c normal/command.c normal/function.c\
-       normal/completion.c normal/context.c normal/main.c              \
+       normal/completion.c normal/datetime.c normal/context.c          \
+       normal/main.c           \
        normal/menu.c normal/menu_entry.c normal/menu_viewer.c          \
        normal/menu_text.c                                              \
        normal/misc.c normal/script.c                                   \
@@ -119,10 +125,10 @@ kernel_syms.lst: $(addprefix include/grub/,$(kerne
 # keep it simpler to update to different architectures.
 #
 normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c    \
-       normal/completion.c normal/execute.c                            \
+       normal/completion.c normal/datetime.c normal/execute.c          \
        normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
        normal/menu_text.c                                              \
        normal/color.c                                                  \
        normal/menu_viewer.c normal/menu_entry.c                        \
        normal/misc.c grub_script.tab.c                                 \
        normal/script.c                                                 \
        normal/i386/setjmp.S
 normal_mod_CFLAGS = $(COMMON_CFLAGS)
 normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
 normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
@@ -177,7 +183,7 @@ lspci_mod_CFLAGS = $(COMMON_CFLAGS)
 lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
 # For datetime.mod
-datetime_mod_SOURCES = lib/datetime.c lib/efi/datetime.c
+datetime_mod_SOURCES = lib/efi/datetime.c
 datetime_mod_CFLAGS = $(COMMON_CFLAGS)
 datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
Index: conf/i386-ieee1275.rmk
===================================================================
--- conf/i386-ieee1275.rmk      (revision 2008)
+++ conf/i386-ieee1275.rmk      (working copy)
@@ -74,4 +74,5 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c
        kern/loader.c kern/main.c kern/misc.c kern/parser.c             \
        grub_script.tab.c kern/partition.c kern/rescue.c kern/term.c    \
        normal/arg.c normal/cmdline.c normal/command.c normal/function.c\
-       normal/completion.c normal/main.c normal/menu_text.c            \
+       normal/completion.c normal/datetime.c normal/main.c             \
+       normal/menu_text.c              \
        normal/menu.c normal/menu_entry.c normal/menu_viewer.c          \
        normal/misc.c normal/script.c                                   \
        normal/color.c                                                  \
        partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c      \
@@ -111,7 +113,7 @@ pkglib_MODULES = normal.mod halt.mod reboot.mod su
 # keep it simpler to update to different architectures.
 #
 normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c    \
-       normal/completion.c normal/execute.c                            \
+       normal/completion.c normal/datetime.c normal/execute.c          \
        normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
        normal/menu_text.c                                              \
        normal/color.c                                                  \
@@ -191,7 +195,7 @@ lspci_mod_CFLAGS = $(COMMON_CFLAGS)
 lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
 # For datetime.mod
-datetime_mod_SOURCES = lib/datetime.c lib/i386/datetime.c
+datetime_mod_SOURCES = lib/i386/datetime.c
 datetime_mod_CFLAGS = $(COMMON_CFLAGS)
 datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
Index: conf/i386-pc.rmk
===================================================================
--- conf/i386-pc.rmk    (revision 2008)
+++ conf/i386-pc.rmk    (working copy)
@@ -128,7 +128,8 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c
        kern/loader.c kern/main.c kern/misc.c kern/parser.c             \
        grub_script.tab.c kern/partition.c kern/rescue.c kern/term.c    \
        normal/arg.c normal/cmdline.c normal/command.c normal/function.c\
-       normal/completion.c normal/main.c normal/color.c                \
+       normal/completion.c normal/datetime.c normal/main.c             \
+       normal/color.c          \
        normal/menu.c normal/menu_entry.c normal/menu_viewer.c          \
        normal/menu_text.c                                              \
        normal/misc.c normal/script.c                                   \
@@ -209,7 +248,7 @@ linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
 # keep it simpler to update to different architectures.
 #
 normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c    \
-       normal/completion.c normal/execute.c                            \
+       normal/completion.c normal/datetime.c  normal/execute.c         \
        normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
        normal/menu_text.c                                              \
        normal/color.c                                                  \
@@ -351,7 +394,7 @@ pxecmd_mod_CFLAGS = $(COMMON_CFLAGS)
 pxecmd_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
 # For datetime.mod
-datetime_mod_SOURCES = lib/datetime.c lib/i386/datetime.c
+datetime_mod_SOURCES = lib/i386/datetime.c
 datetime_mod_CFLAGS = $(COMMON_CFLAGS)
 datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
Index: conf/powerpc-ieee1275.rmk
===================================================================
--- conf/powerpc-ieee1275.rmk   (revision 2008)
+++ conf/powerpc-ieee1275.rmk   (working copy)
@@ -56,7 +56,7 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c
        kern/misc.c kern/parser.c kern/partition.c kern/rescue.c        \
        kern/term.c fs/fshelp.c                                         \
        normal/arg.c normal/cmdline.c normal/command.c                  \
-       normal/completion.c normal/execute.c                            \
+       normal/completion.c normal/datetime.c normal/execute.c          \
        normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
        normal/menu_text.c                                              \
        normal/menu_entry.c normal/menu_viewer.c normal/misc.c          \
@@ -132,7 +132,7 @@ linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
 # keep it simpler to update to different architectures.
 #
 normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c    \
-       normal/completion.c normal/execute.c                            \
+       normal/completion.c normal/datetime.c normal/execute.c          \
        normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
        normal/menu_text.c                                              \
        normal/color.c                                                  \
Index: conf/sparc64-ieee1275.rmk
===================================================================
--- conf/sparc64-ieee1275.rmk   (revision 2008)
+++ conf/sparc64-ieee1275.rmk   (working copy)
@@ -56,7 +56,8 @@ grub_mkimage_SOURCES = util/sparc64/ieee1275/grub-
 #      kern/file.c kern/fs.c kern/loader.c kern/main.c kern/misc.c     \
 #      kern/parser.c kern/partition.c kern/rescue.c kern/term.c        \
 #      normal/arg.c normal/cmdline.c normal/command.c                  \
-#      normal/completion.c normal/context.c normal/execute.c           \
+#      normal/completion.c normal/datetime.c normal/context.c          \
+#      normal/execute.c                \
 #      normal/function.c normal/lexer.c                                \
 #      normal/main.c normal/menu.c normal/menu_entry.c                 \
 #      normal/menu_text.c                                              \
@@ -165,7 +166,7 @@ sfs_mod_LDFLAGS = $(COMMON_LDFLAGS)
 # keep it simpler to update to different architectures.
 #
 normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c    \
-       normal/completion.c normal/execute.c                            \
+       normal/completion.c normal/datetime.c normal/execute.c          \
        normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
        normal/menu_text.c                                              \
        normal/color.c                                                  \
Index: conf/x86_64-efi.rmk
===================================================================
--- conf/x86_64-efi.rmk (revision 2008)
+++ conf/x86_64-efi.rmk (working copy)
@@ -54,7 +54,8 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c
        kern/loader.c kern/main.c kern/misc.c kern/parser.c             \
        grub_script.tab.c kern/partition.c kern/rescue.c kern/term.c    \
        normal/arg.c normal/cmdline.c normal/command.c normal/function.c\
-       normal/completion.c normal/context.c normal/main.c              \
+       normal/completion.c normal/datetime.c normal/context.c \
+       normal/main.c           \
        normal/menu.c normal/menu_entry.c normal/menu_viewer.c          \
        normal/menu_text.c                                              \
        normal/misc.c normal/script.c                                   \
@@ -121,7 +122,7 @@ kernel_syms.lst: $(addprefix include/grub/,$(kerne
 # keep it simpler to update to different architectures.
 #
 normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c    \
-       normal/completion.c normal/execute.c                            \
+       normal/completion.c normal/datetime.c normal/execute.c          \
        normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
        normal/menu_text.c                                              \
        normal/color.c                                                  \
@@ -179,7 +180,7 @@ lspci_mod_CFLAGS = $(COMMON_CFLAGS)
 lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
 # For datetime.mod
-datetime_mod_SOURCES = lib/datetime.c lib/efi/datetime.c
+datetime_mod_SOURCES = lib/efi/datetime.c
 datetime_mod_CFLAGS = $(COMMON_CFLAGS)
 datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
Index: kern/fs.c
===================================================================
--- kern/fs.c   (revision 2008)
+++ kern/fs.c   (working copy)
@@ -65,10 +65,11 @@ grub_fs_t
 grub_fs_probe (grub_device_t device)
 {
   grub_fs_t p;
-  auto int dummy_func (const char *filename, int dir);
+  auto int dummy_func (const char *filename, 
+                      const struct grub_dirhook_info *info);
 
   int dummy_func (const char *filename __attribute__ ((unused)),
-                 int dir __attribute__ ((unused)))
+                 const struct grub_dirhook_info *info  __attribute__ 
((unused)))
     {
       return 1;
     }
Index: kern/rescue.c
===================================================================
--- kern/rescue.c       (revision 2008)
+++ kern/rescue.c       (working copy)
@@ -176,9 +176,10 @@ grub_rescue_print_devices (const char *name)
 }
 
 static int
-grub_rescue_print_files (const char *filename, int dir)
+grub_rescue_print_files (const char *filename, 
+                         const struct grub_dirhook_info *info)
 {
-  grub_printf ("%s%s ", filename, dir ? "/" : "");
+  grub_printf ("%s%s ", filename, info->dir ? "/" : "");
   
   return 0;
 }
Index: hook/datehook.c
===================================================================
--- hook/datehook.c     (revision 2008)
+++ hook/datehook.c     (working copy)
@@ -22,7 +22,7 @@
 #include <grub/env.h>
 #include <grub/misc.h>
 #include <grub/normal.h>
-#include <grub/lib/datetime.h>
+#include <grub/datetime.h>
 
 static char *grub_datetime_names[] =
 {
Index: lib/efi/datetime.c
===================================================================
--- lib/efi/datetime.c  (revision 2008)
+++ lib/efi/datetime.c  (working copy)
@@ -21,7 +21,7 @@
 #include <grub/symbol.h>
 #include <grub/efi/api.h>
 #include <grub/efi/efi.h>
-#include <grub/lib/datetime.h>
+#include <grub/datetime.h>
 
 grub_err_t
 grub_get_datetime (struct grub_datetime *datetime)
Index: lib/datetime.c
===================================================================
--- lib/datetime.c      (revision 2008)
+++ lib/datetime.c      (working copy)
@@ -1,49 +0,0 @@
-/* datetime.c - Module for common datetime function.  */
-/*
- *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2008  Free Software Foundation, Inc.
- *
- *  GRUB is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  GRUB is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <grub/lib/datetime.h>
-
-static char *grub_weekday_names[] =
-{
-  "Sunday",
-  "Monday",
-  "Tuesday",
-  "Wednesday",
-  "Thursday",
-  "Friday",
-  "Saturday",
-};
-
-int
-grub_get_weekday (struct grub_datetime *datetime)
-{
-  int a, y, m;
-
-  a = (14 - datetime->month) / 12;
-  y = datetime->year - a;
-  m = datetime->month + 12 * a - 2;
-
-  return (datetime->day + y + y / 4 - y / 100 + y / 400 + (31 * m / 12)) % 7;
-}
-
-char *
-grub_get_weekday_name (struct grub_datetime *datetime)
-{
-  return grub_weekday_names[grub_get_weekday (datetime)];
-}
Index: fs/xfs.c
===================================================================
--- fs/xfs.c    (revision 2008)
+++ fs/xfs.c    (working copy)
@@ -620,7 +620,8 @@ grub_xfs_mount (grub_disk_t disk)
 
 static grub_err_t
 grub_xfs_dir (grub_device_t device, const char *path, 
-             int (*hook) (const char *filename, int dir))
+             int (*hook) (const char *filename, 
+                          const struct grub_dirhook_info *info))
 {
   struct grub_xfs_data *data = 0;;
   struct grub_fshelp_node *fdiro = 0;
@@ -633,14 +634,11 @@ grub_xfs_dir (grub_device_t device, const char *pa
                                enum grub_fshelp_filetype filetype,
                                grub_fshelp_node_t node)
     {
+      struct grub_dirhook_info info;
+      grub_memset (&info, 0, sizeof (info));
+      info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
       grub_free (node);
-      
-      if (filetype == GRUB_FSHELP_DIR)
-       return hook (filename, 1);
-      else 
-       return hook (filename, 0);
-      
-      return 0;
+      return hook (filename, &info);
     }
 
 #ifndef GRUB_UTIL
Index: fs/afs.c
===================================================================
--- fs/afs.c    (revision 2008)
+++ fs/afs.c    (working copy)
@@ -562,7 +562,8 @@ grub_afs_close (grub_file_t file)
 
 static grub_err_t
 grub_afs_dir (grub_device_t device, const char *path,
-              int (*hook) (const char *filename, int dir))
+              int (*hook) (const char *filename, 
+                          const struct grub_dirhook_info *info))
 {
   struct grub_afs_data *data = 0;;
   struct grub_fshelp_node *fdiro = 0;
@@ -575,14 +576,11 @@ grub_afs_dir (grub_device_t device, const char *pa
                                enum grub_fshelp_filetype filetype,
                                grub_fshelp_node_t node)
     {
+      struct grub_dirhook_info info;
+      grub_memset (&info, 0, sizeof (info));
+      info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
       grub_free (node);
-
-      if (filetype == GRUB_FSHELP_DIR)
-       return hook (filename, 1);
-      else
-       return hook (filename, 0);
-
-      return 0;
+      return hook (filename, &info);
     }
 
 #ifndef GRUB_UTIL
Index: fs/ntfs.c
===================================================================
--- fs/ntfs.c   (revision 2008)
+++ fs/ntfs.c   (working copy)
@@ -864,7 +864,8 @@ fail:
 
 static grub_err_t
 grub_ntfs_dir (grub_device_t device, const char *path,
-              int (*hook) (const char *filename, int dir))
+              int (*hook) (const char *filename, 
+                           const struct grub_dirhook_info *info))
 {
   struct grub_ntfs_data *data = 0;
   struct grub_fshelp_node *fdiro = 0;
@@ -877,14 +878,11 @@ grub_ntfs_dir (grub_device_t device, const char *p
                                enum grub_fshelp_filetype filetype,
                                grub_fshelp_node_t node)
   {
-    grub_free (node);
-
-    if (filetype == GRUB_FSHELP_DIR)
-      return hook (filename, 1);
-    else
-      return hook (filename, 0);
-
-    return 0;
+      struct grub_dirhook_info info;
+      grub_memset (&info, 0, sizeof (info));
+      info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
+      grub_free (node);
+      return hook (filename, &info);
   }
 
 #ifndef GRUB_UTIL
Index: fs/fat.c
===================================================================
--- fs/fat.c    (revision 2008)
+++ 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 @@ grub_fat_read_data (grub_disk_t disk, struct grub_
   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_fat_read_data (grub_disk_t disk, struct grub_
     {
       grub_free (filename);
       grub_free (unibuf);
-      grub_free (dirname);
       return 0;
     }
       
@@ -533,15 +503,8 @@ grub_fat_read_data (grub_disk_t disk, struct grub_
       /* 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_fat_read_data (grub_disk_t disk, struct grub_
              *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,49 +569,122 @@ grub_fat_read_data (grub_disk_t disk, struct grub_
 
       /* 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);
+
+  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, 
+                               const struct grub_dirhook_info *info))
+{
+  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)
+  {
+    struct grub_dirhook_info info;
+    grub_memset (&info, 0, sizeof (info));
+
+    info.dir = !!(dir->attr & GRUB_FAT_ATTR_DIRECTORY);
+    info.case_insensitive = 1;
+
+    if (dir->attr & GRUB_FAT_ATTR_VOLUME_ID)
+      return 0;
+    if (*dirname == '\0' && call_hook)
+      return hook (filename, &info);
+
+    if (grub_strcasecmp (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, &info);
+           
+       return 1;
+      }
+    return 0;
+  }
+  
+  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);
 
-  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 dirp;
+  return found ? dirp : 0;
 }
 
 static grub_err_t
 grub_fat_dir (grub_device_t device, const char *path,
-             int (*hook) (const char *filename, int dir))
+             int (*hook) (const char *filename, 
+                          const struct grub_dirhook_info *info))
 {
   struct grub_fat_data *data = 0;
   grub_disk_t disk = device->disk;
@@ -773,8 +798,17 @@ grub_fat_label (grub_device_t device, char **label
 {
   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 +824,10 @@ grub_fat_label (grub_device_t device, char **label
       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
Index: fs/udf.c
===================================================================
--- fs/udf.c    (revision 2008)
+++ fs/udf.c    (working copy)
@@ -768,7 +768,8 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir,
 
 static grub_err_t
 grub_udf_dir (grub_device_t device, const char *path,
-             int (*hook) (const char *filename, int dir))
+             int (*hook) (const char *filename, 
+                          const struct grub_dirhook_info *info))
 {
   struct grub_udf_data *data = 0;
   struct grub_fshelp_node rootnode;
@@ -782,14 +783,11 @@ grub_udf_dir (grub_device_t device, const char *pa
                                enum grub_fshelp_filetype filetype,
                                grub_fshelp_node_t node)
   {
-    grub_free (node);
-
-    if (filetype == GRUB_FSHELP_DIR)
-      return hook (filename, 1);
-    else
-      return hook (filename, 0);
-
-    return 0;
+      struct grub_dirhook_info info;
+      grub_memset (&info, 0, sizeof (info));
+      info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
+      grub_free (node);
+      return hook (filename, &info);
   }
 
 #ifndef GRUB_UTIL
Index: fs/iso9660.c
===================================================================
--- fs/iso9660.c        (revision 2008)
+++ fs/iso9660.c        (working copy)
@@ -666,7 +666,8 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
 
 static grub_err_t
 grub_iso9660_dir (grub_device_t device, const char *path, 
-                 int (*hook) (const char *filename, int dir))
+                 int (*hook) (const char *filename, 
+                              const struct grub_dirhook_info *info))
 {
   struct grub_iso9660_data *data = 0;
   struct grub_fshelp_node rootnode;
@@ -680,14 +681,11 @@ grub_iso9660_dir (grub_device_t device, const char
                                enum grub_fshelp_filetype filetype,
                                grub_fshelp_node_t node)
     {
+      struct grub_dirhook_info info;
+      grub_memset (&info, 0, sizeof (info));
+      info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
       grub_free (node);
-      
-      if (filetype == GRUB_FSHELP_DIR)
-       return hook (filename, 1);
-      else 
-       return hook (filename, 0);
-      
-      return 0;
+      return hook (filename, &info);
     }
 
 #ifndef GRUB_UTIL
Index: fs/affs.c
===================================================================
--- fs/affs.c   (revision 2008)
+++ fs/affs.c   (working copy)
@@ -456,7 +456,8 @@ grub_affs_read (grub_file_t file, char *buf, grub_
 
 static grub_err_t
 grub_affs_dir (grub_device_t device, const char *path, 
-              int (*hook) (const char *filename, int dir))
+              int (*hook) (const char *filename, 
+                           const struct grub_dirhook_info *info))
 {
   struct grub_affs_data *data = 0;
   struct grub_fshelp_node *fdiro = 0;
@@ -469,14 +470,11 @@ grub_affs_dir (grub_device_t device, const char *p
                                enum grub_fshelp_filetype filetype,
                                grub_fshelp_node_t node)
     {
+      struct grub_dirhook_info info;
+      grub_memset (&info, 0, sizeof (info));
+      info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
       grub_free (node);
-      
-      if (filetype == GRUB_FSHELP_DIR)
-       return hook (filename, 1);
-      else 
-       return hook (filename, 0);
-      
-      return 0;
+      return hook (filename, &info);
     }
 
 #ifndef GRUB_UTIL
Index: fs/hfs.c
===================================================================
--- fs/hfs.c    (revision 2008)
+++ fs/hfs.c    (working copy)
@@ -721,7 +721,8 @@ grub_hfs_find_dir (struct grub_hfs_data *data, con
 
 static grub_err_t
 grub_hfs_dir (grub_device_t device, const char *path, 
-                 int (*hook) (const char *filename, int dir))
+                 int (*hook) (const char *filename,
+                              const struct grub_dirhook_info *info))
 {
   int inode;
 
@@ -732,13 +733,17 @@ grub_hfs_dir (grub_device_t device, const char *pa
       char fname[32] = { 0 };
       char *filetype = rec->data;
       struct grub_hfs_catalog_key *ckey = rec->key;
+      struct grub_dirhook_info info;
+      grub_memset (&info, 0, sizeof (info));
       
       grub_strncpy (fname, (char *) (ckey->str), ckey->strlen);
       
-      if (*filetype == GRUB_HFS_FILETYPE_DIR)
-       return hook (fname, 1);
-      else if (*filetype == GRUB_HFS_FILETYPE_FILE)
-       return hook (fname, 0);
+      if (*filetype == GRUB_HFS_FILETYPE_DIR 
+         || *filetype == GRUB_HFS_FILETYPE_FILE)
+       {
+         info.dir = (*filetype == GRUB_HFS_FILETYPE_DIR);
+         return hook (fname, &info);
+       }
       return 0;
     }
   
Index: fs/reiserfs.c
===================================================================
--- fs/reiserfs.c       (revision 2008)
+++ fs/reiserfs.c       (working copy)
@@ -1266,7 +1266,8 @@ grub_reiserfs_close (grub_file_t file)
 /* Call HOOK with each file under DIR.  */
 static grub_err_t
 grub_reiserfs_dir (grub_device_t device, const char *path,
-                   int (*hook) (const char *filename, int dir))
+                   int (*hook) (const char *filename, 
+                               const struct grub_dirhook_info *info))
 {
   struct grub_reiserfs_data *data = 0;
   struct grub_fshelp_node root, *found;
@@ -1280,12 +1281,11 @@ grub_reiserfs_dir (grub_device_t device, const cha
                                 enum grub_fshelp_filetype filetype,
                                 grub_fshelp_node_t node)
     {
+      struct grub_dirhook_info info;
+      grub_memset (&info, 0, sizeof (info));
+      info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
       grub_free (node);
-      
-      if (filetype == GRUB_FSHELP_DIR)
-        return hook (filename, 1);
-      else
-        return hook (filename, 0);
+      return hook (filename, &info);
     }
 #ifndef GRUB_UTIL
   grub_dl_ref (my_mod);
Index: fs/jfs.c
===================================================================
--- fs/jfs.c    (revision 2008)
+++ fs/jfs.c    (working copy)
@@ -728,7 +728,8 @@ grub_jfs_lookup_symlink (struct grub_jfs_data *dat
 
 static grub_err_t
 grub_jfs_dir (grub_device_t device, const char *path, 
-             int (*hook) (const char *filename, int dir))
+             int (*hook) (const char *filename, 
+                          const struct grub_dirhook_info *info))
 {
   struct grub_jfs_data *data = 0;
   struct grub_jfs_diropen *diro = 0;
@@ -752,14 +753,15 @@ grub_jfs_dir (grub_device_t device, const char *pa
   while (grub_jfs_getent (diro) != GRUB_ERR_OUT_OF_RANGE)
     {
       struct grub_jfs_inode inode;
-      int isdir;
+      struct grub_dirhook_info info;
+      grub_memset (&info, 0, sizeof (info));
       
       if (grub_jfs_read_inode (data, diro->ino, &inode))
        goto fail;
       
-      isdir = (grub_le_to_cpu32 (inode.mode)
-              & GRUB_JFS_FILETYPE_MASK) == GRUB_JFS_FILETYPE_DIR;
-      if (hook (diro->name, isdir))
+      info.dir = (grub_le_to_cpu32 (inode.mode)
+                 & GRUB_JFS_FILETYPE_MASK) == GRUB_JFS_FILETYPE_DIR;
+      if (hook (diro->name, &info))
        goto fail;
     }
   
Index: fs/ext2.c
===================================================================
--- fs/ext2.c   (revision 2008)
+++ fs/ext2.c   (working copy)
@@ -788,7 +790,8 @@ grub_ext2_read (grub_file_t file, char *buf, grub_
 
 static grub_err_t
 grub_ext2_dir (grub_device_t device, const char *path, 
-              int (*hook) (const char *filename, int dir))
+              int (*hook) (const char *filename, 
+                           const struct grub_dirhook_info *info))
 {
   struct grub_ext2_data *data = 0;;
   struct grub_fshelp_node *fdiro = 0;
@@ -801,14 +804,24 @@ grub_ext2_dir (grub_device_t device, const char *p
                                enum grub_fshelp_filetype filetype,
                                grub_fshelp_node_t node)
     {
+      struct grub_dirhook_info info;
+      grub_memset (&info, 0, sizeof (info));
+      if (! node->inode_read)
+       {
+         grub_ext2_read_inode (data, node->ino, &node->inode);
+         if (!grub_errno)
+           node->inode_read = 1;
+         grub_errno = GRUB_ERR_NONE;
+       }
+      if (node->inode_read)
+       {
+         info.mtimeset = 1;
+         info.mtime = grub_le_to_cpu32 (node->inode.mtime);
+       }
+
+      info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
       grub_free (node);
-      
-      if (filetype == GRUB_FSHELP_DIR)
-       return hook (filename, 1);
-      else 
-       return hook (filename, 0);
-      
-      return 0;
+      return hook (filename, &info);
     }
 
 #ifndef GRUB_UTIL
@@ -895,6 +908,34 @@ grub_ext2_uuid (grub_device_t device, char **uuid)
   return grub_errno;
 }
 
+/* Get mtime.  */
+static grub_err_t 
+grub_ext2_mtime (grub_device_t device, grub_int32_t *tm)
+{
+  struct grub_ext2_data *data;
+  grub_disk_t disk = device->disk;
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+
+  data = grub_ext2_mount (disk);
+  if (!data)
+    *tm = 0;
+  else 
+    *tm = grub_le_to_cpu32 (data->sblock.utime);
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  grub_free (data);
+
+  return grub_errno;
+
+}
+
+
 
 static struct grub_fs grub_ext2_fs =
   {
@@ -905,6 +946,7 @@ static struct grub_fs grub_ext2_fs =
     .close = grub_ext2_close,
     .label = grub_ext2_label,
     .uuid = grub_ext2_uuid,
+    .mtime = grub_ext2_mtime,
     .next = 0
   };
 
Index: fs/hfsplus.c
===================================================================
--- fs/hfsplus.c        (revision 2008)
+++ fs/hfsplus.c        (working copy)
@@ -57,9 +57,11 @@ struct grub_hfsplus_volheader
   grub_uint16_t magic;
   grub_uint16_t version;
   grub_uint32_t attributes;
-  grub_uint8_t unused[32];
+  grub_uint8_t unused1[12];
+  grub_uint32_t utime;
+  grub_uint8_t unused2[16];
   grub_uint32_t blksize;
-  grub_uint8_t unused2[68];
+  grub_uint8_t unused3[68];
   struct grub_hfsplus_forkdata allocations_file;
   struct grub_hfsplus_forkdata extents_file;
   struct grub_hfsplus_forkdata catalog_file;
@@ -133,9 +135,11 @@ struct grub_hfsplus_catfile
   grub_uint16_t flags;
   grub_uint32_t reserved;
   grub_uint32_t fileid;
-  grub_uint8_t unused1[30];
+  grub_uint8_t unused1[4];
+  grub_uint32_t mtime;
+  grub_uint8_t unused2[22];
   grub_uint16_t mode;
-  grub_uint8_t unused2[44];
+  grub_uint8_t unused3[44];
   struct grub_hfsplus_forkdata data;
   struct grub_hfsplus_forkdata resource;
 } __attribute__ ((packed));
@@ -190,6 +194,7 @@ struct grub_fshelp_node
   struct grub_hfsplus_extent extents[8];
   grub_uint64_t size;
   grub_uint32_t fileid;
+  grub_int32_t mtime;
 };
 
 struct grub_hfsplus_btree
@@ -780,6 +786,7 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir,
          
          grub_memcpy (node->extents, fileinfo->data.extents,
                       sizeof (node->extents));
+         node->mtime = grub_be_to_cpu32 (fileinfo->mtime) - 2082844800;
          node->size = grub_be_to_cpu64 (fileinfo->data.size);
          node->fileid = grub_be_to_cpu32 (fileinfo->fileid);
 
@@ -885,7 +892,8 @@ grub_hfsplus_read (grub_file_t file, char *buf, gr
 
 static grub_err_t
 grub_hfsplus_dir (grub_device_t device, const char *path, 
-                 int (*hook) (const char *filename, int dir))
+                 int (*hook) (const char *filename, 
+                              const struct grub_dirhook_info *info))
 {
   struct grub_hfsplus_data *data = 0;
   struct grub_fshelp_node *fdiro = 0;
@@ -898,14 +906,14 @@ grub_hfsplus_dir (grub_device_t device, const char
                                enum grub_fshelp_filetype filetype,
                                grub_fshelp_node_t node)
     {
+      struct grub_dirhook_info info;
+      grub_memset (&info, 0, sizeof (info));
+      info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
+      info.mtimeset = 1;
+      info.mtime = node->mtime;
+      info.case_insensitive = !!(filetype & GRUB_FSHELP_CASE_INSENSITIVE);
       grub_free (node);
-      
-      if (filetype == GRUB_FSHELP_DIR)
-       return hook (filename, 1);
-      else 
-       return hook (filename, 0);
-      
-      return 0;
+      return hook (filename, &info);
     }
 
 #ifndef GRUB_UTIL
@@ -949,6 +957,34 @@ grub_hfsplus_label (grub_device_t device __attribu
                     "partition is not implemented");
 }
 
+/* Get mtime.  */
+static grub_err_t 
+grub_hfsplus_mtime (grub_device_t device, grub_int32_t *tm)
+{
+  struct grub_hfsplus_data *data;
+  grub_disk_t disk = device->disk;
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+
+  data = grub_hfsplus_mount (disk);
+  if (!data)
+    *tm = 0;
+  else 
+    *tm = grub_be_to_cpu32 (data->volheader.utime) - 2082844800;
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  grub_free (data);
+
+  return grub_errno;
+
+}
+
+
 
 static struct grub_fs grub_hfsplus_fs =
   {
@@ -958,6 +994,7 @@ static struct grub_fs grub_hfsplus_fs =
     .read = grub_hfsplus_read,
     .close = grub_hfsplus_close,
     .label = grub_hfsplus_label,
+    .mtime = grub_hfsplus_mtime,
     .next = 0
   };
 
Index: fs/minix.c
===================================================================
--- fs/minix.c  (revision 2008)
+++ fs/minix.c  (working copy)
@@ -461,7 +461,8 @@ grub_minix_mount (grub_disk_t disk)
 
 static grub_err_t
 grub_minix_dir (grub_device_t device, const char *path, 
-                 int (*hook) (const char *filename, int dir))
+                 int (*hook) (const char *filename, 
+                              const struct grub_dirhook_info *info))
 {
   struct grub_minix_data *data = 0;
   struct grub_minix_sblock *sblock;
@@ -492,6 +493,9 @@ grub_minix_dir (grub_device_t device, const char *
       grub_uint16_t ino;
       char filename[data->filename_size + 1];
       int dirino = data->ino;
+      struct grub_dirhook_info info;
+      grub_memset (&info, 0, sizeof (info));
+
       
       if (grub_minix_read_file (data, 0, pos, sizeof (ino),
                                (char *) &ino) < 0)
@@ -506,8 +510,9 @@ grub_minix_dir (grub_device_t device, const char *
       /* The filetype is not stored in the dirent.  Read the inode to
         find out the filetype.  This *REALLY* sucks.  */
       grub_minix_read_inode (data, grub_le_to_cpu16 (ino));
-      if (hook (filename, ((GRUB_MINIX_INODE_MODE (data) 
-                           & GRUB_MINIX_IFDIR) == GRUB_MINIX_IFDIR)) ? 1 : 0)
+      info.dir = ((GRUB_MINIX_INODE_MODE (data) 
+                  & GRUB_MINIX_IFDIR) == GRUB_MINIX_IFDIR);
+      if (hook (filename, &info) ? 1 : 0)
        break;
       
       /* Load the old inode back in.  */
Index: fs/cpio.c
===================================================================
--- fs/cpio.c   (revision 2008)
+++ fs/cpio.c   (working copy)
@@ -183,7 +183,8 @@ fail:
 
 static grub_err_t
 grub_cpio_dir (grub_device_t device, const char *path,
-              int (*hook) (const char *filename, int dir))
+              int (*hook) (const char *filename, 
+                           const struct grub_dirhook_info *info))
 {
   struct grub_cpio_data *data;
   grub_uint32_t ofs;
@@ -227,7 +228,11 @@ grub_cpio_dir (grub_device_t device, const char *p
 
          if ((!prev) || (grub_strcmp (prev, name) != 0))
            {
-             hook (name + len, p != NULL);
+             struct grub_dirhook_info info;
+             grub_memset (&info, 0, sizeof (info));
+             info.dir = (p != NULL);
+
+             hook (name + len, &info);
              if (prev)
                grub_free (prev);
              prev = name;
Index: fs/sfs.c
===================================================================
--- fs/sfs.c    (revision 2008)
+++ fs/sfs.c    (working copy)
@@ -519,7 +519,8 @@ grub_sfs_read (grub_file_t file, char *buf, grub_s
 
 static grub_err_t
 grub_sfs_dir (grub_device_t device, const char *path, 
-              int (*hook) (const char *filename, int dir))
+              int (*hook) (const char *filename, 
+                           const struct grub_dirhook_info *info))
 {
   struct grub_sfs_data *data = 0;
   struct grub_fshelp_node *fdiro = 0;
@@ -532,14 +533,11 @@ grub_sfs_dir (grub_device_t device, const char *pa
                                enum grub_fshelp_filetype filetype,
                                grub_fshelp_node_t node)
     {
+      struct grub_dirhook_info info;
+      grub_memset (&info, 0, sizeof (info));
+      info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
       grub_free (node);
-      
-      if (filetype == GRUB_FSHELP_DIR)
-       return hook (filename, 1);
-      else
-       return hook (filename, 0);
-      
-      return 0;
+      return hook (filename, &info);
     }
 
 #ifndef GRUB_UTIL
Index: fs/ufs.c
===================================================================
--- fs/ufs.c    (revision 2008)
+++ fs/ufs.c    (working copy)
@@ -36,7 +36,10 @@
 #define GRUB_UFS_DIRBLKS       12
 #define GRUB_UFS_INDIRBLKS     3
 
-#define GRUB_UFS_ATTR_DIR      040000
+#define GRUB_UFS_ATTR_TYPE      0160000
+#define GRUB_UFS_ATTR_FILE     0100000
+#define GRUB_UFS_ATTR_DIR      0040000
+#define GRUB_UFS_ATTR_LNK       0120000
 
 #define GRUB_UFS_VOLNAME_LEN   32
 
@@ -51,6 +54,8 @@
                            grub_le_to_cpu##bits1 (data->inode.field) : \
                            grub_le_to_cpu##bits2 (data->inode2.field))
 #define INODE_SIZE(data) INODE_ENDIAN (data,size,32,64)
+#define INODE_NBLOCKS(data) INODE_ENDIAN (data,nblocks,32,64)
+
 #define INODE_MODE(data) INODE_ENDIAN (data,mode,16,16)
 #define INODE_BLKSZ(data) (data->ufs_type == UFS1 ? 4 : 8)
 #define INODE_DIRBLOCKS(data,blk) INODE_ENDIAN \
@@ -71,29 +76,35 @@ struct grub_ufs_sblock
   
   /* The start of the cylinder group.  */
   grub_uint32_t cylg_offset;
+  grub_uint8_t unused3[4];
+
+  grub_uint32_t mtime;
+  grub_uint8_t unused4[12];
   
-  grub_uint8_t unused3[20];
-  
   /* The size of a block in bytes.  */
   grub_int32_t bsize;
-  grub_uint8_t unused4[48];
+  grub_uint8_t unused5[48];
   
   /* The size of filesystem blocks to disk blocks.  */
   grub_uint32_t log2_blksz;
-  grub_uint8_t unused5[80];
+  grub_uint8_t unused6[80];
   
   /* Inodes stored per cylinder group.  */
   grub_uint32_t ino_per_group;
   
   /* The frags per cylinder group.  */
   grub_uint32_t frags_per_group;
+  grub_uint8_t unused7[19];
+  grub_uint8_t flags;
   
-  grub_uint8_t unused7[488];
+  grub_uint8_t unused8[468];
 
   /* Volume name for UFS2.  */
   grub_uint8_t volume_name[GRUB_UFS_VOLNAME_LEN];
+  grub_uint8_t unused9[232];
 
-  grub_uint8_t unused8[660];
+  grub_uint64_t mtime2;
+  grub_uint8_t unused10[420];
   
   /* Magic value to check if this is really a UFS filesystem.  */
   grub_uint32_t magic;
@@ -124,7 +135,7 @@ struct grub_ufs_inode
   grub_uint32_t gen;
   grub_uint32_t unused;
   grub_uint8_t pad[12];
-};
+} __attribute__ ((packed));
 
 /* UFS inode.  */
 struct grub_ufs2_inode
@@ -160,16 +171,23 @@ struct grub_ufs2_inode
   };
 
   grub_uint8_t unused[24];
-};
+} __attribute__ ((packed));
 
 /* Directory entry.  */
 struct grub_ufs_dirent
 {
   grub_uint32_t ino;
   grub_uint16_t direntlen;
-  grub_uint8_t filetype;
-  grub_uint8_t namelen;
-};
+  union
+  {
+    grub_uint16_t namelen;
+    struct
+    {
+      grub_uint8_t filetype_bsd;
+      grub_uint8_t namelen_bsd;      
+    };
+  };
+} __attribute__ ((packed));
 
 /* Information about a "mounted" ufs filesystem.  */
 struct grub_ufs_data
@@ -225,24 +243,24 @@ grub_ufs_get_file_block (struct grub_ufs_data *dat
       return (data->ufs_type == UFS1) ? indir[blk] : indir[blk << 1];
     }
   blk -= indirsz;
-  
+
   /* Double indirect block.  */
-  if (blk < UFS_BLKSZ (sblock) / indirsz)
+  if (blk < indirsz * indirsz)
     {
       grub_uint32_t indir[UFS_BLKSZ (sblock) >> 2];
       
       grub_disk_read (data->disk, INODE_INDIRBLOCKS (data, 1) << log2_blksz,
                      0, sizeof (indir), (char *) indir);
       grub_disk_read (data->disk,
-                     (data->ufs_type == UFS1) ?
-                     indir[blk / indirsz] : indir [(blk / indirsz) << 1],
+                     ((data->ufs_type == UFS1) ?
+                     indir[blk / indirsz] : indir [(blk / indirsz) << 1]) 
+                     << log2_blksz,
                      0, sizeof (indir), (char *) indir);
       
       return (data->ufs_type == UFS1) ?
             indir[blk % indirsz] : indir[(blk % indirsz) << 1];
     }
 
-
   grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
              "ufs does not support triple indirect blocks");
   return 0;
@@ -320,7 +338,7 @@ grub_ufs_read_file (struct grub_ufs_data *data,
 /* Read inode INO from the mounted filesystem described by DATA.  This
    inode is used by default now.  */
 static grub_err_t
-grub_ufs_read_inode (struct grub_ufs_data *data, int ino)
+grub_ufs_read_inode (struct grub_ufs_data *data, int ino, char *inode)
 {
   struct grub_ufs_sblock *sblock = &data->sblock;
   
@@ -335,8 +353,12 @@ static grub_err_t
   
   if (data->ufs_type == UFS1)
     {
-      struct grub_ufs_inode *inode = &data->inode;
-      
+      if (!inode)
+       {
+         inode = (char *) &data->inode;
+         data->ino = ino;
+       }
+
       grub_disk_read (data->disk,
                      (((grub_le_to_cpu32 (sblock->inoblk_offs) + grpblk)
                        << grub_le_to_cpu32 (data->sblock.log2_blksz)))
@@ -347,8 +369,12 @@ static grub_err_t
     }
   else
     {
-      struct grub_ufs2_inode *inode = &data->inode2;
-      
+      if (!inode)
+       {
+         inode = (char *) &data->inode2;
+         data->ino = ino;
+       }
+
       grub_disk_read (data->disk,
                      (((grub_le_to_cpu32 (sblock->inoblk_offs) + grpblk)
                        << grub_le_to_cpu32 (data->sblock.log2_blksz)))
@@ -358,7 +384,6 @@ static grub_err_t
                      (char *) inode);
     }
   
-  data->ino = ino;
   return grub_errno;
 }
 
@@ -372,9 +397,8 @@ grub_ufs_lookup_symlink (struct grub_ufs_data *dat
   
   if (++data->linknest > GRUB_UFS_MAX_SYMLNK_CNT)
     return grub_error (GRUB_ERR_SYMLINK_LOOP, "too deep nesting of symlinks");
-  
-  if (INODE_SIZE (data) < (GRUB_UFS_DIRBLKS + GRUB_UFS_INDIRBLKS
-                         * INODE_BLKSZ (data)))
+
+  if (INODE_NBLOCKS (data) == 0)
     grub_strcpy (symlink, (char *) INODE (data, symlink));
   else
     {
@@ -390,7 +414,7 @@ grub_ufs_lookup_symlink (struct grub_ufs_data *dat
     ino = GRUB_UFS_INODE;
   
   /* Now load in the old inode.  */
-  if (grub_ufs_read_inode (data, ino))
+  if (grub_ufs_read_inode (data, ino, 0))
     return grub_errno;
   
   grub_ufs_find_file (data, symlink);
@@ -433,29 +457,34 @@ grub_ufs_find_file (struct grub_ufs_data *data, co
   do
     {
       struct grub_ufs_dirent dirent;
-      
+      int namelen;
+
       if (grub_strlen (name) == 0)
        return GRUB_ERR_NONE;
       
       if (grub_ufs_read_file (data, 0, pos, sizeof (dirent),
                              (char *) &dirent) < 0)
        return grub_errno;
+
+      namelen = (data->ufs_type == UFS2)
+       ? dirent.namelen_bsd : grub_le_to_cpu16 (dirent.namelen);
       
       {
-       char filename[dirent.namelen + 1];
+       char filename[namelen + 1];
 
        if (grub_ufs_read_file (data, 0, pos + sizeof (dirent),
-                               dirent.namelen, filename) < 0)
+                               namelen, filename) < 0)
          return grub_errno;
        
-       filename[dirent.namelen] = '\0';
+       filename[namelen] = '\0';
        
        if (!grub_strcmp (name, filename))
          {
            dirino = data->ino;
-           grub_ufs_read_inode (data, grub_le_to_cpu32 (dirent.ino));
-           
-           if (dirent.filetype == GRUB_UFS_FILETYPE_LNK)
+           grub_ufs_read_inode (data, grub_le_to_cpu32 (dirent.ino), 0);
+
+           if ((INODE_MODE(data) & GRUB_UFS_ATTR_TYPE)
+               == GRUB_UFS_ATTR_LNK)
              {
                grub_ufs_lookup_symlink (data, dirino);
                if (grub_errno)
@@ -475,7 +504,7 @@ grub_ufs_find_file (struct grub_ufs_data *data, co
                next++;
              }
            
-           if (!(dirent.filetype & GRUB_UFS_FILETYPE_DIR))
+           if ((INODE_MODE(data) & GRUB_UFS_ATTR_TYPE) != GRUB_UFS_ATTR_DIR)
              return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
            
            continue;
@@ -544,7 +573,8 @@ grub_ufs_mount (grub_disk_t disk)
 
 static grub_err_t
 grub_ufs_dir (grub_device_t device, const char *path, 
-              int (*hook) (const char *filename, int dir))
+              int (*hook) (const char *filename, 
+                           const struct grub_dirhook_info *info))
 {
   struct grub_ufs_data *data;
   struct grub_ufs_sblock *sblock;
@@ -554,7 +584,7 @@ grub_ufs_dir (grub_device_t device, const char *pa
   if (!data)
     return grub_errno;
   
-  grub_ufs_read_inode (data, GRUB_UFS_INODE);
+  grub_ufs_read_inode (data, GRUB_UFS_INODE, 0);
   if (grub_errno)
     return grub_errno;
   
@@ -570,7 +600,7 @@ grub_ufs_dir (grub_device_t device, const char *pa
   if (grub_errno)
     goto fail;  
   
-  if (!(INODE_MODE (data) & GRUB_UFS_ATTR_DIR))
+  if ((INODE_MODE (data) & GRUB_UFS_ATTR_TYPE) != GRUB_UFS_ATTR_DIR)
     {
       grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
       goto fail;
@@ -579,20 +609,45 @@ grub_ufs_dir (grub_device_t device, const char *pa
   while (pos < INODE_SIZE (data))
     {
       struct grub_ufs_dirent dirent;
-      
+      int namelen;
+
       if (grub_ufs_read_file (data, 0, pos, sizeof (dirent),
                              (char *) &dirent) < 0)
        break;
+
+      namelen = (data->ufs_type == UFS2)
+       ? dirent.namelen_bsd : grub_le_to_cpu16 (dirent.namelen);
       
       {
-       char filename[dirent.namelen + 1];
+       char filename[namelen + 1];
+       struct grub_dirhook_info info;
+       grub_memset (&info, 0, sizeof (info));
        
        if (grub_ufs_read_file (data, 0, pos + sizeof (dirent),
-                               dirent.namelen, filename) < 0)
+                               namelen, filename) < 0)
          break;
        
-       filename[dirent.namelen] = '\0';
-       if (hook (filename, dirent.filetype == GRUB_UFS_FILETYPE_DIR))
+       filename[namelen] = '\0';
+       if (data->ufs_type == UFS1)
+         {
+           struct grub_ufs_inode inode;
+           grub_ufs_read_inode (data, dirent.ino, (char *) &inode);
+           info.dir = ((grub_le_to_cpu16 (inode.mode) & GRUB_UFS_ATTR_TYPE)
+                       == GRUB_UFS_ATTR_DIR);
+           info.mtime = grub_le_to_cpu64 (inode.mtime);
+           info.mtimeset = 1;
+         }
+       else
+         {
+           struct grub_ufs2_inode inode;
+           grub_ufs_read_inode (data, dirent.ino, (char *) &inode);
+           info.dir = ((grub_le_to_cpu16 (inode.mode) & GRUB_UFS_ATTR_TYPE)
+                       == GRUB_UFS_ATTR_DIR);
+           info.mtime = grub_le_to_cpu64 (inode.mtime);
+           info.mtimeset = 1;
+         }
+
+       if (hook (filename, &info))
          break;
       }
       
@@ -615,7 +670,7 @@ grub_ufs_open (struct grub_file *file, const char
   if (!data)
     return grub_errno;
   
-  grub_ufs_read_inode (data, 2);
+  grub_ufs_read_inode (data, 2, 0);
   if (grub_errno)
     {
       grub_free (data);
@@ -688,6 +743,34 @@ grub_ufs_label (grub_device_t device, char **label
   return grub_errno;
 }
 
+/* Get mtime.  */
+static grub_err_t 
+grub_ufs_mtime (grub_device_t device, grub_int32_t *tm)
+{
+  struct grub_ufs_data *data = 0;
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+
+  data = grub_ufs_mount (device->disk);
+  if (!data)
+    *tm = 0;
+  else if (data->ufs_type == UFS1)
+    *tm = grub_le_to_cpu32 (data->sblock.mtime);
+  else
+    *tm = grub_le_to_cpu64 (data->sblock.mtime2);
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  grub_free (data);
+
+  return grub_errno;
+}
+
+
 
 static struct grub_fs grub_ufs_fs =
   {
@@ -697,6 +780,7 @@ static struct grub_fs grub_ufs_fs =
     .read = grub_ufs_read,
     .close = grub_ufs_close,
     .label = grub_ufs_label,
+    .mtime = grub_ufs_mtime,
     .next = 0
   };
 
Index: include/grub/fs.h
===================================================================
--- include/grub/fs.h   (revision 2008)
+++ include/grub/fs.h   (working copy)
@@ -27,6 +27,14 @@
 /* Forward declaration is required, because of mutual reference.  */
 struct grub_file;
 
+struct grub_dirhook_info
+{
+  int dir:1;
+  int mtimeset:1;
+  int case_insensitive:1;
+  grub_int32_t mtime;
+};
+
 /* Filesystem descriptor.  */
 struct grub_fs
 {
@@ -35,7 +43,8 @@ struct grub_fs
 
   /* Call HOOK with each file under DIR.  */
   grub_err_t (*dir) (grub_device_t device, const char *path,
-                    int (*hook) (const char *filename, int dir));
+                    int (*hook) (const char *filename, 
+                                 const struct grub_dirhook_info *info));
   
   /* Open a file named NAME and initialize FILE.  */
   grub_err_t (*open) (struct grub_file *file, const char *name);
@@ -56,6 +65,9 @@ struct grub_fs
      caller.  */
   grub_err_t (*uuid) (grub_device_t device, char **uuid);
 
+  /* Get writing time of filesystem. */
+  grub_err_t (*mtime) (grub_device_t device, grub_int32_t *timebuf);
+
   /* The next filesystem.  */
   struct grub_fs *next;
 };
Index: include/grub/fshelp.h
===================================================================
--- include/grub/fshelp.h       (revision 2008)
+++ include/grub/fshelp.h       (working copy)
@@ -27,6 +27,8 @@
 typedef struct grub_fshelp_node *grub_fshelp_node_t;
 
 #define GRUB_FSHELP_CASE_INSENSITIVE   0x100
+#define GRUB_FSHELP_TYPE_MASK  0xff
+#define GRUB_FSHELP_FLAGS_MASK 0x100
 
 enum grub_fshelp_filetype
   {
Index: normal/completion.c
===================================================================
--- normal/completion.c (revision 2008)
+++ normal/completion.c (working copy)
@@ -123,9 +123,9 @@ iterate_partition (grub_disk_t disk, const grub_pa
 }
 
 static int
-iterate_dir (const char *filename, int dir)
+iterate_dir (const char *filename, const struct grub_dirhook_info *info)
 {
-  if (! dir)
+  if (! info->dir)
     {
       const char *prefix;
       if (cmdline_state == GRUB_PARSER_STATE_DQUOTE)
Index: normal/datetime.c
===================================================================
--- normal/datetime.c   (revision 1989)
+++ normal/datetime.c   (working copy)
@@ -17,7 +17,7 @@
  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <grub/lib/datetime.h>
+#include <grub/datetime.h>
 
 static char *grub_weekday_names[] =
 {
@@ -47,3 +47,54 @@ grub_get_weekday_name (struct grub_datetime *datet
 {
   return grub_weekday_names[grub_get_weekday (datetime)];
 }
+
+#define SECPERMIN 60
+#define SECPERHOUR (60*SECPERMIN)
+#define SECPERDAY (24*SECPERHOUR)
+#define SECPERYEAR (365*SECPERDAY)
+#define SECPER4YEARS (4*SECPERYEAR+SECPERDAY)
+
+
+void
+grub_unixtime2datetime (grub_int32_t nix, struct grub_datetime *datetime)
+{
+  int i;
+  int div;
+  grub_uint8_t months[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 
+  /* In the period of validity of unixtime all years divisible by 4 
+     are bissextile*/
+  /* Convenience: let's have 3 consecutive non-bissextile years 
+     at the begining of the epoch. So count from 1973 instead of 1970 */
+  nix -= 3*SECPERYEAR + SECPERDAY;
+  /* Transform C divisions and modulos to mathematical ones */
+  div = nix / SECPER4YEARS;
+  if (nix < 0)
+    div--;
+  datetime->year = 1973 + 4 * div;
+  nix -= div * SECPER4YEARS;
+
+  /* On 31st december of bissextile years 365 days from the begining 
+     of the year elapsed but year isn't finished yet*/
+  if (nix / SECPERYEAR == 4)
+    {
+      datetime->year += 3;
+      nix -= 3*SECPERYEAR;
+    }
+  else
+    {
+      datetime->year += nix / SECPERYEAR;
+      nix %= SECPERYEAR;
+    }
+  for (i = 0; i < 12 
+        && nix >= ((grub_int32_t) (i==1 && datetime->year % 4 == 0 
+                                   ? 29 : months[i]))*SECPERDAY; i++)
+    nix -= ((grub_int32_t) (i==1 && datetime->year % 4 == 0 
+                           ? 29 : months[i]))*SECPERDAY;
+  datetime->month = i + 1; 
+  datetime->day = 1 + (nix / SECPERDAY);
+  nix %= SECPERDAY;
+  datetime->hour = (nix / SECPERHOUR);  
+  nix %= SECPERHOUR;
+  datetime->minute = nix / SECPERMIN;
+  datetime->second = nix % SECPERMIN;
+}

Property changes on: normal/datetime.c
___________________________________________________________________
Added: svn:mergeinfo

Index: commands/date.c
===================================================================
--- commands/date.c     (revision 2008)
+++ commands/date.c     (working copy)
@@ -22,7 +22,7 @@
 #include <grub/arg.h>
 #include <grub/err.h>
 #include <grub/misc.h>
-#include <grub/lib/datetime.h>
+#include <grub/datetime.h>
 
 #define GRUB_DATETIME_SET_YEAR         1
 #define GRUB_DATETIME_SET_MONTH                2
Index: commands/ls.c
===================================================================
--- commands/ls.c       (revision 2008)
+++ commands/ls.c       (working copy)
@@ -29,6 +29,7 @@
 #include <grub/term.h>
 #include <grub/partition.h>
 #include <grub/file.h>
+#include <grub/datetime.h>
 
 static const struct grub_arg_option options[] =
   {
@@ -68,25 +69,29 @@ grub_ls_list_files (char *dirname, int longlist, i
   grub_fs_t fs;
   const char *path;
   grub_device_t dev;
-  auto int print_files (const char *filename, int dir);
-  auto int print_files_long (const char *filename, int dir);
+
+  auto int print_files (const char *filename, 
+                       const struct grub_dirhook_info *info);
+  auto int print_files_long (const char *filename, 
+                            const struct grub_dirhook_info *info);
   
-  int print_files (const char *filename, int dir)
+  int print_files (const char *filename, const struct grub_dirhook_info *info)
     {
       if (all || filename[0] != '.')
-       grub_printf ("%s%s ", filename, dir ? "/" : "");
+       grub_printf ("%s%s ", filename, info->dir ? "/" : "");
       
       return 0;
     }
      
-  int print_files_long (const char *filename, int dir)
+  int print_files_long (const char *filename, 
+                       const struct grub_dirhook_info *info)
     {
       char pathname[grub_strlen (dirname) + grub_strlen (filename) + 1];
 
       if ((! all) && (filename[0] == '.'))
        return 0;
 
-      if (! dir)
+      if (! info->dir)
        {
          grub_file_t file;
          
@@ -138,7 +143,23 @@ grub_ls_list_files (char *dirname, int longlist, i
       else
        grub_printf ("%-12s", "DIR");
 
-      grub_printf ("%s%s\n", filename, dir ? "/" : "");
+      if (info->mtimeset)
+       {
+         struct grub_datetime datetime;
+         grub_unixtime2datetime (info->mtime, &datetime);
+         if (human)
+           grub_printf (" %d-%02d-%02d %02d:%02d:%02d %-11s ",
+                        datetime.year, datetime.month, datetime.day,
+                        datetime.hour, datetime.minute, 
+                        datetime.second,
+                        grub_get_weekday_name (&datetime));
+         else
+           grub_printf (" %04d%02d%02d%02d%02d%02d ",
+                        datetime.year, datetime.month, 
+                        datetime.day, datetime.hour, 
+                        datetime.minute, datetime.second);
+       }
+      grub_printf ("%s%s\n", filename, info->dir ? "/" : "");
 
       return 0;
     }
@@ -181,7 +202,7 @@ grub_ls_list_files (char *dirname, int longlist, i
          /* PATH might be a regular file.  */
          char *p;
          grub_file_t file;
-
+         struct grub_dirhook_info info;
          grub_errno = 0;
          
          file = grub_file_open (dirname);
@@ -196,10 +217,11 @@ grub_ls_list_files (char *dirname, int longlist, i
            goto fail;
 
          all = 1;
+         grub_memset (&info, 0, sizeof (info));
          if (longlist)
-           print_files_long (p, 0);
+           print_files_long (p, &info);
          else
-           print_files (p, 0);
+           print_files (p, &info);
 
          grub_free (dirname);
        }
Index: util/hostfs.c
===================================================================
--- util/hostfs.c       (revision 2008)
+++ util/hostfs.c       (working copy)
@@ -16,7 +16,7 @@
  *  You should have received a copy of the GNU General Public License
  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
  */
-
+#define _BSD_SOURCE
 #include <grub/fs.h>
 #include <grub/file.h>
 #include <grub/disk.h>
@@ -57,7 +57,8 @@ is_dir (const char *path, const char *name)
 
 static grub_err_t
 grub_hostfs_dir (grub_device_t device, const char *path, 
-                int (*hook) (const char *filename, int dir))
+                int (*hook) (const char *filename, 
+                             const struct grub_dirhook_info *info))
 {
   DIR *dir;
 
@@ -73,16 +74,20 @@ grub_hostfs_dir (grub_device_t device, const char
   while (1)
     {
       struct dirent *de;
+      struct grub_dirhook_info info;
+      grub_memset (&info, 0, sizeof (info));
 
       de = readdir (dir);
       if (! de)
        break;
 
 #ifdef DT_DIR
-      hook (de->d_name, de->d_type == DT_DIR);
+      info.dir = (de->d_type == DT_DIR);
 #else
-      hook (de->d_name, is_dir (path, de->d_name));
+      info.dir = !!is_dir (path, de->d_name);
 #endif
+      hook (de->d_name, &info);
+
     }
 
   closedir (dir);
Index: ChangeLog
===================================================================
--- ChangeLog   (revision 2008)
+++ ChangeLog   (working copy)
@@ -1,3 +1,77 @@
+2009-03-01  Vladimir Serbinenko  <address@hidden>
+
+       UFS improvements
+
+       * fs/ufs.c (GRUB_UFS_ATTR_TYPE): new definition
+       (GRUB_UFS_ATTR_FILE): likewise
+       (GRUB_UFS_ATTR_LNK): likewise
+       (GRUB_UFS_BSD_DIRENT): likewise
+       (struct grub_ufs_sblock): new fields mtime and flags
+       (struct grub_ufs_dirent): added fields for non-BSD dirents
+       (grub_ufs_get_file_block): fixed double indirect handling
+       (grub_ufs_read_inode): new parameter to read inode to a separate buffer
+       all users updated
+       (grub_ufs_find_file): support for non-BSD dirents
+       (grub_ufs_dir): likewise and mtime support
+       (grub_ufs_mtime): new function
+
+2009-03-01  Vladimir Serbinenko  <address@hidden>
+
+       Support for mtime and further expandability of dir command
+
+       * include/grub/lib/datetime.h: moved to ...
+       * include/grub/datetime.h: ... moved here and added 
+       declaration of grub_unixtime2datetime. All users updated
+       * include/grub/fs.h: new syntax for dir and mtime functionin 
+       struct grub_fs 
+       * include/grub/fshelp.h: new declarations of GRUB_FSHELP_TYPE_MASK
+       and GRUB_FSHELP_FLAGS_MASK
+       * commands/ls.c (grub_ls_list_files): Write mtime in long format
+       * fs/ext2.c (grub_ext2_dir): use new dir syntax and supply mtime
+       (grub_ext2_mtime): new function
+       * fs/hfsplus.c (grub_hfsplus_dir): use new dir syntax and supply mtime
+       (grub_hfsplus_mtime): new function
+       * fs/affs.c (grub_affs_dir): use new dir syntax
+       * fs/afs.c (grub_afs_dir): likewise
+       * fs/cpio.c (grub_cpio_dir): likewise
+       * fs/fat.c (grub_fat_find_dir): likewise
+       * fs/hfs.c (grub_hfs_dir): likewise
+       * fs/iso9660.c (grub_iso9660_dir): likewise
+       * fs/jfs.c (grub_jfs_dir): likewise
+       * fs/minix.c (grub_minix_dir): likewise
+       * fs/ntfs.c (grub_ntfs_dir): likewise
+       * fs/reiserfs.c (grub_reiserfs_dir): likewise
+       * fs/sfs.c (grub_sfs_dir): likewise
+       * fs/xfs.c (grub_xfs_dir): likewise
+       * fs/ufs.c (grub_ufs_dir): likewise
+       * util/hostfs.c (grub_hostfs_dir): likewise
+       * lib/datetime.c: moved to ...
+       * normal/datetime.c: ... moved here
+       (grub_unixtime2datetime): new function
+       * kern/rescue.c (grub_rescue_print_files): use new dir syntax
+       * normal/completition.c (iterate_dir): use new dir syntax
+       * normal/misc.c (grub_normal_print_device_info): tell the 
+       last modification time of a volume
+       * kern/fs.c (grub_fs_probe): updated dummy function to use new syntax 
+       * conf/common.rmk: added lib/datetime.c to ls.mod
+       * conf/i386-coreboot.rmk: added normal/datetime.c to grub-emu 
+       and normal.mod. Removed lib/datetime.c from datetime.mod
+       * conf/i386-efi.rmk: likewise
+       * conf/i386-ieee1275.rmk: likewise      
+       * conf/i386-pc.rmk: likewise
+       * conf/powerpc-ieee1275.rmk: likewise
+       * conf/sparc64-ieee1275.rmk: likewise   
+       * conf/x86_64-efi.rmk: likewise 
+       
+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
+
 2009-02-27  Robert Millan  <address@hidden>
 
        Factorize elf32 / elf64 code in Multiboot loader.  This will

reply via email to

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