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