wok-current view grub/stuff/ext3_256byte_inode+ext4.diff @ rev 20223

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