Exemplo n.º 1
0
int write_to_file(int child_nbr, inode inode, uint16_t newblock_nbr, uint8_t block[], superblock spb, FILE * ufs)
{
	if (child_nbr >= 1024)
	{
		printf("Inode full\n");
		return -1;
	}
	
	int blocksize = spb.magic_number;
	// int j; for(j = 0; j < blocksize; j++)printf("%c",block[j]);
	int initial_pos = ftell(ufs);
	if (child_nbr < BLK_PER_IND-4) //No refered position
	{
		inode.blocks[child_nbr] = newblock_nbr;
		inode_write(inode.id, ufs, blocksize, spb.root_inode, inode);
		fseek(ufs, spb.root_dir * blocksize, SEEK_SET);
		fseek(ufs, newblock_nbr * blocksize, SEEK_CUR);
		fwrite(block, sizeof(uint8_t), blocksize, ufs);
	}
	else //Refered position
	{
		// printf("entrou aqui\n");
		int newblock;
		int block_in_vec = (BLK_PER_IND-4) + ((child_nbr - (BLK_PER_IND-4))/(blocksize/2));
		int jump_inside = 0;
		if ((child_nbr - (BLK_PER_IND-4))%(blocksize/2) == 0)//First position, verify is block is already there
		{
			if (inode.blocks[block_in_vec] == 0)//Alloc the block
			{
				// printf("Seraaqui?\n");
				newblock = frst_free_block(ufs, spb.magic_number, spb.root_dir);
				// printf("%d<>%d\n",newblock, block_in_vec);
				inode.blocks[block_in_vec] = newblock;
				inode_write(inode.id, ufs, blocksize, spb.root_inode, inode);
			}
			else newblock = inode.blocks[block_in_vec];
		}
		else 
		{
			newblock = inode.blocks[block_in_vec];
			jump_inside = (child_nbr - (BLK_PER_IND-4))%(blocksize/2) * sizeof(uint16_t);
		}
		fseek(ufs, spb.root_dir * blocksize, SEEK_SET);
		fseek(ufs, newblock * blocksize, SEEK_CUR);
		if (jump_inside) fseek(ufs, jump_inside, SEEK_CUR);
		fwrite(&newblock_nbr, sizeof(uint16_t), 1, ufs);
		fseek(ufs, spb.root_dir * blocksize, SEEK_SET);
		fseek(ufs, newblock_nbr * blocksize, SEEK_CUR);
		fwrite(block, sizeof(uint8_t), blocksize, ufs);
	}
	fseek(ufs, initial_pos, SEEK_SET);
	return 0;
}
Exemplo n.º 2
0
int
fs_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi)
{
	struct inode *ino = (struct inode *)fi->fh;
	ino->i_mtime = time(NULL);
	return inode_write(ino, buf, size, offset);
}
Exemplo n.º 3
0
//****** cnwrite *********************
size_t cnwrite(uint8_t* buf, size_t bytes, int16_t fd)
{
	fd_entry* fde = &fd_tbl[fd];
	check(fde->state == FD_WRITE, "File descriptor not in write mode");

	uint32_t required_size = fde->cursor + bytes;
	if(fde->inode.size < required_size)   //The data cache and block size may have to be expanded
	{
		//Compute new sizes
		uint32_t required_blocks = (required_size / BLOCK_SIZE) + 1;

		//Allocate new data cache
		check(realloc_cache(fde, required_blocks) == 0, "Unable to realloc cache");
		fde->inode.size = required_size;

		//Allocate fs blocks
		if(fde->inode.blocks < required_blocks)
		{
			check(realloc_fs_blocks(&fde->inode, required_blocks) == 0, "Could not allocate fs blocks");
		}
		fde->inode.modified = time(NULL);
		inode_write(fde->inode_id, &fde->inode);
	}

	uint8_t* data_ptr = ((uint8_t*)fde->data)+fde->cursor;
	memcpy(data_ptr, buf, bytes);
	fde->cursor += bytes;
	llwrite(&fde->inode, (block*)fde->data);

	return bytes;
error:
	return 0;
}
Exemplo n.º 4
0
//****** cnseek **********************
int8_t cnseek(int16_t fd, uint32_t offset)
{
	fd_entry* fde = &fd_tbl[fd];
	uint32_t required_size = fde->cursor + offset;
	if(fde->inode.size < required_size)   //The data cache and block size may have to be expanded
	{
		//Compute new sizes
		uint32_t required_blocks = (required_size / BLOCK_SIZE) + 1;

		//Allocate new data cache
		check(realloc_cache(fde, required_blocks) == 0, "Unable to realloc cache");
		fde->inode.size = required_size;

		//Allocate fs blocks
		if(fde->inode.blocks < required_blocks)
		{
			check(realloc_fs_blocks(&fde->inode, required_blocks) == 0, "Could not allocate fs blocks");
		}
		fde->inode.modified = time(NULL);
		inode_write(fde->inode_id, &fde->inode);
	}
	fde->cursor = offset;
	return 0;
error:
	return -1;
}
Exemplo n.º 5
0
//******** rmdir ********************
int8_t cnrmdir(const char* name)
{
	char parent_name[512];
	char entry_name[256];
	dir_entry* entry;
	inode dir_inode;
	memset(&dir_inode, 0, sizeof(inode));

	strcpy(parent_name, name);
	strcat(parent_name, "/..");

	dir_ptr* parent = cnopendir(parent_name);
	check(parent != NULL, "Cannot open parent directory");

	//Copy the entire directory minus the entry
	dir_ptr* new_parent = calloc(1,sizeof(dir_ptr));
	new_parent->data = calloc(parent->inode_st.blocks, sizeof(block));
	dir_entry* new_dir_entry = (dir_entry*)new_parent->data;
	new_parent->inode_st = parent->inode_st;
	new_parent->inode_id = parent->inode_id;
	new_parent->inode_st.size = 0;
	new_parent->index = 0;

	while((entry = cnreaddir(parent)))
	{
		memcpy(entry_name, entry->name, entry->name_len);
		entry_name[entry->name_len] = 0;
		if(strcmp(entry_name, name) == 0)  //If this is the directory we want
		{
			inode_read(entry->inode, &dir_inode);
			check(dir_inode.size == 24, "Directory is not empty");
			release_block(dir_inode.data0[0]);  //Release target directory block
			release_inode(entry->inode);        //Release target inode
			continue;
		}
		new_dir_entry->entry_len = entry->entry_len;
		new_dir_entry->name_len = entry->name_len;
		new_dir_entry->file_type = entry->file_type;
		new_dir_entry->inode = entry->inode;
		memcpy(new_dir_entry->name, entry->name, entry->name_len);
		new_parent->inode_st.size += entry->entry_len;
		new_parent->index += entry->entry_len;
		new_dir_entry = (dir_entry*)((uint8_t*)new_parent->data+new_parent->index);
	}

	inode_write(new_parent->inode_id, &new_parent->inode_st);
	llwrite(&new_parent->inode_st, new_parent->data);

	free(new_parent->data);
	free(new_parent);
	cnclosedir(parent);
	return 0;
error:
	if(new_parent != NULL && new_parent->data != NULL) free(new_parent->data);
	if(new_parent != NULL) free(new_parent);
	if(parent != NULL) cnclosedir(parent);
	return -1;
}
Exemplo n.º 6
0
int inode_append (super_block_t *sb, int index, void *buffer, int len) {
	// assert (sb != NULL);
	// assert (index >= 0 && index < INODE_ARRAY_SIZE);
	// assert (buffer != NULL);
	// assert (len >= 0);

	int offset = sb->inodes[index].size;
	return inode_write (sb, index, offset, buffer, len);
}
Exemplo n.º 7
0
//******** creat ********************
int8_t cncreat(dir_ptr* dir, const char* name)
{
	stat_st stat_buf;
	dir_entry* entry;

	check(cnstat(dir,name,&stat_buf) != 0, "File exists");  //If this file exists

	//Create parent directory entry
	entry = (dir_entry*)(((uint8_t*)dir->data)+dir->index);
	entry->file_type = ITYPE_FILE;
	entry->inode = reserve_inode();
	memcpy(entry->name, name, strlen(name));
	entry->name_len = strlen(name);
	entry->entry_len = entry->name_len + 8;
	entry->entry_len += (4 - entry->entry_len % 4);  //padding out to 32 bits
	dir->inode_st.size += entry->entry_len;
	//TODO: handle creat dir block overflow

	//Write parent dir and inode
	dir->inode_st.modified = time(NULL);
	inode_write(dir->inode_id, &dir->inode_st);
	blk_write(dir->inode_st.data0[0], dir->data);

	//Write new file inode
	inode new_file_i;
	memset(&new_file_i, 0, sizeof(inode));
	uint32_t now = time(NULL);
	new_file_i.modified = now;
	new_file_i.type = ITYPE_FILE;
	new_file_i.size = 0;
	new_file_i.blocks = 0;
	inode_write(entry->inode, &new_file_i);

	return 0;

error:
	return -1;
}
Exemplo n.º 8
0
// Opens a link filetype
unsigned int fs_open_link(char * name, char * target_name) {
	unsigned int folder_inode = current_ttyc()->pwd;
	int target_inode = fs_indir(target_name, folder_inode);
	if(target_inode > 0)
	{
		int result = fs_open_file(name, folder_inode, O_NEW, EXT2_S_IFLNK);
		if(result > 0)	{
			inode_read(result, &n);
			n.data_blocks[0] = target_inode;
			inode_write(result, &n);	
			result = fs_open_reg_file(target_name, folder_inode, O_RD);
			inode_read(result, &n);
			n.links++;
			inode_write(result, &n);				
			return 1;
		}
		else {
			return result;
		}
	} else {
		return ERR_NO_EXIST;
	}

}
Exemplo n.º 9
0
// Changes the permissions of the file
unsigned int fs_chmod(char * filename, int perms) {
	int current_uid = current_ttyc()->uid;
	int start_inode = current_ttyc()->pwd;
	int namenode = fs_indir(filename, start_inode);
	if (namenode) {
		inode_read(namenode, &n);
		if (n.uid == current_uid || current_uid == 0) {
			n.i_file_acl = perms;
			inode_write(namenode, &n);
		} else {
			return ERR_PERMS;
		}
		return 1;
	} else {
		return ERR_NO_EXIST;
	}
}
Exemplo n.º 10
0
// Changes the inode's owner
unsigned int fs_chown(char * filename, char * username) {
	int new_uid = user_exists(username);
	int current_uid = current_ttyc()->uid;
	int start_inode = current_ttyc()->pwd;
	int namenode = fs_indir(filename, start_inode);

	if (namenode && new_uid != -1) {
		inode_read(namenode, &n);
		if (n.uid == current_uid || current_uid == 0) {
			n.uid = new_uid;
			inode_write(namenode, &n);
		} else {
			return ERR_PERMS;
		}
		return 1;
	} else {
		return ERR_NO_EXIST;
	}
}
Exemplo n.º 11
0
void remove_from_dir(int inode_id, inode parent, FILE *ufs, superblock spb)
{
	uint16_t children[1024] = {0};
	inode realoc;
	int i;
	int position = -1;
	int blocksize = spb.magic_number;
	int last = first_free_child(parent, ufs, spb, blocksize, children);
	for (i = 0; i < last; i++)
	{
		if (children[i] == inode_id)
		{
			position = i;
		}
	}
	if (last == -1) last = 1023;
	else last -= 1;
	if (position == -1) 
	{
		printf("Error\n");
		return;
	}
	// printf("Position %d last %d children %d\n", position, last, children[last]);
	write_to_dir(position, parent, children[last], spb, ufs);
	inode_read(parent.id, ufs, spb.magic_number, spb.root_inode, &parent);
	// printf("last one is %d\n",last);
	//inode_read(last, ufs, blocksize, spb.root_inode, &realoc);
	// inode_write(inode_id, ufs, blocksize, uint16_t first_inode_blk, realoc);

	// write_to_dir(inode_id, parent, last, spb, ufs);
	write_to_dir(last, parent, 0, spb, ufs);
	if ((last - (BLK_PER_IND-4))%(blocksize/2) == 0)
	{
		// printf("caiu aqui\n");
		int block_in_vec = (BLK_PER_IND-4) + ((last - (BLK_PER_IND-4))/(blocksize/2));
		inode_read(parent.id, ufs, spb.magic_number, spb.root_inode, &parent);
		parent.blocks[block_in_vec] = 0;
		inode_write(parent.id, ufs, blocksize, spb.root_inode, parent);
	}
}
Exemplo n.º 12
0
int fs_write (fs_t *fs, int index, int offset, void *buffer, int len) {
	// assert (fs != NULL);
	// assert (index >= 0 && index < INODE_ARRAY_SIZE);
	// assert (buffer != NULL);
	// assert (offset >= 0);
	// assert (len >= 0);

	index_node_t *inode = &fs->super_block->inodes[index];
	// assert (inode->in_use == 1);

	if (offset + len > LOC_LIMIT_DOUBLE_INDIRECT)
		return -1;

	int status;
	if (inode->size < offset + len) {
		status = inode_expand (fs->super_block, index, offset + len);
		if (status < 0)
			return -1;
	}

	return inode_write (fs->super_block, index, offset, buffer, len);
}
Exemplo n.º 13
0
/**
 * Write to file f.
 */
