/*
 * 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;
}
예제 #2
0
	sc_segment* map_segment(const sc_string &s)
	{
		tmp_dirent *dirent = find_dirent(s);
		if (!dirent || dirent->dir)
			return 0;
		return dirent->u.seg;
	}
예제 #3
0
	// 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;
	}
예제 #4
0
	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;
	}
예제 #5
0
	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();
	}
예제 #6
0
/* 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;
}