示例#1
0
/* --------------------------------
 *	PQfnumber - Return the field index of a given
 *		    field name within a tuple. 
 * --------------------------------
 */
int
PQfnumber(PortalBuffer *portal, int tuple_index, char *field_name)
{
    GroupBuffer *gbp;
    
    if (!valid_pointer("PQfnumber: invalid portal pointer", portal) ||
	!valid_pointer("PQfnumber: invalid field name pointer", field_name) ||
	!in_range("PQfnumber: tuple index",
		  tuple_index, 0, portal->no_tuples))
	return(-1);
    gbp = PQgroup(portal, tuple_index);
    if (gbp)
	return(pbuf_findFnumber(gbp, field_name));
    return(-1);
}
示例#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;
}
示例#3
0
char *syscall_getcwd(char *buf, size_t size)
{
	if (!valid_pointer(buf, size))
		return NULL;
	snprintf(buf, size, "%s", current_process->cwd);
	return buf;
}
示例#4
0
/* ----------------
 *	PQclear		- free storage claimed by named portal
 * ----------------
 */
void
PQclear(char *pname)
{    
    if (!valid_pointer("PQclear: invalid portal name pointer", pname))
	return;
    pbuf_close(pname);
}
示例#5
0
int syscall_getdent(int fd, struct dirent *entry)
{
	if (!valid_pointer(entry, sizeof(struct dirent)))
		return -EFAULT;

	if ((0 > fd) || (MAX_FDS <= fd)
	    || (NULL == current_process->filedesc[fd]))
		return -EBADF;

	filehandle *fh = current_process->filedesc[fd];
	if (FH_DIR == fh->type) {
		directory *dir =
		    (directory *) (filesystem + fh->entry->location);
		if (fh->entryno >= dir->count)
			return 0;
		entry->d_ino = 0;
		snprintf(entry->d_name, NAME_MAX + 1,
			 dir->entries[fh->entryno].name);
		fh->entryno++;
		return 1;
	} else {
		return -ENOTDIR;
	}
	return 0;
}
示例#6
0
/* --------------------------------
 *	PQfnumberGroup - Return the field number (index) given
 *			 the group index and the field name
 * --------------------------------
 */
int
PQfnumberGroup(PortalBuffer *portal, int group_index, char *field_name)
{
    GroupBuffer *gbp;
    
    if (!valid_pointer("PQfnumberGroup: invalid portal pointer", portal) ||
	!valid_pointer("PQfnumberGroup: invalid field name pointer",
		       field_name) ||
	!in_range("PQfnumberGroup: group index",
		  group_index, 0, portal->no_groups))
	return(-1);
    gbp = pbuf_findGroup(portal, group_index);
    if (gbp)
	return(pbuf_findFnumber(gbp, field_name));
    return(-1);
}
示例#7
0
/* --------------------------------
 *	PQntuples - Return the number of tuples in a portal buffer
 * --------------------------------
 */
int
PQntuples(PortalBuffer *portal)
{
    if (!valid_pointer("PQntuples: invalid portal pointer", portal))
	return(-1);
    
    return(portal->no_tuples);
}
示例#8
0
/* --------------------------------
 *	PQngroups - Return the number of tuple groups in a portal buffer
 * --------------------------------
 */
int
PQngroups(PortalBuffer *portal)
{
    if (!valid_pointer("PQngroups: invalid portal pointer", portal))
	return(-1);
    
    return(portal->no_groups);
}
示例#9
0
/* --------------------------------
 *	PQrulep - Return 1 if an asynchronous portal
 * --------------------------------
 */
int
PQrulep(PortalBuffer *portal)
{
    if (!valid_pointer("PQrulep: invalid portal pointer", portal))
	return(-1);
    
    return(portal->rule_p);
}
示例#10
0
/* --------------------------------
 *	PQparray - Return the portal buffer given a portal name
 * --------------------------------
 */
PortalBuffer *
PQparray(char *pname)
{
    int i;
    
    if (!valid_pointer("PQparray: invalid name buffer", pname))
	return NULL;
    
    if ((i = pbuf_getIndex(pname)) < 0)
	return((PortalBuffer *) NULL);
    return(portals[i]->portal);
}
示例#11
0
文件: pipe.c 项目: anta40/rhythmos
/*
 * syscall_pipe
 * 
 * Implements the pipe system call. This creates a pipe, as well as two file
 * handles. The first file handle can be used for reading from the pipe, and the
 * second for writing to it. Both handles are then associated with file descriptors
 * in the current process's file descriptor table.
 * 
 * The most common use of this function is when a process is about to fork. A pipe
 * is created to allow the parent and child process to communicate. When the fork
 * occurs, the child inherits references to the pipe, and both sides release either
 * the reading or writing file descriptor, depending on the direction in which the
 * data is to flow. The pipe can then be used to transfer data from the parent to
 * the child, or vice-versa.
 */
