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 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, sec_buf, SECTOR_SIZE); 75 struct ext_filesystem *fs = get_fs(); 76 77 startblock = off / (uint64_t)SECTOR_SIZE; 78 startblock += part_offset; 79 remainder = off % (uint64_t)SECTOR_SIZE; 80 remainder &= SECTOR_SIZE - 1; 81 82 if (fs->dev_desc == NULL) 83 return; 84 85 if ((startblock + (size / SECTOR_SIZE)) > 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 / SECTOR_SIZE != 0) { 105 fs->dev_desc->block_write(fs->dev_desc->dev, 106 startblock, 107 size / SECTOR_SIZE, 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 1463 desc_per_blk = EXT2_BLOCK_SIZE(data) / sizeof(struct ext2_block_group); 1464 1465 blkno = __le32_to_cpu(data->sblock.first_data_block) + 1 + 1466 group / desc_per_blk; 1467 blkoff = (group % desc_per_blk) * sizeof(struct ext2_block_group); 1468 1469 debug("ext4fs read %d group descriptor (blkno %ld blkoff %u)\n", 1470 group, blkno, blkoff); 1471 1472 return ext4fs_devread(blkno << LOG2_EXT2_BLOCK_SIZE(data), 1473 blkoff, sizeof(struct ext2_block_group), 1474 (char *)blkgrp); 1475 } 1476 1477 int ext4fs_read_inode(struct ext2_data *data, int ino, struct ext2_inode *inode) 1478 { 1479 struct ext2_block_group blkgrp; 1480 struct ext2_sblock *sblock = &data->sblock; 1481 struct ext_filesystem *fs = get_fs(); 1482 int inodes_per_block, status; 1483 long int blkno; 1484 unsigned int blkoff; 1485 1486 /* It is easier to calculate if the first inode is 0. */ 1487 ino--; 1488 status = ext4fs_blockgroup(data, ino / __le32_to_cpu 1489 (sblock->inodes_per_group), &blkgrp); 1490 if (status == 0) 1491 return 0; 1492 1493 inodes_per_block = EXT2_BLOCK_SIZE(data) / fs->inodesz; 1494 blkno = __le32_to_cpu(blkgrp.inode_table_id) + 1495 (ino % __le32_to_cpu(sblock->inodes_per_group)) / inodes_per_block; 1496 blkoff = (ino % inodes_per_block) * fs->inodesz; 1497 /* Read the inode. */ 1498 status = ext4fs_devread(blkno << LOG2_EXT2_BLOCK_SIZE(data), blkoff, 1499 sizeof(struct ext2_inode), (char *)inode); 1500 if (status == 0) 1501 return 0; 1502 1503 return 1; 1504 } 1505 1506 long int read_allocated_block(struct ext2_inode *inode, int fileblock) 1507 { 1508 long int blknr; 1509 int blksz; 1510 int log2_blksz; 1511 int status; 1512 long int rblock; 1513 long int perblock_parent; 1514 long int perblock_child; 1515 unsigned long long start; 1516 /* get the blocksize of the filesystem */ 1517 blksz = EXT2_BLOCK_SIZE(ext4fs_root); 1518 log2_blksz = LOG2_EXT2_BLOCK_SIZE(ext4fs_root); 1519 if (le32_to_cpu(inode->flags) & EXT4_EXTENTS_FL) { 1520 char *buf = zalloc(blksz); 1521 if (!buf) 1522 return -ENOMEM; 1523 struct ext4_extent_header *ext_block; 1524 struct ext4_extent *extent; 1525 int i = -1; 1526 ext_block = ext4fs_get_extent_block(ext4fs_root, buf, 1527 (struct ext4_extent_header 1528 *)inode->b. 1529 blocks.dir_blocks, 1530 fileblock, log2_blksz); 1531 if (!ext_block) { 1532 printf("invalid extent block\n"); 1533 free(buf); 1534 return -EINVAL; 1535 } 1536 1537 extent = (struct ext4_extent *)(ext_block + 1); 1538 1539 do { 1540 i++; 1541 if (i >= le32_to_cpu(ext_block->eh_entries)) 1542 break; 1543 } while (fileblock >= le32_to_cpu(extent[i].ee_block)); 1544 if (--i >= 0) { 1545 fileblock -= le32_to_cpu(extent[i].ee_block); 1546 if (fileblock >= le32_to_cpu(extent[i].ee_len)) { 1547 free(buf); 1548 return 0; 1549 } 1550 1551 start = le32_to_cpu(extent[i].ee_start_hi); 1552 start = (start << 32) + 1553 le32_to_cpu(extent[i].ee_start_lo); 1554 free(buf); 1555 return fileblock + start; 1556 } 1557 1558 printf("Extent Error\n"); 1559 free(buf); 1560 return -1; 1561 } 1562 1563 /* Direct blocks. */ 1564 if (fileblock < INDIRECT_BLOCKS) 1565 blknr = __le32_to_cpu(inode->b.blocks.dir_blocks[fileblock]); 1566 1567 /* Indirect. */ 1568 else if (fileblock < (INDIRECT_BLOCKS + (blksz / 4))) { 1569 if (ext4fs_indir1_block == NULL) { 1570 ext4fs_indir1_block = zalloc(blksz); 1571 if (ext4fs_indir1_block == NULL) { 1572 printf("** SI ext2fs read block (indir 1)" 1573 "malloc failed. **\n"); 1574 return -1; 1575 } 1576 ext4fs_indir1_size = blksz; 1577 ext4fs_indir1_blkno = -1; 1578 } 1579 if (blksz != ext4fs_indir1_size) { 1580 free(ext4fs_indir1_block); 1581 ext4fs_indir1_block = NULL; 1582 ext4fs_indir1_size = 0; 1583 ext4fs_indir1_blkno = -1; 1584 ext4fs_indir1_block = zalloc(blksz); 1585 if (ext4fs_indir1_block == NULL) { 1586 printf("** SI ext2fs read block (indir 1):" 1587 "malloc failed. **\n"); 1588 return -1; 1589 } 1590 ext4fs_indir1_size = blksz; 1591 } 1592 if ((__le32_to_cpu(inode->b.blocks.indir_block) << 1593 log2_blksz) != ext4fs_indir1_blkno) { 1594 status = 1595 ext4fs_devread(__le32_to_cpu 1596 (inode->b.blocks. 1597 indir_block) << log2_blksz, 0, 1598 blksz, (char *)ext4fs_indir1_block); 1599 if (status == 0) { 1600 printf("** SI ext2fs read block (indir 1)" 1601 "failed. **\n"); 1602 return 0; 1603 } 1604 ext4fs_indir1_blkno = 1605 __le32_to_cpu(inode->b.blocks. 1606 indir_block) << log2_blksz; 1607 } 1608 blknr = __le32_to_cpu(ext4fs_indir1_block 1609 [fileblock - INDIRECT_BLOCKS]); 1610 } 1611 /* Double indirect. */ 1612 else if (fileblock < (INDIRECT_BLOCKS + (blksz / 4 * 1613 (blksz / 4 + 1)))) { 1614 1615 long int perblock = blksz / 4; 1616 long int rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4); 1617 1618 if (ext4fs_indir1_block == NULL) { 1619 ext4fs_indir1_block = zalloc(blksz); 1620 if (ext4fs_indir1_block == NULL) { 1621 printf("** DI ext2fs read block (indir 2 1)" 1622 "malloc failed. **\n"); 1623 return -1; 1624 } 1625 ext4fs_indir1_size = blksz; 1626 ext4fs_indir1_blkno = -1; 1627 } 1628 if (blksz != ext4fs_indir1_size) { 1629 free(ext4fs_indir1_block); 1630 ext4fs_indir1_block = NULL; 1631 ext4fs_indir1_size = 0; 1632 ext4fs_indir1_blkno = -1; 1633 ext4fs_indir1_block = zalloc(blksz); 1634 if (ext4fs_indir1_block == NULL) { 1635 printf("** DI ext2fs read block (indir 2 1)" 1636 "malloc failed. **\n"); 1637 return -1; 1638 } 1639 ext4fs_indir1_size = blksz; 1640 } 1641 if ((__le32_to_cpu(inode->b.blocks.double_indir_block) << 1642 log2_blksz) != ext4fs_indir1_blkno) { 1643 status = 1644 ext4fs_devread(__le32_to_cpu 1645 (inode->b.blocks. 1646 double_indir_block) << log2_blksz, 1647 0, blksz, 1648 (char *)ext4fs_indir1_block); 1649 if (status == 0) { 1650 printf("** DI ext2fs read block (indir 2 1)" 1651 "failed. **\n"); 1652 return -1; 1653 } 1654 ext4fs_indir1_blkno = 1655 __le32_to_cpu(inode->b.blocks.double_indir_block) << 1656 log2_blksz; 1657 } 1658 1659 if (ext4fs_indir2_block == NULL) { 1660 ext4fs_indir2_block = zalloc(blksz); 1661 if (ext4fs_indir2_block == NULL) { 1662 printf("** DI ext2fs read block (indir 2 2)" 1663 "malloc failed. **\n"); 1664 return -1; 1665 } 1666 ext4fs_indir2_size = blksz; 1667 ext4fs_indir2_blkno = -1; 1668 } 1669 if (blksz != ext4fs_indir2_size) { 1670 free(ext4fs_indir2_block); 1671 ext4fs_indir2_block = NULL; 1672 ext4fs_indir2_size = 0; 1673 ext4fs_indir2_blkno = -1; 1674 ext4fs_indir2_block = zalloc(blksz); 1675 if (ext4fs_indir2_block == NULL) { 1676 printf("** DI ext2fs read block (indir 2 2)" 1677 "malloc failed. **\n"); 1678 return -1; 1679 } 1680 ext4fs_indir2_size = blksz; 1681 } 1682 if ((__le32_to_cpu(ext4fs_indir1_block[rblock / perblock]) << 1683 log2_blksz) != ext4fs_indir2_blkno) { 1684 status = ext4fs_devread(__le32_to_cpu 1685 (ext4fs_indir1_block 1686 [rblock / 1687 perblock]) << log2_blksz, 0, 1688 blksz, 1689 (char *)ext4fs_indir2_block); 1690 if (status == 0) { 1691 printf("** DI ext2fs read block (indir 2 2)" 1692 "failed. **\n"); 1693 return -1; 1694 } 1695 ext4fs_indir2_blkno = 1696 __le32_to_cpu(ext4fs_indir1_block[rblock 1697 / 1698 perblock]) << 1699 log2_blksz; 1700 } 1701 blknr = __le32_to_cpu(ext4fs_indir2_block[rblock % perblock]); 1702 } 1703 /* Tripple indirect. */ 1704 else { 1705 rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4 + 1706 (blksz / 4 * blksz / 4)); 1707 perblock_child = blksz / 4; 1708 perblock_parent = ((blksz / 4) * (blksz / 4)); 1709 1710 if (ext4fs_indir1_block == NULL) { 1711 ext4fs_indir1_block = zalloc(blksz); 1712 if (ext4fs_indir1_block == NULL) { 1713 printf("** TI ext2fs read block (indir 2 1)" 1714 "malloc failed. **\n"); 1715 return -1; 1716 } 1717 ext4fs_indir1_size = blksz; 1718 ext4fs_indir1_blkno = -1; 1719 } 1720 if (blksz != ext4fs_indir1_size) { 1721 free(ext4fs_indir1_block); 1722 ext4fs_indir1_block = NULL; 1723 ext4fs_indir1_size = 0; 1724 ext4fs_indir1_blkno = -1; 1725 ext4fs_indir1_block = zalloc(blksz); 1726 if (ext4fs_indir1_block == NULL) { 1727 printf("** TI ext2fs read block (indir 2 1)" 1728 "malloc failed. **\n"); 1729 return -1; 1730 } 1731 ext4fs_indir1_size = blksz; 1732 } 1733 if ((__le32_to_cpu(inode->b.blocks.triple_indir_block) << 1734 log2_blksz) != ext4fs_indir1_blkno) { 1735 status = ext4fs_devread 1736 (__le32_to_cpu(inode->b.blocks.triple_indir_block) 1737 << log2_blksz, 0, blksz, 1738 (char *)ext4fs_indir1_block); 1739 if (status == 0) { 1740 printf("** TI ext2fs read block (indir 2 1)" 1741 "failed. **\n"); 1742 return -1; 1743 } 1744 ext4fs_indir1_blkno = 1745 __le32_to_cpu(inode->b.blocks.triple_indir_block) << 1746 log2_blksz; 1747 } 1748 1749 if (ext4fs_indir2_block == NULL) { 1750 ext4fs_indir2_block = zalloc(blksz); 1751 if (ext4fs_indir2_block == NULL) { 1752 printf("** TI ext2fs read block (indir 2 2)" 1753 "malloc failed. **\n"); 1754 return -1; 1755 } 1756 ext4fs_indir2_size = blksz; 1757 ext4fs_indir2_blkno = -1; 1758 } 1759 if (blksz != ext4fs_indir2_size) { 1760 free(ext4fs_indir2_block); 1761 ext4fs_indir2_block = NULL; 1762 ext4fs_indir2_size = 0; 1763 ext4fs_indir2_blkno = -1; 1764 ext4fs_indir2_block = zalloc(blksz); 1765 if (ext4fs_indir2_block == NULL) { 1766 printf("** TI ext2fs read block (indir 2 2)" 1767 "malloc failed. **\n"); 1768 return -1; 1769 } 1770 ext4fs_indir2_size = blksz; 1771 } 1772 if ((__le32_to_cpu(ext4fs_indir1_block[rblock / 1773 perblock_parent]) << 1774 log2_blksz) 1775 != ext4fs_indir2_blkno) { 1776 status = ext4fs_devread(__le32_to_cpu 1777 (ext4fs_indir1_block 1778 [rblock / 1779 perblock_parent]) << 1780 log2_blksz, 0, blksz, 1781 (char *)ext4fs_indir2_block); 1782 if (status == 0) { 1783 printf("** TI ext2fs read block (indir 2 2)" 1784 "failed. **\n"); 1785 return -1; 1786 } 1787 ext4fs_indir2_blkno = 1788 __le32_to_cpu(ext4fs_indir1_block[rblock / 1789 perblock_parent]) 1790 << log2_blksz; 1791 } 1792 1793 if (ext4fs_indir3_block == NULL) { 1794 ext4fs_indir3_block = zalloc(blksz); 1795 if (ext4fs_indir3_block == NULL) { 1796 printf("** TI ext2fs read block (indir 2 2)" 1797 "malloc failed. **\n"); 1798 return -1; 1799 } 1800 ext4fs_indir3_size = blksz; 1801 ext4fs_indir3_blkno = -1; 1802 } 1803 if (blksz != ext4fs_indir3_size) { 1804 free(ext4fs_indir3_block); 1805 ext4fs_indir3_block = NULL; 1806 ext4fs_indir3_size = 0; 1807 ext4fs_indir3_blkno = -1; 1808 ext4fs_indir3_block = zalloc(blksz); 1809 if (ext4fs_indir3_block == NULL) { 1810 printf("** TI ext2fs read block (indir 2 2)" 1811 "malloc failed. **\n"); 1812 return -1; 1813 } 1814 ext4fs_indir3_size = blksz; 1815 } 1816 if ((__le32_to_cpu(ext4fs_indir2_block[rblock 1817 / 1818 perblock_child]) << 1819 log2_blksz) != ext4fs_indir3_blkno) { 1820 status = 1821 ext4fs_devread(__le32_to_cpu 1822 (ext4fs_indir2_block 1823 [(rblock / perblock_child) 1824 % (blksz / 4)]) << log2_blksz, 0, 1825 blksz, (char *)ext4fs_indir3_block); 1826 if (status == 0) { 1827 printf("** TI ext2fs read block (indir 2 2)" 1828 "failed. **\n"); 1829 return -1; 1830 } 1831 ext4fs_indir3_blkno = 1832 __le32_to_cpu(ext4fs_indir2_block[(rblock / 1833 perblock_child) % 1834 (blksz / 1835 4)]) << 1836 log2_blksz; 1837 } 1838 1839 blknr = __le32_to_cpu(ext4fs_indir3_block 1840 [rblock % perblock_child]); 1841 } 1842 debug("ext4fs_read_block %ld\n", blknr); 1843 1844 return blknr; 1845 } 1846 1847 void ext4fs_close(void) 1848 { 1849 if ((ext4fs_file != NULL) && (ext4fs_root != NULL)) { 1850 ext4fs_free_node(ext4fs_file, &ext4fs_root->diropen); 1851 ext4fs_file = NULL; 1852 } 1853 if (ext4fs_root != NULL) { 1854 free(ext4fs_root); 1855 ext4fs_root = NULL; 1856 } 1857 if (ext4fs_indir1_block != NULL) { 1858 free(ext4fs_indir1_block); 1859 ext4fs_indir1_block = NULL; 1860 ext4fs_indir1_size = 0; 1861 ext4fs_indir1_blkno = -1; 1862 } 1863 if (ext4fs_indir2_block != NULL) { 1864 free(ext4fs_indir2_block); 1865 ext4fs_indir2_block = NULL; 1866 ext4fs_indir2_size = 0; 1867 ext4fs_indir2_blkno = -1; 1868 } 1869 if (ext4fs_indir3_block != NULL) { 1870 free(ext4fs_indir3_block); 1871 ext4fs_indir3_block = NULL; 1872 ext4fs_indir3_size = 0; 1873 ext4fs_indir3_blkno = -1; 1874 } 1875 } 1876 1877 int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name, 1878 struct ext2fs_node **fnode, int *ftype) 1879 { 1880 unsigned int fpos = 0; 1881 int status; 1882 struct ext2fs_node *diro = (struct ext2fs_node *) dir; 1883 1884 #ifdef DEBUG 1885 if (name != NULL) 1886 printf("Iterate dir %s\n", name); 1887 #endif /* of DEBUG */ 1888 if (!diro->inode_read) { 1889 status = ext4fs_read_inode(diro->data, diro->ino, &diro->inode); 1890 if (status == 0) 1891 return 0; 1892 } 1893 /* Search the file. */ 1894 while (fpos < __le32_to_cpu(diro->inode.size)) { 1895 struct ext2_dirent dirent; 1896 1897 status = ext4fs_read_file(diro, fpos, 1898 sizeof(struct ext2_dirent), 1899 (char *) &dirent); 1900 if (status < 1) 1901 return 0; 1902 1903 if (dirent.namelen != 0) { 1904 char filename[dirent.namelen + 1]; 1905 struct ext2fs_node *fdiro; 1906 int type = FILETYPE_UNKNOWN; 1907 1908 status = ext4fs_read_file(diro, 1909 fpos + 1910 sizeof(struct ext2_dirent), 1911 dirent.namelen, filename); 1912 if (status < 1) 1913 return 0; 1914 1915 fdiro = zalloc(sizeof(struct ext2fs_node)); 1916 if (!fdiro) 1917 return 0; 1918 1919 fdiro->data = diro->data; 1920 fdiro->ino = __le32_to_cpu(dirent.inode); 1921 1922 filename[dirent.namelen] = '\0'; 1923 1924 if (dirent.filetype != FILETYPE_UNKNOWN) { 1925 fdiro->inode_read = 0; 1926 1927 if (dirent.filetype == FILETYPE_DIRECTORY) 1928 type = FILETYPE_DIRECTORY; 1929 else if (dirent.filetype == FILETYPE_SYMLINK) 1930 type = FILETYPE_SYMLINK; 1931 else if (dirent.filetype == FILETYPE_REG) 1932 type = FILETYPE_REG; 1933 } else { 1934 status = ext4fs_read_inode(diro->data, 1935 __le32_to_cpu 1936 (dirent.inode), 1937 &fdiro->inode); 1938 if (status == 0) { 1939 free(fdiro); 1940 return 0; 1941 } 1942 fdiro->inode_read = 1; 1943 1944 if ((__le16_to_cpu(fdiro->inode.mode) & 1945 FILETYPE_INO_MASK) == 1946 FILETYPE_INO_DIRECTORY) { 1947 type = FILETYPE_DIRECTORY; 1948 } else if ((__le16_to_cpu(fdiro->inode.mode) 1949 & FILETYPE_INO_MASK) == 1950 FILETYPE_INO_SYMLINK) { 1951 type = FILETYPE_SYMLINK; 1952 } else if ((__le16_to_cpu(fdiro->inode.mode) 1953 & FILETYPE_INO_MASK) == 1954 FILETYPE_INO_REG) { 1955 type = FILETYPE_REG; 1956 } 1957 } 1958 #ifdef DEBUG 1959 printf("iterate >%s<\n", filename); 1960 #endif /* of DEBUG */ 1961 if ((name != NULL) && (fnode != NULL) 1962 && (ftype != NULL)) { 1963 if (strcmp(filename, name) == 0) { 1964 *ftype = type; 1965 *fnode = fdiro; 1966 return 1; 1967 } 1968 } else { 1969 if (fdiro->inode_read == 0) { 1970 status = ext4fs_read_inode(diro->data, 1971 __le32_to_cpu( 1972 dirent.inode), 1973 &fdiro->inode); 1974 if (status == 0) { 1975 free(fdiro); 1976 return 0; 1977 } 1978 fdiro->inode_read = 1; 1979 } 1980 switch (type) { 1981 case FILETYPE_DIRECTORY: 1982 printf("<DIR> "); 1983 break; 1984 case FILETYPE_SYMLINK: 1985 printf("<SYM> "); 1986 break; 1987 case FILETYPE_REG: 1988 printf(" "); 1989 break; 1990 default: 1991 printf("< ? > "); 1992 break; 1993 } 1994 printf("%10d %s\n", 1995 __le32_to_cpu(fdiro->inode.size), 1996 filename); 1997 } 1998 free(fdiro); 1999 } 2000 fpos += __le16_to_cpu(dirent.direntlen); 2001 } 2002 return 0; 2003 } 2004 2005 static char *ext4fs_read_symlink(struct ext2fs_node *node) 2006 { 2007 char *symlink; 2008 struct ext2fs_node *diro = node; 2009 int status; 2010 2011 if (!diro->inode_read) { 2012 status = ext4fs_read_inode(diro->data, diro->ino, &diro->inode); 2013 if (status == 0) 2014 return 0; 2015 } 2016 symlink = zalloc(__le32_to_cpu(diro->inode.size) + 1); 2017 if (!symlink) 2018 return 0; 2019 2020 if (__le32_to_cpu(diro->inode.size) <= 60) { 2021 strncpy(symlink, diro->inode.b.symlink, 2022 __le32_to_cpu(diro->inode.size)); 2023 } else { 2024 status = ext4fs_read_file(diro, 0, 2025 __le32_to_cpu(diro->inode.size), 2026 symlink); 2027 if (status == 0) { 2028 free(symlink); 2029 return 0; 2030 } 2031 } 2032 symlink[__le32_to_cpu(diro->inode.size)] = '\0'; 2033 return symlink; 2034 } 2035 2036 static int ext4fs_find_file1(const char *currpath, 2037 struct ext2fs_node *currroot, 2038 struct ext2fs_node **currfound, int *foundtype) 2039 { 2040 char fpath[strlen(currpath) + 1]; 2041 char *name = fpath; 2042 char *next; 2043 int status; 2044 int type = FILETYPE_DIRECTORY; 2045 struct ext2fs_node *currnode = currroot; 2046 struct ext2fs_node *oldnode = currroot; 2047 2048 strncpy(fpath, currpath, strlen(currpath) + 1); 2049 2050 /* Remove all leading slashes. */ 2051 while (*name == '/') 2052 name++; 2053 2054 if (!*name) { 2055 *currfound = currnode; 2056 return 1; 2057 } 2058 2059 for (;;) { 2060 int found; 2061 2062 /* Extract the actual part from the pathname. */ 2063 next = strchr(name, '/'); 2064 if (next) { 2065 /* Remove all leading slashes. */ 2066 while (*next == '/') 2067 *(next++) = '\0'; 2068 } 2069 2070 if (type != FILETYPE_DIRECTORY) { 2071 ext4fs_free_node(currnode, currroot); 2072 return 0; 2073 } 2074 2075 oldnode = currnode; 2076 2077 /* Iterate over the directory. */ 2078 found = ext4fs_iterate_dir(currnode, name, &currnode, &type); 2079 if (found == 0) 2080 return 0; 2081 2082 if (found == -1) 2083 break; 2084 2085 /* Read in the symlink and follow it. */ 2086 if (type == FILETYPE_SYMLINK) { 2087 char *symlink; 2088 2089 /* Test if the symlink does not loop. */ 2090 if (++symlinknest == 8) { 2091 ext4fs_free_node(currnode, currroot); 2092 ext4fs_free_node(oldnode, currroot); 2093 return 0; 2094 } 2095 2096 symlink = ext4fs_read_symlink(currnode); 2097 ext4fs_free_node(currnode, currroot); 2098 2099 if (!symlink) { 2100 ext4fs_free_node(oldnode, currroot); 2101 return 0; 2102 } 2103 2104 debug("Got symlink >%s<\n", symlink); 2105 2106 if (symlink[0] == '/') { 2107 ext4fs_free_node(oldnode, currroot); 2108 oldnode = &ext4fs_root->diropen; 2109 } 2110 2111 /* Lookup the node the symlink points to. */ 2112 status = ext4fs_find_file1(symlink, oldnode, 2113 &currnode, &type); 2114 2115 free(symlink); 2116 2117 if (status == 0) { 2118 ext4fs_free_node(oldnode, currroot); 2119 return 0; 2120 } 2121 } 2122 2123 ext4fs_free_node(oldnode, currroot); 2124 2125 /* Found the node! */ 2126 if (!next || *next == '\0') { 2127 *currfound = currnode; 2128 *foundtype = type; 2129 return 1; 2130 } 2131 name = next; 2132 } 2133 return -1; 2134 } 2135 2136 int ext4fs_find_file(const char *path, struct ext2fs_node *rootnode, 2137 struct ext2fs_node **foundnode, int expecttype) 2138 { 2139 int status; 2140 int foundtype = FILETYPE_DIRECTORY; 2141 2142 symlinknest = 0; 2143 if (!path) 2144 return 0; 2145 2146 status = ext4fs_find_file1(path, rootnode, foundnode, &foundtype); 2147 if (status == 0) 2148 return 0; 2149 2150 /* Check if the node that was found was of the expected type. */ 2151 if ((expecttype == FILETYPE_REG) && (foundtype != expecttype)) 2152 return 0; 2153 else if ((expecttype == FILETYPE_DIRECTORY) 2154 && (foundtype != expecttype)) 2155 return 0; 2156 2157 return 1; 2158 } 2159 2160 int ext4fs_open(const char *filename) 2161 { 2162 struct ext2fs_node *fdiro = NULL; 2163 int status; 2164 int len; 2165 2166 if (ext4fs_root == NULL) 2167 return -1; 2168 2169 ext4fs_file = NULL; 2170 status = ext4fs_find_file(filename, &ext4fs_root->diropen, &fdiro, 2171 FILETYPE_REG); 2172 if (status == 0) 2173 goto fail; 2174 2175 if (!fdiro->inode_read) { 2176 status = ext4fs_read_inode(fdiro->data, fdiro->ino, 2177 &fdiro->inode); 2178 if (status == 0) 2179 goto fail; 2180 } 2181 len = __le32_to_cpu(fdiro->inode.size); 2182 ext4fs_file = fdiro; 2183 2184 return len; 2185 fail: 2186 ext4fs_free_node(fdiro, &ext4fs_root->diropen); 2187 2188 return -1; 2189 } 2190 2191 int ext4fs_mount(unsigned part_length) 2192 { 2193 struct ext2_data *data; 2194 int status; 2195 struct ext_filesystem *fs = get_fs(); 2196 data = zalloc(sizeof(struct ext2_data)); 2197 if (!data) 2198 return 0; 2199 2200 /* Read the superblock. */ 2201 status = ext4fs_devread(1 * 2, 0, sizeof(struct ext2_sblock), 2202 (char *)&data->sblock); 2203 2204 if (status == 0) 2205 goto fail; 2206 2207 /* Make sure this is an ext2 filesystem. */ 2208 if (__le16_to_cpu(data->sblock.magic) != EXT2_MAGIC) 2209 goto fail; 2210 2211 if (__le32_to_cpu(data->sblock.revision_level == 0)) 2212 fs->inodesz = 128; 2213 else 2214 fs->inodesz = __le16_to_cpu(data->sblock.inode_size); 2215 2216 debug("EXT2 rev %d, inode_size %d\n", 2217 __le32_to_cpu(data->sblock.revision_level), fs->inodesz); 2218 2219 data->diropen.data = data; 2220 data->diropen.ino = 2; 2221 data->diropen.inode_read = 1; 2222 data->inode = &data->diropen.inode; 2223 2224 status = ext4fs_read_inode(data, 2, data->inode); 2225 if (status == 0) 2226 goto fail; 2227 2228 ext4fs_root = data; 2229 2230 return 1; 2231 fail: 2232 printf("Failed to mount ext2 filesystem...\n"); 2233 free(data); 2234 ext4fs_root = NULL; 2235 2236 return 0; 2237 } 2238