s3: Convert some callers of vfs_stat_smb_fname to SMB_VFS_STAT()
[samba.git] / source3 / smbd / trans2.c
index 085a0b2acb8610237fd1f7f29f1e56ba27908fea..856fd9432d072cc924b6eddffe6815a9e9b13692 100644 (file)
@@ -471,17 +471,13 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
                const struct smb_filename *smb_fname, struct ea_list *ea_list)
 {
        char *fname = NULL;
-       NTSTATUS status;
 
        if (!lp_ea_support(SNUM(conn))) {
                return NT_STATUS_EAS_NOT_SUPPORTED;
        }
 
-       status = get_full_smb_filename(talloc_tos(), smb_fname,
-                                      &fname);
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
+       /* For now setting EAs on streams isn't supported. */
+       fname = smb_fname->base_name;
 
        for (;ea_list; ea_list = ea_list->next) {
                int ret;
@@ -502,8 +498,9 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
                if (ea_list->ea.value.length == 0) {
                        /* Remove the attribute. */
                        if (fsp && (fsp->fh->fd != -1)) {
-                               DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
-                                       unix_ea_name, fsp->fsp_name));
+                               DEBUG(10,("set_ea: deleting ea name %s on "
+                                         "file %s by file descriptor.\n",
+                                         unix_ea_name, fsp_str_dbg(fsp)));
                                ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
                        } else {
                                DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
@@ -520,8 +517,9 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
 #endif
                } else {
                        if (fsp && (fsp->fh->fd != -1)) {
-                               DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
-                                       unix_ea_name, fsp->fsp_name));
+                               DEBUG(10,("set_ea: setting ea name %s on file "
+                                         "%s by file descriptor.\n",
+                                         unix_ea_name, fsp_str_dbg(fsp)));
                                ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
                                                        ea_list->ea.value.data, ea_list->ea.value.length, 0);
                        } else {
@@ -1026,8 +1024,7 @@ static void call_trans2open(connection_struct *conn,
                                conn,
                                req->flags2 & FLAGS2_DFS_PATHNAMES,
                                fname,
-                               &smb_fname,
-                               NULL);
+                               &smb_fname);
        if (!NT_STATUS_IS_OK(status)) {
                if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
                        reply_botherror(req,
@@ -1044,12 +1041,10 @@ static void call_trans2open(connection_struct *conn,
                goto out;
        }
 
-       if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
-                               open_ofun,
-                               &access_mask,
-                               &share_mode,
-                               &create_disposition,
-                               &create_options)) {
+       if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
+                                        &access_mask, &share_mode,
+                                        &create_disposition,
+                                        &create_options)) {
                reply_doserror(req, ERRDOS, ERRbadaccess);
                goto out;
        }
@@ -1148,7 +1143,8 @@ static void call_trans2open(connection_struct *conn,
        SIVAL(params,20,inode);
        SSVAL(params,24,0); /* Padding. */
        if (flags & 8) {
-               uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
+               uint32 ea_size = estimate_ea_size(conn, fsp,
+                                                 fsp->fsp_name->base_name);
                SIVAL(params, 26, ea_size);
        } else {
                SIVAL(params, 26, 0);
@@ -2039,7 +2035,7 @@ static void call_trans2findfirst(connection_struct *conn,
 
        if (total_params < 13) {
                reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-               return;
+               goto out;
        }
 
        dirtype = SVAL(params,0);
@@ -2077,12 +2073,12 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
                        ask_sharemode = false;
                        if (!lp_unix_extensions()) {
                                reply_nterror(req, NT_STATUS_INVALID_LEVEL);
-                               return;
+                               goto out;
                        }
                        break;
                default:
                        reply_nterror(req, NT_STATUS_INVALID_LEVEL);
-                       return;
+                       goto out;
        }
 
        srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
@@ -2090,7 +2086,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
                              STR_TERMINATE, &ntstatus, &mask_contains_wcard);
        if (!NT_STATUS_IS_OK(ntstatus)) {
                reply_nterror(req, ntstatus);
-               return;
+               goto out;
        }
 
        ntstatus = resolve_dfspath_wcard(ctx, conn,
@@ -2102,32 +2098,27 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
                if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
                        reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
                                        ERRSRV, ERRbadpath);
-                       return;
+                       goto out;
                }
                reply_nterror(req, ntstatus);
-               return;
+               goto out;
        }
 
        ntstatus = unix_convert(ctx, conn, directory, &smb_dname,
                                (UCF_SAVE_LCOMP | UCF_ALLOW_WCARD_LCOMP));
        if (!NT_STATUS_IS_OK(ntstatus)) {
                reply_nterror(req, ntstatus);
-               return;
+               goto out;
        }
 
        mask = smb_dname->original_lcomp;
 
