Revert "s3: Make the implicit reference to Protocol in is_in_path() explicit"
[gd/samba/.git] / source3 / smbd / reply.c
index 750915b1cb4576b2c59f67beba4e8ad5ad421174..a113a9d98261487873ab536da695238cec431073 100644 (file)
@@ -27,8 +27,6 @@
 #include "includes.h"
 #include "smbd/globals.h"
 
-extern enum protocol_types Protocol;
-
 /****************************************************************************
  Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
  path or anything including wildcards.
@@ -65,14 +63,11 @@ static NTSTATUS check_path_syntax_internal(char *path,
                                if (strchr_m(&s[1], ':')) {
                                        return NT_STATUS_OBJECT_NAME_INVALID;
                                }
-                               if (StrCaseCmp(s, ":$DATA") != 0) {
-                                       return NT_STATUS_INVALID_PARAMETER;
-                               }
                                break;
                        }
                }
 
-               if (!posix_path && !stream_started && *s == ':') {
+               if ((*s == ':') && !posix_path && !stream_started) {
                        if (*p_last_component_contains_wcard) {
                                return NT_STATUS_OBJECT_NAME_INVALID;
                        }
@@ -790,7 +785,7 @@ void reply_tcon_and_X(struct smb_request *req)
        else
                server_devicetype = "A:";
 
-       if (Protocol < PROTOCOL_NT1) {
+       if (get_Protocol() < PROTOCOL_NT1) {
                reply_outbuf(req, 2, 0);
                if (message_push_string(&req->outbuf, server_devicetype,
                                        STR_TERMINATE|STR_ASCII) == -1) {
@@ -1144,7 +1139,7 @@ void reply_getatr(struct smb_request *req)
        }
        SIVAL(req->outbuf,smb_vwv3,(uint32)size);
 
-       if (Protocol >= PROTOCOL_NT1) {
+       if (get_Protocol() >= PROTOCOL_NT1) {
                SSVAL(req->outbuf, smb_flg2,
                      SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
        }
@@ -1269,7 +1264,7 @@ void reply_dskattr(struct smb_request *req)
 
        reply_outbuf(req, 5, 0);
 
-       if (Protocol <= PROTOCOL_LANMAN2) {
+       if (get_Protocol() <= PROTOCOL_LANMAN2) {
                double total_space, free_space;
                /* we need to scale this to a number that DOS6 can handle. We
                   use floating point so we can handle large drives on systems
@@ -1366,6 +1361,8 @@ void reply_search(struct smb_request *req)
        bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
        TALLOC_CTX *ctx = talloc_tos();
        bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
+       struct dptr_struct *dirptr = NULL;
+       struct smbd_server_connection *sconn = smbd_server_conn;
 
        START_PROFILE(SMBsearch);
 
@@ -1446,14 +1443,15 @@ void reply_search(struct smb_request *req)
                                        mask,
                                        mask_contains_wcard,
                                        dirtype,
-                                       &conn->dirptr);
+                                       &dirptr);
                if (!NT_STATUS_IS_OK(nt_status)) {
                        reply_nterror(req, nt_status);
                        goto out;
                }
-               dptr_num = dptr_dnum(conn->dirptr);
+               dptr_num = dptr_dnum(dirptr);
        } else {
                int status_dirtype;
+               const char *dirpath;
 
                memcpy(status,p,21);
                status_dirtype = CVAL(status,0) & 0x1F;
@@ -1461,12 +1459,18 @@ void reply_search(struct smb_request *req)
                        dirtype = status_dirtype;
                }
 
-               conn->dirptr = dptr_fetch(status+12,&dptr_num);
-               if (!conn->dirptr) {
+               dirptr = dptr_fetch(sconn, status+12,&dptr_num);
+               if (!dirptr) {
                        goto SearchEmpty;
                }
-               string_set(&conn->dirpath,dptr_path(dptr_num));
-               mask = dptr_wcard(dptr_num);
+               dirpath = dptr_path(sconn, dptr_num);
+               directory = talloc_strdup(ctx, dirpath);
+               if (!directory) {
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                       goto out;
+               }
+
+               mask = dptr_wcard(sconn, dptr_num);
                if (!mask) {
                        goto SearchEmpty;
                }
@@ -1475,13 +1479,13 @@ void reply_search(struct smb_request *req)
                 * check from the initial saved string.
                 */
                mask_contains_wcard = ms_has_wild(mask);
