Exemple #1
0
/* 
 * Write size bytes from buf into file starting from offset
 *
 */
static int cs1550_write(const char *path, const char *buf, size_t size, 
			  off_t offset, struct fuse_file_info *fi)
{
	(void) fi;
	meta_entry attribute = find_correct_directory(path);
	int index = attribute.file_index;
	cs1550_directory_entry directory_entry = get_directory_entry( attribute.index_of_directory );	

	if( index == -1)	//check to make sure path exists
	{
		size = -1;	//error
	}
	
	else if(  && offset <= directory_entry.files[index].fsize )	//check that offset is <= to the file size and file size is greater than 0
	{
		//write data
		FILE *disk;
		cs1550_disk_block block;	//block to be written
		disk = fopen(".disk", "r+b");
			
		fseek(disk, directory_entry.files[ index ].nStartBlock + offset, SEEK_SET);	//seek from start to where the first block is plus offset
		strcpy(block.data, buf);
		fwrite(&block.data, sizeof(char), sizeof(buf), disk);	//write data			

		size = strlen(buf);	//return the length of data
		fclose(disk);	

		directory_entry.files[index].fsize = size;
		write_directory_entry( directory_entry, attribute.index_of_directory);
	}

	else if( offset <= directory_entry.files[index].fsize )	//append the file
Exemple #2
0
/*
 * syscall_stat
 * 
 * Implementation of the stat system call, which obtains information about a
 * particular file or directory. You should use this as a guideline for how to
 * implement the other system calls in assignment 3.
 */
int syscall_stat(const char *path, struct stat *buf)
{
	/*
	 * Ensure the supplied path name and buffer are valid pointers 
	 */
	if (!valid_string(path))
		return -EFAULT;
	if (!valid_pointer(buf, sizeof(struct stat)))
		return -EFAULT;

	/*
	 * Get the directory_entry object for this path from the filesystem 
	 */
	directory_entry *entry;
	int r;

	char abs[PATH_MAX];
	relative_to_absolute(abs, current_process->cwd, path, PATH_MAX);
	if (0 != (r = get_directory_entry(filesystem, abs, &entry)))
		return r;

	/*
	 * Set all fields of the stat buffer 
	 */
	buf->st_mode = entry->mode;
	buf->st_uid = 0;
	buf->st_gid = 0;
	buf->st_size = entry->size;
	buf->st_mtime = entry->mtime;

	return 0;
}
Exemple #3
0
/* 
 * Called whenever the contents of a directory are desired. Could be from an 'ls'
 * or could even be when a user hits TAB to do autocompletion
 */
static int cs1550_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
			 off_t offset, struct fuse_file_info *fi)
{
	//Since we're building with -Wall (all warnings reported) we need
	//to "use" every parameter, so let's just cast them to void to
	//satisfy the compiler
	(void) offset;
	(void) fi;
	int res = -ENOENT;
	
	//the filler function allows us to add entries to the listing
	//read the fuse.h file for a description (in the ../include dir)
	filler(buf, ".", NULL, 0);
	filler(buf, "..", NULL, 0);

	if ( strcmp(path, "/") == 0 )	//means that the path is root, so filler() all subdirectories
	{
		FILE *directory_list;
		cs1550_directory_entry current_directory;	//current directory to be printed out
		
		directory_list = fopen(".directories", "rb");	//open .directories
		
		if(directory_list != NULL)
		{
			while( fread(&current_directory, sizeof(current_directory), 1, directory_list) == 1 )
			{
				filler(buf, current_directory.dname + 1, NULL, 0);
			}
			fclose(directory_list);
		}
		res = 0;
	}

	else
	{
		//add the user stuff (subdirs or files)
		//the +1 skips the leading '/' on the filenames
		meta_entry attribute = find_correct_directory(path);
			
		if(attribute.index_of_directory > -1)	//means that parameter path is a directory(aka subdirectory of root)
		{
			cs1550_directory_entry directory_entry = get_directory_entry( attribute.index_of_directory );
			
			int count;
			for(count = 0; count < directory_entry.nFiles; count++)	//go through filler() the files
			{
				char fullname[12] = "";
				sprintf(fullname, "%s.%s", directory_entry.files[count].fname, directory_entry.files[count].fext);
				filler(buf, fullname, NULL, 0);
			}
			res = 0;
		}
	}
	return res;
}
Exemple #4
0
int syscall_chdir(const char *path)
{
	if (!valid_string(path))
		return -EFAULT;

	char newcwd[PATH_MAX];
	relative_to_absolute(newcwd, current_process->cwd, path, PATH_MAX);
	int r;
	directory_entry *entry;
	if (0 != (r = get_directory_entry(filesystem, newcwd, &entry)))
		return r;
	if (TYPE_DIR != entry->type)
		return -ENOTDIR;
	memmove(current_process->cwd, newcwd, PATH_MAX);
	return 0;
}
Exemple #5
0
/* 
 * Does the actual creation of a file. Mode and dev can be ignored.
 *
 */
