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