Esempio n. 1
0
static int
ospfs_unlink(struct inode *dirino, struct dentry *dentry)
{
	ospfs_inode_t *oi = ospfs_inode(dentry->d_inode->i_ino);
	ospfs_inode_t *dir_oi = ospfs_inode(dentry->d_parent->d_inode->i_ino);
	int entry_off;
	ospfs_direntry_t *od;

	od = NULL; // silence compiler warning; entry_off indicates when !od
	for (entry_off = 0; entry_off < dir_oi->oi_size;
	     entry_off += OSPFS_DIRENTRY_SIZE) {
		od = ospfs_inode_data(dir_oi, entry_off);
		if (od->od_ino > 0
		    && strlen(od->od_name) == dentry->d_name.len
		    && memcmp(od->od_name, dentry->d_name.name, dentry->d_name.len) == 0)
			break;
	}

	if (entry_off == dir_oi->oi_size) {
		printk("<1>ospfs_unlink should not fail!\n");
		return -ENOENT;
	}

	od->od_ino = 0;
	oi->oi_nlink--;

	// if not a symlink, delete file data when all links are gone
	if (oi->oi_ftype != OSPFS_FTYPE_SYMLINK && oi->oi_nlink == 0)
		return change_size(oi, 0);

	return 0;
}
Esempio n. 2
0
static int
ospfs_link(struct dentry *src_dentry, struct inode *dir, struct dentry *dst_dentry) {
	ospfs_inode_t *dir_oi = ospfs_inode(dir->i_ino);
	ospfs_inode_t *src_oi = ospfs_inode(src_dentry->d_inode->i_ino);
	ospfs_direntry_t *entry;


	if (dst_dentry->d_name.len > OSPFS_MAXSYMLINKLEN) {
		return -ENAMETOOLONG;
	}
	
	if (find_direntry(dir_oi, dst_dentry->d_name.name, dst_dentry->d_name.len) != NULL) {
		return -EEXIST;
	}
	
	if (dir_oi == NULL || dir_oi->oi_nlink + 1 == 0) {
		return -EIO;
	}
	
	entry = create_blank_direntry(dir_oi);
	if (IS_ERR(entry)) {
		return PTR_ERR(entry);
	} else if(entry == NULL) {
		return -EIO;
	}
	
	entry->od_ino = src_dentry->d_inode->i_ino;
	memcpy(entry->od_name, dst_dentry->d_name.name, dst_dentry->d_name.len);
	entry->od_name[dst_dentry->d_name.len] = 0;
	
	src_oi->oi_nlink++;
	dir_oi->oi_nlink++;
	return 0;
}
Esempio n. 3
0
int32_t
copy_inode(uint32_t i_ino, uint8_t *bitmap, ospfs_inode_t *inodeTable)
{
	memcpy(&inodeTable[i_ino], ospfs_inode(i_ino), sizeof(*inodeTable));

	mark_inode_bitmap(ospfs_inode(i_ino), bitmap);
}
Esempio n. 4
0
static int
ospfs_link(struct dentry *src_dentry, struct inode *dir, struct dentry *dst_dentry) {
	ospfs_direntry_t* link;

	// check if name too long
	if (dst_dentry->d_name.len > OSPFS_MAXNAMELEN)
        return -ENAMETOOLONG;
	// check if directory entry already exists
	if (find_direntry(ospfs_inode(dir->i_ino),
		dst_dentry->d_name.name, dst_dentry->d_name.len))
		return -EEXIST;

	// create new hardlinked file
	link = create_blank_direntry(ospfs_inode(dir->i_ino));
	if (IS_ERR(link))
		return PTR_ERR(link);

	// copy file information
	link->od_ino = src_dentry->d_inode->i_ino;
	memcpy(link->od_name, dst_dentry->d_name.name, dst_dentry->d_name.len);
	link->od_name[dst_dentry->d_name.len] = '\0';

	// increment source file link count
	ospfs_inode(src_dentry->d_inode->i_ino)->oi_nlink++;

	return 0;
}
Esempio n. 5
0
static int
ospfs_unlink(uint32_t i_ino, char *d_name)
{
	ospfs_inode_t *oi = ospfs_inode(i_ino); // figure this out???
	ospfs_inode_t *dir_oi = ospfs_inode(i_ino);
	int entry_off;
	ospfs_direntry_t *od;

	od = NULL; // silence compiler warning; entry_off indicates when !od
	for (entry_off = 0; entry_off < dir_oi->oi_size;
	     entry_off += OSPFS_DIRENTRY_SIZE) {
		od = ospfs_inode_data(dir_oi, entry_off);
		if (od->od_ino > 0
		    && strlen(od->od_name) == strlen(d_name)
		    && memcmp(od->od_name, d_name, strlen(d_name)) == 0)
			break;
	}

	if (entry_off == dir_oi->oi_size) {
		return -ENOENT;
	}

	od->od_ino = 0;
	oi->oi_nlink--;
	return 0;
}
Esempio n. 6
0
static int
ospfs_link(struct dentry *src_dentry, struct inode *dir, struct dentry *dst_dentry) {
	/* EXERCISE: Your code here. */
	ospfs_inode_t *dir_oi = ospfs_inode(dir->i_ino);
	ospfs_direntry_t *od;
	ospfs_inode_t *oi;
	uint32_t entry_ino = 0;
	if (dst_dentry->d_name.len > OSPFS_MAXNAMELEN)
		return -ENAMETOOLONG;
	if (find_direntry(dir_oi, dst_dentry->d_name.name, dst_dentry->d_name.len))
		return -EEXIST;

	od = create_blank_direntry(dir_oi);

	if (IS_ERR(od))
		return -ENOSPC;
	for (entry_ino = 2; entry_ino < ospfs_super->os_ninodes; entry_ino++) {
		oi = ospfs_inode(entry_ino);
		if (oi->oi_nlink == 0)
			break;
	}
	if (entry_ino == ospfs_super->os_ninodes)
		return -EIO;
	od->od_ino = src_dentry->d_inode->i_ino;
	strcpy(od->od_name, dst_dentry->d_name.name);
	oi = ospfs_inode(od->od_ino);
	oi->oi_nlink++;

	return 0;
}
Esempio n. 7
0
static int
ospfs_unlink(struct inode *dirino, struct dentry *dentry)
{
	ospfs_inode_t *oi = ospfs_inode(dentry->d_inode->i_ino);
	ospfs_inode_t *dir_oi = ospfs_inode(dentry->d_parent->d_inode->i_ino);
	int entry_off;
	ospfs_direntry_t *od;

	od = NULL; // silence compiler warning; entry_off indicates when !od
	for (entry_off = 0; entry_off < dir_oi->oi_size;
     	entry_off += OSPFS_DIRENTRY_SIZE) {
    	od = ospfs_inode_data(dir_oi, entry_off);
    	if (od->od_ino > 0
        	&& strlen(od->od_name) == dentry->d_name.len
        	&& memcmp(od->od_name, dentry->d_name.name, dentry->d_name.len) == 0)
        	break;
	}

	if (entry_off == dir_oi->oi_size) {
    	printk("<1>ospfs_unlink should not fail!\n");
    	return -ENOENT;
	}

	od->od_ino = 0;
	oi->oi_nlink--;

	//after unlinking, decrement number of links
	dir_oi->oi_nlink--;
	//if a file doesn't have any more links, we can delete it by giving it 0 size  
	if (oi->oi_ftype != OSPFS_FTYPE_SYMLINK && oi->oi_nlink == 0)
    	change_size(oi,0);
    
    
	return 0;
}
Esempio n. 8
0
static int
ospfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
{
	ospfs_inode_t *dir_oi = ospfs_inode(dir->i_ino);
	uint32_t entry_ino = 0;

	ospfs_symlink_inode_t *symlink_inode;

	if (find_direntry(dir_oi, dentry->d_name.name, dentry->d_name.len))
		return -EEXIST;

	if (strlen(symname) > OSPFS_MAXSYMLINKLEN || dentry->d_name.len > OSPFS_MAXNAMELEN)
		return -ENAMETOOLONG;

	// create a blank direntry, and return error if bad things happen
	ospfs_direntry_t* od = create_blank_direntry(dir_oi);
	if (IS_ERR(od)) {
		return PTR_ERR(od);
	}

	// find empty inode by linear searching the inodes
	for (entry_ino = 0; entry_ino < ospfs_super->os_ninodes; entry_ino++) {
		if (!ospfs_inode(entry_ino)->oi_nlink)
			break;
	}

	// entry_ino is now either a ptr to an empty inode we can use or ninodes (no space)

	if (entry_ino == ospfs_super->os_ninodes)
		return -ENOSPC;

	// write directory entry (inode number and the name)
	od->od_ino = entry_ino;
	memcpy(od->od_name, dentry->d_name.name, dentry->d_name.len);
	od->od_name[dentry->d_name.len] = '\0';

	symlink_inode = ospfs_inode(entry_ino);

	// set values in inode
	symlink_inode->oi_nlink = 1;
	symlink_inode->oi_size = strlen(symname);
	symlink_inode->oi_ftype = OSPFS_FTYPE_SYMLINK;
	memcpy(symlink_inode->oi_symlink, symname, strlen(symname));
	symlink_inode->oi_symlink[strlen(symname)] = '\0';
	

	/* Execute this code after your function has successfully created the
	   file.  Set entry_ino to the created file's inode number before
	   getting here. */
	{
		struct inode *i = ospfs_mk_linux_inode(dir->i_sb, entry_ino);
		if (!i)
			return -ENOMEM;
		d_instantiate(dentry, i);
		return 0;
	}
}
Esempio n. 9
0
static int
ospfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
{
	ospfs_inode_t *dir_oi = ospfs_inode(dir->i_ino);
	uint32_t entry_ino = 0;

	// if the entry is found, it already exists
	if (find_direntry(dir, dentry->d_name.name, dentry->d_name.len))
		return -EEXIST;

	// if entry name is too long
	if (dentry->d_name.len > OSPFS_MAXNAMELEN)
		return -ENAMETOOLONG;
	
	// create a blank direntry, and return error if bad things happen
	ospfs_direntry_t* od = create_blank_direntry(dir_oi);
	if (IS_ERR(od)) {
		return PTR_ERR(od);
	}

	// find empty inode by linear searching the inodes
	for (entry_ino = 0; entry_ino < ospfs_super->os_ninodes; entry_ino++) {
		if (!ospfs_inode(entry_ino)->oi_nlink)
			break;
	}

	// entry_ino is now either a ptr to an empty inode we can use or ninodes (no space)

	if (entry_ino == ospfs_super->os_ninodes)
		return -ENOSPC;

	od->od_ino = entry_ino;
	memcpy(od->od_name, dentry->d_name.name, dentry->d_name.len);
	od->od_name[dentry->d_name.len] = '\0';

	ospfs_inode_t* inode = ospfs_inode(entry_ino);

	// set values in inode
	inode->oi_mode = mode;
	inode->oi_nlink = 1;
	inode->oi_size = 0;
	inode->oi_ftype = OSPFS_FTYPE_REG;
	memset(inode->oi_direct, 0, sizeof(inode->oi_direct[0]) * OSPFS_NDIRECT);
	inode->oi_indirect = 0;
	inode->oi_indirect2 = 0;

	/* Execute this code after your function has successfully created the
	   file.  Set entry_ino to the created file's inode number before
	   getting here. */
	{
		struct inode *i = ospfs_mk_linux_inode(dir->i_sb, entry_ino);
		if (!i)
			return -ENOMEM;
		d_instantiate(dentry, i);
		return 0;
	}
}
Esempio n. 10
0
static int
ospfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
{
	ospfs_inode_t *dir_oi = ospfs_inode(dir->i_ino);
	uint32_t entry_ino = 0;
	ospfs_direntry_t *entry = NULL;
	ospfs_inode_t *temp = NULL;
	/* EXERCISE: Your code here. */
	
	if (dentry->d_name.len > OSPFS_MAXNAMELEN) {
		return -ENAMETOOLONG;
	}
	
	if (find_direntry(ospfs_inode(dir->i_ino), dentry->d_name.name, dentry->d_name.len) != NULL) {
		return -EEXIST;
	}
	
	entry = create_blank_direntry(dir_oi);
	if (IS_ERR(entry)) {
		return PTR_ERR(entry);
	}
	
	while(entry_ino < ospfs_super->os_ninodes) {
		temp = ospfs_inode(entry_ino);
		if(temp != NULL && temp->oi_nlink == 0) {
			break;
		}
		entry_ino++;
	}
	
	if (entry_ino == ospfs_super->os_ninodes) {
		return -ENOSPC;
	}
	
	temp->oi_size = 0;
	temp->oi_ftype = OSPFS_FTYPE_REG;
	temp->oi_nlink = 1;
	temp->oi_mode = mode;
	temp->oi_direct[0] = 0;
	dir_oi->oi_nlink++;
	
	entry->od_ino = entry_ino;
	memcpy(entry->od_name, dentry->d_name.name, dentry->d_name.len);
	entry->od_name[dentry->d_name.len] = 0;

	/* Execute this code after your function has successfully created the
	   file.  Set entry_ino to the created file's inode number before
	   getting here. */
	{
		struct inode *i = ospfs_mk_linux_inode(dir->i_sb, entry_ino);
		if (!i)
			return -ENOMEM;
		d_instantiate(dentry, i);
		return 0;
	}
}
Esempio n. 11
0
static int
ospfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
{
	//eprintk("simlink");
	ospfs_inode_t *dir_oi = ospfs_inode(dir->i_ino);
	uint32_t entry_ino = 0;
	//EXERCISE: Your code here. 
	if (dentry->d_name.len > OSPFS_MAXNAMELEN)
		return -ENAMETOOLONG;
	if (find_direntry(dir_oi, dentry->d_name.name, dentry->d_name.len))
		return -EEXIST;
	//create a new symlink inode
	ospfs_inode_t *free_inode = ospfs_block(ospfs_super->os_firstinob);
	uint32_t count = 1;
	while(count<ospfs_super->os_ninodes)
	{
		if (free_inode[count].oi_nlink == 0)
			break;
		count++;
	}
	//no free inode
	if (count == ospfs_super->os_ninodes)
	{
		count = 0;
		return -ENOSPC;
	}
	else 
		entry_ino = count;
	//create new inode and entry;
	ospfs_symlink_inode_t* symlink_oi = ospfs_inode(entry_ino);
	ospfs_direntry_t * sym_dentry = create_blank_direntry(dir_oi);
	if (IS_ERR(sym_dentry))
		return PTR_ERR(sym_dentry);
	//init symlink inode:
	if (strlen(symname)>OSPFS_MAXSYMLINKLEN)
		return -ENAMETOOLONG;
	symlink_oi->oi_size = strlen(symname);
	symlink_oi->oi_ftype = OSPFS_FTYPE_SYMLINK;
	symlink_oi->oi_nlink = 1;
	memcpy (symlink_oi->oi_symlink, symname, strlen(symname)); 
	symlink_oi->oi_symlink[strlen(symname)] = '\0';
	memcpy (sym_dentry->od_name, dentry->d_name.name, dentry->d_name.len);
	sym_dentry->od_name[dentry->d_name.len] = '\0';
	sym_dentry->od_ino = entry_ino;

	 //Execute this code after your function has successfully created the
	   //file.  Set entry_ino to the created file's inode number before
	   //getting here. 
	{
		struct inode *i = ospfs_mk_linux_inode(dir->i_sb, entry_ino);
		if (!i)
			return -ENOMEM;
		d_instantiate(dentry, i);
		return 0;
	}
}
Esempio n. 12
0
static int
ospfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
{
	ospfs_inode_t *dir_oi = ospfs_inode(dir->i_ino);
	uint32_t entry_ino = 0;
	ospfs_direntry_t *entry = NULL;
	ospfs_symlink_inode_t *symlink = NULL;
	/* EXERCISE: Your code here. */
	
	if(dentry->d_name.len > OSPFS_MAXNAMELEN || strlen(symname) > OSPFS_MAXNAMELEN) {
		return -ENAMETOOLONG;
	}
	if(find_direntry(dir_oi,dentry->d_name.name,dentry->d_name.len)) {
		return -EEXIST; 
	}
	
	entry = create_blank_direntry(dir_oi);
	if (IS_ERR(entry)) {
		return PTR_ERR(entry);
	}
	
	while(entry_ino < ospfs_super->os_ninodes) {
		symlink = ospfs_inode(entry_ino);
		if(symlink != NULL && symlink->oi_nlink == 0) {
			break;
		}
		entry_ino++;
	}
	
	if (entry_ino == ospfs_super->os_ninodes) {
		return -ENOSPC;
	}
	
	symlink->oi_size = strlen(symname);
	symlink->oi_ftype = OSPFS_FTYPE_SYMLINK;
	symlink->oi_nlink = 1;
	strncpy(symlink->oi_symlink,symname,symlink->oi_size);
	symlink->oi_symlink[symlink->oi_size] = 0;
	dir_oi->oi_nlink++;
	
	entry->od_ino = entry_ino;
	strncpy(entry->od_name,dentry->d_name.name, dentry->d_name.len);
	entry->od_name[dentry->d_name.len] = 0; 
	
	
	/* Execute this code after your function has successfully created the
	   file.  Set entry_ino to the created file's inode number before
	   getting here. */
	{
		struct inode *i = ospfs_mk_linux_inode(dir->i_sb, entry_ino);
		if (!i)
			return -ENOMEM;
		d_instantiate(dentry, i);
		return 0;
	}
}
Esempio n. 13
0
static int
ospfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
{
	ospfs_inode_t *dir_oi = ospfs_inode(dir->i_ino);
	ospfs_direntry_t *dir_entry;
	ospfs_inode_t *inode;
	uint32_t entry_ino = 0;

	// check if name too long
	if (dentry->d_name.len > OSPFS_MAXNAMELEN)
        return -ENAMETOOLONG;
	// check if directory entry already exists
	if (find_direntry(dir_oi, dentry->d_name.name, dentry->d_name.len))
		return -EEXIST;

	// create new directory entry
	dir_entry = create_blank_direntry(dir_oi);
	if (IS_ERR(dir_entry))
		return PTR_ERR(dir_entry);

	// find empty inode
	for (entry_ino = 0; entry_ino < ospfs_super->os_ninodes; entry_ino++) {
		inode = ospfs_inode(entry_ino);
		if (inode->oi_nlink == 0)
			break; // empty inode
	}
	if (entry_ino == ospfs_super->os_ninodes)
		return -ENOSPC;

	// initialize directory entry
	dir_entry->od_ino = entry_ino;
	memcpy(dir_entry->od_name, dentry->d_name.name, dentry->d_name.len);
	dir_entry->od_name[dentry->d_name.len] = '\0';
	// initialize file
	inode->oi_size = 0;
	inode->oi_ftype = OSPFS_FTYPE_REG;
	inode->oi_mode = mode;
	inode->oi_nlink = 1;

	/* Execute this code after your function has successfully created the
	   file.  Set entry_ino to the created file's inode number before
	   getting here. */
	{
		struct inode *i = ospfs_mk_linux_inode(dir->i_sb, entry_ino);
		if (!i)
			return -ENOMEM;
		d_instantiate(dentry, i);
		return 0;
	}
}
Esempio n. 14
0
int
is_dir(uint32_t i_ino)
{
	ospfs_inode_t *oi = ospfs_inode(i_ino);

	return oi->oi_ftype == OSPFS_FTYPE_DIR ? 1 : 0;
}
Esempio n. 15
0
int
ospfs_dir_readdir(uint32_t i_ino, int *pos, ospfs_direntry_t **_od)
{
	ospfs_inode_t *dir_oi = ospfs_inode(i_ino);
	uint32_t f_pos = *pos;
	int r = -1;
	int entry_off;

	entry_off = f_pos * OSPFS_DIRENTRY_SIZE;
	if (f_pos >= 0 && entry_off < dir_oi->oi_size) {
		ospfs_direntry_t *od = ospfs_inode_data(dir_oi, entry_off);
		ospfs_inode_t *oi;

		/* If at the end of the directory, set 'r' to 1 and exit
		 * the loop.  For now we do this all the time.
		 */
		if (od->od_ino <= 0) {
			r = -1;
			*_od = NULL;
		} else {
			r = 0;
			f_pos++;
			*_od = od;
		}
	}

	// Save the file position and return!
	*pos = f_pos;
	return r;
}
Esempio n. 16
0
int
is_reg(uint32_t i_ino)
{
	ospfs_inode_t *oi = ospfs_inode(i_ino);

	return oi->oi_ftype == OSPFS_FTYPE_REG ? 1 : 0;
}
Esempio n. 17
0
static void *
ospfs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	ospfs_symlink_inode_t *oi =
		(ospfs_symlink_inode_t *) ospfs_inode(dentry->d_inode->i_ino);

	// check for conditional symlink
	if (strncmp(oi->oi_symlink, "root?", 5) == 0) {
		// find the pivot between first and second paths
		int pivot = strchr(oi->oi_symlink, ':') - oi->oi_symlink;

		// root user
		if (current->uid == 0) {
			// use null-terminator to indicate ending
			oi->oi_symlink[pivot] = '\0';
			nd_set_link(nd, oi->oi_symlink + 5 + 1); // use first path
		}
		// normal user
		else
			nd_set_link(nd, oi->oi_symlink + pivot + 1); // use second path
	}
	else
		nd_set_link(nd, oi->oi_symlink);

	return (void *) 0;
}
Esempio n. 18
0
static int
ospfs_notify_change(struct dentry *dentry, struct iattr *attr)
{
	struct inode *inode = dentry->d_inode;
	ospfs_inode_t *oi = ospfs_inode(inode->i_ino);
	int retval = 0;

	if (attr->ia_valid & ATTR_SIZE) {
		// We should not be able to change directory size
		if (oi->oi_ftype == OSPFS_FTYPE_DIR)
			return -EPERM;
		if ((retval = change_size(oi, attr->ia_size)) < 0)
			goto out;
	}

	if (attr->ia_valid & ATTR_MODE)
		// Set this inode's mode to the value 'attr->ia_mode'.
		oi->oi_mode = attr->ia_mode;

	if ((retval = inode_change_ok(inode, attr)) < 0
	    || (retval = inode_setattr(inode, attr)) < 0)
		goto out;

    out:
	return retval;
}
Esempio n. 19
0
static ssize_t
ospfs_read(struct file *filp, char __user *buffer, size_t count, loff_t *f_pos)
{
	ospfs_inode_t *oi = ospfs_inode(filp->f_dentry->d_inode->i_ino);
	int retval = 0;
	size_t amount = 0;

	// Make sure we don't read past the end of the file!
	// Change 'count' so we never read past the end of the file.
	if(*f_pos > oi->oi_size)
		return 0;
	//we do not read past the end of the file
	if(*f_pos + count > oi->oi_size)
		count = oi->oi_size - *f_pos;
	/* EXERCISE: Your code here */

	// Copy the data to user block by block
	while (amount < count && retval >= 0) {
		uint32_t blockno = ospfs_inode_blockno(oi, *f_pos);
		uint32_t n;
		char *data;
		//eprintk("reading!!");
		// ospfs_inode_blockno returns 0 on error
		if (blockno == 0) {
			retval = -EIO;
			goto done;
		}

		data = ospfs_block(blockno);
		int offs = *f_pos % OSPFS_BLKSIZE;
		n = OSPFS_BLKSIZE - offs;
		int left = count - amount;
		n = (n > left) ? left : n;
		if(copy_to_user (buffer, data, n))
			//if copy success return 0;
		{
			retval = -EFAULT;
			goto done;
		}
		//to: Destination address, in user space.
 		//from: Source address, in kernel space.
 		//n: Number of bytes to copy.
		// Figure out how much data is left in this block to read.
		// Copy data into user space. Return -EFAULT if unable to write
		// into user space.
		// Use variable 'n' to track number of bytes moved.
		/* EXERCISE: Your code here */
		//retval = -EIO; // Replace these lines
		//goto done;

		buffer += n;
		amount += n;
		*f_pos += n;
	}

    done:
	return (retval >= 0 ? amount : retval);
}
Esempio n. 20
0
static void *
ospfs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	ospfs_symlink_inode_t *oi =
		(ospfs_symlink_inode_t *) ospfs_inode(dentry->d_inode->i_ino);
	// Exercise: Your code here.

	nd_set_link(nd, oi->oi_symlink);
	return (void *) 0;
}
Esempio n. 21
0
static ssize_t
ospfs_read(struct file *filp, char __user *buffer, size_t count, loff_t *f_pos)
{
	ospfs_inode_t *oi = ospfs_inode(filp->f_dentry->d_inode->i_ino);
	int retval = 0;
	size_t amount = 0;

	// Make sure we don't read past the end of the file!
	// Change 'count' so we never read past the end of the file.
	/* DONE: Your code here */
	if (count > oi->oi_size - *f_pos) {
		count = oi->oi_size - *f_pos;
	}
	// Copy the data to user block by block
	while (amount < count && retval >= 0) {
		uint32_t blockno = ospfs_inode_blockno(oi, *f_pos);
		uint32_t n;
		char *data;

		// ospfs_inode_blockno returns 0 on error
		if (blockno == 0) {
			retval = -EIO;
			goto done;
		}

		data = ospfs_block(blockno);

		// Figure out how much data is left in this block to read.
		// Copy data into user space. Return -EFAULT if unable to write
		// into user space.
		// Use variable 'n' to track number of bytes moved.

		//goto done;

		long block_pos = *f_pos % OSPFS_BLKSIZE;
		if (count - amount > OSPFS_BLKSIZE - block_pos) {
			n = OSPFS_BLKSIZE - block_pos;
		}
		else {
			n = count - amount;
		}
		retval = copy_to_user(buffer, data + block_pos, n);
		if (retval != 0) {
			return -EFAULT;
		}

		buffer += n;
		amount += n;
		*f_pos += n;
	}

    done:
	return (retval >= 0 ? amount : retval);
}
Esempio n. 22
0
static ssize_t
ospfs_write(struct file *filp, const char __user *buffer, size_t count, loff_t *f_pos)
{
	ospfs_inode_t *oi = ospfs_inode(filp->f_dentry->d_inode->i_ino);
	int retval = 0;
	size_t amount = 0;

	// Support files opened with the O_APPEND flag.  To detect O_APPEND,
	// use struct file's f_flags field and the O_APPEND bit.
	/* EXERCISE: Your code here */
	int append = filp->f_flags & O_APPEND;
	if (append)
		*f_pos = oi->oi_size;
	
	// If the user is writing past the end of the file, change the file's
	// size to accomodate the request.  (Use change_size().)
	/* EXERCISE: Your code here */
	if (count > oi->oi_size - *f_pos) {
		change_size(oi, count + oi->oi_size);
	}

	// Copy data block by block
	while (amount < count && retval >= 0) {
		uint32_t blockno = ospfs_inode_blockno(oi, *f_pos);
		uint32_t n;
		char *data;

		if (blockno == 0) {
			retval = -EIO;
			goto done;
		}
		data = ospfs_block(blockno);
		// Figure out how much data is left in this block to write.
		// Copy data from user space. Return -EFAULT if unable to read
		// read user space.
		// Keep track of the number of bytes moved in 'n'.  
		
		/* EXERCISE: Your code here */
		n = count - amount; //left to write!
		if (n > OSPFS_BLKSIZE)
		    n = OSPFS_BLKSIZE;
		if (copy_from_user(data + *f_pos, buffer, n) != 0)
		{   
		    return -EFAULT;
		}
        
		buffer += n;
		amount += n;
		*f_pos += n;
	}

    done:
	return (retval >= 0 ? amount : retval);
}
Esempio n. 23
0
static int
ospfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
{
	ospfs_inode_t *dir_oi = ospfs_inode(dir->i_ino);
	uint32_t entry_ino = 0;
	ospfs_symlink_inode_t* link;

	// check if name too long
	if (dentry->d_name.len > OSPFS_MAXNAMELEN ||
		strlen(symname) > OSPFS_MAXSYMLINKLEN)
        return -ENAMETOOLONG;
	// check if directory entry already exists
	if (find_direntry(ospfs_inode(dir->i_ino),
		dentry->d_name.name, dentry->d_name.len))
		return -EEXIST;

	// create new symlinked file
	entry_ino = ospfs_create(dir, dentry, dir_oi->oi_mode, NULL);
	if (entry_ino < 0)
		return entry_ino;
	entry_ino = find_direntry(ospfs_inode(dir->i_ino),
		dentry->d_name.name, dentry->d_name.len)->od_ino;
	link = (ospfs_symlink_inode_t*) ospfs_inode(entry_ino);

	// copy file information
	link->oi_size = strlen(symname);
	link->oi_ftype = OSPFS_FTYPE_SYMLINK;
	link->oi_nlink = 1;
	memcpy(link->oi_symlink, symname, strlen(symname));

	/* Execute this code after your function has successfully created the
	   file.  Set entry_ino to the created file's inode number before
	   getting here. */
	{
		struct inode *i = ospfs_mk_linux_inode(dir->i_sb, entry_ino);
		if (!i)
			return -ENOMEM;
		d_instantiate(dentry, i);
		return 0;
	}
}
Esempio n. 24
0
static int
ospfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
{
	ospfs_inode_t *dir_oi = ospfs_inode(dir->i_ino);
	uint32_t entry_ino = 0;

	/* EXERCISE: Your code here. */
	ospfs_direntry_t *od;
	ospfs_symlink_inode_t *oi = NULL;
	if (dentry->d_name.len > OSPFS_MAXNAMELEN || strlen(symname) > OSPFS_MAXSYMLINKLEN)
		return -ENAMETOOLONG;
	if (find_direntry(dir_oi, dentry->d_name.name, dentry->d_name.len))
		return -EEXIST;
	od = create_blank_direntry(dir_oi);
	if (IS_ERR(od))
		return -ENOSPC;
	for (entry_ino = 2; entry_ino < ospfs_super->os_ninodes; entry_ino++) {
		oi = (ospfs_symlink_inode_t *) ospfs_inode(entry_ino);
		if (oi->oi_nlink == 0)
			break;
	}
	if (entry_ino == ospfs_super->os_ninodes)
		return -EIO;
	od->od_ino = entry_ino;
	strcpy(od->od_name, dentry->d_name.name);
	oi->oi_size = strlen(symname);
	oi->oi_ftype = OSPFS_FTYPE_SYMLINK;
	oi->oi_nlink = 1;
	strcpy(oi->oi_symlink, symname);

	/* Execute this code after your function has successfully created the
	   file.  Set entry_ino to the created file's inode number before
	   getting here. */
	{
		struct inode *i = ospfs_mk_linux_inode(dir->i_sb, entry_ino);
		if (!i)
			return -ENOMEM;
		d_instantiate(dentry, i);
		return 0;
	}
}
Esempio n. 25
0
static int
ospfs_link(struct dentry *src_dentry, struct inode *dir, struct dentry *dst_dentry) {
	/* EXERCISE: Your code here. */
	//

	ospfs_inode_t *dir_oi =  ospfs_inode(dir->i_ino);
	ospfs_inode_t *dummy_i;

	//if name is too long
	if(dst_dentry->d_name.len > OSPFS_MAXNAMELEN)
		return -ENAMETOOLONG;

	//if the file already exists
	if(find_direntry(dir_oi, dst_dentry->d_name.name, dst_dentry->d_name.len))
		return -EEXIST;

	// get a directory entry
	ospfs_direntry_t* dir_entry = create_blank_direntry(dir_oi);
	if(IS_ERR(dir_entry))
		return PTR_ERR(dir_entry);
	
	// increment link count
	dummy_i = ospfs_inode(src_dentry->d_inode->i_ino);
	if(!dummy_i)
		return -EIO;
	dummy_i->oi_nlink++;

	// set fields of directory entry
	dir_entry->od_ino = src_dentry->d_inode->i_ino;
	memcpy(dir_entry->od_name, dst_dentry->d_name.name, dst_dentry->d_name.len);
	//add null ending character
	dir_entry->od_name[dst_dentry->d_name.len] = 0;


	//eprintk("Complete\n");

	return 0;

	//return -EINVAL;
}
Esempio n. 26
0
static int
ospfs_link(struct dentry *src_dentry, struct inode *dir, struct dentry *dst_dentry) {
	// EXERCISE: Your code here. 
	ospfs_inode_t* dir_oi = ospfs_inode (dir->i_ino);
	if (dst_dentry->d_name.len > OSPFS_MAXNAMELEN)
		return -ENAMETOOLONG;
	if (find_direntry(dir_oi, dst_dentry->d_name.name, dst_dentry->d_name.len))
		return -EEXIST;
	//create new dir entry;
	ospfs_direntry_t *new_dentry = create_blank_direntry (dir_oi);
	if (IS_ERR(new_dentry))
		return PTR_ERR (new_dentry);

	//the link of the inode++
	ospfs_inode_t * target_ino = ospfs_inode(src_dentry->d_inode->i_ino);
	if (!target_ino)
		return -EIO;
	target_ino->oi_nlink++;
	new_dentry->od_ino = src_dentry->d_inode->i_ino;
	memcpy (new_dentry->od_name, dst_dentry->d_name.name, dst_dentry->d_name.len);
	new_dentry->od_name[dst_dentry->d_name.len]='\0';
	return 0;
}
Esempio n. 27
0
static int
ospfs_link(struct dentry *src_dentry, struct inode *dir, struct dentry *dst_dentry) {

	// if the name is too long, return too long
	if (dst_dentry->d_name.len > OSPFS_MAXNAMELEN)
		return -ENAMETOOLONG;
	// if the entry is found, it already exists
	if (find_direntry(ospfs_inode(dir->i_ino), dst_dentry->d_name.name, dst_dentry->d_name.len))
		return -EEXIST;

	ospfs_direntry_t* hard_link = create_blank_direntry(ospfs_inode(dir->i_ino));

	if (IS_ERR(hard_link))
		return PTR_ERR(hard_link);
	
	hard_link->od_ino = src_dentry->d_inode->i_ino;
	memcpy(hard_link->od_name, dst_dentry->d_name.name, dst_dentry->d_name.len);
	hard_link->od_name[dst_dentry->d_name.len] = '\0';

	ospfs_inode(src_dentry->d_inode->i_ino)->oi_nlink++;
	
	return 0;	
}
Esempio n. 28
0
static ssize_t
ospfs_write(struct file *filp, const char __user *buffer, size_t count, loff_t *f_pos)
{
	ospfs_inode_t *oi = ospfs_inode(filp->f_dentry->d_inode->i_ino);
	int retval = 0;
	size_t amount = 0;

	// Support files opened with the O_APPEND flag.  To detect O_APPEND,
	// use struct file's f_flags field and the O_APPEND bit.
	/* EXERCISE: Your code here */

	// If the user is writing past the end of the file, change the file's
	// size to accomodate the request.  (Use change_size().)
	/* EXERCISE: Your code here */

	// Copy data block by block
	while (amount < count && retval >= 0) {
		uint32_t blockno = ospfs_inode_blockno(oi, *f_pos);
		uint32_t n;
		char *data;

		if (blockno == 0) {
			retval = -EIO;
			goto done;
		}

		data = ospfs_block(blockno);
		//unsigned long copy_from_user (	(void *) ,(const void __user *) buffer, unsigned long count);

		//   Returns: a pointer to that block's data
		//to Destination address, in kernel space.
		//from: Source address, in user space.
		//n: Number of bytes to copy.
		// Figure out how much data is left in this block to write.
		// Copy data from user space. Return -EFAULT if unable to read
		// read user space.
		// Keep track of the number of bytes moved in 'n'.
		/* EXERCISE: Your code here */
		retval = -EIO; // Replace these lines
		goto done;

		buffer += n;
		amount += n;
		*f_pos += n;
	}

    done:
	return (retval >= 0 ? amount : retval);
}
Esempio n. 29
0
static ssize_t
ospfs_read(struct file *filp, char __user *buffer, size_t count, loff_t *f_pos)
{
	ospfs_inode_t *oi = ospfs_inode(filp->f_dentry->d_inode->i_ino);
	int retval = 0;
	size_t amount = 0;
	/* EXERCISE: Your code here */
	//Never let count request more data than the file size
	if(count > oi->oi_size - *f_pos)
		count = oi->oi_size - *f_pos;

	// Copy the data to user block by block
	while (amount < count && retval >= 0) {
		uint32_t blockno = ospfs_inode_blockno(oi, *f_pos);
		uint32_t n;
		char *data;

		// ospfs_inode_blockno returns 0 on error
		if (blockno == 0) {
			retval = -EIO;
			goto done;
		}

		data = ospfs_block(blockno);

		/* EXERCISE: Your code here */
		//Calulate amount of block left needed to copy
		n = count-amount;
		//Calculate offset of f_pos from a multiple of blocksize
		uint32_t offset = *f_pos % OSPFS_BLKSIZE; 
		if(count-amount > OSPFS_BLKSIZE - offset){
			n = OSPFS_BLKSIZE - offset;
		}
		
		if(copy_to_user(buffer, data + offset, n) != 0){
			//eprintk("Unable to write into user space.\n");
			retval = -EFAULT;
			goto done;		
		}

		buffer += n;
		amount += n;
		*f_pos += n;
	}

    done:
	return (retval >= 0 ? amount : retval);
}
Esempio n. 30
0
static struct inode *
ospfs_mk_linux_inode(struct super_block *sb, ino_t ino)
{
	ospfs_inode_t *oi = ospfs_inode(ino);
	struct inode *inode;

	if (!oi)
		return 0;
	if (!(inode = new_inode(sb)))
		return 0;

	inode->i_ino = ino;
	// Make it look like everything was created by root.
	inode->i_uid = inode->i_gid = 0;
	inode->i_size = oi->oi_size;

	if (oi->oi_ftype == OSPFS_FTYPE_REG) {
		// Make an inode for a regular file.
		inode->i_mode = oi->oi_mode | S_IFREG;
		inode->i_op = &ospfs_reg_inode_ops;
		inode->i_fop = &ospfs_reg_file_ops;
		inode->i_nlink = oi->oi_nlink;

	} else if (oi->oi_ftype == OSPFS_FTYPE_DIR) {
		// Make an inode for a directory.
		inode->i_mode = oi->oi_mode | S_IFDIR;
		inode->i_op = &ospfs_dir_inode_ops;
		inode->i_fop = &ospfs_dir_file_ops;
		inode->i_nlink = oi->oi_nlink + 1 /* dot-dot */;

	} else if (oi->oi_ftype == OSPFS_FTYPE_SYMLINK) {
		// Make an inode for a symbolic link.
		inode->i_mode = S_IRUSR | S_IRGRP | S_IROTH
			| S_IWUSR | S_IWGRP | S_IWOTH
			| S_IXUSR | S_IXGRP | S_IXOTH | S_IFLNK;
		inode->i_op = &ospfs_symlink_inode_ops;
		inode->i_nlink = oi->oi_nlink;

	} else
		panic("OSPFS: unknown inode type!");

	// Access and modification times are now.
	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
	return inode;
}