Commit 715b56fe2b47e073e6f2425e0cedba0e92a4014d

Authored by Tom Rini
1 parent a7e8c15f71

Revert "ext4fs: Add ext4 extent cache for read operations"

This reverts commit fc0fc50f38a4d7d0554558076a79dfe8b0d78cd5.

The author has asked on the mailing list that we revert this for now as
it breaks write support.

Reported-by: Łukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Tom Rini <trini@ti.com>

Showing 3 changed files with 73 additions and 130 deletions Inline Diff

fs/ext4/ext4_common.c
1 /* 1 /*
2 * (C) Copyright 2011 - 2012 Samsung Electronics 2 * (C) Copyright 2011 - 2012 Samsung Electronics
3 * EXT4 filesystem implementation in Uboot by 3 * EXT4 filesystem implementation in Uboot by
4 * Uma Shankar <uma.shankar@samsung.com> 4 * Uma Shankar <uma.shankar@samsung.com>
5 * Manjunatha C Achar <a.manjunatha@samsung.com> 5 * Manjunatha C Achar <a.manjunatha@samsung.com>
6 * 6 *
7 * ext4ls and ext4load : Based on ext2 ls load support in Uboot. 7 * ext4ls and ext4load : Based on ext2 ls load support in Uboot.
8 * 8 *
9 * (C) Copyright 2004 9 * (C) Copyright 2004
10 * esd gmbh <www.esd-electronics.com> 10 * esd gmbh <www.esd-electronics.com>
11 * Reinhard Arlt <reinhard.arlt@esd-electronics.com> 11 * Reinhard Arlt <reinhard.arlt@esd-electronics.com>
12 * 12 *
13 * based on code from grub2 fs/ext2.c and fs/fshelp.c by 13 * based on code from grub2 fs/ext2.c and fs/fshelp.c by
14 * GRUB -- GRand Unified Bootloader 14 * GRUB -- GRand Unified Bootloader
15 * Copyright (C) 2003, 2004 Free Software Foundation, Inc. 15 * Copyright (C) 2003, 2004 Free Software Foundation, Inc.
16 * 16 *
17 * ext4write : Based on generic ext4 protocol. 17 * ext4write : Based on generic ext4 protocol.
18 * 18 *
19 * SPDX-License-Identifier: GPL-2.0+ 19 * SPDX-License-Identifier: GPL-2.0+
20 */ 20 */
21 21
22 #include <common.h> 22 #include <common.h>
23 #include <ext_common.h> 23 #include <ext_common.h>
24 #include <ext4fs.h> 24 #include <ext4fs.h>
25 #include <malloc.h> 25 #include <malloc.h>
26 #include <stddef.h> 26 #include <stddef.h>
27 #include <linux/stat.h> 27 #include <linux/stat.h>
28 #include <linux/time.h> 28 #include <linux/time.h>
29 #include <linux/list.h>
30 #include <asm/byteorder.h> 29 #include <asm/byteorder.h>
31 #include "ext4_common.h" 30 #include "ext4_common.h"
32 31
33 struct ext2_data *ext4fs_root; 32 struct ext2_data *ext4fs_root;
34 struct ext2fs_node *ext4fs_file; 33 struct ext2fs_node *ext4fs_file;
35 uint32_t *ext4fs_indir1_block; 34 uint32_t *ext4fs_indir1_block;
36 int ext4fs_indir1_size; 35 int ext4fs_indir1_size;
37 int ext4fs_indir1_blkno = -1; 36 int ext4fs_indir1_blkno = -1;
38 uint32_t *ext4fs_indir2_block; 37 uint32_t *ext4fs_indir2_block;
39 int ext4fs_indir2_size; 38 int ext4fs_indir2_size;
40 int ext4fs_indir2_blkno = -1; 39 int ext4fs_indir2_blkno = -1;
41 40
42 uint32_t *ext4fs_indir3_block; 41 uint32_t *ext4fs_indir3_block;
43 int ext4fs_indir3_size; 42 int ext4fs_indir3_size;
44 int ext4fs_indir3_blkno = -1; 43 int ext4fs_indir3_blkno = -1;
45 struct ext2_inode *g_parent_inode; 44 struct ext2_inode *g_parent_inode;
46 static int symlinknest; 45 static int symlinknest;
47 46
48 struct ext4_extent_node {
49 uint32_t block;
50 uint16_t len;
51 uint64_t start;
52 struct list_head lh;
53 };
54 static LIST_HEAD(ext4_extent_lh);
55
56 #if defined(CONFIG_EXT4_WRITE) 47 #if defined(CONFIG_EXT4_WRITE)
57 uint32_t ext4fs_div_roundup(uint32_t size, uint32_t n) 48 uint32_t ext4fs_div_roundup(uint32_t size, uint32_t n)
58 { 49 {
59 uint32_t res = size / n; 50 uint32_t res = size / n;
60 if (res * n != size) 51 if (res * n != size)
61 res++; 52 res++;
62 53
63 return res; 54 return res;
64 } 55 }
65 56
66 void put_ext4(uint64_t off, void *buf, uint32_t size) 57 void put_ext4(uint64_t off, void *buf, uint32_t size)
67 { 58 {
68 uint64_t startblock; 59 uint64_t startblock;
69 uint64_t remainder; 60 uint64_t remainder;
70 unsigned char *temp_ptr = NULL; 61 unsigned char *temp_ptr = NULL;
71 struct ext_filesystem *fs = get_fs(); 62 struct ext_filesystem *fs = get_fs();
72 int log2blksz = fs->dev_desc->log2blksz; 63 int log2blksz = fs->dev_desc->log2blksz;
73 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, sec_buf, fs->dev_desc->blksz); 64 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, sec_buf, fs->dev_desc->blksz);
74 65
75 startblock = off >> log2blksz; 66 startblock = off >> log2blksz;
76 startblock += part_offset; 67 startblock += part_offset;
77 remainder = off & (uint64_t)(fs->dev_desc->blksz - 1); 68 remainder = off & (uint64_t)(fs->dev_desc->blksz - 1);
78 69
79 if (fs->dev_desc == NULL) 70 if (fs->dev_desc == NULL)
80 return; 71 return;
81 72
82 if ((startblock + (size >> log2blksz)) > 73 if ((startblock + (size >> log2blksz)) >
83 (part_offset + fs->total_sect)) { 74 (part_offset + fs->total_sect)) {
84 printf("part_offset is " LBAFU "\n", part_offset); 75 printf("part_offset is " LBAFU "\n", part_offset);
85 printf("total_sector is %llu\n", fs->total_sect); 76 printf("total_sector is %llu\n", fs->total_sect);
86 printf("error: overflow occurs\n"); 77 printf("error: overflow occurs\n");
87 return; 78 return;
88 } 79 }
89 80
90 if (remainder) { 81 if (remainder) {
91 if (fs->dev_desc->block_read) { 82 if (fs->dev_desc->block_read) {
92 fs->dev_desc->block_read(fs->dev_desc->dev, 83 fs->dev_desc->block_read(fs->dev_desc->dev,
93 startblock, 1, sec_buf); 84 startblock, 1, sec_buf);
94 temp_ptr = sec_buf; 85 temp_ptr = sec_buf;
95 memcpy((temp_ptr + remainder), 86 memcpy((temp_ptr + remainder),
96 (unsigned char *)buf, size); 87 (unsigned char *)buf, size);
97 fs->dev_desc->block_write(fs->dev_desc->dev, 88 fs->dev_desc->block_write(fs->dev_desc->dev,
98 startblock, 1, sec_buf); 89 startblock, 1, sec_buf);
99 } 90 }
100 } else { 91 } else {
101 if (size >> log2blksz != 0) { 92 if (size >> log2blksz != 0) {
102 fs->dev_desc->block_write(fs->dev_desc->dev, 93 fs->dev_desc->block_write(fs->dev_desc->dev,
103 startblock, 94 startblock,
104 size >> log2blksz, 95 size >> log2blksz,
105 (unsigned long *)buf); 96 (unsigned long *)buf);
106 } else { 97 } else {
107 fs->dev_desc->block_read(fs->dev_desc->dev, 98 fs->dev_desc->block_read(fs->dev_desc->dev,
108 startblock, 1, sec_buf); 99 startblock, 1, sec_buf);
109 temp_ptr = sec_buf; 100 temp_ptr = sec_buf;
110 memcpy(temp_ptr, buf, size); 101 memcpy(temp_ptr, buf, size);
111 fs->dev_desc->block_write(fs->dev_desc->dev, 102 fs->dev_desc->block_write(fs->dev_desc->dev,
112 startblock, 1, 103 startblock, 1,
113 (unsigned long *)sec_buf); 104 (unsigned long *)sec_buf);
114 } 105 }
115 } 106 }
116 } 107 }
117 108
118 static int _get_new_inode_no(unsigned char *buffer) 109 static int _get_new_inode_no(unsigned char *buffer)
119 { 110 {
120 struct ext_filesystem *fs = get_fs(); 111 struct ext_filesystem *fs = get_fs();
121 unsigned char input; 112 unsigned char input;
122 int operand, status; 113 int operand, status;
123 int count = 1; 114 int count = 1;
124 int j = 0; 115 int j = 0;
125 116
126 /* get the blocksize of the filesystem */ 117 /* get the blocksize of the filesystem */
127 unsigned char *ptr = buffer; 118 unsigned char *ptr = buffer;
128 while (*ptr == 255) { 119 while (*ptr == 255) {
129 ptr++; 120 ptr++;
130 count += 8; 121 count += 8;
131 if (count > ext4fs_root->sblock.inodes_per_group) 122 if (count > ext4fs_root->sblock.inodes_per_group)
132 return -1; 123 return -1;
133 } 124 }
134 125
135 for (j = 0; j < fs->blksz; j++) { 126 for (j = 0; j < fs->blksz; j++) {
136 input = *ptr; 127 input = *ptr;
137 int i = 0; 128 int i = 0;
138 while (i <= 7) { 129 while (i <= 7) {
139 operand = 1 << i; 130 operand = 1 << i;
140 status = input & operand; 131 status = input & operand;
141 if (status) { 132 if (status) {
142 i++; 133 i++;
143 count++; 134 count++;
144 } else { 135 } else {
145 *ptr |= operand; 136 *ptr |= operand;
146 return count; 137 return count;
147 } 138 }
148 } 139 }
149 ptr = ptr + 1; 140 ptr = ptr + 1;
150 } 141 }
151 142
152 return -1; 143 return -1;
153 } 144 }
154 145
155 static int _get_new_blk_no(unsigned char *buffer) 146 static int _get_new_blk_no(unsigned char *buffer)
156 { 147 {
157 unsigned char input; 148 unsigned char input;
158 int operand, status; 149 int operand, status;
159 int count = 0; 150 int count = 0;
160 int j = 0; 151 int j = 0;
161 unsigned char *ptr = buffer; 152 unsigned char *ptr = buffer;
162 struct ext_filesystem *fs = get_fs(); 153 struct ext_filesystem *fs = get_fs();
163 154
164 if (fs->blksz != 1024) 155 if (fs->blksz != 1024)
165 count = 0; 156 count = 0;
166 else 157 else
167 count = 1; 158 count = 1;
168 159
169 while (*ptr == 255) { 160 while (*ptr == 255) {
170 ptr++; 161 ptr++;
171 count += 8; 162 count += 8;
172 if (count == (fs->blksz * 8)) 163 if (count == (fs->blksz * 8))
173 return -1; 164 return -1;
174 } 165 }
175 166
176 for (j = 0; j < fs->blksz; j++) { 167 for (j = 0; j < fs->blksz; j++) {
177 input = *ptr; 168 input = *ptr;
178 int i = 0; 169 int i = 0;
179 while (i <= 7) { 170 while (i <= 7) {
180 operand = 1 << i; 171 operand = 1 << i;
181 status = input & operand; 172 status = input & operand;
182 if (status) { 173 if (status) {
183 i++; 174 i++;
184 count++; 175 count++;
185 } else { 176 } else {
186 *ptr |= operand; 177 *ptr |= operand;
187 return count; 178 return count;
188 } 179 }
189 } 180 }
190 ptr = ptr + 1; 181 ptr = ptr + 1;
191 } 182 }
192 183
193 return -1; 184 return -1;
194 } 185 }
195 186
196 int ext4fs_set_block_bmap(long int blockno, unsigned char *buffer, int index) 187 int ext4fs_set_block_bmap(long int blockno, unsigned char *buffer, int index)
197 { 188 {
198 int i, remainder, status; 189 int i, remainder, status;
199 unsigned char *ptr = buffer; 190 unsigned char *ptr = buffer;
200 unsigned char operand; 191 unsigned char operand;
201 i = blockno / 8; 192 i = blockno / 8;
202 remainder = blockno % 8; 193 remainder = blockno % 8;
203 int blocksize = EXT2_BLOCK_SIZE(ext4fs_root); 194 int blocksize = EXT2_BLOCK_SIZE(ext4fs_root);
204 195
205 i = i - (index * blocksize); 196 i = i - (index * blocksize);
206 if (blocksize != 1024) { 197 if (blocksize != 1024) {
207 ptr = ptr + i; 198 ptr = ptr + i;
208 operand = 1 << remainder; 199 operand = 1 << remainder;
209 status = *ptr & operand; 200 status = *ptr & operand;
210 if (status) 201 if (status)
211 return -1; 202 return -1;
212 203
213 *ptr = *ptr | operand; 204 *ptr = *ptr | operand;
214 return 0; 205 return 0;
215 } else { 206 } else {
216 if (remainder == 0) { 207 if (remainder == 0) {
217 ptr = ptr + i - 1; 208 ptr = ptr + i - 1;
218 operand = (1 << 7); 209 operand = (1 << 7);
219 } else { 210 } else {
220 ptr = ptr + i; 211 ptr = ptr + i;
221 operand = (1 << (remainder - 1)); 212 operand = (1 << (remainder - 1));
222 } 213 }
223 status = *ptr & operand; 214 status = *ptr & operand;
224 if (status) 215 if (status)
225 return -1; 216 return -1;
226 217
227 *ptr = *ptr | operand; 218 *ptr = *ptr | operand;
228 return 0; 219 return 0;
229 } 220 }
230 } 221 }
231 222
232 void ext4fs_reset_block_bmap(long int blockno, unsigned char *buffer, int index) 223 void ext4fs_reset_block_bmap(long int blockno, unsigned char *buffer, int index)
233 { 224 {
234 int i, remainder, status; 225 int i, remainder, status;
235 unsigned char *ptr = buffer; 226 unsigned char *ptr = buffer;
236 unsigned char operand; 227 unsigned char operand;
237 i = blockno / 8; 228 i = blockno / 8;
238 remainder = blockno % 8; 229 remainder = blockno % 8;
239 int blocksize = EXT2_BLOCK_SIZE(ext4fs_root); 230 int blocksize = EXT2_BLOCK_SIZE(ext4fs_root);
240 231
241 i = i - (index * blocksize); 232 i = i - (index * blocksize);
242 if (blocksize != 1024) { 233 if (blocksize != 1024) {
243 ptr = ptr + i; 234 ptr = ptr + i;
244 operand = (1 << remainder); 235 operand = (1 << remainder);
245 status = *ptr & operand; 236 status = *ptr & operand;
246 if (status) 237 if (status)
247 *ptr = *ptr & ~(operand); 238 *ptr = *ptr & ~(operand);
248 } else { 239 } else {
249 if (remainder == 0) { 240 if (remainder == 0) {
250 ptr = ptr + i - 1; 241 ptr = ptr + i - 1;
251 operand = (1 << 7); 242 operand = (1 << 7);
252 } else { 243 } else {
253 ptr = ptr + i; 244 ptr = ptr + i;
254 operand = (1 << (remainder - 1)); 245 operand = (1 << (remainder - 1));
255 } 246 }
256 status = *ptr & operand; 247 status = *ptr & operand;
257 if (status) 248 if (status)
258 *ptr = *ptr & ~(operand); 249 *ptr = *ptr & ~(operand);
259 } 250 }
260 } 251 }
261 252
262 int ext4fs_set_inode_bmap(int inode_no, unsigned char *buffer, int index) 253 int ext4fs_set_inode_bmap(int inode_no, unsigned char *buffer, int index)
263 { 254 {
264 int i, remainder, status; 255 int i, remainder, status;
265 unsigned char *ptr = buffer; 256 unsigned char *ptr = buffer;
266 unsigned char operand; 257 unsigned char operand;
267 258
268 inode_no -= (index * ext4fs_root->sblock.inodes_per_group); 259 inode_no -= (index * ext4fs_root->sblock.inodes_per_group);
269 i = inode_no / 8; 260 i = inode_no / 8;
270 remainder = inode_no % 8; 261 remainder = inode_no % 8;
271 if (remainder == 0) { 262 if (remainder == 0) {
272 ptr = ptr + i - 1; 263 ptr = ptr + i - 1;
273 operand = (1 << 7); 264 operand = (1 << 7);
274 } else { 265 } else {
275 ptr = ptr + i; 266 ptr = ptr + i;
276 operand = (1 << (remainder - 1)); 267 operand = (1 << (remainder - 1));
277 } 268 }
278 status = *ptr & operand; 269 status = *ptr & operand;
279 if (status) 270 if (status)
280 return -1; 271 return -1;
281 272
282 *ptr = *ptr | operand; 273 *ptr = *ptr | operand;
283 274
284 return 0; 275 return 0;
285 } 276 }
286 277
287 void ext4fs_reset_inode_bmap(int inode_no, unsigned char *buffer, int index) 278 void ext4fs_reset_inode_bmap(int inode_no, unsigned char *buffer, int index)
288 { 279 {
289 int i, remainder, status; 280 int i, remainder, status;
290 unsigned char *ptr = buffer; 281 unsigned char *ptr = buffer;
291 unsigned char operand; 282 unsigned char operand;
292 283
293 inode_no -= (index * ext4fs_root->sblock.inodes_per_group); 284 inode_no -= (index * ext4fs_root->sblock.inodes_per_group);
294 i = inode_no / 8; 285 i = inode_no / 8;
295 remainder = inode_no % 8; 286 remainder = inode_no % 8;
296 if (remainder == 0) { 287 if (remainder == 0) {
297 ptr = ptr + i - 1; 288 ptr = ptr + i - 1;
298 operand = (1 << 7); 289 operand = (1 << 7);
299 } else { 290 } else {
300 ptr = ptr + i; 291 ptr = ptr + i;
301 operand = (1 << (remainder - 1)); 292 operand = (1 << (remainder - 1));
302 } 293 }
303 status = *ptr & operand; 294 status = *ptr & operand;
304 if (status) 295 if (status)
305 *ptr = *ptr & ~(operand); 296 *ptr = *ptr & ~(operand);
306 } 297 }
307 298
308 int ext4fs_checksum_update(unsigned int i) 299 int ext4fs_checksum_update(unsigned int i)
309 { 300 {
310 struct ext2_block_group *desc; 301 struct ext2_block_group *desc;
311 struct ext_filesystem *fs = get_fs(); 302 struct ext_filesystem *fs = get_fs();
312 __u16 crc = 0; 303 __u16 crc = 0;
313 304
314 desc = (struct ext2_block_group *)&fs->bgd[i]; 305 desc = (struct ext2_block_group *)&fs->bgd[i];
315 if (fs->sb->feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) { 306 if (fs->sb->feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) {
316 int offset = offsetof(struct ext2_block_group, bg_checksum); 307 int offset = offsetof(struct ext2_block_group, bg_checksum);
317 308
318 crc = ext2fs_crc16(~0, fs->sb->unique_id, 309 crc = ext2fs_crc16(~0, fs->sb->unique_id,
319 sizeof(fs->sb->unique_id)); 310 sizeof(fs->sb->unique_id));
320 crc = ext2fs_crc16(crc, &i, sizeof(i)); 311 crc = ext2fs_crc16(crc, &i, sizeof(i));
321 crc = ext2fs_crc16(crc, desc, offset); 312 crc = ext2fs_crc16(crc, desc, offset);
322 offset += sizeof(desc->bg_checksum); /* skip checksum */ 313 offset += sizeof(desc->bg_checksum); /* skip checksum */
323 assert(offset == sizeof(*desc)); 314 assert(offset == sizeof(*desc));
324 } 315 }
325 316
326 return crc; 317 return crc;
327 } 318 }
328 319
329 static int check_void_in_dentry(struct ext2_dirent *dir, char *filename) 320 static int check_void_in_dentry(struct ext2_dirent *dir, char *filename)
330 { 321 {
331 int dentry_length; 322 int dentry_length;
332 int sizeof_void_space; 323 int sizeof_void_space;
333 int new_entry_byte_reqd; 324 int new_entry_byte_reqd;
334 short padding_factor = 0; 325 short padding_factor = 0;
335 326
336 if (dir->namelen % 4 != 0) 327 if (dir->namelen % 4 != 0)
337 padding_factor = 4 - (dir->namelen % 4); 328 padding_factor = 4 - (dir->namelen % 4);
338 329
339 dentry_length = sizeof(struct ext2_dirent) + 330 dentry_length = sizeof(struct ext2_dirent) +
340 dir->namelen + padding_factor; 331 dir->namelen + padding_factor;
341 sizeof_void_space = dir->direntlen - dentry_length; 332 sizeof_void_space = dir->direntlen - dentry_length;
342 if (sizeof_void_space == 0) 333 if (sizeof_void_space == 0)
343 return 0; 334 return 0;
344 335
345 padding_factor = 0; 336 padding_factor = 0;
346 if (strlen(filename) % 4 != 0) 337 if (strlen(filename) % 4 != 0)
347 padding_factor = 4 - (strlen(filename) % 4); 338 padding_factor = 4 - (strlen(filename) % 4);
348 339
349 new_entry_byte_reqd = strlen(filename) + 340 new_entry_byte_reqd = strlen(filename) +
350 sizeof(struct ext2_dirent) + padding_factor; 341 sizeof(struct ext2_dirent) + padding_factor;
351 if (sizeof_void_space >= new_entry_byte_reqd) { 342 if (sizeof_void_space >= new_entry_byte_reqd) {
352 dir->direntlen = dentry_length; 343 dir->direntlen = dentry_length;
353 return sizeof_void_space; 344 return sizeof_void_space;
354 } 345 }
355 346
356 return 0; 347 return 0;
357 } 348 }
358 349
359 void ext4fs_update_parent_dentry(char *filename, int *p_ino, int file_type) 350 void ext4fs_update_parent_dentry(char *filename, int *p_ino, int file_type)
360 { 351 {
361 unsigned int *zero_buffer = NULL; 352 unsigned int *zero_buffer = NULL;
362 char *root_first_block_buffer = NULL; 353 char *root_first_block_buffer = NULL;
363 int direct_blk_idx; 354 int direct_blk_idx;
364 long int root_blknr; 355 long int root_blknr;
365 long int first_block_no_of_root = 0; 356 long int first_block_no_of_root = 0;
366 long int previous_blknr = -1; 357 long int previous_blknr = -1;
367 int totalbytes = 0; 358 int totalbytes = 0;
368 short int padding_factor = 0; 359 short int padding_factor = 0;
369 unsigned int new_entry_byte_reqd; 360 unsigned int new_entry_byte_reqd;
370 unsigned int last_entry_dirlen; 361 unsigned int last_entry_dirlen;
371 int sizeof_void_space = 0; 362 int sizeof_void_space = 0;
372 int templength = 0; 363 int templength = 0;
373 int inodeno; 364 int inodeno;
374 int status; 365 int status;
375 struct ext_filesystem *fs = get_fs(); 366 struct ext_filesystem *fs = get_fs();
376 /* directory entry */ 367 /* directory entry */
377 struct ext2_dirent *dir; 368 struct ext2_dirent *dir;
378 char *temp_dir = NULL; 369 char *temp_dir = NULL;
379 370
380 zero_buffer = zalloc(fs->blksz); 371 zero_buffer = zalloc(fs->blksz);
381 if (!zero_buffer) { 372 if (!zero_buffer) {
382 printf("No Memory\n"); 373 printf("No Memory\n");
383 return; 374 return;
384 } 375 }
385 root_first_block_buffer = zalloc(fs->blksz); 376 root_first_block_buffer = zalloc(fs->blksz);
386 if (!root_first_block_buffer) { 377 if (!root_first_block_buffer) {
387 free(zero_buffer); 378 free(zero_buffer);
388 printf("No Memory\n"); 379 printf("No Memory\n");
389 return; 380 return;
390 } 381 }
391 restart: 382 restart:
392 383
393 /* read the block no allocated to a file */ 384 /* read the block no allocated to a file */
394 for (direct_blk_idx = 0; direct_blk_idx < INDIRECT_BLOCKS; 385 for (direct_blk_idx = 0; direct_blk_idx < INDIRECT_BLOCKS;
395 direct_blk_idx++) { 386 direct_blk_idx++) {
396 root_blknr = read_allocated_block(g_parent_inode, 387 root_blknr = read_allocated_block(g_parent_inode,
397 direct_blk_idx); 388 direct_blk_idx);
398 if (root_blknr == 0) { 389 if (root_blknr == 0) {
399 first_block_no_of_root = previous_blknr; 390 first_block_no_of_root = previous_blknr;
400 break; 391 break;
401 } 392 }
402 previous_blknr = root_blknr; 393 previous_blknr = root_blknr;
403 } 394 }
404 395
405 status = ext4fs_devread((lbaint_t)first_block_no_of_root 396 status = ext4fs_devread((lbaint_t)first_block_no_of_root
406 * fs->sect_perblk, 397 * fs->sect_perblk,
407 0, fs->blksz, root_first_block_buffer); 398 0, fs->blksz, root_first_block_buffer);
408 if (status == 0) 399 if (status == 0)
409 goto fail; 400 goto fail;
410 401
411 if (ext4fs_log_journal(root_first_block_buffer, first_block_no_of_root)) 402 if (ext4fs_log_journal(root_first_block_buffer, first_block_no_of_root))
412 goto fail; 403 goto fail;
413 dir = (struct ext2_dirent *)root_first_block_buffer; 404 dir = (struct ext2_dirent *)root_first_block_buffer;
414 totalbytes = 0; 405 totalbytes = 0;
415 while (dir->direntlen > 0) { 406 while (dir->direntlen > 0) {
416 /* 407 /*
417 * blocksize-totalbytes because last directory length 408 * blocksize-totalbytes because last directory length
418 * i.e. dir->direntlen is free availble space in the 409 * i.e. dir->direntlen is free availble space in the
419 * block that means it is a last entry of directory 410 * block that means it is a last entry of directory
420 * entry 411 * entry
421 */ 412 */
422 413
423 /* traversing the each directory entry */ 414 /* traversing the each directory entry */
424 if (fs->blksz - totalbytes == dir->direntlen) { 415 if (fs->blksz - totalbytes == dir->direntlen) {
425 if (strlen(filename) % 4 != 0) 416 if (strlen(filename) % 4 != 0)
426 padding_factor = 4 - (strlen(filename) % 4); 417 padding_factor = 4 - (strlen(filename) % 4);
427 418
428 new_entry_byte_reqd = strlen(filename) + 419 new_entry_byte_reqd = strlen(filename) +
429 sizeof(struct ext2_dirent) + padding_factor; 420 sizeof(struct ext2_dirent) + padding_factor;
430 padding_factor = 0; 421 padding_factor = 0;
431 /* 422 /*
432 * update last directory entry length to its 423 * update last directory entry length to its
433 * length because we are creating new directory 424 * length because we are creating new directory
434 * entry 425 * entry
435 */ 426 */
436 if (dir->namelen % 4 != 0) 427 if (dir->namelen % 4 != 0)
437 padding_factor = 4 - (dir->namelen % 4); 428 padding_factor = 4 - (dir->namelen % 4);
438 429
439 last_entry_dirlen = dir->namelen + 430 last_entry_dirlen = dir->namelen +
440 sizeof(struct ext2_dirent) + padding_factor; 431 sizeof(struct ext2_dirent) + padding_factor;
441 if ((fs->blksz - totalbytes - last_entry_dirlen) < 432 if ((fs->blksz - totalbytes - last_entry_dirlen) <
442 new_entry_byte_reqd) { 433 new_entry_byte_reqd) {
443 printf("1st Block Full:Allocate new block\n"); 434 printf("1st Block Full:Allocate new block\n");
444 435
445 if (direct_blk_idx == INDIRECT_BLOCKS - 1) { 436 if (direct_blk_idx == INDIRECT_BLOCKS - 1) {
446 printf("Directory exceeds limit\n"); 437 printf("Directory exceeds limit\n");
447 goto fail; 438 goto fail;
448 } 439 }
449 g_parent_inode->b.blocks.dir_blocks 440 g_parent_inode->b.blocks.dir_blocks
450 [direct_blk_idx] = ext4fs_get_new_blk_no(); 441 [direct_blk_idx] = ext4fs_get_new_blk_no();
451 if (g_parent_inode->b.blocks.dir_blocks 442 if (g_parent_inode->b.blocks.dir_blocks
452 [direct_blk_idx] == -1) { 443 [direct_blk_idx] == -1) {
453 printf("no block left to assign\n"); 444 printf("no block left to assign\n");
454 goto fail; 445 goto fail;
455 } 446 }
456 put_ext4(((uint64_t) 447 put_ext4(((uint64_t)
457 ((uint64_t)g_parent_inode->b. 448 ((uint64_t)g_parent_inode->b.
458 blocks.dir_blocks[direct_blk_idx] * 449 blocks.dir_blocks[direct_blk_idx] *
459 (uint64_t)fs->blksz)), zero_buffer, fs->blksz); 450 (uint64_t)fs->blksz)), zero_buffer, fs->blksz);
460 g_parent_inode->size = 451 g_parent_inode->size =
461 g_parent_inode->size + fs->blksz; 452 g_parent_inode->size + fs->blksz;
462 g_parent_inode->blockcnt = 453 g_parent_inode->blockcnt =
463 g_parent_inode->blockcnt + fs->sect_perblk; 454 g_parent_inode->blockcnt + fs->sect_perblk;
464 if (ext4fs_put_metadata 455 if (ext4fs_put_metadata
465 (root_first_block_buffer, 456 (root_first_block_buffer,
466 first_block_no_of_root)) 457 first_block_no_of_root))
467 goto fail; 458 goto fail;
468 goto restart; 459 goto restart;
469 } 460 }
470 dir->direntlen = last_entry_dirlen; 461 dir->direntlen = last_entry_dirlen;
471 break; 462 break;
472 } 463 }
473 464
474 templength = dir->direntlen; 465 templength = dir->direntlen;
475 totalbytes = totalbytes + templength; 466 totalbytes = totalbytes + templength;
476 sizeof_void_space = check_void_in_dentry(dir, filename); 467 sizeof_void_space = check_void_in_dentry(dir, filename);
477 if (sizeof_void_space) 468 if (sizeof_void_space)
478 break; 469 break;
479 470
480 dir = (struct ext2_dirent *)((char *)dir + templength); 471 dir = (struct ext2_dirent *)((char *)dir + templength);
481 } 472 }
482 473
483 /* make a pointer ready for creating next directory entry */ 474 /* make a pointer ready for creating next directory entry */
484 templength = dir->direntlen; 475 templength = dir->direntlen;
485 totalbytes = totalbytes + templength; 476 totalbytes = totalbytes + templength;
486 dir = (struct ext2_dirent *)((char *)dir + templength); 477 dir = (struct ext2_dirent *)((char *)dir + templength);
487 478
488 /* get the next available inode number */ 479 /* get the next available inode number */
489 inodeno = ext4fs_get_new_inode_no(); 480 inodeno = ext4fs_get_new_inode_no();
490 if (inodeno == -1) { 481 if (inodeno == -1) {
491 printf("no inode left to assign\n"); 482 printf("no inode left to assign\n");
492 goto fail; 483 goto fail;
493 } 484 }
494 dir->inode = inodeno; 485 dir->inode = inodeno;
495 if (sizeof_void_space) 486 if (sizeof_void_space)
496 dir->direntlen = sizeof_void_space; 487 dir->direntlen = sizeof_void_space;
497 else 488 else
498 dir->direntlen = fs->blksz - totalbytes; 489 dir->direntlen = fs->blksz - totalbytes;
499 490
500 dir->namelen = strlen(filename); 491 dir->namelen = strlen(filename);
501 dir->filetype = FILETYPE_REG; /* regular file */ 492 dir->filetype = FILETYPE_REG; /* regular file */
502 temp_dir = (char *)dir; 493 temp_dir = (char *)dir;
503 temp_dir = temp_dir + sizeof(struct ext2_dirent); 494 temp_dir = temp_dir + sizeof(struct ext2_dirent);
504 memcpy(temp_dir, filename, strlen(filename)); 495 memcpy(temp_dir, filename, strlen(filename));
505 496
506 *p_ino = inodeno; 497 *p_ino = inodeno;
507 498
508 /* update or write the 1st block of root inode */ 499 /* update or write the 1st block of root inode */
509 if (ext4fs_put_metadata(root_first_block_buffer, 500 if (ext4fs_put_metadata(root_first_block_buffer,
510 first_block_no_of_root)) 501 first_block_no_of_root))
511 goto fail; 502 goto fail;
512 503
513 fail: 504 fail:
514 free(zero_buffer); 505 free(zero_buffer);
515 free(root_first_block_buffer); 506 free(root_first_block_buffer);
516 } 507 }
517 508
518 static int search_dir(struct ext2_inode *parent_inode, char *dirname) 509 static int search_dir(struct ext2_inode *parent_inode, char *dirname)
519 { 510 {
520 int status; 511 int status;
521 int inodeno; 512 int inodeno;
522 int totalbytes; 513 int totalbytes;
523 int templength; 514 int templength;
524 int direct_blk_idx; 515 int direct_blk_idx;
525 long int blknr; 516 long int blknr;
526 int found = 0; 517 int found = 0;
527 char *ptr = NULL; 518 char *ptr = NULL;
528 unsigned char *block_buffer = NULL; 519 unsigned char *block_buffer = NULL;
529 struct ext2_dirent *dir = NULL; 520 struct ext2_dirent *dir = NULL;
530 struct ext2_dirent *previous_dir = NULL; 521 struct ext2_dirent *previous_dir = NULL;
531 struct ext_filesystem *fs = get_fs(); 522 struct ext_filesystem *fs = get_fs();
532 523
533 /* read the block no allocated to a file */ 524 /* read the block no allocated to a file */
534 for (direct_blk_idx = 0; direct_blk_idx < INDIRECT_BLOCKS; 525 for (direct_blk_idx = 0; direct_blk_idx < INDIRECT_BLOCKS;
535 direct_blk_idx++) { 526 direct_blk_idx++) {
536 blknr = read_allocated_block(parent_inode, direct_blk_idx); 527 blknr = read_allocated_block(parent_inode, direct_blk_idx);
537 if (blknr == 0) 528 if (blknr == 0)
538 goto fail; 529 goto fail;
539 530
540 /* read the blocks of parenet inode */ 531 /* read the blocks of parenet inode */
541 block_buffer = zalloc(fs->blksz); 532 block_buffer = zalloc(fs->blksz);
542 if (!block_buffer) 533 if (!block_buffer)
543 goto fail; 534 goto fail;
544 535
545 status = ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 536 status = ext4fs_devread((lbaint_t)blknr * fs->sect_perblk,
546 0, fs->blksz, (char *)block_buffer); 537 0, fs->blksz, (char *)block_buffer);
547 if (status == 0) 538 if (status == 0)
548 goto fail; 539 goto fail;
549 540
550 dir = (struct ext2_dirent *)block_buffer; 541 dir = (struct ext2_dirent *)block_buffer;
551 ptr = (char *)dir; 542 ptr = (char *)dir;
552 totalbytes = 0; 543 totalbytes = 0;
553 while (dir->direntlen >= 0) { 544 while (dir->direntlen >= 0) {
554 /* 545 /*
555 * blocksize-totalbytes because last directory 546 * blocksize-totalbytes because last directory
556 * length i.e.,*dir->direntlen is free availble 547 * length i.e.,*dir->direntlen is free availble
557 * space in the block that means 548 * space in the block that means
558 * it is a last entry of directory entry 549 * it is a last entry of directory entry
559 */ 550 */
560 if (strlen(dirname) == dir->namelen) { 551 if (strlen(dirname) == dir->namelen) {
561 if (strncmp(dirname, ptr + 552 if (strncmp(dirname, ptr +
562 sizeof(struct ext2_dirent), 553 sizeof(struct ext2_dirent),
563 dir->namelen) == 0) { 554 dir->namelen) == 0) {
564 previous_dir->direntlen += 555 previous_dir->direntlen +=
565 dir->direntlen; 556 dir->direntlen;
566 inodeno = dir->inode; 557 inodeno = dir->inode;
567 dir->inode = 0; 558 dir->inode = 0;
568 found = 1; 559 found = 1;
569 break; 560 break;
570 } 561 }
571 } 562 }
572 563
573 if (fs->blksz - totalbytes == dir->direntlen) 564 if (fs->blksz - totalbytes == dir->direntlen)
574 break; 565 break;
575 566
576 /* traversing the each directory entry */ 567 /* traversing the each directory entry */
577 templength = dir->direntlen; 568 templength = dir->direntlen;
578 totalbytes = totalbytes + templength; 569 totalbytes = totalbytes + templength;
579 previous_dir = dir; 570 previous_dir = dir;
580 dir = (struct ext2_dirent *)((char *)dir + templength); 571 dir = (struct ext2_dirent *)((char *)dir + templength);
581 ptr = (char *)dir; 572 ptr = (char *)dir;
582 } 573 }
583 574
584 if (found == 1) { 575 if (found == 1) {
585 free(block_buffer); 576 free(block_buffer);
586 block_buffer = NULL; 577 block_buffer = NULL;
587 return inodeno; 578 return inodeno;
588 } 579 }
589 580
590 free(block_buffer); 581 free(block_buffer);
591 block_buffer = NULL; 582 block_buffer = NULL;
592 } 583 }
593 584
594 fail: 585 fail:
595 free(block_buffer); 586 free(block_buffer);
596 587
597 return -1; 588 return -1;
598 } 589 }
599 590
600 static int find_dir_depth(char *dirname) 591 static int find_dir_depth(char *dirname)
601 { 592 {
602 char *token = strtok(dirname, "/"); 593 char *token = strtok(dirname, "/");
603 int count = 0; 594 int count = 0;
604 while (token != NULL) { 595 while (token != NULL) {
605 token = strtok(NULL, "/"); 596 token = strtok(NULL, "/");
606 count++; 597 count++;
607 } 598 }
608 return count + 1 + 1; 599 return count + 1 + 1;
609 /* 600 /*
610 * for example for string /home/temp 601 * for example for string /home/temp
611 * depth=home(1)+temp(1)+1 extra for NULL; 602 * depth=home(1)+temp(1)+1 extra for NULL;
612 * so count is 4; 603 * so count is 4;
613 */ 604 */
614 } 605 }
615 606
616 static int parse_path(char **arr, char *dirname) 607 static int parse_path(char **arr, char *dirname)
617 { 608 {
618 char *token = strtok(dirname, "/"); 609 char *token = strtok(dirname, "/");
619 int i = 0; 610 int i = 0;
620 611
621 /* add root */ 612 /* add root */
622 arr[i] = zalloc(strlen("/") + 1); 613 arr[i] = zalloc(strlen("/") + 1);
623 if (!arr[i]) 614 if (!arr[i])
624 return -ENOMEM; 615 return -ENOMEM;
625 616
626 arr[i++] = "/"; 617 arr[i++] = "/";
627 618
628 /* add each path entry after root */ 619 /* add each path entry after root */
629 while (token != NULL) { 620 while (token != NULL) {
630 arr[i] = zalloc(strlen(token) + 1); 621 arr[i] = zalloc(strlen(token) + 1);
631 if (!arr[i]) 622 if (!arr[i])
632 return -ENOMEM; 623 return -ENOMEM;
633 memcpy(arr[i++], token, strlen(token)); 624 memcpy(arr[i++], token, strlen(token));
634 token = strtok(NULL, "/"); 625 token = strtok(NULL, "/");
635 } 626 }
636 arr[i] = NULL; 627 arr[i] = NULL;
637 628
638 return 0; 629 return 0;
639 } 630 }
640 631
641 int ext4fs_iget(int inode_no, struct ext2_inode *inode) 632 int ext4fs_iget(int inode_no, struct ext2_inode *inode)
642 { 633 {
643 if (ext4fs_read_inode(ext4fs_root, inode_no, inode) == 0) 634 if (ext4fs_read_inode(ext4fs_root, inode_no, inode) == 0)
644 return -1; 635 return -1;
645 636
646 return 0; 637 return 0;
647 } 638 }
648 639
649 /* 640 /*
650 * Function: ext4fs_get_parent_inode_num 641 * Function: ext4fs_get_parent_inode_num
651 * Return Value: inode Number of the parent directory of file/Directory to be 642 * Return Value: inode Number of the parent directory of file/Directory to be
652 * created 643 * created
653 * dirname : Input parmater, input path name of the file/directory to be created 644 * dirname : Input parmater, input path name of the file/directory to be created
654 * dname : Output parameter, to be filled with the name of the directory 645 * dname : Output parameter, to be filled with the name of the directory
655 * extracted from dirname 646 * extracted from dirname
656 */ 647 */
657 int ext4fs_get_parent_inode_num(const char *dirname, char *dname, int flags) 648 int ext4fs_get_parent_inode_num(const char *dirname, char *dname, int flags)
658 { 649 {
659 int i; 650 int i;
660 int depth = 0; 651 int depth = 0;
661 int matched_inode_no; 652 int matched_inode_no;
662 int result_inode_no = -1; 653 int result_inode_no = -1;
663 char **ptr = NULL; 654 char **ptr = NULL;
664 char *depth_dirname = NULL; 655 char *depth_dirname = NULL;
665 char *parse_dirname = NULL; 656 char *parse_dirname = NULL;
666 struct ext2_inode *parent_inode = NULL; 657 struct ext2_inode *parent_inode = NULL;
667 struct ext2_inode *first_inode = NULL; 658 struct ext2_inode *first_inode = NULL;
668 struct ext2_inode temp_inode; 659 struct ext2_inode temp_inode;
669 660
670 if (*dirname != '/') { 661 if (*dirname != '/') {
671 printf("Please supply Absolute path\n"); 662 printf("Please supply Absolute path\n");
672 return -1; 663 return -1;
673 } 664 }
674 665
675 /* TODO: input validation make equivalent to linux */ 666 /* TODO: input validation make equivalent to linux */
676 depth_dirname = zalloc(strlen(dirname) + 1); 667 depth_dirname = zalloc(strlen(dirname) + 1);
677 if (!depth_dirname) 668 if (!depth_dirname)
678 return -ENOMEM; 669 return -ENOMEM;
679 670
680 memcpy(depth_dirname, dirname, strlen(dirname)); 671 memcpy(depth_dirname, dirname, strlen(dirname));
681 depth = find_dir_depth(depth_dirname); 672 depth = find_dir_depth(depth_dirname);
682 parse_dirname = zalloc(strlen(dirname) + 1); 673 parse_dirname = zalloc(strlen(dirname) + 1);
683 if (!parse_dirname) 674 if (!parse_dirname)
684 goto fail; 675 goto fail;
685 memcpy(parse_dirname, dirname, strlen(dirname)); 676 memcpy(parse_dirname, dirname, strlen(dirname));
686 677
687 /* allocate memory for each directory level */ 678 /* allocate memory for each directory level */
688 ptr = zalloc((depth) * sizeof(char *)); 679 ptr = zalloc((depth) * sizeof(char *));
689 if (!ptr) 680 if (!ptr)
690 goto fail; 681 goto fail;
691 if (parse_path(ptr, parse_dirname)) 682 if (parse_path(ptr, parse_dirname))
692 goto fail; 683 goto fail;
693 parent_inode = zalloc(sizeof(struct ext2_inode)); 684 parent_inode = zalloc(sizeof(struct ext2_inode));
694 if (!parent_inode) 685 if (!parent_inode)
695 goto fail; 686 goto fail;
696 first_inode = zalloc(sizeof(struct ext2_inode)); 687 first_inode = zalloc(sizeof(struct ext2_inode));
697 if (!first_inode) 688 if (!first_inode)
698 goto fail; 689 goto fail;
699 memcpy(parent_inode, ext4fs_root->inode, sizeof(struct ext2_inode)); 690 memcpy(parent_inode, ext4fs_root->inode, sizeof(struct ext2_inode));
700 memcpy(first_inode, parent_inode, sizeof(struct ext2_inode)); 691 memcpy(first_inode, parent_inode, sizeof(struct ext2_inode));
701 if (flags & F_FILE) 692 if (flags & F_FILE)
702 result_inode_no = EXT2_ROOT_INO; 693 result_inode_no = EXT2_ROOT_INO;
703 for (i = 1; i < depth; i++) { 694 for (i = 1; i < depth; i++) {
704 matched_inode_no = search_dir(parent_inode, ptr[i]); 695 matched_inode_no = search_dir(parent_inode, ptr[i]);
705 if (matched_inode_no == -1) { 696 if (matched_inode_no == -1) {
706 if (ptr[i + 1] == NULL && i == 1) { 697 if (ptr[i + 1] == NULL && i == 1) {
707 result_inode_no = EXT2_ROOT_INO; 698 result_inode_no = EXT2_ROOT_INO;
708 goto end; 699 goto end;
709 } else { 700 } else {
710 if (ptr[i + 1] == NULL) 701 if (ptr[i + 1] == NULL)
711 break; 702 break;
712 printf("Invalid path\n"); 703 printf("Invalid path\n");
713 result_inode_no = -1; 704 result_inode_no = -1;
714 goto fail; 705 goto fail;
715 } 706 }
716 } else { 707 } else {
717 if (ptr[i + 1] != NULL) { 708 if (ptr[i + 1] != NULL) {
718 memset(parent_inode, '\0', 709 memset(parent_inode, '\0',
719 sizeof(struct ext2_inode)); 710 sizeof(struct ext2_inode));
720 if (ext4fs_iget(matched_inode_no, 711 if (ext4fs_iget(matched_inode_no,
721 parent_inode)) { 712 parent_inode)) {
722 result_inode_no = -1; 713 result_inode_no = -1;
723 goto fail; 714 goto fail;
724 } 715 }
725 result_inode_no = matched_inode_no; 716 result_inode_no = matched_inode_no;
726 } else { 717 } else {
727 break; 718 break;
728 } 719 }
729 } 720 }
730 } 721 }
731 722
732 end: 723 end:
733 if (i == 1) 724 if (i == 1)
734 matched_inode_no = search_dir(first_inode, ptr[i]); 725 matched_inode_no = search_dir(first_inode, ptr[i]);
735 else 726 else
736 matched_inode_no = search_dir(parent_inode, ptr[i]); 727 matched_inode_no = search_dir(parent_inode, ptr[i]);
737 728
738 if (matched_inode_no != -1) { 729 if (matched_inode_no != -1) {
739 ext4fs_iget(matched_inode_no, &temp_inode); 730 ext4fs_iget(matched_inode_no, &temp_inode);
740 if (temp_inode.mode & S_IFDIR) { 731 if (temp_inode.mode & S_IFDIR) {
741 printf("It is a Directory\n"); 732 printf("It is a Directory\n");
742 result_inode_no = -1; 733 result_inode_no = -1;
743 goto fail; 734 goto fail;
744 } 735 }
745 } 736 }
746 737
747 if (strlen(ptr[i]) > 256) { 738 if (strlen(ptr[i]) > 256) {
748 result_inode_no = -1; 739 result_inode_no = -1;
749 goto fail; 740 goto fail;
750 } 741 }
751 memcpy(dname, ptr[i], strlen(ptr[i])); 742 memcpy(dname, ptr[i], strlen(ptr[i]));
752 743
753 fail: 744 fail:
754 free(depth_dirname); 745 free(depth_dirname);
755 free(parse_dirname); 746 free(parse_dirname);
756 free(ptr); 747 free(ptr);
757 free(parent_inode); 748 free(parent_inode);
758 free(first_inode); 749 free(first_inode);
759 750
760 return result_inode_no; 751 return result_inode_no;
761 } 752 }
762 753
763 static int check_filename(char *filename, unsigned int blknr) 754 static int check_filename(char *filename, unsigned int blknr)
764 { 755 {
765 unsigned int first_block_no_of_root; 756 unsigned int first_block_no_of_root;
766 int totalbytes = 0; 757 int totalbytes = 0;
767 int templength = 0; 758 int templength = 0;
768 int status, inodeno; 759 int status, inodeno;
769 int found = 0; 760 int found = 0;
770 char *root_first_block_buffer = NULL; 761 char *root_first_block_buffer = NULL;
771 char *root_first_block_addr = NULL; 762 char *root_first_block_addr = NULL;
772 struct ext2_dirent *dir = NULL; 763 struct ext2_dirent *dir = NULL;
773 struct ext2_dirent *previous_dir = NULL; 764 struct ext2_dirent *previous_dir = NULL;
774 char *ptr = NULL; 765 char *ptr = NULL;
775 struct ext_filesystem *fs = get_fs(); 766 struct ext_filesystem *fs = get_fs();
776 767
777 /* get the first block of root */ 768 /* get the first block of root */
778 first_block_no_of_root = blknr; 769 first_block_no_of_root = blknr;
779 root_first_block_buffer = zalloc(fs->blksz); 770 root_first_block_buffer = zalloc(fs->blksz);
780 if (!root_first_block_buffer) 771 if (!root_first_block_buffer)
781 return -ENOMEM; 772 return -ENOMEM;
782 root_first_block_addr = root_first_block_buffer; 773 root_first_block_addr = root_first_block_buffer;
783 status = ext4fs_devread((lbaint_t)first_block_no_of_root * 774 status = ext4fs_devread((lbaint_t)first_block_no_of_root *
784 fs->sect_perblk, 0, 775 fs->sect_perblk, 0,
785 fs->blksz, root_first_block_buffer); 776 fs->blksz, root_first_block_buffer);
786 if (status == 0) 777 if (status == 0)
787 goto fail; 778 goto fail;
788 779
789 if (ext4fs_log_journal(root_first_block_buffer, first_block_no_of_root)) 780 if (ext4fs_log_journal(root_first_block_buffer, first_block_no_of_root))
790 goto fail; 781 goto fail;
791 dir = (struct ext2_dirent *)root_first_block_buffer; 782 dir = (struct ext2_dirent *)root_first_block_buffer;
792 ptr = (char *)dir; 783 ptr = (char *)dir;
793 totalbytes = 0; 784 totalbytes = 0;
794 while (dir->direntlen >= 0) { 785 while (dir->direntlen >= 0) {
795 /* 786 /*
796 * blocksize-totalbytes because last 787 * blocksize-totalbytes because last
797 * directory length i.e., *dir->direntlen 788 * directory length i.e., *dir->direntlen
798 * is free availble space in the block that 789 * is free availble space in the block that
799 * means it is a last entry of directory entry 790 * means it is a last entry of directory entry
800 */ 791 */
801 if (strlen(filename) == dir->namelen) { 792 if (strlen(filename) == dir->namelen) {
802 if (strncmp(filename, ptr + sizeof(struct ext2_dirent), 793 if (strncmp(filename, ptr + sizeof(struct ext2_dirent),
803 dir->namelen) == 0) { 794 dir->namelen) == 0) {
804 printf("file found deleting\n"); 795 printf("file found deleting\n");
805 previous_dir->direntlen += dir->direntlen; 796 previous_dir->direntlen += dir->direntlen;
806 inodeno = dir->inode; 797 inodeno = dir->inode;
807 dir->inode = 0; 798 dir->inode = 0;
808 found = 1; 799 found = 1;
809 break; 800 break;
810 } 801 }
811 } 802 }
812 803
813 if (fs->blksz - totalbytes == dir->direntlen) 804 if (fs->blksz - totalbytes == dir->direntlen)
814 break; 805 break;
815 806
816 /* traversing the each directory entry */ 807 /* traversing the each directory entry */
817 templength = dir->direntlen; 808 templength = dir->direntlen;
818 totalbytes = totalbytes + templength; 809 totalbytes = totalbytes + templength;
819 previous_dir = dir; 810 previous_dir = dir;
820 dir = (struct ext2_dirent *)((char *)dir + templength); 811 dir = (struct ext2_dirent *)((char *)dir + templength);
821 ptr = (char *)dir; 812 ptr = (char *)dir;
822 } 813 }
823 814
824 815
825 if (found == 1) { 816 if (found == 1) {
826 if (ext4fs_put_metadata(root_first_block_addr, 817 if (ext4fs_put_metadata(root_first_block_addr,
827 first_block_no_of_root)) 818 first_block_no_of_root))
828 goto fail; 819 goto fail;
829 return inodeno; 820 return inodeno;
830 } 821 }
831 fail: 822 fail:
832 free(root_first_block_buffer); 823 free(root_first_block_buffer);
833 824
834 return -1; 825 return -1;
835 } 826 }
836 827
837 int ext4fs_filename_check(char *filename) 828 int ext4fs_filename_check(char *filename)
838 { 829 {
839 short direct_blk_idx = 0; 830 short direct_blk_idx = 0;
840 long int blknr = -1; 831 long int blknr = -1;
841 int inodeno = -1; 832 int inodeno = -1;
842 833
843 /* read the block no allocated to a file */ 834 /* read the block no allocated to a file */
844 for (direct_blk_idx = 0; direct_blk_idx < INDIRECT_BLOCKS; 835 for (direct_blk_idx = 0; direct_blk_idx < INDIRECT_BLOCKS;
845 direct_blk_idx++) { 836 direct_blk_idx++) {
846 blknr = read_allocated_block(g_parent_inode, direct_blk_idx); 837 blknr = read_allocated_block(g_parent_inode, direct_blk_idx);
847 if (blknr == 0) 838 if (blknr == 0)
848 break; 839 break;
849 inodeno = check_filename(filename, blknr); 840 inodeno = check_filename(filename, blknr);
850 if (inodeno != -1) 841 if (inodeno != -1)
851 return inodeno; 842 return inodeno;
852 } 843 }
853 844
854 return -1; 845 return -1;
855 } 846 }
856 847
857 long int ext4fs_get_new_blk_no(void) 848 long int ext4fs_get_new_blk_no(void)
858 { 849 {
859 short i; 850 short i;
860 short status; 851 short status;
861 int remainder; 852 int remainder;
862 unsigned int bg_idx; 853 unsigned int bg_idx;
863 static int prev_bg_bitmap_index = -1; 854 static int prev_bg_bitmap_index = -1;
864 unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group; 855 unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group;
865 struct ext_filesystem *fs = get_fs(); 856 struct ext_filesystem *fs = get_fs();
866 char *journal_buffer = zalloc(fs->blksz); 857 char *journal_buffer = zalloc(fs->blksz);
867 char *zero_buffer = zalloc(fs->blksz); 858 char *zero_buffer = zalloc(fs->blksz);
868 if (!journal_buffer || !zero_buffer) 859 if (!journal_buffer || !zero_buffer)
869 goto fail; 860 goto fail;
870 struct ext2_block_group *bgd = (struct ext2_block_group *)fs->gdtable; 861 struct ext2_block_group *bgd = (struct ext2_block_group *)fs->gdtable;
871 862
872 if (fs->first_pass_bbmap == 0) { 863 if (fs->first_pass_bbmap == 0) {
873 for (i = 0; i < fs->no_blkgrp; i++) { 864 for (i = 0; i < fs->no_blkgrp; i++) {
874 if (bgd[i].free_blocks) { 865 if (bgd[i].free_blocks) {
875 if (bgd[i].bg_flags & EXT4_BG_BLOCK_UNINIT) { 866 if (bgd[i].bg_flags & EXT4_BG_BLOCK_UNINIT) {
876 put_ext4(((uint64_t) ((uint64_t)bgd[i].block_id * 867 put_ext4(((uint64_t) ((uint64_t)bgd[i].block_id *
877 (uint64_t)fs->blksz)), 868 (uint64_t)fs->blksz)),
878 zero_buffer, fs->blksz); 869 zero_buffer, fs->blksz);
879 bgd[i].bg_flags = 870 bgd[i].bg_flags =
880 bgd[i]. 871 bgd[i].
881 bg_flags & ~EXT4_BG_BLOCK_UNINIT; 872 bg_flags & ~EXT4_BG_BLOCK_UNINIT;
882 memcpy(fs->blk_bmaps[i], zero_buffer, 873 memcpy(fs->blk_bmaps[i], zero_buffer,
883 fs->blksz); 874 fs->blksz);
884 } 875 }
885 fs->curr_blkno = 876 fs->curr_blkno =
886 _get_new_blk_no(fs->blk_bmaps[i]); 877 _get_new_blk_no(fs->blk_bmaps[i]);
887 if (fs->curr_blkno == -1) 878 if (fs->curr_blkno == -1)
888 /* if block bitmap is completely fill */ 879 /* if block bitmap is completely fill */
889 continue; 880 continue;
890 fs->curr_blkno = fs->curr_blkno + 881 fs->curr_blkno = fs->curr_blkno +
891 (i * fs->blksz * 8); 882 (i * fs->blksz * 8);
892 fs->first_pass_bbmap++; 883 fs->first_pass_bbmap++;
893 bgd[i].free_blocks--; 884 bgd[i].free_blocks--;
894 fs->sb->free_blocks--; 885 fs->sb->free_blocks--;
895 status = ext4fs_devread((lbaint_t) 886 status = ext4fs_devread((lbaint_t)
896 bgd[i].block_id * 887 bgd[i].block_id *
897 fs->sect_perblk, 0, 888 fs->sect_perblk, 0,
898 fs->blksz, 889 fs->blksz,
899 journal_buffer); 890 journal_buffer);
900 if (status == 0) 891 if (status == 0)
901 goto fail; 892 goto fail;
902 if (ext4fs_log_journal(journal_buffer, 893 if (ext4fs_log_journal(journal_buffer,
903 bgd[i].block_id)) 894 bgd[i].block_id))
904 goto fail; 895 goto fail;
905 goto success; 896 goto success;
906 } else { 897 } else {
907 debug("no space left on block group %d\n", i); 898 debug("no space left on block group %d\n", i);
908 } 899 }
909 } 900 }
910 901
911 goto fail; 902 goto fail;
912 } else { 903 } else {
913 restart: 904 restart:
914 fs->curr_blkno++; 905 fs->curr_blkno++;
915 /* get the blockbitmap index respective to blockno */ 906 /* get the blockbitmap index respective to blockno */
916 if (fs->blksz != 1024) { 907 if (fs->blksz != 1024) {
917 bg_idx = fs->curr_blkno / blk_per_grp; 908 bg_idx = fs->curr_blkno / blk_per_grp;
918 } else { 909 } else {
919 bg_idx = fs->curr_blkno / blk_per_grp; 910 bg_idx = fs->curr_blkno / blk_per_grp;
920 remainder = fs->curr_blkno % blk_per_grp; 911 remainder = fs->curr_blkno % blk_per_grp;
921 if (!remainder) 912 if (!remainder)
922 bg_idx--; 913 bg_idx--;
923 } 914 }
924 915
925 /* 916 /*
926 * To skip completely filled block group bitmaps 917 * To skip completely filled block group bitmaps
927 * Optimize the block allocation 918 * Optimize the block allocation
928 */ 919 */
929 if (bg_idx >= fs->no_blkgrp) 920 if (bg_idx >= fs->no_blkgrp)
930 goto fail; 921 goto fail;
931 922
932 if (bgd[bg_idx].free_blocks == 0) { 923 if (bgd[bg_idx].free_blocks == 0) {
933 debug("block group %u is full. Skipping\n", bg_idx); 924 debug("block group %u is full. Skipping\n", bg_idx);
934 fs->curr_blkno = fs->curr_blkno + blk_per_grp; 925 fs->curr_blkno = fs->curr_blkno + blk_per_grp;
935 fs->curr_blkno--; 926 fs->curr_blkno--;
936 goto restart; 927 goto restart;
937 } 928 }
938 929
939 if (bgd[bg_idx].bg_flags & EXT4_BG_BLOCK_UNINIT) { 930 if (bgd[bg_idx].bg_flags & EXT4_BG_BLOCK_UNINIT) {
940 memset(zero_buffer, '\0', fs->blksz); 931 memset(zero_buffer, '\0', fs->blksz);
941 put_ext4(((uint64_t) ((uint64_t)bgd[bg_idx].block_id * 932 put_ext4(((uint64_t) ((uint64_t)bgd[bg_idx].block_id *
942 (uint64_t)fs->blksz)), zero_buffer, fs->blksz); 933 (uint64_t)fs->blksz)), zero_buffer, fs->blksz);
943 memcpy(fs->blk_bmaps[bg_idx], zero_buffer, fs->blksz); 934 memcpy(fs->blk_bmaps[bg_idx], zero_buffer, fs->blksz);
944 bgd[bg_idx].bg_flags = bgd[bg_idx].bg_flags & 935 bgd[bg_idx].bg_flags = bgd[bg_idx].bg_flags &
945 ~EXT4_BG_BLOCK_UNINIT; 936 ~EXT4_BG_BLOCK_UNINIT;
946 } 937 }
947 938
948 if (ext4fs_set_block_bmap(fs->curr_blkno, fs->blk_bmaps[bg_idx], 939 if (ext4fs_set_block_bmap(fs->curr_blkno, fs->blk_bmaps[bg_idx],
949 bg_idx) != 0) { 940 bg_idx) != 0) {
950 debug("going for restart for the block no %ld %u\n", 941 debug("going for restart for the block no %ld %u\n",
951 fs->curr_blkno, bg_idx); 942 fs->curr_blkno, bg_idx);
952 goto restart; 943 goto restart;
953 } 944 }
954 945
955 /* journal backup */ 946 /* journal backup */
956 if (prev_bg_bitmap_index != bg_idx) { 947 if (prev_bg_bitmap_index != bg_idx) {
957 memset(journal_buffer, '\0', fs->blksz); 948 memset(journal_buffer, '\0', fs->blksz);
958 status = ext4fs_devread((lbaint_t)bgd[bg_idx].block_id 949 status = ext4fs_devread((lbaint_t)bgd[bg_idx].block_id
959 * fs->sect_perblk, 950 * fs->sect_perblk,
960 0, fs->blksz, journal_buffer); 951 0, fs->blksz, journal_buffer);
961 if (status == 0) 952 if (status == 0)
962 goto fail; 953 goto fail;
963 if (ext4fs_log_journal(journal_buffer, 954 if (ext4fs_log_journal(journal_buffer,
964 bgd[bg_idx].block_id)) 955 bgd[bg_idx].block_id))
965 goto fail; 956 goto fail;
966 957
967 prev_bg_bitmap_index = bg_idx; 958 prev_bg_bitmap_index = bg_idx;
968 } 959 }
969 bgd[bg_idx].free_blocks--; 960 bgd[bg_idx].free_blocks--;
970 fs->sb->free_blocks--; 961 fs->sb->free_blocks--;
971 goto success; 962 goto success;
972 } 963 }
973 success: 964 success:
974 free(journal_buffer); 965 free(journal_buffer);
975 free(zero_buffer); 966 free(zero_buffer);
976 967
977 return fs->curr_blkno; 968 return fs->curr_blkno;
978 fail: 969 fail:
979 free(journal_buffer); 970 free(journal_buffer);
980 free(zero_buffer); 971 free(zero_buffer);
981 972
982 return -1; 973 return -1;
983 } 974 }
984 975
985 int ext4fs_get_new_inode_no(void) 976 int ext4fs_get_new_inode_no(void)
986 { 977 {
987 short i; 978 short i;
988 short status; 979 short status;
989 unsigned int ibmap_idx; 980 unsigned int ibmap_idx;
990 static int prev_inode_bitmap_index = -1; 981 static int prev_inode_bitmap_index = -1;
991 unsigned int inodes_per_grp = ext4fs_root->sblock.inodes_per_group; 982 unsigned int inodes_per_grp = ext4fs_root->sblock.inodes_per_group;
992 struct ext_filesystem *fs = get_fs(); 983 struct ext_filesystem *fs = get_fs();
993 char *journal_buffer = zalloc(fs->blksz); 984 char *journal_buffer = zalloc(fs->blksz);
994 char *zero_buffer = zalloc(fs->blksz); 985 char *zero_buffer = zalloc(fs->blksz);
995 if (!journal_buffer || !zero_buffer) 986 if (!journal_buffer || !zero_buffer)
996 goto fail; 987 goto fail;
997 struct ext2_block_group *bgd = (struct ext2_block_group *)fs->gdtable; 988 struct ext2_block_group *bgd = (struct ext2_block_group *)fs->gdtable;
998 989
999 if (fs->first_pass_ibmap == 0) { 990 if (fs->first_pass_ibmap == 0) {
1000 for (i = 0; i < fs->no_blkgrp; i++) { 991 for (i = 0; i < fs->no_blkgrp; i++) {
1001 if (bgd[i].free_inodes) { 992 if (bgd[i].free_inodes) {
1002 if (bgd[i].bg_itable_unused != 993 if (bgd[i].bg_itable_unused !=
1003 bgd[i].free_inodes) 994 bgd[i].free_inodes)
1004 bgd[i].bg_itable_unused = 995 bgd[i].bg_itable_unused =
1005 bgd[i].free_inodes; 996 bgd[i].free_inodes;
1006 if (bgd[i].bg_flags & EXT4_BG_INODE_UNINIT) { 997 if (bgd[i].bg_flags & EXT4_BG_INODE_UNINIT) {
1007 put_ext4(((uint64_t) 998 put_ext4(((uint64_t)
1008 ((uint64_t)bgd[i].inode_id * 999 ((uint64_t)bgd[i].inode_id *
1009 (uint64_t)fs->blksz)), 1000 (uint64_t)fs->blksz)),
1010 zero_buffer, fs->blksz); 1001 zero_buffer, fs->blksz);
1011 bgd[i].bg_flags = bgd[i].bg_flags & 1002 bgd[i].bg_flags = bgd[i].bg_flags &
1012 ~EXT4_BG_INODE_UNINIT; 1003 ~EXT4_BG_INODE_UNINIT;
1013 memcpy(fs->inode_bmaps[i], 1004 memcpy(fs->inode_bmaps[i],
1014 zero_buffer, fs->blksz); 1005 zero_buffer, fs->blksz);
1015 } 1006 }
1016 fs->curr_inode_no = 1007 fs->curr_inode_no =
1017 _get_new_inode_no(fs->inode_bmaps[i]); 1008 _get_new_inode_no(fs->inode_bmaps[i]);
1018 if (fs->curr_inode_no == -1) 1009 if (fs->curr_inode_no == -1)
1019 /* if block bitmap is completely fill */ 1010 /* if block bitmap is completely fill */
1020 continue; 1011 continue;
1021 fs->curr_inode_no = fs->curr_inode_no + 1012 fs->curr_inode_no = fs->curr_inode_no +
1022 (i * inodes_per_grp); 1013 (i * inodes_per_grp);
1023 fs->first_pass_ibmap++; 1014 fs->first_pass_ibmap++;
1024 bgd[i].free_inodes--; 1015 bgd[i].free_inodes--;
1025 bgd[i].bg_itable_unused--; 1016 bgd[i].bg_itable_unused--;
1026 fs->sb->free_inodes--; 1017 fs->sb->free_inodes--;
1027 status = ext4fs_devread((lbaint_t) 1018 status = ext4fs_devread((lbaint_t)
1028 bgd[i].inode_id * 1019 bgd[i].inode_id *
1029 fs->sect_perblk, 0, 1020 fs->sect_perblk, 0,
1030 fs->blksz, 1021 fs->blksz,
1031 journal_buffer); 1022 journal_buffer);
1032 if (status == 0) 1023 if (status == 0)
1033 goto fail; 1024 goto fail;
1034 if (ext4fs_log_journal(journal_buffer, 1025 if (ext4fs_log_journal(journal_buffer,
1035 bgd[i].inode_id)) 1026 bgd[i].inode_id))
1036 goto fail; 1027 goto fail;
1037 goto success; 1028 goto success;
1038 } else 1029 } else
1039 debug("no inode left on block group %d\n", i); 1030 debug("no inode left on block group %d\n", i);
1040 } 1031 }
1041 goto fail; 1032 goto fail;
1042 } else { 1033 } else {
1043 restart: 1034 restart:
1044 fs->curr_inode_no++; 1035 fs->curr_inode_no++;
1045 /* get the blockbitmap index respective to blockno */ 1036 /* get the blockbitmap index respective to blockno */
1046 ibmap_idx = fs->curr_inode_no / inodes_per_grp; 1037 ibmap_idx = fs->curr_inode_no / inodes_per_grp;
1047 if (bgd[ibmap_idx].bg_flags & EXT4_BG_INODE_UNINIT) { 1038 if (bgd[ibmap_idx].bg_flags & EXT4_BG_INODE_UNINIT) {
1048 memset(zero_buffer, '\0', fs->blksz); 1039 memset(zero_buffer, '\0', fs->blksz);
1049 put_ext4(((uint64_t) ((uint64_t)bgd[ibmap_idx].inode_id * 1040 put_ext4(((uint64_t) ((uint64_t)bgd[ibmap_idx].inode_id *
1050 (uint64_t)fs->blksz)), zero_buffer, 1041 (uint64_t)fs->blksz)), zero_buffer,
1051 fs->blksz); 1042 fs->blksz);
1052 bgd[ibmap_idx].bg_flags = 1043 bgd[ibmap_idx].bg_flags =
1053 bgd[ibmap_idx].bg_flags & ~EXT4_BG_INODE_UNINIT; 1044 bgd[ibmap_idx].bg_flags & ~EXT4_BG_INODE_UNINIT;
1054 memcpy(fs->inode_bmaps[ibmap_idx], zero_buffer, 1045 memcpy(fs->inode_bmaps[ibmap_idx], zero_buffer,
1055 fs->blksz); 1046 fs->blksz);
1056 } 1047 }
1057 1048
1058 if (ext4fs_set_inode_bmap(fs->curr_inode_no, 1049 if (ext4fs_set_inode_bmap(fs->curr_inode_no,
1059 fs->inode_bmaps[ibmap_idx], 1050 fs->inode_bmaps[ibmap_idx],
1060 ibmap_idx) != 0) { 1051 ibmap_idx) != 0) {
1061 debug("going for restart for the block no %d %u\n", 1052 debug("going for restart for the block no %d %u\n",
1062 fs->curr_inode_no, ibmap_idx); 1053 fs->curr_inode_no, ibmap_idx);
1063 goto restart; 1054 goto restart;
1064 } 1055 }
1065 1056
1066 /* journal backup */ 1057 /* journal backup */
1067 if (prev_inode_bitmap_index != ibmap_idx) { 1058 if (prev_inode_bitmap_index != ibmap_idx) {
1068 memset(journal_buffer, '\0', fs->blksz); 1059 memset(journal_buffer, '\0', fs->blksz);
1069 status = ext4fs_devread((lbaint_t) 1060 status = ext4fs_devread((lbaint_t)
1070 bgd[ibmap_idx].inode_id 1061 bgd[ibmap_idx].inode_id
1071 * fs->sect_perblk, 1062 * fs->sect_perblk,
1072 0, fs->blksz, journal_buffer); 1063 0, fs->blksz, journal_buffer);
1073 if (status == 0) 1064 if (status == 0)
1074 goto fail; 1065 goto fail;
1075 if (ext4fs_log_journal(journal_buffer, 1066 if (ext4fs_log_journal(journal_buffer,
1076 bgd[ibmap_idx].inode_id)) 1067 bgd[ibmap_idx].inode_id))
1077 goto fail; 1068 goto fail;
1078 prev_inode_bitmap_index = ibmap_idx; 1069 prev_inode_bitmap_index = ibmap_idx;
1079 } 1070 }
1080 if (bgd[ibmap_idx].bg_itable_unused != 1071 if (bgd[ibmap_idx].bg_itable_unused !=
1081 bgd[ibmap_idx].free_inodes) 1072 bgd[ibmap_idx].free_inodes)
1082 bgd[ibmap_idx].bg_itable_unused = 1073 bgd[ibmap_idx].bg_itable_unused =
1083 bgd[ibmap_idx].free_inodes; 1074 bgd[ibmap_idx].free_inodes;
1084 bgd[ibmap_idx].free_inodes--; 1075 bgd[ibmap_idx].free_inodes--;
1085 bgd[ibmap_idx].bg_itable_unused--; 1076 bgd[ibmap_idx].bg_itable_unused--;
1086 fs->sb->free_inodes--; 1077 fs->sb->free_inodes--;
1087 goto success; 1078 goto success;
1088 } 1079 }
1089 1080
1090 success: 1081 success:
1091 free(journal_buffer); 1082 free(journal_buffer);
1092 free(zero_buffer); 1083 free(zero_buffer);
1093 1084
1094 return fs->curr_inode_no; 1085 return fs->curr_inode_no;
1095 fail: 1086 fail:
1096 free(journal_buffer); 1087 free(journal_buffer);
1097 free(zero_buffer); 1088 free(zero_buffer);
1098 1089
1099 return -1; 1090 return -1;
1100 1091
1101 } 1092 }
1102 1093
1103 1094
1104 static void alloc_single_indirect_block(struct ext2_inode *file_inode, 1095 static void alloc_single_indirect_block(struct ext2_inode *file_inode,
1105 unsigned int *total_remaining_blocks, 1096 unsigned int *total_remaining_blocks,
1106 unsigned int *no_blks_reqd) 1097 unsigned int *no_blks_reqd)
1107 { 1098 {
1108 short i; 1099 short i;
1109 short status; 1100 short status;
1110 long int actual_block_no; 1101 long int actual_block_no;
1111 long int si_blockno; 1102 long int si_blockno;
1112 /* si :single indirect */ 1103 /* si :single indirect */
1113 unsigned int *si_buffer = NULL; 1104 unsigned int *si_buffer = NULL;
1114 unsigned int *si_start_addr = NULL; 1105 unsigned int *si_start_addr = NULL;
1115 struct ext_filesystem *fs = get_fs(); 1106 struct ext_filesystem *fs = get_fs();
1116 1107
1117 if (*total_remaining_blocks != 0) { 1108 if (*total_remaining_blocks != 0) {
1118 si_buffer = zalloc(fs->blksz); 1109 si_buffer = zalloc(fs->blksz);
1119 if (!si_buffer) { 1110 if (!si_buffer) {
1120 printf("No Memory\n"); 1111 printf("No Memory\n");
1121 return; 1112 return;
1122 } 1113 }
1123 si_start_addr = si_buffer; 1114 si_start_addr = si_buffer;
1124 si_blockno = ext4fs_get_new_blk_no(); 1115 si_blockno = ext4fs_get_new_blk_no();
1125 if (si_blockno == -1) { 1116 if (si_blockno == -1) {
1126 printf("no block left to assign\n"); 1117 printf("no block left to assign\n");
1127 goto fail; 1118 goto fail;
1128 } 1119 }
1129 (*no_blks_reqd)++; 1120 (*no_blks_reqd)++;
1130 debug("SIPB %ld: %u\n", si_blockno, *total_remaining_blocks); 1121 debug("SIPB %ld: %u\n", si_blockno, *total_remaining_blocks);
1131 1122
1132 status = ext4fs_devread((lbaint_t)si_blockno * fs->sect_perblk, 1123 status = ext4fs_devread((lbaint_t)si_blockno * fs->sect_perblk,
1133 0, fs->blksz, (char *)si_buffer); 1124 0, fs->blksz, (char *)si_buffer);
1134 memset(si_buffer, '\0', fs->blksz); 1125 memset(si_buffer, '\0', fs->blksz);
1135 if (status == 0) 1126 if (status == 0)
1136 goto fail; 1127 goto fail;
1137 1128
1138 for (i = 0; i < (fs->blksz / sizeof(int)); i++) { 1129 for (i = 0; i < (fs->blksz / sizeof(int)); i++) {
1139 actual_block_no = ext4fs_get_new_blk_no(); 1130 actual_block_no = ext4fs_get_new_blk_no();
1140 if (actual_block_no == -1) { 1131 if (actual_block_no == -1) {
1141 printf("no block left to assign\n"); 1132 printf("no block left to assign\n");
1142 goto fail; 1133 goto fail;
1143 } 1134 }
1144 *si_buffer = actual_block_no; 1135 *si_buffer = actual_block_no;
1145 debug("SIAB %u: %u\n", *si_buffer, 1136 debug("SIAB %u: %u\n", *si_buffer,
1146 *total_remaining_blocks); 1137 *total_remaining_blocks);
1147 1138
1148 si_buffer++; 1139 si_buffer++;
1149 (*total_remaining_blocks)--; 1140 (*total_remaining_blocks)--;
1150 if (*total_remaining_blocks == 0) 1141 if (*total_remaining_blocks == 0)
1151 break; 1142 break;
1152 } 1143 }
1153 1144
1154 /* write the block to disk */ 1145 /* write the block to disk */
1155 put_ext4(((uint64_t) ((uint64_t)si_blockno * (uint64_t)fs->blksz)), 1146 put_ext4(((uint64_t) ((uint64_t)si_blockno * (uint64_t)fs->blksz)),
1156 si_start_addr, fs->blksz); 1147 si_start_addr, fs->blksz);
1157 file_inode->b.blocks.indir_block = si_blockno; 1148 file_inode->b.blocks.indir_block = si_blockno;
1158 } 1149 }
1159 fail: 1150 fail:
1160 free(si_start_addr); 1151 free(si_start_addr);
1161 } 1152 }
1162 1153
1163 static void alloc_double_indirect_block(struct ext2_inode *file_inode, 1154 static void alloc_double_indirect_block(struct ext2_inode *file_inode,
1164 unsigned int *total_remaining_blocks, 1155 unsigned int *total_remaining_blocks,
1165 unsigned int *no_blks_reqd) 1156 unsigned int *no_blks_reqd)
1166 { 1157 {
1167 short i; 1158 short i;
1168 short j; 1159 short j;
1169 short status; 1160 short status;
1170 long int actual_block_no; 1161 long int actual_block_no;
1171 /* di:double indirect */ 1162 /* di:double indirect */
1172 long int di_blockno_parent; 1163 long int di_blockno_parent;
1173 long int di_blockno_child; 1164 long int di_blockno_child;
1174 unsigned int *di_parent_buffer = NULL; 1165 unsigned int *di_parent_buffer = NULL;
1175 unsigned int *di_child_buff = NULL; 1166 unsigned int *di_child_buff = NULL;
1176 unsigned int *di_block_start_addr = NULL; 1167 unsigned int *di_block_start_addr = NULL;
1177 unsigned int *di_child_buff_start = NULL; 1168 unsigned int *di_child_buff_start = NULL;
1178 struct ext_filesystem *fs = get_fs(); 1169 struct ext_filesystem *fs = get_fs();
1179 1170
1180 if (*total_remaining_blocks != 0) { 1171 if (*total_remaining_blocks != 0) {
1181 /* double indirect parent block connecting to inode */ 1172 /* double indirect parent block connecting to inode */
1182 di_blockno_parent = ext4fs_get_new_blk_no(); 1173 di_blockno_parent = ext4fs_get_new_blk_no();
1183 if (di_blockno_parent == -1) { 1174 if (di_blockno_parent == -1) {
1184 printf("no block left to assign\n"); 1175 printf("no block left to assign\n");
1185 goto fail; 1176 goto fail;
1186 } 1177 }
1187 di_parent_buffer = zalloc(fs->blksz); 1178 di_parent_buffer = zalloc(fs->blksz);
1188 if (!di_parent_buffer) 1179 if (!di_parent_buffer)
1189 goto fail; 1180 goto fail;
1190 1181
1191 di_block_start_addr = di_parent_buffer; 1182 di_block_start_addr = di_parent_buffer;
1192 (*no_blks_reqd)++; 1183 (*no_blks_reqd)++;
1193 debug("DIPB %ld: %u\n", di_blockno_parent, 1184 debug("DIPB %ld: %u\n", di_blockno_parent,
1194 *total_remaining_blocks); 1185 *total_remaining_blocks);
1195 1186
1196 status = ext4fs_devread((lbaint_t)di_blockno_parent * 1187 status = ext4fs_devread((lbaint_t)di_blockno_parent *
1197 fs->sect_perblk, 0, 1188 fs->sect_perblk, 0,
1198 fs->blksz, (char *)di_parent_buffer); 1189 fs->blksz, (char *)di_parent_buffer);
1199 1190
1200 if (!status) { 1191 if (!status) {
1201 printf("%s: Device read error!\n", __func__); 1192 printf("%s: Device read error!\n", __func__);
1202 goto fail; 1193 goto fail;
1203 } 1194 }
1204 memset(di_parent_buffer, '\0', fs->blksz); 1195 memset(di_parent_buffer, '\0', fs->blksz);
1205 1196
1206 /* 1197 /*
1207 * start:for each double indirect parent 1198 * start:for each double indirect parent
1208 * block create one more block 1199 * block create one more block
1209 */ 1200 */
1210 for (i = 0; i < (fs->blksz / sizeof(int)); i++) { 1201 for (i = 0; i < (fs->blksz / sizeof(int)); i++) {
1211 di_blockno_child = ext4fs_get_new_blk_no(); 1202 di_blockno_child = ext4fs_get_new_blk_no();
1212 if (di_blockno_child == -1) { 1203 if (di_blockno_child == -1) {
1213 printf("no block left to assign\n"); 1204 printf("no block left to assign\n");
1214 goto fail; 1205 goto fail;
1215 } 1206 }
1216 di_child_buff = zalloc(fs->blksz); 1207 di_child_buff = zalloc(fs->blksz);
1217 if (!di_child_buff) 1208 if (!di_child_buff)
1218 goto fail; 1209 goto fail;
1219 1210
1220 di_child_buff_start = di_child_buff; 1211 di_child_buff_start = di_child_buff;
1221 *di_parent_buffer = di_blockno_child; 1212 *di_parent_buffer = di_blockno_child;
1222 di_parent_buffer++; 1213 di_parent_buffer++;
1223 (*no_blks_reqd)++; 1214 (*no_blks_reqd)++;
1224 debug("DICB %ld: %u\n", di_blockno_child, 1215 debug("DICB %ld: %u\n", di_blockno_child,
1225 *total_remaining_blocks); 1216 *total_remaining_blocks);
1226 1217
1227 status = ext4fs_devread((lbaint_t)di_blockno_child * 1218 status = ext4fs_devread((lbaint_t)di_blockno_child *
1228 fs->sect_perblk, 0, 1219 fs->sect_perblk, 0,
1229 fs->blksz, 1220 fs->blksz,
1230 (char *)di_child_buff); 1221 (char *)di_child_buff);
1231 1222
1232 if (!status) { 1223 if (!status) {
1233 printf("%s: Device read error!\n", __func__); 1224 printf("%s: Device read error!\n", __func__);
1234 goto fail; 1225 goto fail;
1235 } 1226 }
1236 memset(di_child_buff, '\0', fs->blksz); 1227 memset(di_child_buff, '\0', fs->blksz);
1237 /* filling of actual datablocks for each child */ 1228 /* filling of actual datablocks for each child */
1238 for (j = 0; j < (fs->blksz / sizeof(int)); j++) { 1229 for (j = 0; j < (fs->blksz / sizeof(int)); j++) {
1239 actual_block_no = ext4fs_get_new_blk_no(); 1230 actual_block_no = ext4fs_get_new_blk_no();
1240 if (actual_block_no == -1) { 1231 if (actual_block_no == -1) {
1241 printf("no block left to assign\n"); 1232 printf("no block left to assign\n");
1242 goto fail; 1233 goto fail;
1243 } 1234 }
1244 *di_child_buff = actual_block_no; 1235 *di_child_buff = actual_block_no;
1245 debug("DIAB %ld: %u\n", actual_block_no, 1236 debug("DIAB %ld: %u\n", actual_block_no,
1246 *total_remaining_blocks); 1237 *total_remaining_blocks);
1247 1238
1248 di_child_buff++; 1239 di_child_buff++;
1249 (*total_remaining_blocks)--; 1240 (*total_remaining_blocks)--;
1250 if (*total_remaining_blocks == 0) 1241 if (*total_remaining_blocks == 0)
1251 break; 1242 break;
1252 } 1243 }
1253 /* write the block table */ 1244 /* write the block table */
1254 put_ext4(((uint64_t) ((uint64_t)di_blockno_child * (uint64_t)fs->blksz)), 1245 put_ext4(((uint64_t) ((uint64_t)di_blockno_child * (uint64_t)fs->blksz)),
1255 di_child_buff_start, fs->blksz); 1246 di_child_buff_start, fs->blksz);
1256 free(di_child_buff_start); 1247 free(di_child_buff_start);
1257 di_child_buff_start = NULL; 1248 di_child_buff_start = NULL;
1258 1249
1259 if (*total_remaining_blocks == 0) 1250 if (*total_remaining_blocks == 0)
1260 break; 1251 break;
1261 } 1252 }
1262 put_ext4(((uint64_t) ((uint64_t)di_blockno_parent * (uint64_t)fs->blksz)), 1253 put_ext4(((uint64_t) ((uint64_t)di_blockno_parent * (uint64_t)fs->blksz)),
1263 di_block_start_addr, fs->blksz); 1254 di_block_start_addr, fs->blksz);
1264 file_inode->b.blocks.double_indir_block = di_blockno_parent; 1255 file_inode->b.blocks.double_indir_block = di_blockno_parent;
1265 } 1256 }
1266 fail: 1257 fail:
1267 free(di_block_start_addr); 1258 free(di_block_start_addr);
1268 } 1259 }
1269 1260
1270 static void alloc_triple_indirect_block(struct ext2_inode *file_inode, 1261 static void alloc_triple_indirect_block(struct ext2_inode *file_inode,
1271 unsigned int *total_remaining_blocks, 1262 unsigned int *total_remaining_blocks,
1272 unsigned int *no_blks_reqd) 1263 unsigned int *no_blks_reqd)
1273 { 1264 {
1274 short i; 1265 short i;
1275 short j; 1266 short j;
1276 short k; 1267 short k;
1277 long int actual_block_no; 1268 long int actual_block_no;
1278 /* ti: Triple Indirect */ 1269 /* ti: Triple Indirect */
1279 long int ti_gp_blockno; 1270 long int ti_gp_blockno;
1280 long int ti_parent_blockno; 1271 long int ti_parent_blockno;
1281 long int ti_child_blockno; 1272 long int ti_child_blockno;
1282 unsigned int *ti_gp_buff = NULL; 1273 unsigned int *ti_gp_buff = NULL;
1283 unsigned int *ti_parent_buff = NULL; 1274 unsigned int *ti_parent_buff = NULL;
1284 unsigned int *ti_child_buff = NULL; 1275 unsigned int *ti_child_buff = NULL;
1285 unsigned int *ti_gp_buff_start_addr = NULL; 1276 unsigned int *ti_gp_buff_start_addr = NULL;
1286 unsigned int *ti_pbuff_start_addr = NULL; 1277 unsigned int *ti_pbuff_start_addr = NULL;
1287 unsigned int *ti_cbuff_start_addr = NULL; 1278 unsigned int *ti_cbuff_start_addr = NULL;
1288 struct ext_filesystem *fs = get_fs(); 1279 struct ext_filesystem *fs = get_fs();
1289 if (*total_remaining_blocks != 0) { 1280 if (*total_remaining_blocks != 0) {
1290 /* triple indirect grand parent block connecting to inode */ 1281 /* triple indirect grand parent block connecting to inode */
1291 ti_gp_blockno = ext4fs_get_new_blk_no(); 1282 ti_gp_blockno = ext4fs_get_new_blk_no();
1292 if (ti_gp_blockno == -1) { 1283 if (ti_gp_blockno == -1) {
1293 printf("no block left to assign\n"); 1284 printf("no block left to assign\n");
1294 goto fail; 1285 goto fail;
1295 } 1286 }
1296 ti_gp_buff = zalloc(fs->blksz); 1287 ti_gp_buff = zalloc(fs->blksz);
1297 if (!ti_gp_buff) 1288 if (!ti_gp_buff)
1298 goto fail; 1289 goto fail;
1299 1290
1300 ti_gp_buff_start_addr = ti_gp_buff; 1291 ti_gp_buff_start_addr = ti_gp_buff;
1301 (*no_blks_reqd)++; 1292 (*no_blks_reqd)++;
1302 debug("TIGPB %ld: %u\n", ti_gp_blockno, 1293 debug("TIGPB %ld: %u\n", ti_gp_blockno,
1303 *total_remaining_blocks); 1294 *total_remaining_blocks);
1304 1295
1305 /* for each 4 byte grand parent entry create one more block */ 1296 /* for each 4 byte grand parent entry create one more block */
1306 for (i = 0; i < (fs->blksz / sizeof(int)); i++) { 1297 for (i = 0; i < (fs->blksz / sizeof(int)); i++) {
1307 ti_parent_blockno = ext4fs_get_new_blk_no(); 1298 ti_parent_blockno = ext4fs_get_new_blk_no();
1308 if (ti_parent_blockno == -1) { 1299 if (ti_parent_blockno == -1) {
1309 printf("no block left to assign\n"); 1300 printf("no block left to assign\n");
1310 goto fail; 1301 goto fail;
1311 } 1302 }
1312 ti_parent_buff = zalloc(fs->blksz); 1303 ti_parent_buff = zalloc(fs->blksz);
1313 if (!ti_parent_buff) 1304 if (!ti_parent_buff)
1314 goto fail; 1305 goto fail;
1315 1306
1316 ti_pbuff_start_addr = ti_parent_buff; 1307 ti_pbuff_start_addr = ti_parent_buff;
1317 *ti_gp_buff = ti_parent_blockno; 1308 *ti_gp_buff = ti_parent_blockno;
1318 ti_gp_buff++; 1309 ti_gp_buff++;
1319 (*no_blks_reqd)++; 1310 (*no_blks_reqd)++;
1320 debug("TIPB %ld: %u\n", ti_parent_blockno, 1311 debug("TIPB %ld: %u\n", ti_parent_blockno,
1321 *total_remaining_blocks); 1312 *total_remaining_blocks);
1322 1313
1323 /* for each 4 byte entry parent create one more block */ 1314 /* for each 4 byte entry parent create one more block */
1324 for (j = 0; j < (fs->blksz / sizeof(int)); j++) { 1315 for (j = 0; j < (fs->blksz / sizeof(int)); j++) {
1325 ti_child_blockno = ext4fs_get_new_blk_no(); 1316 ti_child_blockno = ext4fs_get_new_blk_no();
1326 if (ti_child_blockno == -1) { 1317 if (ti_child_blockno == -1) {
1327 printf("no block left assign\n"); 1318 printf("no block left assign\n");
1328 goto fail; 1319 goto fail;
1329 } 1320 }
1330 ti_child_buff = zalloc(fs->blksz); 1321 ti_child_buff = zalloc(fs->blksz);
1331 if (!ti_child_buff) 1322 if (!ti_child_buff)
1332 goto fail; 1323 goto fail;
1333 1324
1334 ti_cbuff_start_addr = ti_child_buff; 1325 ti_cbuff_start_addr = ti_child_buff;
1335 *ti_parent_buff = ti_child_blockno; 1326 *ti_parent_buff = ti_child_blockno;
1336 ti_parent_buff++; 1327 ti_parent_buff++;
1337 (*no_blks_reqd)++; 1328 (*no_blks_reqd)++;
1338 debug("TICB %ld: %u\n", ti_parent_blockno, 1329 debug("TICB %ld: %u\n", ti_parent_blockno,
1339 *total_remaining_blocks); 1330 *total_remaining_blocks);
1340 1331
1341 /* fill actual datablocks for each child */ 1332 /* fill actual datablocks for each child */
1342 for (k = 0; k < (fs->blksz / sizeof(int)); 1333 for (k = 0; k < (fs->blksz / sizeof(int));
1343 k++) { 1334 k++) {
1344 actual_block_no = 1335 actual_block_no =
1345 ext4fs_get_new_blk_no(); 1336 ext4fs_get_new_blk_no();
1346 if (actual_block_no == -1) { 1337 if (actual_block_no == -1) {
1347 printf("no block left\n"); 1338 printf("no block left\n");
1348 goto fail; 1339 goto fail;
1349 } 1340 }
1350 *ti_child_buff = actual_block_no; 1341 *ti_child_buff = actual_block_no;
1351 debug("TIAB %ld: %u\n", actual_block_no, 1342 debug("TIAB %ld: %u\n", actual_block_no,
1352 *total_remaining_blocks); 1343 *total_remaining_blocks);
1353 1344
1354 ti_child_buff++; 1345 ti_child_buff++;
1355 (*total_remaining_blocks)--; 1346 (*total_remaining_blocks)--;
1356 if (*total_remaining_blocks == 0) 1347 if (*total_remaining_blocks == 0)
1357 break; 1348 break;
1358 } 1349 }
1359 /* write the child block */ 1350 /* write the child block */
1360 put_ext4(((uint64_t) ((uint64_t)ti_child_blockno * 1351 put_ext4(((uint64_t) ((uint64_t)ti_child_blockno *
1361 (uint64_t)fs->blksz)), 1352 (uint64_t)fs->blksz)),
1362 ti_cbuff_start_addr, fs->blksz); 1353 ti_cbuff_start_addr, fs->blksz);
1363 free(ti_cbuff_start_addr); 1354 free(ti_cbuff_start_addr);
1364 1355
1365 if (*total_remaining_blocks == 0) 1356 if (*total_remaining_blocks == 0)
1366 break; 1357 break;
1367 } 1358 }
1368 /* write the parent block */ 1359 /* write the parent block */
1369 put_ext4(((uint64_t) ((uint64_t)ti_parent_blockno * (uint64_t)fs->blksz)), 1360 put_ext4(((uint64_t) ((uint64_t)ti_parent_blockno * (uint64_t)fs->blksz)),
1370 ti_pbuff_start_addr, fs->blksz); 1361 ti_pbuff_start_addr, fs->blksz);
1371 free(ti_pbuff_start_addr); 1362 free(ti_pbuff_start_addr);
1372 1363
1373 if (*total_remaining_blocks == 0) 1364 if (*total_remaining_blocks == 0)
1374 break; 1365 break;
1375 } 1366 }
1376 /* write the grand parent block */ 1367 /* write the grand parent block */
1377 put_ext4(((uint64_t) ((uint64_t)ti_gp_blockno * (uint64_t)fs->blksz)), 1368 put_ext4(((uint64_t) ((uint64_t)ti_gp_blockno * (uint64_t)fs->blksz)),
1378 ti_gp_buff_start_addr, fs->blksz); 1369 ti_gp_buff_start_addr, fs->blksz);
1379 file_inode->b.blocks.triple_indir_block = ti_gp_blockno; 1370 file_inode->b.blocks.triple_indir_block = ti_gp_blockno;
1380 } 1371 }
1381 fail: 1372 fail:
1382 free(ti_gp_buff_start_addr); 1373 free(ti_gp_buff_start_addr);
1383 } 1374 }
1384 1375
1385 void ext4fs_allocate_blocks(struct ext2_inode *file_inode, 1376 void ext4fs_allocate_blocks(struct ext2_inode *file_inode,
1386 unsigned int total_remaining_blocks, 1377 unsigned int total_remaining_blocks,
1387 unsigned int *total_no_of_block) 1378 unsigned int *total_no_of_block)
1388 { 1379 {
1389 short i; 1380 short i;
1390 long int direct_blockno; 1381 long int direct_blockno;
1391 unsigned int no_blks_reqd = 0; 1382 unsigned int no_blks_reqd = 0;
1392 1383
1393 /* allocation of direct blocks */ 1384 /* allocation of direct blocks */
1394 for (i = 0; i < INDIRECT_BLOCKS; i++) { 1385 for (i = 0; i < INDIRECT_BLOCKS; i++) {
1395 direct_blockno = ext4fs_get_new_blk_no(); 1386 direct_blockno = ext4fs_get_new_blk_no();
1396 if (direct_blockno == -1) { 1387 if (direct_blockno == -1) {
1397 printf("no block left to assign\n"); 1388 printf("no block left to assign\n");
1398 return; 1389 return;
1399 } 1390 }
1400 file_inode->b.blocks.dir_blocks[i] = direct_blockno; 1391 file_inode->b.blocks.dir_blocks[i] = direct_blockno;
1401 debug("DB %ld: %u\n", direct_blockno, total_remaining_blocks); 1392 debug("DB %ld: %u\n", direct_blockno, total_remaining_blocks);
1402 1393
1403 total_remaining_blocks--; 1394 total_remaining_blocks--;
1404 if (total_remaining_blocks == 0) 1395 if (total_remaining_blocks == 0)
1405 break; 1396 break;
1406 } 1397 }
1407 1398
1408 alloc_single_indirect_block(file_inode, &total_remaining_blocks, 1399 alloc_single_indirect_block(file_inode, &total_remaining_blocks,
1409 &no_blks_reqd); 1400 &no_blks_reqd);
1410 alloc_double_indirect_block(file_inode, &total_remaining_blocks, 1401 alloc_double_indirect_block(file_inode, &total_remaining_blocks,
1411 &no_blks_reqd); 1402 &no_blks_reqd);
1412 alloc_triple_indirect_block(file_inode, &total_remaining_blocks, 1403 alloc_triple_indirect_block(file_inode, &total_remaining_blocks,
1413 &no_blks_reqd); 1404 &no_blks_reqd);
1414 *total_no_of_block += no_blks_reqd; 1405 *total_no_of_block += no_blks_reqd;
1415 } 1406 }
1416 1407
1417 #endif 1408 #endif
1418 1409
1419 static void ext4fs_extent_cache_insert(struct ext4_extent_node *new) 1410 static struct ext4_extent_header *ext4fs_get_extent_block
1411 (struct ext2_data *data, char *buf,
1412 struct ext4_extent_header *ext_block,
1413 uint32_t fileblock, int log2_blksz)
1420 { 1414 {
1421 struct ext4_extent_node *node;
1422
1423 list_for_each_entry(node, &ext4_extent_lh, lh)
1424 if (node->block > new->block) {
1425 list_add_tail(&new->lh, &node->lh);
1426 return;
1427 }
1428 list_add_tail(&new->lh, &ext4_extent_lh);
1429 }
1430
1431 static int __ext4fs_build_extent_cache(struct ext2_data *data,
1432 struct ext4_extent_header *ext_block)
1433 {
1434 int blksz = EXT2_BLOCK_SIZE(data);
1435 int log2_blksz = LOG2_BLOCK_SIZE(data)
1436 - get_fs()->dev_desc->log2blksz;
1437 struct ext4_extent_node *node;
1438 struct ext4_extent_idx *index; 1415 struct ext4_extent_idx *index;
1439 struct ext4_extent *extent;
1440 unsigned long long block; 1416 unsigned long long block;
1441 char *buf; 1417 int blksz = EXT2_BLOCK_SIZE(data);
1442 int i, err; 1418 int i;
1443 1419
1444 if (le16_to_cpu(ext_block->eh_magic) != EXT4_EXT_MAGIC) 1420 while (1) {
1445 return -EINVAL; 1421 index = (struct ext4_extent_idx *)(ext_block + 1);
1446 1422
1447 if (ext_block->eh_depth == 0) { 1423 if (le16_to_cpu(ext_block->eh_magic) != EXT4_EXT_MAGIC)
1448 extent = (struct ext4_extent *)(ext_block + 1); 1424 return 0;
1449 for (i = 0; i < le16_to_cpu(ext_block->eh_entries); i++) {
1450 node = malloc(sizeof(*node));
1451 if (!node)
1452 return -ENOMEM;
1453 node->block = le32_to_cpu(extent[i].ee_block);
1454 node->len = le16_to_cpu(extent[i].ee_len);
1455 node->start = le16_to_cpu(extent[i].ee_start_hi);
1456 node->start = (node->start << 32) +
1457 le32_to_cpu(extent[i].ee_start_lo);
1458 ext4fs_extent_cache_insert(node);
1459 }
1460 return 0;
1461 }
1462 1425
1463 index = (struct ext4_extent_idx *)(ext_block + 1); 1426 if (ext_block->eh_depth == 0)
1464 for (i = 0; i < le16_to_cpu(ext_block->eh_entries); i++) { 1427 return ext_block;
1465 buf = malloc(blksz); 1428 i = -1;
1466 if (!buf) 1429 do {
1467 return -ENOMEM; 1430 i++;
1431 if (i >= le16_to_cpu(ext_block->eh_entries))
1432 break;
1433 } while (fileblock >= le32_to_cpu(index[i].ei_block));
1468 1434
1435 if (--i < 0)
1436 return 0;
1437
1469 block = le16_to_cpu(index[i].ei_leaf_hi); 1438 block = le16_to_cpu(index[i].ei_leaf_hi);
1470 block = (block << 32) + le32_to_cpu(index[i].ei_leaf_lo); 1439 block = (block << 32) + le32_to_cpu(index[i].ei_leaf_lo);
1471 1440
1472 if (!ext4fs_devread(block << log2_blksz, 0, blksz, buf)) { 1441 if (ext4fs_devread((lbaint_t)block << log2_blksz, 0, blksz,
1473 free(buf); 1442 buf))
1474 return -EIO; 1443 ext_block = (struct ext4_extent_header *)buf;
1475 } 1444 else
1476 1445 return 0;
1477 err = __ext4fs_build_extent_cache(data,
1478 (struct ext4_extent_header *) buf);
1479 free(buf);
1480 if (err < 0)
1481 return err;
1482 } 1446 }
1483
1484 return 0;
1485 } 1447 }
1486 1448
1487 int ext4fs_build_extent_cache(struct ext2_inode *inode)
1488 {
1489 return __ext4fs_build_extent_cache(ext4fs_root,
1490 (struct ext4_extent_header *)
1491 inode->b.blocks.dir_blocks);
1492 }
1493
1494 void ext4fs_free_extent_cache(void)
1495 {
1496 struct ext4_extent_node *node, *tmp;
1497
1498 list_for_each_entry_safe(node, tmp, &ext4_extent_lh, lh) {
1499 list_del(&node->lh);
1500 free(node);
1501 }
1502 }
1503
1504 static struct ext4_extent_node *ext4fs_extent_cache_get(uint32_t block)
1505 {
1506 struct ext4_extent_node *node;
1507
1508 list_for_each_entry(node, &ext4_extent_lh, lh)
1509 if (block >= node->block && block < node->block + node->len)
1510 return node;
1511
1512 return NULL;
1513 }
1514
1515 static int ext4fs_blockgroup 1449 static int ext4fs_blockgroup
1516 (struct ext2_data *data, int group, struct ext2_block_group *blkgrp) 1450 (struct ext2_data *data, int group, struct ext2_block_group *blkgrp)
1517 { 1451 {
1518 long int blkno; 1452 long int blkno;
1519 unsigned int blkoff, desc_per_blk; 1453 unsigned int blkoff, desc_per_blk;
1520 int log2blksz = get_fs()->dev_desc->log2blksz; 1454 int log2blksz = get_fs()->dev_desc->log2blksz;
1521 1455
1522 desc_per_blk = EXT2_BLOCK_SIZE(data) / sizeof(struct ext2_block_group); 1456 desc_per_blk = EXT2_BLOCK_SIZE(data) / sizeof(struct ext2_block_group);
1523 1457
1524 blkno = __le32_to_cpu(data->sblock.first_data_block) + 1 + 1458 blkno = __le32_to_cpu(data->sblock.first_data_block) + 1 +
1525 group / desc_per_blk; 1459 group / desc_per_blk;
1526 blkoff = (group % desc_per_blk) * sizeof(struct ext2_block_group); 1460 blkoff = (group % desc_per_blk) * sizeof(struct ext2_block_group);
1527 1461
1528 debug("ext4fs read %d group descriptor (blkno %ld blkoff %u)\n", 1462 debug("ext4fs read %d group descriptor (blkno %ld blkoff %u)\n",
1529 group, blkno, blkoff); 1463 group, blkno, blkoff);
1530 1464
1531 return ext4fs_devread((lbaint_t)blkno << 1465 return ext4fs_devread((lbaint_t)blkno <<
1532 (LOG2_BLOCK_SIZE(data) - log2blksz), 1466 (LOG2_BLOCK_SIZE(data) - log2blksz),
1533 blkoff, sizeof(struct ext2_block_group), 1467 blkoff, sizeof(struct ext2_block_group),
1534 (char *)blkgrp); 1468 (char *)blkgrp);
1535 } 1469 }
1536 1470
1537 int ext4fs_read_inode(struct ext2_data *data, int ino, struct ext2_inode *inode) 1471 int ext4fs_read_inode(struct ext2_data *data, int ino, struct ext2_inode *inode)
1538 { 1472 {
1539 struct ext2_block_group blkgrp; 1473 struct ext2_block_group blkgrp;
1540 struct ext2_sblock *sblock = &data->sblock; 1474 struct ext2_sblock *sblock = &data->sblock;
1541 struct ext_filesystem *fs = get_fs(); 1475 struct ext_filesystem *fs = get_fs();
1542 int log2blksz = get_fs()->dev_desc->log2blksz; 1476 int log2blksz = get_fs()->dev_desc->log2blksz;
1543 int inodes_per_block, status; 1477 int inodes_per_block, status;
1544 long int blkno; 1478 long int blkno;
1545 unsigned int blkoff; 1479 unsigned int blkoff;
1546 1480
1547 /* It is easier to calculate if the first inode is 0. */ 1481 /* It is easier to calculate if the first inode is 0. */
1548 ino--; 1482 ino--;
1549 status = ext4fs_blockgroup(data, ino / __le32_to_cpu 1483 status = ext4fs_blockgroup(data, ino / __le32_to_cpu
1550 (sblock->inodes_per_group), &blkgrp); 1484 (sblock->inodes_per_group), &blkgrp);
1551 if (status == 0) 1485 if (status == 0)
1552 return 0; 1486 return 0;
1553 1487
1554 inodes_per_block = EXT2_BLOCK_SIZE(data) / fs->inodesz; 1488 inodes_per_block = EXT2_BLOCK_SIZE(data) / fs->inodesz;
1555 blkno = __le32_to_cpu(blkgrp.inode_table_id) + 1489 blkno = __le32_to_cpu(blkgrp.inode_table_id) +
1556 (ino % __le32_to_cpu(sblock->inodes_per_group)) / inodes_per_block; 1490 (ino % __le32_to_cpu(sblock->inodes_per_group)) / inodes_per_block;
1557 blkoff = (ino % inodes_per_block) * fs->inodesz; 1491 blkoff = (ino % inodes_per_block) * fs->inodesz;
1558 /* Read the inode. */ 1492 /* Read the inode. */
1559 status = ext4fs_devread((lbaint_t)blkno << (LOG2_BLOCK_SIZE(data) - 1493 status = ext4fs_devread((lbaint_t)blkno << (LOG2_BLOCK_SIZE(data) -
1560 log2blksz), blkoff, 1494 log2blksz), blkoff,
1561 sizeof(struct ext2_inode), (char *)inode); 1495 sizeof(struct ext2_inode), (char *)inode);
1562 if (status == 0) 1496 if (status == 0)
1563 return 0; 1497 return 0;
1564 1498
1565 return 1; 1499 return 1;
1566 } 1500 }
1567 1501
1568 long int read_allocated_block(struct ext2_inode *inode, int fileblock) 1502 long int read_allocated_block(struct ext2_inode *inode, int fileblock)
1569 { 1503 {
1570 long int blknr; 1504 long int blknr;
1571 int blksz; 1505 int blksz;
1572 int log2_blksz; 1506 int log2_blksz;
1573 int status; 1507 int status;
1574 long int rblock; 1508 long int rblock;
1575 long int perblock_parent; 1509 long int perblock_parent;
1576 long int perblock_child; 1510 long int perblock_child;
1577 1511 unsigned long long start;
1578 /* get the blocksize of the filesystem */ 1512 /* get the blocksize of the filesystem */
1579 blksz = EXT2_BLOCK_SIZE(ext4fs_root); 1513 blksz = EXT2_BLOCK_SIZE(ext4fs_root);
1580 log2_blksz = LOG2_BLOCK_SIZE(ext4fs_root) 1514 log2_blksz = LOG2_BLOCK_SIZE(ext4fs_root)
1581 - get_fs()->dev_desc->log2blksz; 1515 - get_fs()->dev_desc->log2blksz;
1582 1516
1583 if (le32_to_cpu(inode->flags) & EXT4_EXTENTS_FL) { 1517 if (le32_to_cpu(inode->flags) & EXT4_EXTENTS_FL) {
1584 struct ext4_extent_node *node; 1518 char *buf = zalloc(blksz);
1519 if (!buf)
1520 return -ENOMEM;
1521 struct ext4_extent_header *ext_block;
1522 struct ext4_extent *extent;
1523 int i = -1;
1524 ext_block =
1525 ext4fs_get_extent_block(ext4fs_root, buf,
1526 (struct ext4_extent_header *)
1527 inode->b.blocks.dir_blocks,
1528 fileblock, log2_blksz);
1529 if (!ext_block) {
1530 printf("invalid extent block\n");
1531 free(buf);
1532 return -EINVAL;
1533 }
1585 1534
1586 node = ext4fs_extent_cache_get(fileblock); 1535 extent = (struct ext4_extent *)(ext_block + 1);
1587 if (!node) { 1536
1588 printf("Extent Error\n"); 1537 do {
1589 return -1; 1538 i++;
1539 if (i >= le16_to_cpu(ext_block->eh_entries))
1540 break;
1541 } while (fileblock >= le32_to_cpu(extent[i].ee_block));
1542 if (--i >= 0) {
1543 fileblock -= le32_to_cpu(extent[i].ee_block);
1544 if (fileblock >= le16_to_cpu(extent[i].ee_len)) {
1545 free(buf);
1546 return 0;
1547 }
1548
1549 start = le16_to_cpu(extent[i].ee_start_hi);
1550 start = (start << 32) +
1551 le32_to_cpu(extent[i].ee_start_lo);
1552 free(buf);
1553 return fileblock + start;
1590 } 1554 }
1591 1555
1592 return fileblock - node->block + node->start; 1556 printf("Extent Error\n");
1557 free(buf);
1558 return -1;
1593 } 1559 }
1594 1560
1595 /* Direct blocks. */ 1561 /* Direct blocks. */
1596 if (fileblock < INDIRECT_BLOCKS) 1562 if (fileblock < INDIRECT_BLOCKS)
1597 blknr = __le32_to_cpu(inode->b.blocks.dir_blocks[fileblock]); 1563 blknr = __le32_to_cpu(inode->b.blocks.dir_blocks[fileblock]);
1598 1564
1599 /* Indirect. */ 1565 /* Indirect. */
1600 else if (fileblock < (INDIRECT_BLOCKS + (blksz / 4))) { 1566 else if (fileblock < (INDIRECT_BLOCKS + (blksz / 4))) {
1601 if (ext4fs_indir1_block == NULL) { 1567 if (ext4fs_indir1_block == NULL) {
1602 ext4fs_indir1_block = zalloc(blksz); 1568 ext4fs_indir1_block = zalloc(blksz);
1603 if (ext4fs_indir1_block == NULL) { 1569 if (ext4fs_indir1_block == NULL) {
1604 printf("** SI ext2fs read block (indir 1)" 1570 printf("** SI ext2fs read block (indir 1)"
1605 "malloc failed. **\n"); 1571 "malloc failed. **\n");
1606 return -1; 1572 return -1;
1607 } 1573 }
1608 ext4fs_indir1_size = blksz; 1574 ext4fs_indir1_size = blksz;
1609 ext4fs_indir1_blkno = -1; 1575 ext4fs_indir1_blkno = -1;
1610 } 1576 }
1611 if (blksz != ext4fs_indir1_size) { 1577 if (blksz != ext4fs_indir1_size) {
1612 free(ext4fs_indir1_block); 1578 free(ext4fs_indir1_block);
1613 ext4fs_indir1_block = NULL; 1579 ext4fs_indir1_block = NULL;
1614 ext4fs_indir1_size = 0; 1580 ext4fs_indir1_size = 0;
1615 ext4fs_indir1_blkno = -1; 1581 ext4fs_indir1_blkno = -1;
1616 ext4fs_indir1_block = zalloc(blksz); 1582 ext4fs_indir1_block = zalloc(blksz);
1617 if (ext4fs_indir1_block == NULL) { 1583 if (ext4fs_indir1_block == NULL) {
1618 printf("** SI ext2fs read block (indir 1):" 1584 printf("** SI ext2fs read block (indir 1):"
1619 "malloc failed. **\n"); 1585 "malloc failed. **\n");
1620 return -1; 1586 return -1;
1621 } 1587 }
1622 ext4fs_indir1_size = blksz; 1588 ext4fs_indir1_size = blksz;
1623 } 1589 }
1624 if ((__le32_to_cpu(inode->b.blocks.indir_block) << 1590 if ((__le32_to_cpu(inode->b.blocks.indir_block) <<
1625 log2_blksz) != ext4fs_indir1_blkno) { 1591 log2_blksz) != ext4fs_indir1_blkno) {
1626 status = 1592 status =
1627 ext4fs_devread((lbaint_t)__le32_to_cpu 1593 ext4fs_devread((lbaint_t)__le32_to_cpu
1628 (inode->b.blocks. 1594 (inode->b.blocks.
1629 indir_block) << log2_blksz, 0, 1595 indir_block) << log2_blksz, 0,
1630 blksz, (char *)ext4fs_indir1_block); 1596 blksz, (char *)ext4fs_indir1_block);
1631 if (status == 0) { 1597 if (status == 0) {
1632 printf("** SI ext2fs read block (indir 1)" 1598 printf("** SI ext2fs read block (indir 1)"
1633 "failed. **\n"); 1599 "failed. **\n");
1634 return 0; 1600 return 0;
1635 } 1601 }
1636 ext4fs_indir1_blkno = 1602 ext4fs_indir1_blkno =
1637 __le32_to_cpu(inode->b.blocks. 1603 __le32_to_cpu(inode->b.blocks.
1638 indir_block) << log2_blksz; 1604 indir_block) << log2_blksz;
1639 } 1605 }
1640 blknr = __le32_to_cpu(ext4fs_indir1_block 1606 blknr = __le32_to_cpu(ext4fs_indir1_block
1641 [fileblock - INDIRECT_BLOCKS]); 1607 [fileblock - INDIRECT_BLOCKS]);
1642 } 1608 }
1643 /* Double indirect. */ 1609 /* Double indirect. */
1644 else if (fileblock < (INDIRECT_BLOCKS + (blksz / 4 * 1610 else if (fileblock < (INDIRECT_BLOCKS + (blksz / 4 *
1645 (blksz / 4 + 1)))) { 1611 (blksz / 4 + 1)))) {
1646 1612
1647 long int perblock = blksz / 4; 1613 long int perblock = blksz / 4;
1648 long int rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4); 1614 long int rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4);
1649 1615
1650 if (ext4fs_indir1_block == NULL) { 1616 if (ext4fs_indir1_block == NULL) {
1651 ext4fs_indir1_block = zalloc(blksz); 1617 ext4fs_indir1_block = zalloc(blksz);
1652 if (ext4fs_indir1_block == NULL) { 1618 if (ext4fs_indir1_block == NULL) {
1653 printf("** DI ext2fs read block (indir 2 1)" 1619 printf("** DI ext2fs read block (indir 2 1)"
1654 "malloc failed. **\n"); 1620 "malloc failed. **\n");
1655 return -1; 1621 return -1;
1656 } 1622 }
1657 ext4fs_indir1_size = blksz; 1623 ext4fs_indir1_size = blksz;
1658 ext4fs_indir1_blkno = -1; 1624 ext4fs_indir1_blkno = -1;
1659 } 1625 }
1660 if (blksz != ext4fs_indir1_size) { 1626 if (blksz != ext4fs_indir1_size) {
1661 free(ext4fs_indir1_block); 1627 free(ext4fs_indir1_block);
1662 ext4fs_indir1_block = NULL; 1628 ext4fs_indir1_block = NULL;
1663 ext4fs_indir1_size = 0; 1629 ext4fs_indir1_size = 0;
1664 ext4fs_indir1_blkno = -1; 1630 ext4fs_indir1_blkno = -1;
1665 ext4fs_indir1_block = zalloc(blksz); 1631 ext4fs_indir1_block = zalloc(blksz);
1666 if (ext4fs_indir1_block == NULL) { 1632 if (ext4fs_indir1_block == NULL) {
1667 printf("** DI ext2fs read block (indir 2 1)" 1633 printf("** DI ext2fs read block (indir 2 1)"
1668 "malloc failed. **\n"); 1634 "malloc failed. **\n");
1669 return -1; 1635 return -1;
1670 } 1636 }
1671 ext4fs_indir1_size = blksz; 1637 ext4fs_indir1_size = blksz;
1672 } 1638 }
1673 if ((__le32_to_cpu(inode->b.blocks.double_indir_block) << 1639 if ((__le32_to_cpu(inode->b.blocks.double_indir_block) <<
1674 log2_blksz) != ext4fs_indir1_blkno) { 1640 log2_blksz) != ext4fs_indir1_blkno) {
1675 status = 1641 status =
1676 ext4fs_devread((lbaint_t)__le32_to_cpu 1642 ext4fs_devread((lbaint_t)__le32_to_cpu
1677 (inode->b.blocks. 1643 (inode->b.blocks.
1678 double_indir_block) << log2_blksz, 1644 double_indir_block) << log2_blksz,
1679 0, blksz, 1645 0, blksz,
1680 (char *)ext4fs_indir1_block); 1646 (char *)ext4fs_indir1_block);
1681 if (status == 0) { 1647 if (status == 0) {
1682 printf("** DI ext2fs read block (indir 2 1)" 1648 printf("** DI ext2fs read block (indir 2 1)"
1683 "failed. **\n"); 1649 "failed. **\n");
1684 return -1; 1650 return -1;
1685 } 1651 }
1686 ext4fs_indir1_blkno = 1652 ext4fs_indir1_blkno =
1687 __le32_to_cpu(inode->b.blocks.double_indir_block) << 1653 __le32_to_cpu(inode->b.blocks.double_indir_block) <<
1688 log2_blksz; 1654 log2_blksz;
1689 } 1655 }
1690 1656
1691 if (ext4fs_indir2_block == NULL) { 1657 if (ext4fs_indir2_block == NULL) {
1692 ext4fs_indir2_block = zalloc(blksz); 1658 ext4fs_indir2_block = zalloc(blksz);
1693 if (ext4fs_indir2_block == NULL) { 1659 if (ext4fs_indir2_block == NULL) {
1694 printf("** DI ext2fs read block (indir 2 2)" 1660 printf("** DI ext2fs read block (indir 2 2)"
1695 "malloc failed. **\n"); 1661 "malloc failed. **\n");
1696 return -1; 1662 return -1;
1697 } 1663 }
1698 ext4fs_indir2_size = blksz; 1664 ext4fs_indir2_size = blksz;
1699 ext4fs_indir2_blkno = -1; 1665 ext4fs_indir2_blkno = -1;
1700 } 1666 }
1701 if (blksz != ext4fs_indir2_size) { 1667 if (blksz != ext4fs_indir2_size) {
1702 free(ext4fs_indir2_block); 1668 free(ext4fs_indir2_block);
1703 ext4fs_indir2_block = NULL; 1669 ext4fs_indir2_block = NULL;
1704 ext4fs_indir2_size = 0; 1670 ext4fs_indir2_size = 0;
1705 ext4fs_indir2_blkno = -1; 1671 ext4fs_indir2_blkno = -1;
1706 ext4fs_indir2_block = zalloc(blksz); 1672 ext4fs_indir2_block = zalloc(blksz);
1707 if (ext4fs_indir2_block == NULL) { 1673 if (ext4fs_indir2_block == NULL) {
1708 printf("** DI ext2fs read block (indir 2 2)" 1674 printf("** DI ext2fs read block (indir 2 2)"
1709 "malloc failed. **\n"); 1675 "malloc failed. **\n");
1710 return -1; 1676 return -1;
1711 } 1677 }
1712 ext4fs_indir2_size = blksz; 1678 ext4fs_indir2_size = blksz;
1713 } 1679 }
1714 if ((__le32_to_cpu(ext4fs_indir1_block[rblock / perblock]) << 1680 if ((__le32_to_cpu(ext4fs_indir1_block[rblock / perblock]) <<
1715 log2_blksz) != ext4fs_indir2_blkno) { 1681 log2_blksz) != ext4fs_indir2_blkno) {
1716 status = ext4fs_devread((lbaint_t)__le32_to_cpu 1682 status = ext4fs_devread((lbaint_t)__le32_to_cpu
1717 (ext4fs_indir1_block 1683 (ext4fs_indir1_block
1718 [rblock / 1684 [rblock /
1719 perblock]) << log2_blksz, 0, 1685 perblock]) << log2_blksz, 0,
1720 blksz, 1686 blksz,
1721 (char *)ext4fs_indir2_block); 1687 (char *)ext4fs_indir2_block);
1722 if (status == 0) { 1688 if (status == 0) {
1723 printf("** DI ext2fs read block (indir 2 2)" 1689 printf("** DI ext2fs read block (indir 2 2)"
1724 "failed. **\n"); 1690 "failed. **\n");
1725 return -1; 1691 return -1;
1726 } 1692 }
1727 ext4fs_indir2_blkno = 1693 ext4fs_indir2_blkno =
1728 __le32_to_cpu(ext4fs_indir1_block[rblock 1694 __le32_to_cpu(ext4fs_indir1_block[rblock
1729 / 1695 /
1730 perblock]) << 1696 perblock]) <<
1731 log2_blksz; 1697 log2_blksz;
1732 } 1698 }
1733 blknr = __le32_to_cpu(ext4fs_indir2_block[rblock % perblock]); 1699 blknr = __le32_to_cpu(ext4fs_indir2_block[rblock % perblock]);
1734 } 1700 }
1735 /* Tripple indirect. */ 1701 /* Tripple indirect. */
1736 else { 1702 else {
1737 rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4 + 1703 rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4 +
1738 (blksz / 4 * blksz / 4)); 1704 (blksz / 4 * blksz / 4));
1739 perblock_child = blksz / 4; 1705 perblock_child = blksz / 4;
1740 perblock_parent = ((blksz / 4) * (blksz / 4)); 1706 perblock_parent = ((blksz / 4) * (blksz / 4));
1741 1707
1742 if (ext4fs_indir1_block == NULL) { 1708 if (ext4fs_indir1_block == NULL) {
1743 ext4fs_indir1_block = zalloc(blksz); 1709 ext4fs_indir1_block = zalloc(blksz);
1744 if (ext4fs_indir1_block == NULL) { 1710 if (ext4fs_indir1_block == NULL) {
1745 printf("** TI ext2fs read block (indir 2 1)" 1711 printf("** TI ext2fs read block (indir 2 1)"
1746 "malloc failed. **\n"); 1712 "malloc failed. **\n");
1747 return -1; 1713 return -1;
1748 } 1714 }
1749 ext4fs_indir1_size = blksz; 1715 ext4fs_indir1_size = blksz;
1750 ext4fs_indir1_blkno = -1; 1716 ext4fs_indir1_blkno = -1;
1751 } 1717 }
1752 if (blksz != ext4fs_indir1_size) { 1718 if (blksz != ext4fs_indir1_size) {
1753 free(ext4fs_indir1_block); 1719 free(ext4fs_indir1_block);
1754 ext4fs_indir1_block = NULL; 1720 ext4fs_indir1_block = NULL;
1755 ext4fs_indir1_size = 0; 1721 ext4fs_indir1_size = 0;
1756 ext4fs_indir1_blkno = -1; 1722 ext4fs_indir1_blkno = -1;
1757 ext4fs_indir1_block = zalloc(blksz); 1723 ext4fs_indir1_block = zalloc(blksz);
1758 if (ext4fs_indir1_block == NULL) { 1724 if (ext4fs_indir1_block == NULL) {
1759 printf("** TI ext2fs read block (indir 2 1)" 1725 printf("** TI ext2fs read block (indir 2 1)"
1760 "malloc failed. **\n"); 1726 "malloc failed. **\n");
1761 return -1; 1727 return -1;
1762 } 1728 }
1763 ext4fs_indir1_size = blksz; 1729 ext4fs_indir1_size = blksz;
1764 } 1730 }
1765 if ((__le32_to_cpu(inode->b.blocks.triple_indir_block) << 1731 if ((__le32_to_cpu(inode->b.blocks.triple_indir_block) <<
1766 log2_blksz) != ext4fs_indir1_blkno) { 1732 log2_blksz) != ext4fs_indir1_blkno) {
1767 status = ext4fs_devread 1733 status = ext4fs_devread
1768 ((lbaint_t) 1734 ((lbaint_t)
1769 __le32_to_cpu(inode->b.blocks.triple_indir_block) 1735 __le32_to_cpu(inode->b.blocks.triple_indir_block)
1770 << log2_blksz, 0, blksz, 1736 << log2_blksz, 0, blksz,
1771 (char *)ext4fs_indir1_block); 1737 (char *)ext4fs_indir1_block);
1772 if (status == 0) { 1738 if (status == 0) {
1773 printf("** TI ext2fs read block (indir 2 1)" 1739 printf("** TI ext2fs read block (indir 2 1)"
1774 "failed. **\n"); 1740 "failed. **\n");
1775 return -1; 1741 return -1;
1776 } 1742 }
1777 ext4fs_indir1_blkno = 1743 ext4fs_indir1_blkno =
1778 __le32_to_cpu(inode->b.blocks.triple_indir_block) << 1744 __le32_to_cpu(inode->b.blocks.triple_indir_block) <<
1779 log2_blksz; 1745 log2_blksz;
1780 } 1746 }
1781 1747
1782 if (ext4fs_indir2_block == NULL) { 1748 if (ext4fs_indir2_block == NULL) {
1783 ext4fs_indir2_block = zalloc(blksz); 1749 ext4fs_indir2_block = zalloc(blksz);
1784 if (ext4fs_indir2_block == NULL) { 1750 if (ext4fs_indir2_block == NULL) {
1785 printf("** TI ext2fs read block (indir 2 2)" 1751 printf("** TI ext2fs read block (indir 2 2)"
1786 "malloc failed. **\n"); 1752 "malloc failed. **\n");
1787 return -1; 1753 return -1;
1788 } 1754 }
1789 ext4fs_indir2_size = blksz; 1755 ext4fs_indir2_size = blksz;
1790 ext4fs_indir2_blkno = -1; 1756 ext4fs_indir2_blkno = -1;
1791 } 1757 }
1792 if (blksz != ext4fs_indir2_size) { 1758 if (blksz != ext4fs_indir2_size) {
1793 free(ext4fs_indir2_block); 1759 free(ext4fs_indir2_block);
1794 ext4fs_indir2_block = NULL; 1760 ext4fs_indir2_block = NULL;
1795 ext4fs_indir2_size = 0; 1761 ext4fs_indir2_size = 0;
1796 ext4fs_indir2_blkno = -1; 1762 ext4fs_indir2_blkno = -1;
1797 ext4fs_indir2_block = zalloc(blksz); 1763 ext4fs_indir2_block = zalloc(blksz);
1798 if (ext4fs_indir2_block == NULL) { 1764 if (ext4fs_indir2_block == NULL) {
1799 printf("** TI ext2fs read block (indir 2 2)" 1765 printf("** TI ext2fs read block (indir 2 2)"
1800 "malloc failed. **\n"); 1766 "malloc failed. **\n");
1801 return -1; 1767 return -1;
1802 } 1768 }
1803 ext4fs_indir2_size = blksz; 1769 ext4fs_indir2_size = blksz;
1804 } 1770 }
1805 if ((__le32_to_cpu(ext4fs_indir1_block[rblock / 1771 if ((__le32_to_cpu(ext4fs_indir1_block[rblock /
1806 perblock_parent]) << 1772 perblock_parent]) <<
1807 log2_blksz) 1773 log2_blksz)
1808 != ext4fs_indir2_blkno) { 1774 != ext4fs_indir2_blkno) {
1809 status = ext4fs_devread((lbaint_t)__le32_to_cpu 1775 status = ext4fs_devread((lbaint_t)__le32_to_cpu
1810 (ext4fs_indir1_block 1776 (ext4fs_indir1_block
1811 [rblock / 1777 [rblock /
1812 perblock_parent]) << 1778 perblock_parent]) <<
1813 log2_blksz, 0, blksz, 1779 log2_blksz, 0, blksz,
1814 (char *)ext4fs_indir2_block); 1780 (char *)ext4fs_indir2_block);
1815 if (status == 0) { 1781 if (status == 0) {
1816 printf("** TI ext2fs read block (indir 2 2)" 1782 printf("** TI ext2fs read block (indir 2 2)"
1817 "failed. **\n"); 1783 "failed. **\n");
1818 return -1; 1784 return -1;
1819 } 1785 }
1820 ext4fs_indir2_blkno = 1786 ext4fs_indir2_blkno =
1821 __le32_to_cpu(ext4fs_indir1_block[rblock / 1787 __le32_to_cpu(ext4fs_indir1_block[rblock /
1822 perblock_parent]) 1788 perblock_parent])
1823 << log2_blksz; 1789 << log2_blksz;
1824 } 1790 }
1825 1791
1826 if (ext4fs_indir3_block == NULL) { 1792 if (ext4fs_indir3_block == NULL) {
1827 ext4fs_indir3_block = zalloc(blksz); 1793 ext4fs_indir3_block = zalloc(blksz);
1828 if (ext4fs_indir3_block == NULL) { 1794 if (ext4fs_indir3_block == NULL) {
1829 printf("** TI ext2fs read block (indir 2 2)" 1795 printf("** TI ext2fs read block (indir 2 2)"
1830 "malloc failed. **\n"); 1796 "malloc failed. **\n");
1831 return -1; 1797 return -1;
1832 } 1798 }
1833 ext4fs_indir3_size = blksz; 1799 ext4fs_indir3_size = blksz;
1834 ext4fs_indir3_blkno = -1; 1800 ext4fs_indir3_blkno = -1;
1835 } 1801 }
1836 if (blksz != ext4fs_indir3_size) { 1802 if (blksz != ext4fs_indir3_size) {
1837 free(ext4fs_indir3_block); 1803 free(ext4fs_indir3_block);
1838 ext4fs_indir3_block = NULL; 1804 ext4fs_indir3_block = NULL;
1839 ext4fs_indir3_size = 0; 1805 ext4fs_indir3_size = 0;
1840 ext4fs_indir3_blkno = -1; 1806 ext4fs_indir3_blkno = -1;
1841 ext4fs_indir3_block = zalloc(blksz); 1807 ext4fs_indir3_block = zalloc(blksz);
1842 if (ext4fs_indir3_block == NULL) { 1808 if (ext4fs_indir3_block == NULL) {
1843 printf("** TI ext2fs read block (indir 2 2)" 1809 printf("** TI ext2fs read block (indir 2 2)"
1844 "malloc failed. **\n"); 1810 "malloc failed. **\n");
1845 return -1; 1811 return -1;
1846 } 1812 }
1847 ext4fs_indir3_size = blksz; 1813 ext4fs_indir3_size = blksz;
1848 } 1814 }
1849 if ((__le32_to_cpu(ext4fs_indir2_block[rblock 1815 if ((__le32_to_cpu(ext4fs_indir2_block[rblock
1850 / 1816 /
1851 perblock_child]) << 1817 perblock_child]) <<
1852 log2_blksz) != ext4fs_indir3_blkno) { 1818 log2_blksz) != ext4fs_indir3_blkno) {
1853 status = 1819 status =
1854 ext4fs_devread((lbaint_t)__le32_to_cpu 1820 ext4fs_devread((lbaint_t)__le32_to_cpu
1855 (ext4fs_indir2_block 1821 (ext4fs_indir2_block
1856 [(rblock / perblock_child) 1822 [(rblock / perblock_child)
1857 % (blksz / 4)]) << log2_blksz, 0, 1823 % (blksz / 4)]) << log2_blksz, 0,
1858 blksz, (char *)ext4fs_indir3_block); 1824 blksz, (char *)ext4fs_indir3_block);
1859 if (status == 0) { 1825 if (status == 0) {
1860 printf("** TI ext2fs read block (indir 2 2)" 1826 printf("** TI ext2fs read block (indir 2 2)"
1861 "failed. **\n"); 1827 "failed. **\n");
1862 return -1; 1828 return -1;
1863 } 1829 }
1864 ext4fs_indir3_blkno = 1830 ext4fs_indir3_blkno =
1865 __le32_to_cpu(ext4fs_indir2_block[(rblock / 1831 __le32_to_cpu(ext4fs_indir2_block[(rblock /
1866 perblock_child) % 1832 perblock_child) %
1867 (blksz / 1833 (blksz /
1868 4)]) << 1834 4)]) <<
1869 log2_blksz; 1835 log2_blksz;
1870 } 1836 }
1871 1837
1872 blknr = __le32_to_cpu(ext4fs_indir3_block 1838 blknr = __le32_to_cpu(ext4fs_indir3_block
1873 [rblock % perblock_child]); 1839 [rblock % perblock_child]);
1874 } 1840 }
1875 debug("read_allocated_block %ld\n", blknr); 1841 debug("read_allocated_block %ld\n", blknr);
1876 1842
1877 return blknr; 1843 return blknr;
1878 } 1844 }
1879 1845
1880 void ext4fs_close(void) 1846 void ext4fs_close(void)
1881 { 1847 {
1882 if ((ext4fs_file != NULL) && (ext4fs_root != NULL)) { 1848 if ((ext4fs_file != NULL) && (ext4fs_root != NULL)) {
1883 ext4fs_free_node(ext4fs_file, &ext4fs_root->diropen); 1849 ext4fs_free_node(ext4fs_file, &ext4fs_root->diropen);
1884 ext4fs_file = NULL; 1850 ext4fs_file = NULL;
1885 } 1851 }
1886 if (ext4fs_root != NULL) { 1852 if (ext4fs_root != NULL) {
1887 free(ext4fs_root); 1853 free(ext4fs_root);
1888 ext4fs_root = NULL; 1854 ext4fs_root = NULL;
1889 } 1855 }
1890 if (ext4fs_indir1_block != NULL) { 1856 if (ext4fs_indir1_block != NULL) {
1891 free(ext4fs_indir1_block); 1857 free(ext4fs_indir1_block);
1892 ext4fs_indir1_block = NULL; 1858 ext4fs_indir1_block = NULL;
1893 ext4fs_indir1_size = 0; 1859 ext4fs_indir1_size = 0;
1894 ext4fs_indir1_blkno = -1; 1860 ext4fs_indir1_blkno = -1;
1895 } 1861 }
1896 if (ext4fs_indir2_block != NULL) { 1862 if (ext4fs_indir2_block != NULL) {
1897 free(ext4fs_indir2_block); 1863 free(ext4fs_indir2_block);
1898 ext4fs_indir2_block = NULL; 1864 ext4fs_indir2_block = NULL;
1899 ext4fs_indir2_size = 0; 1865 ext4fs_indir2_size = 0;
1900 ext4fs_indir2_blkno = -1; 1866 ext4fs_indir2_blkno = -1;
1901 } 1867 }
1902 if (ext4fs_indir3_block != NULL) { 1868 if (ext4fs_indir3_block != NULL) {
1903 free(ext4fs_indir3_block); 1869 free(ext4fs_indir3_block);
1904 ext4fs_indir3_block = NULL; 1870 ext4fs_indir3_block = NULL;
1905 ext4fs_indir3_size = 0; 1871 ext4fs_indir3_size = 0;
1906 ext4fs_indir3_blkno = -1; 1872 ext4fs_indir3_blkno = -1;
1907 } 1873 }
1908 } 1874 }
1909 1875
1910 int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name, 1876 int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name,
1911 struct ext2fs_node **fnode, int *ftype) 1877 struct ext2fs_node **fnode, int *ftype)
1912 { 1878 {
1913 unsigned int fpos = 0; 1879 unsigned int fpos = 0;
1914 int status; 1880 int status;
1915 struct ext2fs_node *diro = (struct ext2fs_node *) dir; 1881 struct ext2fs_node *diro = (struct ext2fs_node *) dir;
1916 1882
1917 #ifdef DEBUG 1883 #ifdef DEBUG
1918 if (name != NULL) 1884 if (name != NULL)
1919 printf("Iterate dir %s\n", name); 1885 printf("Iterate dir %s\n", name);
1920 #endif /* of DEBUG */ 1886 #endif /* of DEBUG */
1921 if (!diro->inode_read) { 1887 if (!diro->inode_read) {
1922 status = ext4fs_read_inode(diro->data, diro->ino, &diro->inode); 1888 status = ext4fs_read_inode(diro->data, diro->ino, &diro->inode);
1923 if (status == 0) 1889 if (status == 0)
1924 return 0; 1890 return 0;
1925 } 1891 }
1926 /* Search the file. */ 1892 /* Search the file. */
1927 while (fpos < __le32_to_cpu(diro->inode.size)) { 1893 while (fpos < __le32_to_cpu(diro->inode.size)) {
1928 struct ext2_dirent dirent; 1894 struct ext2_dirent dirent;
1929 1895
1930 status = ext4fs_read_file(diro, fpos, 1896 status = ext4fs_read_file(diro, fpos,
1931 sizeof(struct ext2_dirent), 1897 sizeof(struct ext2_dirent),
1932 (char *) &dirent); 1898 (char *) &dirent);
1933 if (status < 1) 1899 if (status < 1)
1934 return 0; 1900 return 0;
1935 1901
1936 if (dirent.namelen != 0) { 1902 if (dirent.namelen != 0) {
1937 char filename[dirent.namelen + 1]; 1903 char filename[dirent.namelen + 1];
1938 struct ext2fs_node *fdiro; 1904 struct ext2fs_node *fdiro;
1939 int type = FILETYPE_UNKNOWN; 1905 int type = FILETYPE_UNKNOWN;
1940 1906
1941 status = ext4fs_read_file(diro, 1907 status = ext4fs_read_file(diro,
1942 fpos + 1908 fpos +
1943 sizeof(struct ext2_dirent), 1909 sizeof(struct ext2_dirent),
1944 dirent.namelen, filename); 1910 dirent.namelen, filename);
1945 if (status < 1) 1911 if (status < 1)
1946 return 0; 1912 return 0;
1947 1913
1948 fdiro = zalloc(sizeof(struct ext2fs_node)); 1914 fdiro = zalloc(sizeof(struct ext2fs_node));
1949 if (!fdiro) 1915 if (!fdiro)
1950 return 0; 1916 return 0;
1951 1917
1952 fdiro->data = diro->data; 1918 fdiro->data = diro->data;
1953 fdiro->ino = __le32_to_cpu(dirent.inode); 1919 fdiro->ino = __le32_to_cpu(dirent.inode);
1954 1920
1955 filename[dirent.namelen] = '\0'; 1921 filename[dirent.namelen] = '\0';
1956 1922
1957 if (dirent.filetype != FILETYPE_UNKNOWN) { 1923 if (dirent.filetype != FILETYPE_UNKNOWN) {
1958 fdiro->inode_read = 0; 1924 fdiro->inode_read = 0;
1959 1925
1960 if (dirent.filetype == FILETYPE_DIRECTORY) 1926 if (dirent.filetype == FILETYPE_DIRECTORY)
1961 type = FILETYPE_DIRECTORY; 1927 type = FILETYPE_DIRECTORY;
1962 else if (dirent.filetype == FILETYPE_SYMLINK) 1928 else if (dirent.filetype == FILETYPE_SYMLINK)
1963 type = FILETYPE_SYMLINK; 1929 type = FILETYPE_SYMLINK;
1964 else if (dirent.filetype == FILETYPE_REG) 1930 else if (dirent.filetype == FILETYPE_REG)
1965 type = FILETYPE_REG; 1931 type = FILETYPE_REG;
1966 } else { 1932 } else {
1967 status = ext4fs_read_inode(diro->data, 1933 status = ext4fs_read_inode(diro->data,
1968 __le32_to_cpu 1934 __le32_to_cpu
1969 (dirent.inode), 1935 (dirent.inode),
1970 &fdiro->inode); 1936 &fdiro->inode);
1971 if (status == 0) { 1937 if (status == 0) {
1972 free(fdiro); 1938 free(fdiro);
1973 return 0; 1939 return 0;
1974 } 1940 }
1975 fdiro->inode_read = 1; 1941 fdiro->inode_read = 1;
1976 1942
1977 if ((__le16_to_cpu(fdiro->inode.mode) & 1943 if ((__le16_to_cpu(fdiro->inode.mode) &
1978 FILETYPE_INO_MASK) == 1944 FILETYPE_INO_MASK) ==
1979 FILETYPE_INO_DIRECTORY) { 1945 FILETYPE_INO_DIRECTORY) {
1980 type = FILETYPE_DIRECTORY; 1946 type = FILETYPE_DIRECTORY;
1981 } else if ((__le16_to_cpu(fdiro->inode.mode) 1947 } else if ((__le16_to_cpu(fdiro->inode.mode)
1982 & FILETYPE_INO_MASK) == 1948 & FILETYPE_INO_MASK) ==
1983 FILETYPE_INO_SYMLINK) { 1949 FILETYPE_INO_SYMLINK) {
1984 type = FILETYPE_SYMLINK; 1950 type = FILETYPE_SYMLINK;
1985 } else if ((__le16_to_cpu(fdiro->inode.mode) 1951 } else if ((__le16_to_cpu(fdiro->inode.mode)
1986 & FILETYPE_INO_MASK) == 1952 & FILETYPE_INO_MASK) ==
1987 FILETYPE_INO_REG) { 1953 FILETYPE_INO_REG) {
1988 type = FILETYPE_REG; 1954 type = FILETYPE_REG;
1989 } 1955 }
1990 } 1956 }
1991 #ifdef DEBUG 1957 #ifdef DEBUG
1992 printf("iterate >%s<\n", filename); 1958 printf("iterate >%s<\n", filename);
1993 #endif /* of DEBUG */ 1959 #endif /* of DEBUG */
1994 if ((name != NULL) && (fnode != NULL) 1960 if ((name != NULL) && (fnode != NULL)
1995 && (ftype != NULL)) { 1961 && (ftype != NULL)) {
1996 if (strcmp(filename, name) == 0) { 1962 if (strcmp(filename, name) == 0) {
1997 *ftype = type; 1963 *ftype = type;
1998 *fnode = fdiro; 1964 *fnode = fdiro;
1999 return 1; 1965 return 1;
2000 } 1966 }
2001 } else { 1967 } else {
2002 if (fdiro->inode_read == 0) { 1968 if (fdiro->inode_read == 0) {
2003 status = ext4fs_read_inode(diro->data, 1969 status = ext4fs_read_inode(diro->data,
2004 __le32_to_cpu( 1970 __le32_to_cpu(
2005 dirent.inode), 1971 dirent.inode),
2006 &fdiro->inode); 1972 &fdiro->inode);
2007 if (status == 0) { 1973 if (status == 0) {
2008 free(fdiro); 1974 free(fdiro);
2009 return 0; 1975 return 0;
2010 } 1976 }
2011 fdiro->inode_read = 1; 1977 fdiro->inode_read = 1;
2012 } 1978 }
2013 switch (type) { 1979 switch (type) {
2014 case FILETYPE_DIRECTORY: 1980 case FILETYPE_DIRECTORY:
2015 printf("<DIR> "); 1981 printf("<DIR> ");
2016 break; 1982 break;
2017 case FILETYPE_SYMLINK: 1983 case FILETYPE_SYMLINK:
2018 printf("<SYM> "); 1984 printf("<SYM> ");
2019 break; 1985 break;
2020 case FILETYPE_REG: 1986 case FILETYPE_REG:
2021 printf(" "); 1987 printf(" ");
2022 break; 1988 break;
2023 default: 1989 default:
2024 printf("< ? > "); 1990 printf("< ? > ");
2025 break; 1991 break;
2026 } 1992 }
2027 printf("%10d %s\n", 1993 printf("%10d %s\n",
2028 __le32_to_cpu(fdiro->inode.size), 1994 __le32_to_cpu(fdiro->inode.size),
2029 filename); 1995 filename);
2030 } 1996 }
2031 free(fdiro); 1997 free(fdiro);
2032 } 1998 }
2033 fpos += __le16_to_cpu(dirent.direntlen); 1999 fpos += __le16_to_cpu(dirent.direntlen);
2034 } 2000 }
2035 return 0; 2001 return 0;
2036 } 2002 }
2037 2003
2038 static char *ext4fs_read_symlink(struct ext2fs_node *node) 2004 static char *ext4fs_read_symlink(struct ext2fs_node *node)
2039 { 2005 {
2040 char *symlink; 2006 char *symlink;
2041 struct ext2fs_node *diro = node; 2007 struct ext2fs_node *diro = node;
2042 int status; 2008 int status;
2043 2009
2044 if (!diro->inode_read) { 2010 if (!diro->inode_read) {
2045 status = ext4fs_read_inode(diro->data, diro->ino, &diro->inode); 2011 status = ext4fs_read_inode(diro->data, diro->ino, &diro->inode);
2046 if (status == 0) 2012 if (status == 0)
2047 return 0; 2013 return 0;
2048 } 2014 }
2049 symlink = zalloc(__le32_to_cpu(diro->inode.size) + 1); 2015 symlink = zalloc(__le32_to_cpu(diro->inode.size) + 1);
2050 if (!symlink) 2016 if (!symlink)
2051 return 0; 2017 return 0;
2052 2018
2053 if (__le32_to_cpu(diro->inode.size) <= 60) { 2019 if (__le32_to_cpu(diro->inode.size) <= 60) {
2054 strncpy(symlink, diro->inode.b.symlink, 2020 strncpy(symlink, diro->inode.b.symlink,
2055 __le32_to_cpu(diro->inode.size)); 2021 __le32_to_cpu(diro->inode.size));
2056 } else { 2022 } else {
2057 status = ext4fs_read_file(diro, 0, 2023 status = ext4fs_read_file(diro, 0,
2058 __le32_to_cpu(diro->inode.size), 2024 __le32_to_cpu(diro->inode.size),
2059 symlink); 2025 symlink);
2060 if (status == 0) { 2026 if (status == 0) {
2061 free(symlink); 2027 free(symlink);
2062 return 0; 2028 return 0;
2063 } 2029 }
2064 } 2030 }
2065 symlink[__le32_to_cpu(diro->inode.size)] = '\0'; 2031 symlink[__le32_to_cpu(diro->inode.size)] = '\0';
2066 return symlink; 2032 return symlink;
2067 } 2033 }
2068 2034
2069 static int ext4fs_find_file1(const char *currpath, 2035 static int ext4fs_find_file1(const char *currpath,
2070 struct ext2fs_node *currroot, 2036 struct ext2fs_node *currroot,
2071 struct ext2fs_node **currfound, int *foundtype) 2037 struct ext2fs_node **currfound, int *foundtype)
2072 { 2038 {
2073 char fpath[strlen(currpath) + 1]; 2039 char fpath[strlen(currpath) + 1];
2074 char *name = fpath; 2040 char *name = fpath;
2075 char *next; 2041 char *next;
2076 int status; 2042 int status;
2077 int type = FILETYPE_DIRECTORY; 2043 int type = FILETYPE_DIRECTORY;
2078 struct ext2fs_node *currnode = currroot; 2044 struct ext2fs_node *currnode = currroot;
2079 struct ext2fs_node *oldnode = currroot; 2045 struct ext2fs_node *oldnode = currroot;
2080 2046
2081 strncpy(fpath, currpath, strlen(currpath) + 1); 2047 strncpy(fpath, currpath, strlen(currpath) + 1);
2082 2048
2083 /* Remove all leading slashes. */ 2049 /* Remove all leading slashes. */
2084 while (*name == '/') 2050 while (*name == '/')
2085 name++; 2051 name++;
2086 2052
2087 if (!*name) { 2053 if (!*name) {
2088 *currfound = currnode; 2054 *currfound = currnode;
2089 return 1; 2055 return 1;
2090 } 2056 }
2091 2057
2092 for (;;) { 2058 for (;;) {
2093 int found; 2059 int found;
2094 2060
2095 /* Extract the actual part from the pathname. */ 2061 /* Extract the actual part from the pathname. */
2096 next = strchr(name, '/'); 2062 next = strchr(name, '/');
2097 if (next) { 2063 if (next) {
2098 /* Remove all leading slashes. */ 2064 /* Remove all leading slashes. */
2099 while (*next == '/') 2065 while (*next == '/')
2100 *(next++) = '\0'; 2066 *(next++) = '\0';
2101 } 2067 }
2102 2068
2103 if (type != FILETYPE_DIRECTORY) { 2069 if (type != FILETYPE_DIRECTORY) {
2104 ext4fs_free_node(currnode, currroot); 2070 ext4fs_free_node(currnode, currroot);
2105 return 0; 2071 return 0;
2106 } 2072 }
2107 2073
2108 oldnode = currnode; 2074 oldnode = currnode;
2109 2075
2110 /* Iterate over the directory. */ 2076 /* Iterate over the directory. */
2111 found = ext4fs_iterate_dir(currnode, name, &currnode, &type); 2077 found = ext4fs_iterate_dir(currnode, name, &currnode, &type);
2112 if (found == 0) 2078 if (found == 0)
2113 return 0; 2079 return 0;
2114 2080
2115 if (found == -1) 2081 if (found == -1)
2116 break; 2082 break;
2117 2083
2118 /* Read in the symlink and follow it. */ 2084 /* Read in the symlink and follow it. */
2119 if (type == FILETYPE_SYMLINK) { 2085 if (type == FILETYPE_SYMLINK) {
2120 char *symlink; 2086 char *symlink;
2121 2087
2122 /* Test if the symlink does not loop. */ 2088 /* Test if the symlink does not loop. */
2123 if (++symlinknest == 8) { 2089 if (++symlinknest == 8) {
2124 ext4fs_free_node(currnode, currroot); 2090 ext4fs_free_node(currnode, currroot);
2125 ext4fs_free_node(oldnode, currroot); 2091 ext4fs_free_node(oldnode, currroot);
2126 return 0; 2092 return 0;
2127 } 2093 }
2128 2094
2129 symlink = ext4fs_read_symlink(currnode); 2095 symlink = ext4fs_read_symlink(currnode);
2130 ext4fs_free_node(currnode, currroot); 2096 ext4fs_free_node(currnode, currroot);
2131 2097
2132 if (!symlink) { 2098 if (!symlink) {
2133 ext4fs_free_node(oldnode, currroot); 2099 ext4fs_free_node(oldnode, currroot);
2134 return 0; 2100 return 0;
2135 } 2101 }
2136 2102
2137 debug("Got symlink >%s<\n", symlink); 2103 debug("Got symlink >%s<\n", symlink);
2138 2104
2139 if (symlink[0] == '/') { 2105 if (symlink[0] == '/') {
2140 ext4fs_free_node(oldnode, currroot); 2106 ext4fs_free_node(oldnode, currroot);
2141 oldnode = &ext4fs_root->diropen; 2107 oldnode = &ext4fs_root->diropen;
2142 } 2108 }
2143 2109
2144 /* Lookup the node the symlink points to. */ 2110 /* Lookup the node the symlink points to. */
2145 status = ext4fs_find_file1(symlink, oldnode, 2111 status = ext4fs_find_file1(symlink, oldnode,
2146 &currnode, &type); 2112 &currnode, &type);
2147 2113
2148 free(symlink); 2114 free(symlink);
2149 2115
2150 if (status == 0) { 2116 if (status == 0) {
2151 ext4fs_free_node(oldnode, currroot); 2117 ext4fs_free_node(oldnode, currroot);
2152 return 0; 2118 return 0;
2153 } 2119 }
2154 } 2120 }
2155 2121
2156 ext4fs_free_node(oldnode, currroot); 2122 ext4fs_free_node(oldnode, currroot);
2157 2123
2158 /* Found the node! */ 2124 /* Found the node! */
2159 if (!next || *next == '\0') { 2125 if (!next || *next == '\0') {
2160 *currfound = currnode; 2126 *currfound = currnode;
2161 *foundtype = type; 2127 *foundtype = type;
2162 return 1; 2128 return 1;
2163 } 2129 }
2164 name = next; 2130 name = next;
2165 } 2131 }
2166 return -1; 2132 return -1;
2167 } 2133 }
2168 2134
2169 int ext4fs_find_file(const char *path, struct ext2fs_node *rootnode, 2135 int ext4fs_find_file(const char *path, struct ext2fs_node *rootnode,
2170 struct ext2fs_node **foundnode, int expecttype) 2136 struct ext2fs_node **foundnode, int expecttype)
2171 { 2137 {
2172 int status; 2138 int status;
2173 int foundtype = FILETYPE_DIRECTORY; 2139 int foundtype = FILETYPE_DIRECTORY;
2174 2140
2175 symlinknest = 0; 2141 symlinknest = 0;
2176 if (!path) 2142 if (!path)
2177 return 0; 2143 return 0;
2178 2144
2179 status = ext4fs_find_file1(path, rootnode, foundnode, &foundtype); 2145 status = ext4fs_find_file1(path, rootnode, foundnode, &foundtype);
2180 if (status == 0) 2146 if (status == 0)
2181 return 0; 2147 return 0;
2182 2148
2183 /* Check if the node that was found was of the expected type. */ 2149 /* Check if the node that was found was of the expected type. */
2184 if ((expecttype == FILETYPE_REG) && (foundtype != expecttype)) 2150 if ((expecttype == FILETYPE_REG) && (foundtype != expecttype))
2185 return 0; 2151 return 0;
2186 else if ((expecttype == FILETYPE_DIRECTORY) 2152 else if ((expecttype == FILETYPE_DIRECTORY)
2187 && (foundtype != expecttype)) 2153 && (foundtype != expecttype))
2188 return 0; 2154 return 0;
2189 2155
2190 return 1; 2156 return 1;
2191 } 2157 }
2192 2158
2193 int ext4fs_open(const char *filename) 2159 int ext4fs_open(const char *filename)
2194 { 2160 {
2195 struct ext2fs_node *fdiro = NULL; 2161 struct ext2fs_node *fdiro = NULL;
2196 int status; 2162 int status;
2197 int len; 2163 int len;
2198 2164
2199 if (ext4fs_root == NULL) 2165 if (ext4fs_root == NULL)
2200 return -1; 2166 return -1;
2201 2167
2202 ext4fs_file = NULL; 2168 ext4fs_file = NULL;
2203 status = ext4fs_find_file(filename, &ext4fs_root->diropen, &fdiro, 2169 status = ext4fs_find_file(filename, &ext4fs_root->diropen, &fdiro,
2204 FILETYPE_REG); 2170 FILETYPE_REG);
2205 if (status == 0) 2171 if (status == 0)
2206 goto fail; 2172 goto fail;
2207 2173
2208 if (!fdiro->inode_read) { 2174 if (!fdiro->inode_read) {
2209 status = ext4fs_read_inode(fdiro->data, fdiro->ino, 2175 status = ext4fs_read_inode(fdiro->data, fdiro->ino,
2210 &fdiro->inode); 2176 &fdiro->inode);
2211 if (status == 0) 2177 if (status == 0)
2212 goto fail; 2178 goto fail;
2213 } 2179 }
2214 len = __le32_to_cpu(fdiro->inode.size); 2180 len = __le32_to_cpu(fdiro->inode.size);
2215 ext4fs_file = fdiro; 2181 ext4fs_file = fdiro;
2216 2182
2217 return len; 2183 return len;
2218 fail: 2184 fail:
2219 ext4fs_free_node(fdiro, &ext4fs_root->diropen); 2185 ext4fs_free_node(fdiro, &ext4fs_root->diropen);
2220 2186
2221 return -1; 2187 return -1;
2222 } 2188 }
2223 2189
2224 int ext4fs_mount(unsigned part_length) 2190 int ext4fs_mount(unsigned part_length)
2225 { 2191 {
2226 struct ext2_data *data; 2192 struct ext2_data *data;
2227 int status; 2193 int status;
2228 struct ext_filesystem *fs = get_fs(); 2194 struct ext_filesystem *fs = get_fs();
2229 data = zalloc(SUPERBLOCK_SIZE); 2195 data = zalloc(SUPERBLOCK_SIZE);
fs/ext4/ext4_common.h
1 /* 1 /*
2 * (C) Copyright 2011 - 2012 Samsung Electronics 2 * (C) Copyright 2011 - 2012 Samsung Electronics
3 * EXT4 filesystem implementation in Uboot by 3 * EXT4 filesystem implementation in Uboot by
4 * Uma Shankar <uma.shankar@samsung.com> 4 * Uma Shankar <uma.shankar@samsung.com>
5 * Manjunatha C Achar <a.manjunatha@samsung.com> 5 * Manjunatha C Achar <a.manjunatha@samsung.com>
6 * 6 *
7 * ext4ls and ext4load : based on ext2 ls load support in Uboot. 7 * ext4ls and ext4load : based on ext2 ls load support in Uboot.
8 * 8 *
9 * (C) Copyright 2004 9 * (C) Copyright 2004
10 * esd gmbh <www.esd-electronics.com> 10 * esd gmbh <www.esd-electronics.com>
11 * Reinhard Arlt <reinhard.arlt@esd-electronics.com> 11 * Reinhard Arlt <reinhard.arlt@esd-electronics.com>
12 * 12 *
13 * based on code from grub2 fs/ext2.c and fs/fshelp.c by 13 * based on code from grub2 fs/ext2.c and fs/fshelp.c by
14 * GRUB -- GRand Unified Bootloader 14 * GRUB -- GRand Unified Bootloader
15 * Copyright (C) 2003, 2004 Free Software Foundation, Inc. 15 * Copyright (C) 2003, 2004 Free Software Foundation, Inc.
16 * 16 *
17 * ext4write : Based on generic ext4 protocol. 17 * ext4write : Based on generic ext4 protocol.
18 * 18 *
19 * SPDX-License-Identifier: GPL-2.0+ 19 * SPDX-License-Identifier: GPL-2.0+
20 */ 20 */
21 21
22 #ifndef __EXT4_COMMON__ 22 #ifndef __EXT4_COMMON__
23 #define __EXT4_COMMON__ 23 #define __EXT4_COMMON__
24 #include <ext_common.h> 24 #include <ext_common.h>
25 #include <ext4fs.h> 25 #include <ext4fs.h>
26 #include <malloc.h> 26 #include <malloc.h>
27 #include <asm/errno.h> 27 #include <asm/errno.h>
28 #if defined(CONFIG_EXT4_WRITE) 28 #if defined(CONFIG_EXT4_WRITE)
29 #include "ext4_journal.h" 29 #include "ext4_journal.h"
30 #include "crc16.h" 30 #include "crc16.h"
31 #endif 31 #endif
32 32
33 #define YES 1 33 #define YES 1
34 #define NO 0 34 #define NO 0
35 #define RECOVER 1 35 #define RECOVER 1
36 #define SCAN 0 36 #define SCAN 0
37 37
38 #define S_IFLNK 0120000 /* symbolic link */ 38 #define S_IFLNK 0120000 /* symbolic link */
39 #define BLOCK_NO_ONE 1 39 #define BLOCK_NO_ONE 1
40 #define SUPERBLOCK_START (2 * 512) 40 #define SUPERBLOCK_START (2 * 512)
41 #define SUPERBLOCK_SIZE 1024 41 #define SUPERBLOCK_SIZE 1024
42 #define F_FILE 1 42 #define F_FILE 1
43 43
44 static inline void *zalloc(size_t size) 44 static inline void *zalloc(size_t size)
45 { 45 {
46 void *p = memalign(ARCH_DMA_MINALIGN, size); 46 void *p = memalign(ARCH_DMA_MINALIGN, size);
47 memset(p, 0, size); 47 memset(p, 0, size);
48 return p; 48 return p;
49 } 49 }
50 50
51 int ext4fs_read_inode(struct ext2_data *data, int ino, 51 int ext4fs_read_inode(struct ext2_data *data, int ino,
52 struct ext2_inode *inode); 52 struct ext2_inode *inode);
53 int ext4fs_read_file(struct ext2fs_node *node, int pos, 53 int ext4fs_read_file(struct ext2fs_node *node, int pos,
54 unsigned int len, char *buf); 54 unsigned int len, char *buf);
55 int ext4fs_find_file(const char *path, struct ext2fs_node *rootnode, 55 int ext4fs_find_file(const char *path, struct ext2fs_node *rootnode,
56 struct ext2fs_node **foundnode, int expecttype); 56 struct ext2fs_node **foundnode, int expecttype);
57 int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name, 57 int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name,
58 struct ext2fs_node **fnode, int *ftype); 58 struct ext2fs_node **fnode, int *ftype);
59 59
60 int ext4fs_build_extent_cache(struct ext2_inode *inode);
61 void ext4fs_free_extent_cache(void);
62
63 #if defined(CONFIG_EXT4_WRITE) 60 #if defined(CONFIG_EXT4_WRITE)
64 uint32_t ext4fs_div_roundup(uint32_t size, uint32_t n); 61 uint32_t ext4fs_div_roundup(uint32_t size, uint32_t n);
65 int ext4fs_checksum_update(unsigned int i); 62 int ext4fs_checksum_update(unsigned int i);
66 int ext4fs_get_parent_inode_num(const char *dirname, char *dname, int flags); 63 int ext4fs_get_parent_inode_num(const char *dirname, char *dname, int flags);
67 void ext4fs_update_parent_dentry(char *filename, int *p_ino, int file_type); 64 void ext4fs_update_parent_dentry(char *filename, int *p_ino, int file_type);
68 long int ext4fs_get_new_blk_no(void); 65 long int ext4fs_get_new_blk_no(void);
69 int ext4fs_get_new_inode_no(void); 66 int ext4fs_get_new_inode_no(void);
70 void ext4fs_reset_block_bmap(long int blockno, unsigned char *buffer, 67 void ext4fs_reset_block_bmap(long int blockno, unsigned char *buffer,
71 int index); 68 int index);
72 int ext4fs_set_block_bmap(long int blockno, unsigned char *buffer, int index); 69 int ext4fs_set_block_bmap(long int blockno, unsigned char *buffer, int index);
73 int ext4fs_set_inode_bmap(int inode_no, unsigned char *buffer, int index); 70 int ext4fs_set_inode_bmap(int inode_no, unsigned char *buffer, int index);
74 void ext4fs_reset_inode_bmap(int inode_no, unsigned char *buffer, int index); 71 void ext4fs_reset_inode_bmap(int inode_no, unsigned char *buffer, int index);
75 int ext4fs_iget(int inode_no, struct ext2_inode *inode); 72 int ext4fs_iget(int inode_no, struct ext2_inode *inode);
76 void ext4fs_allocate_blocks(struct ext2_inode *file_inode, 73 void ext4fs_allocate_blocks(struct ext2_inode *file_inode,
77 unsigned int total_remaining_blocks, 74 unsigned int total_remaining_blocks,
78 unsigned int *total_no_of_block); 75 unsigned int *total_no_of_block);
79 void put_ext4(uint64_t off, void *buf, uint32_t size); 76 void put_ext4(uint64_t off, void *buf, uint32_t size);
80 #endif 77 #endif
81 #endif 78 #endif
82 79
1 /* 1 /*
2 * (C) Copyright 2011 - 2012 Samsung Electronics 2 * (C) Copyright 2011 - 2012 Samsung Electronics
3 * EXT4 filesystem implementation in Uboot by 3 * EXT4 filesystem implementation in Uboot by
4 * Uma Shankar <uma.shankar@samsung.com> 4 * Uma Shankar <uma.shankar@samsung.com>
5 * Manjunatha C Achar <a.manjunatha@samsung.com> 5 * Manjunatha C Achar <a.manjunatha@samsung.com>
6 * 6 *
7 * ext4ls and ext4load : Based on ext2 ls and load support in Uboot. 7 * ext4ls and ext4load : Based on ext2 ls and load support in Uboot.
8 * Ext4 read optimization taken from Open-Moko 8 * Ext4 read optimization taken from Open-Moko
9 * Qi bootloader 9 * Qi bootloader
10 * 10 *
11 * (C) Copyright 2004 11 * (C) Copyright 2004
12 * esd gmbh <www.esd-electronics.com> 12 * esd gmbh <www.esd-electronics.com>
13 * Reinhard Arlt <reinhard.arlt@esd-electronics.com> 13 * Reinhard Arlt <reinhard.arlt@esd-electronics.com>
14 * 14 *
15 * based on code from grub2 fs/ext2.c and fs/fshelp.c by 15 * based on code from grub2 fs/ext2.c and fs/fshelp.c by
16 * GRUB -- GRand Unified Bootloader 16 * GRUB -- GRand Unified Bootloader
17 * Copyright (C) 2003, 2004 Free Software Foundation, Inc. 17 * Copyright (C) 2003, 2004 Free Software Foundation, Inc.
18 * 18 *
19 * ext4write : Based on generic ext4 protocol. 19 * ext4write : Based on generic ext4 protocol.
20 * 20 *
21 * SPDX-License-Identifier: GPL-2.0+ 21 * SPDX-License-Identifier: GPL-2.0+
22 */ 22 */
23 23
24 #include <common.h> 24 #include <common.h>
25 #include <ext_common.h> 25 #include <ext_common.h>
26 #include <ext4fs.h> 26 #include <ext4fs.h>
27 #include "ext4_common.h" 27 #include "ext4_common.h"
28 28
29 int ext4fs_symlinknest; 29 int ext4fs_symlinknest;
30 struct ext_filesystem ext_fs; 30 struct ext_filesystem ext_fs;
31 31
32 struct ext_filesystem *get_fs(void) 32 struct ext_filesystem *get_fs(void)
33 { 33 {
34 return &ext_fs; 34 return &ext_fs;
35 } 35 }
36 36
37 void ext4fs_free_node(struct ext2fs_node *node, struct ext2fs_node *currroot) 37 void ext4fs_free_node(struct ext2fs_node *node, struct ext2fs_node *currroot)
38 { 38 {
39 if ((node != &ext4fs_root->diropen) && (node != currroot)) 39 if ((node != &ext4fs_root->diropen) && (node != currroot))
40 free(node); 40 free(node);
41 } 41 }
42 42
43 /* 43 /*
44 * Taken from openmoko-kernel mailing list: By Andy green 44 * Taken from openmoko-kernel mailing list: By Andy green
45 * Optimized read file API : collects and defers contiguous sector 45 * Optimized read file API : collects and defers contiguous sector
46 * reads into one potentially more efficient larger sequential read action 46 * reads into one potentially more efficient larger sequential read action
47 */ 47 */
48 int ext4fs_read_file(struct ext2fs_node *node, int pos, 48 int ext4fs_read_file(struct ext2fs_node *node, int pos,
49 unsigned int len, char *buf) 49 unsigned int len, char *buf)
50 { 50 {
51 struct ext_filesystem *fs = get_fs(); 51 struct ext_filesystem *fs = get_fs();
52 int i; 52 int i;
53 lbaint_t blockcnt; 53 lbaint_t blockcnt;
54 int log2blksz = fs->dev_desc->log2blksz; 54 int log2blksz = fs->dev_desc->log2blksz;
55 int log2_fs_blocksize = LOG2_BLOCK_SIZE(node->data) - log2blksz; 55 int log2_fs_blocksize = LOG2_BLOCK_SIZE(node->data) - log2blksz;
56 int blocksize = (1 << (log2_fs_blocksize + log2blksz)); 56 int blocksize = (1 << (log2_fs_blocksize + log2blksz));
57 unsigned int filesize = __le32_to_cpu(node->inode.size); 57 unsigned int filesize = __le32_to_cpu(node->inode.size);
58 lbaint_t previous_block_number = -1; 58 lbaint_t previous_block_number = -1;
59 lbaint_t delayed_start = 0; 59 lbaint_t delayed_start = 0;
60 lbaint_t delayed_extent = 0; 60 lbaint_t delayed_extent = 0;
61 lbaint_t delayed_skipfirst = 0; 61 lbaint_t delayed_skipfirst = 0;
62 lbaint_t delayed_next = 0; 62 lbaint_t delayed_next = 0;
63 char *delayed_buf = NULL; 63 char *delayed_buf = NULL;
64 short status; 64 short status;
65 65
66 if (le32_to_cpu(node->inode.flags) & EXT4_EXTENTS_FL) {
67 if (ext4fs_build_extent_cache(&node->inode)) {
68 printf("Error building extent cache!\n");
69 len = -1;
70 goto out_exit;
71 }
72 }
73
74 /* Adjust len so it we can't read past the end of the file. */ 66 /* Adjust len so it we can't read past the end of the file. */
75 if (len > filesize) 67 if (len > filesize)
76 len = filesize; 68 len = filesize;
77 69
78 blockcnt = ((len + pos) + blocksize - 1) / blocksize; 70 blockcnt = ((len + pos) + blocksize - 1) / blocksize;
79 71
80 for (i = pos / blocksize; i < blockcnt; i++) { 72 for (i = pos / blocksize; i < blockcnt; i++) {
81 lbaint_t blknr; 73 lbaint_t blknr;
82 int blockoff = pos % blocksize; 74 int blockoff = pos % blocksize;
83 int blockend = blocksize; 75 int blockend = blocksize;
84 int skipfirst = 0; 76 int skipfirst = 0;
85 blknr = read_allocated_block(&(node->inode), i); 77 blknr = read_allocated_block(&(node->inode), i);
86 if (blknr < 0) { 78 if (blknr < 0)
87 len = -1; 79 return -1;
88 goto out_exit;
89 }
90 80
91 blknr = blknr << log2_fs_blocksize; 81 blknr = blknr << log2_fs_blocksize;
92 82
93 /* Last block. */ 83 /* Last block. */
94 if (i == blockcnt - 1) { 84 if (i == blockcnt - 1) {
95 blockend = (len + pos) % blocksize; 85 blockend = (len + pos) % blocksize;
96 86
97 /* The last portion is exactly blocksize. */ 87 /* The last portion is exactly blocksize. */
98 if (!blockend) 88 if (!blockend)
99 blockend = blocksize; 89 blockend = blocksize;
100 } 90 }
101 91
102 /* First block. */ 92 /* First block. */
103 if (i == pos / blocksize) { 93 if (i == pos / blocksize) {
104 skipfirst = blockoff; 94 skipfirst = blockoff;
105 blockend -= skipfirst; 95 blockend -= skipfirst;
106 } 96 }
107 if (blknr) { 97 if (blknr) {
108 int status; 98 int status;
109 99
110 if (previous_block_number != -1) { 100 if (previous_block_number != -1) {
111 if (delayed_next == blknr) { 101 if (delayed_next == blknr) {
112 delayed_extent += blockend; 102 delayed_extent += blockend;
113 delayed_next += blockend >> log2blksz; 103 delayed_next += blockend >> log2blksz;
114 } else { /* spill */ 104 } else { /* spill */
115 status = ext4fs_devread(delayed_start, 105 status = ext4fs_devread(delayed_start,
116 delayed_skipfirst, 106 delayed_skipfirst,
117 delayed_extent, 107 delayed_extent,
118 delayed_buf); 108 delayed_buf);
119 if (status == 0) { 109 if (status == 0)
120 len = -1; 110 return -1;
121 goto out_exit;
122 }
123 previous_block_number = blknr; 111 previous_block_number = blknr;
124 delayed_start = blknr; 112 delayed_start = blknr;
125 delayed_extent = blockend; 113 delayed_extent = blockend;
126 delayed_skipfirst = skipfirst; 114 delayed_skipfirst = skipfirst;
127 delayed_buf = buf; 115 delayed_buf = buf;
128 delayed_next = blknr + 116 delayed_next = blknr +
129 (blockend >> log2blksz); 117 (blockend >> log2blksz);
130 } 118 }
131 } else { 119 } else {
132 previous_block_number = blknr; 120 previous_block_number = blknr;
133 delayed_start = blknr; 121 delayed_start = blknr;
134 delayed_extent = blockend; 122 delayed_extent = blockend;
135 delayed_skipfirst = skipfirst; 123 delayed_skipfirst = skipfirst;
136 delayed_buf = buf; 124 delayed_buf = buf;
137 delayed_next = blknr + 125 delayed_next = blknr +
138 (blockend >> log2blksz); 126 (blockend >> log2blksz);
139 } 127 }
140 } else { 128 } else {
141 if (previous_block_number != -1) { 129 if (previous_block_number != -1) {
142 /* spill */ 130 /* spill */
143 status = ext4fs_devread(delayed_start, 131 status = ext4fs_devread(delayed_start,
144 delayed_skipfirst, 132 delayed_skipfirst,
145 delayed_extent, 133 delayed_extent,
146 delayed_buf); 134 delayed_buf);
147 if (status == 0) { 135 if (status == 0)
148 len = -1; 136 return -1;
149 goto out_exit;
150 }
151 previous_block_number = -1; 137 previous_block_number = -1;
152 } 138 }
153 memset(buf, 0, blocksize - skipfirst); 139 memset(buf, 0, blocksize - skipfirst);
154 } 140 }
155 buf += blocksize - skipfirst; 141 buf += blocksize - skipfirst;
156 } 142 }
157 if (previous_block_number != -1) { 143 if (previous_block_number != -1) {
158 /* spill */ 144 /* spill */
159 status = ext4fs_devread(delayed_start, 145 status = ext4fs_devread(delayed_start,
160 delayed_skipfirst, delayed_extent, 146 delayed_skipfirst, delayed_extent,
161 delayed_buf); 147 delayed_buf);
162 if (status == 0) { 148 if (status == 0)
163 len = -1; 149 return -1;
164 goto out_exit;
165 }
166 previous_block_number = -1; 150 previous_block_number = -1;
167 } 151 }
168
169
170 out_exit:
171 ext4fs_free_extent_cache();
172 152
173 return len; 153 return len;
174 } 154 }
175 155
176 int ext4fs_ls(const char *dirname) 156 int ext4fs_ls(const char *dirname)
177 { 157 {
178 struct ext2fs_node *dirnode; 158 struct ext2fs_node *dirnode;
179 int status; 159 int status;
180 160
181 if (dirname == NULL) 161 if (dirname == NULL)
182 return 0; 162 return 0;
183 163
184 status = ext4fs_find_file(dirname, &ext4fs_root->diropen, &dirnode, 164 status = ext4fs_find_file(dirname, &ext4fs_root->diropen, &dirnode,
185 FILETYPE_DIRECTORY); 165 FILETYPE_DIRECTORY);
186 if (status != 1) { 166 if (status != 1) {
187 printf("** Can not find directory. **\n"); 167 printf("** Can not find directory. **\n");
188 return 1; 168 return 1;
189 } 169 }
190 170
191 ext4fs_iterate_dir(dirnode, NULL, NULL, NULL); 171 ext4fs_iterate_dir(dirnode, NULL, NULL, NULL);
192 ext4fs_free_node(dirnode, &ext4fs_root->diropen); 172 ext4fs_free_node(dirnode, &ext4fs_root->diropen);
193 173
194 return 0; 174 return 0;
195 } 175 }
196 176
197 int ext4fs_exists(const char *filename) 177 int ext4fs_exists(const char *filename)
198 { 178 {
199 int file_len; 179 int file_len;
200 180
201 file_len = ext4fs_open(filename); 181 file_len = ext4fs_open(filename);
202 return file_len >= 0; 182 return file_len >= 0;
203 } 183 }
204 184
205 int ext4fs_read(char *buf, unsigned len) 185 int ext4fs_read(char *buf, unsigned len)
206 { 186 {
207 if (ext4fs_root == NULL || ext4fs_file == NULL) 187 if (ext4fs_root == NULL || ext4fs_file == NULL)
208 return 0; 188 return 0;
209 189
210 return ext4fs_read_file(ext4fs_file, 0, len, buf); 190 return ext4fs_read_file(ext4fs_file, 0, len, buf);
211 } 191 }
212 192
213 int ext4fs_probe(block_dev_desc_t *fs_dev_desc, 193 int ext4fs_probe(block_dev_desc_t *fs_dev_desc,
214 disk_partition_t *fs_partition) 194 disk_partition_t *fs_partition)
215 { 195 {
216 ext4fs_set_blk_dev(fs_dev_desc, fs_partition); 196 ext4fs_set_blk_dev(fs_dev_desc, fs_partition);
217 197
218 if (!ext4fs_mount(fs_partition->size)) { 198 if (!ext4fs_mount(fs_partition->size)) {
219 ext4fs_close(); 199 ext4fs_close();
220 return -1; 200 return -1;
221 } 201 }
222 202
223 return 0; 203 return 0;
224 } 204 }
225 205
226 int ext4_read_file(const char *filename, void *buf, int offset, int len) 206 int ext4_read_file(const char *filename, void *buf, int offset, int len)
227 { 207 {
228 int file_len; 208 int file_len;
229 int len_read; 209 int len_read;
230 210
231 if (offset != 0) { 211 if (offset != 0) {
232 printf("** Cannot support non-zero offset **\n"); 212 printf("** Cannot support non-zero offset **\n");
233 return -1; 213 return -1;
234 } 214 }
235 215
236 file_len = ext4fs_open(filename); 216 file_len = ext4fs_open(filename);
237 if (file_len < 0) { 217 if (file_len < 0) {
238 printf("** File not found %s **\n", filename); 218 printf("** File not found %s **\n", filename);
239 return -1; 219 return -1;
240 } 220 }
241 221
242 if (len == 0) 222 if (len == 0)
243 len = file_len; 223 len = file_len;
244 224
245 len_read = ext4fs_read(buf, len); 225 len_read = ext4fs_read(buf, len);
246 226
247 return len_read; 227 return len_read;
248 } 228 }
249 229