-       ntstatus = get_full_smb_filename(ctx, smb_dname, &directory);
-       TALLOC_FREE(smb_dname);
-       if (!NT_STATUS_IS_OK(ntstatus)) {
-               reply_nterror(req, ntstatus);
-               return;
-       }
+       directory = smb_dname->base_name;
 
        ntstatus = check_name(conn, directory);
        if (!NT_STATUS_IS_OK(ntstatus)) {
                reply_nterror(req, ntstatus);
-               return;
+               goto out;
        }
 
        p = strrchr_m(directory,'/');
@@ -2137,14 +2128,14 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
                        mask = talloc_strdup(ctx,"*");
                        if (!mask) {
                                reply_nterror(req, NT_STATUS_NO_MEMORY);
-                               return;
+                               goto out;
                        }
                        mask_contains_wcard = True;
                }
                directory = talloc_strdup(talloc_tos(), "./");
                if (!directory) {
                        reply_nterror(req, NT_STATUS_NO_MEMORY);
-                       return;
+                       goto out;
                }
        } else {
                *p = 0;
@@ -2157,7 +2148,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
 
                if (total_data < 4) {
                        reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-                       return;
+                       goto out;
                }
 
                ea_size = IVAL(pdata,0);
@@ -2165,19 +2156,19 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
                        DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
                        reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-                       return;
+                       goto out;
                }
 
                if (!lp_ea_support(SNUM(conn))) {
                        reply_doserror(req, ERRDOS, ERReasnotsupported);
-                       return;
+                       goto out;
                }
 
                /* Pull out the list of names. */
                ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
                if (!ea_list) {
                        reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-                       return;
+                       goto out;
                }
        }
 
@@ -2185,7 +2176,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
        if(*ppdata == NULL ) {
                reply_nterror(req, NT_STATUS_NO_MEMORY);
-               return;
+               goto out;
        }
        pdata = *ppdata;
        data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
@@ -2194,7 +2185,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
        *pparams = (char *)SMB_REALLOC(*pparams, 10);
        if (*pparams == NULL) {
                reply_nterror(req, NT_STATUS_NO_MEMORY);
-               return;
+               goto out;
        }
        params = *pparams;
 
@@ -2213,7 +2204,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 
        if (!NT_STATUS_IS_OK(ntstatus)) {
                reply_nterror(req, ntstatus);
-               return;
+               goto out;
        }
 
        dptr_num = dptr_dnum(conn->dirptr);
@@ -2296,11 +2287,11 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                dptr_close(&dptr_num);
                if (Protocol < PROTOCOL_NT1) {
                        reply_doserror(req, ERRDOS, ERRnofiles);
-                       return;
+                       goto out;
                } else {
                        reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
                                        ERRDOS, ERRbadfile);
-                       return;
+                       goto out;
                }
        }
 
@@ -2339,7 +2330,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                char mangled_name[13];
                name_to_8_3(mask, mangled_name, True, conn->params);
        }
-
+ out:
+       TALLOC_FREE(smb_dname);
        return;
 }
 
@@ -2687,67 +2679,54 @@ static void samba_extended_info_version(struct smb_extended_info *extended_info)
                  "%s", samba_version_string());
 }
 
-/****************************************************************************
- Reply to a TRANS2_QFSINFO (query filesystem info).
-****************************************************************************/
-
-static void call_trans2qfsinfo(connection_struct *conn,
-                              struct smb_request *req,
-                              char **pparams, int total_params,
-                              char **ppdata, int total_data,
-                              unsigned int max_data_bytes)
+NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
+                        TALLOC_CTX *mem_ctx,
+                        uint16_t info_level,
+                        uint16_t flags2,
+                        unsigned int max_data_bytes,
+                        char **ppdata,
+                        int *ret_data_len)
 {
        char *pdata, *end_data;
-       char *params = *pparams;
-       uint16 info_level;
-       int data_len, len;
-       SMB_STRUCT_STAT st;
+       int data_len = 0, len;
        const char *vname = volume_label(SNUM(conn));
        int snum = SNUM(conn);
        char *fstype = lp_fstype(SNUM(conn));
        uint32 additional_flags = 0;
-
-       if (total_params < 2) {
-               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-               return;
-       }
-
-       info_level = SVAL(params,0);
+       struct smb_filename *smb_fname_dot = NULL;
+       SMB_STRUCT_STAT st;
+       NTSTATUS status;
 
        if (IS_IPC(conn)) {
                if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
-                       DEBUG(0,("call_trans2qfsinfo: not an allowed "
+                       DEBUG(0,("smbd_do_qfsinfo: not an allowed "
                                "info level (0x%x) on IPC$.\n",
                                (unsigned int)info_level));
-                       reply_nterror(req, NT_STATUS_ACCESS_DENIED);
-                       return;
+                       return NT_STATUS_ACCESS_DENIED;
                }
        }
 
-       if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
-               if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
-                       DEBUG(0,("call_trans2qfsinfo: encryption required "
-                               "and info level 0x%x sent.\n",
-                               (unsigned int)info_level));
-                       exit_server_cleanly("encryption required "
-                               "on connection");
-                       return;
-               }
-       }
+       DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
 
