/*! Remove a file */ bool remove(const char *f_name) { struct dir* cur_dir; char name[15]; /* Checks the validity of the given pointer */ //printf("going to remove file %s\n\n", f_name); if (!checkva(f_name)) exit(-1); if (!decompose_dir(f_name, name, &cur_dir)) return false; if (strcmp(".", name) == 0 || strcmp("..", name) == 0) return false; lock_acquire(&filesys_lock); /* Remove the file, while locking the file system. */ bool flag = filesys_dir_remove(name, cur_dir); //printf("name decomposed! %x\n\n", cur_dir); dir_close(cur_dir); lock_release(&filesys_lock); return flag; }
/*! Read from file */ int read(uint32_t fd, void *buffer, unsigned size) { uint8_t* addr_e; struct supp_table* st; /* Check the validity of given pointer */ if ((!checkva(buffer)) || (!checkva(buffer + size))){ exit(-1); } for (addr_e = (uint8_t*) pg_round_down(buffer); addr_e < (uint8_t*) buffer + size; addr_e += PGSIZE){ st = find_supp_table(addr_e); if (st && !st->writable) exit(-1); } int read_size = 0; if (fd == STDIN_FILENO) { /* If std-in, then read using input_getc() */ unsigned i; for (i = 0; i < size; i++){ *((uint8_t*) buffer) = input_getc(); ++ read_size; ++ buffer; } } else { /* Otherwise, first find the file of this fd. */ struct f_info* f = findfile(fd); /* We should read a dir like a file. */ if (f->isdir) exit(-1); struct file* fin = f->f; off_t pos = f->pos; /* Read from the file at f->pos */ //lock_acquire(&filesys_lock); read_size = (int) file_read_at(fin, buffer, (off_t) size, pos); f->pos += (off_t) read_size; //lock_release(&filesys_lock); } return read_size; }
// Copy data to/from user space, // using checkva() above to validate the address range // and using sysrecover() to recover from any traps during the copy. void usercopy(trapframe *utf, bool copyout, void *kva, uint32_t uva, size_t size) { checkva(utf, uva, size); cpu *c = cpu_cur(); c->recover = sysrecover; if(copyout) memmove((void*)uva, kva, size); else memmove(kva, (void*)uva, size); c->recover = NULL; }
/*! Write to file. */ int write(uint32_t fd, const void *buffer, unsigned size) { uint8_t* addr_e; struct supp_table *st; /* Check the validity of given pointer */ if ((!checkva(buffer)) || (!checkva(buffer + size))) exit(-1); /* Checking we are not writing to unwritable pages. */ int write_size = 0; if (fd == STDOUT_FILENO) { /* If std-out, then write using putbuf() */ putbuf(buffer, size); write_size = size; } else { /* Otherwise, first find the file of this fd. */ struct f_info* f = findfile(fd); /* We should write to a directory just like a file. */ if (f->isdir) exit(-1); struct file* fout = f->f; off_t pos = f->pos; /* Write to the file at f->pos */ //lock_acquire(&filesys_lock); write_size = (int) file_write_at(fout, buffer, (off_t) size, pos); f->pos += (off_t) write_size; //lock_release(&filesys_lock); } return write_size; }
/*! Reads a directory entry from file descriptor fd. If successful, stores, * the null-terminated file name in name. If no entries are left in * directory, returns false. */ bool _readdir(uint32_t fd, char* name){ /* Check for the validity of the pointer. */ if (!checkva(name)) return false; /* Get the f_info struct of this fd*/ struct f_info* f = findfile(fd); /*Check that we are opening a directory. */ if (!f->isdir) return false; /* Use the defined dir_readir to finish the function. */ return dir_readdir(f->d, name); }
/*! Create a file */ bool create(const char *f_name, unsigned initial_size) { struct dir* cur_dir; char name[15]; /* Checks the validity of the given pointer */ if (!checkva(f_name) || !(*f_name)) exit(-1); if (!decompose_dir(f_name, name, &cur_dir)){ return false; } lock_acquire(&filesys_lock); /* Create the file, while locking the file system. */ bool flag = filesys_dir_create(name, (off_t) initial_size, cur_dir); dir_close(cur_dir); lock_release(&filesys_lock); return flag; }
/*! Creates the directory named dir. Return true if successful, but false * if dir already exists or if any directory name in dir, besides the last * one does not exist. */ bool _mkdir(const char* dir) { /* Inode for the new directory created. */ struct inode* next_inode; /* Parent directory. */ struct dir* cur_dir; /* Name of the directory. */ char name[15]; /* Sector number allocated to the new directory. */ block_sector_t sector; /* Check the validity of the pointer*/ if (!checkva(dir)) exit(-1); /* The compose the path to a final dir name and its parent directory. */ if (!decompose_dir(dir, name, &cur_dir)){ return false; } ASSERT(cur_dir != NULL); /* Allocate a new sector for this new directory; * Create a new directory */ if (!free_map_allocate(1, §or) || !dir_create(sector, 0, dir_get_inode(cur_dir)->sector)){ dir_close(cur_dir); return false; } /* Add the new directory to its parent directory. */ if (!dir_add(cur_dir, name, sector)){ free_map_release(sector, 1); dir_close(cur_dir); return false; } dir_close(cur_dir); return true; }
/*! Changes the working directory of the current process (i.e. * thread->cur_dir). Returns true if the operation is successfull * and false otherwise. */ bool _chdir(const char* dir){ /* The current process*/ struct thread* t = thread_current(); /* inode for the new directory*/ struct inode* next_inode; /* new directory struct*/ struct dir* cur_dir; /* name of the directory*/ char name[15]; /* Check validity of the pointer*/ if (!checkva(dir)){ exit(-1); } /* Decompose the path to a final name and parent directory. */ if (!decompose_dir(dir, name, &cur_dir)) return false; if (strcmp(name, "\0") != 0){ /* If name is not empty, then we simply look for the name * under the parent directory cur_dir, and get the inode * of this destination directory. */ if (!dir_lookup(cur_dir, name, &next_inode)) { dir_close(cur_dir); return false; } /* Close the parent directory, as we do not need it any more. */ dir_close(cur_dir); /* Check that the inode we are opening is a directory. */ if (next_inode->data.type != DIR_INODE_DISK) { inode_close(next_inode); return false; } /* Open up the inode to directory struct*/ cur_dir = dir_open(next_inode); if (cur_dir == NULL) { inode_close(next_inode); return false; } } else if (dir[strlen(dir)] != '/'){ /* If the name is not empty, and the give path does not end with "/" * then this path is an invalid directory path. * Note if the path is in fact valid and the name we get is empty, * then the distiniation directory has been already opened in * cur_dir. */ dir_close(cur_dir); return false; } /* Update the current process's working directory */ dir_close(t->cur_dir); t->cur_dir = dir_reopen(cur_dir); dir_close(cur_dir); return true; }
/*! Memory map from file to user address. */ mapid_t mmap(uint32_t fd, void* addr){ int f_size; void* addr_e; mapid_t mapid; uint32_t read_bytes, zero_bytes; uint8_t *upage; off_t ofs; struct file* file; struct f_info* f; struct mmap_elem* me; struct supp_table* st; struct thread* t = thread_current(); if (!checkva(addr)) return MAP_FAIL; /* Check for the invalid conditions: * fd is standard io; file size of the given fd is 0; give user address * is not valie; given address is not page aligned; given address is 0. * If invalid, then return MAP_FAIL. */ if (fd == STDIN_FILENO || fd == STDOUT_FILENO || filesize(fd) == 0 || pg_ofs(addr) != 0 || addr == 0) { return MAP_FAIL; } /* Get the file size of the file. And check the entire range of the * to-be-mapped user address does not overlap with any already allocated * pages. */ f_size = filesize(fd); for (addr_e = addr; addr_e < addr + f_size; addr_e += PGSIZE){ if (find_supp_table(addr_e) != NULL){ /* If found a supplemental page entry of this page address, * Then this is already alocated. Return MAP_FAIL. */ return MAP_FAIL; } } /* Increment the thread's max mmapid to give this mmapping a unque ID. */ ++ t->mmapid_max; mapid = t->mmapid_max; /* Allocated the new mmap struct */ me = (struct mmap_elem*) malloc(sizeof(struct mmap_elem)); if (me == NULL) return MAP_FAIL; /* Reopen the file according to the file descriptor. */ f = findfile(fd); if (f->isdir) return MAP_FAIL; lock_acquire(&filesys_lock); file = file_reopen(f->f); lock_release(&filesys_lock); /* If the file is NULL, then free the struct and return MAP_FAIL. */ if (file == NULL){ free(me); return MAP_FAIL; } /* Setup the fields of the mmap struct.*/ me->file = file; me->mapid = mapid; /* Push the mmap struct to the list of mmap of this process. */ list_push_back(&(t->mmap_lst), &(me->elem)); list_init(&(me->s_table)); /* Allocate pages for the read-in file data.*/ upage = addr; ofs = 0; read_bytes = f_size; if (read_bytes >= PGSIZE) zero_bytes = 0; else zero_bytes = PGSIZE - read_bytes; while (read_bytes > 0) { /* Calculate how to fill this page. We will read PAGE_READ_BYTES bytes from FILE and zero the final PAGE_ZERO_BYTES bytes. */ size_t page_read_bytes = read_bytes < PGSIZE ? read_bytes : PGSIZE; size_t page_zero_bytes = PGSIZE - page_read_bytes; /* Create a new supplemental page entry for this page*/ st = create_mmap_supp_table(file, ofs, upage, page_read_bytes, page_zero_bytes, true); /* Push the page entry to the mmap struct's list */ list_push_back(&(me->s_table), &(st->map_elem)); /* Update the remaining read_bytes, zero_bytes; * Update upage, and ofs. This is for the next page to load the file.*/ read_bytes -= page_read_bytes; zero_bytes -= page_zero_bytes; upage += PGSIZE; ofs += page_read_bytes; } return mapid; }
/*! Open a file or an directory */ int open(const char *f_name) { /* The parent directory of the opening file or directory. */ struct dir* cur_dir; /* Name of the file or the directory. */ char name[15]; /* CUrrent thread. */ struct thread *t; /* file info struct for creating fd to this thread. */ struct f_info *f; /* dir struct or file struct depending what we are opening */ struct dir* d_open; struct file* f_open; /* The flag for whether we are opening a directory. */ bool isdir; /* fd number assigned to this file / directory */ uint32_t fd; /* Inode of the file / dir we are opening. */ struct inode* inode; /* Checks the validity of the given pointer */ if (!checkva(f_name) || f_name[0] == '\0'){ return -1; } /* Decomposes a path to the final file / dir name * and its corresponding parent dir. */ if (!decompose_dir(f_name, name, &cur_dir)){ return -1; } /* Open the file when locking the file system. */ lock_acquire(&filesys_lock); if (strcmp(name, "\0") != 0){ /* If file / dir name is not empty, then look for it in its parent * directory. */ if (!dir_lookup(cur_dir, name, &inode)){ lock_release(&filesys_lock); return -1; } /* Decide whether the inode is a directory or a file. */ isdir = (inode->data.type == DIR_INODE_DISK); /* Open the file / dir */ if (isdir) d_open = dir_open(inode); else f_open = file_open(inode); lock_release(&filesys_lock); } else { /* Since we decomposed the entire path to a diretory * then we must be opening a directory. */ isdir = true; /* Reopen the directory, to store in f_info */ d_open = dir_reopen(cur_dir); } if (f_open == NULL && dir_open == NULL) { inode_close(inode); /* If file open failed, then exit with error. */ return -1; } else { /* Assign fd to the file / dir */ t = thread_current(); if (t->f_count > 127){ if (isdir){ dir_close(d_open); } else { file_close(f_open); } return -1; } /* Set up new f_info */ f = (struct f_info*) malloc(sizeof(struct f_info)); f->isdir = isdir; if (isdir) f->d = d_open; else f->f = f_open; f->pos = 0; /* Update the process's fd info */ lock_acquire(&filesys_lock); fd = (++(t->fd_max)); f->fd = fd; /* Push f_info to the thread's list, * and update thread's list count. */ list_push_back(&(t->f_lst), &(f->elem)); ++(t->f_count); lock_release(&filesys_lock); } return fd; }
/*! execute a command-line */ pid_t exec(const char *cmd_line) { if (checkva(cmd_line)) return process_execute(cmd_line); exit(-1); }
/*! Reads for bytes from the stack according to the offset. */ static uint32_t read4(struct intr_frame * f, int offset) { if (!checkva(f->esp + offset)) exit(-1); return *((uint32_t *) (f->esp + offset)); }