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