static struct dir* filesys_get_dir (const char* path) { struct dir* dir; int len = strlen(path); char *p = (char *)malloc(sizeof(char) * (len + 1)); memcpy(p, path, len); p[len]='\0'; bool openRoot = p[0]=='/' || thread_current ()->cur_dir == NULL; dir = openRoot ? dir_open_root() : dir_reopen(thread_current()->cur_dir); char *save_ptr; char *token = strtok_r(p, "/", &save_ptr); char *next_token = token!=NULL ? strtok_r(NULL, "/", &save_ptr): NULL; struct inode *inode; bool isdir; while (next_token!=NULL){ if (dir_lookup(dir, token, &inode, &isdir) == NULL) return NULL; dir_close(dir); dir = dir_open(inode); if (isdir == false){ dir_close(dir); return NULL; } token = next_token; next_token = strtok_r(NULL, "/", &save_ptr); } return dir; }
static struct dir *get_cwd (const char *name) { struct dir *search_dir = NULL; if (name[0] == '/') { search_dir = dir_open_root(); } else { struct dir *cwd = thread_current()->cwd; if (cwd != NULL) { search_dir = dir_reopen(cwd); } else if (thread_current()->parent_data != NULL && thread_current()->parent_data->cwd != NULL) { search_dir = dir_reopen(thread_current()->parent_data->cwd); } else { search_dir = dir_open_root(); } } return search_dir; }
/* Opens the file with the given NAME. Returns the new file if successful or a null pointer otherwise. Fails if no file named NAME exists, or if an internal memory allocation fails. */ struct file * filesys_open (const char *name) { if (strnlen (name, FULLPATH_MAX_LEN) == 0) return NULL; if (strcmp (".", name) == 0) { block_sector_t cwd = thread_current ()->cwd_sector; struct inode *curr = NULL; curr = inode_open (cwd); struct dir *p; p = dir_open (inode_open (curr->data.parent_dir_sector)); struct dir_entry e; size_t ofs; ASSERT (p != NULL); for (ofs = 0; inode_read_at (p->inode, &e, sizeof e, ofs) == sizeof e; ofs += sizeof e) { if (e.inode_sector == cwd && e.in_use) { return filesys_open (e.name); } } return NULL; } struct inode *crr = NULL; crr = inode_open (thread_current ()->cwd_sector); struct dir *parent_dir = dir_reopen(dir_get_parent_dir (name)); //if (crr->data.is_dir) //parent_dir = dir_open (inode_open (crr->data.parent_dir_sector)); //else if (parent_dir == NULL) return NULL; struct inode *inode = NULL; char leaf_name[NAME_MAX + 1]; if (!dir_get_leaf_name (name, leaf_name) && strnlen(leaf_name, NAME_MAX) == 0) { inode = inode_reopen (dir_get_inode (parent_dir)); dir_close (parent_dir); return file_open (inode); } if (parent_dir != NULL) dir_lookup (parent_dir, leaf_name, &inode); dir_close (parent_dir); return file_open (inode); }
//returns the inode of the last dir in name before the last / //the user has to check for existing file after the / struct dir * dir_lookup_rec (const char *name) { //printf("lookup path is %s\n",name); //if the string starts with / it is an absolut path //root dir if ( strcmp( name, "/") == 0 ) return dir_open_root(); //for the return value int success = 0; char *token ,*save_ptr; char * temp = (char *)malloc(strlen(name) + 1 ); strlcpy (temp, name, strlen(name) + 1); //open root and start struct dir * current; //if it is relative make it absolute if ( name[0] != '/' ) { current = dir_reopen(thread_current()->pwd); } else { current = dir_open_root(); } struct inode * nextdir = dir_get_inode(current); //go through and check that the previous direcrtories exist for (token = strtok_r (temp, "/", &save_ptr); token != NULL; token = strtok_r (NULL, "/", &save_ptr)) { //somethings wrong if this hapens if (current == NULL ) break; //last round has to be not existing if (strlen(save_ptr) == 0) { success = 1; break; } //goto next if token is empty in case of //a/ if(strlen(token) != 0) { //check if this directory exists true if exists if ( dir_lookup (current, token,&nextdir) ) { //check if it is a directory and then open it enum file_type type = inode_type (nextdir); //is it a dir if(type == FILE_DIR) { dir_close(current); current = dir_open(nextdir); } else break; } else break; } } if( success == 1) return current; else return NULL; }
struct dir *get_directory(const char *path, bool flag){ if(strlen(path)==0) return NULL; struct dir *curr; char *word, *brkt, *buffer = malloc(strlen(path)+1), *save, *last; struct inode *inode; memcpy(buffer, path, strlen(path)+1); save = buffer; if(buffer[0]=='/'){ curr = dir_open_root(); last = strtok_r(buffer+1, "/", &brkt); } else{ if(thread_current()->dir) curr = dir_reopen(thread_current()->dir); else curr = dir_open_root(); last = strtok_r(buffer, "/", &brkt); } while(1){ word = last; if(word == NULL) break; last = strtok_r(NULL, "/", &brkt); if(last == NULL && flag) break; if(strcmp(word,"")==0); else if(strcmp(word,".")==0); else if(strcmp(word,"..")==0){ inode = inode_open(inode_parent_number(dir_get_inode(curr))); dir_close(curr); curr = dir_open(inode); } else{ inode = NULL; if(dir_lookup(curr, word, &inode)){ dir_close(curr); if(inode_is_dir(inode)) curr = dir_open(inode); else{ inode_close(inode); free(save); return NULL; } } else{ dir_close(curr); free(save); return NULL; } } } free(save); if(inode_removed(curr->inode)) return NULL; return curr; }
struct dir* get_containing_dir (const char* path) { char s[strlen(path)+1]; memcpy(s, path, strlen(path)+1); char *save_ptr, *next_token = NULL, *token = strtok_r(s, "/", &save_ptr); struct dir* dir; if (s[0] == 47 || !thread_current ()->cwd) { dir = dir_open_root (); } else { dir = dir_reopen (thread_current()->cwd); } if (token) { next_token = strtok_r (NULL, "/", &save_ptr); } while (next_token != NULL) { if (strcmp(token, ".") != 0) { struct inode *inode; if (strcmp(token, "..") == 0) { if (!dir_get_parent (dir, &inode)) { return NULL; } } else { if (!dir_lookup (dir, token, &inode)) { return NULL; } } if (inode_is_dir (inode)) { dir_close (dir); dir = dir_open (inode); } else { inode_close (inode); } } token = next_token; next_token = strtok_r (NULL, "/", &save_ptr); } return dir; }
struct dir * dir_from_path (char *path) { char *save_ptr, *token, *next = NULL; int length = strlen(path) + 1; char dir_path [length]; struct dir *directory; struct thread *cur = thread_current (); struct inode *dir_node; bool success = false; memcpy (dir_path, path, length); token = strtok_r (dir_path, "/", &save_ptr); if (dir_path[0] == SLASH_SYM || cur->dir == NULL) directory = dir_open_root (); else directory = dir_reopen (cur->dir); if (token != NULL) next = strtok_r (NULL, "/", &save_ptr); while (next != NULL) { if (strcmp (token, ".") != 0) { if (strcmp (token, "..") != 0) success = dir_lookup (directory, token, &dir_node); else success = dir_lookup (directory, token, &dir_node); if (success) { if (inode_is_dir(dir_node)) { dir_close (directory); directory = dir_open (dir_node); } } else return NULL; } token = next; next = strtok_r (NULL, "/", &save_ptr); } return directory; }
bool filesys_chdir(const char *name) { bool success=false; struct inode *inode = NULL; struct thread *t = thread_current(); char *file_name = get_file_name(name); struct dir *dir = get_directory(name); // printf("lookup start\n"); if (dir != NULL) { if( strcmp(file_name,".")==0) { t->curr_dir = dir_reopen(dir); free(file_name); return true; } else if(strcmp(file_name,"..")==0) { if( inode_get_inumber(dir_get_inode(dir))==1 ) { t->curr_dir = dir_open(inode_open(1)); free(file_name); dir_close(dir); return true; } else { t->curr_dir = dir_open( inode_open(inode_get_parent(dir_get_inode(dir)))); free(file_name); dir_close(dir); return true; } } success=dir_lookup (dir, file_name, &inode); } dir_close (dir); if(success) { t->curr_dir = dir_open(inode); } free(file_name); /* printf("changed dir sector: %d\n",inode_get_inumber(dir_get_inode(t->curr_dir))); printf("value %d\n",inode_get_data(dir_get_inode(t->curr_dir),0));*/ return success; }
/* Adds a file named NAME to DIR, which must not already contain a file by that name. The file's inode is in sector INODE_SECTOR. Returns true if successful, false on failure. Fails if NAME is invalid (i.e. too long) or a disk or memory error occurs. */ bool dir_add (struct dir *dir, const char *name, block_sector_t inode_sector) { struct dir_entry e; off_t ofs; bool success = false; ASSERT (dir != NULL); ASSERT (name != NULL); /* Check NAME for validity. */ if (*name == '\0' || strlen (name) > NAME_MAX) return false; /* Check that NAME is not in use. */ if (lookup (dir, name, NULL, NULL)) goto done; struct inode* inode = inode_open(inode_sector); inode->up_dir = dir_reopen(dir); inode_close(inode); /* Set OFS to offset of free slot. If there are no free slots, then it will be set to the current end-of-file. inode_read_at() will only return a short read at end of file. Otherwise, we'd need to verify that we didn't get a short read due to something intermittent such as low memory. */ for (ofs = 0; inode_read_at (dir->inode, &e, sizeof e, ofs) == sizeof e; ofs += sizeof e) if (!e.in_use) break; /* Write slot. */ e.in_use = true; strlcpy (e.name, name, sizeof e.name); e.inode_sector = inode_sector; success = inode_write_at (dir->inode, &e, sizeof e, ofs) == sizeof e; done: return success; }
/* parsing the path, and return working directory */ struct dir* parse_path(char *path_name, char *file_name) { struct dir *dir; char *token, *next_token, *save_ptr; struct inode *inode; if(path_name == NULL || file_name == NULL) return NULL; if(strlen(path_name) == 0) return NULL; /* if path name is absulute path */ if(path_name[0] == '/') dir = dir_open_root(); else /* path name is relative path */ dir = dir_reopen(thread_current()->thread_dir); token = strtok_r(path_name, "/", &save_ptr); next_token = strtok_r(NULL, "/", &save_ptr); while(token != NULL && next_token != NULL) { /* find file named token in dir directory */ if(dir_lookup(dir, token, &inode) == false) { return NULL; } /* if token is not a directory */ if(inode_is_dir(inode) == false){ dir_close(dir); return NULL; } /* close dir */ dir_close(dir); /* set dir */ dir = dir_open(inode); /* advance */ token = next_token; next_token = strtok_r(NULL, "/", &save_ptr); } /* copy token to file_name */ strlcpy(file_name, token, strlen(token)+1); return dir; }
/* Deletes the file named NAME. Returns true if successful, false on failure. Fails if no file named NAME exists, or if an internal memory allocation fails. */ bool filesys_remove (const char *name) { bool success = false; struct inode *inode = NULL; struct dir *search_dir = get_cwd(name); struct dir *parent_dir = NULL; if (search_dir == NULL) { return false; } parent_dir = dir_reopen(search_dir); char *part = malloc(NAME_MAX + 1); if (part == NULL) { return false; } memset(part, 0, NAME_MAX + 1); int retrieved_next_part; for (retrieved_next_part = get_next_part(part, &name); retrieved_next_part > 0; retrieved_next_part = get_next_part(part, &name)) { if (dir_lookup (search_dir, part, &inode)) { dir_close(parent_dir); parent_dir = dir_reopen(search_dir); if (parent_dir == NULL) { dir_close(search_dir); free(part); return false; } if (!inode_is_dir(inode)) { break; } else { dir_close(search_dir); search_dir = dir_open(inode); if (search_dir == NULL) { dir_close(parent_dir); free(part); return false; } } } else { inode = NULL; break; } } if (inode == NULL || get_next_part(part, &name) != 0) { if (inode != NULL && !inode_is_dir(inode)) { inode_close(inode); } dir_close(parent_dir); dir_close(search_dir); free(part); return false; } if (parent_dir == NULL || search_dir == NULL) { dir_close(search_dir); dir_close(parent_dir); free(part); return false; } if (inode_is_dir(inode)) { char buffer[NAME_MAX + 1]; if (inode_is_open(inode) || dir_readdir(search_dir, buffer)) { success = false; } else { inode_close(inode); success = dir_remove (parent_dir, part); } } else { inode_close(inode); success = dir_remove(parent_dir, part); } dir_close(search_dir); dir_close(parent_dir); free(part); return success; }
static struct dir *get_directory(char *path) { char s[1024]; memcpy(s,path,strlen(path)+1); char *token, *save_ptr,*prev_token="", *next_token="";//,*save,*real; token = strtok_r(s,"/",&save_ptr); // real = strtok_r(token,"/",&save); struct dir *start; struct inode *inode; if( s[0]=='/' || !thread_current()->curr_dir ) { // printf("when create a/b\n"); start = dir_open_root(); } else { // printf("come on\n"); if( inode_is_removed(dir_get_inode(thread_current()->curr_dir))) return NULL; else start = dir_reopen(thread_current()->curr_dir); } /* if( strcmp(token,"." )==0) { } else if( strcmp(token,"..") == 0) { if( thread_current()->curr_dir) start = dir_get_parent(thread_current()->curr_dir); else start = dir_open_root(); } else { printf("here\n"); if(thread_current()->curr_dir) { // printf("also here\n"); start = dir_reopen(thread_current()->curr_dir); } else { // printf("when create a/b\n"); start = dir_open_root(); } }*/ // printf("first setting\n"); // real = strtok_r(token,"/",&save); // printf("token %s s %s\n",token,s); if(token) { next_token = strtok_r(NULL,"/",&save_ptr); /* if(next_token == NULL) printf("AAAA\n"); else printf("%s\n",next_token);*/ // printf("first %s second %s\n",token,next_token); } while( next_token!=NULL) { // printf("but not here\n"); if( strcmp(token,"." )==0) { continue; } else if( strcmp(token,"..") == 0) { if(inode_get_inumber(dir_get_inode(start))!=1) { start=dir_get_parent(start); } } else { if(dir_lookup(start ,token, &inode)) { // printf("when create a/b token:%s\n",token); // printf("aaaa\n"); dir_close(start); start = dir_open(inode); } else return NULL; // dir_close(start); /* if( inode==NULL ) { return NULL; } else if(inode_is_removed(inode)) return NULL;*/ // start = dir_open(inode); } prev_token = token; token = next_token; next_token = strtok_r(NULL,"/",&save_ptr); // printf("first %s second %s\n",token,next_token); } // printf("directory name : %s \n",token); return start; }
/* Decomposes the given path (dir) to a final file or directory name and * its parent directory. Write the name to ret_name, and the parent directory * struct to par_dir. Returns true if the decomposition is successfull, i.e. * successfully decomposed the final name, and open all the directories in * path successfully. */ bool decompose_dir(const char* dir, char* ret_name, struct dir** par_dir){ /* parent directory*/ struct dir* cur_dir; /* inode for iteration*/ struct inode* next_inode; /* iterator for the path string*/ unsigned i; /* Current process*/ struct thread* t = thread_current(); /* Final name of the file or the directory*/ char name[15]; /* Check that give path is not empty*/ if (*dir == NULL || dir[0] == '\0') return false; if (dir[0] == '/') { /* If give an absolute path, then first set cur_dir as root. */ cur_dir = dir_open_root(); } else if (t->cur_dir == NULL) { /* Given path is relative. However, as the process's cur_dir is * NULL, which is equivelant to the root directory in our * implemtation. Also set update proccess's cur_dir to root. */ cur_dir = dir_open_root(); t->cur_dir = dir_open_root(); } else { /* Give path is also relative. And set cur_dir same as the process's * working director. */ if (dir_get_inode(t->cur_dir)->removed) /* If the working directory has been removed, then return false * right away. */ return false; cur_dir = dir_reopen(t->cur_dir); } /* Iterate the path with dir as iterator until the null terminator. */ while (*dir != '\0'){ /* Reset the index iterator. for extract next subdirectory name. */ i = 0; /*Skip the directory symbol*/ while (*dir == '/') ++dir; /* Increment i until the directory symbol or null terminator*/ while ((*(dir + i) != '/' && *(dir + i) != '\0') && (i <= 15)){ ++i; } /* Enforces NAME_MAX length to all directories*/ if (i > 15) { dir_close(cur_dir); return false; } /* Copy this directory name to name*/ memcpy(name, dir, i); name[i] = '\0'; /* If this is the last name, then we got our final dir / file name, * i.e. finished decomposition of path. */ if (*(dir + i) == '\0') break; /* Look up the file / dir from the parent directory cur_dir. */ if (!dir_lookup(cur_dir, name, &next_inode)) { dir_close(cur_dir); return false; } /* Close the current parent directory, as we have found the next * one.*/ dir_close(cur_dir); /* Makes sure that we are always opening a directory. */ if (next_inode->data.type != DIR_INODE_DISK) { inode_close(next_inode); return false; } /* Open up the next directory in path. */ cur_dir = dir_open(next_inode); if (cur_dir == NULL) { inode_close(next_inode); return false; } /* Advance. */ dir += i; } /* Set the parent directory as cur_dir*/ *par_dir = cur_dir; /*Copy the final name ret_name*/ strlcpy(ret_name, name, strlen(name) + 1); 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; }
/*! 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; }