-       DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
+       status = create_synthetic_smb_fname(talloc_tos(), ".", NULL, NULL,
+                                           &smb_fname_dot);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
 
-       if(vfs_stat_smb_fname(conn,".",&st)!=0) {
-               DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
-               reply_doserror(req, ERRSRV, ERRinvdevice);
-               return;
+       if(SMB_VFS_STAT(conn, smb_fname_dot) != 0) {
+               DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
+               TALLOC_FREE(smb_fname_dot);
+               return map_nt_error_from_unix(errno);
        }
 
+       st = smb_fname_dot->st;
+       TALLOC_FREE(smb_fname_dot);
+
        *ppdata = (char *)SMB_REALLOC(
                *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
-       if (*ppdata == NULL ) {
-               reply_nterror(req, NT_STATUS_NO_MEMORY);
-               return;
+       if (*ppdata == NULL) {
+               return NT_STATUS_NO_MEMORY;
        }
 
        pdata = *ppdata;
@@ -2760,8 +2739,7 @@ static void call_trans2qfsinfo(connection_struct *conn,
                        uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
                        data_len = 18;
                        if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
-                               reply_nterror(req, map_nt_error_from_unix(errno));
-                               return;
+                               return map_nt_error_from_unix(errno);
                        }
 
                        block_size = lp_block_size(snum);
@@ -2780,7 +2758,7 @@ static void call_trans2qfsinfo(connection_struct *conn,
                        bytes_per_sector = 512;
                        sectors_per_unit = bsize/bytes_per_sector;
 
-                       DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
+                       DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
                                (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
 
@@ -2806,13 +2784,13 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
                         * the pushed string. The change here was adding the STR_TERMINATE. JRA.
                         */
                        len = srvstr_push(
-                               pdata, req->flags2,
+                               pdata, flags2,
                                pdata+l2_vol_szVolLabel, vname,
                                PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
                                STR_NOALIGN|STR_TERMINATE);
                        SCVAL(pdata,l2_vol_cch,len);
                        data_len = l2_vol_szVolLabel + len;
-                       DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
+                       DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
                                 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
                                 len, vname));
                        break;
@@ -2839,7 +2817,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
                        SIVAL(pdata,4,255); /* Max filename component length */
                        /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
                                and will think we can't do long filenames */
-                       len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
+                       len = srvstr_push(pdata, flags2, pdata+12, fstype,
                                          PTR_DIFF(end_data, pdata+12),
                                          STR_UNICODE);
                        SIVAL(pdata,8,len);
@@ -2848,7 +2826,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
 
                case SMB_QUERY_FS_LABEL_INFO:
                case SMB_FS_LABEL_INFORMATION:
-                       len = srvstr_push(pdata, req->flags2, pdata+4, vname,
+                       len = srvstr_push(pdata, flags2, pdata+4, vname,
                                          PTR_DIFF(end_data, pdata+4), 0);
                        data_len = 4 + len;
                        SIVAL(pdata,0,len);
@@ -2865,13 +2843,13 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
                                (str_checksum(get_local_machine_name())<<16));
 
                        /* Max label len is 32 characters. */
-                       len = srvstr_push(pdata, req->flags2, pdata+18, vname,
+                       len = srvstr_push(pdata, flags2, pdata+18, vname,
                                          PTR_DIFF(end_data, pdata+18),
                                          STR_UNICODE);
                        SIVAL(pdata,12,len);
                        data_len = 18+len;
 
-                       DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", 
+                       DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
                                (int)strlen(vname),vname, lp_servicename(snum)));
                        break;
 
@@ -2881,8 +2859,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
                        uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
                        data_len = 24;
                        if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
-                               reply_nterror(req, map_nt_error_from_unix(errno));
-                               return;
+                               return map_nt_error_from_unix(errno);
                        }
                        block_size = lp_block_size(snum);
                        if (bsize < block_size) {
@@ -2899,7 +2876,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
                        }
                        bytes_per_sector = 512;
                        sectors_per_unit = bsize/bytes_per_sector;
-                       DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
+                       DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
                                (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
                        SBIG_UINT(pdata,0,dsize);
@@ -2914,8 +2891,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                        uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
                        data_len = 32;
                        if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
-                               reply_nterror(req, map_nt_error_from_unix(errno));
-                               return;
+                               return map_nt_error_from_unix(errno);
                        }
                        block_size = lp_block_size(snum);
                        if (bsize < block_size) {
@@ -2932,7 +2908,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                        }
                        bytes_per_sector = 512;
                        sectors_per_unit = bsize/bytes_per_sector;
-                       DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
+                       DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
                                (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
                        SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
@@ -2985,24 +2961,23 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                        fsp.fnum = -1;
 
                        /* access check */
-                       if (conn->server_info->utok.uid != 0) {
+                       if (conn->server_info->utok.uid != sec_initial_uid()) {
                                DEBUG(0,("set_user_quota: access_denied "
                                         "service [%s] user [%s]\n",
                                         lp_servicename(SNUM(conn)),
                                         conn->server_info->unix_name));
-                               reply_doserror(req, ERRDOS, ERRnoaccess);
-                               return;
+                               return NT_STATUS_ACCESS_DENIED;
                        }
 
                        if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
                                DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
-                               reply_doserror(req, ERRSRV, ERRerror);
-                               return;
+                               return map_nt_error_from_unix(errno);
                        }
 
                        data_len = 48;
 
-                       DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));          
+                       DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
+                                 lp_servicename(SNUM(conn))));
 
                        /* Unknown1 24 NULL bytes*/
                        SBIG_UINT(pdata,0,(uint64_t)0);
