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