s3: smbd: Change dptr_create() to take a const struct smb_filename * instead of const...
authorJeremy Allison <jra@samba.org>
Sat, 27 Feb 2016 00:35:17 +0000 (16:35 -0800)
committerRalph Boehme <slow@samba.org>
Tue, 1 Mar 2016 17:34:24 +0000 (18:34 +0100)
Also internally change path storage inside struct dptr_struct
to a struct smb_filename *.

This allows me to remove several of the synthetic_smb_fname()
calls I had to add in the previous patches, as we're now
dealing with struct smb_filename * throughout the dptr and
OpenDir code.

Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
Autobuild-User(master): Ralph Böhme <slow@samba.org>
Autobuild-Date(master): Tue Mar  1 18:34:24 CET 2016 on sn-devel-144

source3/smbd/dir.c
source3/smbd/proto.h
source3/smbd/reply.c
source3/smbd/smb2_query_directory.c
source3/smbd/trans2.c

index b71234e8889c9eccde51a59de1b63979f8ff1c35..82841ebc5e726ebaabb83784cbf351c6915f4873 100644 (file)
@@ -70,7 +70,7 @@ struct dptr_struct {
        bool expect_close;
        char *wcard;
        uint32_t attr;
-       char *path;
+       struct smb_filename *smb_dname;
        bool has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */
        bool did_stat; /* Optimisation for non-wcard searches. */
        bool priv;     /* Directory handle opened with privilege. */
@@ -163,33 +163,21 @@ static struct dptr_struct *dptr_get(struct smbd_server_connection *sconn,
        for(dptr = sconn->searches.dirptrs; dptr; dptr = dptr->next) {
                if(dptr->dnum == key) {
                        if (!forclose && !dptr->dir_hnd) {
-                               struct smb_filename *smb_dname = NULL;
-
                                if (sconn->searches.dirhandles_open >= MAX_OPEN_DIRECTORIES)
                                        dptr_idleoldest(sconn);
                                DEBUG(4,("dptr_get: Reopening dptr key %d\n",key));
 
-                               smb_dname = synthetic_smb_fname(talloc_tos(),
-                                       dptr->path,
-                                       NULL,
-                                       NULL);
-                               if (smb_dname == NULL) {
-                                       return NULL;
-                               }
-
                                if (!(dptr->dir_hnd = OpenDir(NULL,
                                                        dptr->conn,
-                                                       smb_dname,
+                                                       dptr->smb_dname,
                                                        dptr->wcard,
                                                        dptr->attr))) {
                                        DEBUG(4,("dptr_get: Failed to "
                                                "open %s (%s)\n",
-                                               dptr->path,
+                                               dptr->smb_dname->base_name,
                                                strerror(errno)));
-                                       TALLOC_FREE(smb_dname);
                                        return NULL;
                                }
-                               TALLOC_FREE(smb_dname);
                        }
                        DLIST_PROMOTE(sconn->searches.dirptrs,dptr);
                        return dptr;
@@ -206,7 +194,7 @@ const char *dptr_path(struct smbd_server_connection *sconn, int key)
 {
        struct dptr_struct *dptr = dptr_get(sconn, key, false);
        if (dptr)
-               return(dptr->path);
+               return(dptr->smb_dname->base_name);
        return(NULL);
 }
 
@@ -356,8 +344,10 @@ void dptr_closepath(struct smbd_server_connection *sconn,
        struct dptr_struct *dptr, *next;
        for(dptr = sconn->searches.dirptrs; dptr; dptr = next) {
                next = dptr->next;
-               if (spid == dptr->spid && strequal(dptr->path,path))
+               if (spid == dptr->spid &&
+                               strequal(dptr->smb_dname->base_name,path)) {
                        dptr_close_internal(dptr);
+               }
        }
 }
 
@@ -404,7 +394,7 @@ static void dptr_close_oldest(struct smbd_server_connection *sconn,
 
 static struct smb_Dir *open_dir_with_privilege(connection_struct *conn,
                                        struct smb_request *req,
-                                       const char *path,
+                                       const struct smb_filename *smb_dname,
                                        const char *wcard,
                                        uint32_t attr)
 {
@@ -418,7 +408,7 @@ static struct smb_Dir *open_dir_with_privilege(connection_struct *conn,
                return NULL;
        }
 
-       if (vfs_ChDir(conn, path) == -1) {
+       if (vfs_ChDir(conn, smb_dname->base_name) == -1) {
                return NULL;
        }
 
@@ -436,7 +426,7 @@ static struct smb_Dir *open_dir_with_privilege(connection_struct *conn,
        if (!check_same_stat(&smb_fname_cwd->st, &priv_paths->parent_name.st)) {
                DEBUG(0,("open_dir_with_privilege: stat mismatch between %s "
                        "and %s\n",
-                       path,
+                       smb_dname->base_name,
                        smb_fname_str_dbg(&priv_paths->parent_name)));
                goto out;
        }
@@ -461,18 +451,24 @@ static struct smb_Dir *open_dir_with_privilege(connection_struct *conn,
 NTSTATUS dptr_create(connection_struct *conn,
                struct smb_request *req,
                files_struct *fsp,
-               const char *path, bool old_handle, bool expect_close,uint16_t spid,
-               const char *wcard, bool wcard_has_wild, uint32_t attr, struct dptr_struct **dptr_ret)
+               const struct smb_filename *smb_dname,
+               bool old_handle,
+               bool expect_close,
+               uint16_t spid,
+               const char *wcard,
+               bool wcard_has_wild,
+               uint32_t attr,
+               struct dptr_struct **dptr_ret)
 {
        struct smbd_server_connection *sconn = conn->sconn;
        struct dptr_struct *dptr = NULL;
        struct smb_Dir *dir_hnd;
 
        if (fsp && fsp->is_directory && fsp->fh->fd != -1) {
-               path = fsp->fsp_name->base_name;
+               smb_dname = fsp->fsp_name;
        }
 
-       DEBUG(5,("dptr_create dir=%s\n", path));
+       DEBUG(5,("dptr_create dir=%s\n", smb_dname->base_name));
 
        if (sconn == NULL) {
                DEBUG(0,("dptr_create: called with fake connection_struct\n"));
@@ -487,48 +483,57 @@ NTSTATUS dptr_create(connection_struct *conn,
                if (!(fsp->access_mask & SEC_DIR_LIST)) {
                        DEBUG(5,("dptr_create: directory %s "
                                "not open for LIST access\n",
-                               path));
+                               smb_dname->base_name));
                        return NT_STATUS_ACCESS_DENIED;
                }
                dir_hnd = OpenDir_fsp(NULL, conn, fsp, wcard, attr);
        } else {
                int ret;
                bool backup_intent = (req && req->priv_paths);
-               struct smb_filename *smb_dname;
                NTSTATUS status;
+               struct smb_filename *smb_dname_cp =
+                       cp_smb_filename(talloc_tos(), smb_dname);
 
-               smb_dname = synthetic_smb_fname(talloc_tos(), path,
-                                               NULL, NULL);
-               if (smb_dname == NULL) {
+               if (smb_dname_cp == NULL) {
                        return NT_STATUS_NO_MEMORY;
                }
+
                if (req != NULL && req->posix_pathnames) {
-                       ret = SMB_VFS_LSTAT(conn, smb_dname);
+                       ret = SMB_VFS_LSTAT(conn, smb_dname_cp);
                } else {
-                       ret = SMB_VFS_STAT(conn, smb_dname);
+                       ret = SMB_VFS_STAT(conn, smb_dname_cp);
                }
                if (ret == -1) {
-                       return map_nt_error_from_unix(errno);
+                       status = map_nt_error_from_unix(errno);
+                       TALLOC_FREE(smb_dname_cp);
+                       return status;
                }
-               if (!S_ISDIR(smb_dname->st.st_ex_mode)) {
+               if (!S_ISDIR(smb_dname_cp->st.st_ex_mode)) {
+                       TALLOC_FREE(smb_dname_cp);
                        return NT_STATUS_NOT_A_DIRECTORY;
                }
                status = smbd_check_access_rights(conn,
-                                               smb_dname,
+                                               smb_dname_cp,
                                                backup_intent,
                                                SEC_DIR_LIST);
                if (!NT_STATUS_IS_OK(status)) {
+                       TALLOC_FREE(smb_dname_cp);
                        return status;
                }
                if (backup_intent) {
                        dir_hnd = open_dir_with_privilege(conn,
                                                req,
-                                               path,
+                                               smb_dname_cp,
                                                wcard,
                                                attr);
                } else {
-                       dir_hnd = OpenDir(NULL, conn, smb_dname, wcard, attr);
+                       dir_hnd = OpenDir(NULL,
+                                       conn,
+                                       smb_dname_cp,
+                                       wcard,
+                                       attr);
                }
+               TALLOC_FREE(smb_dname_cp);
        }
 
        if (!dir_hnd) {
@@ -546,8 +551,8 @@ NTSTATUS dptr_create(connection_struct *conn,
                return NT_STATUS_NO_MEMORY;
        }
 
-       dptr->path = talloc_strdup(dptr, path);
-       if (!dptr->path) {
+       dptr->smb_dname = cp_smb_filename(dptr, smb_dname);
+       if (!dptr->smb_dname) {
                TALLOC_FREE(dptr);
                TALLOC_FREE(dir_hnd);
                return NT_STATUS_NO_MEMORY;
@@ -643,7 +648,9 @@ NTSTATUS dptr_create(connection_struct *conn,
 
 done:
        DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
-               dptr->dnum,path,expect_close));  
+               dptr->dnum,
+               dptr->smb_dname->base_name,
+               expect_close));
 
        *dptr_ret = dptr;
 
@@ -712,7 +719,11 @@ static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr,
 
        while ((name = ReadDirName(dptr->dir_hnd, poffset, pst, &talloced))
               != NULL) {
-               if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
+               if (is_visible_file(dptr->conn,
+                               dptr->smb_dname->base_name,
+                               name,
+                               pst,
+                               true)) {
                        *ptalloced = talloced;
                        return name;
                }
@@ -766,9 +777,11 @@ static char *dptr_ReadDirName(TALLOC_CTX *ctx,
        dptr->did_stat = true;
 
        /* First check if it should be visible. */
-       if (!is_visible_file(dptr->conn, dptr->path, dptr->wcard,
-           pst, true))
-       {
+       if (!is_visible_file(dptr->conn,
+                       dptr->smb_dname->base_name,
+                       dptr->wcard,
+                       pst,
+                       true)) {
                /* This only returns false if the file was found, but
                   is explicitly not visible. Set us to end of
                   directory, but return NULL as we know we can't ever
@@ -783,7 +796,7 @@ static char *dptr_ReadDirName(TALLOC_CTX *ctx,
 
        pathreal = talloc_asprintf(ctx,
                                "%s/%s",
-                               dptr->path,
+                               dptr->smb_dname->base_name,
                                dptr->wcard);
        if (!pathreal)
                return NULL;
@@ -818,8 +831,11 @@ static char *dptr_ReadDirName(TALLOC_CTX *ctx,
         * Try case-insensitive stat if the fs has the ability. This avoids
         * scanning the whole directory.
         */
-       ret = SMB_VFS_GET_REAL_FILENAME(dptr->conn, dptr->path, dptr->wcard,
-                                       ctx, &found_name);
+       ret = SMB_VFS_GET_REAL_FILENAME(dptr->conn,
+                                       dptr->smb_dname->base_name,
+                                       dptr->wcard,
+                                       ctx,
+                                       &found_name);
        if (ret == 0) {
                name = found_name;
                goto clean;
@@ -1029,7 +1045,7 @@ struct dptr_struct *dptr_fetch(struct smbd_server_connection *sconn,
        seekoff = map_wire_to_dir_offset(dptr, wire_offset);
        SeekDir(dptr->dir_hnd,seekoff);
        DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
-               key, dptr->path, (int)seekoff));
+               key, dptr->smb_dname->base_name, (int)seekoff));
        return(dptr);
 }
 
@@ -1046,7 +1062,9 @@ struct dptr_struct *dptr_fetch_lanman2(struct smbd_server_connection *sconn,
                DEBUG(3,("fetched null dirptr %d\n",dptr_num));
                return(NULL);
        }
-       DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr->path));
+       DEBUG(3,("fetching dirptr %d for path %s\n",
+               dptr_num,
+               dptr->smb_dname->base_name));
        return(dptr);
 }
 
@@ -1086,13 +1104,14 @@ bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
        connection_struct *conn = dirptr->conn;
        size_t slashlen;
        size_t pathlen;
-       bool dirptr_path_is_dot = ISDOT(dirptr->path);
+       const char *dpath = dirptr->smb_dname->base_name;
+       bool dirptr_path_is_dot = ISDOT(dpath);
 
        *_smb_fname = NULL;
        *_mode = 0;
 
-       pathlen = strlen(dirptr->path);
-       slashlen = ( dirptr->path[pathlen-1] != '/') ? 1 : 0;
+       pathlen = strlen(dpath);
+       slashlen = ( dpath[pathlen-1] != '/') ? 1 : 0;
 
        while (true) {
                long cur_offset;
@@ -1158,7 +1177,7 @@ bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
                if (dirptr_path_is_dot) {
                        memcpy(pathreal, dname, talloc_get_size(dname));
                } else {
-                       memcpy(pathreal, dirptr->path, pathlen);
+                       memcpy(pathreal, dpath, pathlen);
                        pathreal[pathlen] = '/';
                        memcpy(pathreal + slashlen + pathlen, dname,
                               talloc_get_size(dname));
index 3f9ddb58263168aafeb2d09a82793718fa9f8cb9..8df3197488d369bf04583c08750bcf7119e9bfb7 100644 (file)
@@ -193,8 +193,14 @@ void dptr_closepath(struct smbd_server_connection *sconn,
 NTSTATUS dptr_create(connection_struct *conn,
                struct smb_request *req,
                files_struct *fsp,
-               const char *path, bool old_handle, bool expect_close,uint16_t spid,
-               const char *wcard, bool wcard_has_wild, uint32_t attr, struct dptr_struct **dptr_ret);
+               const struct smb_filename *smb_dname,
+               bool old_handle,
+               bool expect_close,
+               uint16_t spid,
+               const char *wcard,
+               bool wcard_has_wild,
+               uint32_t attr,
+               struct dptr_struct **dptr_ret);
 void dptr_CloseDir(files_struct *fsp);
 void dptr_SeekDir(struct dptr_struct *dptr, long offset);
 long dptr_TellDir(struct dptr_struct *dptr);
index 6763218124506e154a5a7ad30a0fb34957d965dc..bb91d77b416830909c77303e6e6b792373c852be 100644 (file)
@@ -1783,6 +1783,7 @@ void reply_search(struct smb_request *req)
        /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
 
        if (status_len == 0) {
+               struct smb_filename *smb_dname = NULL;
                uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
                        (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
                nt_status = filename_convert(ctx, conn,
@@ -1821,10 +1822,19 @@ void reply_search(struct smb_request *req)
                memset((char *)status,'\0',21);
                SCVAL(status,0,(dirtype & 0x1F));
 
+               smb_dname = synthetic_smb_fname(talloc_tos(),
+                                       directory,
+                                       NULL,
+                                       NULL);
+               if (smb_dname == NULL) {
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                       goto out;
+               }
+
                nt_status = dptr_create(conn,
                                        NULL, /* req */
                                        NULL, /* fsp */
-                                       directory,
+                                       smb_dname,
                                        True,
                                        expect_close,
                                        req->smbpid,
@@ -1832,6 +1842,9 @@ void reply_search(struct smb_request *req)
                                        mask_contains_wcard,
                                        dirtype,
                                        &dirptr);
+
+               TALLOC_FREE(smb_dname);
+
                if (!NT_STATUS_IS_OK(nt_status)) {
                        reply_nterror(req, nt_status);
                        goto out;
index 4b6ca1b8c0abbfcf3b15d4b4ff949d00a599e816..e18a279d9b404f951a210ba262e2a6c68e716498 100644 (file)
@@ -376,7 +376,7 @@ static struct tevent_req *smbd_smb2_query_directory_send(TALLOC_CTX *mem_ctx,
                status = dptr_create(conn,
                                     NULL, /* req */
                                     fsp,
-                                    fsp->fsp_name->base_name,
+                                    fsp->fsp_name,
                                     false, /* old_handle */
                                     false, /* expect_close */
                                     0, /* spid */
index bc34add01898f760336aee9395034522ceceda64..584039faad6b09f6fd74c907d2c907dc006ae38b 100644 (file)
@@ -2633,6 +2633,8 @@ close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_da
                        reply_nterror(req, NT_STATUS_NO_MEMORY);
                        goto out;
                }
+               /* Ensure smb_dname->base_name matches. */
+               smb_dname->base_name = directory;
        }
 
        DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
@@ -2698,7 +2700,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
        ntstatus = dptr_create(conn,
                                req,
                                NULL, /* fsp */
-                               directory,
+                               smb_dname,
                                False,
                                True,
                                req->smbpid,