예제 #1
0
static int initiate_cifs_search(const int xid, struct file *file)
{
	__u16 search_flags;
	int rc = 0;
	char *full_path = NULL;
	struct cifsFileInfo *cifsFile;
	struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
	struct tcon_link *tlink = NULL;
	struct cifs_tcon *pTcon;

	if (file->private_data == NULL) {
		tlink = cifs_sb_tlink(cifs_sb);
		if (IS_ERR(tlink))
			return PTR_ERR(tlink);

		cifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
		if (cifsFile == NULL) {
			rc = -ENOMEM;
			goto error_exit;
		}
		file->private_data = cifsFile;
		cifsFile->tlink = cifs_get_tlink(tlink);
		pTcon = tlink_tcon(tlink);
	} else {
		cifsFile = file->private_data;
		pTcon = tlink_tcon(cifsFile->tlink);
	}

	cifsFile->invalidHandle = true;
	cifsFile->srch_inf.endOfSearch = false;

	full_path = build_path_from_dentry(file->f_path.dentry);
	if (full_path == NULL) {
		rc = -ENOMEM;
		goto error_exit;
	}

	cFYI(1, "Full path: %s start at: %lld", full_path, file->f_pos);

ffirst_retry:
	
	
	if (pTcon->unix_ext)
		cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX;
	else if ((pTcon->ses->capabilities &
			(CAP_NT_SMBS | CAP_NT_FIND)) == 0) {
		cifsFile->srch_inf.info_level = SMB_FIND_FILE_INFO_STANDARD;
	} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
		cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
	} else  {
		cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
	}

	search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME;
	if (backup_cred(cifs_sb))
		search_flags |= CIFS_SEARCH_BACKUP_SEARCH;

	rc = CIFSFindFirst(xid, pTcon, full_path, cifs_sb->local_nls,
		&cifsFile->netfid, search_flags, &cifsFile->srch_inf,
		cifs_sb->mnt_cifs_flags &
			CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb));
	if (rc == 0)
		cifsFile->invalidHandle = false;
	else if ((rc == -EOPNOTSUPP) &&
		(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
		goto ffirst_retry;
	}
error_exit:
	kfree(full_path);
	cifs_put_tlink(tlink);
	return rc;
}
예제 #2
0
파일: readdir.c 프로젝트: piastry/etercifs
static int
initiate_cifs_search(const unsigned int xid, struct file *file)
{
	__u16 search_flags;
	int rc = 0;
	char *full_path = NULL;
	struct cifsFileInfo *cifsFile;
	struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file);
	struct tcon_link *tlink = NULL;
	struct cifs_tcon *tcon;
	struct TCP_Server_Info *server;

	if (file->private_data == NULL) {
		tlink = cifs_sb_tlink(cifs_sb);
		if (IS_ERR(tlink))
			return PTR_ERR(tlink);

		cifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
		if (cifsFile == NULL) {
			rc = -ENOMEM;
			goto error_exit;
		}
		file->private_data = cifsFile;
		cifsFile->tlink = cifs_get_tlink(tlink);
		tcon = tlink_tcon(tlink);
	} else {
		cifsFile = file->private_data;
		tcon = tlink_tcon(cifsFile->tlink);
	}

	server = tcon->ses->server;

	if (!server->ops->query_dir_first) {
		rc = -ENOSYS;
		goto error_exit;
	}

	cifsFile->invalidHandle = true;
	cifsFile->srch_inf.endOfSearch = false;

	full_path = build_path_from_dentry(file->f_path.dentry);
	if (full_path == NULL) {
		rc = -ENOMEM;
		goto error_exit;
	}

	cifs_dbg(FYI, "Full path: %s start at: %lld\n", full_path, file->f_pos);

ffirst_retry:
	/* test for Unix extensions */
	/* but now check for them on the share/mount not on the SMB session */
	/* if (cap_unix(tcon->ses) { */
	if (tcon->unix_ext)
		cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX;
	else if ((tcon->ses->capabilities &
		  tcon->ses->server->vals->cap_nt_find) == 0) {
		cifsFile->srch_inf.info_level = SMB_FIND_FILE_INFO_STANDARD;
	} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
		cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
	} else /* not srvinos - BB fixme add check for backlevel? */ {
		cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
	}

	search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME;
	if (backup_cred(cifs_sb))
		search_flags |= CIFS_SEARCH_BACKUP_SEARCH;

	rc = server->ops->query_dir_first(xid, tcon, full_path, cifs_sb,
					  &cifsFile->fid, search_flags,
					  &cifsFile->srch_inf);

	if (rc == 0)
		cifsFile->invalidHandle = false;
	/* BB add following call to handle readdir on new NTFS symlink errors
	else if STATUS_STOPPED_ON_SYMLINK
		call get_symlink_reparse_path and retry with new path */
	else if ((rc == -EOPNOTSUPP) &&
		(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
		goto ffirst_retry;
	}
error_exit:
	kfree(full_path);
	cifs_put_tlink(tlink);
	return rc;
}
예제 #3
0
static int initiate_cifs_search(const int xid, struct file *file)
{
    int rc = 0;
    char *full_path = NULL;
    struct cifsFileInfo *cifsFile;
    struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
    struct tcon_link *tlink = NULL;
    struct cifs_tcon *pTcon;

    if (file->private_data == NULL) {
        tlink = cifs_sb_tlink(cifs_sb);
        if (IS_ERR(tlink))
            return PTR_ERR(tlink);

        cifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
        if (cifsFile == NULL) {
            rc = -ENOMEM;
            goto error_exit;
        }
        file->private_data = cifsFile;
        cifsFile->tlink = cifs_get_tlink(tlink);
        pTcon = tlink_tcon(tlink);
    } else {
        cifsFile = file->private_data;
        pTcon = tlink_tcon(cifsFile->tlink);
    }

    cifsFile->invalidHandle = true;
    cifsFile->srch_inf.endOfSearch = false;

    full_path = build_path_from_dentry(file->f_path.dentry);
    if (full_path == NULL) {
        rc = -ENOMEM;
        goto error_exit;
    }

    cFYI(1, "Full path: %s start at: %lld", full_path, file->f_pos);

ffirst_retry:
    /* test for Unix extensions */
    /* but now check for them on the share/mount not on the SMB session */
    /*	if (pTcon->ses->capabilities & CAP_UNIX) { */
    if (pTcon->unix_ext)
        cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX;
    else if ((pTcon->ses->capabilities &
              (CAP_NT_SMBS | CAP_NT_FIND)) == 0) {
        cifsFile->srch_inf.info_level = SMB_FIND_FILE_INFO_STANDARD;
    } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
        cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
    } else { /* not srvinos - BB fixme add check for backlevel? */
        cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
    }

    rc = CIFSFindFirst(xid, pTcon, full_path, cifs_sb->local_nls,
                       &cifsFile->netfid, &cifsFile->srch_inf,
                       cifs_sb->mnt_cifs_flags &
                       CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb));
    if (rc == 0)
        cifsFile->invalidHandle = false;
    /* BB add following call to handle readdir on new NTFS symlink errors
    else if STATUS_STOPPED_ON_SYMLINK
    	call get_symlink_reparse_path and retry with new path */
    else if ((rc == -EOPNOTSUPP) &&
             (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
        cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
        goto ffirst_retry;
    }
error_exit:
    kfree(full_path);
    cifs_put_tlink(tlink);
    return rc;
}