static int cs1550_mknod(const char *path, mode_t mode, dev_t dev)
{
	(void) mode;
	(void) dev;
	char directory[MAX_FILENAME + 1];	//name of directory we are looking for
	char filename[MAX_FILENAME + 1];	//name of file we are looking for
	char extension[MAX_EXTENSION + 1];	//file extension we are looking for
	
	int res = 0;
	meta_entry attribute = find_correct_directory(path);  

	sscanf(path, "/%[^/]/%[^.].%s", directory, filename, extension);	//tokenizes and stores the strings for the directory we are looking for	

	if( attribute.slash_count == 1 )	//under root, do not give permission
	{
		res = -EPERM;
	}

	else if( strlen(filename) > 8 || strlen(extension) > 3 )	//name length is too long
	{
		res = -ENAMETOOLONG;
	}

	else if( attribute.file_index > -1)	//is already a file
	{
		res = -EEXIST;
	}

	else	//create file
	{
		cs1550_directory_entry directory_entry = get_directory_entry( attribute.index_of_directory );
				
		strcpy(directory_entry.files[ directory_entry.nFiles ].fname, filename); //put filename in array index
		strcpy(directory_entry.files[ directory_entry.nFiles ].fext, extension);	//put extension in array index
//		directory_entry.files[ directory_entry.nFiles ].fsize = 512;	//size of block

		directory_entry.files[ directory_entry.nFiles ].fsize = 0;	//size of block
		directory_entry.files[ directory_entry.nFiles ].nStartBlock = get_first_free_block();	//gets the first free block
		directory_entry.nFiles = directory_entry.nFiles++;	//increment the amount of files  

		write_directory_entry( directory_entry, attribute.index_of_directory );	//write the directory entry			
		
	}

	return res;
}
Exemple #6
0
int locate_file(char *directory, char *filename, char *extension)	//locates and returns index of file in directory, -1 means not located
{
	int index_of_file = -1;
	int count;	//count of file indexes
	int index_of_directory = locate_directory( directory );	//locates the directory that holds supposive file

	if(index_of_directory > -1)	//means the directory is actually there
	{
		cs1550_directory_entry current_directory = get_directory_entry( index_of_directory );	//get directory
	
		for(count = 0; count < current_directory.nFiles; count++)
		{
			//checks if filename and extension match
			if( strcmp(filename, current_directory.files[ count ].fname) == 0 && strcmp(extension, current_directory.files[ count ].fext) == 0 )
			{
				index_of_file = count;
				break;
			}
		}
	}
	return index_of_file;
}
Exemple #7
0
int syscall_open(const char *pathname, int flags)
{
	if (!valid_string(pathname))
		return -EFAULT;

	int fd = -1;
	for (fd = 0; fd < MAX_FDS; fd++) {
		if (NULL == current_process->filedesc[fd])
			break;
	}
	if (MAX_FDS == fd)
		return -EMFILE;

	char abspath[PATH_MAX];
	relative_to_absolute(abspath, current_process->cwd, pathname, PATH_MAX);

	directory_entry *entry;
	int r;
	if (0 != (r = get_directory_entry(filesystem, abspath, &entry)))
		return r;

	if ((flags == OPEN_DIRECTORY) && (entry->type != TYPE_DIR))
		return -ENOTDIR;
	else if ((flags != OPEN_DIRECTORY) && (entry->type == TYPE_DIR))
		return -EISDIR;

	filehandle *fh;
	if (TYPE_DIR == entry->type)
		fh = new_file(FH_DIR);
	else
		fh = new_file(FH_FILE);
	fh->entry = entry;
	fh->pos = 0;
	fh->entryno = 0;
	current_process->filedesc[fd] = fh;
	return fd;
}
Exemple #8
0
/* 
 * Read size bytes from file into buf starting from offset
 *
 */
static int cs1550_read(const char *path, char *buf, size_t size, off_t offset,
			  struct fuse_file_info *fi)
{
	(void) fi;
	meta_entry attribute = find_correct_directory(path);

	//check to make sure path exists
	if(attribute.index_of_directory > -1 && attribute.slash_count == 1)	//means that paramter path is a directory
	{
		size = -EISDIR;
	}
	
