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