@@ -3053,8 +3028,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                        int encrypt_caps = 0;
 
                        if (!lp_unix_extensions()) {
-                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
-                               return;
+                               return NT_STATUS_INVALID_LEVEL;
                        }
 
                        switch (conn->encrypt_level) {
@@ -3099,8 +3073,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                        vfs_statvfs_struct svfs;
 
                        if (!lp_unix_extensions()) {
-                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
-                               return;
+                               return NT_STATUS_INVALID_LEVEL;
                        }
 
                        rc = SMB_VFS_STATVFS(conn, ".", &svfs);
@@ -3115,16 +3088,14 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                                SBIG_UINT(pdata,32,svfs.TotalFileNodes);
                                SBIG_UINT(pdata,40,svfs.FreeFileNodes);
                                SBIG_UINT(pdata,48,svfs.FsIdentifier);
-                               DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
+                               DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
 #ifdef EOPNOTSUPP
                        } else if (rc == EOPNOTSUPP) {
-                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
-                               return;
+                               return NT_STATUS_INVALID_LEVEL;
 #endif /* EOPNOTSUPP */
                        } else {
                                DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
-                               reply_doserror(req, ERRSRV, ERRerror);
-                               return;
+                               return NT_STATUS_DOS(ERRSRV, ERRerror);
                        }
                        break;
                }
@@ -3136,13 +3107,11 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                        int i;
 
                        if (!lp_unix_extensions()) {
-                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
-                               return;
+                               return NT_STATUS_INVALID_LEVEL;
                        }
 
                        if (max_data_bytes < 40) {
-                               reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
-                               return;
+                               return NT_STATUS_BUFFER_TOO_SMALL;
                        }
 
                        /* We ARE guest if global_sid_Builtin_Guests is
@@ -3256,12 +3225,59 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                        }
                        /* drop through */
                default:
-                       reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                       return NT_STATUS_INVALID_LEVEL;
+       }
+
+       *ret_data_len = data_len;
+       return NT_STATUS_OK;
+}
+
+/****************************************************************************
+ Reply to a TRANS2_QFSINFO (query filesystem info).
+****************************************************************************/
+
+static void call_trans2qfsinfo(connection_struct *conn,
+                              struct smb_request *req,
+                              char **pparams, int total_params,
+                              char **ppdata, int total_data,
+                              unsigned int max_data_bytes)
+{
+       char *params = *pparams;
+       uint16_t info_level;
+       int data_len = 0;
+       NTSTATUS status;
+
+       if (total_params < 2) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
+       }
+
+       info_level = SVAL(params,0);
+
+       if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
+               if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
+                       DEBUG(0,("call_trans2qfsinfo: encryption required "
+                               "and info level 0x%x sent.\n",
+                               (unsigned int)info_level));
+                       exit_server_cleanly("encryption required "
+                               "on connection");
                        return;
+               }
        }
 
+       DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
+
+       status = smbd_do_qfsinfo(conn, req,
+                                info_level,
+                                req->flags2,
+                                max_data_bytes,
+                                ppdata, &data_len);
+       if (!NT_STATUS_IS_OK(status)) {
+               reply_nterror(req, status);
+               return;
+       }
 
-       send_trans2_replies(conn, req, params, 0, pdata, data_len,
+       send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
                            max_data_bytes);
 
        DEBUG( 4, ( "%s info_level = %d\n",
@@ -3432,12 +3448,12 @@ cap_low = 0x%x, cap_high = 0x%x\n",
                                ZERO_STRUCT(quotas);
 
                                /* access check */
-                               if ((conn->server_info->utok.uid != 0)
+                               if ((conn->server_info->utok.uid != sec_initial_uid())
                                    ||!CAN_WRITE(conn)) {
                                        DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
                                                 lp_servicename(SNUM(conn)),
                                                 conn->server_info->unix_name));
-                                       reply_doserror(req, ERRSRV, ERRaccess);
+                                       reply_nterror(req, NT_STATUS_ACCESS_DENIED);
                                        return;
                                }
 
@@ -3506,7 +3522,7 @@ cap_low = 0x%x, cap_high = 0x%x\n",
                                /* now set the quotas */
                                if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
                                        DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
-                                       reply_doserror(req, ERRSRV, ERRerror);
+                                       reply_nterror(req, map_nt_error_from_unix(errno));
                                        return;
                                }
 
