15b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*
25b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  GRUB  --  GRand Unified Bootloader
35b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  Copyright (C) 1999, 2001, 2003  Free Software Foundation, Inc.
45b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
55b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  This program is free software; you can redistribute it and/or modify
65b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  it under the terms of the GNU General Public License as published by
75b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  the Free Software Foundation; either version 2 of the License, or
85b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  (at your option) any later version.
95b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  This program is distributed in the hope that it will be useful,
115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  but WITHOUT ANY WARRANTY; without even the implied warranty of
125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  GNU General Public License for more details.
145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  You should have received a copy of the GNU General Public License
165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  along with this program; if not, write to the Free Software
175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef FSYS_EXT2FS
215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include "shared.h"
235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include "filesys.h"
245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int mapblock1, mapblock2;
265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* sizes are always in bytes, BLOCK values are always in DEV_BSIZE (sectors) */
285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define DEV_BSIZE 512
295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* include/linux/fs.h */
315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define BLOCK_SIZE 1024		/* initial block size for superblock read */
325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* made up, defaults to 1 but can be passed via mount_opts */
335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define WHICH_SUPER 1
345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* kind of from fs/ext2/super.c */
355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define SBLOCK (WHICH_SUPER * BLOCK_SIZE / DEV_BSIZE)	/* = 2 */
365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* include/asm-i386/types.h */
385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projecttypedef __signed__ char __s8;
395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projecttypedef unsigned char __u8;
405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projecttypedef __signed__ short __s16;
415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projecttypedef unsigned short __u16;
425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projecttypedef __signed__ int __s32;
435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projecttypedef unsigned int __u32;
445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*
465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Constants relative to the data blocks, from ext2_fs.h
475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define EXT2_NDIR_BLOCKS                12
495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define EXT2_IND_BLOCK                  EXT2_NDIR_BLOCKS
505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define EXT2_DIND_BLOCK                 (EXT2_IND_BLOCK + 1)
515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define EXT2_TIND_BLOCK                 (EXT2_DIND_BLOCK + 1)
525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define EXT2_N_BLOCKS                   (EXT2_TIND_BLOCK + 1)
535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* include/linux/ext2_fs.h */
555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstruct ext2_super_block
565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  {
575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 s_inodes_count;	/* Inodes count */
585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 s_blocks_count;	/* Blocks count */
595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 s_r_blocks_count;	/* Reserved blocks count */
605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 s_free_blocks_count;	/* Free blocks count */
615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 s_free_inodes_count;	/* Free inodes count */
625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 s_first_data_block;	/* First Data Block */
635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 s_log_block_size;	/* Block size */
645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __s32 s_log_frag_size;	/* Fragment size */
655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 s_blocks_per_group;	/* # Blocks per group */
665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 s_frags_per_group;	/* # Fragments per group */
675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 s_inodes_per_group;	/* # Inodes per group */
685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 s_mtime;		/* Mount time */
695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 s_wtime;		/* Write time */
705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u16 s_mnt_count;		/* Mount count */
715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __s16 s_max_mnt_count;	/* Maximal mount count */
725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u16 s_magic;		/* Magic signature */
735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u16 s_state;		/* File system state */
745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u16 s_errors;		/* Behaviour when detecting errors */
755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u16 s_pad;
765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 s_lastcheck;		/* time of last check */
775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 s_checkinterval;	/* max. time between checks */
785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 s_creator_os;		/* OS */
795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 s_rev_level;		/* Revision level */
805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u16 s_def_resuid;		/* Default uid for reserved blocks */
815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u16 s_def_resgid;		/* Default gid for reserved blocks */
825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 s_reserved[235];	/* Padding to the end of the block */
835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  };
845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstruct ext2_group_desc
865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  {
875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 bg_block_bitmap;	/* Blocks bitmap block */
885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 bg_inode_bitmap;	/* Inodes bitmap block */
895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 bg_inode_table;	/* Inodes table block */
905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u16 bg_free_blocks_count;	/* Free blocks count */
915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u16 bg_free_inodes_count;	/* Free inodes count */
925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u16 bg_used_dirs_count;	/* Directories count */
935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u16 bg_pad;
945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 bg_reserved[3];
955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  };
965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstruct ext2_inode
985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  {
995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u16 i_mode;		/* File mode */
1005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u16 i_uid;		/* Owner Uid */
1015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 i_size;		/* 4: Size in bytes */
1025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 i_atime;		/* Access time */
1035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 i_ctime;		/* 12: Creation time */
1045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 i_mtime;		/* Modification time */
1055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 i_dtime;		/* 20: Deletion Time */
1065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u16 i_gid;		/* Group Id */
1075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u16 i_links_count;	/* 24: Links count */
1085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 i_blocks;		/* Blocks count */
1095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 i_flags;		/* 32: File flags */
1105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    union
1115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      {
1125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	struct
1135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  {
1145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    __u32 l_i_reserved1;
1155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  }
1165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	linux1;
1175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	struct
1185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  {
1195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    __u32 h_i_translator;
1205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  }
1215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	hurd1;
1225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	struct
1235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  {
1245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    __u32 m_i_reserved1;
1255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  }
1265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	masix1;
1275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      }
1285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    osd1;			/* OS dependent 1 */
1295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 i_block[EXT2_N_BLOCKS];	/* 40: Pointers to blocks */
1305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 i_version;		/* File version (for NFS) */
1315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 i_file_acl;		/* File ACL */
1325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 i_dir_acl;		/* Directory ACL */
1335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 i_faddr;		/* Fragment address */
1345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    union
1355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      {
1365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	struct
1375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  {
1385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    __u8 l_i_frag;	/* Fragment number */
1395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    __u8 l_i_fsize;	/* Fragment size */
1405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    __u16 i_pad1;
1415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    __u32 l_i_reserved2[2];
1425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  }
1435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	linux2;
1445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	struct
1455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  {
1465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    __u8 h_i_frag;	/* Fragment number */
1475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    __u8 h_i_fsize;	/* Fragment size */
1485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    __u16 h_i_mode_high;
1495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    __u16 h_i_uid_high;
1505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    __u16 h_i_gid_high;
1515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    __u32 h_i_author;
1525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  }
1535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	hurd2;
1545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	struct
1555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  {
1565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    __u8 m_i_frag;	/* Fragment number */
1575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    __u8 m_i_fsize;	/* Fragment size */
1585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    __u16 m_pad1;
1595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    __u32 m_i_reserved2[2];
1605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  }
1615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	masix2;
1625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      }
1635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    osd2;			/* OS dependent 2 */
1645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  };
1655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* linux/limits.h */
1675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define NAME_MAX         255	/* # chars in a file name */
1685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* linux/posix_type.h */
1705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projecttypedef long linux_off_t;
1715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* linux/ext2fs.h */
1735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define EXT2_NAME_LEN 255
1745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstruct ext2_dir_entry
1755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  {
1765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u32 inode;		/* Inode number */
1775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u16 rec_len;		/* Directory entry length */
1785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u8 name_len;		/* Name length */
1795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    __u8 file_type;
1805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    char name[EXT2_NAME_LEN];	/* File name */
1815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  };
1825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* linux/ext2fs.h */
1845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*
1855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * EXT2_DIR_PAD defines the directory entries boundaries
1865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
1875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * NOTE: It must be a multiple of 4
1885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
1895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define EXT2_DIR_PAD                    4
1905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define EXT2_DIR_ROUND                  (EXT2_DIR_PAD - 1)
1915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define EXT2_DIR_REC_LEN(name_len)      (((name_len) + 8 + EXT2_DIR_ROUND) & \
1925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                                         ~EXT2_DIR_ROUND)
1935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* ext2/super.c */
1965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define log2(n) ffz(~(n))
1975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define EXT2_SUPER_MAGIC      0xEF53	/* include/linux/ext2_fs.h */
1995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define EXT2_ROOT_INO              2	/* include/linux/ext2_fs.h */
2005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define PATH_MAX                1024	/* include/linux/limits.h */
2015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define MAX_LINK_COUNT             5	/* number of symbolic links to follow */
2025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* made up, these are pointers into FSYS_BUF */
2045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* read once, always stays there: */
2055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define SUPERBLOCK \
2065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    ((struct ext2_super_block *)(FSYS_BUF))
2075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define GROUP_DESC \
2085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    ((struct ext2_group_desc *) \
2095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     ((int)SUPERBLOCK + sizeof(struct ext2_super_block)))
2105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define INODE \
2115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    ((struct ext2_inode *)((int)GROUP_DESC + EXT2_BLOCK_SIZE(SUPERBLOCK)))
2125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define DATABLOCK1 \
2135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    ((int)((int)INODE + sizeof(struct ext2_inode)))
2145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define DATABLOCK2 \
2155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    ((int)((int)DATABLOCK1 + EXT2_BLOCK_SIZE(SUPERBLOCK)))
2165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* linux/ext2_fs.h */
2185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define EXT2_ADDR_PER_BLOCK(s)          (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
2195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define EXT2_ADDR_PER_BLOCK_BITS(s)		(log2(EXT2_ADDR_PER_BLOCK(s)))
2205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* linux/ext2_fs.h */
2225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define EXT2_BLOCK_SIZE_BITS(s)        ((s)->s_log_block_size + 10)
2235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* kind of from ext2/super.c */
2245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define EXT2_BLOCK_SIZE(s)	(1 << EXT2_BLOCK_SIZE_BITS(s))
2255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* linux/ext2fs.h */
2265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define EXT2_DESC_PER_BLOCK(s) \
2275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
2285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* linux/stat.h */
2295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define S_IFMT  00170000
2305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define S_IFLNK  0120000
2315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define S_IFREG  0100000
2325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define S_IFDIR  0040000
2335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define S_ISLNK(m)	(((m) & S_IFMT) == S_IFLNK)
2345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define S_ISREG(m)      (((m) & S_IFMT) == S_IFREG)
2355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define S_ISDIR(m)      (((m) & S_IFMT) == S_IFDIR)
2365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* include/asm-i386/bitops.h */
2385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*
2395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * ffz = Find First Zero in word. Undefined if no zero exists,
2405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * so code should check against ~0UL first..
2415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
2425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic __inline__ unsigned long
2435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectffz (unsigned long word)
2445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
2455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  __asm__ ("bsfl %1,%0"
2465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project:	   "=r" (word)
2475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project:	   "r" (~word));
2485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  return word;
2495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
2505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* check filesystem types and read superblock into memory buffer */
2525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectint
2535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectext2fs_mount (void)
2545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
2555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int retval = 1;
2565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if ((((current_drive & 0x80) || (current_slice != 0))
2585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       && (current_slice != PC_SLICE_TYPE_EXT2FS)
2595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       && (current_slice != PC_SLICE_TYPE_LINUX_RAID)
2605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       && (! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_EXT2FS))
2615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       && (! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_OTHER)))
2625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      || part_length < (SBLOCK + (sizeof (struct ext2_super_block) / DEV_BSIZE))
2635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      || !devread (SBLOCK, 0, sizeof (struct ext2_super_block),
2645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		   (char *) SUPERBLOCK)
2655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      || SUPERBLOCK->s_magic != EXT2_SUPER_MAGIC)
2665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      retval = 0;
2675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  return retval;
2695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
2705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Takes a file system block number and reads it into BUFFER. */
2725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int
2735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectext2_rdfsb (int fsblock, int buffer)
2745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
2755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef E2DEBUG
2765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  printf ("fsblock %d buffer %d\n", fsblock, buffer);
2775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif /* E2DEBUG */
2785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  return devread (fsblock * (EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE), 0,
2795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  EXT2_BLOCK_SIZE (SUPERBLOCK), (char *) buffer);
2805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
2815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* from
2835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  ext2/inode.c:ext2_bmap()
2845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project*/
2855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Maps LOGICAL_BLOCK (the file offset divided by the blocksize) into
2865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   a physical block (the location in the file system) via an inode. */
2875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int
2885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectext2fs_block_map (int logical_block)
2895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
2905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef E2DEBUG
2925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  unsigned char *i;
2935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  for (i = (unsigned char *) INODE;
2945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       i < ((unsigned char *) INODE + sizeof (struct ext2_inode));
2955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       i++)
2965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
2975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      printf ("%c", "0123456789abcdef"[*i >> 4]);
2985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      printf ("%c", "0123456789abcdef"[*i % 16]);
2995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (!((i + 1 - (unsigned char *) INODE) % 16))
3005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
3015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  printf ("\n");
3025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
3035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      else
3045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
3055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  printf (" ");
3065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
3075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
3085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  printf ("logical block %d\n", logical_block);
3095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif /* E2DEBUG */
3105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* if it is directly pointed to by the inode, return that physical addr */
3125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (logical_block < EXT2_NDIR_BLOCKS)
3135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
3145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef E2DEBUG
3155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      printf ("returning %d\n", (unsigned char *) (INODE->i_block[logical_block]));
3165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      printf ("returning %d\n", INODE->i_block[logical_block]);
3175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif /* E2DEBUG */
3185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      return INODE->i_block[logical_block];
3195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
3205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* else */
3215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  logical_block -= EXT2_NDIR_BLOCKS;
3225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* try the indirect block */
3235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (logical_block < EXT2_ADDR_PER_BLOCK (SUPERBLOCK))
3245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
3255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (mapblock1 != 1
3265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  && !ext2_rdfsb (INODE->i_block[EXT2_IND_BLOCK], DATABLOCK1))
3275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
3285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  errnum = ERR_FSYS_CORRUPT;
3295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  return -1;
3305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
3315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      mapblock1 = 1;
3325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      return ((__u32 *) DATABLOCK1)[logical_block];
3335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
3345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* else */
3355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  logical_block -= EXT2_ADDR_PER_BLOCK (SUPERBLOCK);
3365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* now try the double indirect block */
3375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (logical_block < (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2)))
3385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
3395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      int bnum;
3405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (mapblock1 != 2
3415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  && !ext2_rdfsb (INODE->i_block[EXT2_DIND_BLOCK], DATABLOCK1))
3425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
3435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  errnum = ERR_FSYS_CORRUPT;
3445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  return -1;
3455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
3465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      mapblock1 = 2;
3475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if ((bnum = (((__u32 *) DATABLOCK1)
3485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		   [logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)]))
3495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  != mapblock2
3505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  && !ext2_rdfsb (bnum, DATABLOCK2))
3515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
3525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  errnum = ERR_FSYS_CORRUPT;
3535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  return -1;
3545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
3555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      mapblock2 = bnum;
3565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      return ((__u32 *) DATABLOCK2)
3575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	[logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
3585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
3595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* else */
3605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  mapblock2 = -1;
3615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  logical_block -= (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2));
3625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (mapblock1 != 3
3635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      && !ext2_rdfsb (INODE->i_block[EXT2_TIND_BLOCK], DATABLOCK1))
3645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
3655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      errnum = ERR_FSYS_CORRUPT;
3665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      return -1;
3675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
3685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  mapblock1 = 3;
3695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (!ext2_rdfsb (((__u32 *) DATABLOCK1)
3705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		   [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)
3715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				      * 2)],
3725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		   DATABLOCK2))
3735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
3745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      errnum = ERR_FSYS_CORRUPT;
3755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      return -1;
3765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
3775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (!ext2_rdfsb (((__u32 *) DATABLOCK2)
3785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		   [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK))
3795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		    & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)],
3805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		   DATABLOCK2))
3815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
3825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      errnum = ERR_FSYS_CORRUPT;
3835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      return -1;
3845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
3855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  return ((__u32 *) DATABLOCK2)
3865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
3875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
3885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* preconditions: all preconds of ext2fs_block_map */
3905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectint
3915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectext2fs_read (char *buf, int len)
3925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
3935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int logical_block;
3945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int offset;
3955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int map;
3965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int ret = 0;
3975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int size = 0;
3985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef E2DEBUG
4005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  static char hexdigit[] = "0123456789abcdef";
4015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  unsigned char *i;
4025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  for (i = (unsigned char *) INODE;
4035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       i < ((unsigned char *) INODE + sizeof (struct ext2_inode));
4045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       i++)
4055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
4065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      printf ("%c", hexdigit[*i >> 4]);
4075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      printf ("%c", hexdigit[*i % 16]);
4085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (!((i + 1 - (unsigned char *) INODE) % 16))
4095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
4105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  printf ("\n");
4115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
4125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      else
4135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
4145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  printf (" ");
4155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
4165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
4175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif /* E2DEBUG */
4185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  while (len > 0)
4195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
4205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* find the (logical) block component of our location */
4215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      logical_block = filepos >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK);
4225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      offset = filepos & (EXT2_BLOCK_SIZE (SUPERBLOCK) - 1);
4235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      map = ext2fs_block_map (logical_block);
4245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef E2DEBUG
4255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      printf ("map=%d\n", map);
4265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif /* E2DEBUG */
4275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (map < 0)
4285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	break;
4295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      size = EXT2_BLOCK_SIZE (SUPERBLOCK);
4315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      size -= offset;
4325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (size > len)
4335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	size = len;
4345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (map == 0) {
4365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        memset ((char *) buf, 0, size);
4375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      } else {
4385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        disk_read_func = disk_read_hook;
4395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        devread (map * (EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE),
4415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	         offset, size, buf);
4425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        disk_read_func = NULL;
4445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      }
4455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      buf += size;
4475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      len -= size;
4485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      filepos += size;
4495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      ret += size;
4505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
4515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (errnum)
4535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    ret = 0;
4545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  return ret;
4565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
4575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Based on:
4605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   def_blk_fops points to
4615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   blkdev_open, which calls (I think):
4625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   sys_open()
4635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   do_open()
4645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   open_namei()
4655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   dir_namei() which accesses current->fs->root
4665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     fs->root was set during original mount:
4675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     (something)... which calls (I think):
4685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     ext2_read_super()
4695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     iget()
4705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     __iget()
4715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     read_inode()
4725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     ext2_read_inode()
4735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       uses desc_per_block_bits, which is set in ext2_read_super()
4745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       also uses group descriptors loaded during ext2_read_super()
4755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   lookup()
4765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   ext2_lookup()
4775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   ext2_find_entry()
4785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   ext2_getblk()
4795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project*/
4815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic inline
4835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectint ext2_is_fast_symlink (void)
4845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
4855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int ea_blocks;
4865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  ea_blocks = INODE->i_file_acl ? EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE : 0;
4875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  return INODE->i_blocks == ea_blocks;
4885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
4895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* preconditions: ext2fs_mount already executed, therefore supblk in buffer
4915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *   known as SUPERBLOCK
4925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * returns: 0 if error, nonzero iff we were able to find the file successfully
4935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * postconditions: on a nonzero return, buffer known as INODE contains the
4945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *   inode of the file we were trying to look up
4955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * side effects: messes up GROUP_DESC buffer area
4965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
4975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectint
4985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectext2fs_dir (char *dirname)
4995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
5005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int current_ino = EXT2_ROOT_INO;	/* start at the root */
5015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int updir_ino = current_ino;	/* the parent of the current directory */
5025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int group_id;			/* which group the inode is in */
5035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int group_desc;		/* fs pointer to that group */
5045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int desc;			/* index within that group */
5055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int ino_blk;			/* fs pointer of the inode's information */
5065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int str_chk = 0;		/* used to hold the results of a string compare */
5075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  struct ext2_group_desc *gdp;
5085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  struct ext2_inode *raw_inode;	/* inode info corresponding to current_ino */
5095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  char linkbuf[PATH_MAX];	/* buffer for following symbolic links */
5115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int link_count = 0;
5125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  char *rest;
5145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  char ch;			/* temp char holder */
5155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int off;			/* offset within block of directory entry (off mod blocksize) */
5175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int loc;			/* location within a directory */
5185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int blk;			/* which data blk within dir entry (off div blocksize) */
5195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  long map;			/* fs pointer of a particular block from dir entry */
5205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  struct ext2_dir_entry *dp;	/* pointer to directory entry */
5215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef E2DEBUG
5225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  unsigned char *i;
5235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif	/* E2DEBUG */
5245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* loop invariants:
5265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     current_ino = inode to lookup
5275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     dirname = pointer to filename component we are cur looking up within
5285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     the directory known pointed to by current_ino (if any)
5295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   */
5305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  while (1)
5325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
5335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef E2DEBUG
5345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      printf ("inode %d\n", current_ino);
5355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      printf ("dirname=%s\n", dirname);
5365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif /* E2DEBUG */
5375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* look up an inode */
5395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      group_id = (current_ino - 1) / (SUPERBLOCK->s_inodes_per_group);
5405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      group_desc = group_id >> log2 (EXT2_DESC_PER_BLOCK (SUPERBLOCK));
5415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      desc = group_id & (EXT2_DESC_PER_BLOCK (SUPERBLOCK) - 1);
5425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef E2DEBUG
5435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      printf ("ipg=%d, dpb=%d\n", SUPERBLOCK->s_inodes_per_group,
5445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      EXT2_DESC_PER_BLOCK (SUPERBLOCK));
5455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      printf ("group_id=%d group_desc=%d desc=%d\n", group_id, group_desc, desc);
5465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif /* E2DEBUG */
5475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (!ext2_rdfsb (
5485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			(WHICH_SUPER + group_desc + SUPERBLOCK->s_first_data_block),
5495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			(int) GROUP_DESC))
5505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
5515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  return 0;
5525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
5535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      gdp = GROUP_DESC;
5545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      ino_blk = gdp[desc].bg_inode_table +
5555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	(((current_ino - 1) % (SUPERBLOCK->s_inodes_per_group))
5565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	 >> log2 (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)));
5575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef E2DEBUG
5585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      printf ("inode table fsblock=%d\n", ino_blk);
5595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif /* E2DEBUG */
5605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (!ext2_rdfsb (ino_blk, (int) INODE))
5615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
5625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  return 0;
5635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
5645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* reset indirect blocks! */
5665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      mapblock2 = mapblock1 = -1;
5675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      raw_inode = INODE +
5695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	((current_ino - 1)
5705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	 & (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode) - 1));
5715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef E2DEBUG
5725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      printf ("ipb=%d, sizeof(inode)=%d\n",
5735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)),
5745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      sizeof (struct ext2_inode));
5755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      printf ("inode=%x, raw_inode=%x\n", INODE, raw_inode);
5765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      printf ("offset into inode table block=%d\n", (int) raw_inode - (int) INODE);
5775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      for (i = (unsigned char *) INODE; i <= (unsigned char *) raw_inode;
5785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	   i++)
5795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
5805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  printf ("%c", "0123456789abcdef"[*i >> 4]);
5815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  printf ("%c", "0123456789abcdef"[*i % 16]);
5825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (!((i + 1 - (unsigned char *) INODE) % 16))
5835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
5845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      printf ("\n");
5855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
5865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  else
5875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
5885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      printf (" ");
5895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
5905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
5915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      printf ("first word=%x\n", *((int *) raw_inode));
5925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif /* E2DEBUG */
5935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* copy inode to fixed location */
5955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      memmove ((void *) INODE, (void *) raw_inode, sizeof (struct ext2_inode));
5965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef E2DEBUG
5985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      printf ("first word=%x\n", *((int *) INODE));
5995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif /* E2DEBUG */
6005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* If we've got a symbolic link, then chase it. */
6025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (S_ISLNK (INODE->i_mode))
6035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
6045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  int len;
6055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (++link_count > MAX_LINK_COUNT)
6065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
6075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      errnum = ERR_SYMLINK_LOOP;
6085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      return 0;
6095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
6105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* Find out how long our remaining name is. */
6125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  len = 0;
6135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  while (dirname[len] && !isspace (dirname[len]))
6145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    len++;
6155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* Get the symlink size. */
6175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  filemax = (INODE->i_size);
6185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (filemax + len > sizeof (linkbuf) - 2)
6195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
6205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      errnum = ERR_FILELENGTH;
6215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      return 0;
6225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
6235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (len)
6255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
6265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      /* Copy the remaining name to the end of the symlink data.
6275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	         Note that DIRNAME and LINKBUF may overlap! */
6285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      memmove (linkbuf + filemax, dirname, len);
6295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
6305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  linkbuf[filemax + len] = '\0';
6315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* Read the symlink data. */
6335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (! ext2_is_fast_symlink ())
6345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
6355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      /* Read the necessary blocks, and reset the file pointer. */
6365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      len = grub_read (linkbuf, filemax);
6375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      filepos = 0;
6385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (!len)
6395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		return 0;
6405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
6415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  else
6425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
6435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      /* Copy the data directly from the inode. */
6445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      len = filemax;
6455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      memmove (linkbuf, (char *) INODE->i_block, len);
6465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
6475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef E2DEBUG
6495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  printf ("symlink=%s\n", linkbuf);
6505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
6515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  dirname = linkbuf;
6535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (*dirname == '/')
6545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
6555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      /* It's an absolute link, so look it up in root. */
6565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      current_ino = EXT2_ROOT_INO;
6575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      updir_ino = current_ino;
6585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
6595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  else
6605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
6615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      /* Relative, so look it up in our parent directory. */
6625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      current_ino = updir_ino;
6635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
6645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* Try again using the new name. */
6665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  continue;
6675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
6685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* if end of filename, INODE points to the file's inode */
6705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (!*dirname || isspace (*dirname))
6715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
6725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (!S_ISREG (INODE->i_mode))
6735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
6745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      errnum = ERR_BAD_FILETYPE;
6755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      return 0;
6765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
6775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  filemax = (INODE->i_size);
6795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  return 1;
6805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
6815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* else we have to traverse a directory */
6835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      updir_ino = current_ino;
6845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* skip over slashes */
6865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      while (*dirname == '/')
6875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	dirname++;
6885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* if this isn't a directory of sufficient size to hold our file, abort */
6905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (!(INODE->i_size) || !S_ISDIR (INODE->i_mode))
6915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
6925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  errnum = ERR_BAD_FILETYPE;
6935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  return 0;
6945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
6955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* skip to next slash or end of filename (space) */
6975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/';
6985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	   rest++);
6995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* look through this directory and find the next filename component */
7015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* invariant: rest points to slash after the next filename component */
7025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      *rest = 0;
7035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      loc = 0;
7045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      do
7065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
7075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef E2DEBUG
7095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  printf ("dirname=%s, rest=%s, loc=%d\n", dirname, rest, loc);
7105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif /* E2DEBUG */
7115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* if our location/byte offset into the directory exceeds the size,
7135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	     give up */
7145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (loc >= INODE->i_size)
7155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
7165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (print_possibilities < 0)
7175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		{
7185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project# if 0
7195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  putchar ('\n');
7205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project# endif
7215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		}
7225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      else
7235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		{
7245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  errnum = ERR_FILE_NOT_FOUND;
7255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  *rest = ch;
7265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		}
7275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      return (print_possibilities < 0);
7285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
7295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* else, find the (logical) block component of our location */
7315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  blk = loc >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK);
7325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* we know which logical block of the directory entry we are looking
7345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	     for, now we have to translate that to the physical (fs) block on
7355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	     the disk */
7365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  map = ext2fs_block_map (blk);
7375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef E2DEBUG
7385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  printf ("fs block=%d\n", map);
7395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif /* E2DEBUG */
7405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  mapblock2 = -1;
7415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if ((map < 0) || !ext2_rdfsb (map, DATABLOCK2))
7425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
7435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      errnum = ERR_FSYS_CORRUPT;
7445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      *rest = ch;
7455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      return 0;
7465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
7475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  off = loc & (EXT2_BLOCK_SIZE (SUPERBLOCK) - 1);
7485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  dp = (struct ext2_dir_entry *) (DATABLOCK2 + off);
7495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* advance loc prematurely to next on-disk directory entry  */
7505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  loc += dp->rec_len;
7515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* NOTE: ext2fs filenames are NOT null-terminated */
7535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef E2DEBUG
7555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  printf ("directory entry ino=%d\n", dp->inode);
7565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (dp->inode)
7575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    printf ("entry=%s\n", dp->name);
7585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif /* E2DEBUG */
7595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (dp->inode)
7615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
7625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      int saved_c = dp->name[dp->name_len];
7635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      dp->name[dp->name_len] = 0;
7655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      str_chk = substring (dirname, dp->name);
7665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project# ifndef STAGE1_5
7685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (print_possibilities && ch != '/'
7695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  && (!*dirname || str_chk <= 0))
7705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		{
7715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  if (print_possibilities > 0)
7725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		    print_possibilities = -print_possibilities;
7735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  print_a_completion (dp->name);
7745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		}
7755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project# endif
7765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      dp->name[dp->name_len] = saved_c;
7785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
7795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
7815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      while (!dp->inode || (str_chk || (print_possibilities && ch != '/')));
7825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      current_ino = dp->inode;
7845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      *(dirname = rest) = ch;
7855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
7865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* never get here */
7875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
7885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif /* FSYS_EXT2_FS */
790