/* ext2.c - Second Extended filesystem */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc.
*
* 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/>.
*/
/* Magic value used to identify an ext2 filesystem. */
/* Amount of indirect blocks in an inode. */
/* The good old revision and the default inode size. */
#define EXT2_GOOD_OLD_REVISION 0
/* Filetype used in directory entry. */
#define FILETYPE_UNKNOWN 0
/* Filetype information as used in inodes. */
GRUB_MOD_LICENSE ("GPLv3+");
/* Log2 size of ext2 block in 512 blocks. */
/* Log2 size of ext2 block in bytes. */
/* The size of an ext2 block in bytes. */
/* The revision level. */
/* The inode size. */
/* Superblock filesystem feature flags (RW compatible)
* A filesystem with any of these enabled can be read and written by a driver
/* Superblock filesystem feature flags (RO compatible)
* A filesystem with any of these enabled can be safely read by a driver that
* does not understand them, but should not be written to, usually because
* additional metadata is required. */
/* Superblock filesystem feature flags (back-incompatible)
* A filesystem with any of these enabled should not be attempted to be read
* by a driver that does not understand them, since they usually indicate
* metadata format changes that might confuse the reader. */
/* The set of back-incompatible features this driver DOES support. Add (OR)
* flags here as the related features are implemented into the driver. */
/* List of rationales for the ignored "incompatible" features:
* needs_recovery: Not really back-incompatible - was added as such to forbid
* ext2 drivers from mounting an ext3 volume with a dirty
* journal because they will ignore the journal, but the next
* ext3 driver to mount the volume will find the journal and
* replay it, potentially corrupting the metadata written by
* the ext2 drivers. Safe to ignore for this RO driver. */
/* The ext2 superblock. */
struct grub_ext2_sblock
{
};
/* The ext2 blockgroup. */
struct grub_ext2_block_group
{
};
/* The ext2 inode. */
struct grub_ext2_inode
{
union
{
struct datablocks
{
} blocks;
};
};
/* The header of an ext2 directory entry. */
struct ext2_dirent
{
};
struct grub_ext3_journal_header
{
};
{
};
struct grub_ext3_journal_block_tag
{
};
struct grub_ext3_journal_sblock
{
};
struct grub_ext4_extent_header
{
};
struct grub_ext4_extent
{
};
struct grub_ext4_extent_idx
{
};
struct grub_fshelp_node
{
int ino;
int inode_read;
};
/* Information about a "mounted" ext2 filesystem. */
struct grub_ext2_data
{
};
/* Read into BLKGRP the blockgroup descriptor of blockgroup GROUP of
the mounted filesystem DATA. */
inline static grub_err_t
struct grub_ext2_block_group *blkgrp)
{
<< LOG2_EXT2_BLOCK_SIZE (data)),
group * sizeof (struct grub_ext2_block_group),
sizeof (struct grub_ext2_block_group), blkgrp);
}
static struct grub_ext4_extent_header *
struct grub_ext4_extent_header *ext_block,
{
while (1)
{
int i;
return 0;
return ext_block;
{
break;
}
if (--i < 0)
return 0;
return 0;
}
}
static grub_disk_addr_t
{
{
int i;
if (! leaf)
{
return -1;
}
{
break;
}
if (--i >= 0)
{
return 0;
else
{
}
}
else
{
return -1;
}
}
/* Direct blocks. */
if (fileblock < INDIRECT_BLOCKS)
/* Indirect. */
{
<< log2_blksz,
return grub_errno;
}
/* Double indirect. */
{
+ blksz / 4);
<< log2_blksz,
return grub_errno;
<< log2_blksz,
return grub_errno;
}
/* triple indirect. */
{
<< log2_blksz,
return grub_errno;
<< log2_blksz,
return grub_errno;
<< log2_blksz,
return grub_errno;
}
else
{
"ext2fs doesn't support quadruple indirect blocks");
}
return blknr;
}
/* Read LEN bytes from the file described by DATA starting with byte
POS. Return the amount of read bytes in READ. */
static grub_ssize_t
{
}
/* Read the inode INO for the file described by DATA into INODE. */
static grub_err_t
{
int inodes_per_block;
unsigned int blkno;
unsigned int blkoff;
/* It is easier to calculate if the first inode is 0. */
ino--;
&blkgrp);
if (grub_errno)
return grub_errno;
/* Read the inode. */
<< LOG2_EXT2_BLOCK_SIZE (data)),
sizeof (struct grub_ext2_inode), inode))
return grub_errno;
return 0;
}
static struct grub_ext2_data *
{
if (!data)
return 0;
/* Read the superblock. */
if (grub_errno)
goto fail;
/* Make sure this is an ext2 filesystem. */
{
goto fail;
}
/* Check the FS doesn't have feature bits enabled that we don't support. */
{
goto fail;
}
if (grub_errno)
goto fail;
return data;
fail:
if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
return 0;
}
static char *
{
char *symlink;
if (! diro->inode_read)
{
if (grub_errno)
return 0;
}
if (! symlink)
return 0;
/* If the filesize of the symlink is bigger than
60 the symlink is stored in a separate block,
otherwise it is stored in the inode. */
else
{
grub_ext2_read_file (diro, 0, 0,
symlink);
if (grub_errno)
{
return 0;
}
}
return symlink;
}
static int
int NESTED_FUNC_ATTR
enum grub_fshelp_filetype filetype,
{
unsigned int fpos = 0;
if (! diro->inode_read)
{
if (grub_errno)
return 0;
}
/* Search the file. */
{
(char *) &dirent);
if (grub_errno)
return 0;
return 0;
{
if (grub_errno)
return 0;
if (! fdiro)
return 0;
{
fdiro->inode_read = 0;
}
else
{
/* The filetype can not be read from the dirent, read
the inode to get more information. */
if (grub_errno)
{
return 0;
}
}
return 1;
}
}
return 0;
}
/* Open a file named NAME and initialize FILE. */
static grub_err_t
{
if (! data)
{
err = grub_errno;
goto fail;
}
if (err)
goto fail;
if (! fdiro->inode_read)
{
if (err)
goto fail;
}
return 0;
fail:
return err;
}
static grub_err_t
{
return GRUB_ERR_NONE;
}
/* Read LEN bytes data from FILE into BUF. */
static grub_ssize_t
{
}
static grub_err_t
const struct grub_dirhook_info *info))
{
enum grub_fshelp_filetype filetype,
enum grub_fshelp_filetype filetype,
{
if (! node->inode_read)
{
if (!grub_errno)
}
if (node->inode_read)
{
}
}
if (! data)
goto fail;
if (grub_errno)
goto fail;
fail:
return grub_errno;
}
static grub_err_t
{
if (data)
else
return grub_errno;
}
static grub_err_t
{
if (data)
{
}
else
return grub_errno;
}
/* Get mtime. */
static grub_err_t
{
if (!data)
*tm = 0;
else
return grub_errno;
}
{
.name = "ext2",
.dir = grub_ext2_dir,
.open = grub_ext2_open,
.read = grub_ext2_read,
.close = grub_ext2_close,
.label = grub_ext2_label,
.uuid = grub_ext2_uuid,
.mtime = grub_ext2_mtime,
#ifdef GRUB_UTIL
.reserved_first_sector = 1,
#endif
.next = 0
};
{
}
{
}