@@ -3988,7 +4004,8 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
        }
 
        DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
-               fname, fsp ? fsp->fnum : -1, info_level, max_data_bytes));
+                smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
+                info_level, max_data_bytes));
 
        if (ms_dfs_link) {
                mode = dos_mode_msdfs(conn, smb_fname);
@@ -4074,7 +4091,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                file_size = get_file_size_stat(&sbuf);
        }
 
-       if (fsp && fsp->fh) {
+       if (fsp) {
                pos = fsp->fh->position_information;
        }
 
@@ -4091,7 +4108,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
           I think this causes us to fail the IFSKIT
           BasicFileInformationTest. -tpot */
        file_index =  ((sbuf.st_ex_ino) & UINT32_MAX); /* FileIndexLow */
-       file_index |= ((sbuf.st_ex_dev) & UINT32_MAX) << 32; /* FileIndexHigh */
+       file_index |= ((uint64_t)((sbuf.st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
 
        switch (info_level) {
                case SMB_INFO_STANDARD:
@@ -4570,7 +4587,11 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
 
                                if (S_ISDIR(sbuf.st_ex_mode)) {
                                        if (fsp && fsp->is_directory) {
-                                               def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
+                                               def_acl =
+                                                   SMB_VFS_SYS_ACL_GET_FILE(
+                                                           conn,
+                                                           fsp->fsp_name->base_name,
+                                                           SMB_ACL_TYPE_DEFAULT);
                                        } else {
                                                def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
                                        }
@@ -4635,6 +4656,11 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                        uint32 lock_pid;
                        enum brl_type lock_type;
 
+                       /* We need an open file with a real fd for this. */
+                       if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
+                               return NT_STATUS_INVALID_LEVEL;
+                       }
+
                        if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
                                return NT_STATUS_INVALID_PARAMETER;
                        }
@@ -4724,7 +4750,6 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
        uint16 info_level;
        unsigned int data_size = 0;
        unsigned int param_size = 2;
-       char *fname = NULL;
        struct smb_filename *smb_fname = NULL;
        bool delete_pending = False;
        struct timespec write_time_ts;
@@ -4772,14 +4797,8 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
                        return;
                }
 
-               fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
-               if (!fname) {
-                       reply_nterror(req, NT_STATUS_NO_MEMORY);
-                       return;
-               }
-
-               status = create_synthetic_smb_fname_split(talloc_tos(), fname,
-                                                         NULL, &smb_fname);
+               status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
+                                          &smb_fname);
                if (!NT_STATUS_IS_OK(status)) {
                        reply_nterror(req, status);
                        return;
@@ -4792,7 +4811,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
 
                        /* We know this name is ok, it's already passed the checks. */
 
-               } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
+               } else if(fsp->is_directory || fsp->fh->fd == -1) {
                        /*
                         * This is actually a QFILEINFO on a directory
                         * handle (returned from an NT SMB). NT5.0 seems
@@ -4843,6 +4862,8 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
                }
 
        } else {
+               char *fname = NULL;
+
                /* qpathinfo */
                if (total_params < 7) {
                        reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
@@ -4870,8 +4891,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
                                        conn,
                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
                                        fname,
-                                       &smb_fname,
-                                       &fname);
+                                       &smb_fname);
                if (!NT_STATUS_IS_OK(status)) {
                        if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
                                reply_botherror(req,
@@ -4951,7 +4971,8 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
                } else if (!VALID_STAT(smb_fname->st) &&
                           SMB_VFS_STAT(conn, smb_fname) &&
                           (info_level != SMB_INFO_IS_NAME_VALID)) {
-                       ms_dfs_link = check_msdfs_link(conn, fname,
+                       ms_dfs_link = check_msdfs_link(conn,
+                                                      smb_fname->base_name,
                                                       &smb_fname->st);
 
                        if (!ms_dfs_link) {
@@ -4973,8 +4994,9 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
                }
        }
 
-       DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
-               fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
+       DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
+                "total_data=%d\n", smb_fname_str_dbg(smb_fname),
+                fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
 
        /* Pull out any data sent here before we realloc. */
        switch (info_level) {
@@ -5103,8 +5125,6 @@ NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
                const struct smb_filename *smb_fname_old,
                const struct smb_filename *smb_fname_new)
 {
-       char *oldname = NULL;
-       char *newname = NULL;
        NTSTATUS status = NT_STATUS_OK;
 
        /* source must already exist. */
@@ -5122,25 +5142,22 @@ NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
                return NT_STATUS_FILE_IS_A_DIRECTORY;
        }
 
-       status = get_full_smb_filename(ctx, smb_fname_new, &newname);
-       if (!NT_STATUS_IS_OK(status)) {
-               goto out;
-       }
-       status = get_full_smb_filename(ctx, smb_fname_old, &oldname);
-       if (!NT_STATUS_IS_OK(status)) {
-               goto out;
+       /* Setting a hardlink to/from a stream isn't currently supported. */
+       if (is_ntfs_stream_smb_fname(smb_fname_old) ||
+           is_ntfs_stream_smb_fname(smb_fname_new)) {
+               return NT_STATUS_INVALID_PARAMETER;
        }
 
-       DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
+       DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
+                 smb_fname_old->base_name, smb_fname_new->base_name));
 
-       if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
+       if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
+                        smb_fname_new->base_name) != 0) {
                status = map_nt_error_from_unix(errno);
                DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
-                                nt_errstr(status), newname, oldname));
+                        nt_errstr(status), smb_fname_old->base_name,
+                        smb_fname_new->base_name));
        }
