wok view grub/stuff/ext3_256byte_inode+ext4.diff @ rev 20227

grub: add ext4 patch (again)
author Pascal Bellard <pascal.bellard@slitaz.org>
date Thu Mar 01 11:55:46 2018 +0100 (2018-03-01)
parents e6d3b1fa06cd
children 12f947645264
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,17 +86,63 @@
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 + //__u32 s_reserved[235]; /* Padding to the end of the block */
57 + /*
58 + * These fields are for EXT2_DYNAMIC_REV superblocks only.
59 + *
60 + * Note: the difference between the compatible feature set and
61 + * the incompatible feature set is that if there is a bit set
62 + * in the incompatible feature set that the kernel doesn't
63 + * know about, it should refuse to mount the filesystem.
64 + *
65 + * e2fsck's requirements are more strict; if it doesn't know
66 + * about a feature in either the compatible or incompatible
67 + * feature set, it must abort and not try to meddle with
68 + * things it doesn't understand...
69 + */
70 + __u32 s_first_ino; /* First non-reserved inode */
71 + __u16 s_inode_size; /* size of inode structure */
72 + __u16 s_block_group_nr; /* block group # of this superblock */
73 + __u32 s_feature_compat; /* compatible feature set */
74 + __u32 s_feature_incompat; /* incompatible feature set */
75 + __u32 s_feature_ro_compat; /* readonly-compatible feature set */
76 + __u8 s_uuid[16]; /* 128-bit uuid for volume */
77 + char s_volume_name[16]; /* volume name */
78 + char s_last_mounted[64]; /* directory where last mounted */
79 + __u32 s_algorithm_usage_bitmap; /* For compression */
80 + /*
81 + * Performance hints. Directory preallocation should only
82 + * happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on.
83 + */
84 + __u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
85 + __u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
86 + __u16 s_reserved_gdt_blocks;/* Per group table for online growth */
87 + /*
88 + * Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set.
89 + */
90 + __u8 s_journal_uuid[16]; /* uuid of journal superblock */
91 + __u32 s_journal_inum; /* inode number of journal file */
92 + __u32 s_journal_dev; /* device number of journal file */
93 + __u32 s_last_orphan; /* start of list of inodes to delete */
94 + __u32 s_hash_seed[4]; /* HTREE hash seed */
95 + __u8 s_def_hash_version; /* Default hash version to use */
96 + __u8 s_jnl_backup_type; /* Default type of journal backup */
97 + __u16 s_desc_size; /* size of group descriptor */
98 + __u32 s_default_mount_opts;
99 + __u32 s_first_meta_bg; /* First metablock group */
100 + __u32 s_mkfs_time; /* When the filesystem was created */
101 + __u32 s_jnl_blocks[17]; /* Backup of the journal inode */
102 + __u32 s_reserved[172]; /* Padding to the end of the block */
103 };
105 -struct ext2_group_desc
106 +struct ext4_group_desc
107 {
108 __u32 bg_block_bitmap; /* Blocks bitmap block */
109 __u32 bg_inode_bitmap; /* Inodes bitmap block */
110 @@ -90,8 +150,18 @@
111 __u16 bg_free_blocks_count; /* Free blocks count */
112 __u16 bg_free_inodes_count; /* Free inodes count */
113 __u16 bg_used_dirs_count; /* Directories count */
114 - __u16 bg_pad;
115 - __u32 bg_reserved[3];
116 + __u16 bg_flags; /* EXT4_BG_flags (INODE_UNINIT, etc) */
117 + __u32 bg_reserved[2]; /* Likely block/inode bitmap checksum */
118 + __u16 bg_itable_unused; /* Unused inodes count */
119 + __u16 bg_checksum; /* crc16(sb_uuid+group+desc) */
120 + __u32 bg_block_bitmap_hi; /* Blocks bitmap block MSB */
121 + __u32 bg_inode_bitmap_hi; /* Inodes bitmap block MSB */
122 + __u32 bg_inode_table_hi; /* Inodes table block MSB */
123 + __u16 bg_free_blocks_count_hi;/* Free blocks count MSB */
124 + __u16 bg_free_inodes_count_hi;/* Free inodes count MSB */
125 + __u16 bg_used_dirs_count_hi; /* Directories count MSB */
126 + __u16 bg_itable_unused_hi; /* Unused inodes count MSB */
127 + __u32 bg_reserved2[3];
128 };
130 struct ext2_inode
131 @@ -129,22 +199,22 @@
132 __u32 i_block[EXT2_N_BLOCKS]; /* 40: Pointers to blocks */
133 __u32 i_version; /* File version (for NFS) */
134 __u32 i_file_acl; /* File ACL */
135 - __u32 i_dir_acl; /* Directory ACL */
136 - __u32 i_faddr; /* Fragment address */
137 + __u32 i_size_high;
138 + __u32 i_obso_faddr; /* Obsoleted fragment address */
139 union
140 {
141 struct
142 {
143 - __u8 l_i_frag; /* Fragment number */
144 - __u8 l_i_fsize; /* Fragment size */
145 - __u16 i_pad1;
146 - __u32 l_i_reserved2[2];
147 + __u16 l_i_blocks_high; /* were l_i_reserved1 */
148 + __u16 l_i_file_acl_high;
149 + __u16 l_i_uid_high; /* these 2 fields */
150 + __u16 l_i_gid_high; /* were reserved2[0] */
151 + __u32 l_i_reserved2;
152 }
153 linux2;
154 struct
155 {
156 - __u8 h_i_frag; /* Fragment number */
157 - __u8 h_i_fsize; /* Fragment size */
158 + __u16 h_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */
159 __u16 h_i_mode_high;
160 __u16 h_i_uid_high;
161 __u16 h_i_gid_high;
162 @@ -153,16 +223,36 @@
163 hurd2;
164 struct
165 {
166 - __u8 m_i_frag; /* Fragment number */
167 - __u8 m_i_fsize; /* Fragment size */
168 - __u16 m_pad1;
169 + __u16 h_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */
170 + __u16 m_i_file_acl_high;
171 __u32 m_i_reserved2[2];
172 }
173 masix2;
174 }
175 osd2; /* OS dependent 2 */
176 + __u16 i_extra_isize;
177 + __u16 i_pad1;
178 + __u32 i_ctime_extra; /* extra Change time (nsec << 2 | epoch) */
179 + __u32 i_mtime_extra; /* extra Modification time(nsec << 2 | epoch) */
180 + __u32 i_atime_extra; /* extra Access time (nsec << 2 | epoch) */
181 + __u32 i_crtime; /* File Creation time */
182 + __u32 i_crtime_extra; /* extra FileCreationtime (nsec << 2 | epoch) */
183 + __u32 i_version_hi; /* high 32 bits for 64-bit version */
184 };
186 +#define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */
187 +#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080 /* grub not supported*/
188 +#define EXT4_FEATURE_INCOMPAT_MMP 0x0100
189 +#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200
190 +
191 +#define EXT4_HAS_INCOMPAT_FEATURE(sb,mask) \
192 + ( sb->s_feature_incompat & mask )
193 +
194 +#define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */
195 +#define EXT4_HUGE_FILE_FL 0x00040000 /* Set to each huge file */
196 +
197 +#define EXT4_MIN_DESC_SIZE 32
198 +
199 /* linux/limits.h */
200 #define NAME_MAX 255 /* # chars in a file name */
202 @@ -180,6 +270,57 @@
203 char name[EXT2_NAME_LEN]; /* File name */
204 };
206 +/* linux/ext4_fs_extents.h */
207 +/* This is the extent on-disk structure.
208 + * It's used at the bottom of the tree.
209 + */
210 +struct ext4_extent
211 + {
212 + __u32 ee_block; /* first logical block extent covers */
213 + __u16 ee_len; /* number of blocks covered by extent */
214 + __u16 ee_start_hi; /* high 16 bits of physical block */
215 + __u32 ee_start_lo; /* low 32 bits of physical block */
216 + };
217 +
218 +/*
219 + * This is index on-disk structure.
220 + * It's used at all the levels except the bottom.
221 + */
222 +struct ext4_extent_idx
223 + {
224 + __u32 ei_block; /* index covers logical blocks from 'block' */
225 + __u32 ei_leaf_lo; /* pointer to the physical block of the next *
226 + * level. leaf or next index could be there */
227 + __u16 ei_leaf_hi; /* high 16 bits of physical block */
228 + __u16 ei_unused;
229 + };
230 +
231 +/*
232 + * Each block (leaves and indexes), even inode-stored has header.
233 + */
234 +struct ext4_extent_header
235 + {
236 + __u16 eh_magic; /* probably will support different formats */
237 + __u16 eh_entries; /* number of valid entries */
238 + __u16 eh_max; /* capacity of store in entries */
239 + __u16 eh_depth; /* has tree real underlying blocks? */
240 + __u32 eh_generation; /* generation of the tree */
241 + };
242 +
243 +#define EXT4_EXT_MAGIC (0xf30a)
244 +#define EXT_FIRST_EXTENT(__hdr__) \
245 + ((struct ext4_extent *) (((char *) (__hdr__)) + \
246 + sizeof(struct ext4_extent_header)))
247 +#define EXT_FIRST_INDEX(__hdr__) \
248 + ((struct ext4_extent_idx *) (((char *) (__hdr__)) + \
249 + sizeof(struct ext4_extent_header)))
250 +#define EXT_LAST_EXTENT(__hdr__) \
251 + (EXT_FIRST_EXTENT((__hdr__)) + (__u16)((__hdr__)->eh_entries) - 1)
252 +#define EXT_LAST_INDEX(__hdr__) \
253 + (EXT_FIRST_INDEX((__hdr__)) + (__u16)((__hdr__)->eh_entries) - 1)
254 +
255 +
256 +
257 /* linux/ext2fs.h */
258 /*
259 * EXT2_DIR_PAD defines the directory entries boundaries
260 @@ -193,7 +334,7 @@
263 /* ext2/super.c */
264 -#define log2(n) ffz(~(n))
265 +//#define log2(n) ffz(~(n))
267 #define EXT2_SUPER_MAGIC 0xEF53 /* include/linux/ext2_fs.h */
268 #define EXT2_ROOT_INO 2 /* include/linux/ext2_fs.h */
269 @@ -202,11 +343,12 @@
271 /* made up, these are pointers into FSYS_BUF */
272 /* read once, always stays there: */
273 +#define NAME_BUF ((char *)(FSYS_BUF)) /* 512 bytes */
274 #define SUPERBLOCK \
275 - ((struct ext2_super_block *)(FSYS_BUF))
276 + ((struct ext2_super_block *)((FSYS_BUF)+512)) /* 1024 bytes */
277 #define GROUP_DESC \
278 ((struct ext2_group_desc *) \
279 - ((int)SUPERBLOCK + sizeof(struct ext2_super_block)))
280 + ((int)SUPERBLOCK + sizeof(struct ext2_super_block))) /* 32 bytes */
281 #define INODE \
282 ((struct ext2_inode *)((int)GROUP_DESC + EXT2_BLOCK_SIZE(SUPERBLOCK)))
283 #define DATABLOCK1 \
284 @@ -216,15 +358,37 @@
286 /* linux/ext2_fs.h */
287 #define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
288 -#define EXT2_ADDR_PER_BLOCK_BITS(s) (log2(EXT2_ADDR_PER_BLOCK(s)))
289 +#define EXT2_ADDR_PER_BLOCK_BITS(s) (log2(EXT2_ADDR_PER_BLOCK(s)))
291 +/* Revision levels */
292 +#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */
293 +#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */
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))
303 +
304 /* linux/ext2_fs.h */
305 #define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
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 @@ -234,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))
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 @@ -285,7 +493,7 @@
428 /* Maps LOGICAL_BLOCK (the file offset divided by the blocksize) into
429 a physical block (the location in the file system) via an inode. */
430 static int
431 -ext2fs_block_map (int logical_block)
432 +ext2fs_block_map (unsigned long logical_block)
433 {
435 #ifdef E2DEBUG
436 @@ -359,13 +567,16 @@
437 /* else */
438 mapblock2 = -1;
439 logical_block -= (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2));
440 +
441 if (mapblock1 != 3
442 && !ext2_rdfsb (INODE->i_block[EXT2_TIND_BLOCK], DATABLOCK1))
443 {
444 errnum = ERR_FSYS_CORRUPT;
445 return -1;
446 }
447 +
448 mapblock1 = 3;
449 +
450 if (!ext2_rdfsb (((__u32 *) DATABLOCK1)
451 [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)
452 * 2)],
453 @@ -374,7 +585,8 @@
454 errnum = ERR_FSYS_CORRUPT;
455 return -1;
456 }
457 - if (!ext2_rdfsb (((__u32 *) DATABLOCK2)
458 +
459 + if (! ext2_rdfsb (((__u32 *) DATABLOCK2)
460 [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK))
461 & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)],
462 DATABLOCK2))
463 @@ -382,30 +594,148 @@
464 errnum = ERR_FSYS_CORRUPT;
465 return -1;
466 }
467 - return ((__u32 *) DATABLOCK2)
468 - [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
469 +
470 + return ((__u32 *) DATABLOCK2)[logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
471 }
473 +/* extent binary search index
474 + * find closest index in the current level extent tree
475 + * kind of from ext4_ext_binsearch_idx in ext4/extents.c
476 + */
477 +static struct ext4_extent_idx*
478 +ext4_ext_binsearch_idx(struct ext4_extent_header* eh, int logical_block)
479 +{
480 + struct ext4_extent_idx *r, *l, *m;
481 + l = EXT_FIRST_INDEX(eh) + 1;
482 + r = EXT_LAST_INDEX(eh);
483 + while (l <= r)
484 + {
485 + m = l + (r - l) / 2;
486 + if (logical_block < m->ei_block)
487 + r = m - 1;
488 + else
489 + l = m + 1;
490 + }
491 + return (struct ext4_extent_idx*)(l - 1);
492 +}
493 +
494 +/* extent binary search
495 + * find closest extent in the leaf level
496 + * kind of from ext4_ext_binsearch in ext4/extents.c
497 + */
498 +static struct ext4_extent*
499 +ext4_ext_binsearch(struct ext4_extent_header* eh, int logical_block)
500 +{
501 + struct ext4_extent *r, *l, *m;
502 + l = EXT_FIRST_EXTENT(eh) + 1;
503 + r = EXT_LAST_EXTENT(eh);
504 + while (l <= r)
505 + {
506 + m = l + (r - l) / 2;
507 + if (logical_block < m->ee_block)
508 + r = m - 1;
509 + else
510 + l = m + 1;
511 + }
512 + return (struct ext4_extent*)(l - 1);
513 +}
514 +
515 +/* Maps extents enabled logical block into physical block via an inode.
516 + * EXT4_HUGE_FILE_FL should be checked before calling this.
517 + */
518 +static int
519 +ext4fs_block_map (int logical_block)
520 +{
521 + struct ext4_extent_header *eh;
522 + struct ext4_extent *ex;//, *extent;
523 + struct ext4_extent_idx *ei;//, *index;
524 + int depth;
525 + //int i;
526 +
527 +#ifdef E2DEBUG
528 + unsigned char *i;
529 + for (i = (unsigned char *) INODE;
530 + i < ((unsigned char *) INODE + sizeof (struct ext2_inode));
531 + i++)
532 + {
533 + printf ("%c", "0123456789abcdef"[*i >> 4]);
534 + printf ("%c", "0123456789abcdef"[*i % 16]);
535 + if (!((i + 1 - (unsigned char *) INODE) % 16))
536 + {
537 + printf ("\n");
538 + }
539 + else
540 + {
541 + printf (" ");
542 + }
543 + }
544 + printf ("logical block %d\n", logical_block);
545 +#endif /* E2DEBUG */
546 + eh = (struct ext4_extent_header*)INODE->i_block;
547 + if (eh->eh_magic != EXT4_EXT_MAGIC)
548 + {
549 + errnum = ERR_FSYS_CORRUPT;
550 + return -1;
551 + }
552 + while((depth = eh->eh_depth) != 0)
553 + { /* extent index */
554 + if (eh->eh_magic != EXT4_EXT_MAGIC)
555 + {
556 + errnum = ERR_FSYS_CORRUPT;
557 + return -1;
558 + }
559 + ei = ext4_ext_binsearch_idx(eh, logical_block);
560 + if (ei->ei_leaf_hi)
561 + {/* 64bit physical block number not supported */
562 + errnum = ERR_FILELENGTH;
563 + return -1;
564 + }
565 + if (!ext2_rdfsb(ei->ei_leaf_lo, DATABLOCK1))
566 + {
567 + errnum = ERR_FSYS_CORRUPT;
568 + return -1;
569 + }
570 + eh = (struct ext4_extent_header*)DATABLOCK1;
571 + }
572 +
573 + /* depth==0, we come to the leaf */
574 + ex = ext4_ext_binsearch(eh, logical_block);
575 + if (ex->ee_start_hi)
576 + {/* 64bit physical block number not supported */
577 + errnum = ERR_FILELENGTH;
578 + return -1;
579 + }
580 + if ((ex->ee_block + ex->ee_len) < logical_block)
581 + {
582 + errnum = ERR_FSYS_CORRUPT;
583 + return -1;
584 + }
585 + return ex->ee_start_lo + logical_block - ex->ee_block;
586 +
587 +}
588 +
589 /* preconditions: all preconds of ext2fs_block_map */
590 int
591 ext2fs_read (char *buf, int len)
592 {
593 - int logical_block;
594 - int offset;
595 + unsigned long logical_block;
596 + unsigned long offset;
597 + unsigned long ret = 0;
598 + unsigned long size = 0;
599 int map;
600 - int ret = 0;
601 - int size = 0;
603 #ifdef E2DEBUG
604 static char hexdigit[] = "0123456789abcdef";
605 unsigned char *i;
606 +
607 for (i = (unsigned char *) INODE;
608 i < ((unsigned char *) INODE + sizeof (struct ext2_inode));
609 i++)
610 {
611 printf ("%c", hexdigit[*i >> 4]);
612 printf ("%c", hexdigit[*i % 16]);
613 - if (!((i + 1 - (unsigned char *) INODE) % 16))
614 +
615 + if (! ((i + 1 - (unsigned char *) INODE) % 16))
616 {
617 printf ("\n");
618 }
619 @@ -416,41 +746,53 @@
620 }
621 #endif /* E2DEBUG */
622 while (len > 0)
623 - {
624 + {
625 /* find the (logical) block component of our location */
626 logical_block = filepos >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK);
627 offset = filepos & (EXT2_BLOCK_SIZE (SUPERBLOCK) - 1);
628 +
629 + /* map extents enabled logical block number to physical fs on-dick block number */
630 + if (EXT4_HAS_INCOMPAT_FEATURE(SUPERBLOCK,EXT4_FEATURE_INCOMPAT_EXTENTS)
631 + && INODE->i_flags & EXT4_EXTENTS_FL)
632 + map = ext4fs_block_map (logical_block);
633 + else
634 map = ext2fs_block_map (logical_block);
635 +
636 #ifdef E2DEBUG
637 printf ("map=%d\n", map);
638 #endif /* E2DEBUG */
639 +
640 if (map < 0)
641 - break;
642 + break;
644 size = EXT2_BLOCK_SIZE (SUPERBLOCK);
645 size -= offset;
646 +
647 if (size > len)
648 - size = len;
649 + size = len;
651 - if (map == 0) {
652 - memset ((char *) buf, 0, size);
653 + if (map == 0)
654 + {
655 + if (buf)
656 + memset ((char *) buf, 0, size);
657 } else {
658 - disk_read_func = disk_read_hook;
659 + disk_read_func = disk_read_hook;
661 - devread (map * (EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE),
662 - offset, size, buf);
663 + devread (map * (EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE),
664 + offset, size, buf);
666 - disk_read_func = NULL;
667 + disk_read_func = NULL;
668 }
670 - buf += size;
671 - len -= size;
672 + if (buf)
673 + buf += size;
674 + len -= size; /* len always >= 0 */
675 filepos += size;
676 ret += size;
677 - }
678 + }
680 if (errnum)
681 - ret = 0;
682 + ret = 0;
684 return ret;
685 }
686 @@ -504,10 +846,10 @@
687 int desc; /* index within that group */
688 int ino_blk; /* fs pointer of the inode's information */
689 int str_chk = 0; /* used to hold the results of a string compare */
690 - struct ext2_group_desc *gdp;
691 + struct ext4_group_desc *ext4_gdp;
692 struct ext2_inode *raw_inode; /* inode info corresponding to current_ino */
694 - char linkbuf[PATH_MAX]; /* buffer for following symbolic links */
695 +//char linkbuf[PATH_MAX]; /* buffer for following symbolic links */
696 int link_count = 0;
698 char *rest;
699 @@ -537,7 +879,7 @@
701 /* look up an inode */
702 group_id = (current_ino - 1) / (SUPERBLOCK->s_inodes_per_group);
703 - group_desc = group_id >> log2 (EXT2_DESC_PER_BLOCK (SUPERBLOCK));
704 + group_desc = group_id >> log2 (EXT2_DESC_PER_BLOCK (SUPERBLOCK));
705 desc = group_id & (EXT2_DESC_PER_BLOCK (SUPERBLOCK) - 1);
706 #ifdef E2DEBUG
707 printf ("ipg=%d, dpb=%d\n", SUPERBLOCK->s_inodes_per_group,
708 @@ -550,10 +892,17 @@
709 {
710 return 0;
711 }
712 - gdp = GROUP_DESC;
713 - ino_blk = gdp[desc].bg_inode_table +
714 + ext4_gdp = (struct ext4_group_desc *)( (__u8*)GROUP_DESC +
715 + desc * EXT2_DESC_SIZE(SUPERBLOCK));
716 + if (EXT4_HAS_INCOMPAT_FEATURE(SUPERBLOCK, EXT4_FEATURE_INCOMPAT_64BIT)
717 + && (! ext4_gdp->bg_inode_table_hi))
718 + {/* 64bit itable not supported */
719 + errnum = ERR_FILELENGTH;
720 + return -1;
721 + }
722 + ino_blk = ext4_gdp->bg_inode_table +
723 (((current_ino - 1) % (SUPERBLOCK->s_inodes_per_group))
724 - >> log2 (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)));
725 + >> log2 (EXT2_INODES_PER_BLOCK (SUPERBLOCK)));
726 #ifdef E2DEBUG
727 printf ("inode table fsblock=%d\n", ino_blk);
728 #endif /* E2DEBUG */
729 @@ -565,13 +914,12 @@
730 /* reset indirect blocks! */
731 mapblock2 = mapblock1 = -1;
733 - raw_inode = INODE +
734 - ((current_ino - 1)
735 - & (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode) - 1));
736 + raw_inode = (struct ext2_inode *)((char *)INODE +
737 + ((current_ino - 1) & (EXT2_INODES_PER_BLOCK (SUPERBLOCK) - 1)) *
738 + EXT2_INODE_SIZE (SUPERBLOCK));
739 #ifdef E2DEBUG
740 printf ("ipb=%d, sizeof(inode)=%d\n",
741 - (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)),
742 - sizeof (struct ext2_inode));
743 + EXT2_INODES_PER_BLOCK (SUPERBLOCK), EXT2_INODE_SIZE (SUPERBLOCK));
744 printf ("inode=%x, raw_inode=%x\n", INODE, raw_inode);
745 printf ("offset into inode table block=%d\n", (int) raw_inode - (int) INODE);
746 for (i = (unsigned char *) INODE; i <= (unsigned char *) raw_inode;
747 @@ -609,13 +957,22 @@
748 }
750 /* Find out how long our remaining name is. */
751 - len = 0;
752 - while (dirname[len] && !isspace (dirname[len]))
753 - len++;
754 + //len = 0;
755 + //while (dirname[len] && !isspace (dirname[len]))
756 + // len++;
757 + for (len = 0; (ch = dirname[len]) && !isspace (ch); len++)
758 + {
759 + if (ch == '\\')
760 + {
761 + len++;
762 + if (! (ch = dirname[len]))
763 + break;
764 + }
765 + }
767 /* Get the symlink size. */
768 filemax = (INODE->i_size);
769 - if (filemax + len > sizeof (linkbuf) - 2)
770 + if (filemax + len > PATH_MAX - 2)
771 {
772 errnum = ERR_FILELENGTH;
773 return 0;
774 @@ -629,18 +986,23 @@
775 }
776 linkbuf[filemax + len] = '\0';
778 - /* Read the symlink data. */
779 + /* Read the symlink data.
780 + * Slow symlink is extents enabled
781 + * But since grub_read invokes ext2fs_read, nothing to change here
782 + * */
783 if (! ext2_is_fast_symlink ())
784 {
785 /* Read the necessary blocks, and reset the file pointer. */
786 - len = grub_read (linkbuf, filemax);
787 + len = grub_read (linkbuf, filemax);
788 filepos = 0;
789 if (!len)
790 return 0;
791 }
792 else
793 {
794 - /* Copy the data directly from the inode. */
795 + /* Copy the data directly from the inode.
796 + * Fast symlink is not extents enabled
797 + * */
798 len = filemax;
799 memmove (linkbuf, (char *) INODE->i_block, len);
800 }
801 @@ -674,6 +1036,13 @@
802 errnum = ERR_BAD_FILETYPE;
803 return 0;
804 }
805 + /* if file is too large, just stop and report an error*/
806 + if ( (INODE->i_flags & EXT4_HUGE_FILE_FL) && !(INODE->i_size_high))
807 + {
808 + /* file too large, stop reading */
809 + errnum = ERR_FILELENGTH;
810 + return 0;
811 + }
813 filemax = (INODE->i_size);
814 return 1;
815 @@ -694,8 +1063,17 @@
816 }
818 /* skip to next slash or end of filename (space) */
819 - for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/';
820 - rest++);
821 +// for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/';
822 +// rest++);
823 + for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++)
824 + {
825 + if (ch == '\\')
826 + {
827 + rest++;
828 + if (! (ch = *rest))
829 + break;
830 + }
831 + }
833 /* look through this directory and find the next filename component */
834 /* invariant: rest points to slash after the next filename component */
835 @@ -713,32 +1091,45 @@
836 give up */
837 if (loc >= INODE->i_size)
838 {
839 +# ifndef STAGE1_5
840 if (print_possibilities < 0)
841 {
842 # if 0
843 putchar ('\n');
844 # endif
845 + return 1;
846 }
847 - else
848 - {
849 - errnum = ERR_FILE_NOT_FOUND;
850 - *rest = ch;
851 - }
852 - return (print_possibilities < 0);
853 +# endif /* STAGE1_5 */
854 +
855 + errnum = ERR_FILE_NOT_FOUND;
856 + *rest = ch;
857 +
858 + return 0;
859 }
861 /* else, find the (logical) block component of our location */
862 + /* ext4 logical block number the same as ext2/3 */
863 blk = loc >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK);
865 /* we know which logical block of the directory entry we are looking
866 for, now we have to translate that to the physical (fs) block on
867 the disk */
868 + /* map extents enabled logical block number to physical fs on-dick block number */
869 + if (EXT4_HAS_INCOMPAT_FEATURE(SUPERBLOCK,EXT4_FEATURE_INCOMPAT_EXTENTS)
870 + && INODE->i_flags & EXT4_EXTENTS_FL)
871 + map = ext4fs_block_map (blk);
872 + else
873 map = ext2fs_block_map (blk);
874 #ifdef E2DEBUG
875 printf ("fs block=%d\n", map);
876 #endif /* E2DEBUG */
877 mapblock2 = -1;
878 - if ((map < 0) || !ext2_rdfsb (map, DATABLOCK2))
879 + if (map < 0)
880 + {
881 + *rest = ch;
882 + return 0;
883 + }
884 + if (!ext2_rdfsb (map, DATABLOCK2))
885 {
886 errnum = ERR_FSYS_CORRUPT;
887 *rest = ch;
888 @@ -759,22 +1150,36 @@
890 if (dp->inode)
891 {
892 - int saved_c = dp->name[dp->name_len];
893 + //int saved_c = dp->name[dp->name_len];
894 + int j, k;
895 + char ch1;
896 + char *tmp_name= NAME_BUF; /* EXT2_NAME_LEN is 255, so 512 byte buffer is needed. */
898 - dp->name[dp->name_len] = 0;
899 - str_chk = substring (dirname, dp->name);
900 + /* copy dp->name to tmp_name, and quote the spaces with a '\\' */
901 + for (j = 0, k = 0; j < dp->name_len; j++)
902 + {
903 + if (! (ch1 = dp->name[j]))
904 + break;
905 + if (ch1 == ' ')
906 + tmp_name[k++] = '\\';
907 + tmp_name[k++] = ch1;
908 + }
909 + tmp_name[k] = 0;
911 + //dp->name[dp->name_len] = 0;
912 + str_chk = substring (dirname, tmp_name);
913 +
914 # ifndef STAGE1_5
915 if (print_possibilities && ch != '/'
916 && (!*dirname || str_chk <= 0))
917 {
918 if (print_possibilities > 0)
919 print_possibilities = -print_possibilities;
920 - print_a_completion (dp->name);
921 + print_a_completion (tmp_name);
922 }
923 # endif
925 - dp->name[dp->name_len] = saved_c;
926 + //dp->name[dp->name_len] = saved_c;
927 }
929 }