Allow SMB2_FIND to actually use the open fd handle if we support fdopendir. Fallback...
authorJeremy Allison <jra@samba.org>
Wed, 9 Feb 2011 23:05:58 +0000 (15:05 -0800)
committerJeremy Allison <jra@samba.org>
Wed, 9 Feb 2011 23:13:40 +0000 (15:13 -0800)
source3/include/proto.h
source3/smbd/close.c
source3/smbd/dir.c
source3/smbd/filename.c
source3/smbd/reply.c
source3/smbd/smb2_find.c
source3/smbd/trans2.c

index 0cca013143e6fe11fcbfae7dd4042519a8084435..969d12fb52d7c84f80e152431eb19b36d7dbcc2a 100644 (file)
@@ -4547,7 +4547,8 @@ void dptr_closecnum(connection_struct *conn);
 void dptr_idlecnum(connection_struct *conn);
 void dptr_closepath(struct smbd_server_connection *sconn,
                    char *path,uint16 spid);
-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);
 void dptr_CloseDir(files_struct *fsp);
 void dptr_SeekDir(struct dptr_struct *dptr, long offset);
@@ -4580,6 +4581,7 @@ bool get_dir_entry(TALLOC_CTX *ctx,
                bool ask_sharemode);
 bool is_visible_file(connection_struct *conn, const char *dir_path, const char *name, SMB_STRUCT_STAT *pst, bool use_veto);
 struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn,
+                       files_struct *fsp,
                        const char *name, const char *mask, uint32 attr);
 const char *ReadDirName(struct smb_Dir *dirp, long *poffset,
                        SMB_STRUCT_STAT *sbuf, char **talloced);
index d5a824f868fbc2ec22a719d26bd3703eef09980f..60cf8ed945057a5a4a2cee4cbc95fdf90bec415d 100644 (file)
@@ -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);
 
index f81206e0ecfeebde899a2d1c0a3c1779570f403d..edc1ffe65f342524eb6605b3868ac40e1bb5ced0 100644 (file)
@@ -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);
index 03877218de57a4caba492c990680031246343440..8e6de84424452ea10b7c2bcb45b4dbf7196755c9 100644 (file)
@@ -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;
index e64627b06c10954d4ad4f14ae137cdd3c1c13d7b..120b8bc69fcca4560e8ceed5f56b7c39665ebf99 100644 (file)
@@ -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);
index b10446c3f10c009d2c603a4522e37d30ed185c6b..9a7488605829b580492f40bdf89300d955d07bee 100644 (file)
@@ -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 */
index 2ce1fd746aef747ef044506a5484ded514d0942e..ed8e9f564215679fc4648969071a073bf2a55069 100644 (file)
@@ -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,