]> git.proxmox.com Git - grub2.git/blobdiff - grub-core/fs/minix.c
Minix FS fixes.
[grub2.git] / grub-core / fs / minix.c
index c93dfe085cfcf779fa0b07e02c4ed1d42864fc93..1db2883cde0481803f9d35f02175d5940ffefecb 100644 (file)
@@ -25,6 +25,8 @@
 #include <grub/dl.h>
 #include <grub/types.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 #ifdef MODE_MINIX3
 #define GRUB_MINIX_MAGIC       0x4D5A
 #elif defined(MODE_MINIX2)
@@ -61,7 +63,7 @@ typedef grub_uint16_t grub_minix_ino_t;
 #define grub_minix_le_to_cpu_ino grub_le_to_cpu16
 #endif
 
-#define GRUB_MINIX_INODE_SIZE(data) (grub_minix_le_to_cpu_n (data->inode.size))
+#define GRUB_MINIX_INODE_SIZE(data) (grub_le_to_cpu32 (data->inode.size))
 #define GRUB_MINIX_INODE_MODE(data) (grub_le_to_cpu16 (data->inode.mode))
 #define GRUB_MINIX_INODE_DIR_ZONES(data,blk) (grub_minix_le_to_cpu_n   \
                                              (data->inode.dir_zones[blk]))
@@ -70,10 +72,19 @@ typedef grub_uint16_t grub_minix_ino_t;
 #define GRUB_MINIX_INODE_DINDIR_ZONE(data) (grub_minix_le_to_cpu_n \
                                            (data->inode.double_indir_zone))
 
+#ifndef MODE_MINIX3
 #define GRUB_MINIX_LOG2_ZONESZ (GRUB_MINIX_LOG2_BSIZE                          \
-                                + grub_le_to_cpu16 (sblock->log2_zone_size))
+                                + grub_le_to_cpu16 (data->sblock.log2_zone_size))
+#endif
 #define GRUB_MINIX_ZONESZ      (data->block_size                               \
-                                << grub_le_to_cpu16 (sblock->log2_zone_size))
+                                << grub_le_to_cpu16 (data->sblock.log2_zone_size))
+
+#ifdef MODE_MINIX3
+#define GRUB_MINIX_ZONE2SECT(zone) ((zone) * (data->block_size / GRUB_DISK_SECTOR_SIZE))
+#else
+#define GRUB_MINIX_ZONE2SECT(zone) ((zone) << GRUB_MINIX_LOG2_ZONESZ)
+#endif
+
 
 #ifdef MODE_MINIX3
 struct grub_minix_sblock
@@ -107,15 +118,13 @@ struct grub_minix_sblock
 };
 #endif
 
-#if defined(MODE_MINIX3)
-
+#if defined(MODE_MINIX3) || defined(MODE_MINIX2)
 struct grub_minix_inode
 {
   grub_uint16_t mode;
   grub_uint16_t nlinks;
   grub_uint16_t uid;
-  grub_uint8_t gid;
-  grub_uint8_t pad;
+  grub_uint16_t gid;
   grub_uint32_t size;
   grub_uint32_t atime;
   grub_uint32_t mtime;
@@ -125,14 +134,13 @@ struct grub_minix_inode
   grub_uint32_t double_indir_zone;
   grub_uint32_t unused;
 };
-
-#elif defined(MODE_MINIX2)
+#else
 struct grub_minix_inode
 {
   grub_uint16_t mode;
   grub_uint16_t uid;
-  grub_uint16_t size;
-  grub_uint32_t ctime;
+  grub_uint32_t size;
+  grub_uint32_t mtime;
   grub_uint8_t gid;
   grub_uint8_t nlinks;
   grub_uint16_t dir_zones[7];
@@ -140,25 +148,6 @@ struct grub_minix_inode
   grub_uint16_t double_indir_zone;
 };
 
-#else
-
-struct grub_minix_inode
-{
-  grub_uint16_t mode;
-  grub_uint16_t nlinks;
-  grub_uint16_t uid;
-  grub_uint16_t gid;
-  grub_uint32_t size;
-  grub_uint32_t atime;
-  grub_uint32_t mtime;
-  grub_uint32_t ctime;
-  grub_uint32_t dir_zones[7];
-  grub_uint32_t indir_zone;
-  grub_uint32_t double_indir_zone;
-  grub_uint32_t unused;
-
-};
-
 #endif
 
 /* Information about a "mounted" minix filesystem.  */
@@ -178,24 +167,23 @@ static grub_dl_t my_mod;
 static grub_err_t grub_minix_find_file (struct grub_minix_data *data,
                                        const char *path);
 
