static int cifs_filldir(char *pfindEntry, struct file *file,
	filldir_t filldir, void *direntry, char *scratch_buf, int max_len)
{
	int rc = 0;
	struct qstr qstring;
	struct cifsFileInfo *pCifsF;
	unsigned int obj_type;
	__u64  inum;
	struct cifs_sb_info *cifs_sb;
	struct inode *tmp_inode;
	struct dentry *tmp_dentry;

	/* get filename and len into qstring */
	/* get dentry */
	/* decide whether to create and populate ionde */
	if ((direntry == NULL) || (file == NULL))
		return -EINVAL;

	pCifsF = file->private_data;

	if ((scratch_buf == NULL) || (pfindEntry == NULL) || (pCifsF == NULL))
		return -ENOENT;

	rc = cifs_entry_is_dot(pfindEntry, pCifsF);
	/* skip . and .. since we added them first */
	if (rc != 0)
		return 0;

	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);

	qstring.name = scratch_buf;
	rc = cifs_get_name_from_search_buf(&qstring, pfindEntry,
			pCifsF->srch_inf.info_level,
			pCifsF->srch_inf.unicode, cifs_sb,
			max_len,
			&inum /* returned */);

	if (rc)
		return rc;

	/* only these two infolevels return valid inode numbers */
	if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX ||
	    pCifsF->srch_inf.info_level == SMB_FIND_FILE_ID_FULL_DIR_INFO)
		rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry,
					&inum);
	else
		rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry,
					NULL);

	if ((tmp_inode == NULL) || (tmp_dentry == NULL))
		return -ENOMEM;

	/* we pass in rc below, indicating whether it is a new inode,
	   so we can figure out whether to invalidate the inode cached
	   data if the file has changed */
	if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX)
		unix_fill_in_inode(tmp_inode,
				   (FILE_UNIX_INFO *)pfindEntry,
				   &obj_type, rc);
	else if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD)
		fill_in_inode(tmp_inode, 0 /* old level 1 buffer type */,
				pfindEntry, &obj_type, rc);
	else
		fill_in_inode(tmp_inode, 1 /* NT */, pfindEntry, &obj_type, rc);

	if (rc) /* new inode - needs to be tied to dentry */ {
		d_instantiate(tmp_dentry, tmp_inode);
		if (rc == 2)
			d_rehash(tmp_dentry);
	}


	rc = filldir(direntry, qstring.name, qstring.len, file->f_pos,
		     tmp_inode->i_ino, obj_type);
	if (rc) {
		cFYI(1, ("filldir rc = %d", rc));
		/* we can not return filldir errors to the caller
		since they are "normal" when the stat blocksize
		is too small - we return remapped error instead */
		rc = -EOVERFLOW;
	}

	dput(tmp_dentry);
	return rc;
}
示例#2
0
static int cifs_filldir(char *pfindEntry, struct file *file,
	filldir_t filldir, void *direntry, char *scratch_buf)
{
	int rc = 0;
	struct qstr qstring;
	struct cifsFileInfo * pCifsF;
	unsigned obj_type;
	ino_t  inum;
	struct cifs_sb_info * cifs_sb;
	struct inode *tmp_inode;
	struct dentry *tmp_dentry;

	/* get filename and len into qstring */
	/* get dentry */
	/* decide whether to create and populate ionde */
	if((direntry == NULL) || (file == NULL))
		return -EINVAL;

	pCifsF = file->private_data;
	
	if((scratch_buf == NULL) || (pfindEntry == NULL) || (pCifsF == NULL))
		return -ENOENT;

	if(file->f_dentry == NULL)
		return -ENOENT;

	cifs_sb = CIFS_SB(file->f_dentry->d_sb);

	qstring.name = scratch_buf;
	rc = cifs_get_name_from_search_buf(&qstring,pfindEntry,
			pCifsF->srch_inf.info_level,
			pCifsF->srch_inf.unicode,cifs_sb,
			&inum /* returned */);

	if(rc)
		return rc;

	rc = construct_dentry(&qstring,file,&tmp_inode, &tmp_dentry);
	if((tmp_inode == NULL) || (tmp_dentry == NULL))
		return -ENOMEM;

	if(rc) {
		/* inode created, we need to hash it with right inode number */
		if(inum != 0) {
			/* BB fixme - hash the 2 32 quantities bits together if necessary BB */
			tmp_inode->i_ino = inum;
		}
		insert_inode_hash(tmp_inode);
	}

	/* we pass in rc below, indicating whether it is a new inode,
	   so we can figure out whether to invalidate the inode cached
	   data if the file has changed */
	if(pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) {
		unix_fill_in_inode(tmp_inode,
				   (FILE_UNIX_INFO *)pfindEntry,&obj_type, rc);
	} else {
		fill_in_inode(tmp_inode,
			      (FILE_DIRECTORY_INFO *)pfindEntry,&obj_type, rc);
	}
	
	rc = filldir(direntry,qstring.name,qstring.len,file->f_pos,tmp_inode->i_ino,obj_type);
	if(rc) {
		cFYI(1,("filldir rc = %d",rc));
	}

	dput(tmp_dentry);
	return rc;
}
示例#3
0
static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir,
                        void *direntry, char *scratch_buf, unsigned int max_len)
{
    int rc = 0;
    struct qstr qstring;
    struct cifsFileInfo *pCifsF;
    u64    inum;
    ino_t  ino;
    struct super_block *sb;
    struct cifs_sb_info *cifs_sb;
    struct dentry *tmp_dentry;
    struct cifs_fattr fattr;

    /* get filename and len into qstring */
    /* get dentry */
    /* decide whether to create and populate ionde */
    if ((direntry == NULL) || (file == NULL))
        return -EINVAL;

    pCifsF = file->private_data;

    if ((scratch_buf == NULL) || (pfindEntry == NULL) || (pCifsF == NULL))
        return -ENOENT;

    rc = cifs_entry_is_dot(pfindEntry, pCifsF);
    /* skip . and .. since we added them first */
    if (rc != 0)
        return 0;

    sb = file->f_path.dentry->d_sb;
    cifs_sb = CIFS_SB(sb);

    qstring.name = scratch_buf;
    rc = cifs_get_name_from_search_buf(&qstring, pfindEntry,
                                       pCifsF->srch_inf.info_level,
                                       pCifsF->srch_inf.unicode, cifs_sb,
                                       max_len, &inum /* returned */);

    if (rc)
        return rc;

    if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX)
        cifs_unix_basic_to_fattr(&fattr,
                                 &((FILE_UNIX_INFO *) pfindEntry)->basic,
                                 cifs_sb);
    else if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD)
        cifs_std_info_to_fattr(&fattr, (FIND_FILE_STANDARD_INFO *)
                               pfindEntry, cifs_sb);
    else
        cifs_dir_info_to_fattr(&fattr, (FILE_DIRECTORY_INFO *)
                               pfindEntry, cifs_sb);

    if (inum && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
        fattr.cf_uniqueid = inum;
    } else {
        fattr.cf_uniqueid = iunique(sb, ROOT_I);
        cifs_autodisable_serverino(cifs_sb);
    }

    if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) &&
            CIFSCouldBeMFSymlink(&fattr))
        /*
         * trying to get the type and mode can be slow,
         * so just call those regular files for now, and mark
         * for reval
         */
        fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;

    ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid);
    tmp_dentry = cifs_readdir_lookup(file->f_dentry, &qstring, &fattr);

    rc = filldir(direntry, qstring.name, qstring.len, file->f_pos,
                 ino, fattr.cf_dtype);

    dput(tmp_dentry);
    return rc;
}
示例#4
0
static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir,
			void *direntry, char *scratch_buf, unsigned int max_len)
{
	int rc = 0;
	struct qstr qstring;
	struct cifsFileInfo *pCifsF;
	u64    inum;
	ino_t  ino;
	struct super_block *sb;
	struct cifs_sb_info *cifs_sb;
	struct dentry *tmp_dentry;
	struct cifs_fattr fattr;

	/* get filename and len into qstring */
	/* get dentry */
	/* decide whether to create and populate ionde */
	if ((direntry == NULL) || (file == NULL))
		return -EINVAL;

	pCifsF = file->private_data;

	if ((scratch_buf == NULL) || (pfindEntry == NULL) || (pCifsF == NULL))
		return -ENOENT;

	rc = cifs_entry_is_dot(pfindEntry, pCifsF);
	/* skip . and .. since we added them first */
	if (rc != 0)
		return 0;

	sb = file->f_path.dentry->d_sb;
	cifs_sb = CIFS_SB(sb);

	qstring.name = scratch_buf;
	rc = cifs_get_name_from_search_buf(&qstring, pfindEntry,
			pCifsF->srch_inf.info_level,
			pCifsF->srch_inf.unicode, cifs_sb,
			max_len, &inum /* returned */);

	if (rc)
		return rc;

	if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX)
		cifs_unix_basic_to_fattr(&fattr,
				 &((FILE_UNIX_INFO *) pfindEntry)->basic,
				 cifs_sb);
	else if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD)
		cifs_std_info_to_fattr(&fattr, (FIND_FILE_STANDARD_INFO *)
					pfindEntry, cifs_sb);
	else
		cifs_dir_info_to_fattr(&fattr, (FILE_DIRECTORY_INFO *)
					pfindEntry, cifs_sb);

	if (inum && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
		fattr.cf_uniqueid = inum;
	} else {
		fattr.cf_uniqueid = iunique(sb, ROOT_I);
		cifs_autodisable_serverino(cifs_sb);
	}

	ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid);
	tmp_dentry = cifs_readdir_lookup(file->f_dentry, &qstring, &fattr);

	rc = filldir(direntry, qstring.name, qstring.len, file->f_pos,
		     ino, fattr.cf_dtype);

	/*
	 * we can not return filldir errors to the caller since they are
	 * "normal" when the stat blocksize is too small - we return remapped
	 * error instead
	 *
	 * FIXME: This looks bogus. filldir returns -EOVERFLOW in the above
	 * case already. Why should we be clobbering other errors from it?
	 */
	if (rc) {
		cFYI(1, ("filldir rc = %d", rc));
		rc = -EOVERFLOW;
	}
	dput(tmp_dentry);
	return rc;
}