	else
	{
		int index = attribute.file_index;
		cs1550_directory_entry directory_entry = get_directory_entry( attribute.index_of_directory );
		
		if( size > 0 && offset <= directory_entry.files[index].fsize )	//check that size is > 0 and offset is <= to the file size
		{
			//read in data
			FILE *disk;
			disk = fopen(".disk", "rb");

			fseek(disk, directory_entry.files[ index ].nStartBlock + offset, SEEK_SET);	//seek from start to where the first block is plus offset
			fread(buf, sizeof(char), sizeof(buf), disk);	//read in the amount of bytes needed			
 			size = strlen(buf);	//set size and return, or error

			fclose(disk);	
		}
		
		else
		{
			size = -1;	//error
		}
	}
	return size;
}
Exemple #9
0
/*
 * Called whenever the system wants to know the file attributes, including
 * simply whether the file exists or not. 
 *
 * man -s 2 stat will show the fields of a stat structure
 */
static int cs1550_getattr(const char *path, struct stat *stbuf)
{
	int res = -ENOENT;	//sets res to error first, if the directory or file is found then res is set to 0 because there is no error

	memset(stbuf, 0, sizeof(struct stat));
	//is path the root dir?
	if (strcmp(path, "/") == 0) {
		stbuf->st_mode = S_IFDIR | 0755;
		stbuf->st_nlink = 2;
		res = 0;
	} 

	else	//is directly under root directory
	{
		meta_entry attribute = find_correct_directory(path);

		if(attribute.index_of_directory > -1 && attribute.slash_count == 1)	//means that paramter path is a directory
		{
			//Might want to return a structure with these fields
			stbuf->st_mode = S_IFDIR | 0755;
			stbuf->st_nlink = 2;
			res = 0;	
		}

		else if(attribute.index_of_directory > -1 && attribute.file_index > -1)//means that parameter path is a file
		{
			//regular file, probably want to be read and write
			cs1550_directory_entry directory_entry = get_directory_entry( attribute.index_of_directory );
			stbuf->st_mode = S_IFREG | 0666; 
			stbuf->st_nlink = 1; //file link
			stbuf->st_size = directory_entry.files[ attribute.file_index ].fsize; //file size - make sure you replace with real size!
			res = 0; // no error
		}
	}

	return res;
}
Exemple #10
0
/*
 * Deletes a file
 */
