/* * Find the given page, and call find_dirent() in order to try to * return the next entry. */ static inline int find_dirent_page(nfs_readdir_descriptor_t *desc) { struct inode *inode = desc->file->f_dentry->d_inode; struct page *page; int status; dfprintk(VFS, "NFS: find_dirent_page() searching directory page %ld\n", desc->page_index); desc->plus = NFS_USE_READDIRPLUS(inode); page = read_cache_page(&inode->i_data, desc->page_index, (filler_t *)nfs_readdir_filler, desc); if (IS_ERR(page)) { status = PTR_ERR(page); goto out; } if (!Page_Uptodate(page)) goto read_error; /* NOTE: Someone else may have changed the READDIRPLUS flag */ desc->page = page; desc->ptr = kmap(page); status = find_dirent(desc, page); if (status < 0) dir_page_release(desc); out: dfprintk(VFS, "NFS: find_dirent_page() returns %d\n", status); return status; read_error: page_cache_release(page); return -EIO; }
sc_segment* map_segment(const sc_string &s) { tmp_dirent *dirent = find_dirent(s); if (!dirent || dirent->dir) return 0; return dirent->u.seg; }
// finds direcory where item s reside and returns place where its name begins // dir means allowed to have trailing / tmp_dir* find_directory(const sc_string &s,int &i,bool _dir) { i = (s.size())-1; if (i<0) return 0; assert(i>0 || s[0] != '/'); if (_dir) { // get rid of trailing / while (s[i] == '/') i--; } else if (s[i] == '/') return 0; while (i>0) if (s[--i] == '/') break; tmp_dir *dir = &root; if (i>0) { int k = i; while (s[--k] == '/'); tmp_dirent *dent = find_dirent(s.substr(0,k+1)); if (!dent || !dent->dir) return 0; dir = dent->u.dir; i++; } return dir; }
sc_retval _stat(const sc_string &s) { if (!s.size()) return RV_ELSE_GEN; tmp_dirent *dirent = find_dirent(s); if (!dirent) return RV_ERR_GEN; return dirent->dir?RV_ELSE_GEN:RV_OK; }
sc_dir_iterator *search_dir(const sc_string &s) { if (!s.size()) { return root.search(); } tmp_dirent *dirent = find_dirent(s); if (!dirent || !dirent->dir) return 0; return dirent->u.dir->search(); }
/* Walk a path string, either changing directories or finding the right path If mode is WALK_CHDIR, the result of this function is entering into the new directory on success, or the old directory being returned on failure. If mode is WALK_OPEN, the result of this function is the directory remains unchanged and a pointer to the directory entry for the requested file or directory is returned. If it is a file, the directory entry for the file itself is returned. If it is a directory, the directory entry of the first file or directory inside that directory is returned. The type specifier allows a person to specify that only a directory or file should be returned. This works for WALK_OPEN only. */ static int recurse_path(const char * const path, int mode, directory_entry_t **dirent, int type) { int ret = DFS_ESUCCESS; char token[MAX_FILENAME_LEN+1]; char *cur_path = (char *)path; uint32_t dir_stack[MAX_DIRECTORY_DEPTH]; uint32_t dir_loc = directory_top; int last_type = TYPE_ANY; int ignore = 1; // Do not, by default, read again during the first while /* Save directory stack */ memcpy(dir_stack, directories, sizeof(uint32_t) * MAX_DIRECTORY_DEPTH); /* Grab first token, make sure it isn't root */ cur_path = get_next_token(cur_path, token); if(strcmp(token, "/") == 0) { /* It is an absolute path */ clear_directory(); /* Ensure that we remember this as a directory */ last_type = TYPE_DIR; /* We need to read through the first while loop */ ignore = 0; } /* Loop through the rest */ while(cur_path || ignore) { /* Grab out the next token */ if(!ignore) { cur_path = get_next_token(cur_path, token); } ignore = 0; if( (token[0] == '/' || token[0] == '.') ) { if(token[1] == '.') pop_directory();/* Up one directory */ last_type = TYPE_DIR; } else { /* Find directory entry, push */ directory_entry_t *tmp_node = find_dirent(token, peek_directory()); if(tmp_node) { /* Grab node, make sure it is a directory, push subdirectory, try again! */ directory_entry_t node; grab_sector(tmp_node, &node); uint32_t flags = get_flags(&node); if(FILETYPE(flags) == FLAGS_DIR) { /* Push subdirectory onto stack and loop */ push_directory(get_first_entry(&node)); last_type = TYPE_DIR; } else { if(mode == WALK_CHDIR) { /* Not found, this is a file */ ret = DFS_ENOFILE; break; } else { last_type = TYPE_FILE; /* Only count if this is the last thing we are doing */ if(!cur_path) { /* Push file entry onto stack in preparation of a return */ push_directory(tmp_node); } else { /* Not found, this is a file */ ret = DFS_ENOFILE; break; } } } } else { /* Not found! */ ret = DFS_ENOFILE; break; } } } if(type != TYPE_ANY && type != last_type) { /* Found an entry, but it was the wrong type! */ ret = DFS_ENOFILE; } if(mode == WALK_OPEN) { /* Must return the node found if we found one */ if(ret == DFS_ESUCCESS && dirent) { *dirent = peek_directory(); } } if(mode == WALK_OPEN || ret != DFS_ESUCCESS) { /* Restore stack */ directory_top = dir_loc; memcpy(directories, dir_stack, sizeof(uint32_t) * MAX_DIRECTORY_DEPTH); } return ret; }