-               dirtype = dptr_attr(dptr_num);
+               dirtype = dptr_attr(sconn, dptr_num);
        }
 
        DEBUG(4,("dptr_num is %d\n",dptr_num));
 
        /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
-       dptr_init_search_op(conn->dirptr);
+       dptr_init_search_op(dirptr);
 
        if ((dirtype&0x1F) == aVOLID) {
                char buf[DIR_STRUCT_SIZE];
@@ -1491,7 +1495,7 @@ void reply_search(struct smb_request *req)
                        reply_nterror(req, NT_STATUS_NO_MEMORY);
                        goto out;
                }
-               dptr_fill(buf+12,dptr_num);
+               dptr_fill(sconn, buf+12,dptr_num);
                if (dptr_zero(buf+12) && (status_len==0)) {
                        numentries = 1;
                } else {
@@ -1512,14 +1516,14 @@ void reply_search(struct smb_request *req)
                         /DIR_STRUCT_SIZE));
 
                DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
-                       conn->dirpath,lp_dontdescend(SNUM(conn))));
-               if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
+                       directory,lp_dontdescend(SNUM(conn))));
+               if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
                        check_descend = True;
                }
 
                for (i=numentries;(i<maxentries) && !finished;i++) {
                        finished = !get_dir_entry(ctx,
-                                                 conn,
+                                                 dirptr,
                                                  mask,
                                                  dirtype,
                                                  &fname,
@@ -1542,7 +1546,7 @@ void reply_search(struct smb_request *req)
                                        reply_nterror(req, NT_STATUS_NO_MEMORY);
                                        goto out;
                                }
-                               if (!dptr_fill(buf+12,dptr_num)) {
+                               if (!dptr_fill(sconn, buf+12,dptr_num)) {
                                        break;
                                }
                                if (message_push_blob(&req->outbuf,
@@ -1563,15 +1567,15 @@ void reply_search(struct smb_request *req)
                (X/Open spec) */
 
        if (numentries == 0) {
-               dptr_close(&dptr_num);
+               dptr_close(sconn, &dptr_num);
        } else if(expect_close && status_len == 0) {
                /* Close the dptr - we know it's gone */
-               dptr_close(&dptr_num);
+               dptr_close(sconn, &dptr_num);
        }
 
        /* If we were called as SMBfunique, then we can close the dirptr now ! */
        if(dptr_num >= 0 && req->cmd == SMBfunique) {
-               dptr_close(&dptr_num);
+               dptr_close(sconn, &dptr_num);
        }
 
        if ((numentries == 0) && !mask_contains_wcard) {
@@ -1597,18 +1601,15 @@ void reply_search(struct smb_request *req)
        SSVAL(req->outbuf, smb_flg2,
              (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
 
-       if (!directory) {
-               directory = dptr_path(dptr_num);
-       }
-
        DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
                smb_fn_name(req->cmd),
                mask,
-               directory ? directory : "./",
+               directory,
                dirtype,
                numentries,
                maxentries ));
  out:
+       TALLOC_FREE(directory);
        TALLOC_FREE(smb_fname);
        END_PROFILE(SMBsearch);
        return;
@@ -1628,6 +1629,7 @@ void reply_fclose(struct smb_request *req)
        NTSTATUS err;
        bool path_contains_wcard = False;
        TALLOC_CTX *ctx = talloc_tos();
+       struct smbd_server_connection *sconn = smbd_server_conn;
 
        START_PROFILE(SMBfclose);
 
@@ -1657,9 +1659,9 @@ void reply_fclose(struct smb_request *req)
 
        memcpy(status,p,21);
 
-       if(dptr_fetch(status+12,&dptr_num)) {
+       if(dptr_fetch(sconn, status+12,&dptr_num)) {
                /*  Close the dptr - we know it's gone */
-               dptr_close(&dptr_num);
+               dptr_close(sconn, &dptr_num);
        }
 
        reply_outbuf(req, 1, 0);
@@ -2332,7 +2334,7 @@ void reply_ctemp(struct smb_request *req)
 ********************************************************************/
 
 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
-                          uint16 dirtype, SMB_STRUCT_STAT *pst)
+                       uint16 dirtype)
 {
        uint32 fmode;
 
@@ -2345,7 +2347,7 @@ static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
                return NT_STATUS_NO_SUCH_FILE;
        }
 
-       if (S_ISDIR(pst->st_ex_mode)) {
+       if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
                if (fsp->posix_open) {
                        return NT_STATUS_OK;
                }
@@ -2379,6 +2381,8 @@ static NTSTATUS do_unlink(connection_struct *conn,
        files_struct *fsp;
        uint32 dirtype_orig = dirtype;
        NTSTATUS status;
+       int ret;
+       bool posix_paths = lp_posix_pathnames();
 
        DEBUG(10,("do_unlink: %s, dirtype = %d\n",
                  smb_fname_str_dbg(smb_fname),
@@ -2388,7 +2392,12 @@ static NTSTATUS do_unlink(connection_struct *conn,
                return NT_STATUS_MEDIA_WRITE_PROTECTED;
        }
 
-       if (SMB_VFS_LSTAT(conn, smb_fname) != 0) {
+       if (posix_paths) {
+               ret = SMB_VFS_LSTAT(conn, smb_fname);
+       } else {
+               ret = SMB_VFS_LSTAT(conn, smb_fname);
+       }
+       if (ret != 0) {
                return map_nt_error_from_unix(errno);
        }
 
@@ -2475,7 +2484,9 @@ static NTSTATUS do_unlink(connection_struct *conn,
                 FILE_SHARE_NONE,       /* share_access */
                 FILE_OPEN,             /* create_disposition*/
                 FILE_NON_DIRECTORY_FILE, /* create_options */
-                FILE_ATTRIBUTE_NORMAL, /* file_attributes */
+                                       /* file_attributes */
+                posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
+                               FILE_ATTRIBUTE_NORMAL,
                 0,                     /* oplock_request */
                 0,                     /* allocation_size */
                 NULL,                  /* sd */
@@ -2573,7 +2584,8 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
        } else {
                struct smb_Dir *dir_hnd = NULL;
                long offset = 0;
-               const char *dname;
+               const char *dname = NULL;
+               char *talloced = NULL;
 
                if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
                        status = NT_STATUS_OBJECT_NAME_INVALID;
@@ -2609,24 +2621,27 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
                status = NT_STATUS_NO_SUCH_FILE;
 
                while ((dname = ReadDirName(dir_hnd, &offset,
-                                           &smb_fname->st))) {
+                                           &smb_fname->st, &talloced))) {
                        TALLOC_CTX *frame = talloc_stackframe();
 
                        if (!is_visible_file(conn, fname_dir, dname,
                                             &smb_fname->st, true)) {
                                TALLOC_FREE(frame);
+                               TALLOC_FREE(talloced);
                                continue;
                        }
 
                        /* Quick check for "." and ".." */
                        if (ISDOT(dname) || ISDOTDOT(dname)) {
                                TALLOC_FREE(frame);
+                               TALLOC_FREE(talloced);
                                continue;
                        }
 
-                       if(!mask_match(dname, fname_mask,
+                       if(!mask_match(dname, fname_mask, get_Protocol(),
                                       conn->case_sensitive)) {
                                TALLOC_FREE(frame);
+                               TALLOC_FREE(talloced);
                                continue;
                        }
 
@@ -2639,6 +2654,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
                                TALLOC_FREE(dir_hnd);
                                status = NT_STATUS_NO_MEMORY;
                                TALLOC_FREE(frame);
+                               TALLOC_FREE(talloced);
                                goto out;
                        }
 
@@ -2646,12 +2662,14 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
                        if (!NT_STATUS_IS_OK(status)) {
                                TALLOC_FREE(dir_hnd);
                                TALLOC_FREE(frame);
+                               TALLOC_FREE(talloced);
                                goto out;
                        }
 
                        status = do_unlink(conn, req, smb_fname, dirtype);
                        if (!NT_STATUS_IS_OK(status)) {
                                TALLOC_FREE(frame);
+                               TALLOC_FREE(talloced);
                                continue;
                        }
 
@@ -2660,6 +2678,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
                                 smb_fname->base_name));
 
                        TALLOC_FREE(frame);
+                       TALLOC_FREE(talloced);
                }
                TALLOC_FREE(dir_hnd);
        }
@@ -3009,7 +3028,6 @@ void reply_readbraw(struct smb_request *req)
        SMB_OFF_T startpos;
        files_struct *fsp;
        struct lock_struct lock;
-       SMB_STRUCT_STAT st;
        SMB_OFF_T size = 0;
 
        START_PROFILE(SMBreadbraw);
@@ -3101,7 +3119,7 @@ void reply_readbraw(struct smb_request *req)
                        reply_readbraw_error();
                        END_PROFILE(SMBreadbraw);
                        return;
-               }      
+               }
        }
 
        maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
@@ -3120,8 +3138,8 @@ void reply_readbraw(struct smb_request *req)
                return;
        }
 
-       if (SMB_VFS_FSTAT(fsp, &st) == 0) {
-               size = st.st_ex_size;
+       if (fsp_stat(fsp) == 0) {
+               size = fsp->fsp_name->st.st_ex_size;
        }
 
        if (startpos >= size) {
@@ -3396,12 +3414,11 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
                            files_struct *fsp, SMB_OFF_T startpos,
                            size_t smb_maxcnt)
 {
-       SMB_STRUCT_STAT sbuf;
        ssize_t nread = -1;
        struct lock_struct lock;
        int saved_errno = 0;
 
-       if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
+       if(fsp_stat(fsp) == -1) {
                reply_nterror(req, map_nt_error_from_unix(errno));
                return;
        }
@@ -3415,8 +3432,9 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
                return;
        }
 
-       if (!S_ISREG(sbuf.st_ex_mode) || (startpos > sbuf.st_ex_size)
-           || (smb_maxcnt > (sbuf.st_ex_size - startpos))) {
+       if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
+                       (startpos > fsp->fsp_name->st.st_ex_size)
+                       || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
                /*
                 * We already know that we would do a short read, so don't
                 * try the sendfile() path.
@@ -3755,7 +3773,7 @@ void reply_writebraw(struct smb_request *req)
        /* We have to deal with slightly different formats depending
                on whether we are using the core+ or lanman1.0 protocol */
 
-       if(Protocol <= PROTOCOL_COREPLUS) {
+       if(get_Protocol() <= PROTOCOL_COREPLUS) {
                numtowrite = SVAL(smb_buf(req->inbuf),-2);
                data = smb_buf(req->inbuf);
        } else {
@@ -3811,7 +3829,7 @@ void reply_writebraw(struct smb_request *req)
         * it to send more bytes */
 
        memcpy(buf, req->inbuf, smb_size);
-       srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
+       srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
        SCVAL(buf,smb_com,SMBwritebraw);
        SSVALS(buf,smb_vwv0,0xFFFF);
        show_msg(buf);
@@ -4481,16 +4499,15 @@ void reply_lseek(struct smb_request *req)
                if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
                        if(errno == EINVAL) {
                                SMB_OFF_T current_pos = startpos;
-                               SMB_STRUCT_STAT sbuf;
 
-                               if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
+                               if(fsp_stat(fsp) == -1) {
                                        reply_nterror(req,
                                                map_nt_error_from_unix(errno));
                                        END_PROFILE(SMBlseek);
                                        return;
                                }
 
-                               current_pos += sbuf.st_ex_size;
+                               current_pos += fsp->fsp_name->st.st_ex_size;
                                if(current_pos < 0)
                                        res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
                        }
@@ -4962,7 +4979,6 @@ void reply_printopen(struct smb_request *req)
 {
        connection_struct *conn = req->conn;
        files_struct *fsp;
-       SMB_STRUCT_STAT sbuf;
        NTSTATUS status;
 
        START_PROFILE(SMBsplopen);
@@ -4987,7 +5003,7 @@ void reply_printopen(struct smb_request *req)
        }
 
        /* Open for exclusive use, write only. */
-       status = print_fsp_open(req, conn, NULL, req->vuid, fsp, &sbuf);
+       status = print_fsp_open(req, conn, NULL, req->vuid, fsp);
 
        if (!NT_STATUS_IS_OK(status)) {
                file_free(req, fsp);
@@ -5284,6 +5300,7 @@ static bool recursive_rmdir(TALLOC_CTX *ctx,
                        struct smb_filename *smb_dname)
 {
        const char *dname = NULL;
+       char *talloced = NULL;
        bool ret = True;
        long offset = 0;
        SMB_STRUCT_STAT st;
@@ -5295,18 +5312,20 @@ static bool recursive_rmdir(TALLOC_CTX *ctx,
        if(dir_hnd == NULL)
                return False;
 
-       while((dname = ReadDirName(dir_hnd, &offset, &st))) {
+       while((dname = ReadDirName(dir_hnd, &offset, &st, &talloced))) {
                struct smb_filename *smb_dname_full = NULL;
                char *fullname = NULL;
                bool do_break = true;
                NTSTATUS status;
 
                if (ISDOT(dname) || ISDOTDOT(dname)) {
+                       TALLOC_FREE(talloced);
                        continue;
                }
 
                if (!is_visible_file(conn, smb_dname->base_name, dname, &st,
                                     false)) {
+                       TALLOC_FREE(talloced);
                        continue;
                }
 
@@ -5349,6 +5368,7 @@ static bool recursive_rmdir(TALLOC_CTX *ctx,
         err_break:
                TALLOC_FREE(smb_dname_full);
                TALLOC_FREE(fullname);
+               TALLOC_FREE(talloced);
                if (do_break) {
                        ret = false;
                        break;
@@ -5367,7 +5387,6 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
                         struct smb_filename *smb_dname)
 {
        int ret;
-       SMB_STRUCT_STAT st;
 
        SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
 
@@ -5402,7 +5421,9 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
                 * retry. If we fail to delete any of them (and we *don't*
                 * do a recursive delete) then fail the rmdir.
                 */
-               const char *dname;
+               SMB_STRUCT_STAT st;
+               const char *dname = NULL;
+               char *talloced = NULL;
                long dirpos = 0;
                struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
                                                  smb_dname->base_name, NULL,
@@ -5413,17 +5434,24 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
                        goto err;
                }
 
-               while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
-                       if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
+               while ((dname = ReadDirName(dir_hnd, &dirpos, &st,
+                                           &talloced)) != NULL) {
+                       if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) {
+                               TALLOC_FREE(talloced);
                                continue;
+                       }
                        if (!is_visible_file(conn, smb_dname->base_name, dname,
-                                            &st, false))
+                                            &st, false)) {
+                               TALLOC_FREE(talloced);
                                continue;
+                       }
                        if(!IS_VETO_PATH(conn, dname)) {
                                TALLOC_FREE(dir_hnd);
+                               TALLOC_FREE(talloced);
                                errno = ENOTEMPTY;
                                goto err;
                        }
+                       TALLOC_FREE(talloced);
                }
 
                /* We only have veto files/directories.
@@ -5437,17 +5465,20 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
 
                /* Do a recursive delete. */
                RewindDir(dir_hnd,&dirpos);
-               while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
+               while ((dname = ReadDirName(dir_hnd, &dirpos, &st,
+                                           &talloced)) != NULL) {
                        struct smb_filename *smb_dname_full = NULL;
                        char *fullname = NULL;
                        bool do_break = true;
                        NTSTATUS status;
 
                        if (ISDOT(dname) || ISDOTDOT(dname)) {
+                               TALLOC_FREE(talloced);
                                continue;
                        }
                        if (!is_visible_file(conn, smb_dname->base_name, dname,
                                             &st, false)) {
+                               TALLOC_FREE(talloced);
                                continue;
                        }
 
@@ -5492,6 +5523,7 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
                 err_break:
                        TALLOC_FREE(fullname);
                        TALLOC_FREE(smb_dname_full);
+                       TALLOC_FREE(talloced);
                        if (do_break)
                                break;
                }
@@ -5527,6 +5559,7 @@ void reply_rmdir(struct smb_request *req)
        char *directory = NULL;
        NTSTATUS status;
        TALLOC_CTX *ctx = talloc_tos();
+       struct smbd_server_connection *sconn = smbd_server_conn;
 
        START_PROFILE(SMBrmdir);
 
@@ -5558,7 +5591,7 @@ void reply_rmdir(struct smb_request *req)
                goto out;
        }
 
-       dptr_closepath(smb_dname->base_name, req->smbpid);
+       dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
        status = rmdir_internals(ctx, conn, smb_dname);
        if (!NT_STATUS_IS_OK(status)) {
                reply_nterror(req, status);
@@ -5836,25 +5869,17 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
                        bool replace_if_exists)
 {
        TALLOC_CTX *ctx = talloc_tos();
-       struct smb_filename *smb_fname_src = NULL;
        struct smb_filename *smb_fname_dst = NULL;
-       SMB_STRUCT_STAT sbuf;
        NTSTATUS status = NT_STATUS_OK;
        struct share_mode_lock *lck = NULL;
        bool dst_exists, old_is_stream, new_is_stream;
 
-       ZERO_STRUCT(sbuf);
-
        status = check_name(conn, smb_fname_dst_in->base_name);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
-       /* Make a copy of the src and dst smb_fname structs */
-       status = copy_smb_filename(ctx, fsp->fsp_name, &smb_fname_src);
-       if (!NT_STATUS_IS_OK(status)) {
-               goto out;
-       }
+       /* Make a copy of the dst smb_fname structs */
 
        status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
        if (!NT_STATUS_IS_OK(status)) {
@@ -5882,8 +5907,8 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
         * filename).
         */
        if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
-           strequal(smb_fname_src->base_name, smb_fname_dst->base_name) &&
-           strequal(smb_fname_src->stream_name, smb_fname_dst->stream_name)) {
+           strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
+           strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
                char *last_slash;
                char *fname_dst_lcomp_base_mod = NULL;
                struct smb_filename *smb_fname_orig_lcomp = NULL;
@@ -5960,8 +5985,8 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
         * don't do the rename, just return success.
         */
 
-       if (strcsequal(smb_fname_src->base_name, smb_fname_dst->base_name) &&
-           strcsequal(smb_fname_src->stream_name,
+       if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
+           strcsequal(fsp->fsp_name->stream_name,
                       smb_fname_dst->stream_name)) {
                DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
                          "- returning success\n",
@@ -5970,7 +5995,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
                goto out;
        }
 
-       old_is_stream = is_ntfs_stream_smb_fname(smb_fname_src);
+       old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
        new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
 
        /* Return the correct error code if both names aren't streams. */
@@ -5988,7 +6013,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
 
        if(!replace_if_exists && dst_exists) {
                DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
-                         "%s -> %s\n", smb_fname_str_dbg(smb_fname_src),
+                         "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
                          smb_fname_str_dbg(smb_fname_dst)));
                status = NT_STATUS_OBJECT_NAME_COLLISION;
                goto out;
@@ -6007,38 +6032,23 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
        }
 
        /* Ensure we have a valid stat struct for the source. */
-       if (fsp->fh->fd != -1) {
-               if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
-                       status = map_nt_error_from_unix(errno);
-                       goto out;
-               }
-       } else {
-               int ret = -1;
-               if (fsp->posix_open) {
-                       ret = SMB_VFS_LSTAT(conn, smb_fname_src);
-               } else {
-
-                       ret = SMB_VFS_STAT(conn, smb_fname_src);
-               }
-               if (ret == -1) {
-                       status = map_nt_error_from_unix(errno);
-                       goto out;
-               }
-               sbuf = smb_fname_src->st;
+       status = vfs_stat_fsp(fsp);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto out;
        }
 
-       status = can_rename(conn, fsp, attrs, &sbuf);
+       status = can_rename(conn, fsp, attrs);
 
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
-                         nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
+                         nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
                          smb_fname_str_dbg(smb_fname_dst)));
                if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
                        status = NT_STATUS_ACCESS_DENIED;
                goto out;
        }
 
-       if (rename_path_prefix_equal(smb_fname_src, smb_fname_dst)) {
+       if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
                status = NT_STATUS_ACCESS_DENIED;
        }
 
@@ -6052,14 +6062,14 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
 
        SMB_ASSERT(lck != NULL);
 
-       if(SMB_VFS_RENAME(conn, smb_fname_src, smb_fname_dst) == 0) {
+       if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
                uint32 create_options = fsp->fh->private_options;
 
                DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
-                         "%s -> %s\n", smb_fname_str_dbg(smb_fname_src),
+                         "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
                          smb_fname_str_dbg(smb_fname_dst)));
 
-               notify_rename(conn, fsp->is_directory, smb_fname_src,
+               notify_rename(conn, fsp->is_directory, fsp->fsp_name,
                              smb_fname_dst);
 
                rename_open_files(conn, lck, smb_fname_dst);
@@ -6096,11 +6106,10 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
        }
 
        DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
-                 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
+                 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
                  smb_fname_str_dbg(smb_fname_dst)));
 
  out:
-       TALLOC_FREE(smb_fname_src);
        TALLOC_FREE(smb_fname_dst);
 
        return status;
@@ -6127,7 +6136,8 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
        int count=0;
        NTSTATUS status = NT_STATUS_OK;
        struct smb_Dir *dir_hnd = NULL;
-       const char *dname;
+       const char *dname = NULL;
+       char *talloced = NULL;
        long offset = 0;
        int create_options = 0;
        bool posix_pathnames = lp_posix_pathnames();
@@ -6305,7 +6315,8 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
         * - gentest fix. JRA
         */
 
-       while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st))) {
+       while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
+                                   &talloced))) {
                files_struct *fsp = NULL;
                char *destname = NULL;
                bool sysdir_entry = False;
@@ -6315,16 +6326,20 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
                        if (attrs & aDIR) {
                                sysdir_entry = True;
                        } else {
+                               TALLOC_FREE(talloced);
                                continue;
                        }
                }
 
                if (!is_visible_file(conn, fname_src_dir, dname,
                                     &smb_fname_src->st, false)) {
+                       TALLOC_FREE(talloced);
                        continue;
                }
 
