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