int syscall_pipe(int filedes[2])
{
	/*
	 * Ensure the supplied array is within the process's address space 
	 */
	if (!valid_pointer(filedes, 2 * sizeof(int)))
		return -EFAULT;

	/*
	 * Find two unused file descriptors 
	 */
	int readfd = -1;
	int writefd = -1;
	int i;
	for (i = 0; (i < MAX_FDS) && (-1 == writefd); i++) {
		if (NULL == current_process->filedesc[i]) {
			if (-1 == readfd)
				readfd = i;
			else if (-1 == writefd)
				writefd = i;
		}
	}

	/*
	 * If we were unable to allocate the file descriptors, the call cannot
	 * complete successfully. Return an error to the process indicating that there
	 * aren't enough file descriptors available. 
	 */
	if ((-1 == readfd) || (-1 == writefd))
		return -EMFILE;

	/*
	 * Create a new pipe 
	 */
	pipe_buffer *b = new_pipe();

	/*
	 * Create the file handles and place references to them in the process's
	 * file descriptor table 
	 */
	current_process->filedesc[readfd] = new_pipe_reader(b);
	current_process->filedesc[writefd] = new_pipe_writer(b);

	/*
	 * Store the file descriptors in the output array, so the process knows which
	 * ones to use for reading and writing to the pipe 
	 */
	filedes[0] = readfd;
	filedes[1] = writefd;

	return 0;
}
示例#12
0
static TupleBlock *
PQGetTupleBlock(PortalBuffer *portal,
		int tuple_index,
		int *tuple_offset)
{
    GroupBuffer *gbp;
    TupleBlock  *tbp;
    int tuple_count = 0;
    
    if (!valid_pointer("PQGetTupleBlock: invalid portal pointer", portal) ||
	!valid_pointer("PQGetTupleBlock: invalid offset pointer",
		       tuple_offset) ||
	!in_range("PQGetTupleBlock: tuple index",
		  tuple_index, 0, portal->no_tuples))
	return((TupleBlock *) NULL);
    
    for (gbp = portal->groups;
	 gbp && tuple_index >= (tuple_count += gbp->no_tuples);
	 gbp = gbp->next)
	;
    if (!gbp ||
	!in_range("PQGetTupleBlock: tuple not found: tuple index",
		  tuple_index, 0, tuple_count))
	return((TupleBlock *) NULL);
    tuple_count -= gbp->no_tuples;
    for (tbp = gbp->tuples;
	 tbp && tuple_index >= (tuple_count += TupleBlockSize);
	 tbp = tbp->next)
	;
    if (!tbp ||
	!in_range("PQGetTupleBlock: tuple not found: tuple index",
		  tuple_index, 0, tuple_count))
	return((TupleBlock *) NULL);
    tuple_count -= TupleBlockSize;
    
    *tuple_offset = tuple_index - tuple_count;
    return(tbp);
}
示例#13
0
/* --------------------------------
 *	PQnfields - Return the number of fields in a tuple
 * --------------------------------
 */
int
PQnfields(PortalBuffer *portal, int	tuple_index)
{
    GroupBuffer *gbp;
    
    if (!valid_pointer("PQnfields: invalid portal pointer", portal) ||
	!in_range("PQnfields: tuple index",
		  tuple_index, 0, portal->no_tuples))
	return(-1);
    gbp = PQgroup(portal, tuple_index);
    if (gbp)
	return(gbp->no_fields);
    return(-1);
}
示例#14
0
/* --------------------------------
 *	PQnfieldsGroup - Return the number of fields in a tuple group
 * --------------------------------
 */
int
PQnfieldsGroup(PortalBuffer *portal, int group_index)
{
    GroupBuffer *gbp;
    
    if (!valid_pointer("PQnfieldsGroup: invalid portal pointer", portal) ||
	!in_range("PQnfieldsGroup: group index",
		  group_index, 0, portal->no_groups))
	return(-1);
    gbp = pbuf_findGroup(portal, group_index);
    if (gbp)
	return(gbp->no_fields);
    return(-1);
}
示例#15
0
/* --------------------------------
 *	PQfsize - Return the size of a field
 * --------------------------------
 */
int
PQfsize(PortalBuffer *portal, int tuple_index, int field_number)
{
    GroupBuffer *gbp;
    
    if (!valid_pointer("PQfsize: invalid portal pointer", portal) ||
	!in_range("PQfsize: tuple index",
		  tuple_index, 0, portal->no_tuples))
	return(-1);
    
    if ((gbp = PQgroup(portal, tuple_index)) &&
	in_range("PQfsize: field number", field_number, 0, gbp->no_fields))
	return(gbp->types[field_number].adtsize);
    return(-1);
}
示例#16
0
/* --------------------------------
 *	PQfsizeGroup - Return the size of a field given
 *                     the group index and field index
 * --------------------------------
 */