- out:
-       TALLOC_FREE(newname);
-       TALLOC_FREE(oldname);
        return status;
 }
 
@@ -5505,8 +5522,9 @@ static NTSTATUS smb_file_position_information(connection_struct *conn,
        }
 #endif /* LARGE_SMB_OFF_T */
 
-       DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
-               fsp->fsp_name, (double)position_information ));
+       DEBUG(10,("smb_file_position_information: Set file position "
+                 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
+                 (double)position_information));
        fsp->fh->position_information = position_information;
        return NT_STATUS_OK;
 }
@@ -5539,10 +5557,10 @@ static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
                                       struct smb_request *req,
                                       const char *pdata,
                                       int total_data,
-                                      const char *fname)
+                                      const struct smb_filename *smb_fname)
 {
        char *link_target = NULL;
-       const char *newname = fname;
+       const char *newname = smb_fname->base_name;
        NTSTATUS status = NT_STATUS_OK;
        TALLOC_CTX *ctx = talloc_tos();
 
@@ -5642,8 +5660,7 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
                                conn,
                                req->flags2 & FLAGS2_DFS_PATHNAMES,
                                oldname,
-                               &smb_fname_old,
-                               NULL);
+                               &smb_fname_old);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -5717,8 +5734,8 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
 
                /* Create an smb_fname to call rename_internals_fsp() with. */
                status = create_synthetic_smb_fname(talloc_tos(),
-                                                   fsp->base_fsp->fsp_name,
-                                                   newname, NULL, &smb_fname);
+                   fsp->base_fsp->fsp_name->base_name, newname, NULL,
+                   &smb_fname);
                if (!NT_STATUS_IS_OK(status)) {
                        goto out;
                }
@@ -5735,7 +5752,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
 
                /* Create a char * to call rename_internals() with. */
                base_name = talloc_asprintf(ctx, "%s%s",
-                                          fsp->base_fsp->fsp_name,
+                                          fsp->base_fsp->fsp_name->base_name,
                                           newname);
                if (!base_name) {
                        status = NT_STATUS_NO_MEMORY;
@@ -5792,13 +5809,15 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
        }
 
        if (fsp) {
-               DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
-                       fsp->fnum, fsp->fsp_name, base_name ));
+               DEBUG(10,("smb_file_rename_information: "
+                         "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
+                         fsp->fnum, fsp_str_dbg(fsp), base_name));
                status = rename_internals_fsp(conn, fsp, smb_fname, 0,
                                              overwrite);
        } else {
-               DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
-                       fname, base_name ));
+               DEBUG(10,("smb_file_rename_information: "
+                         "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
+                         fname, base_name));
                status = rename_internals(ctx, conn, req, fname, base_name, 0,
                                        overwrite, False, dest_has_wcard,
                                        FILE_WRITE_ATTRIBUTES);
@@ -5817,8 +5836,7 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
                                const char *pdata,
                                int total_data,
                                files_struct *fsp,
-                               const char *fname,
-                               SMB_STRUCT_STAT *psbuf)
+                               const struct smb_filename *smb_fname)
 {
        uint16 posix_acl_version;
        uint16 num_file_acls;
@@ -5853,18 +5871,20 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
        }
 
        DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
-               fname ? fname : fsp->fsp_name,
+               smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
                (unsigned int)num_file_acls,
                (unsigned int)num_def_acls));
 
-       if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
-                       pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
+       if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
+               smb_fname->base_name, num_file_acls,
+               pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
                return map_nt_error_from_unix(errno);
        }
 