int
file_write(struct file *f, char *addr, int n)
{
  int r;

  if(f->writable == 0)
    return -1;
  if(f->type == FD_INODE){
    // Write a few blocks at a time to avoid exceeding
    // the maximum log transaction size, including
    // i-node, indirect block, allocation blocks,
    // and 2 blocks of slop for non-aligned writes.
    // this really belongs lower down, since inode_write()
    // might be writing a device like the console.
    int max = ((LOGSIZE-1-1-2) / 2) * 512;
    int i = 0;
    while(i < n){
      int n1 = n - i;
      if(n1 > max)
        n1 = max;

      begin_trans();
      inode_lock(f->ip);
      if ((r = inode_write(f->ip, addr + i, f->off, n1)) > 0)
        f->off += r;
      inode_unlock(f->ip);
      commit_trans();

      if(r < 0)
        break;
      if(r != n1)
        KERN_PANIC("short file_write");
      i += r;
    }
    return i == n ? n : -1;
  }
  KERN_PANIC("file_write");
}
Exemplo n.º 14
0
void write_root_dir(void)
{
	//Prepare inode
	inode root_i;
	memset(&root_i, 0, sizeof(inode));
	uint32_t now = time(NULL);
	root_i.modified = now;
	root_i.type = ITYPE_DIR;
	root_i.size = 0;
	root_i.blocks = 1;
	root_i.data0[0] = BLOCKID_ROOT_DIR;

	block* root_dir_block = calloc(1,sizeof(block));

	// . (self entry)
	dir_entry* root_dir_entry = (dir_entry*)root_dir_block;
	root_dir_entry->inode = 0;
	root_dir_entry->file_type = ITYPE_DIR;
	root_dir_entry->name_len = 1;
	root_dir_entry->entry_len = 12;
	memcpy(root_dir_entry->name, ".", 1);
	root_i.size += 12;

	// .. (parent entry, also itself)
	root_dir_entry = (dir_entry*)(((char*)root_dir_block) + 12);
	root_dir_entry->inode = 0;
	root_dir_entry->file_type = ITYPE_DIR;
	root_dir_entry->name_len = 2;
	root_dir_entry->entry_len = 12;
	memcpy(root_dir_entry->name, "..", 2);
	root_i.size += 12;

	inode_write(0, &root_i);
	blk_write(BLOCKID_ROOT_DIR, root_dir_block);

	free(root_dir_block);
}
Exemplo n.º 15
0
// Writes to a file, as simple as unix
unsigned int fs_write_file(int inode, char * data, int size) {
	inode_clear(&n);							// Clear the inode to take off the trash
	inode_read(inode, &n);						// Read the current inode.
	

	int log_block = n.blocks / 2;
	block_clear(&b);							// Prepare to read the data, clear it.

	int i = 0;
	int block_index = n._last_write_offset;
	log_block_read(&n, &log_block);				// Set up the point where we'll write
	char * block = (char *) &b;
	
	// Write until we reach end
	for (; i < size; i++) {
		block[block_index] = data[i];
		if (block_index == FS_BLOCK_SIZE - 1) {
			log_block_write(&n, &log_block);
			log_block++;						// Iterate if necessary.
			log_block_read(&n, &log_block);
			block_index = 0;
		} else {
			block_index++;
		}
	}
	
	n._last_write_offset = block_index;
	log_block_write(&n, &log_block);			// Save the last bits
	
	n.blocks = log_block * 2;					// Update the inodes

	inode_write(inode,&n);
	fs_bitmaps_write_all();  					// Persist the changes in the FS

	return i;
}
Exemplo n.º 16
0
// Used to move a file
unsigned int fs_mv(char * name, char * newname, int from_inode) {
	int i1 = fs_open_file(name, from_inode, O_WR | O_RD, EXT2_S_IFREG);
	if(i1 < 0)	{
		return i1; // If there's an error with the first name then there's nothing to do actually.
	}
	
	int i2 = fs_indir(newname, from_inode);
	if(i2 == 0)	{
		folder_rem_direntry(i1, n._dir_inode);

		inode_read(from_inode, &n);
		int log_block = n.blocks / 2;

		block_clear(&b);
		dir_op_offset = 0;
		log_block_read(&n, &log_block);
		add_dir_entry(&n, EXT2_FT_DIR, i1, newname, &log_block);
		log_block_write(&n, &log_block);		
		
		n.blocks = log_block * 2;
		inode_write(from_inode, &n);
		
		return 1;
	} else {
		inode_read(i2, &n);

		if(!fs_has_perms(&n, ACTION_READ))	{
			return ERR_PERMS;
		}
		
		if(!(n.mode & EXT2_S_IFDIR))	{
			return ERR_INVALID_TYPE;
		}
		
		if (fs_indir(name, i2)) {
			return ERR_REPEATED;
		}

		int log_block = n.blocks / 2;

		block_clear(&b);
		dir_op_offset = 0;
		log_block_read(&n, &log_block);
		add_dir_entry(&n, EXT2_FT_DIR, i1, name, &log_block);
		log_block_write(&n, &log_block);

		n.blocks = log_block * 2;
		inode_write(i2, &n);

		inode_read(i1, &n);
		folder_rem_direntry(i1, n._dir_inode);
		inode_read(i1, &n);
		folder_rem_direntry(n._dir_inode, i1);
		log_block_read(&n, &log_block);
		add_dir_entry(&n, EXT2_FT_DIR, i2, "..", &log_block);
		log_block_write(&n, &log_block);
		n._dir_inode = i2;
		inode_write(i1, &n);
	}	
	return i1;
	
}
Exemplo n.º 17
0
//******** mkdir ********************
int8_t cnmkdir(const char* name)
{
	char* name_copy = strdup(name);
	char name_tok[256];
	char entry_name[256];
	char* next_name_tok;
	dir_entry* entry;
	dir_ptr *dir = calloc(1,sizeof(dir_ptr));		//Directory file in memory (e.g. DIR object from filedef.h)
	bool last_dir = false;

	inode_read(cwd->inode_id, &dir->inode_st);		//Start at cwd
	dir->inode_id = cwd->inode_id;

	next_name_tok = strtok(name_copy, "/");
	do
	{
		//name_tok is the dir we are searching for or going to create
		strcpy(name_tok, next_name_tok);

		//Read the directory file for this inode
		dir->data = calloc(dir->inode_st.blocks,sizeof(block));  	//Memory for all directory file blocks
		llread(&dir->inode_st, dir->data);	//Read the directory file
		dir->index = 0;

		next_name_tok = strtok(NULL, "/");		//Read the next token
		if(next_name_tok == NULL)   //This is the last directory in the path
		{
			last_dir = true;
		}

		//Find the token in this dir
		while((entry = cnreaddir(dir)))
		{
			memcpy(entry_name, entry->name, entry->name_len);
			entry_name[entry->name_len] = 0;
			if(strcmp(entry_name, name_tok) == 0)  //If this directory already exists
			{
				if(last_dir)
				{
					return -1;   //Directory already exists
				}
				else   //Read the directory inode
				{
					dir->inode_id = entry->inode;
					inode_read(entry->inode,&dir->inode_st);   //Read the next directory's inode
					free(dir->data);  //Forget the directory we just read
					break;
				}
			}
		}

		if(last_dir)  //Create the directory at the end of the list
		{
			//Create parent directory entry
			entry = (dir_entry*)(((uint8_t*)dir->data)+dir->index);
			entry->file_type = ITYPE_DIR;
			entry->inode = reserve_inode();
			memcpy(entry->name,name_tok,strlen(name_tok));
			entry->name_len = strlen(name_tok);
			entry->entry_len = entry->name_len + 8;
			entry->entry_len += (4 - entry->entry_len % 4);  //padding out to 32 bits
			dir->inode_st.size += entry->entry_len;
			//TODO: handle mkdir block overflow

			//Write parent dir and inode
			dir->inode_st.modified = time(NULL);
			inode_write(dir->inode_id, &dir->inode_st);
			blk_write(dir->inode_st.data0[0], dir->data);

			//Write new directory inode
			inode new_dir_i;
			memset(&new_dir_i, 0, sizeof(inode));
			uint32_t now = time(NULL);
			new_dir_i.modified = now;
			new_dir_i.type = ITYPE_DIR;
			new_dir_i.size = 0;
			new_dir_i.blocks = 1;
			new_dir_i.data0[0] = reserve_block();

			//Write new directory file
			block* new_dir_block = calloc(1,sizeof(block));

			// . (self entry)
			dir_entry* new_dir_self_entry = (dir_entry*)new_dir_block;
			new_dir_self_entry->inode = entry->inode;
			new_dir_self_entry->file_type = ITYPE_DIR;
			new_dir_self_entry->name_len = 1;
			new_dir_self_entry->entry_len = 12;
			memcpy(new_dir_self_entry->name, ".", 1);
			new_dir_i.size += 12;

			// .. (parent entry)
			dir_entry* new_dir_parent_entry = (dir_entry*)(((uint8_t*)new_dir_block) + 12);
			new_dir_parent_entry->inode = dir->inode_id;
			new_dir_parent_entry->file_type = ITYPE_DIR;
			new_dir_parent_entry->name_len = 2;
			new_dir_parent_entry->entry_len = 12;
			memcpy(new_dir_parent_entry->name, "..", 2);
			new_dir_i.size += 12;

			//Write new dir and inode
			inode_write(entry->inode, &new_dir_i);
			blk_write(new_dir_i.data0[0], new_dir_block);

			free(new_dir_block);
			break;
		}

	} while(1);
	free(dir);
	free(name_copy);
	return 0;
}
Exemplo n.º 18
0
// Makes a new directory
unsigned int fs_mkdir(char * name, unsigned int parent_inode) {
	unsigned int inode_id = 0;
	if ((inode_id = fs_indir(name, parent_inode))) {
		return 0;
	}
	inode_id = bitmap_first_valued(bm_inodes, FS_INODE_BITMAP_SIZE, 0) + 1;
	
	if (!parent_inode) {
		parent_inode = inode_id;
	}
	
	int log_block;
	
	if (parent_inode != inode_id) {
		inode_read(parent_inode, &n);
		
		if(!fs_has_perms(&n, ACTION_WRITE))	{
			return ERR_PERMS;
		}
		
		log_block = n.blocks / 2;
		
		block_clear(&b);
		dir_op_offset = 0;
		log_block_read(&n, &log_block);
		add_dir_entry(&n, EXT2_FT_DIR, inode_id, name, &log_block);
		log_block_write(&n, &log_block);
		
		inode_write(parent_inode, &n);	
	}
	bitmap_write(bm_inodes, inode_id - 1, 1);

	
	

	
	inode_clear(&n);
	

	if(!fs_done)
	{
		n.uid = 0;
	} else {
		n.uid = current_ttyc()->uid;
	}

	n.mode = EXT2_S_IFDIR;
	n.size = 0;
	n.blocks = 0; // Beware! This represents the SECTORS!
	
	
	log_block = n.blocks / 2;
	
	block_clear(&b);
	dir_op_offset = 0;
	
	add_dir_entry(&n, EXT2_FT_DIR, inode_id, ".", &log_block);
	add_dir_entry(&n, EXT2_FT_DIR, parent_inode, "..", &log_block);

	log_block_write(&n, &log_block);
	
	n.blocks = (log_block) * 2;
	
	n.i_file_acl = 511;
	n._dir_inode = parent_inode;
	n._last_write_offset = dir_op_offset;
	
	inode_write(inode_id, &n);	
	



	
	fs_bitmaps_write_all();
	return inode_id;
}
Exemplo n.º 19
0
// Opens a file
unsigned int fs_open_file(char * name, unsigned int folder_inode, int mode, int type) {
	unsigned int inode_id = 0;

	if(strcmp(name, "/") == 0 && strlen(name) == strlen("/"))	{
		return 1; // root
	}


	if(name[0] == 0)
	{
		inode_id = current_ttyc()->pwd;
	} else {
		inode_id = fs_indir(name, folder_inode);
	}
	
	if (inode_id) {
		if (mode & O_CREAT) {
			int _rm_res = fs_rm(inode_id, 0);
			if(_rm_res < 0) {
				return _rm_res;
			}
		} else if(mode & O_NEW) {
			inode_read(inode_id, &n);
			if(n.mode == EXT2_S_IFLNK)	{
				return n.data_blocks[0];
			}
			return inode_id;
		} 
		else {
			inode_read(inode_id, &n);
			int can = 1;
			if((mode & O_RD) && !fs_has_perms(&n, ACTION_READ))	{
				can = 0;
			}
			if((mode & O_WR) && !fs_has_perms(&n, ACTION_WRITE))	{
				can = 0;
			}
			if(can || !fs_done)	{
				if(n.mode == EXT2_S_IFLNK)	{
					return n.data_blocks[0];
				}
				return inode_id;
			} else {
				return ERR_PERMS;
			}
		}
	} else if (!(mode & (O_NEW | O_CREAT))) {
		return ERR_NO_EXIST;
	}
	
	inode_id = bitmap_first_valued(bm_inodes, FS_INODE_BITMAP_SIZE, 0) + 1;
	
	if (!folder_inode) {
		folder_inode = inode_id;
	}
	
	int log_block;
	
	if (folder_inode != inode_id) {
		inode_read(folder_inode, &n);
		
		if(!fs_has_perms(&n, ACTION_WRITE))	{
			return ERR_PERMS;
		}
		
		log_block = n.blocks / 2;
		
		block_clear(&b);
		dir_op_offset = 0;
		log_block_read(&n, &log_block);
		add_dir_entry(&n, EXT2_FT_DIR, inode_id, name, &log_block);
		log_block_write(&n, &log_block);
		
		inode_write(folder_inode, &n);	
	}
	bitmap_write(bm_inodes, inode_id - 1, 1);
		
	inode_clear(&n);
	
	
	if(!fs_done)
	{
		n.uid = 0;
	} else {
		n.uid = current_ttyc()->uid;
	}
	
	n.mode =  type;
	n.size = 0;
	n.blocks = 0; // Beware! This represents the SECTORS!
	
	
	n._last_write_offset = 0;
	n.i_file_acl = 511;
	n._dir_inode = folder_inode;
	
	inode_write(inode_id, &n);	
	
	inode_clear(&n);

	if(n.mode == EXT2_S_IFLNK)	{
		return n.data_blocks[0];
	}
	
	return inode_id;
}
Exemplo n.º 20
0
// Removes an inode from the filesystem, documented in header
unsigned int fs_rm(unsigned int inode, int inside_recursion) {
	inode_read(inode, &n);
	
	if(!(inode > 1))	{
		return ERR_PERMS; 					// Permissions check
	}
	
	if(!fs_has_perms(&n, ACTION_WRITE))	{
		return ERR_PERMS;					// If you can't write you can't delete...
	}
	
	if(n.links > 0)
	{
		return ERR_PERMS;					// If you can't write you can't delete...
	}
	
	if(n.mode == EXT2_S_IFLNK)
	{
		int ptr = n.data_blocks[0];
		inode_read(ptr, &n);
		n.links--;
		inode_write(ptr, &n);
		inode_read(inode, &n);
	}
	
	if (!inside_recursion) { // I'm not sure about this, but well... at least it's just a security flaw.
		inode_read(n._dir_inode, &n);
		if(!fs_has_perms(&n, ACTION_WRITE))	{		
			return ERR_PERMS;				// If you can't write on the parent folder you can't delete
		}
		inode_read(inode, &n);
	}
	

	int log_block = n.blocks / 2 + 1;		// Logical block top
	int ph_block = 0;
	
	// Go from top to bottom to delete everything.
	while(log_block > 0) {
		log_block--;
		make_ph_block(&n, &ph_block, &log_block);
	 	
		if (n.mode & EXT2_S_IFDIR) { // If it's a directory... then... RECURSION! D:
			block entries;
			data_read_block(&entries, ph_block);
			int off = 0;
			dir_op_offset = 0;
			dir_entry * old_dot = NULL;
			dir_entry * dot = iterate_dir_entry(&entries);
			// Iterates dir entries
			while (dot != NULL) {
				if (dot == NULL) {
					break;
				} else {
					if (dot->name_len > 0 && dot->inode != inode && dot->inode != n._dir_inode) {
						// If we get an error we don't actually make anything :D, but we might delete other files.
						int _rm = fs_rm(dot->inode, 1);
						if(_rm < 0)
						{
							data_write_block(&entries, ph_block);
							bitmap_write(bm_blocks, ph_block - 1, 0);
							return _rm;
						}
						off = dir_op_offset;
						dot->name_len = 0;
						dir_op_offset = off;
						inode_read(inode, &n);
					}
				}
				old_dot = dot;
				dot = iterate_dir_entry(&entries);
			}	

			data_write_block(&entries, ph_block);
		}
		bitmap_write(bm_blocks, ph_block - 1, 0); // This deletes the stuff actually
		delete_internal_inodes(log_block);        // This deletes the EXT2 ugly but wise indirects.
	}
	
	// Delete the directory entry of the file.
	if (!inside_recursion) {
		inode_read(inode, &n);
		unsigned int folder_inode = n._dir_inode;
		inode_read(folder_inode, &n);		
		folder_rem_direntry(inode, folder_inode);
	}

	bitmap_write(bm_inodes, inode - 1, 0);		 // Persist the directory liberation.

	fs_bitmaps_write_all();  					 // Persist in the FS.

						  
	return 1;
}