-static int
+static grub_minix_uintn_t
 grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk)
 {
-  struct grub_minix_sblock *sblock = &data->sblock;
-  int indir;
+  grub_minix_uintn_t indir;
+  const grub_uint32_t block_per_zone = (GRUB_MINIX_ZONESZ
+                                       / GRUB_MINIX_INODE_BLKSZ (data));
 
-  auto int grub_get_indir (int, int);
+  auto grub_minix_uintn_t grub_get_indir (grub_minix_uintn_t,
+                                         grub_minix_uintn_t);
 
   /* Read the block pointer in ZONE, on the offset NUM.  */
-  int grub_get_indir (int zone, int num)
+  grub_minix_uintn_t grub_get_indir (grub_minix_uintn_t zone,
+                                    grub_minix_uintn_t num)
     {
       grub_minix_uintn_t indirn;
       grub_disk_read (data->disk,
-#ifdef MODE_MINIX3
-                      zone * (data->block_size / GRUB_DISK_SECTOR_SIZE),
-#else
-                     zone << GRUB_MINIX_LOG2_ZONESZ,
-#endif
+                     GRUB_MINIX_ZONE2SECT(zone),
                      sizeof (grub_minix_uintn_t) * num,
                      sizeof (grub_minix_uintn_t), (char *) &indirn);
       return grub_minix_le_to_cpu_n (indirn);
@@ -207,21 +195,20 @@ grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk)
 
   /* Indirect block.  */
   blk -= GRUB_MINIX_INODE_DIR_BLOCKS;
-  if (blk < GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data))
+  if (blk < block_per_zone)
     {
       indir = grub_get_indir (GRUB_MINIX_INODE_INDIR_ZONE (data), blk);
       return indir;
     }
 
   /* Double indirect block.  */
-  blk -= GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data);
-  if (blk < (GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data))
-      * (GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data)))
+  blk -= block_per_zone;
+  if (blk < block_per_zone * block_per_zone)
     {
       indir = grub_get_indir (GRUB_MINIX_INODE_DINDIR_ZONE (data),
-                             blk / GRUB_MINIX_ZONESZ);
+                             blk / block_per_zone);
 
-      indir = grub_get_indir (indir, blk % GRUB_MINIX_ZONESZ);
+      indir = grub_get_indir (indir, blk % block_per_zone);
 
       return indir;
     }
@@ -241,11 +228,10 @@ grub_minix_read_file (struct grub_minix_data *data,
                                         unsigned offset, unsigned length),
                      grub_off_t pos, grub_disk_addr_t len, char *buf)
 {
-  struct grub_minix_sblock *sblock = &data->sblock;
   grub_disk_addr_t i;
   grub_disk_addr_t blockcnt;
   grub_uint64_t posblock;
-  grub_uint32_t blockoff;
+  grub_uint64_t blockoff;
 
   /* Adjust len so it we can't read past the end of the file.  */
   if (len + pos > GRUB_MINIX_INODE_SIZE (data))
@@ -258,7 +244,7 @@ grub_minix_read_file (struct grub_minix_data *data,
   for (i = posblock; i < blockcnt; i++)
     {
       grub_disk_addr_t blknr;
-      grub_uint32_t blockend = data->block_size;
+      grub_uint64_t blockend = data->block_size;
       grub_off_t skipfirst = 0;
 
       blknr = grub_minix_get_file_block (data, i);
@@ -283,11 +269,7 @@ grub_minix_read_file (struct grub_minix_data *data,
 
       data->disk->read_hook = read_hook;
       grub_disk_read (data->disk,
-#ifdef MODE_MINIX3
-                     blknr * (sblock->block_size / GRUB_DISK_SECTOR_SIZE),
-#else
-                     blknr << GRUB_MINIX_LOG2_ZONESZ,
-#endif
+                     GRUB_MINIX_ZONE2SECT(blknr),
                      skipfirst, blockend, buf);
       data->disk->read_hook = 0;
       if (grub_errno)
@@ -313,13 +295,8 @@ grub_minix_read_inode (struct grub_minix_data *data, int ino)
 
   /* The first inode in minix is inode 1.  */
   ino--;
-  block = (2 + grub_le_to_cpu16 (sblock->inode_bmap_size)
-          + grub_le_to_cpu16 (sblock->zone_bmap_size));
-#ifndef MODE_MINIX3
-  block <<= GRUB_MINIX_LOG2_BSIZE;
-#else
-  block *= sblock->block_size / GRUB_DISK_SECTOR_SIZE;
-#endif
+  block = GRUB_MINIX_ZONE2SECT (2 + grub_le_to_cpu16 (sblock->inode_bmap_size)
+                               + grub_le_to_cpu16 (sblock->zone_bmap_size));
   block += ino / (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix_inode));
   int offs = (ino % (GRUB_DISK_SECTOR_SIZE
                     / sizeof (struct grub_minix_inode))
@@ -449,7 +426,7 @@ grub_minix_find_file (struct grub_minix_data *data, const char *path)
       pos += sizeof (ino) + data->filename_size;
     } while (pos < GRUB_MINIX_INODE_SIZE (data));
 
-  grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
+  grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", path);
   return grub_errno;
 }
 
@@ -560,6 +537,9 @@ grub_minix_dir (grub_device_t device, const char *path,
       grub_minix_read_inode (data, grub_minix_le_to_cpu_ino (ino));
       info.dir = ((GRUB_MINIX_INODE_MODE (data)
                   & GRUB_MINIX_IFDIR) == GRUB_MINIX_IFDIR);
+      info.mtimeset = 1;
+      info.mtime = grub_le_to_cpu32 (data->inode.mtime);
+
       if (hook (filename, &info) ? 1 : 0)
        break;