-       if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
-                       pdata + SMB_POSIX_ACL_HEADER_SIZE +
-                       (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
+       if (valid_def_acls && !set_unix_posix_default_acl(conn,
+               smb_fname->base_name, &smb_fname->st, num_def_acls,
+               pdata + SMB_POSIX_ACL_HEADER_SIZE +
+               (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
                return map_nt_error_from_unix(errno);
        }
        return NT_STATUS_OK;
@@ -5940,7 +5960,7 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn,
 
        DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
                        "lock_pid = %u, count = %.0f, offset = %.0f\n",
-               fsp->fsp_name,
+               fsp_str_dbg(fsp),
                (unsigned int)lock_type,
                (unsigned int)lock_pid,
                (double)count,
@@ -6632,11 +6652,9 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
                                struct smb_request *req,
                                char **ppdata,
                                int total_data,
-                               const char *fname,
-                               SMB_STRUCT_STAT *psbuf,
+                               struct smb_filename *smb_fname,
                                int *pdata_return_size)
 {
-       struct smb_filename *smb_fname;
        NTSTATUS status = NT_STATUS_OK;
        uint32 raw_unixmode = 0;
        uint32 mod_unixmode = 0;
@@ -6653,7 +6671,8 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
        raw_unixmode = IVAL(pdata,8);
        /* Next 4 bytes are not yet defined. */
 
-       status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
+       status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
+                                     PERM_NEW_DIR, &unixmode);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -6661,13 +6680,7 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
        mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
 
        DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
-               fname, (unsigned int)unixmode ));
-
-       status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
-                                                 &smb_fname);
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
+                 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
 
         status = SMB_VFS_CREATE_FILE(
                conn,                                   /* conn */
@@ -6686,9 +6699,6 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
                &fsp,                                   /* result */
                &info);                                 /* pinfo */
 
-       *psbuf = smb_fname->st;
-       TALLOC_FREE(smb_fname);
-
         if (NT_STATUS_IS_OK(status)) {
                 close_file(req, fsp, NORMAL_CLOSE);
         }
@@ -6719,12 +6729,14 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
                case SMB_QUERY_FILE_UNIX_BASIC:
                        SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
                        SSVAL(pdata,10,0); /* Padding. */
-                       store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
+                       store_file_unix_basic(conn, pdata + 12, fsp,
+                                             &smb_fname->st);
                        break;
                case SMB_QUERY_FILE_UNIX_INFO2:
                        SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
                        SSVAL(pdata,10,0); /* Padding. */
-                       store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
+                       store_file_unix_basic_info2(conn, pdata + 12, fsp,
+                                                   &smb_fname->st);
                        break;
                default:
                        SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
@@ -6743,11 +6755,9 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
                               struct smb_request *req,
                                char **ppdata,
                                int total_data,
-                               const char *fname,
-                               SMB_STRUCT_STAT *psbuf,
+                               struct smb_filename *smb_fname,
                                int *pdata_return_size)
 {
-       struct smb_filename *smb_fname = NULL;
        bool extended_oplock_granted = False;
        char *pdata = *ppdata;
        uint32 flags = 0;
@@ -6780,8 +6790,7 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
                return smb_posix_mkdir(conn, req,
                                        ppdata,
                                        total_data,
-                                       fname,
-                                       psbuf,
+                                       smb_fname,
                                        pdata_return_size);
        }
 
@@ -6820,11 +6829,10 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
        raw_unixmode = IVAL(pdata,8);
        /* Next 4 bytes are not yet defined. */
 
-       status = unix_perms_from_wire(conn,
-                               psbuf,
-                               raw_unixmode,
-                               VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
-                               &unixmode);
+       status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
+                                     (VALID_STAT(smb_fname->st) ?
+                                         PERM_EXISTING_FILE : PERM_NEW_FILE),
+                                     &unixmode);
 
        if (!NT_STATUS_IS_OK(status)) {
                return status;
@@ -6843,16 +6851,10 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
        }
 
        DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
-               fname,
+               smb_fname_str_dbg(smb_fname),
                (unsigned int)wire_open_mode,
                (unsigned int)unixmode ));
 
-       status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
-                                                 &smb_fname);
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
-
         status = SMB_VFS_CREATE_FILE(
                conn,                                   /* conn */
                req,                                    /* req */
@@ -6871,9 +6873,6 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
                &fsp,                                   /* result */
                &info);                                 /* pinfo */
 
-       *psbuf = smb_fname->st;
-       TALLOC_FREE(smb_fname);
-
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -6926,12 +6925,14 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
                case SMB_QUERY_FILE_UNIX_BASIC:
                        SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
                        SSVAL(pdata,10,0); /* padding. */
-                       store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
+                       store_file_unix_basic(conn, pdata + 12, fsp,
+                                             &smb_fname->st);
                        break;
                case SMB_QUERY_FILE_UNIX_INFO2:
                        SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
                        SSVAL(pdata,10,0); /* padding. */
-                       store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
+                       store_file_unix_basic_info2(conn, pdata + 12, fsp,
+                                                   &smb_fname->st);
                        break;
                default:
                        SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
