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