Пример #1
0
bool filesys_create (const char *path, off_t initial_size, enum FILE_TYPE type, uint32_t permission){
	struct block *d = NULL;
	struct ext2_meta_data *meta = NULL;
	char *parent = NULL, *name = NULL;
	struct directory *parent_dir = NULL;
	struct file *parent_file = NULL;
	struct directory *directory_data = NULL;
	struct directory *last_entry = NULL;
	uint32_t file_size = 0, bytes_read = 0;
	uint32_t inode_num;
	struct inode inode;
	int err, i;
	bool success = false;

	ASSERT(path != NULL && initial_size >= 0);

	// Get device
	d = block_get_role (BLOCK_FILESYS);
	ASSERT(d != NULL);
	meta = ext2_get_meta(d);
	ASSERT(meta != NULL && meta->sb != NULL);

	// Check if file already exists!
	directory_data = dir_lookup(d,path);
	if(directory_data != NULL){ // file exists
		printf("File %s exists!.\n",path);
		goto cleanup;
	}

	// Split path
	filesys_split_path(path, &parent, &name);
	ASSERT(parent != NULL && name != NULL);

	// Get parent directory
	parent_dir = dir_lookup(d,parent);
	if(parent_dir == NULL){
		printf("Directory %s does not exist.\n",parent);
		goto cleanup;
	}
	// Check file type
	if(parent_dir -> file_type != EXT2_FT_DIR){
		printf("Path %s is not a directory.\n",parent);
		goto cleanup;
	}

	// Get directory file
	parent_file = filesys_open(parent);
	if(parent_file == NULL) goto cleanup;

	// Get parent directory data
	file_size = parent_file->inode->i_size;
	directory_data = kmalloc(file_size);
	bytes_read = file_read(parent_file,directory_data,file_size);
	if(bytes_read != file_size) goto cleanup;
	
	// Get last entry
	last_entry = directory_data;
	do {
		last_entry = dir_get_next(last_entry);
	} while (last_entry != NULL 
		&& last_entry->inode != 0 
		&& (uint8_t*)last_entry+last_entry->rec_len < (uint8_t*)directory_data+file_size);

	// check if pointer passed file limit
	if(last_entry == NULL || (uint8_t*)last_entry >= (uint8_t*)directory_data+file_size)
		goto cleanup;

	// Get free inode
	inode_num = freemap_get_inode();
	if(inode_num == FREEMAP_GET_ERROR) goto cleanup;

	// Recalibrate record length
	if(last_entry->inode != 0){
		last_entry->rec_len = sizeof(struct directory) - (UINT8_MAX - last_entry->name_len);
		// Align 4 bytes
		i = last_entry->rec_len % 4;
		if(i > 0) last_entry->rec_len += (4-i);
	}

	// Goto new last entry
	last_entry = dir_get_next(last_entry);
	if(last_entry == NULL || (uint8_t*)last_entry >= (uint8_t*)directory_data+file_size)
		goto cleanup;
	
	// Create inode
	memset(&inode,0,sizeof(struct inode));
	inode.i_mode = EXT2_S_IFREG | permission;
	inode.i_links_count = 1;
	err = inode_resize(&inode,initial_size);
	if(err < 0) goto cleanup;
	// Write inode to disk
	ext2_write_inode(d,inode_num,&inode);
	
	// Create file entry
	memset(last_entry,0,sizeof(struct directory));
	last_entry->inode = inode_num;
	last_entry->name_len = strlen(name);
	if(last_entry->name_len > UINT8_MAX) last_entry->name_len = UINT8_MAX;
	memcpy(last_entry->name,name, last_entry->name_len);
	switch(type){
		case FILESYS_REGULAR: 
			last_entry -> file_type = EXT2_FT_REG_FILE;
			break;
		case FILESYS_DIRECTORY: 
			last_entry -> file_type = EXT2_FT_DIR;
			break;
		default:
			last_entry -> file_type = EXT2_FT_UNKNOWN;
			break;
	};
	last_entry->rec_len = ext2_get_block_size(meta->sb) - 
		(uint32_t)((uintptr_t)last_entry - (uintptr_t) directory_data);

	// Write directory file
	file_write_at(parent_file,directory_data,file_size,0);
	
	// file created successfully.
	success = true;

cleanup:
	// close file
	if(parent_file != NULL) file_close(parent_file);
	// release memory
	if(parent != NULL) kfree(parent);
	if(name != NULL) kfree(name);
	if(parent_dir != NULL) kfree(parent_dir);
	if(directory_data != NULL) kfree(directory_data);
	
	return success;
}
Пример #2
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;
}
Пример #3
0
bool filesys_remove (const char *path){
	struct block *d = NULL;
	struct ext2_meta_data *meta = NULL;
	char *parent = NULL, *name = NULL;
	struct directory *parent_dir = NULL;
	struct file *parent_file = NULL, *file = NULL;
	struct directory *directory_data = NULL;
	struct directory *file_entry = NULL, *last_entry = NULL;
	uint32_t file_size = 0, bytes_read = 0;
	bool success = false;

	ASSERT(path != NULL && strlen(path) > 0);

	// Get device
	d = block_get_role (BLOCK_FILESYS);
	ASSERT(d != NULL);
	meta = ext2_get_meta(d);
	ASSERT(meta != NULL && meta->sb != NULL);

	// open file
	file = filesys_open(path);
	if(file == NULL){ // file does not exists
		printf("filesys_remove: %s does not exist!.\n",path);
		goto cleanup;
	}
	
	//Check file type
	if(file->dir->file_type != EXT2_FT_REG_FILE){
		printf("filesys_remove %s is not a regular file.\n",path);
		goto cleanup;
	}

	// Split path
	filesys_split_path(path, &parent, &name);
	ASSERT(parent != NULL && name != NULL);

	// Get parent directory
	parent_dir = dir_lookup(d,parent);
	if(parent_dir == NULL){
		printf("Directory %s does not exist.\n",parent);
		goto cleanup;
	}
	// Check parent type
	if(parent_dir -> file_type != EXT2_FT_DIR){
		printf("Path %s is not a directory.\n",parent);
		goto cleanup;
	}

	// Get directory file
	parent_file = filesys_open(parent);
	if(parent_file == NULL) goto cleanup;

	// Get parent directory data
	file_size = parent_file->inode->i_size;
	directory_data = kmalloc(file_size);
	bytes_read = file_read(parent_file,directory_data,file_size);
	if(bytes_read != file_size) goto cleanup;
	
	// Get file directory entry
	file_entry = directory_data;
	while (file_entry != NULL 
		&& memcmp(file_entry->name,name,file_entry->name_len) != 0
		&& (uint8_t*)file_entry+file_entry->rec_len < (uint8_t*)directory_data+file_size){
		last_entry = file_entry;
		file_entry = dir_get_next(file_entry);
	}

	// check if file entry if found.
	if( (uint8_t*)file_entry >= (uint8_t*)directory_data+file_size
		|| memcmp(file_entry->name,name,file_entry->name_len) != 0 )
		goto cleanup;

	// Truncate file to zero length
	// Aka. Free blocks
	file_truncate(file,0);

	// Zero inode
	memset(file->inode,0,sizeof(struct inode));
	ext2_write_inode(d,file->dir->inode,file->inode);

	// Free inode
	freemap_free_inode(file_entry->inode);
	
	// Delete directory record
	// Use last entry record length to skip file entry
	if(last_entry->inode != 0)
		last_entry->rec_len += file_entry->rec_len;

	// Write directory file
	file_write_at(parent_file,directory_data,file_size,0);
	
	// file deleted successfully.
	success = true;

cleanup:
	// close file
	if(file != NULL) file_close(file);
	if(parent_file != NULL) file_close(parent_file);
	// release memory
	if(parent != NULL) kfree(parent);
	if(name != NULL) kfree(name);
	if(parent_dir != NULL) kfree(parent_dir);
	if(directory_data != NULL) kfree(directory_data);
	
	return success;
}