/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999, 2001, 2003 Free Software Foundation, Inc.
*
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef FSYS_EXT2FS
#include "shared.h"
#include "filesys.h"
/* sizes are always in bytes, BLOCK values are always in DEV_BSIZE (sectors) */
/* made up, defaults to 1 but can be passed via mount_opts */
typedef unsigned char __u8;
typedef unsigned short __u16;
typedef unsigned int __u32;
/*
* Constants relative to the data blocks, from ext2_fs.h
*/
struct ext2_super_block
{
/*
* These fields are for EXT2_DYNAMIC_REV superblocks only.
*
* Note: the difference between the compatible feature set and
* the incompatible feature set is that if there is a bit set
* in the incompatible feature set that the kernel doesn't
* know about, it should refuse to mount the filesystem.
*
* e2fsck's requirements are more strict; if it doesn't know
* about a feature in either the compatible or incompatible
* feature set, it must abort and not try to meddle with
* things it doesn't understand...
*/
/*
* Performance hints. Directory preallocation should only
* happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on.
*/
/*
* Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set.
*/
};
struct ext2_group_desc
{
};
struct ext2_inode
{
union
{
struct
{
}
struct
{
}
struct
{
}
}
union
{
struct
{
}
struct
{
}
struct
{
}
}
};
/* linux/posix_type.h */
typedef long linux_off_t;
struct ext2_dir_entry
{
};
/*
* EXT2_DIR_PAD defines the directory entries boundaries
*
* NOTE: It must be a multiple of 4
*/
/* made up, these are pointers into FSYS_BUF */
/* read once, always stays there: */
#define SUPERBLOCK \
((struct ext2_super_block *)(FSYS_BUF))
#define GROUP_DESC \
((struct ext2_group_desc *) \
((int)SUPERBLOCK + sizeof(struct ext2_super_block)))
#define INODE \
#define DATABLOCK1 \
((int)((int)INODE + sizeof(struct ext2_inode)))
#define DATABLOCK2 \
#define EXT2_DESC_PER_BLOCK(s) \
(EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
/*
* ffz = Find First Zero in word. Undefined if no zero exists,
* so code should check against ~0UL first..
*/
static __inline__ unsigned long
{
__asm__ ("bsfl %1,%0"
: "=r" (word)
: "r" (~word));
return word;
}
/* check filesystem types and read superblock into memory buffer */
int
ext2fs_mount (void)
{
&& (current_slice != PC_SLICE_TYPE_EXT2FS)
(char *) SUPERBLOCK)
retval = 0;
return retval;
}
/* Takes a file system block number and reads it into BUFFER. */
static int
{
#ifdef E2DEBUG
#endif /* E2DEBUG */
}
/* from
*/
/* Maps LOGICAL_BLOCK (the file offset divided by the blocksize) into
a physical block (the location in the file system) via an inode. */
static int
{
#ifdef E2DEBUG
unsigned char *i;
for (i = (unsigned char *) INODE;
i < ((unsigned char *) INODE + sizeof (struct ext2_inode));
i++)
{
{
printf ("\n");
}
else
{
printf (" ");
}
}
#endif /* E2DEBUG */
/* if it is directly pointed to by the inode, return that physical addr */
if (logical_block < EXT2_NDIR_BLOCKS)
{
#ifdef E2DEBUG
#endif /* E2DEBUG */
}
/* else */
/* try the indirect block */
{
if (mapblock1 != 1
{
return -1;
}
mapblock1 = 1;
}
/* else */
/* now try the double indirect block */
{
int bnum;
if (mapblock1 != 2
{
return -1;
}
mapblock1 = 2;
!= mapblock2
{
return -1;
}
return ((__u32 *) DATABLOCK2)
}
/* else */
mapblock2 = -1;
if (mapblock1 != 3
{
return -1;
}
mapblock1 = 3;
* 2)],
{
return -1;
}
{
return -1;
}
return ((__u32 *) DATABLOCK2)
}
/* preconditions: all preconds of ext2fs_block_map */
int
{
int logical_block;
int offset;
int map;
int ret = 0;
int size = 0;
#ifdef E2DEBUG
unsigned char *i;
for (i = (unsigned char *) INODE;
i < ((unsigned char *) INODE + sizeof (struct ext2_inode));
i++)
{
{
printf ("\n");
}
else
{
printf (" ");
}
}
#endif /* E2DEBUG */
while (len > 0)
{
/* find the (logical) block component of our location */
#ifdef E2DEBUG
#endif /* E2DEBUG */
if (map < 0)
break;
if (map == 0) {
} else {
}
}
if (errnum)
ret = 0;
return ret;
}
/* Based on:
def_blk_fops points to
blkdev_open, which calls (I think):
sys_open()
do_open()
open_namei()
dir_namei() which accesses current->fs->root
fs->root was set during original mount:
(something)... which calls (I think):
ext2_read_super()
iget()
__iget()
read_inode()
ext2_read_inode()
uses desc_per_block_bits, which is set in ext2_read_super()
also uses group descriptors loaded during ext2_read_super()
lookup()
ext2_lookup()
ext2_find_entry()
ext2_getblk()
*/
static inline
int ext2_is_fast_symlink (void)
{
int ea_blocks;
}
/* preconditions: ext2fs_mount already executed, therefore supblk in buffer
* known as SUPERBLOCK
* returns: 0 if error, nonzero iff we were able to find the file successfully
* postconditions: on a nonzero return, buffer known as INODE contains the
* inode of the file we were trying to look up
* side effects: messes up GROUP_DESC buffer area
*/
int
{
int link_count = 0;
char *rest;
#ifdef E2DEBUG
unsigned char *i;
#endif /* E2DEBUG */
/* loop invariants:
current_ino = inode to lookup
dirname = pointer to filename component we are cur looking up within
the directory known pointed to by current_ino (if any)
*/
while (1)
{
#ifdef E2DEBUG
#endif /* E2DEBUG */
/* look up an inode */
#ifdef E2DEBUG
#endif /* E2DEBUG */
if (!ext2_rdfsb (
(int) GROUP_DESC))
{
return 0;
}
gdp = GROUP_DESC;
#ifdef E2DEBUG
#endif /* E2DEBUG */
{
return 0;
}
/* reset indirect blocks! */
#ifdef E2DEBUG
printf ("ipb=%d, sizeof(inode)=%d\n",
i++)
{
{
printf ("\n");
}
else
{
printf (" ");
}
}
#endif /* E2DEBUG */
/* copy inode to fixed location */
#ifdef E2DEBUG
#endif /* E2DEBUG */
/* If we've got a symbolic link, then chase it. */
{
int len;
if (++link_count > MAX_LINK_COUNT)
{
return 0;
}
/* Find out how long our remaining name is. */
len = 0;
len++;
/* Get the symlink size. */
{
return 0;
}
if (len)
{
/* Copy the remaining name to the end of the symlink data.
Note that DIRNAME and LINKBUF may overlap! */
}
/* Read the symlink data. */
if (! ext2_is_fast_symlink ())
{
/* Read the necessary blocks, and reset the file pointer. */
filepos = 0;
if (!len)
return 0;
}
else
{
/* Copy the data directly from the inode. */
}
#ifdef E2DEBUG
#endif
if (*dirname == '/')
{
/* It's an absolute link, so look it up in root. */
}
else
{
/* Relative, so look it up in our parent directory. */
}
/* Try again using the new name. */
continue;
}
/* if end of filename, INODE points to the file's inode */
{
{
return 0;
}
return 1;
}
/* else we have to traverse a directory */
/* skip over slashes */
while (*dirname == '/')
dirname++;
/* if this isn't a directory of sufficient size to hold our file, abort */
{
return 0;
}
/* skip to next slash or end of filename (space) */
rest++);
/* look through this directory and find the next filename component */
/* invariant: rest points to slash after the next filename component */
*rest = 0;
loc = 0;
do
{
#ifdef E2DEBUG
#endif /* E2DEBUG */
give up */
{
if (print_possibilities < 0)
{
# if 0
putchar ('\n');
# endif
}
else
{
}
return (print_possibilities < 0);
}
/* else, find the (logical) block component of our location */
/* we know which logical block of the directory entry we are looking
for, now we have to translate that to the physical (fs) block on
the disk */
#ifdef E2DEBUG
#endif /* E2DEBUG */
mapblock2 = -1;
{
return 0;
}
/* advance loc prematurely to next on-disk directory entry */
/* NOTE: ext2fs filenames are NOT null-terminated */
#ifdef E2DEBUG
#endif /* E2DEBUG */
{
# ifndef STAGE1_5
{
if (print_possibilities > 0)
}
# endif
}
}
}
/* never get here */
}
#endif /* FSYS_EXT2_FS */