rev |
line source |
pascal@20223
|
1 --- grub-0.97/stage2/fsys_ext2fs.c
|
pascal@20223
|
2 +++ grub-0.97/stage2/fsys_ext2fs.c
|
pascal@20223
|
3 @@ -17,6 +17,19 @@
|
pascal@20223
|
4 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
pascal@20223
|
5 */
|
pascal@20223
|
6
|
pascal@20223
|
7 +/*
|
pascal@20223
|
8 + * The patch about "ext3 with 256-byte inode size" was made by
|
pascal@20223
|
9 + * Stefan Lippers-Hollmann <s.L-H@gmx.de> for Debian in 2008-01-30.
|
pascal@20223
|
10 + * Thank Barton for submittal of this patch.
|
pascal@20223
|
11 + * ---- Tinybit, 2008-06-24
|
pascal@20223
|
12 + */
|
pascal@20223
|
13 +
|
pascal@20223
|
14 +/*
|
pascal@20223
|
15 + * The ext4 patch comes from Gentoo.
|
pascal@20223
|
16 + * Thank kraml for direction to this patch.
|
pascal@20223
|
17 + * ---- Tinybit, 2009-02-11
|
pascal@20223
|
18 + */
|
pascal@20223
|
19 +
|
pascal@20223
|
20 #ifdef FSYS_EXT2FS
|
pascal@20223
|
21
|
pascal@20223
|
22 #include "shared.h"
|
pascal@20223
|
23 @@ -41,6 +54,7 @@
|
pascal@20223
|
24 typedef unsigned short __u16;
|
pascal@20223
|
25 typedef __signed__ int __s32;
|
pascal@20223
|
26 typedef unsigned int __u32;
|
pascal@20223
|
27 +typedef unsigned long long __u64;
|
pascal@20223
|
28
|
pascal@20223
|
29 /*
|
pascal@20223
|
30 * Constants relative to the data blocks, from ext2_fs.h
|
pascal@20223
|
31 @@ -61,9 +75,9 @@
|
pascal@20223
|
32 __u32 s_free_inodes_count; /* Free inodes count */
|
pascal@20223
|
33 __u32 s_first_data_block; /* First Data Block */
|
pascal@20223
|
34 __u32 s_log_block_size; /* Block size */
|
pascal@20223
|
35 - __s32 s_log_frag_size; /* Fragment size */
|
pascal@20223
|
36 + __s32 s_obso_log_frag_size; /* Obsoleted Fragment size */
|
pascal@20223
|
37 __u32 s_blocks_per_group; /* # Blocks per group */
|
pascal@20223
|
38 - __u32 s_frags_per_group; /* # Fragments per group */
|
pascal@20223
|
39 + __u32 s_obso_frags_per_group; /* Obsoleted Fragments per group */
|
pascal@20223
|
40 __u32 s_inodes_per_group; /* # Inodes per group */
|
pascal@20223
|
41 __u32 s_mtime; /* Mount time */
|
pascal@20223
|
42 __u32 s_wtime; /* Write time */
|
pascal@20224
|
43 @@ -72,17 +86,63 @@
|
pascal@20223
|
44 __u16 s_magic; /* Magic signature */
|
pascal@20223
|
45 __u16 s_state; /* File system state */
|
pascal@20223
|
46 __u16 s_errors; /* Behaviour when detecting errors */
|
pascal@20223
|
47 - __u16 s_pad;
|
pascal@20223
|
48 + __u16 s_minor_rev_level; /* minor revision level */
|
pascal@20223
|
49 __u32 s_lastcheck; /* time of last check */
|
pascal@20223
|
50 __u32 s_checkinterval; /* max. time between checks */
|
pascal@20223
|
51 __u32 s_creator_os; /* OS */
|
pascal@20223
|
52 __u32 s_rev_level; /* Revision level */
|
pascal@20223
|
53 __u16 s_def_resuid; /* Default uid for reserved blocks */
|
pascal@20223
|
54 __u16 s_def_resgid; /* Default gid for reserved blocks */
|
pascal@20224
|
55 - __u32 s_reserved[235]; /* Padding to the end of the block */
|
pascal@20223
|
56 + //__u32 s_reserved[235]; /* Padding to the end of the block */
|
pascal@20224
|
57 + /*
|
pascal@20224
|
58 + * These fields are for EXT2_DYNAMIC_REV superblocks only.
|
pascal@20224
|
59 + *
|
pascal@20224
|
60 + * Note: the difference between the compatible feature set and
|
pascal@20224
|
61 + * the incompatible feature set is that if there is a bit set
|
pascal@20224
|
62 + * in the incompatible feature set that the kernel doesn't
|
pascal@20224
|
63 + * know about, it should refuse to mount the filesystem.
|
pascal@20224
|
64 + *
|
pascal@20224
|
65 + * e2fsck's requirements are more strict; if it doesn't know
|
pascal@20224
|
66 + * about a feature in either the compatible or incompatible
|
pascal@20224
|
67 + * feature set, it must abort and not try to meddle with
|
pascal@20224
|
68 + * things it doesn't understand...
|
pascal@20224
|
69 + */
|
pascal@20224
|
70 + __u32 s_first_ino; /* First non-reserved inode */
|
pascal@20224
|
71 + __u16 s_inode_size; /* size of inode structure */
|
pascal@20224
|
72 + __u16 s_block_group_nr; /* block group # of this superblock */
|
pascal@20224
|
73 + __u32 s_feature_compat; /* compatible feature set */
|
pascal@20224
|
74 + __u32 s_feature_incompat; /* incompatible feature set */
|
pascal@20224
|
75 + __u32 s_feature_ro_compat; /* readonly-compatible feature set */
|
pascal@20223
|
76 + __u8 s_uuid[16]; /* 128-bit uuid for volume */
|
pascal@20223
|
77 + char s_volume_name[16]; /* volume name */
|
pascal@20223
|
78 + char s_last_mounted[64]; /* directory where last mounted */
|
pascal@20223
|
79 + __u32 s_algorithm_usage_bitmap; /* For compression */
|
pascal@20224
|
80 + /*
|
pascal@20223
|
81 + * Performance hints. Directory preallocation should only
|
pascal@20224
|
82 + * happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on.
|
pascal@20224
|
83 + */
|
pascal@20223
|
84 + __u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
|
pascal@20223
|
85 + __u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
|
pascal@20224
|
86 + __u16 s_reserved_gdt_blocks;/* Per group table for online growth */
|
pascal@20224
|
87 + /*
|
pascal@20224
|
88 + * Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set.
|
pascal@20224
|
89 + */
|
pascal@20224
|
90 + __u8 s_journal_uuid[16]; /* uuid of journal superblock */
|
pascal@20224
|
91 + __u32 s_journal_inum; /* inode number of journal file */
|
pascal@20224
|
92 + __u32 s_journal_dev; /* device number of journal file */
|
pascal@20224
|
93 + __u32 s_last_orphan; /* start of list of inodes to delete */
|
pascal@20224
|
94 + __u32 s_hash_seed[4]; /* HTREE hash seed */
|
pascal@20223
|
95 + __u8 s_def_hash_version; /* Default hash version to use */
|
pascal@20223
|
96 + __u8 s_jnl_backup_type; /* Default type of journal backup */
|
pascal@20223
|
97 + __u16 s_desc_size; /* size of group descriptor */
|
pascal@20224
|
98 + __u32 s_default_mount_opts;
|
pascal@20224
|
99 + __u32 s_first_meta_bg; /* First metablock group */
|
pascal@20224
|
100 + __u32 s_mkfs_time; /* When the filesystem was created */
|
pascal@20223
|
101 + __u32 s_jnl_blocks[17]; /* Backup of the journal inode */
|
pascal@20224
|
102 + __u32 s_reserved[172]; /* Padding to the end of the block */
|
pascal@20223
|
103 };
|
pascal@20223
|
104
|
pascal@20223
|
105 -struct ext2_group_desc
|
pascal@20223
|
106 +struct ext4_group_desc
|
pascal@20223
|
107 {
|
pascal@20223
|
108 __u32 bg_block_bitmap; /* Blocks bitmap block */
|
pascal@20223
|
109 __u32 bg_inode_bitmap; /* Inodes bitmap block */
|
pascal@20224
|
110 @@ -90,8 +150,18 @@
|
pascal@20223
|
111 __u16 bg_free_blocks_count; /* Free blocks count */
|
pascal@20223
|
112 __u16 bg_free_inodes_count; /* Free inodes count */
|
pascal@20223
|
113 __u16 bg_used_dirs_count; /* Directories count */
|
pascal@20223
|
114 - __u16 bg_pad;
|
pascal@20223
|
115 - __u32 bg_reserved[3];
|
pascal@20223
|
116 + __u16 bg_flags; /* EXT4_BG_flags (INODE_UNINIT, etc) */
|
pascal@20223
|
117 + __u32 bg_reserved[2]; /* Likely block/inode bitmap checksum */
|
pascal@20223
|
118 + __u16 bg_itable_unused; /* Unused inodes count */
|
pascal@20223
|
119 + __u16 bg_checksum; /* crc16(sb_uuid+group+desc) */
|
pascal@20223
|
120 + __u32 bg_block_bitmap_hi; /* Blocks bitmap block MSB */
|
pascal@20223
|
121 + __u32 bg_inode_bitmap_hi; /* Inodes bitmap block MSB */
|
pascal@20223
|
122 + __u32 bg_inode_table_hi; /* Inodes table block MSB */
|
pascal@20223
|
123 + __u16 bg_free_blocks_count_hi;/* Free blocks count MSB */
|
pascal@20223
|
124 + __u16 bg_free_inodes_count_hi;/* Free inodes count MSB */
|
pascal@20223
|
125 + __u16 bg_used_dirs_count_hi; /* Directories count MSB */
|
pascal@20223
|
126 + __u16 bg_itable_unused_hi; /* Unused inodes count MSB */
|
pascal@20223
|
127 + __u32 bg_reserved2[3];
|
pascal@20223
|
128 };
|
pascal@20223
|
129
|
pascal@20223
|
130 struct ext2_inode
|
pascal@20224
|
131 @@ -129,22 +199,22 @@
|
pascal@20223
|
132 __u32 i_block[EXT2_N_BLOCKS]; /* 40: Pointers to blocks */
|
pascal@20223
|
133 __u32 i_version; /* File version (for NFS) */
|
pascal@20223
|
134 __u32 i_file_acl; /* File ACL */
|
pascal@20223
|
135 - __u32 i_dir_acl; /* Directory ACL */
|
pascal@20223
|
136 - __u32 i_faddr; /* Fragment address */
|
pascal@20223
|
137 + __u32 i_size_high;
|
pascal@20223
|
138 + __u32 i_obso_faddr; /* Obsoleted fragment address */
|
pascal@20223
|
139 union
|
pascal@20223
|
140 {
|
pascal@20223
|
141 struct
|
pascal@20223
|
142 {
|
pascal@20223
|
143 - __u8 l_i_frag; /* Fragment number */
|
pascal@20223
|
144 - __u8 l_i_fsize; /* Fragment size */
|
pascal@20223
|
145 - __u16 i_pad1;
|
pascal@20223
|
146 - __u32 l_i_reserved2[2];
|
pascal@20223
|
147 + __u16 l_i_blocks_high; /* were l_i_reserved1 */
|
pascal@20223
|
148 + __u16 l_i_file_acl_high;
|
pascal@20223
|
149 + __u16 l_i_uid_high; /* these 2 fields */
|
pascal@20223
|
150 + __u16 l_i_gid_high; /* were reserved2[0] */
|
pascal@20223
|
151 + __u32 l_i_reserved2;
|
pascal@20223
|
152 }
|
pascal@20223
|
153 linux2;
|
pascal@20223
|
154 struct
|
pascal@20223
|
155 {
|
pascal@20223
|
156 - __u8 h_i_frag; /* Fragment number */
|
pascal@20223
|
157 - __u8 h_i_fsize; /* Fragment size */
|
pascal@20223
|
158 + __u16 h_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */
|
pascal@20223
|
159 __u16 h_i_mode_high;
|
pascal@20223
|
160 __u16 h_i_uid_high;
|
pascal@20223
|
161 __u16 h_i_gid_high;
|
pascal@20224
|
162 @@ -153,16 +223,36 @@
|
pascal@20223
|
163 hurd2;
|
pascal@20223
|
164 struct
|
pascal@20223
|
165 {
|
pascal@20223
|
166 - __u8 m_i_frag; /* Fragment number */
|
pascal@20223
|
167 - __u8 m_i_fsize; /* Fragment size */
|
pascal@20223
|
168 - __u16 m_pad1;
|
pascal@20223
|
169 + __u16 h_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */
|
pascal@20223
|
170 + __u16 m_i_file_acl_high;
|
pascal@20223
|
171 __u32 m_i_reserved2[2];
|
pascal@20223
|
172 }
|
pascal@20223
|
173 masix2;
|
pascal@20223
|
174 }
|
pascal@20223
|
175 osd2; /* OS dependent 2 */
|
pascal@20223
|
176 + __u16 i_extra_isize;
|
pascal@20223
|
177 + __u16 i_pad1;
|
pascal@20223
|
178 + __u32 i_ctime_extra; /* extra Change time (nsec << 2 | epoch) */
|
pascal@20223
|
179 + __u32 i_mtime_extra; /* extra Modification time(nsec << 2 | epoch) */
|
pascal@20223
|
180 + __u32 i_atime_extra; /* extra Access time (nsec << 2 | epoch) */
|
pascal@20223
|
181 + __u32 i_crtime; /* File Creation time */
|
pascal@20223
|
182 + __u32 i_crtime_extra; /* extra FileCreationtime (nsec << 2 | epoch) */
|
pascal@20223
|
183 + __u32 i_version_hi; /* high 32 bits for 64-bit version */
|
pascal@20223
|
184 };
|
pascal@20223
|
185
|
pascal@20223
|
186 +#define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */
|
pascal@20223
|
187 +#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080 /* grub not supported*/
|
pascal@20223
|
188 +#define EXT4_FEATURE_INCOMPAT_MMP 0x0100
|
pascal@20223
|
189 +#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200
|
pascal@20223
|
190 +
|
pascal@20223
|
191 +#define EXT4_HAS_INCOMPAT_FEATURE(sb,mask) \
|
pascal@20223
|
192 + ( sb->s_feature_incompat & mask )
|
pascal@20223
|
193 +
|
pascal@20223
|
194 +#define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */
|
pascal@20223
|
195 +#define EXT4_HUGE_FILE_FL 0x00040000 /* Set to each huge file */
|
pascal@20223
|
196 +
|
pascal@20223
|
197 +#define EXT4_MIN_DESC_SIZE 32
|
pascal@20223
|
198 +
|
pascal@20223
|
199 /* linux/limits.h */
|
pascal@20223
|
200 #define NAME_MAX 255 /* # chars in a file name */
|
pascal@20223
|
201
|
pascal@20224
|
202 @@ -180,6 +270,57 @@
|
pascal@20223
|
203 char name[EXT2_NAME_LEN]; /* File name */
|
pascal@20223
|
204 };
|
pascal@20223
|
205
|
pascal@20223
|
206 +/* linux/ext4_fs_extents.h */
|
pascal@20223
|
207 +/* This is the extent on-disk structure.
|
pascal@20223
|
208 + * It's used at the bottom of the tree.
|
pascal@20223
|
209 + */
|
pascal@20223
|
210 +struct ext4_extent
|
pascal@20223
|
211 + {
|
pascal@20223
|
212 + __u32 ee_block; /* first logical block extent covers */
|
pascal@20223
|
213 + __u16 ee_len; /* number of blocks covered by extent */
|
pascal@20223
|
214 + __u16 ee_start_hi; /* high 16 bits of physical block */
|
pascal@20223
|
215 + __u32 ee_start_lo; /* low 32 bits of physical block */
|
pascal@20223
|
216 + };
|
pascal@20223
|
217 +
|
pascal@20223
|
218 +/*
|
pascal@20223
|
219 + * This is index on-disk structure.
|
pascal@20223
|
220 + * It's used at all the levels except the bottom.
|
pascal@20223
|
221 + */
|
pascal@20223
|
222 +struct ext4_extent_idx
|
pascal@20223
|
223 + {
|
pascal@20223
|
224 + __u32 ei_block; /* index covers logical blocks from 'block' */
|
pascal@20223
|
225 + __u32 ei_leaf_lo; /* pointer to the physical block of the next *
|
pascal@20223
|
226 + * level. leaf or next index could be there */
|
pascal@20223
|
227 + __u16 ei_leaf_hi; /* high 16 bits of physical block */
|
pascal@20223
|
228 + __u16 ei_unused;
|
pascal@20223
|
229 + };
|
pascal@20223
|
230 +
|
pascal@20223
|
231 +/*
|
pascal@20223
|
232 + * Each block (leaves and indexes), even inode-stored has header.
|
pascal@20223
|
233 + */
|
pascal@20223
|
234 +struct ext4_extent_header
|
pascal@20223
|
235 + {
|
pascal@20223
|
236 + __u16 eh_magic; /* probably will support different formats */
|
pascal@20223
|
237 + __u16 eh_entries; /* number of valid entries */
|
pascal@20223
|
238 + __u16 eh_max; /* capacity of store in entries */
|
pascal@20223
|
239 + __u16 eh_depth; /* has tree real underlying blocks? */
|
pascal@20223
|
240 + __u32 eh_generation; /* generation of the tree */
|
pascal@20223
|
241 + };
|
pascal@20223
|
242 +
|
pascal@20223
|
243 +#define EXT4_EXT_MAGIC (0xf30a)
|
pascal@20223
|
244 +#define EXT_FIRST_EXTENT(__hdr__) \
|
pascal@20223
|
245 + ((struct ext4_extent *) (((char *) (__hdr__)) + \
|
pascal@20223
|
246 + sizeof(struct ext4_extent_header)))
|
pascal@20223
|
247 +#define EXT_FIRST_INDEX(__hdr__) \
|
pascal@20223
|
248 + ((struct ext4_extent_idx *) (((char *) (__hdr__)) + \
|
pascal@20223
|
249 + sizeof(struct ext4_extent_header)))
|
pascal@20223
|
250 +#define EXT_LAST_EXTENT(__hdr__) \
|
pascal@20223
|
251 + (EXT_FIRST_EXTENT((__hdr__)) + (__u16)((__hdr__)->eh_entries) - 1)
|
pascal@20223
|
252 +#define EXT_LAST_INDEX(__hdr__) \
|
pascal@20223
|
253 + (EXT_FIRST_INDEX((__hdr__)) + (__u16)((__hdr__)->eh_entries) - 1)
|
pascal@20223
|
254 +
|
pascal@20223
|
255 +
|
pascal@20223
|
256 +
|
pascal@20223
|
257 /* linux/ext2fs.h */
|
pascal@20223
|
258 /*
|
pascal@20223
|
259 * EXT2_DIR_PAD defines the directory entries boundaries
|
pascal@20224
|
260 @@ -193,7 +334,7 @@
|
pascal@20223
|
261
|
pascal@20223
|
262
|
pascal@20223
|
263 /* ext2/super.c */
|
pascal@20223
|
264 -#define log2(n) ffz(~(n))
|
pascal@20223
|
265 +//#define log2(n) ffz(~(n))
|
pascal@20223
|
266
|
pascal@20223
|
267 #define EXT2_SUPER_MAGIC 0xEF53 /* include/linux/ext2_fs.h */
|
pascal@20223
|
268 #define EXT2_ROOT_INO 2 /* include/linux/ext2_fs.h */
|
pascal@20224
|
269 @@ -202,11 +343,12 @@
|
pascal@20223
|
270
|
pascal@20223
|
271 /* made up, these are pointers into FSYS_BUF */
|
pascal@20223
|
272 /* read once, always stays there: */
|
pascal@20223
|
273 +#define NAME_BUF ((char *)(FSYS_BUF)) /* 512 bytes */
|
pascal@20223
|
274 #define SUPERBLOCK \
|
pascal@20223
|
275 - ((struct ext2_super_block *)(FSYS_BUF))
|
pascal@20223
|
276 + ((struct ext2_super_block *)((FSYS_BUF)+512)) /* 1024 bytes */
|
pascal@20223
|
277 #define GROUP_DESC \
|
pascal@20223
|
278 ((struct ext2_group_desc *) \
|
pascal@20223
|
279 - ((int)SUPERBLOCK + sizeof(struct ext2_super_block)))
|
pascal@20223
|
280 + ((int)SUPERBLOCK + sizeof(struct ext2_super_block))) /* 32 bytes */
|
pascal@20223
|
281 #define INODE \
|
pascal@20223
|
282 ((struct ext2_inode *)((int)GROUP_DESC + EXT2_BLOCK_SIZE(SUPERBLOCK)))
|
pascal@20223
|
283 #define DATABLOCK1 \
|
pascal@20224
|
284 @@ -216,15 +358,37 @@
|
pascal@20223
|
285
|
pascal@20223
|
286 /* linux/ext2_fs.h */
|
pascal@20223
|
287 #define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
|
pascal@20223
|
288 -#define EXT2_ADDR_PER_BLOCK_BITS(s) (log2(EXT2_ADDR_PER_BLOCK(s)))
|
pascal@20223
|
289 +#define EXT2_ADDR_PER_BLOCK_BITS(s) (log2_tmp(EXT2_ADDR_PER_BLOCK(s)))
|
pascal@20223
|
290
|
pascal@20223
|
291 +/* Revision levels */
|
pascal@20224
|
292 +#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */
|
pascal@20224
|
293 +#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */
|
pascal@20223
|
294 +
|
pascal@20223
|
295 +#define EXT2_CURRENT_REV EXT2_GOOD_OLD_REV
|
pascal@20223
|
296 +#define EXT2_MAX_SUPP_REV EXT2_DYNAMIC_REV
|
pascal@20223
|
297 +
|
pascal@20223
|
298 +#define EXT2_GOOD_OLD_INODE_SIZE 128
|
pascal@20223
|
299 +
|
pascal@20223
|
300 +#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? EXT2_GOOD_OLD_INODE_SIZE : (s)->s_inode_size)
|
pascal@20223
|
301 +//#define EXT2_INODE_SIZE(s) (SUPERBLOCK->s_inode_size)
|
pascal@20224
|
302 +#define EXT2_INODES_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s)/EXT2_INODE_SIZE(s))
|
pascal@20224
|
303 +
|
pascal@20223
|
304 /* linux/ext2_fs.h */
|
pascal@20224
|
305 #define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
|
pascal@20223
|
306 /* kind of from ext2/super.c */
|
pascal@20223
|
307 #define EXT2_BLOCK_SIZE(s) (1 << EXT2_BLOCK_SIZE_BITS(s))
|
pascal@20223
|
308 /* linux/ext2fs.h */
|
pascal@20223
|
309 +/* sizeof(struct ext2_group_desc) is changed in ext4
|
pascal@20223
|
310 + * in kernel code, ext2/3 uses sizeof(struct ext2_group_desc) to calculate
|
pascal@20223
|
311 + * number of desc per block, while ext4 uses superblock->s_desc_size in stead
|
pascal@20223
|
312 + * superblock->s_desc_size is not available in ext2/3
|
pascal@20223
|
313 + * */
|
pascal@20223
|
314 +#define EXT2_DESC_SIZE(s) \
|
pascal@20223
|
315 + (EXT4_HAS_INCOMPAT_FEATURE(s,EXT4_FEATURE_INCOMPAT_64BIT)? \
|
pascal@20223
|
316 + s->s_desc_size : EXT4_MIN_DESC_SIZE)
|
pascal@20223
|
317 #define EXT2_DESC_PER_BLOCK(s) \
|
pascal@20223
|
318 - (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
|
pascal@20223
|
319 + (EXT2_BLOCK_SIZE(s) / EXT2_DESC_SIZE(s))
|
pascal@20223
|
320 +
|
pascal@20223
|
321 /* linux/stat.h */
|
pascal@20223
|
322 #define S_IFMT 00170000
|
pascal@20223
|
323 #define S_IFLNK 0120000
|
pascal@20224
|
324 @@ -234,38 +398,82 @@
|
pascal@20223
|
325 #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
|
pascal@20223
|
326 #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
pascal@20223
|
327
|
pascal@20223
|
328 +#ifndef GRUB_UTIL
|
pascal@20223
|
329 +static char *linkbuf = (char *)(FSYS_BUF - PATH_MAX); /* buffer for following symbolic links */
|
pascal@20223
|
330 +#else
|
pascal@20223
|
331 +static char linkbuf[PATH_MAX]; /* buffer for following symbolic links */
|
pascal@20223
|
332 +#endif
|
pascal@20223
|
333 +
|
pascal@20223
|
334 /* include/asm-i386/bitops.h */
|
pascal@20223
|
335 /*
|
pascal@20223
|
336 * ffz = Find First Zero in word. Undefined if no zero exists,
|
pascal@20223
|
337 * so code should check against ~0UL first..
|
pascal@20223
|
338 */
|
pascal@20223
|
339 -static __inline__ unsigned long
|
pascal@20223
|
340 -ffz (unsigned long word)
|
pascal@20223
|
341 -{
|
pascal@20223
|
342 - __asm__ ("bsfl %1,%0"
|
pascal@20223
|
343 -: "=r" (word)
|
pascal@20223
|
344 -: "r" (~word));
|
pascal@20223
|
345 - return word;
|
pascal@20223
|
346 -}
|
pascal@20223
|
347 +//static __inline__ unsigned long
|
pascal@20223
|
348 +//ffz (unsigned long word)
|
pascal@20223
|
349 +//{
|
pascal@20223
|
350 +// __asm__ ("bsfl %1,%0"
|
pascal@20223
|
351 +//: "=r" (word)
|
pascal@20223
|
352 +//: "r" (~word));
|
pascal@20223
|
353 +// return word;
|
pascal@20223
|
354 +//}
|
pascal@20223
|
355
|
pascal@20223
|
356 /* check filesystem types and read superblock into memory buffer */
|
pascal@20223
|
357 int
|
pascal@20223
|
358 ext2fs_mount (void)
|
pascal@20223
|
359 {
|
pascal@20223
|
360 - int retval = 1;
|
pascal@20223
|
361 +// if (((current_drive & 0x80) || (current_slice != 0))
|
pascal@20223
|
362 +// && (current_slice != PC_SLICE_TYPE_EXT2FS)
|
pascal@20223
|
363 +// && (current_slice != PC_SLICE_TYPE_LINUX_RAID)
|
pascal@20223
|
364 +// && (! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_EXT2FS))
|
pascal@20223
|
365 +// && (! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_OTHER)))
|
pascal@20223
|
366 +// return 0;
|
pascal@20223
|
367 +
|
pascal@20223
|
368 + if ((unsigned long)part_length < (SBLOCK + (sizeof(struct ext2_super_block) / DEV_BSIZE)))
|
pascal@20223
|
369 + return 0;
|
pascal@20223
|
370
|
pascal@20223
|
371 - if ((((current_drive & 0x80) || (current_slice != 0))
|
pascal@20223
|
372 - && (current_slice != PC_SLICE_TYPE_EXT2FS)
|
pascal@20223
|
373 - && (current_slice != PC_SLICE_TYPE_LINUX_RAID)
|
pascal@20223
|
374 - && (! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_EXT2FS))
|
pascal@20223
|
375 - && (! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_OTHER)))
|
pascal@20223
|
376 - || part_length < (SBLOCK + (sizeof (struct ext2_super_block) / DEV_BSIZE))
|
pascal@20223
|
377 - || !devread (SBLOCK, 0, sizeof (struct ext2_super_block),
|
pascal@20223
|
378 - (char *) SUPERBLOCK)
|
pascal@20223
|
379 - || SUPERBLOCK->s_magic != EXT2_SUPER_MAGIC)
|
pascal@20223
|
380 - retval = 0;
|
pascal@20225
|
381 + if (!devread(SBLOCK, 0, sizeof(struct ext2_super_block), (char *)SUPERBLOCK))
|
pascal@20223
|
382 + return 0;
|
pascal@20223
|
383
|
pascal@20223
|
384 - return retval;
|
pascal@20223
|
385 + if (SUPERBLOCK->s_magic != EXT2_SUPER_MAGIC)
|
pascal@20223
|
386 + return 0;
|
pascal@20223
|
387 +
|
pascal@20223
|
388 + if (SUPERBLOCK->s_inodes_count == 0)
|
pascal@20223
|
389 + return 0;
|
pascal@20223
|
390 +
|
pascal@20223
|
391 + if (SUPERBLOCK->s_blocks_count == 0)
|
pascal@20223
|
392 + return 0;
|
pascal@20223
|
393 +
|
pascal@20223
|
394 + if (SUPERBLOCK->s_blocks_per_group == 0)
|
pascal@20223
|
395 + return 0;
|
pascal@20223
|
396 +
|
pascal@20223
|
397 + if (SUPERBLOCK->s_inodes_per_group == 0)
|
pascal@20223
|
398 + return 0;
|
pascal@20223
|
399 +
|
pascal@20223
|
400 + if (SUPERBLOCK->s_first_data_block > 1) /* 1 for 1K block, 0 otherwise */
|
pascal@20223
|
401 + return 0;
|
pascal@20223
|
402 +
|
pascal@20223
|
403 + if (SUPERBLOCK->s_log_block_size > 4) /* max size of block is 16K. 0 for 1K */
|
pascal@20223
|
404 + return 0;
|
pascal@20223
|
405 +
|
pascal@20223
|
406 + if (SUPERBLOCK->s_first_data_block)
|
pascal@20223
|
407 + {
|
pascal@20223
|
408 + if (SUPERBLOCK->s_log_block_size)
|
pascal@20223
|
409 + return 0;
|
pascal@20223
|
410 + } else {
|
pascal@20223
|
411 + if (SUPERBLOCK->s_log_block_size == 0)
|
pascal@20223
|
412 + return 0;
|
pascal@20223
|
413 + }
|
pascal@20223
|
414 +
|
pascal@20223
|
415 + if (SUPERBLOCK->s_rev_level)
|
pascal@20223
|
416 + {
|
pascal@20223
|
417 + if (SUPERBLOCK->s_inode_size == 0)
|
pascal@20223
|
418 + return 0;
|
pascal@20223
|
419 + if (EXT2_BLOCK_SIZE(SUPERBLOCK) % (SUPERBLOCK->s_inode_size))
|
pascal@20223
|
420 + return 0;
|
pascal@20223
|
421 + }
|
pascal@20223
|
422 +
|
pascal@20223
|
423 + return 1;
|
pascal@20223
|
424 }
|
pascal@20223
|
425
|
pascal@20223
|
426 /* Takes a file system block number and reads it into BUFFER. */
|
pascal@20224
|
427 @@ -285,7 +493,7 @@
|
pascal@20223
|
428 /* Maps LOGICAL_BLOCK (the file offset divided by the blocksize) into
|
pascal@20223
|
429 a physical block (the location in the file system) via an inode. */
|
pascal@20223
|
430 static int
|
pascal@20223
|
431 -ext2fs_block_map (int logical_block)
|
pascal@20223
|
432 +ext2fs_block_map (unsigned long logical_block)
|
pascal@20223
|
433 {
|
pascal@20223
|
434
|
pascal@20223
|
435 #ifdef E2DEBUG
|
pascal@20224
|
436 @@ -359,13 +567,16 @@
|
pascal@20223
|
437 /* else */
|
pascal@20223
|
438 mapblock2 = -1;
|
pascal@20223
|
439 logical_block -= (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2));
|
pascal@20223
|
440 +
|
pascal@20223
|
441 if (mapblock1 != 3
|
pascal@20223
|
442 && !ext2_rdfsb (INODE->i_block[EXT2_TIND_BLOCK], DATABLOCK1))
|
pascal@20223
|
443 {
|
pascal@20223
|
444 errnum = ERR_FSYS_CORRUPT;
|
pascal@20223
|
445 return -1;
|
pascal@20223
|
446 }
|
pascal@20223
|
447 +
|
pascal@20223
|
448 mapblock1 = 3;
|
pascal@20223
|
449 +
|
pascal@20223
|
450 if (!ext2_rdfsb (((__u32 *) DATABLOCK1)
|
pascal@20223
|
451 [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)
|
pascal@20223
|
452 * 2)],
|
pascal@20224
|
453 @@ -374,7 +585,8 @@
|
pascal@20223
|
454 errnum = ERR_FSYS_CORRUPT;
|
pascal@20223
|
455 return -1;
|
pascal@20223
|
456 }
|
pascal@20223
|
457 - if (!ext2_rdfsb (((__u32 *) DATABLOCK2)
|
pascal@20223
|
458 +
|
pascal@20223
|
459 + if (! ext2_rdfsb (((__u32 *) DATABLOCK2)
|
pascal@20223
|
460 [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK))
|
pascal@20223
|
461 & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)],
|
pascal@20223
|
462 DATABLOCK2))
|
pascal@20224
|
463 @@ -382,30 +594,148 @@
|
pascal@20223
|
464 errnum = ERR_FSYS_CORRUPT;
|
pascal@20223
|
465 return -1;
|
pascal@20223
|
466 }
|
pascal@20223
|
467 - return ((__u32 *) DATABLOCK2)
|
pascal@20223
|
468 - [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
|
pascal@20223
|
469 +
|
pascal@20223
|
470 + return ((__u32 *) DATABLOCK2)[logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
|
pascal@20223
|
471 }
|
pascal@20223
|
472
|
pascal@20223
|
473 +/* extent binary search index
|
pascal@20223
|
474 + * find closest index in the current level extent tree
|
pascal@20223
|
475 + * kind of from ext4_ext_binsearch_idx in ext4/extents.c
|
pascal@20223
|
476 + */
|
pascal@20223
|
477 +static struct ext4_extent_idx*
|
pascal@20223
|
478 +ext4_ext_binsearch_idx(struct ext4_extent_header* eh, int logical_block)
|
pascal@20223
|
479 +{
|
pascal@20223
|
480 + struct ext4_extent_idx *r, *l, *m;
|
pascal@20223
|
481 + l = EXT_FIRST_INDEX(eh) + 1;
|
pascal@20223
|
482 + r = EXT_LAST_INDEX(eh);
|
pascal@20223
|
483 + while (l <= r)
|
pascal@20223
|
484 + {
|
pascal@20223
|
485 + m = l + (r - l) / 2;
|
pascal@20223
|
486 + if (logical_block < m->ei_block)
|
pascal@20223
|
487 + r = m - 1;
|
pascal@20223
|
488 + else
|
pascal@20223
|
489 + l = m + 1;
|
pascal@20223
|
490 + }
|
pascal@20223
|
491 + return (struct ext4_extent_idx*)(l - 1);
|
pascal@20223
|
492 +}
|
pascal@20223
|
493 +
|
pascal@20223
|
494 +/* extent binary search
|
pascal@20223
|
495 + * find closest extent in the leaf level
|
pascal@20223
|
496 + * kind of from ext4_ext_binsearch in ext4/extents.c
|
pascal@20223
|
497 + */
|
pascal@20223
|
498 +static struct ext4_extent*
|
pascal@20223
|
499 +ext4_ext_binsearch(struct ext4_extent_header* eh, int logical_block)
|
pascal@20223
|
500 +{
|
pascal@20223
|
501 + struct ext4_extent *r, *l, *m;
|
pascal@20223
|
502 + l = EXT_FIRST_EXTENT(eh) + 1;
|
pascal@20223
|
503 + r = EXT_LAST_EXTENT(eh);
|
pascal@20223
|
504 + while (l <= r)
|
pascal@20223
|
505 + {
|
pascal@20223
|
506 + m = l + (r - l) / 2;
|
pascal@20223
|
507 + if (logical_block < m->ee_block)
|
pascal@20223
|
508 + r = m - 1;
|
pascal@20223
|
509 + else
|
pascal@20223
|
510 + l = m + 1;
|
pascal@20223
|
511 + }
|
pascal@20223
|
512 + return (struct ext4_extent*)(l - 1);
|
pascal@20223
|
513 +}
|
pascal@20223
|
514 +
|
pascal@20223
|
515 +/* Maps extents enabled logical block into physical block via an inode.
|
pascal@20223
|
516 + * EXT4_HUGE_FILE_FL should be checked before calling this.
|
pascal@20223
|
517 + */
|
pascal@20223
|
518 +static int
|
pascal@20223
|
519 +ext4fs_block_map (int logical_block)
|
pascal@20223
|
520 +{
|
pascal@20223
|
521 + struct ext4_extent_header *eh;
|
pascal@20223
|
522 + struct ext4_extent *ex;//, *extent;
|
pascal@20223
|
523 + struct ext4_extent_idx *ei;//, *index;
|
pascal@20223
|
524 + int depth;
|
pascal@20223
|
525 + //int i;
|
pascal@20223
|
526 +
|
pascal@20223
|
527 +#ifdef E2DEBUG
|
pascal@20223
|
528 + unsigned char *i;
|
pascal@20223
|
529 + for (i = (unsigned char *) INODE;
|
pascal@20223
|
530 + i < ((unsigned char *) INODE + sizeof (struct ext2_inode));
|
pascal@20223
|
531 + i++)
|
pascal@20223
|
532 + {
|
pascal@20223
|
533 + printf ("%c", "0123456789abcdef"[*i >> 4]);
|
pascal@20223
|
534 + printf ("%c", "0123456789abcdef"[*i % 16]);
|
pascal@20223
|
535 + if (!((i + 1 - (unsigned char *) INODE) % 16))
|
pascal@20223
|
536 + {
|
pascal@20223
|
537 + printf ("\n");
|
pascal@20223
|
538 + }
|
pascal@20223
|
539 + else
|
pascal@20223
|
540 + {
|
pascal@20223
|
541 + printf (" ");
|
pascal@20223
|
542 + }
|
pascal@20223
|
543 + }
|
pascal@20223
|
544 + printf ("logical block %d\n", logical_block);
|
pascal@20223
|
545 +#endif /* E2DEBUG */
|
pascal@20223
|
546 + eh = (struct ext4_extent_header*)INODE->i_block;
|
pascal@20223
|
547 + if (eh->eh_magic != EXT4_EXT_MAGIC)
|
pascal@20223
|
548 + {
|
pascal@20223
|
549 + errnum = ERR_FSYS_CORRUPT;
|
pascal@20223
|
550 + return -1;
|
pascal@20223
|
551 + }
|
pascal@20223
|
552 + while((depth = eh->eh_depth) != 0)
|
pascal@20223
|
553 + { /* extent index */
|
pascal@20223
|
554 + if (eh->eh_magic != EXT4_EXT_MAGIC)
|
pascal@20223
|
555 + {
|
pascal@20223
|
556 + errnum = ERR_FSYS_CORRUPT;
|
pascal@20223
|
557 + return -1;
|
pascal@20223
|
558 + }
|
pascal@20223
|
559 + ei = ext4_ext_binsearch_idx(eh, logical_block);
|
pascal@20223
|
560 + if (ei->ei_leaf_hi)
|
pascal@20223
|
561 + {/* 64bit physical block number not supported */
|
pascal@20223
|
562 + errnum = ERR_FILELENGTH;
|
pascal@20223
|
563 + return -1;
|
pascal@20223
|
564 + }
|
pascal@20223
|
565 + if (!ext2_rdfsb(ei->ei_leaf_lo, DATABLOCK1))
|
pascal@20223
|
566 + {
|
pascal@20223
|
567 + errnum = ERR_FSYS_CORRUPT;
|
pascal@20223
|
568 + return -1;
|
pascal@20223
|
569 + }
|
pascal@20223
|
570 + eh = (struct ext4_extent_header*)DATABLOCK1;
|
pascal@20223
|
571 + }
|
pascal@20223
|
572 +
|
pascal@20223
|
573 + /* depth==0, we come to the leaf */
|
pascal@20223
|
574 + ex = ext4_ext_binsearch(eh, logical_block);
|
pascal@20223
|
575 + if (ex->ee_start_hi)
|
pascal@20223
|
576 + {/* 64bit physical block number not supported */
|
pascal@20223
|
577 + errnum = ERR_FILELENGTH;
|
pascal@20223
|
578 + return -1;
|
pascal@20223
|
579 + }
|
pascal@20223
|
580 + if ((ex->ee_block + ex->ee_len) < logical_block)
|
pascal@20223
|
581 + {
|
pascal@20223
|
582 + errnum = ERR_FSYS_CORRUPT;
|
pascal@20223
|
583 + return -1;
|
pascal@20223
|
584 + }
|
pascal@20223
|
585 + return ex->ee_start_lo + logical_block - ex->ee_block;
|
pascal@20223
|
586 +
|
pascal@20223
|
587 +}
|
pascal@20223
|
588 +
|
pascal@20223
|
589 /* preconditions: all preconds of ext2fs_block_map */
|
pascal@20225
|
590 int
|
pascal@20225
|
591 ext2fs_read (char *buf, int len)
|
pascal@20223
|
592 {
|
pascal@20223
|
593 - int logical_block;
|
pascal@20223
|
594 - int offset;
|
pascal@20223
|
595 + unsigned long logical_block;
|
pascal@20223
|
596 + unsigned long offset;
|
pascal@20223
|
597 + unsigned long ret = 0;
|
pascal@20223
|
598 + unsigned long size = 0;
|
pascal@20223
|
599 int map;
|
pascal@20223
|
600 - int ret = 0;
|
pascal@20223
|
601 - int size = 0;
|
pascal@20223
|
602
|
pascal@20223
|
603 #ifdef E2DEBUG
|
pascal@20223
|
604 static char hexdigit[] = "0123456789abcdef";
|
pascal@20223
|
605 unsigned char *i;
|
pascal@20223
|
606 +
|
pascal@20223
|
607 for (i = (unsigned char *) INODE;
|
pascal@20223
|
608 i < ((unsigned char *) INODE + sizeof (struct ext2_inode));
|
pascal@20223
|
609 i++)
|
pascal@20223
|
610 {
|
pascal@20223
|
611 printf ("%c", hexdigit[*i >> 4]);
|
pascal@20223
|
612 printf ("%c", hexdigit[*i % 16]);
|
pascal@20223
|
613 - if (!((i + 1 - (unsigned char *) INODE) % 16))
|
pascal@20223
|
614 +
|
pascal@20223
|
615 + if (! ((i + 1 - (unsigned char *) INODE) % 16))
|
pascal@20223
|
616 {
|
pascal@20223
|
617 printf ("\n");
|
pascal@20223
|
618 }
|
pascal@20224
|
619 @@ -416,41 +746,53 @@
|
pascal@20223
|
620 }
|
pascal@20223
|
621 #endif /* E2DEBUG */
|
pascal@20223
|
622 while (len > 0)
|
pascal@20223
|
623 - {
|
pascal@20223
|
624 + {
|
pascal@20223
|
625 /* find the (logical) block component of our location */
|
pascal@20223
|
626 logical_block = filepos >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK);
|
pascal@20223
|
627 offset = filepos & (EXT2_BLOCK_SIZE (SUPERBLOCK) - 1);
|
pascal@20223
|
628 +
|
pascal@20223
|
629 + /* map extents enabled logical block number to physical fs on-dick block number */
|
pascal@20223
|
630 + if (EXT4_HAS_INCOMPAT_FEATURE(SUPERBLOCK,EXT4_FEATURE_INCOMPAT_EXTENTS)
|
pascal@20223
|
631 + && INODE->i_flags & EXT4_EXTENTS_FL)
|
pascal@20223
|
632 + map = ext4fs_block_map (logical_block);
|
pascal@20223
|
633 + else
|
pascal@20223
|
634 map = ext2fs_block_map (logical_block);
|
pascal@20223
|
635 +
|
pascal@20223
|
636 #ifdef E2DEBUG
|
pascal@20223
|
637 printf ("map=%d\n", map);
|
pascal@20223
|
638 #endif /* E2DEBUG */
|
pascal@20223
|
639 +
|
pascal@20223
|
640 if (map < 0)
|
pascal@20223
|
641 - break;
|
pascal@20223
|
642 + break;
|
pascal@20223
|
643
|
pascal@20223
|
644 size = EXT2_BLOCK_SIZE (SUPERBLOCK);
|
pascal@20223
|
645 size -= offset;
|
pascal@20223
|
646 +
|
pascal@20223
|
647 if (size > len)
|
pascal@20223
|
648 - size = len;
|
pascal@20223
|
649 + size = len;
|
pascal@20223
|
650
|
pascal@20223
|
651 - if (map == 0) {
|
pascal@20223
|
652 - memset ((char *) buf, 0, size);
|
pascal@20223
|
653 + if (map == 0)
|
pascal@20223
|
654 + {
|
pascal@20223
|
655 + if (buf)
|
pascal@20223
|
656 + memset ((char *) buf, 0, size);
|
pascal@20223
|
657 } else {
|
pascal@20223
|
658 - disk_read_func = disk_read_hook;
|
pascal@20223
|
659 + disk_read_func = disk_read_hook;
|
pascal@20223
|
660
|
pascal@20223
|
661 - devread (map * (EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE),
|
pascal@20223
|
662 - offset, size, buf);
|
pascal@20223
|
663 + devread (map * (EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE),
|
pascal@20225
|
664 + offset, size, buf);
|
pascal@20223
|
665
|
pascal@20223
|
666 - disk_read_func = NULL;
|
pascal@20223
|
667 + disk_read_func = NULL;
|
pascal@20223
|
668 }
|
pascal@20223
|
669
|
pascal@20223
|
670 - buf += size;
|
pascal@20223
|
671 - len -= size;
|
pascal@20223
|
672 + if (buf)
|
pascal@20223
|
673 + buf += size;
|
pascal@20223
|
674 + len -= size; /* len always >= 0 */
|
pascal@20223
|
675 filepos += size;
|
pascal@20223
|
676 ret += size;
|
pascal@20223
|
677 - }
|
pascal@20223
|
678 + }
|
pascal@20223
|
679
|
pascal@20223
|
680 if (errnum)
|
pascal@20223
|
681 - ret = 0;
|
pascal@20223
|
682 + ret = 0;
|
pascal@20223
|
683
|
pascal@20223
|
684 return ret;
|
pascal@20223
|
685 }
|
pascal@20224
|
686 @@ -504,10 +846,10 @@
|
pascal@20223
|
687 int desc; /* index within that group */
|
pascal@20223
|
688 int ino_blk; /* fs pointer of the inode's information */
|
pascal@20223
|
689 int str_chk = 0; /* used to hold the results of a string compare */
|
pascal@20223
|
690 - struct ext2_group_desc *gdp;
|
pascal@20223
|
691 + struct ext4_group_desc *ext4_gdp;
|
pascal@20223
|
692 struct ext2_inode *raw_inode; /* inode info corresponding to current_ino */
|
pascal@20223
|
693
|
pascal@20223
|
694 - char linkbuf[PATH_MAX]; /* buffer for following symbolic links */
|
pascal@20223
|
695 +//char linkbuf[PATH_MAX]; /* buffer for following symbolic links */
|
pascal@20223
|
696 int link_count = 0;
|
pascal@20223
|
697
|
pascal@20223
|
698 char *rest;
|
pascal@20224
|
699 @@ -537,7 +879,7 @@
|
pascal@20223
|
700
|
pascal@20223
|
701 /* look up an inode */
|
pascal@20223
|
702 group_id = (current_ino - 1) / (SUPERBLOCK->s_inodes_per_group);
|
pascal@20223
|
703 - group_desc = group_id >> log2 (EXT2_DESC_PER_BLOCK (SUPERBLOCK));
|
pascal@20223
|
704 + group_desc = group_id >> log2_tmp (EXT2_DESC_PER_BLOCK (SUPERBLOCK));
|
pascal@20223
|
705 desc = group_id & (EXT2_DESC_PER_BLOCK (SUPERBLOCK) - 1);
|
pascal@20223
|
706 #ifdef E2DEBUG
|
pascal@20223
|
707 printf ("ipg=%d, dpb=%d\n", SUPERBLOCK->s_inodes_per_group,
|
pascal@20224
|
708 @@ -550,10 +892,17 @@
|
pascal@20223
|
709 {
|
pascal@20223
|
710 return 0;
|
pascal@20223
|
711 }
|
pascal@20223
|
712 - gdp = GROUP_DESC;
|
pascal@20223
|
713 - ino_blk = gdp[desc].bg_inode_table +
|
pascal@20223
|
714 + ext4_gdp = (struct ext4_group_desc *)( (__u8*)GROUP_DESC +
|
pascal@20223
|
715 + desc * EXT2_DESC_SIZE(SUPERBLOCK));
|
pascal@20223
|
716 + if (EXT4_HAS_INCOMPAT_FEATURE(SUPERBLOCK, EXT4_FEATURE_INCOMPAT_64BIT)
|
pascal@20223
|
717 + && (! ext4_gdp->bg_inode_table_hi))
|
pascal@20223
|
718 + {/* 64bit itable not supported */
|
pascal@20223
|
719 + errnum = ERR_FILELENGTH;
|
pascal@20223
|
720 + return -1;
|
pascal@20223
|
721 + }
|
pascal@20223
|
722 + ino_blk = ext4_gdp->bg_inode_table +
|
pascal@20223
|
723 (((current_ino - 1) % (SUPERBLOCK->s_inodes_per_group))
|
pascal@20224
|
724 - >> log2 (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)));
|
pascal@20223
|
725 + >> log2_tmp (EXT2_INODES_PER_BLOCK (SUPERBLOCK)));
|
pascal@20223
|
726 #ifdef E2DEBUG
|
pascal@20223
|
727 printf ("inode table fsblock=%d\n", ino_blk);
|
pascal@20223
|
728 #endif /* E2DEBUG */
|
pascal@20224
|
729 @@ -565,13 +914,12 @@
|
pascal@20224
|
730 /* reset indirect blocks! */
|
pascal@20224
|
731 mapblock2 = mapblock1 = -1;
|
pascal@20223
|
732
|
pascal@20224
|
733 - raw_inode = INODE +
|
pascal@20224
|
734 - ((current_ino - 1)
|
pascal@20224
|
735 - & (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode) - 1));
|
pascal@20224
|
736 + raw_inode = (struct ext2_inode *)((char *)INODE +
|
pascal@20224
|
737 + ((current_ino - 1) & (EXT2_INODES_PER_BLOCK (SUPERBLOCK) - 1)) *
|
pascal@20223
|
738 + EXT2_INODE_SIZE (SUPERBLOCK));
|
pascal@20223
|
739 #ifdef E2DEBUG
|
pascal@20223
|
740 printf ("ipb=%d, sizeof(inode)=%d\n",
|
pascal@20224
|
741 - (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)),
|
pascal@20224
|
742 - sizeof (struct ext2_inode));
|
pascal@20223
|
743 + EXT2_INODES_PER_BLOCK (SUPERBLOCK), EXT2_INODE_SIZE (SUPERBLOCK));
|
pascal@20223
|
744 printf ("inode=%x, raw_inode=%x\n", INODE, raw_inode);
|
pascal@20223
|
745 printf ("offset into inode table block=%d\n", (int) raw_inode - (int) INODE);
|
pascal@20223
|
746 for (i = (unsigned char *) INODE; i <= (unsigned char *) raw_inode;
|
pascal@20224
|
747 @@ -609,13 +957,22 @@
|
pascal@20223
|
748 }
|
pascal@20223
|
749
|
pascal@20223
|
750 /* Find out how long our remaining name is. */
|
pascal@20223
|
751 - len = 0;
|
pascal@20223
|
752 - while (dirname[len] && !isspace (dirname[len]))
|
pascal@20223
|
753 - len++;
|
pascal@20223
|
754 + //len = 0;
|
pascal@20223
|
755 + //while (dirname[len] && !isspace (dirname[len]))
|
pascal@20223
|
756 + // len++;
|
pascal@20223
|
757 + for (len = 0; (ch = dirname[len]) && !isspace (ch); len++)
|
pascal@20223
|
758 + {
|
pascal@20223
|
759 + if (ch == '\\')
|
pascal@20223
|
760 + {
|
pascal@20223
|
761 + len++;
|
pascal@20223
|
762 + if (! (ch = dirname[len]))
|
pascal@20223
|
763 + break;
|
pascal@20223
|
764 + }
|
pascal@20223
|
765 + }
|
pascal@20223
|
766
|
pascal@20223
|
767 /* Get the symlink size. */
|
pascal@20223
|
768 filemax = (INODE->i_size);
|
pascal@20223
|
769 - if (filemax + len > sizeof (linkbuf) - 2)
|
pascal@20223
|
770 + if (filemax + len > PATH_MAX - 2)
|
pascal@20223
|
771 {
|
pascal@20223
|
772 errnum = ERR_FILELENGTH;
|
pascal@20223
|
773 return 0;
|
pascal@20224
|
774 @@ -629,18 +986,23 @@
|
pascal@20223
|
775 }
|
pascal@20223
|
776 linkbuf[filemax + len] = '\0';
|
pascal@20223
|
777
|
pascal@20223
|
778 - /* Read the symlink data. */
|
pascal@20223
|
779 + /* Read the symlink data.
|
pascal@20223
|
780 + * Slow symlink is extents enabled
|
pascal@20223
|
781 + * But since grub_read invokes ext2fs_read, nothing to change here
|
pascal@20223
|
782 + * */
|
pascal@20223
|
783 if (! ext2_is_fast_symlink ())
|
pascal@20223
|
784 {
|
pascal@20223
|
785 /* Read the necessary blocks, and reset the file pointer. */
|
pascal@20223
|
786 - len = grub_read (linkbuf, filemax);
|
pascal@20226
|
787 + len = grub_read (linkbuf, filemax);
|
pascal@20223
|
788 filepos = 0;
|
pascal@20223
|
789 if (!len)
|
pascal@20223
|
790 return 0;
|
pascal@20223
|
791 }
|
pascal@20223
|
792 else
|
pascal@20223
|
793 {
|
pascal@20223
|
794 - /* Copy the data directly from the inode. */
|
pascal@20223
|
795 + /* Copy the data directly from the inode.
|
pascal@20223
|
796 + * Fast symlink is not extents enabled
|
pascal@20223
|
797 + * */
|
pascal@20223
|
798 len = filemax;
|
pascal@20223
|
799 memmove (linkbuf, (char *) INODE->i_block, len);
|
pascal@20223
|
800 }
|
pascal@20224
|
801 @@ -674,6 +1036,13 @@
|
pascal@20223
|
802 errnum = ERR_BAD_FILETYPE;
|
pascal@20223
|
803 return 0;
|
pascal@20223
|
804 }
|
pascal@20223
|
805 + /* if file is too large, just stop and report an error*/
|
pascal@20223
|
806 + if ( (INODE->i_flags & EXT4_HUGE_FILE_FL) && !(INODE->i_size_high))
|
pascal@20223
|
807 + {
|
pascal@20223
|
808 + /* file too large, stop reading */
|
pascal@20223
|
809 + errnum = ERR_FILELENGTH;
|
pascal@20223
|
810 + return 0;
|
pascal@20223
|
811 + }
|
pascal@20223
|
812
|
pascal@20223
|
813 filemax = (INODE->i_size);
|
pascal@20223
|
814 return 1;
|
pascal@20224
|
815 @@ -694,8 +1063,17 @@
|
pascal@20223
|
816 }
|
pascal@20223
|
817
|
pascal@20223
|
818 /* skip to next slash or end of filename (space) */
|
pascal@20223
|
819 - for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/';
|
pascal@20223
|
820 - rest++);
|
pascal@20223
|
821 +// for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/';
|
pascal@20223
|
822 +// rest++);
|
pascal@20223
|
823 + for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++)
|
pascal@20223
|
824 + {
|
pascal@20223
|
825 + if (ch == '\\')
|
pascal@20223
|
826 + {
|
pascal@20223
|
827 + rest++;
|
pascal@20223
|
828 + if (! (ch = *rest))
|
pascal@20223
|
829 + break;
|
pascal@20223
|
830 + }
|
pascal@20223
|
831 + }
|
pascal@20223
|
832
|
pascal@20223
|
833 /* look through this directory and find the next filename component */
|
pascal@20223
|
834 /* invariant: rest points to slash after the next filename component */
|
pascal@20224
|
835 @@ -713,32 +1091,45 @@
|
pascal@20223
|
836 give up */
|
pascal@20223
|
837 if (loc >= INODE->i_size)
|
pascal@20223
|
838 {
|
pascal@20223
|
839 +# ifndef STAGE1_5
|
pascal@20223
|
840 if (print_possibilities < 0)
|
pascal@20223
|
841 {
|
pascal@20223
|
842 # if 0
|
pascal@20223
|
843 putchar ('\n');
|
pascal@20223
|
844 # endif
|
pascal@20223
|
845 + return 1;
|
pascal@20223
|
846 }
|
pascal@20223
|
847 - else
|
pascal@20223
|
848 - {
|
pascal@20223
|
849 - errnum = ERR_FILE_NOT_FOUND;
|
pascal@20223
|
850 - *rest = ch;
|
pascal@20223
|
851 - }
|
pascal@20223
|
852 - return (print_possibilities < 0);
|
pascal@20223
|
853 +# endif /* STAGE1_5 */
|
pascal@20223
|
854 +
|
pascal@20223
|
855 + errnum = ERR_FILE_NOT_FOUND;
|
pascal@20223
|
856 + *rest = ch;
|
pascal@20223
|
857 +
|
pascal@20223
|
858 + return 0;
|
pascal@20223
|
859 }
|
pascal@20223
|
860
|
pascal@20223
|
861 /* else, find the (logical) block component of our location */
|
pascal@20223
|
862 + /* ext4 logical block number the same as ext2/3 */
|
pascal@20223
|
863 blk = loc >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK);
|
pascal@20223
|
864
|
pascal@20223
|
865 /* we know which logical block of the directory entry we are looking
|
pascal@20223
|
866 for, now we have to translate that to the physical (fs) block on
|
pascal@20223
|
867 the disk */
|
pascal@20223
|
868 + /* map extents enabled logical block number to physical fs on-dick block number */
|
pascal@20223
|
869 + if (EXT4_HAS_INCOMPAT_FEATURE(SUPERBLOCK,EXT4_FEATURE_INCOMPAT_EXTENTS)
|
pascal@20223
|
870 + && INODE->i_flags & EXT4_EXTENTS_FL)
|
pascal@20223
|
871 + map = ext4fs_block_map (blk);
|
pascal@20223
|
872 + else
|
pascal@20223
|
873 map = ext2fs_block_map (blk);
|
pascal@20223
|
874 #ifdef E2DEBUG
|
pascal@20223
|
875 printf ("fs block=%d\n", map);
|
pascal@20223
|
876 #endif /* E2DEBUG */
|
pascal@20223
|
877 mapblock2 = -1;
|
pascal@20223
|
878 - if ((map < 0) || !ext2_rdfsb (map, DATABLOCK2))
|
pascal@20223
|
879 + if (map < 0)
|
pascal@20223
|
880 + {
|
pascal@20223
|
881 + *rest = ch;
|
pascal@20223
|
882 + return 0;
|
pascal@20223
|
883 + }
|
pascal@20223
|
884 + if (!ext2_rdfsb (map, DATABLOCK2))
|
pascal@20223
|
885 {
|
pascal@20223
|
886 errnum = ERR_FSYS_CORRUPT;
|
pascal@20223
|
887 *rest = ch;
|
pascal@20224
|
888 @@ -759,22 +1150,36 @@
|
pascal@20223
|
889
|
pascal@20223
|
890 if (dp->inode)
|
pascal@20223
|
891 {
|
pascal@20223
|
892 - int saved_c = dp->name[dp->name_len];
|
pascal@20223
|
893 + //int saved_c = dp->name[dp->name_len];
|
pascal@20223
|
894 + int j, k;
|
pascal@20223
|
895 + char ch1;
|
pascal@20223
|
896 + char *tmp_name= NAME_BUF; /* EXT2_NAME_LEN is 255, so 512 byte buffer is needed. */
|
pascal@20223
|
897
|
pascal@20223
|
898 - dp->name[dp->name_len] = 0;
|
pascal@20223
|
899 - str_chk = substring (dirname, dp->name);
|
pascal@20223
|
900 + /* copy dp->name to tmp_name, and quote the spaces with a '\\' */
|
pascal@20223
|
901 + for (j = 0, k = 0; j < dp->name_len; j++)
|
pascal@20223
|
902 + {
|
pascal@20223
|
903 + if (! (ch1 = dp->name[j]))
|
pascal@20223
|
904 + break;
|
pascal@20223
|
905 + if (ch1 == ' ')
|
pascal@20223
|
906 + tmp_name[k++] = '\\';
|
pascal@20223
|
907 + tmp_name[k++] = ch1;
|
pascal@20223
|
908 + }
|
pascal@20223
|
909 + tmp_name[k] = 0;
|
pascal@20223
|
910
|
pascal@20223
|
911 + //dp->name[dp->name_len] = 0;
|
pascal@20225
|
912 + str_chk = substring (dirname, tmp_name);
|
pascal@20223
|
913 +
|
pascal@20223
|
914 # ifndef STAGE1_5
|
pascal@20223
|
915 if (print_possibilities && ch != '/'
|
pascal@20223
|
916 && (!*dirname || str_chk <= 0))
|
pascal@20223
|
917 {
|
pascal@20223
|
918 if (print_possibilities > 0)
|
pascal@20223
|
919 print_possibilities = -print_possibilities;
|
pascal@20223
|
920 - print_a_completion (dp->name);
|
pascal@20223
|
921 + print_a_completion (tmp_name);
|
pascal@20223
|
922 }
|
pascal@20223
|
923 # endif
|
pascal@20223
|
924
|
pascal@20223
|
925 - dp->name[dp->name_len] = saved_c;
|
pascal@20223
|
926 + //dp->name[dp->name_len] = saved_c;
|
pascal@20223
|
927 }
|
pascal@20223
|
928
|
pascal@20223
|
929 }
|