/* ext2.c - Second Extended filesystem */
/*
* GRUB -- GRand Unified Bootloader
- * Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+ * Copyright (C) 2003,2004,2005,2007 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
/* Maximum nesting of symlinks, used to prevent a loop. */
#define EXT2_MAX_SYMLINKCNT 8
+/* The good old revision and the default inode size. */
+#define EXT2_GOOD_OLD_REVISION 0
+#define EXT2_GOOD_OLD_INODE_SIZE 128
+
/* Filetype used in directory entry. */
#define FILETYPE_UNKNOWN 0
#define FILETYPE_REG 1
(grub_le_to_cpu32 (data->sblock.log2_block_size) + 10)
/* The size of an ext2 block in bytes. */
-#define EXT2_BLOCK_SIZE(data) (1 << LOG2_BLOCK_SIZE(data))
+#define EXT2_BLOCK_SIZE(data) (1 << LOG2_BLOCK_SIZE (data))
+
+/* The revision level. */
+#define EXT2_REVISION(data) grub_le_to_cpu32 (data->sblock.revision_level)
+
+/* The inode size. */
+#define EXT2_INODE_SIZE(data) \
+ (EXT2_REVISION (data) == EXT2_GOOD_OLD_REVISION \
+ ? EXT2_GOOD_OLD_INODE_SIZE \
+ : grub_le_to_cpu16 (data->sblock.inode_size))
/* The ext2 superblock. */
struct grub_ext2_sblock
grub_uint32_t inode_table_id;
grub_uint16_t free_blocks;
grub_uint16_t free_inodes;
+ grub_uint16_t used_dirs;
grub_uint16_t pad;
grub_uint32_t reserved[3];
};
#ifndef GRUB_UTIL
static grub_dl_t my_mod;
#endif
+
\f
+
/* Read into BLKGRP the blockgroup descriptor of blockgroup GROUP of
the mounted filesystem DATA. */
inline static grub_err_t
blknr = grub_le_to_cpu32 (indir[fileblock - INDIRECT_BLOCKS]);
}
/* Double indirect. */
- else if (fileblock < INDIRECT_BLOCKS + blksz / 4 * (blksz / 4 + 1))
+ else if (fileblock < INDIRECT_BLOCKS + blksz / 4 * (blksz / 4 + 1))
{
unsigned int perblock = blksz / 4;
unsigned int rblock = fileblock - (INDIRECT_BLOCKS
/* It is easier to calculate if the first inode is 0. */
ino--;
- grub_ext2_blockgroup (data, ino / grub_le_to_cpu32 (sblock->inodes_per_group),
+ grub_ext2_blockgroup (data,
+ ino / grub_le_to_cpu32 (sblock->inodes_per_group),
&blkgrp);
if (grub_errno)
return grub_errno;
- inodes_per_block = EXT2_BLOCK_SIZE (data) / 128;
+ inodes_per_block = EXT2_BLOCK_SIZE (data) / EXT2_INODE_SIZE (data);
blkno = (ino % grub_le_to_cpu32 (sblock->inodes_per_group))
/ inodes_per_block;
blkoff = (ino % grub_le_to_cpu32 (sblock->inodes_per_group))
if (grub_disk_read (data->disk,
((grub_le_to_cpu32 (blkgrp.inode_table_id) + blkno)
<< LOG2_EXT2_BLOCK_SIZE (data)),
- grub_le_to_cpu16 (sblock->inode_size) * blkoff,
+ EXT2_INODE_SIZE (data) * blkoff,
sizeof (struct grub_ext2_inode), (char *) inode))
return grub_errno;
/* Read the superblock. */
grub_disk_read (disk, 1 * 2, 0, sizeof (struct grub_ext2_sblock),
- (char *) &data->sblock);
+ (char *) &data->sblock);
if (grub_errno)
goto fail;
char *symlink;
struct grub_fshelp_node *diro = node;
- if (!diro->inode_read)
+ if (! diro->inode_read)
{
grub_ext2_read_inode (diro->data, diro->ino, &diro->inode);
if (grub_errno)
}
symlink = grub_malloc (grub_le_to_cpu32 (diro->inode.size) + 1);
- if (!symlink)
+ if (! symlink)
return 0;
/* If the filesize of the symlink is bigger than
unsigned int fpos = 0;
struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir;
- if (!diro->inode_read)
+ if (! diro->inode_read)
{
grub_ext2_read_inode (diro->data, diro->ino, &diro->inode);
if (grub_errno)
return 0;
fdiro = grub_malloc (sizeof (struct grub_fshelp_node));
- if (!fdiro)
+ if (! fdiro)
return 0;
fdiro->data = diro->data;
{
/* The filetype can not be read from the dirent, read
the inode to get more information. */
- grub_ext2_read_inode (diro->data, grub_le_to_cpu32 (dirent.inode),
+ grub_ext2_read_inode (diro->data,
+ grub_le_to_cpu32 (dirent.inode),
&fdiro->inode);
if (grub_errno)
{
#endif
data = grub_ext2_mount (file->device->disk);
- if (!data)
+ if (! data)
goto fail;
grub_fshelp_find_file (name, &data->diropen, &fdiro, grub_ext2_iterate_dir,
if (grub_errno)
goto fail;
- if (!fdiro->inode_read)
+ if (! fdiro->inode_read)
{
grub_ext2_read_inode (data, fdiro->ino, &fdiro->inode);
if (grub_errno)
static grub_ssize_t
grub_ext2_read (grub_file_t file, char *buf, grub_size_t len)
{
- struct grub_ext2_data *data =
- (struct grub_ext2_data *) file->data;
+ struct grub_ext2_data *data = (struct grub_ext2_data *) file->data;
return grub_ext2_read_file (&data->diropen, file->read_hook,
file->offset, len, buf);
#endif
data = grub_ext2_mount (device->disk);
- if (!data)
+ if (! data)
goto fail;
grub_fshelp_find_file (path, &data->diropen, &fdiro, grub_ext2_iterate_dir,
while (*name == '/')
name++;
- if (!*name)
+ if (! *name)
{
*currfound = currnode;
return 0;
/* Iterate over the directory. */
found = iterate_dir (currnode, iterate);
- if (!found)
+ if (! found)
{
if (grub_errno)
return grub_errno;
{
free_node (currnode);
free_node (oldnode);
- return grub_error (GRUB_ERR_SYMLINK_LOOP, "too deep nesting of symlinks");
+ return grub_error (GRUB_ERR_SYMLINK_LOOP,
+ "too deep nesting of symlinks");
}
symlink = read_symlink (currnode);
free_node (oldnode);
/* Found the node! */
- if (!next || *next == '\0')
+ if (! next || *next == '\0')
{
*currfound = currnode;
foundtype = type;
int blockcnt;
int blocksize = 1 << (log2blocksize + GRUB_DISK_SECTOR_BITS);
- /* Adjust len so it we can't read past the end of the file. */
+ /* Adjust LEN so it we can't read past the end of the file. */
if (len > filesize)
len = filesize;
- blockcnt = ((len + pos)
- + blocksize - 1) / blocksize;
+ blockcnt = ((len + pos) + blocksize - 1) / blocksize;
for (i = pos / blocksize; i < blockcnt; i++)
{
blockend = (len + pos) % blocksize;
/* The last portion is exactly blocksize. */
- if (!blockend)
+ if (! blockend)
blockend = blocksize;
}
*pow = 0;
while (blksize > 1)
{
- mod = blksize - ((blksize >> 1) << 1);
+ mod = blksize - ((blksize >> 1) << 1);
blksize >>= 1;
/* Check if it really is a power of two. */