From 1607ebfe8632fa13c5ffb466b8c9f416d7ab20aa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 9 Feb 2011 15:05:58 -0800 Subject: Allow SMB2_FIND to actually use the open fd handle if we support fdopendir. Fallback to pathname opendir if not. --- source3/smbd/close.c | 3 ++- source3/smbd/dir.c | 54 ++++++++++++++++++++++++++++++++++++++---------- source3/smbd/filename.c | 2 +- source3/smbd/reply.c | 7 ++++--- source3/smbd/smb2_find.c | 1 + source3/smbd/trans2.c | 1 + 6 files changed, 52 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index d5a824f868..60cf8ed945 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -699,7 +699,7 @@ static bool recursive_rmdir(TALLOC_CTX *ctx, SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname)); - dir_hnd = OpenDir(talloc_tos(), conn, smb_dname->base_name, NULL, 0); + dir_hnd = OpenDir(talloc_tos(), conn, NULL, smb_dname->base_name, NULL, 0); if(dir_hnd == NULL) return False; @@ -817,6 +817,7 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, files_struct *fsp) char *talloced = NULL; long dirpos = 0; struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, + NULL, smb_dname->base_name, NULL, 0); diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index f81206e0ec..edc1ffe65f 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -190,7 +190,7 @@ static struct dptr_struct *dptr_get(struct smbd_server_connection *sconn, dptr_idleoldest(sconn); DEBUG(4,("dptr_get: Reopening dptr key %d\n",key)); if (!(dptr->dir_hnd = OpenDir( - NULL, dptr->conn, dptr->path, + NULL, dptr->conn, NULL, dptr->path, dptr->wcard, dptr->attr))) { DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr->path, strerror(errno))); @@ -413,7 +413,8 @@ static void dptr_close_oldest(struct smbd_server_connection *sconn, wcard must not be zero. ****************************************************************************/ -NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, bool expect_close,uint16 spid, +NTSTATUS dptr_create(connection_struct *conn, files_struct *fsp, + const char *path, bool old_handle, bool expect_close,uint16 spid, const char *wcard, bool wcard_has_wild, uint32 attr, struct dptr_struct **dptr_ret) { struct smbd_server_connection *sconn = conn->sconn; @@ -421,6 +422,10 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, struct smb_Dir *dir_hnd; NTSTATUS status; + if (fsp && fsp->is_directory && fsp->fh->fd != -1) { + path = fsp->fsp_name->base_name; + } + DEBUG(5,("dptr_create dir=%s\n", path)); if (sconn == NULL) { @@ -432,12 +437,14 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, return NT_STATUS_INVALID_PARAMETER; } - status = check_name(conn,path); - if (!NT_STATUS_IS_OK(status)) { - return status; + if (!fsp) { + status = check_name(conn,path); + if (!NT_STATUS_IS_OK(status)) { + return status; + } } - dir_hnd = OpenDir(NULL, conn, path, wcard, attr); + dir_hnd = OpenDir(NULL, conn, fsp, path, wcard, attr); if (!dir_hnd) { return map_nt_error_from_unix(errno); } @@ -1305,7 +1312,10 @@ static int smb_Dir_destructor(struct smb_Dir *dirp) ********************************************************************/ struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn, - const char *name, const char *mask, uint32 attr) + files_struct *fsp, + const char *name, + const char *mask, + uint32 attr) { struct smb_Dir *dirp = TALLOC_ZERO_P(mem_ctx, struct smb_Dir); struct smbd_server_connection *sconn = conn->sconn; @@ -1317,7 +1327,11 @@ struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn, dirp->conn = conn; dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn)); - dirp->dir_path = talloc_strdup(dirp, name); + if (fsp) { + dirp->dir_path = talloc_strdup(dirp, fsp->fsp_name->base_name); + } else { + dirp->dir_path = talloc_strdup(dirp, name); + } if (!dirp->dir_path) { errno = ENOMEM; goto fail; @@ -1328,7 +1342,25 @@ struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn, } talloc_set_destructor(dirp, smb_Dir_destructor); - dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr); + if (fsp && fsp->is_directory && fsp->fh->fd != -1) { + dirp->dir = SMB_VFS_FDOPENDIR(fsp, mask, attr); + if (dirp->dir == NULL) { + DEBUG(10,("OpenDir: SMB_VFS_FDOPENDIR on %s returned " + "NULL (%s)\n", + dirp->dir_path, + strerror(errno))); + if (errno != ENOSYS) { + return NULL; + } + } + } + + if (dirp->dir == NULL) { + /* FDOPENDIR didn't work - or fsp == NULL. Use + OPENDIR instead. */ + dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr); + } + if (!dirp->dir) { DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path, strerror(errno) )); @@ -1536,8 +1568,8 @@ NTSTATUS can_delete_directory(struct connection_struct *conn, const char *dname = NULL; char *talloced = NULL; SMB_STRUCT_STAT st; - struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, dirname, - NULL, 0); + struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, NULL, + dirname, NULL, 0); if (!dir_hnd) { return map_nt_error_from_unix(errno); diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 03877218de..8e6de84424 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -1074,7 +1074,7 @@ static int get_real_filename_full_scan(connection_struct *conn, } /* open the directory */ - if (!(cur_dir = OpenDir(talloc_tos(), conn, path, NULL, 0))) { + if (!(cur_dir = OpenDir(talloc_tos(), conn, NULL, path, NULL, 0))) { DEBUG(3,("scan dir didn't open dir [%s]\n",path)); TALLOC_FREE(unmangled_name); return -1; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e64627b06c..120b8bc69f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1460,6 +1460,7 @@ void reply_search(struct smb_request *req) SCVAL(status,0,(dirtype & 0x1F)); nt_status = dptr_create(conn, + NULL, /* fsp */ directory, True, expect_close, @@ -2646,7 +2647,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, goto out; } - dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask, + dir_hnd = OpenDir(talloc_tos(), conn, NULL, fname_dir, fname_mask, dirtype); if (dir_hnd == NULL) { status = map_nt_error_from_unix(errno); @@ -6379,7 +6380,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, goto out; } - dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask, + dir_hnd = OpenDir(talloc_tos(), conn, NULL, fname_src_dir, fname_src_mask, attrs); if (dir_hnd == NULL) { status = map_nt_error_from_unix(errno); @@ -7066,7 +7067,7 @@ void reply_copy(struct smb_request *req) goto out; } - dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0); + dir_hnd = OpenDir(ctx, conn, NULL, fname_src_dir, fname_src_mask, 0); if (dir_hnd == NULL) { status = map_nt_error_from_unix(errno); reply_nterror(req, status); diff --git a/source3/smbd/smb2_find.c b/source3/smbd/smb2_find.c index b10446c3f1..9a74886058 100644 --- a/source3/smbd/smb2_find.c +++ b/source3/smbd/smb2_find.c @@ -331,6 +331,7 @@ static struct tevent_req *smbd_smb2_find_send(TALLOC_CTX *mem_ctx, wcard_has_wild = ms_has_wild(in_file_name); status = dptr_create(conn, + fsp, directory, false, /* old_handle */ false, /* expect_close */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 2ce1fd746a..ed8e9f5642 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2417,6 +2417,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd needed as lanman2 assumes these are being saved between calls */ ntstatus = dptr_create(conn, + NULL, /* fsp */ directory, False, True, -- cgit