static int cs1550_unlink(const char *path)
{
	int res = 0;
	meta_entry attribute = find_correct_directory(path);  

	if( attribute.slash_count == 1 )	//the path is a directory, overwrite res
	{
		res = -EISDIR;
	}

 	else if( attribute.index_of_directory > 1 && attribute.file_index == -1 )	//file not found(or wrong path but goes under same error)
	{
		res = -ENOENT;
	}   	
	
	else	//remove file
	{
		int index = attribute.file_index;
		cs1550_directory_entry directory_entry = get_directory_entry( attribute.index_of_directory );

		//collasce the array
		for( ; index < directory_entry.nFiles-1; index++)
		{
			strcpy( directory_entry.files[ index ].fname, directory_entry.files[ index + 1 ].fname );
			strcpy( directory_entry.files[ index ].fext, directory_entry.files[ index + 1 ].fext );
			directory_entry.files[ index ].fsize = directory_entry.files[ index + 1 ].fsize;
			directory_entry.files[ index ].nStartBlock = directory_entry.files[ index + 1 ].nStartBlock;
		}
		
		directory_entry.nFiles = directory_entry.nFiles--;	//remove the file from count

		write_directory_entry( directory_entry, attribute.index_of_directory );	//write the directory entry			

	}
	return res;
}
Exemple #11
0
		fclose(disk);	

		directory_entry.files[index].fsize = size;
		write_directory_entry( directory_entry, attribute.index_of_directory);
	}

	else if( offset <= directory_entry.files[index].fsize )	//append the file
	{
		//hopefully how many writes is only 1 becuase it will be poor performance otherwise 
		int how_many_writes = (offset - directory_entry.files[index].fsize) / 512 + 1;	//how many times to copy
		int count = 0;
		FILE *disk;
		cs1550_disk_block block;

		FILE *directory_list;	//to edit and sent directory
		cs1550_directory_entry directory = get_directory_entry( attribute.index_of_directory );	//get directory
		while(count < how_many_writes)
		{
			move_file( directory, index);
			disk = fopen(".disk", "r+b");
			strncpy(block.data, buf + count * 512, 512);	//copies up to \0 or 512 bytes
			
			fwrite(&block.data, sizeof(char), sizeof(block.data), disk);	//write the new data
			count++;
			directory.files[index].fsize = directory_entry.files[index].fsize + 512;	//update size
			fclose(disk);
		}
		directory_list = fopen(".directories", "r+b");	
		fseek(directory_list, index * sizeof(directory_entry), SEEK_SET );	//seek to correct direcotry entry
		fwrite(&directory_entry, sizeof(directory_entry), 1, directory_list);	//rewrite the struct				
		fclose(directory_list);
Exemple #12
0
/*
 * syscall_execve
 * 
 * Implements the execve system call. This effectively does a "brain transplant"
 * on a process by arranging for it to run a different program to what it was
 * previously. This is achieved by loading the new program from the file system,
 * placing a copy in the process's text segment, and changing the instruction
 * pointer of the process to point to the first instruction of the loaded
 * executable file.
 * 
 * In addition to loading a new program, this call is also responsible for passing
 * command line arguments to the new program. This is done by using the memory
 * at the bottom of the stack (actually the highest address, since the stack grows
 * downwards), in which the array of strings corresponding to argv is placed. The
 * argv and argc values are placed at the top of the stack, so that the main
 * function will be able to access them as arguments.
 */
int
syscall_execve(const char *filename, char *const argv[],
	       char *const envp[], regs * r)
{
	process *proc = current_process;

	/*
	 * Verify that the filename and all of the pointers within argc arg valid
	 * (i.e. completely reside in the process's address space) 
	 */
	if (!valid_string(filename))
		return -EFAULT;

	unsigned int argno = 0;
	if (NULL != argv) {
		while (1) {
			if (!valid_pointer(argv, (argno + 1) * sizeof(char *)))
				return -EFAULT;
			if (NULL == argv[argno])
				break;
			if (!valid_string(argv[argno]))
				return -EFAULT;
			argno++;
		}
	}

	/*
	 * Check that the specified executable file actually exists, and find out its
	 * location within the file system 
	 */
	directory_entry *entry;
	int res;
	if (0 > (res = get_directory_entry(filesystem, filename, &entry)))
		return res;
	if (TYPE_DIR == entry->type)
		return -EISDIR;

	/*
	 * Calculate number of arguments and amount of space needed to store them 
	 */
	unsigned int argc = 0;
	unsigned int argslen = 0;
	for (argc = 0; argv && argv[argc]; argc++)
		argslen += strlen(argv[argc]) + 1;

	/*
	 * Allocate a temporary buffer in which to store the argument data. This will
	 * later be copied to the process's stack. The reason we can't do this
	 * in-place is that doing so would risk overwriting some of the data we are
	 * copying from. 
	 */
	unsigned int argdata_size =
	    argslen + argc * sizeof(char *) + 2 * sizeof(int);
	char *argdata = kmalloc(argdata_size);
	char **newargv = (char **)(argdata + 8);

	/*
	 * Work backwards through the allocated buffer, copying in the strings one-
	 * by-one 
	 */
	unsigned int pos = argdata_size;
	for (argno = 0; argno < argc; argno++) {
		unsigned int nbytes = strlen(argv[argno]) + 1;
		pos -= nbytes;
		memmove(&argdata[pos], argv[argno], nbytes);
		newargv[argno] =
		    (char *)(PROCESS_STACK_BASE - argdata_size + pos);
	}

	/*
	 * Set argc and argv as the top two words on the stack. These are the values
	 * that main will see passed in as its parameters. 
	 */
	*(unsigned int *)(argdata + 0) = argc;
	*(unsigned int *)(argdata + 4) = PROCESS_STACK_BASE - argdata_size + 8;

	/*
	 * Unmap the existing text segment 
	 */
	disable_paging();
	unsigned int addr;
	for (addr = proc->text_start; addr < proc->text_end; addr += PAGE_SIZE)
		unmap_and_free_page(proc->pdir, addr);
	for (addr = proc->data_start; addr < proc->data_end; addr += PAGE_SIZE)
		unmap_and_free_page(proc->pdir, addr);

	/*
	 * Resize text and data segments to 0 bytes each 
	 */
	proc->text_start = PROCESS_TEXT_BASE;
	proc->text_end = PROCESS_TEXT_BASE;
	proc->data_start = PROCESS_DATA_BASE;
	proc->data_end = PROCESS_DATA_BASE;

	/*
	 * Load in the text segment from the executable file 
	 */
	char *data = filesystem + entry->location;
	for (pos = 0; pos < entry->size; pos += PAGE_SIZE) {
		proc->text_end = proc->text_start + pos;
		void *page = alloc_page();
		if (PAGE_SIZE <= entry->size - pos)
			memmove(page, &data[pos], PAGE_SIZE);
		else
			memmove(page, &data[pos], entry->size - pos);
		map_page(proc->pdir, proc->text_end, (unsigned int)page,
			 PAGE_USER, PAGE_READ_WRITE);
	}
	proc->text_end = proc->text_start + pos;
	enable_paging(current_process->pdir);

	/*
	 * Copy the command line argument data we set up above to the process's
	 * stack 
	 */
	memmove((void *)(PROCESS_STACK_BASE - argdata_size), argdata,
		argdata_size);
	kfree(argdata);

	/*
	 * Set up the process's saved register state so that when it resumes
	 * execution, it will start from the beginning of the loaded code. 
	 */
	init_regs(r, PROCESS_STACK_BASE - argdata_size,
		  (void *)current_process->text_start);

	return 0;
}