@@ -7014,7 +7015,7 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
                                  NULL);
        if (lck == NULL) {
                DEBUG(0, ("smb_posix_unlink: Could not get share mode "
-                       "lock for file %s\n", fsp->fsp_name));
+                         "lock for file %s\n", fsp_str_dbg(fsp)));
                close_file(req, fsp, NORMAL_CLOSE);
                return NT_STATUS_INVALID_PARAMETER;
        }
@@ -7065,16 +7066,12 @@ NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
                                int *ret_data_size)
 {
        char *pdata = *ppdata;
-       SMB_STRUCT_STAT sbuf;
        char *fname = NULL;
        NTSTATUS status = NT_STATUS_OK;
        int data_return_size = 0;
 
        *ret_data_size = 0;
 
-       /* Set sbuf for use below. */
-       sbuf = smb_fname->st;
-
        if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
                return NT_STATUS_INVALID_LEVEL;
        }
@@ -7092,8 +7089,9 @@ NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
                return status;
        }
 
-       DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d totdata=%d\n",
-               fname, fsp ? fsp->fnum : -1, info_level, total_data));
+       DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
+                "totdata=%d\n", smb_fname_str_dbg(smb_fname),
+                fsp ? fsp->fnum : -1, info_level, total_data));
 
        switch (info_level) {
 
@@ -7224,13 +7222,13 @@ NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
                                return NT_STATUS_INVALID_LEVEL;
                        }
                        status = smb_set_file_unix_link(conn, req, pdata,
-                                                       total_data, fname);
+                                                       total_data, smb_fname);
                        break;
                }
 
                case SMB_SET_FILE_UNIX_HLINK:
                {
-                       if (fsp || smb_fname == NULL) {
+                       if (fsp) {
                                /* We must have a pathname for this. */
                                return NT_STATUS_INVALID_LEVEL;
                        }
@@ -7255,15 +7253,14 @@ NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
                                                pdata,
                                                total_data,
                                                fsp,
-                                               fname,
-                                               &sbuf);
+                                               smb_fname);
                        break;
                }
 #endif
 
                case SMB_SET_POSIX_LOCK:
                {
-                       if (fsp) {
+                       if (!fsp) {
                                return NT_STATUS_INVALID_LEVEL;
                        }
                        status = smb_set_posix_lock(conn, req,
@@ -7281,8 +7278,7 @@ NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
                        status = smb_posix_open(conn, req,
                                                ppdata,
                                                total_data,
-                                               fname,
-                                               &sbuf,
+                                               smb_fname,
                                                &data_return_size);
                        break;
                }
@@ -7327,7 +7323,6 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
        char *params = *pparams;
        char *pdata = *ppdata;
        uint16 info_level;
-       char *fname = NULL;
        struct smb_filename *smb_fname = NULL;
        files_struct *fsp = NULL;
        NTSTATUS status = NT_STATUS_OK;
@@ -7351,14 +7346,8 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
                }
                info_level = SVAL(params,2);
 
-               fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
-               if (!fname) {
-                       reply_nterror(req, NT_STATUS_NO_MEMORY);
-                       return;
-               }
-
-               status = create_synthetic_smb_fname_split(talloc_tos(), fname,
-                                                         NULL, &smb_fname);
+               status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
+                                          &smb_fname);
                if (!NT_STATUS_IS_OK(status)) {
                        reply_nterror(req, status);
                        return;
@@ -7398,7 +7387,9 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
                        if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
                                fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
 
-                               DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
+                               DEBUG(3,("call_trans2setfilepathinfo: "
+                                        "Cancelling print job (%s)\n",
+                                        fsp_str_dbg(fsp)));
 
                                SSVAL(params,0,0);
                                send_trans2_replies(conn, req, params, 2,
@@ -7426,6 +7417,8 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
                        }
                }
        } else {
+               char *fname = NULL;
+
                /* set path info */
                if (total_params < 7) {
                        reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
@@ -7444,8 +7437,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
                status = filename_convert(req, conn,
                                         req->flags2 & FLAGS2_DFS_PATHNAMES,
                                         fname,
-                                        &smb_fname,
-                                        &fname);
+                                        &smb_fname);
                if (!NT_STATUS_IS_OK(status)) {
                        if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
                                reply_botherror(req,
@@ -7476,8 +7468,9 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
                }
        }
 
-       DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
-               tran_call, fname, fsp ? fsp->fnum : -1, info_level,total_data));
+       DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
+                "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
+                fsp ? fsp->fnum : -1, info_level,total_data));
 
        /* Realloc the parameter size */
        *pparams = (char *)SMB_REALLOC(*pparams,2);
@@ -7565,8 +7558,7 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
                                conn,
                                req->flags2 & FLAGS2_DFS_PATHNAMES,
                                directory,
-                               &smb_dname,
-                               NULL);
+                               &smb_dname);
 
        if (!NT_STATUS_IS_OK(status)) {
                if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {