예제 #1
0
bool ext2_read_inode(PEXT2_FILESYS Ext2Sys,
            ULONG               ino,
            ULONG               offset,
            PVOID               Buffer,
            ULONG               size,
            PULONG              dwReturn)
{
    PEXT2_BDL   ext2_bdl = NULL;
    ULONG       blocks, i;
    bool        bRet = true;
    EXT2_INODE  ext2_inode;
    ULONG       dwTotal = 0;

    if (!ext2_load_inode(Ext2Sys, ino, &ext2_inode))
    {
        return false;
    }

    blocks = ext2_build_bdl(Ext2Sys, &ext2_inode, offset, size, &ext2_bdl);

    if (blocks <= 0)
        return  false;
    
   
    for(i = 0; i < blocks; i++)
    {
        bRet = NT_SUCCESS(Ext2ReadDisk(
                Ext2Sys,
                ext2_bdl[i].Lba, 
                ext2_bdl[i].Length,
                (PUCHAR)Buffer + ext2_bdl[i].Offset
               ));

        if (!bRet)
            break;
        dwTotal += ext2_bdl[i].Length;
    }

    *dwReturn = dwTotal;

    if (ext2_bdl)
        RtlFreeHeap(RtlGetProcessHeap(), 0, ext2_bdl);

    return bRet;
}
예제 #2
0
int ext2_dirent(fscookie cookie, const char *_path, unsigned index, char **name)
{
	ext2_t *ext2 = (ext2_t *)cookie;
	inodenum_t diri;
	struct ext2_inode inode;
	struct ext2_inode *inodep;
	int rv;

	if (strlen(_path) != 0) {
		rv = ext2_walk(ext2, _path, &ext2->root_inode, &diri, 1);
		if (rv < 0) return rv;
		rv = ext2_load_inode(ext2, diri, &inode);
		if (rv < 0) return rv;
		inodep = &inode;
	} else {
		inodep = &ext2->root_inode;
	}

	return ext2_dirent_lookup(ext2, inodep, name, index);
}
예제 #3
0
파일: ext2.c 프로젝트: ArthurMurata/lk
int ext2_mount(bdev_t *dev, fscookie *cookie)
{
	int err;

	LTRACEF("dev %p\n", dev);

	ext2_t *ext2 = malloc(sizeof(ext2_t));
	ext2->dev = dev;

	err = bio_read(dev, &ext2->sb, 1024, sizeof(struct ext2_super_block));
	if (err < 0)
		goto err;

	endian_swap_superblock(&ext2->sb);

	/* see if the superblock is good */
	if (ext2->sb.s_magic != EXT2_SUPER_MAGIC) {
		err = -1;
		return err;
	}

	/* calculate group count, rounded up */
	ext2->s_group_count = (ext2->sb.s_blocks_count + ext2->sb.s_blocks_per_group - 1) / ext2->sb.s_blocks_per_group;

	/* print some info */
	LTRACEF("rev level %d\n", ext2->sb.s_rev_level);
	LTRACEF("compat features 0x%x\n", ext2->sb.s_feature_compat);
	LTRACEF("incompat features 0x%x\n", ext2->sb.s_feature_incompat);
	LTRACEF("ro compat features 0x%x\n", ext2->sb.s_feature_ro_compat);
	LTRACEF("block size %d\n", EXT2_BLOCK_SIZE(ext2->sb));
	LTRACEF("inode size %d\n", EXT2_INODE_SIZE(ext2->sb));
	LTRACEF("block count %d\n", ext2->sb.s_blocks_count);
	LTRACEF("blocks per group %d\n", ext2->sb.s_blocks_per_group);
	LTRACEF("group count %d\n", ext2->s_group_count);
	LTRACEF("inodes per group %d\n", ext2->sb.s_inodes_per_group);

	/* we only support dynamic revs */
	if (ext2->sb.s_rev_level > EXT2_DYNAMIC_REV) {
		err = -2;
		return err;
	}

	/* make sure it doesn't have any ro features we don't support */
	if (ext2->sb.s_feature_ro_compat & ~(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
		err = -3;
		return err;
	}

	/* read in all the group descriptors */
	ext2->gd = malloc(sizeof(struct ext2_group_desc) * ext2->s_group_count);
	err = bio_read(ext2->dev, (void *)ext2->gd,
	               (EXT2_BLOCK_SIZE(ext2->sb) == 4096) ? 4096 : 2048,
	               sizeof(struct ext2_group_desc) * ext2->s_group_count);
	if (err < 0) {
		err = -4;
		return err;
	}

	int i;
	for (i=0; i < ext2->s_group_count; i++) {
		endian_swap_group_desc(&ext2->gd[i]);
		LTRACEF("group %d:\n", i);
		LTRACEF("\tblock bitmap %d\n", ext2->gd[i].bg_block_bitmap);
		LTRACEF("\tinode bitmap %d\n", ext2->gd[i].bg_inode_bitmap);
		LTRACEF("\tinode table %d\n", ext2->gd[i].bg_inode_table);
		LTRACEF("\tfree blocks %d\n", ext2->gd[i].bg_free_blocks_count);
		LTRACEF("\tfree inodes %d\n", ext2->gd[i].bg_free_inodes_count);
		LTRACEF("\tused dirs %d\n", ext2->gd[i].bg_used_dirs_count);
	}

	/* initialize the block cache */
	ext2->cache = bcache_create(ext2->dev, EXT2_BLOCK_SIZE(ext2->sb), 4);

	/* load the first inode */
	err = ext2_load_inode(ext2, EXT2_ROOT_INO, &ext2->root_inode);
	if (err < 0)
		goto err;

//	TRACE("successfully mounted volume\n");

	*cookie = ext2;

	return 0;

err:
	LTRACEF("exiting with err code %d\n", err);

	free(ext2);
	return err;
}
예제 #4
0
/* note, trashes path */
static int ext2_walk(ext2_t *ext2, char *path, struct ext2_inode *start_inode, inodenum_t *inum, int recurse)
{
	char *ptr;
	struct ext2_inode inode;
	struct ext2_inode dir_inode;
	int err;
	bool done;

	LTRACEF("path '%s', start_inode %p, inum %p, recurse %d\n", path, start_inode, inum, recurse);

	if (recurse > 4)
		return ERR_RECURSE_TOO_DEEP;

	/* chew up leading slashes */
	ptr = &path[0];
	while (*ptr == '/')
		ptr++;

	done = false;
	memcpy(&dir_inode, start_inode, sizeof(struct ext2_inode));
	while (!done) {
		/* process the first component */
		char *next_sep = strchr(ptr, '/');
		if (next_sep) {
			/* terminate the next component, giving us a substring */
			*next_sep = 0;
		} else {
			/* this is the last component */
			done = true;
		}

		LTRACEF("component '%s', done %d\n", ptr, done);

		/* do the lookup on this component */
		err = ext2_dir_lookup(ext2, &dir_inode, ptr, inum);
		if (err < 0)
			return err;

nextcomponent:
		LTRACEF("inum %u\n", *inum);

		/* load the next inode */
		err = ext2_load_inode(ext2, *inum, &inode);
		if (err < 0)
			return err;
		
		/* is it a symlink? */
		if (S_ISLNK(inode.i_mode)) {
			char link[512];

			LTRACEF("hit symlink\n");

			err = ext2_read_link(ext2, &inode, link, sizeof(link));
			if (err < 0)
				return err;

			LTRACEF("symlink read returns %d '%s'\n", err, link);

			/* recurse, parsing the link */
			if (link[0] == '/') {
				/* link starts with '/', so start over again at the rootfs */
				err = ext2_walk(ext2, link, &ext2->root_inode, inum, recurse + 1);
			} else {
				err = ext2_walk(ext2, link, &dir_inode, inum, recurse + 1);
			}

			LTRACEF("recursive walk returns %d\n", err);

			if (err < 0)
				return err;

			/* if we weren't done with our path parsing, start again with the result of this recurse */
			if (!done) {
				goto nextcomponent;
			}
		} else if (S_ISDIR(inode.i_mode)) {
			/* for the next cycle, point the dir inode at our new directory */
			memcpy(&dir_inode, &inode, sizeof(struct ext2_inode));
		} else {
			if (!done) {
				/* we aren't done and this walked over a nondir, abort */
				LTRACEF("not finished and component is nondir\n");
				return ERR_NOT_FOUND;
			}
		}

		if (!done) {
			/* move to the next seperator */
			ptr = next_sep + 1; 

			/* consume multiple seperators */
			while (*ptr == '/')
				ptr++;
		}
	}

	return 0;
}
예제 #5
0
bool
ext2_add_entry( PEXT2_FILESYS Ext2Sys,
                ULONG parent, ULONG inode,
                int filetype, char *name )
{
    PEXT2_DIR_ENTRY2  dir = NULL, newdir = NULL;
    EXT2_INODE      parent_inode;
    ULONG       dwRet;
    char        *buf;
    int         rec_len;
    bool        bRet = false;

    rec_len = EXT2_DIR_REC_LEN(strlen(name));

    if (!ext2_load_inode(Ext2Sys, parent, &parent_inode))
    {
        return false;
    }

    buf = (char *)RtlAllocateHeap(RtlGetProcessHeap(), 0, parent_inode.i_size);

    if (!ext2_read_inode(Ext2Sys, parent, 0, buf, parent_inode.i_size, &dwRet))
    {
        return false;
    }

    dir = (PEXT2_DIR_ENTRY2) buf;

    while ((char *)dir < buf + parent_inode.i_size)
    {
        if ((dir->inode == 0 && dir->rec_len >= rec_len) || 
               (dir->rec_len >= dir->name_len + rec_len) )
        {
            if (dir->inode)
            {
                newdir = (PEXT2_DIR_ENTRY2) ((PUCHAR)dir + EXT2_DIR_REC_LEN(dir->name_len));
                newdir->rec_len = dir->rec_len - EXT2_DIR_REC_LEN(dir->name_len);

                dir->rec_len = EXT2_DIR_REC_LEN(dir->name_len);

                dir = newdir;
            }

            dir->file_type = filetype;
            dir->inode = inode;
            dir->name_len = strlen(name);
            memcpy(dir->name, name, strlen(name));
    
            bRet = true;
            break;
        }

        dir = (PEXT2_DIR_ENTRY2) (dir->rec_len + (PUCHAR) dir);
    }


    if (bRet)
        return ext2_write_inode(Ext2Sys, parent, 0, buf, parent_inode.i_size, &dwRet);

    return bRet;
}
예제 #6
0
bool ext2_write_inode (PEXT2_FILESYS Ext2Sys,
            ULONG               ino,
            ULONG               offset,
            PVOID               Buffer,
            ULONG               size,
            PULONG              dwReturn )
{
    PEXT2_BDL   ext2_bdl = NULL;
    ULONG       blocks, i;
    bool        bRet = true;
    EXT2_INODE  inode;
    ULONG       dwTotal = 0;
    ULONG       dwBlk = 0;
    ULONG       TotalBlks;

    blocks =  (size + offset + Ext2Sys->blocksize - 1) / Ext2Sys->blocksize;

    if (!ext2_load_inode(Ext2Sys, ino, &inode))
    {
        return false;
    }

    TotalBlks = inode.i_blocks / (Ext2Sys->blocksize / SECTOR_SIZE);
    TotalBlks = Ext2DataBlocks(Ext2Sys, TotalBlks);

    if (blocks > TotalBlks)
    {
        for (i=0; i < (blocks - TotalBlks);  i++)
        {
            if (ext2_alloc_block(Ext2Sys, 0, &dwBlk) )
            {
                ext2_expand_inode(Ext2Sys, &inode, dwBlk);
                inode.i_blocks += (Ext2Sys->blocksize/SECTOR_SIZE);
            }
        }
    }

    blocks = ext2_build_bdl(Ext2Sys, &inode, offset, size, &ext2_bdl);

    if (blocks <= 0)
        return  false;
    
    for(i = 0; i < blocks; i++)
    {
        bRet = NT_SUCCESS(Ext2WriteDisk(
                Ext2Sys,
                ext2_bdl[i].Lba, 
                ext2_bdl[i].Length,
                (PUCHAR)Buffer + ext2_bdl[i].Offset
               ));

        if (!bRet)
        {
            goto errorout;
        }

        dwTotal += ext2_bdl[i].Length;
    }

    *dwReturn = dwTotal;

    if (size + offset > inode.i_size)
    {
        inode.i_size = size + offset;
    }

    ext2_save_inode(Ext2Sys, ino, &inode);


errorout:
   
    if (ext2_bdl)
        RtlFreeHeap(RtlGetProcessHeap(), 0, ext2_bdl);

    return bRet;
}