/* Traverse -- if thread is non-NULL, update the path of the thread */ block_sector_t path_traverse (char *path, struct thread *t) { char *token, *save_ptr; bool found; struct dir dir; struct dir_entry entry; block_sector_t sector; if (path == NULL) return thread_get_cwd (); /* Check if absolute path */ if (path[0] == '/') { sector = free_map_root_sector (); path++; if (t != NULL) thread_clear_dirs (t); } else { sector = thread_get_cwd (); } for (token = strtok_r (path, "/", &save_ptr); token != NULL; token = strtok_r (NULL, "/", &save_ptr)) { /* Open the inode for this directory */ dir.inode = inode_open (sector); dir.pos = 0; if (dir.inode == NULL || !inode_is_directory (dir.inode)) { sector = INODE_INVALID_BLOCK_SECTOR; inode_close (dir.inode); break; } /* Make the thread leave the directory if applicable */ if (t != NULL) thread_leave_dir (t, dir.inode); /* Look up in current directory */ found = lookup (&dir, token, &entry, NULL); if (found) { sector = entry.inode_sector; /* Make thread enter the directory if applicable */ if (t != NULL) thread_enter_dir (t, dir.inode); inode_close (dir.inode); } else { sector = INODE_INVALID_BLOCK_SECTOR; inode_close (dir.inode); break; } } return sector; }
/* Deletes NAME from DIR. Returns true if successful, false on failure, which occurs only if there is no file with the given NAME. */ bool dir_remove (struct dir *dir, const char *name) { struct dir_entry e; struct inode *inode = NULL; bool success = false; off_t ofs; ASSERT (dir != NULL); ASSERT (name != NULL); lock_acquire (&dir->l); /* Find directory entry. */ if (!lookup (dir, name, &e, &ofs)) goto done; /* Open inode. */ inode = inode_open (e.inode_sector); if (inode == NULL) goto done; /* If directory, make sure it's empty */ if (inode_is_directory (inode)) { struct dir *inner = dir_open (inode_open (e.inode_sector)); int size = dir_size (inner); dir_close (inner); if (size != 0) goto done; } /* Erase directory entry. */ e.in_use = false; if (inode_write_at (dir->inode, &e, sizeof e, ofs) != sizeof e) goto done; /* Remove inode. */ success = inode_remove (inode); done: lock_release (&dir->l); inode_close (inode); return success; }
/* Opens a file for the given INODE, of which it takes ownership, and returns the new file. Returns a null pointer if an allocation fails or if INODE is null. */ struct file * file_open (struct inode *inode) { struct file *file = calloc (1, sizeof *file); if (inode != NULL && file != NULL) { file->inode = inode; file->pos = 0; if (inode_is_directory (inode)) file->dir = dir_open (file->inode); file->deny_write = false; return file; } else { inode_close (inode); free (file); return NULL; } }
int sys_open(const char* file) { // memory validation check_user((const uint8_t*) file); struct file* file_opened; struct file_desc* fd = palloc_get_page(0); if (!fd) { return -1; } lock_acquire (&filesys_lock); file_opened = filesys_open(file); if (!file_opened) { palloc_free_page (fd); lock_release (&filesys_lock); return -1; } fd->file = file_opened; //file save // directory handling struct inode *inode = file_get_inode(fd->file); if(inode != NULL && inode_is_directory(inode)) { fd->dir = dir_open( inode_reopen(inode) ); } else fd->dir = NULL; struct list* fd_list = &thread_current()->file_descriptors; if (list_empty(fd_list)) { // 0, 1, 2 are reserved for stdin, stdout, stderr fd->id = 3; } else { fd->id = (list_entry(list_back(fd_list), struct file_desc, elem)->id) + 1; } list_push_back(fd_list, &(fd->elem)); lock_release (&filesys_lock); return fd->id; }