-               if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
+               if(!mask_match(dname, fname_src_mask, get_Protocol(),
+                              conn->case_sensitive)) {
+                       TALLOC_FREE(talloced);
                        continue;
                }
 
@@ -6348,6 +6363,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
                                       &destname)) {
                        DEBUG(6, ("resolve_wildcards %s %s failed\n",
                                  smb_fname_src->base_name, destname));
+                       TALLOC_FREE(talloced);
                        continue;
                }
                if (!destname) {
@@ -6423,7 +6439,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
                DEBUG(3,("rename_internals: doing rename on %s -> "
                         "%s\n", smb_fname_str_dbg(smb_fname_src),
                         smb_fname_str_dbg(smb_fname_src)));
-
+               TALLOC_FREE(talloced);
        }
        TALLOC_FREE(dir_hnd);
 
@@ -6432,6 +6448,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
        }
 
  out:
+       TALLOC_FREE(talloced);
        TALLOC_FREE(fname_src_dir);
        TALLOC_FREE(fname_src_mask);
        return status;
@@ -6897,6 +6914,7 @@ void reply_copy(struct smb_request *req)
        } else {
                struct smb_Dir *dir_hnd = NULL;
                const char *dname = NULL;
+               char *talloced = NULL;
                long offset = 0;
 
                /*
@@ -6937,20 +6955,23 @@ void reply_copy(struct smb_request *req)
 
                /* Iterate over the src dir copying each entry to the dst. */
                while ((dname = ReadDirName(dir_hnd, &offset,
-                                           &smb_fname_src->st))) {
+                                           &smb_fname_src->st, &talloced))) {
                        char *destname = NULL;
 
                        if (ISDOT(dname) || ISDOTDOT(dname)) {
+                               TALLOC_FREE(talloced);
                                continue;
                        }
 
                        if (!is_visible_file(conn, fname_src_dir, dname,
                                             &smb_fname_src->st, false)) {
+                               TALLOC_FREE(talloced);
                                continue;
                        }
 
-                       if(!mask_match(dname, fname_src_mask,
+                       if(!mask_match(dname, fname_src_mask, get_Protocol(),
                                       conn->case_sensitive)) {
+                               TALLOC_FREE(talloced);
                                continue;
                        }
 
@@ -6964,6 +6985,7 @@ void reply_copy(struct smb_request *req)
 
                        if (!smb_fname_src->base_name) {
                                TALLOC_FREE(dir_hnd);
+                               TALLOC_FREE(talloced);
                                reply_nterror(req, NT_STATUS_NO_MEMORY);
                                goto out;
                        }
@@ -6971,10 +6993,12 @@ void reply_copy(struct smb_request *req)
                        if (!resolve_wildcards(ctx, smb_fname_src->base_name,
                                               smb_fname_dst->base_name,
                                               &destname)) {
+                               TALLOC_FREE(talloced);
                                continue;
                        }
                        if (!destname) {
                                TALLOC_FREE(dir_hnd);
+                               TALLOC_FREE(talloced);
                                reply_nterror(req, NT_STATUS_NO_MEMORY);
                                goto out;
                        }
@@ -6985,6 +7009,7 @@ void reply_copy(struct smb_request *req)
                        status = check_name(conn, smb_fname_src->base_name);
                        if (!NT_STATUS_IS_OK(status)) {
                                TALLOC_FREE(dir_hnd);
+                               TALLOC_FREE(talloced);
                                reply_nterror(req, status);
                                goto out;
                        }
@@ -6992,6 +7017,7 @@ void reply_copy(struct smb_request *req)
                        status = check_name(conn, smb_fname_dst->base_name);
                        if (!NT_STATUS_IS_OK(status)) {
                                TALLOC_FREE(dir_hnd);
+                               TALLOC_FREE(talloced);
                                reply_nterror(req, status);
                                goto out;
                        }
@@ -7006,6 +7032,8 @@ void reply_copy(struct smb_request *req)
                        if (NT_STATUS_IS_OK(status)) {
                                count++;
                        }
+
+                       TALLOC_FREE(talloced);
                }
                TALLOC_FREE(dir_hnd);
        }
@@ -7668,25 +7696,10 @@ void reply_setattrE(struct smb_request *req)
         */
 
        /* Ensure we have a valid stat struct for the source. */
-       if (fsp->fh->fd != -1) {
-               if (SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) == -1) {
-                       status = map_nt_error_from_unix(errno);
-                       reply_nterror(req, status);
-                       goto out;
-               }
-       } else {
-               int ret = -1;
-
-               if (fsp->posix_open) {
-                       ret = SMB_VFS_LSTAT(conn, fsp->fsp_name);
-               } else {
-                       ret = SMB_VFS_STAT(conn, fsp->fsp_name);
-               }
-               if (ret == -1) {
-                       status = map_nt_error_from_unix(errno);
-                       reply_nterror(req, status);
-                       goto out;
-               }
+       status = vfs_stat_fsp(fsp);
+       if (!NT_STATUS_IS_OK(status)) {
+               reply_nterror(req, status);
+               goto out;
        }
 
        status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
@@ -7745,7 +7758,6 @@ void reply_writebs(struct smb_request *req)
 void reply_getattrE(struct smb_request *req)
 {
        connection_struct *conn = req->conn;
-       SMB_STRUCT_STAT sbuf;
        int mode;
        files_struct *fsp;
        struct timespec create_ts;
@@ -7767,14 +7779,12 @@ void reply_getattrE(struct smb_request *req)
        }
 
        /* Do an fstat on this file */
-       if(fsp_stat(fsp, &sbuf)) {
+       if(fsp_stat(fsp)) {
                reply_nterror(req, map_nt_error_from_unix(errno));
                END_PROFILE(SMBgetattrE);
                return;
        }
 
-       fsp->fsp_name->st = sbuf;
-
        mode = dos_mode(conn, fsp->fsp_name);
 
        /*
@@ -7785,20 +7795,20 @@ void reply_getattrE(struct smb_request *req)
 
        reply_outbuf(req, 11, 0);
 
-       create_ts = sbuf.st_ex_btime;
+       create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
        srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
        srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
-                         convert_timespec_to_time_t(sbuf.st_ex_atime));
+                         convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
        /* Should we check pending modtime here ? JRA */
        srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
-                         convert_timespec_to_time_t(sbuf.st_ex_mtime));
+                         convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
 
        if (mode & aDIR) {
                SIVAL(req->outbuf, smb_vwv6, 0);
                SIVAL(req->outbuf, smb_vwv8, 0);
        } else {
-               uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &sbuf);
-               SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_ex_size);
+               uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
+               SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
                SIVAL(req->outbuf, smb_vwv8, allocation_size);
        }
        SSVAL(req->outbuf,smb_vwv10, mode);