int
PQfsizeGroup(PortalBuffer *portal, int group_index, int field_number)
{
    GroupBuffer *gbp;
    
    if (!valid_pointer("PQfsizeGroup: invalid portal pointer", portal) ||
	!in_range("PQfsizeGroup: tuple index",
		  group_index, 0, portal->no_groups))
	return(-1);
    
    if ((gbp = pbuf_findGroup(portal, group_index)) &&
	in_range("PQfsizeGroup: field number", field_number, 0, gbp->no_fields))
	return(gbp->types[field_number].adtsize);
    return(-1);
}
示例#17
0
/* --------------------------------
 *	PQfnameGroup - Return the field (attribute) name given
 *			the group index and field index. 
 * --------------------------------
 */
char *
PQfnameGroup(PortalBuffer *portal, int group_index, int field_number)
{
    GroupBuffer *gbp;
    
    if (!valid_pointer("PQfnameGroup: invalid portal pointer", portal) ||
	!in_range("PQfnameGroup: group index",
		  group_index, 0, portal->no_groups))
	return((char *) NULL);
    
    if ((gbp = pbuf_findGroup(portal, group_index)) &&
	in_range("PQfnameGroup: field number",
		 field_number, 0, gbp->no_fields))
	return(pbuf_findFname(gbp, field_number));
    return((char *) NULL);
}
示例#18
0
/* --------------------------------
 *	PQfname - Return the name of a field
 * --------------------------------
 */
char *
PQfname(PortalBuffer *portal, int	tuple_index, int field_number)
{
    GroupBuffer *gbp;
    
    if (!valid_pointer("PQfname: invalid portal pointer", portal) ||
	!in_range("PQfname: tuple index",
		  tuple_index, 0, portal->no_tuples))
	return((char *) NULL);
    
    if ((gbp = PQgroup(portal, tuple_index)) &&
	in_range("PQfname: field number",
		 field_number, 0, gbp->no_fields))
	return(pbuf_findFname(gbp, field_number));
    return((char *) NULL);
}
示例#19
0
/* --------------------------------
 *	PQpnames - Return all the portal names
 * 	If rule_p, only return asynchronous portals. 
 *
 *         the caller must have allocated sufficient memory for char** pnames
 *	   (an array of PQnportals strings of length PortalNameLength).
 *
 *	   notice that this assumes that the user is calling PQnportals and
 *	   PQpnames with the same rule_p argument, and with no intervening
 *	   portal closures.  if not, you can get in heap big trouble..
 * --------------------------------
 */
void
PQpnames(char **pnames, int rule_p)
{
    int i, cur_pname = 0;
    
    if (!valid_pointer("PQpnames: invalid name buffer", pnames))
	return;
    
    for (i = 0; i < portals_array_size; ++i) {
	if (portals[i] && portals[i]->portal) {
	    if (!rule_p || portals[i]->portal->rule_p) {
		(void) strncpy(pnames[cur_pname], portals[i]->name, PortalNameLength);
		++cur_pname;
	    }
	}
    }
}
示例#20
0
/* --------------------------------
 *	PQsametype - Return 1 if the two tuples have the same type
 *			(in the same group)
 * --------------------------------
 */
int
PQsametype(PortalBuffer *portal, int tuple_index1, int tuple_index2)
{
    GroupBuffer *gbp1, *gbp2;
    
    if (!valid_pointer("PQsametype: invalid portal pointer", portal) ||
	!in_range("PQsametype: tuple index 1",
		  tuple_index1, 0, portal->no_tuples) ||
	!in_range("PQsametype: tuple index 2",
		  tuple_index2, 0, portal->no_tuples))
	return(-1);
    
    gbp1 = PQgroup(portal, tuple_index1);
    gbp2 = PQgroup(portal, tuple_index2);
    if (gbp1 && gbp2)
	return(gbp1 == gbp2);
    return(-1);
}
示例#21
0
/* --------------------------------
 *	PQgetgroup - Return the index of the group that a
 *		     particular tuple is in
 * --------------------------------
 */
int
PQgetgroup(PortalBuffer *portal, int tuple_index)
{
    GroupBuffer *gbp;
    int tuple_count = 0, group_count = 0;
    
    if (!valid_pointer("PQgetgroup: invalid portal pointer", portal) ||
	!in_range("PQgetgroup: tuple index",
		  tuple_index, 0, portal->no_tuples))
	return(-1);
    
    for (gbp = portal->groups;
	 gbp && tuple_index >= (tuple_count += gbp->no_tuples);
	 gbp = gbp->next)
	++group_count;
    if (!gbp || !in_range("PQgetgroup: tuple not found: tuple index",
			  tuple_index, 0, tuple_count))
	return(-1);
    return(group_count);
}
示例#22
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;
}