s3: VFS: Change SMB_VFS_SYMLINK to use const struct smb_filename * instead of const...
[sfrench/samba-autobuild/.git] / source3 / smbd / trans2.c
index e2640e4f528f96cf5957210ae150624752c4ce99..de6073a973fdbc35197caf5831199727b83f49f2 100644 (file)
@@ -40,6 +40,7 @@
 #include "rpc_server/srv_pipe_hnd.h"
 #include "printing.h"
 #include "lib/util_ea.h"
+#include "lib/readdir_attr.h"
 
 #define DIR_ENTRY_SAFETY_MARGIN 4096
 
@@ -53,6 +54,51 @@ static char *store_file_unix_basic_info2(connection_struct *conn,
                                files_struct *fsp,
                                const SMB_STRUCT_STAT *psbuf);
 
+/****************************************************************************
+ Check if an open file handle or smb_fname is a symlink.
+****************************************************************************/
+
+static NTSTATUS refuse_symlink(connection_struct *conn,
+                       const files_struct *fsp,
+                       const struct smb_filename *smb_fname)
+{
+       SMB_STRUCT_STAT sbuf;
+       const SMB_STRUCT_STAT *pst = NULL;
+
+       if (fsp) {
+               pst = &fsp->fsp_name->st;
+       } else {
+               pst = &smb_fname->st;
+       }
+
+       if (!VALID_STAT(*pst)) {
+               int ret = vfs_stat_smb_basename(conn,
+                               smb_fname,
+                               &sbuf);
+               if (ret == -1 && errno != ENOENT) {
+                       return map_nt_error_from_unix(errno);
+               } else if (ret == -1) {
+                       /* it's not a symlink.. */
+                       return NT_STATUS_OK;
+               }
+               pst = &sbuf;
+       }
+
+       if (S_ISLNK(pst->st_ex_mode)) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+       return NT_STATUS_OK;
+}
+
+NTSTATUS check_access_fsp(const struct files_struct *fsp,
+                         uint32_t access_mask)
+{
+       if (!(fsp->access_mask & access_mask)) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+       return NT_STATUS_OK;
+}
+
 /********************************************************************
  The canonical "check access" based on object handle or path function.
 ********************************************************************/
@@ -62,20 +108,16 @@ NTSTATUS check_access(connection_struct *conn,
                                const struct smb_filename *smb_fname,
                                uint32_t access_mask)
 {
+       NTSTATUS status;
+
        if (fsp) {
-               if (!(fsp->access_mask & access_mask)) {
-                       return NT_STATUS_ACCESS_DENIED;
-               }
+               status = check_access_fsp(fsp, access_mask);
        } else {
-               NTSTATUS status = smbd_check_access_rights(conn,
-                                       smb_fname,
-                                       false,
-                                       access_mask);
-               if (!NT_STATUS_IS_OK(status)) {
-                       return status;
-               }
+               status = smbd_check_access_rights(conn, smb_fname,
+                                                 false, access_mask);
        }
-       return NT_STATUS_OK;
+
+       return status;
 }
 
 /********************************************************************
@@ -104,6 +146,9 @@ uint64_t smb_roundup(connection_struct *conn, uint64_t val)
 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
 {
        uint64_t file_index;
+       if (conn->sconn->aapl_zero_file_id) {
+               return 0;
+       }
        if (conn->base_share_dev == psbuf->st_ex_dev) {
                return (uint64_t)psbuf->st_ex_ino;
        }
@@ -112,6 +157,17 @@ uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
        return file_index;
 }
 
+
+/********************************************************************
+ Globally (for this connection / multi-channel) disable file-ID
+ calculation. This is required to be global because it serves
+ Macs in AAPL mode, which is globally set.
+********************************************************************/
+void aapl_force_zero_file_id(struct smbd_server_connection *sconn)
+{
+       sconn->aapl_zero_file_id = true;
+}
+
 /****************************************************************************
  Utility functions for dealing with extended attributes.
 ****************************************************************************/
@@ -147,9 +203,12 @@ bool samba_private_attr_name(const char *unix_ea_name)
  Get one EA value. Fill in a struct ea_struct.
 ****************************************************************************/
 
-NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
-                     files_struct *fsp, const char *fname,
-                     const char *ea_name, struct ea_struct *pea)
+NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx,
+                       connection_struct *conn,
+                       files_struct *fsp,
+                       const struct smb_filename *smb_fname,
+                       const char *ea_name,
+                       struct ea_struct *pea)
 {
        /* Get the value of this xattr. Max size is 64k. */
        size_t attr_size = 256;
@@ -166,7 +225,8 @@ NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
        if (fsp && fsp->fh->fd != -1) {
                sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
        } else {
-               sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
+               sizeret = SMB_VFS_GETXATTR(conn, smb_fname,
+                               ea_name, val, attr_size);
        }
 
        if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
@@ -179,7 +239,7 @@ NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
        }
 
        DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
-       dump_data(10, (uint8 *)val, sizeret);
+       dump_data(10, (uint8_t *)val, sizeret);
 
        pea->flags = 0;
        if (strnequal(ea_name, "user.", 5)) {
@@ -196,77 +256,77 @@ NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
        return NT_STATUS_OK;
 }
 
-NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
-                               files_struct *fsp, const char *fname,
-                               char ***pnames, size_t *pnum_names)
+NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx,
+                               connection_struct *conn,
+                               files_struct *fsp,
+                               const struct smb_filename *smb_fname,
+                               char ***pnames,
+                               size_t *pnum_names)
 {
+       char smallbuf[1024];
        /* Get a list of all xattrs. Max namesize is 64k. */
        size_t ea_namelist_size = 1024;
-       char *ea_namelist = NULL;
+       char *ea_namelist = smallbuf;
+       char *to_free = NULL;
 
        char *p;
-       char **names, **tmp;
+       char **names;
        size_t num_names;
        ssize_t sizeret = -1;
+       NTSTATUS status;
 
-       if (!lp_ea_support(SNUM(conn))) {
-               if (pnames) {
-                       *pnames = NULL;
-               }
-               *pnum_names = 0;
-               return NT_STATUS_OK;
+       if (pnames) {
+               *pnames = NULL;
        }
+       *pnum_names = 0;
 
-       /*
-        * TALLOC the result early to get the talloc hierarchy right.
-        */
-
-       names = talloc_array(mem_ctx, char *, 1);
-       if (names == NULL) {
-               DEBUG(0, ("talloc failed\n"));
-               return NT_STATUS_NO_MEMORY;
+       status = refuse_symlink(conn, fsp, smb_fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               /*
+                * Just return no EA's on a symlink.
+                */
+               return NT_STATUS_OK;
        }
 
-       while (ea_namelist_size <= 65536) {
+       if (fsp && fsp->fh->fd != -1) {
+               sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
+                                            ea_namelist_size);
+       } else {
+               sizeret = SMB_VFS_LISTXATTR(conn,
+                                           smb_fname,
+                                           ea_namelist,
+                                           ea_namelist_size);
+       }
 
-               ea_namelist = talloc_realloc(
-                       names, ea_namelist, char, ea_namelist_size);
+       if ((sizeret == -1) && (errno == ERANGE)) {
+               ea_namelist_size = 65536;
+               ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
                if (ea_namelist == NULL) {
-                       DEBUG(0, ("talloc failed\n"));
-                       TALLOC_FREE(names);
                        return NT_STATUS_NO_MEMORY;
                }
+               to_free = ea_namelist;
 
                if (fsp && fsp->fh->fd != -1) {
                        sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
                                                     ea_namelist_size);
                } else {
-                       sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
+                       sizeret = SMB_VFS_LISTXATTR(conn,
+                                                   smb_fname,
+                                                   ea_namelist,
                                                    ea_namelist_size);
                }
-
-               if ((sizeret == -1) && (errno == ERANGE)) {
-                       ea_namelist_size *= 2;
-               }
-               else {
-                       break;
-               }
        }
 
        if (sizeret == -1) {
-               TALLOC_FREE(names);
-               return map_nt_error_from_unix(errno);
+               status = map_nt_error_from_unix(errno);
+               TALLOC_FREE(to_free);
+               return status;
        }
 
-       DEBUG(10, ("%s: ea_namelist size = %u\n",
-                  __func__, (unsigned int)sizeret));
+       DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
 
        if (sizeret == 0) {
-               TALLOC_FREE(names);
-               if (pnames) {
-                       *pnames = NULL;
-               }
-               *pnum_names = 0;
+               TALLOC_FREE(to_free);
                return NT_STATUS_OK;
        }
 
@@ -275,7 +335,7 @@ NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
         */
 
        if (ea_namelist[sizeret-1] != '\0') {
-               TALLOC_FREE(names);
+               TALLOC_FREE(to_free);
                return NT_STATUS_INTERNAL_ERROR;
        }
 
@@ -288,26 +348,45 @@ NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
                num_names += 1;
        }
 
-       tmp = talloc_realloc(mem_ctx, names, char *, num_names);
-       if (tmp == NULL) {
+       *pnum_names = num_names;
+
+       if (pnames == NULL) {
+               TALLOC_FREE(to_free);
+               return NT_STATUS_OK;
+       }
+
+       names = talloc_array(mem_ctx, char *, num_names);
+       if (names == NULL) {
                DEBUG(0, ("talloc failed\n"));
-               TALLOC_FREE(names);
+               TALLOC_FREE(to_free);
                return NT_STATUS_NO_MEMORY;
        }
 
-       names = tmp;
+       if (ea_namelist == smallbuf) {
+               ea_namelist = talloc_memdup(names, smallbuf, sizeret);
+               if (ea_namelist == NULL) {
+                       TALLOC_FREE(names);
+                       return NT_STATUS_NO_MEMORY;
+               }
+       } else {
+               talloc_steal(names, ea_namelist);
+
+               ea_namelist = talloc_realloc(names, ea_namelist, char,
+                                            sizeret);
+               if (ea_namelist == NULL) {
+                       TALLOC_FREE(names);
+                       return NT_STATUS_NO_MEMORY;
+               }
+       }
+
        num_names = 0;
 
        for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
                names[num_names++] = p;
        }
 
-       if (pnames) {
-               *pnames = names;
-       } else {
-               TALLOC_FREE(names);
-       }
-       *pnum_names = num_names;
+       *pnames = names;
+
        return NT_STATUS_OK;
 }
 
@@ -315,27 +394,46 @@ NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
  Return a linked list of the total EA's. Plus the total size
 ****************************************************************************/
 
-static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
-                                     const char *fname, size_t *pea_total_len, struct ea_list **ea_list)
+static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx,
+                               connection_struct *conn,
+                               files_struct *fsp,
+                               const struct smb_filename *smb_fname,
+                               size_t *pea_total_len,
+                               struct ea_list **ea_list)
 {
        /* Get a list of all xattrs. Max namesize is 64k. */
        size_t i, num_names;
        char **names;
        struct ea_list *ea_list_head = NULL;
+       bool posix_pathnames = false;
        NTSTATUS status;
 
        *pea_total_len = 0;
        *ea_list = NULL;
 
-       status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
-                                       &names, &num_names);
+       if (!lp_ea_support(SNUM(conn))) {
+               return NT_STATUS_OK;
+       }
+
+       if (fsp) {
+               posix_pathnames =
+                       (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
+       } else {
+               posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
+       }
+
+       status = get_ea_names_from_file(talloc_tos(),
+                               conn,
+                               fsp,
+                               smb_fname,
+                               &names,
+                               &num_names);
 
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
        if (num_names == 0) {
-               *ea_list = NULL;
                return NT_STATUS_OK;
        }
 
@@ -351,7 +449,7 @@ static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struc
                 * Filter out any underlying POSIX EA names
                 * that a Windows client can't handle.
                 */
-               if (!lp_posix_pathnames() &&
+               if (!posix_pathnames &&
                                is_invalid_windows_ea_name(names[i])) {
                        continue;
                }
@@ -361,9 +459,12 @@ static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struc
                        return NT_STATUS_NO_MEMORY;
                }
 
-               status = get_ea_value(listp, conn, fsp,
-                                     fname, names[i],
-                                     &listp->ea);
+               status = get_ea_value(listp,
+                                       conn,
+                                       fsp,
+                                       smb_fname,
+                                       names[i],
+                                       &listp->ea);
 
                if (!NT_STATUS_IS_OK(status)) {
                        TALLOC_FREE(listp);
@@ -388,7 +489,7 @@ static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struc
                          "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
                          (unsigned int)listp->ea.value.length));
 
-               DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
+               DLIST_ADD_END(ea_list_head, listp);
 
        }
 
@@ -418,7 +519,12 @@ static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *co
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
+       return get_ea_list_from_file_path(mem_ctx,
+                               conn,
+                               fsp,
+                               smb_fname,
+                               pea_total_len,
+                               ea_list);
 }
 
 /****************************************************************************
@@ -561,7 +667,12 @@ static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp,
        if (is_ntfs_stream_smb_fname(smb_fname)) {
                fsp = NULL;
        }
-       (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
+       (void)get_ea_list_from_file_path(mem_ctx,
+                               conn,
+                               fsp,
+                               smb_fname,
+                               &total_ea_len,
+                               &ea_list);
        if(conn->sconn->using_smb2) {
                NTSTATUS status;
                unsigned int ret_data_size;
@@ -590,12 +701,20 @@ static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp,
  Ensure the EA name is case insensitive by matching any existing EA name.
 ****************************************************************************/
 
-static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
+static void canonicalize_ea_name(connection_struct *conn,
+                       files_struct *fsp,
+                       const struct smb_filename *smb_fname,
+                       fstring unix_ea_name)
 {
        size_t total_ea_len;
        TALLOC_CTX *mem_ctx = talloc_tos();
        struct ea_list *ea_list;
-       NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
+       NTSTATUS status = get_ea_list_from_file_path(mem_ctx,
+                                       conn,
+                                       fsp,
+                                       smb_fname,
+                                       &total_ea_len,
+                                       &ea_list);
        if (!NT_STATUS_IS_OK(status)) {
                return;
        }
@@ -618,12 +737,24 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
                const struct smb_filename *smb_fname, struct ea_list *ea_list)
 {
        NTSTATUS status;
-       char *fname = NULL;
+       bool posix_pathnames = false;
 
        if (!lp_ea_support(SNUM(conn))) {
                return NT_STATUS_EAS_NOT_SUPPORTED;
        }
 
+       if (fsp) {
+               posix_pathnames =
+                       (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
+       } else {
+               posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
+       }
+
+       status = refuse_symlink(conn, fsp, smb_fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
        status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
@@ -639,12 +770,10 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
         * we set *any* of them.
         */
 
-       if (ea_list_has_invalid_name(ea_list)) {
+       if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
                return STATUS_INVALID_EA_NAME;
        }
 
-       fname = smb_fname->base_name;
-
        for (;ea_list; ea_list = ea_list->next) {
                int ret;
                fstring unix_ea_name;
@@ -652,7 +781,10 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
                fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
                fstrcat(unix_ea_name, ea_list->ea.name);
 
-               canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
+               canonicalize_ea_name(conn,
+                               fsp,
+                               smb_fname,
+                               unix_ea_name);
 
                DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
 
@@ -670,8 +802,10 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
                                ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
                        } else {
                                DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
-                                       unix_ea_name, fname));
-                               ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
+                                       unix_ea_name, smb_fname->base_name));
+                               ret = SMB_VFS_REMOVEXATTR(conn,
+                                               smb_fname,
+                                               unix_ea_name);
                        }
 #ifdef ENOATTR
                        /* Removing a non existent attribute always succeeds. */
@@ -690,9 +824,13 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
                                                        ea_list->ea.value.data, ea_list->ea.value.length, 0);
                        } else {
                                DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
-                                       unix_ea_name, fname));
-                               ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
-                                                       ea_list->ea.value.data, ea_list->ea.value.length, 0);
+                                       unix_ea_name, smb_fname->base_name));
+                               ret = SMB_VFS_SETXATTR(conn,
+                                               smb_fname,
+                                               unix_ea_name,
+                                               ea_list->ea.value.data,
+                                               ea_list->ea.value.length,
+                                               0);
                        }
                }
 
@@ -743,7 +881,7 @@ static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, siz
                }
 
                offset += (namelen + 1); /* Go past the name + terminating zero. */
-               DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
+               DLIST_ADD_END(ea_list_head, eal);
                DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
        }
 
@@ -767,7 +905,7 @@ static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t d
                        return NULL;
                }
 
-               DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
+               DLIST_ADD_END(ea_list_head, eal);
                offset += bytes_used;
        }
 
@@ -1067,7 +1205,7 @@ static void call_trans2open(connection_struct *conn,
        char *params = *pparams;
        char *pdata = *ppdata;
        int deny_mode;
-       int32 open_attr;
+       int32_t open_attr;
        bool oplock_request;
 #if 0
        bool return_additional_info;
@@ -1075,7 +1213,7 @@ static void call_trans2open(connection_struct *conn,
        time_t open_time;
 #endif
        int open_ofun;
-       uint32 open_size;
+       uint32_t open_size;
        char *pname;
        char *fname = NULL;
        off_t size=0;
@@ -1084,13 +1222,14 @@ static void call_trans2open(connection_struct *conn,
        int smb_action = 0;
        files_struct *fsp;
        struct ea_list *ea_list = NULL;
-       uint16 flags = 0;
+       uint16_t flags = 0;
        NTSTATUS status;
-       uint32 access_mask;
-       uint32 share_mode;
-       uint32 create_disposition;
-       uint32 create_options = 0;
+       uint32_t access_mask;
+       uint32_t share_mode;
+       uint32_t create_disposition;
+       uint32_t create_options = 0;
        uint32_t private_flags = 0;
+       uint32_t ucf_flags = ucf_flags_from_smb_request(req);
        TALLOC_CTX *ctx = talloc_tos();
 
        /*
@@ -1124,9 +1263,25 @@ static void call_trans2open(connection_struct *conn,
                goto out;
        }
 
-       srvstr_get_path(ctx, params, req->flags2, &fname, pname,
-                       total_params - 28, STR_TERMINATE,
+       if (req->posix_pathnames) {
+               srvstr_get_path_posix(ctx,
+                       params,
+                       req->flags2,
+                       &fname,
+                       pname,
+                       total_params - 28,
+                       STR_TERMINATE,
+                       &status);
+       } else {
+               srvstr_get_path(ctx,
+                       params,
+                       req->flags2,
+                       &fname,
+                       pname,
+                       total_params - 28,
+                       STR_TERMINATE,
                        &status);
+       }
        if (!NT_STATUS_IS_OK(status)) {
                reply_nterror(req, status);
                goto out;
@@ -1138,9 +1293,8 @@ static void call_trans2open(connection_struct *conn,
 
        status = filename_convert(ctx,
                                conn,
-                               req->flags2 & FLAGS2_DFS_PATHNAMES,
                                fname,
-                               0,
+                               ucf_flags,
                                NULL,
                                &smb_fname);
        if (!NT_STATUS_IS_OK(status)) {
@@ -1195,7 +1349,8 @@ static void call_trans2open(connection_struct *conn,
                        goto out;
                }
 
-               if (ea_list_has_invalid_name(ea_list)) {
+               if (!req->posix_pathnames &&
+                               ea_list_has_invalid_name(ea_list)) {
                        int param_len = 30;
                        *pparams = (char *)SMB_REALLOC(*pparams, param_len);
                        if(*pparams == NULL ) {
@@ -1260,7 +1415,7 @@ static void call_trans2open(connection_struct *conn,
        SSVAL(params,0,fsp->fnum);
        SSVAL(params,2,fattr);
        srv_put_dos_date2(params,4, mtime);
-       SIVAL(params,8, (uint32)size);
+       SIVAL(params,8, (uint32_t)size);
        SSVAL(params,12,deny_mode);
        SSVAL(params,14,0); /* open_type - file or directory. */
        SSVAL(params,16,0); /* open_state - only valid for IPC device. */
@@ -1277,7 +1432,7 @@ 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,
+               uint32_t ea_size = estimate_ea_size(conn, fsp,
                                                  smb_fname);
                SIVAL(params, 26, ea_size);
        } else {
@@ -1321,7 +1476,7 @@ static bool exact_match(bool has_wild,
  Return the filetype for UNIX extensions.
 ****************************************************************************/
 
-static uint32 unix_filetype(mode_t mode)
+static uint32_t unix_filetype(mode_t mode)
 {
        if(S_ISREG(mode))
                return UNIX_TYPE_FILE;
@@ -1360,7 +1515,7 @@ enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_
 
 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
                                const SMB_STRUCT_STAT *psbuf,
-                               uint32 perms,
+                               uint32_t perms,
                                enum perm_type ptype,
                                mode_t *ret_perms)
 {
@@ -1422,18 +1577,18 @@ static NTSTATUS unix_perms_from_wire( connection_struct *conn,
 ****************************************************************************/
 
 static bool check_msdfs_link(connection_struct *conn,
-                               const char *pathname,
-                               SMB_STRUCT_STAT *psbuf)
+                               struct smb_filename *smb_fname)
 {
        int saved_errno = errno;
        if(lp_host_msdfs() &&
                lp_msdfs_root(SNUM(conn)) &&
-               is_msdfs_link(conn, pathname, psbuf)) {
+               is_msdfs_link(conn, smb_fname)) {
 
                DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
                        "as a directory\n",
-                       pathname));
-               psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
+                       smb_fname->base_name));
+               smb_fname->st.st_ex_mode =
+                       (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
                errno = saved_errno;
                return true;
        }
@@ -1477,7 +1632,7 @@ static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
                size_t ret_len = 0;
                size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
                uint8_t *tmp = talloc_array(talloc_tos(),
-                                       uint8,
+                                       uint8_t,
                                        len);
 
                status = srvstr_push(NULL,
@@ -1574,8 +1729,7 @@ static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
                 * directories */
 
                ms_dfs_link = check_msdfs_link(state->conn,
-                                              smb_fname->base_name,
-                                              &smb_fname->st);
+                                              smb_fname);
                if (!ms_dfs_link) {
                        DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
                                 "Couldn't stat [%s] (%s)\n",
@@ -1619,7 +1773,10 @@ static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
        uint64_t allocation_size = 0;
        uint64_t file_index = 0;
        size_t len = 0;
-       struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
+       struct timespec mdate_ts = {0};
+       struct timespec adate_ts = {0};
+       struct timespec cdate_ts = {0};
+       struct timespec create_date_ts = {0};
        time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
        char *nameptr;
        char *last_entry_ptr;
@@ -1627,17 +1784,20 @@ static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
        int off;
        int pad = 0;
        NTSTATUS status;
-
-       ZERO_STRUCT(mdate_ts);
-       ZERO_STRUCT(adate_ts);
-       ZERO_STRUCT(create_date_ts);
-       ZERO_STRUCT(cdate_ts);
+       struct readdir_attr_data *readdir_attr_data = NULL;
 
        if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
                file_size = get_file_size_stat(&smb_fname->st);
        }
        allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
 
+       status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
+       if (!NT_STATUS_IS_OK(status)) {
+               if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
+                       return status;
+               }
+       }
+
        file_index = get_FileIndex(conn, &smb_fname->st);
 
        mdate_ts = smb_fname->st.st_ex_mtime;
@@ -1698,8 +1858,8 @@ static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                srv_put_dos_date2(p,0,create_date);
                srv_put_dos_date2(p,4,adate);
                srv_put_dos_date2(p,8,mdate);
-               SIVAL(p,12,(uint32)file_size);
-               SIVAL(p,16,(uint32)allocation_size);
+               SIVAL(p,12,(uint32_t)file_size);
+               SIVAL(p,16,(uint32_t)allocation_size);
                SSVAL(p,20,mode);
                p += 23;
                nameptr = p;
@@ -1737,8 +1897,8 @@ static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                srv_put_dos_date2(p,0,create_date);
                srv_put_dos_date2(p,4,adate);
                srv_put_dos_date2(p,8,mdate);
-               SIVAL(p,12,(uint32)file_size);
-               SIVAL(p,16,(uint32)allocation_size);
+               SIVAL(p,12,(uint32_t)file_size);
+               SIVAL(p,16,(uint32_t)allocation_size);
                SSVAL(p,20,mode);
                {
                        unsigned int ea_size = estimate_ea_size(conn, NULL,
@@ -1787,8 +1947,8 @@ static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                srv_put_dos_date2(p,0,create_date);
                srv_put_dos_date2(p,4,adate);
                srv_put_dos_date2(p,8,mdate);
-               SIVAL(p,12,(uint32)file_size);
-               SIVAL(p,16,(uint32)allocation_size);
+               SIVAL(p,12,(uint32_t)file_size);
+               SIVAL(p,16,(uint32_t)allocation_size);
                SSVAL(p,20,mode);
                p += 22; /* p now points to the EA area. */
 
@@ -2098,17 +2258,41 @@ static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                q = p; p += 4; /* q is placeholder for name length */
                if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
                        SIVAL(p, 0, IO_REPARSE_TAG_DFS);
+               } else if (readdir_attr_data &&
+                          readdir_attr_data->type == RDATTR_AAPL) {
+                       /*
+                        * OS X specific SMB2 extension negotiated via
+                        * AAPL create context: return max_access in
+                        * ea_size field.
+                        */
+                       SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
                } else {
                        unsigned int ea_size = estimate_ea_size(conn, NULL,
                                                                smb_fname);
                        SIVAL(p,0,ea_size); /* Extended attributes */
                }
                p += 4;
-               /* Clear the short name buffer. This is
-                * IMPORTANT as not doing so will trigger
-                * a Win2k client bug. JRA.
-                */
-               if (!was_8_3 && check_mangled_names) {
+
+               if (readdir_attr_data &&
+                   readdir_attr_data->type == RDATTR_AAPL) {
+                       /*
+                        * OS X specific SMB2 extension negotiated via
+                        * AAPL create context: return resource fork
+                        * length and compressed FinderInfo in
+                        * shortname field.
+                        *
+                        * According to documentation short_name_len
+                        * should be 0, but on the wire behaviour
+                        * shows its set to 24 by clients.
+                        */
+                       SSVAL(p, 0, 24);
+
+                       /* Resourefork length */
+                       SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
+
+                       /* Compressed FinderInfo */
+                       memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
+               } else if (!was_8_3 && check_mangled_names) {
                        char mangled_name[13]; /* mangled 8.3 name. */
                        if (!name_to_8_3(fname,mangled_name,True,
                                        conn->params)) {
@@ -2128,10 +2312,29 @@ static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                        }
                        SSVAL(p, 0, len);
                } else {
+                       /* Clear the short name buffer. This is
+                        * IMPORTANT as not doing so will trigger
+                        * a Win2k client bug. JRA.
+                        */
                        memset(p,'\0',26);
                }
                p += 26;
-               SSVAL(p,0,0); p += 2; /* Reserved ? */
+
+               /* Reserved ? */
+               if (readdir_attr_data &&
+                   readdir_attr_data->type == RDATTR_AAPL) {
+                       /*
+                        * OS X specific SMB2 extension negotiated via
+                        * AAPL create context: return UNIX mode in
+                        * reserved field.
+                        */
+                       uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
+                       SSVAL(p, 0, aapl_mode);
+               } else {
+                       SSVAL(p, 0, 0);
+               }
+               p += 2;
+
                SBVAL(p,0,file_index); p += 8;
                status = srvstr_push(base_data, flags2, p,
                                  fname, PTR_DIFF(end_data, p),
@@ -2240,9 +2443,9 @@ static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
                               connection_struct *conn,
                               struct dptr_struct *dirptr,
-                              uint16 flags2,
+                              uint16_t flags2,
                               const char *path_mask,
-                              uint32 dirtype,
+                              uint32_t dirtype,
                               int info_level,
                               int requires_resume_key,
                               bool dont_descend,
@@ -2255,7 +2458,8 @@ NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
                               int space_remaining,
                               bool *got_exact_match,
                               int *_last_entry_off,
-                              struct ea_list *name_list)
+                              struct ea_list *name_list,
+                              struct file_id *file_id)
 {
        const char *p;
        const char *mask = NULL;
@@ -2267,11 +2471,17 @@ NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
        bool ok;
        uint64_t last_entry_off = 0;
        NTSTATUS status;
+       enum mangled_names_options mangled_names;
+       bool marshall_with_83_names;
+
+       mangled_names = lp_mangled_names(conn->params);
 
        ZERO_STRUCT(state);
        state.conn = conn;
        state.info_level = info_level;
-       state.check_mangled_names = lp_mangled_names(conn->params);
+       if (mangled_names != MANGLED_NAMES_NO) {
+               state.check_mangled_names = true;
+       }
        state.has_wild = dptr_has_wild(dirptr);
        state.got_exact_match = false;
 
@@ -2307,12 +2517,14 @@ NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
 
        *got_exact_match = state.got_exact_match;
 
+       marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
+
        status = smbd_marshall_dir_entry(ctx,
                                     conn,
                                     flags2,
                                     info_level,
                                     name_list,
-                                    state.check_mangled_names,
+                                    marshall_with_83_names,
                                     requires_resume_key,
                                     mode,
                                     fname,
@@ -2324,6 +2536,15 @@ NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
                                     ppdata,
                                     end_data,
                                     &last_entry_off);
+       if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
+               DEBUG(1,("Conversion error: illegal character: %s\n",
+                        smb_fname_str_dbg(smb_fname)));
+       }
+
+       if (file_id != NULL) {
+               *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
+       }
+
        TALLOC_FREE(fname);
        TALLOC_FREE(smb_fname);
        if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
@@ -2341,9 +2562,9 @@ NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
                                connection_struct *conn,
                                struct dptr_struct *dirptr,
-                               uint16 flags2,
+                               uint16_t flags2,
                                const char *path_mask,
-                               uint32 dirtype,
+                               uint32_t dirtype,
                                int info_level,
                                bool requires_resume_key,
                                bool dont_descend,
@@ -2371,7 +2592,7 @@ static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
                                         ppdata, base_data, end_data,
                                         space_remaining,
                                         got_exact_match,
-                                        last_entry_off, name_list);
+                                        last_entry_off, name_list, NULL);
 }
 
 /****************************************************************************
@@ -2393,9 +2614,9 @@ static void call_trans2findfirst(connection_struct *conn,
        char *params = *pparams;
        char *pdata = *ppdata;
        char *data_end;
-       uint32 dirtype;
+       uint32_t dirtype;
        int maxentries;
-       uint16 findfirst_flags;
+       uint16_t findfirst_flags;
        bool close_after_first;
        bool close_if_end;
        bool requires_resume_key;
@@ -2415,11 +2636,12 @@ static void call_trans2findfirst(connection_struct *conn,
        struct ea_list *ea_list = NULL;
        NTSTATUS ntstatus = NT_STATUS_OK;
        bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
-       TALLOC_CTX *ctx = talloc_tos();
        struct dptr_struct *dirptr = NULL;
        struct smbd_server_connection *sconn = req->sconn;
-       uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
+       uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
+                       ucf_flags_from_smb_request(req);
        bool backup_priv = false;
+       bool as_root = false;
 
        if (total_params < 13) {
                reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
@@ -2475,9 +2697,27 @@ close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_da
                        goto out;
        }
 
-       srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
-                             params+12, total_params - 12,
-                             STR_TERMINATE, &ntstatus, &mask_contains_wcard);
+       if (req->posix_pathnames) {
+               srvstr_get_path_wcard_posix(talloc_tos(),
+                               params,
+                               req->flags2,
+                               &directory,
+                               params+12,
+                               total_params - 12,
+                               STR_TERMINATE,
+                               &ntstatus,
+                               &mask_contains_wcard);
+       } else {
+               srvstr_get_path_wcard(talloc_tos(),
+                               params,
+                               req->flags2,
+                               &directory,
+                               params+12,
+                               total_params - 12,
+                               STR_TERMINATE,
+                               &ntstatus,
+                               &mask_contains_wcard);
+       }
        if (!NT_STATUS_IS_OK(ntstatus)) {
                reply_nterror(req, ntstatus);
                goto out;
@@ -2485,7 +2725,8 @@ close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_da
 
        if (backup_priv) {
                become_root();
-               ntstatus = filename_convert_with_privilege(ctx,
+               as_root = true;
+               ntstatus = filename_convert_with_privilege(talloc_tos(),
                                conn,
                                req,
                                directory,
@@ -2493,8 +2734,7 @@ close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_da
                                &mask_contains_wcard,
                                &smb_dname);
        } else {
-               ntstatus = filename_convert(ctx, conn,
-                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
+               ntstatus = filename_convert(talloc_tos(), conn,
                                    directory,
                                    ucf_flags,
                                    &mask_contains_wcard,
@@ -2519,7 +2759,7 @@ close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_da
        if(p == NULL) {
                /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
                if((directory[0] == '.') && (directory[1] == '\0')) {
-                       mask = talloc_strdup(ctx,"*");
+                       mask = talloc_strdup(talloc_tos(),"*");
                        if (!mask) {
                                reply_nterror(req, NT_STATUS_NO_MEMORY);
                                goto out;
@@ -2537,12 +2777,14 @@ close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_da
                        reply_nterror(req, NT_STATUS_NO_MEMORY);
                        goto out;
                }
+               /* Ensure smb_dname->base_name matches. */
+               smb_dname->base_name = directory;
        }
 
        DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
 
        if (info_level == SMB_FIND_EA_LIST) {
-               uint32 ea_size;
+               uint32_t ea_size;
 
                if (total_data < 4) {
                        reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
@@ -2563,7 +2805,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                }
 
                /* Pull out the list of names. */
-               ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
+               ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
                if (!ea_list) {
                        reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
                        goto out;
@@ -2583,7 +2825,11 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
        }
        pdata = *ppdata;
        data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
-
+       /*
+        * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
+        * error.
+        */
+       memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
        /* Realloc the params space */
        *pparams = (char *)SMB_REALLOC(*pparams, 10);
        if (*pparams == NULL) {
@@ -2598,7 +2844,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
        ntstatus = dptr_create(conn,
                                req,
                                NULL, /* fsp */
-                               directory,
+                               smb_dname,
                                False,
                                True,
                                req->smbpid,
@@ -2628,9 +2874,12 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                a different TRANS2 call. */
 
        DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
-                directory,lp_dont_descend(ctx, SNUM(conn))));
-       if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
+                directory,lp_dont_descend(talloc_tos(), SNUM(conn))));
+       if (in_list(directory,
+                       lp_dont_descend(talloc_tos(), SNUM(conn)),
+                       conn->case_sensitive)) {
                dont_descend = True;
+       }
 
        p = pdata;
        space_remaining = max_data_bytes;
@@ -2645,7 +2894,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                        out_of_space = True;
                        finished = False;
                } else {
-                       ntstatus = get_lanman2_dir_entry(ctx,
+                       ntstatus = get_lanman2_dir_entry(talloc_tos(),
                                        conn,
                                        dirptr,
                                        req->flags2,
@@ -2755,7 +3004,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
        }
  out:
 
-       if (backup_priv) {
+       if (as_root) {
                unbecome_root();
        }
 
@@ -2783,9 +3032,9 @@ static void call_trans2findnext(connection_struct *conn,
        char *data_end;
        int dptr_num;
        int maxentries;
-       uint16 info_level;
-       uint32 resume_key;
-       uint16 findnext_flags;
+       uint16_t info_level;
+       uint32_t resume_key;
+       uint16_t findnext_flags;
        bool close_after_request;
        bool close_if_end;
        bool requires_resume_key;
@@ -2795,7 +3044,7 @@ static void call_trans2findnext(connection_struct *conn,
        const char *mask = NULL;
        const char *directory = NULL;
        char *p = NULL;
-       uint16 dirtype;
+       uint16_t dirtype;
        int numentries = 0;
        int i, last_entry_off=0;
        bool finished = False;
@@ -2809,6 +3058,7 @@ static void call_trans2findnext(connection_struct *conn,
        struct dptr_struct *dirptr;
        struct smbd_server_connection *sconn = req->sconn;
        bool backup_priv = false; 
+       bool as_root = false;
 
        if (total_params < 13) {
                reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
@@ -2827,10 +3077,27 @@ static void call_trans2findnext(connection_struct *conn,
 
        if (!continue_bit) {
                /* We only need resume_name if continue_bit is zero. */
-               srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
-                             params+12,
-                             total_params - 12, STR_TERMINATE, &ntstatus,
-                             &mask_contains_wcard);
+               if (req->posix_pathnames) {
+                       srvstr_get_path_wcard_posix(ctx,
+                               params,
+                               req->flags2,
+                               &resume_name,
+                               params+12,
+                               total_params - 12,
+                               STR_TERMINATE,
+                               &ntstatus,
+                               &mask_contains_wcard);
+               } else {
+                       srvstr_get_path_wcard(ctx,
+                               params,
+                               req->flags2,
+                               &resume_name,
+                               params+12,
+                               total_params - 12,
+                               STR_TERMINATE,
+                               &ntstatus,
+                               &mask_contains_wcard);
+               }
                if (!NT_STATUS_IS_OK(ntstatus)) {
                        /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
                           complain (it thinks we're asking for the directory above the shared
@@ -2886,7 +3153,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n",
        }
 
        if (info_level == SMB_FIND_EA_LIST) {
-               uint32 ea_size;
+               uint32_t ea_size;
 
                if (total_data < 4) {
                        reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
@@ -2929,6 +3196,11 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
        pdata = *ppdata;
        data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
 
+       /*
+        * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
+        * error.
+        */
+       memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
        /* Realloc the params space */
        *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
        if(*pparams == NULL ) {
@@ -2982,6 +3254,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 
        if (backup_priv) {
                become_root();
+               as_root = true;
        }
 
        /*
@@ -3083,7 +3356,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
        }
 
-       if (backup_priv) {
+       if (as_root) {
                unbecome_root();
        }
 
@@ -3158,10 +3431,12 @@ NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
        int snum = SNUM(conn);
        const char *fstype = lp_fstype(SNUM(conn));
        const char *filename = NULL;
-       uint32 additional_flags = 0;
+       const uint64_t bytes_per_sector = 512;
+       uint32_t additional_flags = 0;
        struct smb_filename smb_fname;
        SMB_STRUCT_STAT st;
        NTSTATUS status = NT_STATUS_OK;
+       uint64_t df_ret;
 
        if (fname == NULL || fname->base_name == NULL) {
                filename = ".";
@@ -3209,9 +3484,11 @@ NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
        switch (info_level) {
                case SMB_INFO_ALLOCATION:
                {
-                       uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
+                       uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
                        data_len = 18;
-                       if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
+                       df_ret = get_dfree_info(conn, &smb_fname, &bsize,
+                                               &dfree, &dsize);
+                       if (df_ret == (uint64_t)-1) {
                                return map_nt_error_from_unix(errno);
                        }
 
@@ -3228,13 +3505,18 @@ NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
                                dsize *= factor;
                                dfree *= factor;
                        }
-                       bytes_per_sector = 512;
                        sectors_per_unit = bsize/bytes_per_sector;
 
                        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));
 
+                       /*
+                        * For large drives, return max values and not modulo.
+                        */
+                       dsize = MIN(dsize, UINT32_MAX);
+                       dfree = MIN(dfree, UINT32_MAX);
+
                        SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
                        SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
                        SIVAL(pdata,l1_cUnit,dsize);
@@ -3359,9 +3641,11 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
                case SMB_QUERY_FS_SIZE_INFO:
                case SMB_FS_SIZE_INFORMATION:
                {
-                       uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
+                       uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
                        data_len = 24;
-                       if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
+                       df_ret = get_dfree_info(conn, &smb_fname, &bsize,
+                                               &dfree, &dsize);
+                       if (df_ret == (uint64_t)-1) {
                                return map_nt_error_from_unix(errno);
                        }
                        block_size = lp_block_size(snum);
@@ -3377,7 +3661,6 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
                                dsize *= factor;
                                dfree *= factor;
                        }
-                       bytes_per_sector = 512;
                        sectors_per_unit = bsize/bytes_per_sector;
                        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,
@@ -3392,9 +3675,11 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
 
                case SMB_FS_FULL_SIZE_INFORMATION:
                {
-                       uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
+                       uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
                        data_len = 32;
-                       if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
+                       df_ret = get_dfree_info(conn, &smb_fname, &bsize,
+                                               &dfree, &dsize);
+                       if (df_ret == (uint64_t)-1) {
                                return map_nt_error_from_unix(errno);
                        }
                        block_size = lp_block_size(snum);
@@ -3410,7 +3695,6 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                                dsize *= factor;
                                dfree *= factor;
                        }
-                       bytes_per_sector = 512;
                        sectors_per_unit = bsize/bytes_per_sector;
                        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,
@@ -3482,9 +3766,11 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                                return NT_STATUS_ACCESS_DENIED;
                        }
 
-                       if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
+                       status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
+                                                NULL, &quotas);
+                       if (!NT_STATUS_IS_OK(status)) {
                                DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
-                               return map_nt_error_from_unix(errno);
+                               return status;
                        }
 
                        data_len = 48;
@@ -3528,6 +3814,34 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                        break;
                }
 
+               case SMB_FS_SECTOR_SIZE_INFORMATION:
+               {
+                       data_len = 28;
+                       /*
+                        * These values match a physical Windows Server 2012
+                        * share backed by NTFS atop spinning rust.
+                        */
+                       DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
+                       /* logical_bytes_per_sector */
+                       SIVAL(pdata, 0, bytes_per_sector);
+                       /* phys_bytes_per_sector_atomic */
+                       SIVAL(pdata, 4, bytes_per_sector);
+                       /* phys_bytes_per_sector_perf */
+                       SIVAL(pdata, 8, bytes_per_sector);
+                       /* fs_effective_phys_bytes_per_sector_atomic */
+                       SIVAL(pdata, 12, bytes_per_sector);
+                       /* flags */
+                       SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
+                               | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
+                       /* byte_off_sector_align */
+                       SIVAL(pdata, 20, 0);
+                       /* byte_off_partition_align */
+                       SIVAL(pdata, 24, 0);
+                       *fixed_portion = 28;
+                       break;
+               }
+
+
                /*
                 * Query the version and capabilities of the CIFS UNIX extensions
                 * in use.
@@ -3548,6 +3862,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                        case SMB_SIGNING_OFF:
                                encrypt_caps = 0;
                                break;
+                       case SMB_SIGNING_DESIRED:
                        case SMB_SIGNING_IF_REQUIRED:
                        case SMB_SIGNING_DEFAULT:
                                encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
@@ -3589,7 +3904,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                                return NT_STATUS_INVALID_LEVEL;
                        }
 
-                       rc = SMB_VFS_STATVFS(conn, filename, &svfs);
+                       rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
 
                        if (!rc) {
                                data_len = 56;
@@ -3704,7 +4019,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                                        &conn->session_info->security_token->sids[i],
                                        0);
 
-                               sid_linearize(pdata + data_len, sid_len,
+                               sid_linearize((uint8_t *)(pdata + data_len),
+                                             sid_len,
                                    &conn->session_info->security_token->sids[i]);
                                data_len += sid_len;
                        }
@@ -3731,6 +4047,86 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
        return status;
 }
 
+static NTSTATUS smb_set_fsquota(connection_struct *conn,
+                       struct smb_request *req,
+                       files_struct *fsp,
+                       const DATA_BLOB *qdata)
+{
+       NTSTATUS status;
+       SMB_NTQUOTA_STRUCT quotas;
+
+       ZERO_STRUCT(quotas);
+
+       /* access check */
+       if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
+               DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
+                         lp_servicename(talloc_tos(), SNUM(conn)),
+                         conn->session_info->unix_info->unix_name));
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       if (!check_fsp_ntquota_handle(conn, req,
+                                     fsp)) {
+               DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
+               return NT_STATUS_INVALID_HANDLE;
+       }
+
+       /* note: normally there're 48 bytes,
+        * but we didn't use the last 6 bytes for now
+        * --metze
+        */
+       if (qdata->length < 42) {
+               DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
+                       (unsigned int)qdata->length));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       /* unknown_1 24 NULL bytes in pdata*/
+
+       /* the soft quotas 8 bytes (uint64_t)*/
+       quotas.softlim = BVAL(qdata->data,24);
+
+       /* the hard quotas 8 bytes (uint64_t)*/
+       quotas.hardlim = BVAL(qdata->data,32);
+
+       /* quota_flags 2 bytes **/
+       quotas.qflags = SVAL(qdata->data,40);
+
+       /* unknown_2 6 NULL bytes follow*/
+
+       /* now set the quotas */
+       if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
+               DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
+                         lp_servicename(talloc_tos(), SNUM(conn))));
+               status =  map_nt_error_from_unix(errno);
+       } else {
+               status = NT_STATUS_OK;
+       }
+       return status;
+}
+
+NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
+                                struct smb_request *req,
+                                TALLOC_CTX *mem_ctx,
+                                uint16_t info_level,
+                                files_struct *fsp,
+                               const DATA_BLOB *pdata)
+{
+       switch (info_level) {
+               case SMB_FS_QUOTA_INFORMATION:
+               {
+                       return smb_set_fsquota(conn,
+                                               req,
+                                               fsp,
+                                               pdata);
+               }
+
+               default:
+                       break;
+       }
+       return NT_STATUS_INVALID_LEVEL;
+}
+
 /****************************************************************************
  Reply to a TRANS2_QFSINFO (query filesystem info).
 ****************************************************************************/
@@ -3800,7 +4196,7 @@ static void call_trans2setfsinfo(connection_struct *conn,
        struct smbXsrv_connection *xconn = req->xconn;
        char *pdata = *ppdata;
        char *params = *pparams;
-       uint16 info_level;
+       uint16_t info_level;
 
        DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
                  lp_servicename(talloc_tos(), SNUM(conn))));
@@ -3958,63 +4354,22 @@ static void call_trans2setfsinfo(connection_struct *conn,
 
                case SMB_FS_QUOTA_INFORMATION:
                        {
+                               NTSTATUS status;
+                               DATA_BLOB qdata = {
+                                               .data = (uint8_t *)pdata,
+                                               .length = total_data
+                               };
                                files_struct *fsp = NULL;
-                               SMB_NTQUOTA_STRUCT quotas;
-
-                               ZERO_STRUCT(quotas);
-
-                               /* access check */
-                               if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
-                                       DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
-                                                lp_servicename(talloc_tos(), SNUM(conn)),
-                                                conn->session_info->unix_info->unix_name));
-                                       reply_nterror(req, NT_STATUS_ACCESS_DENIED);
-                                       return;
-                               }
-
-                               /* note: normaly there're 48 bytes,
-                                * but we didn't use the last 6 bytes for now 
-                                * --metze 
-                                */
                                fsp = file_fsp(req, SVAL(params,0));
 
-                               if (!check_fsp_ntquota_handle(conn, req,
-                                                             fsp)) {
-                                       DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
-                                       reply_nterror(
-                                               req, NT_STATUS_INVALID_HANDLE);
-                                       return;
-                               }
-
-                               if (total_data < 42) {
-                                       DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
-                                               total_data));
-                                       reply_nterror(
-                                               req,
-                                               NT_STATUS_INVALID_PARAMETER);
-                                       return;
-                               }
-
-                               /* unknown_1 24 NULL bytes in pdata*/
-
-                               /* the soft quotas 8 bytes (uint64_t)*/
-                               quotas.softlim = BVAL(pdata,24);
-
-                               /* the hard quotas 8 bytes (uint64_t)*/
-                               quotas.hardlim = BVAL(pdata,32);
-
-                               /* quota_flags 2 bytes **/
-                               quotas.qflags = SVAL(pdata,40);
-
-                               /* unknown_2 6 NULL bytes follow*/
-
-                               /* 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(talloc_tos(), SNUM(conn))));
-                                       reply_nterror(req, map_nt_error_from_unix(errno));
+                               status = smb_set_fsquota(conn,
+                                                       req,
+                                                       fsp,
+                                                       &qdata);
+                               if (!NT_STATUS_IS_OK(status)) {
+                                       reply_nterror(req, status);
                                        return;
                                }
-
                                break;
                        }
                default:
@@ -4251,7 +4606,7 @@ static const struct {unsigned stat_fflag; unsigned smb_fflag;}
 };
 
 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
-                               uint32 *smb_fflags, uint32 *smb_fmask)
+                               uint32_t *smb_fflags, uint32_t *smb_fmask)
 {
        int i;
 
@@ -4264,11 +4619,11 @@ static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
 }
 
 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
-                               const uint32 smb_fflags,
-                               const uint32 smb_fmask,
+                               const uint32_t smb_fflags,
+                               const uint32_t smb_fmask,
                                int *stat_fflags)
 {
-       uint32 max_fmask = 0;
+       uint32_t max_fmask = 0;
        int i;
 
        *stat_fflags = psbuf->st_ex_flags;
@@ -4308,8 +4663,8 @@ static char *store_file_unix_basic_info2(connection_struct *conn,
                                files_struct *fsp,
                                const SMB_STRUCT_STAT *psbuf)
 {
-       uint32 file_flags = 0;
-       uint32 flags_mask = 0;
+       uint32_t file_flags = 0;
+       uint32_t flags_mask = 0;
 
        pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
 
@@ -4421,7 +4776,7 @@ static void call_trans2qpipeinfo(connection_struct *conn,
        char *pdata = *ppdata;
        unsigned int data_size = 0;
        unsigned int param_size = 2;
-       uint16 info_level;
+       uint16_t info_level;
        files_struct *fsp;
 
        if (!params) {
@@ -4644,8 +4999,8 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                        srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
                        srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
                        srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
-                       SIVAL(pdata,l1_cbFile,(uint32)file_size);
-                       SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
+                       SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
+                       SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
                        SSVAL(pdata,l1_attrFile,mode);
                        break;
 
@@ -4659,8 +5014,8 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                        srv_put_dos_date2(pdata,0,create_time);
                        srv_put_dos_date2(pdata,4,atime);
                        srv_put_dos_date2(pdata,8,mtime); /* write time */
-                       SIVAL(pdata,12,(uint32)file_size);
-                       SIVAL(pdata,16,(uint32)allocation_size);
+                       SIVAL(pdata,12,(uint32_t)file_size);
+                       SIVAL(pdata,16,(uint32_t)allocation_size);
                        SSVAL(pdata,20,mode);
                        SIVAL(pdata,22,ea_size);
                        break;
@@ -5016,8 +5371,12 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                                return NT_STATUS_INVALID_PARAMETER;
                        }
 
-                       status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
-                                               talloc_tos(), &num_streams, &streams);
+                       status = vfs_streaminfo(conn,
+                                               fsp,
+                                               smb_fname,
+                                               talloc_tos(),
+                                               &num_streams,
+                                               &streams);
 
                        if (!NT_STATUS_IS_OK(status)) {
                                DEBUG(10, ("could not get stream info: %s\n",
@@ -5123,7 +5482,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                                return NT_STATUS_DOS(ERRDOS, ERRbadlink);
 #endif
                                link_len = SMB_VFS_READLINK(conn,
-                                                      smb_fname->base_name,
+                                                      smb_fname,
                                                       buffer, PATH_MAX);
                                if (link_len == -1) {
                                        return map_nt_error_from_unix(errno);
@@ -5147,8 +5506,15 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                        {
                                SMB_ACL_T file_acl = NULL;
                                SMB_ACL_T def_acl = NULL;
-                               uint16 num_file_acls = 0;
-                               uint16 num_def_acls = 0;
+                               uint16_t num_file_acls = 0;
+                               uint16_t num_def_acls = 0;
+
+                               status = refuse_symlink(conn,
+                                               fsp,
+                                               smb_fname);
+                               if (!NT_STATUS_IS_OK(status)) {
+                                       return status;
+                               }
 
                                if (fsp && fsp->fh->fd != -1) {
                                        file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
@@ -5156,7 +5522,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                                } else {
                                        file_acl =
                                            SMB_VFS_SYS_ACL_GET_FILE(conn,
-                                               smb_fname->base_name,
+                                               smb_fname,
                                                SMB_ACL_TYPE_ACCESS,
                                                talloc_tos());
                                }
@@ -5174,14 +5540,14 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                                                def_acl =
                                                    SMB_VFS_SYS_ACL_GET_FILE(
                                                            conn,
-                                                           fsp->fsp_name->base_name,
+                                                           fsp->fsp_name,
                                                            SMB_ACL_TYPE_DEFAULT,
                                                            talloc_tos());
                                        } else {
                                                def_acl =
                                                    SMB_VFS_SYS_ACL_GET_FILE(
                                                            conn,
-                                                           smb_fname->base_name,
+                                                           smb_fname,
                                                            SMB_ACL_TYPE_DEFAULT,
                                                            talloc_tos());
                                        }
@@ -5323,7 +5689,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
 {
        char *params = *pparams;
        char *pdata = *ppdata;
-       uint16 info_level;
+       uint16_t info_level;
        unsigned int data_size = 0;
        unsigned int param_size = 2;
        struct smb_filename *smb_fname = NULL;
@@ -5435,7 +5801,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
        } else {
                uint32_t name_hash;
                char *fname = NULL;
-               uint32_t ucf_flags = 0;
+               uint32_t ucf_flags = ucf_flags_from_smb_request(req);
 
                /* qpathinfo */
                if (total_params < 7) {
@@ -5454,14 +5820,31 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
                        }
                        if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
                                        info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
-                                       info_level == SMB_QUERY_FILE_UNIX_LINK) {
+                                       info_level == SMB_QUERY_FILE_UNIX_LINK ||
+                                       req->posix_pathnames) {
                                ucf_flags |= UCF_UNIX_NAME_LOOKUP;
                        }
                }
 
-               srvstr_get_path(req, params, req->flags2, &fname, &params[6],
+               if (req->posix_pathnames) {
+                       srvstr_get_path_posix(req,
+                               params,
+                               req->flags2,
+                               &fname,
+                               &params[6],
+                               total_params - 6,
+                               STR_TERMINATE,
+                               &status);
+               } else {
+                       srvstr_get_path(req,
+                               params,
+                               req->flags2,
+                               &fname,
+                               &params[6],
                                total_params - 6,
-                               STR_TERMINATE, &status);
+                               STR_TERMINATE,
+                               &status);
+               }
                if (!NT_STATUS_IS_OK(status)) {
                        reply_nterror(req, status);
                        return;
@@ -5469,7 +5852,6 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
 
                status = filename_convert(req,
                                        conn,
-                                       req->flags2 & FLAGS2_DFS_PATHNAMES,
                                        fname,
                                        ucf_flags,
                                        NULL,
@@ -5492,14 +5874,17 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
 
                        /* Create an smb_filename with stream_name == NULL. */
                        smb_fname_base = synthetic_smb_fname(
-                               talloc_tos(), smb_fname->base_name,
-                               NULL, NULL);
+                                               talloc_tos(),
+                                               smb_fname->base_name,
+                                               NULL,
+                                               NULL,
+                                               smb_fname->flags);
                        if (smb_fname_base == NULL) {
                                reply_nterror(req, NT_STATUS_NO_MEMORY);
                                return;
                        }
 
-                       if (INFO_LEVEL_IS_UNIX(info_level)) {
+                       if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
                                /* Always do lstat for UNIX calls. */
                                if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
                                        DEBUG(3,("call_trans2qfilepathinfo: "
@@ -5545,7 +5930,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
                        }
                }
 
-               if (INFO_LEVEL_IS_UNIX(info_level)) {
+               if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
                        /* Always do lstat for UNIX calls. */
                        if (SMB_VFS_LSTAT(conn, smb_fname)) {
                                DEBUG(3,("call_trans2qfilepathinfo: "
@@ -5595,7 +5980,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
                case SMB_INFO_QUERY_EAS_FROM_LIST:
                {
                        /* Pull any EA list from the data portion. */
-                       uint32 ea_size;
+                       uint32_t ea_size;
 
                        if (total_data < 4) {
                                reply_nterror(
@@ -5763,8 +6148,7 @@ NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
        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, smb_fname_old->base_name,
-                        smb_fname_new->base_name) != 0) {
+       if (SMB_VFS_LINK(conn, smb_fname_old, smb_fname_new) != 0) {
                status = map_nt_error_from_unix(errno);
                DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
                         nt_errstr(status), smb_fname_old->base_name,
@@ -5786,7 +6170,7 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
                           bool setting_write_time)
 {
        struct smb_filename smb_fname_base;
-       uint32 action =
+       uint32_t action =
                FILE_NOTIFY_CHANGE_LAST_ACCESS
                |FILE_NOTIFY_CHANGE_LAST_WRITE
                |FILE_NOTIFY_CHANGE_CREATION;
@@ -5881,7 +6265,7 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
 
 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
                                     const struct smb_filename *smb_fname,
-                                    uint32 dosmode)
+                                    uint32_t dosmode)
 {
        struct smb_filename *smb_fname_base;
        NTSTATUS status;
@@ -5891,8 +6275,11 @@ static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
        }
 
        /* Always operate on the base_name, even if a stream was passed in. */
-       smb_fname_base = synthetic_smb_fname(
-               talloc_tos(), smb_fname->base_name, NULL, &smb_fname->st);
+       smb_fname_base = synthetic_smb_fname(talloc_tos(),
+                                       smb_fname->base_name,
+                                       NULL,
+                                       &smb_fname->st,
+                                       smb_fname->flags);
        if (smb_fname_base == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -6127,7 +6514,7 @@ static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
 {
        NTSTATUS status = NT_STATUS_OK;
        bool delete_on_close;
-       uint32 dosmode = 0;
+       uint32_t dosmode = 0;
 
        if (total_data < 1) {
                return NT_STATUS_INVALID_PARAMETER;
@@ -6200,7 +6587,7 @@ static NTSTATUS smb_file_mode_information(connection_struct *conn,
                                const char *pdata,
                                int total_data)
 {
-       uint32 mode;
+       uint32_t mode;
 
        if (total_data < 4) {
                return NT_STATUS_INVALID_PARAMETER;
@@ -6220,10 +6607,9 @@ static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
                                       struct smb_request *req,
                                       const char *pdata,
                                       int total_data,
-                                      const struct smb_filename *smb_fname)
+                                      const struct smb_filename *new_smb_fname)
 {
        char *link_target = NULL;
-       const char *newname = smb_fname->base_name;
        TALLOC_CTX *ctx = talloc_tos();
 
        /* Set a symbolic link. */
@@ -6245,9 +6631,9 @@ static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
        }
 
        DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
-                       newname, link_target ));
+                       new_smb_fname->base_name, link_target ));
 
-       if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
+       if (SMB_VFS_SYMLINK(conn,link_target,new_smb_fname) != 0) {
                return map_nt_error_from_unix(errno);
        }
 
@@ -6265,6 +6651,7 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
 {
        char *oldname = NULL;
        struct smb_filename *smb_fname_old = NULL;
+       uint32_t ucf_flags = ucf_flags_from_smb_request(req);
        TALLOC_CTX *ctx = talloc_tos();
        NTSTATUS status = NT_STATUS_OK;
 
@@ -6273,8 +6660,25 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
-                       total_data, STR_TERMINATE, &status);
+       if (req->posix_pathnames) {
+               srvstr_get_path_posix(ctx,
+                       pdata,
+                       req->flags2,
+                       &oldname,
+                       pdata,
+                       total_data,
+                       STR_TERMINATE,
+                       &status);
+       } else {
+               srvstr_get_path(ctx,
+                       pdata,
+                       req->flags2,
+                       &oldname,
+                       pdata,
+                       total_data,
+                       STR_TERMINATE,
+                       &status);
+       }
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -6284,9 +6688,8 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
 
        status = filename_convert(ctx,
                                conn,
-                               req->flags2 & FLAGS2_DFS_PATHNAMES,
                                oldname,
-                               0,
+                               ucf_flags,
                                NULL,
                                &smb_fname_old);
        if (!NT_STATUS_IS_OK(status)) {
@@ -6312,6 +6715,8 @@ static NTSTATUS smb2_file_rename_information(connection_struct *conn,
        uint32_t len;
        char *newname = NULL;
        struct smb_filename *smb_fname_dst = NULL;
+       uint32_t ucf_flags = UCF_SAVE_LCOMP |
+               ucf_flags_from_smb_request(req);
        NTSTATUS status = NT_STATUS_OK;
        TALLOC_CTX *ctx = talloc_tos();
 
@@ -6330,9 +6735,25 @@ static NTSTATUS smb2_file_rename_information(connection_struct *conn,
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       srvstr_get_path(ctx, pdata, req->flags2, &newname,
-                               &pdata[20], len, STR_TERMINATE,
+       if (req->posix_pathnames) {
+               srvstr_get_path_posix(ctx,
+                               pdata,
+                               req->flags2,
+                               &newname,
+                               &pdata[20],
+                               len,
+                               STR_TERMINATE,
                                &status);
+       } else {
+               srvstr_get_path(ctx,
+                               pdata,
+                               req->flags2,
+                               &newname,
+                               &pdata[20],
+                               len,
+                               STR_TERMINATE,
+                               &status);
+       }
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -6342,9 +6763,8 @@ static NTSTATUS smb2_file_rename_information(connection_struct *conn,
 
        status = filename_convert(ctx,
                                conn,
-                               req->flags2 & FLAGS2_DFS_PATHNAMES,
                                newname,
-                               UCF_SAVE_LCOMP,
+                               ucf_flags,
                                NULL,
                                &smb_fname_dst);
        if (!NT_STATUS_IS_OK(status)) {
@@ -6358,9 +6778,11 @@ static NTSTATUS smb2_file_rename_information(connection_struct *conn,
                }
 
                /* Create an smb_fname to call rename_internals_fsp() with. */
-               smb_fname_dst = synthetic_smb_fname(
-                       talloc_tos(), fsp->base_fsp->fsp_name->base_name,
-                       newname, NULL);
+               smb_fname_dst = synthetic_smb_fname(talloc_tos(),
+                                       fsp->base_fsp->fsp_name->base_name,
+                                       newname,
+                                       NULL,
+                                       fsp->base_fsp->fsp_name->flags);
                if (smb_fname_dst == NULL) {
                        status = NT_STATUS_NO_MEMORY;
                        goto out;
@@ -6404,6 +6826,8 @@ static NTSTATUS smb_file_link_information(connection_struct *conn,
        char *newname = NULL;
        struct smb_filename *smb_fname_dst = NULL;
        NTSTATUS status = NT_STATUS_OK;
+       uint32_t ucf_flags = UCF_SAVE_LCOMP |
+               ucf_flags_from_smb_request(req);
        TALLOC_CTX *ctx = talloc_tos();
 
        if (!fsp) {
@@ -6421,9 +6845,25 @@ static NTSTATUS smb_file_link_information(connection_struct *conn,
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       srvstr_get_path(ctx, pdata, req->flags2, &newname,
-                               &pdata[20], len, STR_TERMINATE,
+       if (req->posix_pathnames) {
+               srvstr_get_path_posix(ctx,
+                               pdata,
+                               req->flags2,
+                               &newname,
+                               &pdata[20],
+                               len,
+                               STR_TERMINATE,
+                               &status);
+       } else {
+               srvstr_get_path(ctx,
+                               pdata,
+                               req->flags2,
+                               &newname,
+                               &pdata[20],
+                               len,
+                               STR_TERMINATE,
                                &status);
+       }
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -6433,9 +6873,8 @@ static NTSTATUS smb_file_link_information(connection_struct *conn,
 
        status = filename_convert(ctx,
                                conn,
-                               req->flags2 & FLAGS2_DFS_PATHNAMES,
                                newname,
-                               UCF_SAVE_LCOMP,
+                               ucf_flags,
                                NULL,
                                &smb_fname_dst);
        if (!NT_STATUS_IS_OK(status)) {
@@ -6474,8 +6913,8 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
                                            struct smb_filename *smb_fname_src)
 {
        bool overwrite;
-       uint32 root_fid;
-       uint32 len;
+       uint32_t root_fid;
+       uint32_t len;
        char *newname = NULL;
        struct smb_filename *smb_fname_dst = NULL;
        bool dest_has_wcard = False;
@@ -6495,9 +6934,27 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
-                             len, 0, &status,
-                             &dest_has_wcard);
+       if (req->posix_pathnames) {
+               srvstr_get_path_wcard_posix(ctx,
+                               pdata,
+                               req->flags2,
+                               &newname,
+                               &pdata[12],
+                               len,
+                               0,
+                               &status,
+                               &dest_has_wcard);
+       } else {
+               srvstr_get_path_wcard(ctx,
+                               pdata,
+                               req->flags2,
+                               &newname,
+                               &pdata[12],
+                               len,
+                               0,
+                               &status,
+                               &dest_has_wcard);
+       }
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -6505,15 +6962,16 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
        DEBUG(10,("smb_file_rename_information: got name |%s|\n",
                                newname));
 
-       status = resolve_dfspath_wcard(ctx, conn,
-                                      req->flags2 & FLAGS2_DFS_PATHNAMES,
+       if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
+               status = resolve_dfspath_wcard(ctx, conn,
                                       newname,
-                                      true,
+                                      UCF_COND_ALLOW_WCARD_LCOMP,
                                       !conn->sconn->using_smb2,
                                       &newname,
                                       &dest_has_wcard);
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
        }
 
        /* Check the new name has no '/' characters. */
@@ -6528,9 +6986,11 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
                }
 
                /* Create an smb_fname to call rename_internals_fsp() with. */
-               smb_fname_dst = synthetic_smb_fname(
-                       talloc_tos(), fsp->base_fsp->fsp_name->base_name,
-                       newname, NULL);
+               smb_fname_dst = synthetic_smb_fname(talloc_tos(),
+                                       fsp->base_fsp->fsp_name->base_name,
+                                       newname,
+                                       NULL,
+                                       fsp->base_fsp->fsp_name->flags);
                if (smb_fname_dst == NULL) {
                        status = NT_STATUS_NO_MEMORY;
                        goto out;
@@ -6554,6 +7014,12 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
                 * the newname instead.
                 */
                char *base_name = NULL;
+               uint32_t ucf_flags = UCF_SAVE_LCOMP |
+                       ucf_flags_from_smb_request(req);
+
+               if (dest_has_wcard) {
+                       ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
+               }
 
                /* newname must *not* be a stream name. */
                if (newname[0] == ':') {
@@ -6586,10 +7052,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
                }
 
                status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
-                                     (UCF_SAVE_LCOMP |
-                                         (dest_has_wcard ?
-                                             UCF_ALWAYS_ALLOW_WCARD_LCOMP :
-                                             0)));
+                                       ucf_flags);
 
                /* If an error we expect this to be
                 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
@@ -6600,8 +7063,11 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
                                goto out;
                        }
                        /* Create an smb_fname to call rename_internals_fsp() */
-                       smb_fname_dst = synthetic_smb_fname(
-                               ctx, base_name, NULL, NULL);
+                       smb_fname_dst = synthetic_smb_fname(ctx,
+                                               base_name,
+                                               NULL,
+                                               NULL,
+                                               smb_fname_src->flags);
                        if (smb_fname_dst == NULL) {
                                status = NT_STATUS_NO_MEMORY;
                                goto out;
@@ -6642,11 +7108,12 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
                                files_struct *fsp,
                                const struct smb_filename *smb_fname)
 {
-       uint16 posix_acl_version;
-       uint16 num_file_acls;
-       uint16 num_def_acls;
+       uint16_t posix_acl_version;
+       uint16_t num_file_acls;
+       uint16_t num_def_acls;
        bool valid_file_acls = True;
        bool valid_def_acls = True;
+       NTSTATUS status;
 
        if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
                return NT_STATUS_INVALID_PARAMETER;
@@ -6674,19 +7141,24 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
                return NT_STATUS_INVALID_PARAMETER;
        }
 
+       status = refuse_symlink(conn, fsp, smb_fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
        DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
                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,
-               smb_fname->base_name, num_file_acls,
+               smb_fname, 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,
-               smb_fname->base_name, &smb_fname->st, num_def_acls,
+               smb_fname, num_def_acls,
                pdata + SMB_POSIX_ACL_HEADER_SIZE +
                (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
                return map_nt_error_from_unix(errno);
@@ -6825,7 +7297,7 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
 {
        /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
        struct smb_file_time ft;
-       uint32 dosmode = 0;
+       uint32_t dosmode = 0;
        NTSTATUS status = NT_STATUS_OK;
 
        ZERO_STRUCT(ft);
@@ -7051,13 +7523,13 @@ static NTSTATUS smb_unix_mknod(connection_struct *conn,
                                        int total_data,
                                        const struct smb_filename *smb_fname)
 {
-       uint32 file_type = IVAL(pdata,56);
+       uint32_t file_type = IVAL(pdata,56);
 #if defined(HAVE_MAKEDEV)
-       uint32 dev_major = IVAL(pdata,60);
-       uint32 dev_minor = IVAL(pdata,68);
+       uint32_t dev_major = IVAL(pdata,60);
+       uint32_t dev_minor = IVAL(pdata,68);
 #endif
        SMB_DEV_T dev = (SMB_DEV_T)0;
-       uint32 raw_unixmode = IVAL(pdata,84);
+       uint32_t raw_unixmode = IVAL(pdata,84);
        NTSTATUS status;
        mode_t unixmode;
 
@@ -7105,7 +7577,7 @@ static NTSTATUS smb_unix_mknod(connection_struct *conn,
                  (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
 
        /* Ok - do the mknod. */
-       if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
+       if (SMB_VFS_MKNOD(conn, smb_fname, unixmode, dev) != 0) {
                return map_nt_error_from_unix(errno);
        }
 
@@ -7119,7 +7591,7 @@ static NTSTATUS smb_unix_mknod(connection_struct *conn,
                                    &parent, NULL)) {
                        return NT_STATUS_NO_MEMORY;
                }
-               inherit_access_posix_acl(conn, parent, smb_fname->base_name,
+               inherit_access_posix_acl(conn, parent, smb_fname,
                                         unixmode);
                TALLOC_FREE(parent);
        }
@@ -7139,7 +7611,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
                                        const struct smb_filename *smb_fname)
 {
        struct smb_file_time ft;
-       uint32 raw_unixmode;
+       uint32_t raw_unixmode;
        mode_t unixmode;
        off_t size = 0;
        uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
@@ -7261,7 +7733,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
                if (fsp && fsp->fh->fd != -1) {
                        ret = SMB_VFS_FCHMOD(fsp, unixmode);
                } else {
-                       ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode);
+                       ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
                }
                if (ret != 0) {
                        return map_nt_error_from_unix(errno);
@@ -7288,7 +7760,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
                         * UNIX extensions calls must always operate
                         * on symlinks.
                         */
-                       ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
+                       ret = SMB_VFS_LCHOWN(conn, smb_fname,
                                             set_owner, (gid_t)-1);
                }
 
@@ -7320,7 +7792,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
                         * UNIX extensions calls must always operate
                         * on symlinks.
                         */
-                       ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, (uid_t)-1,
+                       ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
                                  set_grp);
                }
                if (ret != 0) {
@@ -7395,8 +7867,8 @@ static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
                                        const struct smb_filename *smb_fname)
 {
        NTSTATUS status;
-       uint32 smb_fflags;
-       uint32 smb_fmask;
+       uint32_t smb_fflags;
+       uint32_t smb_fmask;
 
        if (total_data < 116) {
                return NT_STATUS_INVALID_PARAMETER;
@@ -7430,7 +7902,7 @@ static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
                        /* XXX: we should be  using SMB_VFS_FCHFLAGS here. */
                        return NT_STATUS_NOT_SUPPORTED;
                } else {
-                       if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
+                       if (SMB_VFS_CHFLAGS(conn, smb_fname,
                                            stat_fflags) != 0) {
                                return map_nt_error_from_unix(errno);
                        }
@@ -7457,11 +7929,11 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
                                int *pdata_return_size)
 {
        NTSTATUS status = NT_STATUS_OK;
-       uint32 raw_unixmode = 0;
-       uint32 mod_unixmode = 0;
+       uint32_t raw_unixmode = 0;
+       uint32_t mod_unixmode = 0;
        mode_t unixmode = (mode_t)0;
        files_struct *fsp = NULL;
-       uint16 info_level_return = 0;
+       uint16_t info_level_return = 0;
        int info;
        char *pdata = *ppdata;
 
@@ -7478,7 +7950,7 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
                return status;
        }
 
-       mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
+       mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
 
        DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
                  smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
@@ -7567,19 +8039,19 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
 {
        bool extended_oplock_granted = False;
        char *pdata = *ppdata;
-       uint32 flags = 0;
-       uint32 wire_open_mode = 0;
-       uint32 raw_unixmode = 0;
-       uint32 mod_unixmode = 0;
-       uint32 create_disp = 0;
-       uint32 access_mask = 0;
-       uint32 create_options = FILE_NON_DIRECTORY_FILE;
+       uint32_t flags = 0;
+       uint32_t wire_open_mode = 0;
+       uint32_t raw_unixmode = 0;
+       uint32_t mod_unixmode = 0;
+       uint32_t create_disp = 0;
+       uint32_t access_mask = 0;
+       uint32_t create_options = FILE_NON_DIRECTORY_FILE;
        NTSTATUS status = NT_STATUS_OK;
        mode_t unixmode = (mode_t)0;
        files_struct *fsp = NULL;
        int oplock_request = 0;
        int info = 0;
-       uint16 info_level_return = 0;
+       uint16_t info_level_return = 0;
 
        if (total_data < 18) {
                return NT_STATUS_INVALID_PARAMETER;
@@ -7690,7 +8162,7 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
                return status;
        }
 
-       mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
+       mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
 
        if (wire_open_mode & SMB_O_SYNC) {
                create_options |= FILE_WRITE_THROUGH;
@@ -7818,7 +8290,7 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
 {
        NTSTATUS status = NT_STATUS_OK;
        files_struct *fsp = NULL;
-       uint16 flags = 0;
+       uint16_t flags = 0;
        char del = 1;
        int info = 0;
        int create_options = 0;
@@ -8223,7 +8695,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
 {
        char *params = *pparams;
        char *pdata = *ppdata;
-       uint16 info_level;
+       uint16_t info_level;
        struct smb_filename *smb_fname = NULL;
        files_struct *fsp = NULL;
        NTSTATUS status = NT_STATUS_OK;
@@ -8315,7 +8787,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
                }
        } else {
                char *fname = NULL;
-               uint32_t ucf_flags = 0;
+               uint32_t ucf_flags = ucf_flags_from_smb_request(req);
 
                /* set path info */
                if (total_params < 7) {
@@ -8324,9 +8796,25 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
                }
 
                info_level = SVAL(params,0);
-               srvstr_get_path(req, params, req->flags2, &fname, &params[6],
-                               total_params - 6, STR_TERMINATE,
+               if (req->posix_pathnames) {
+                       srvstr_get_path_posix(req,
+                               params,
+                               req->flags2,
+                               &fname,
+                               &params[6],
+                               total_params - 6,
+                               STR_TERMINATE,
+                               &status);
+               } else {
+                       srvstr_get_path(req,
+                               params,
+                               req->flags2,
+                               &fname,
+                               &params[6],
+                               total_params - 6,
+                               STR_TERMINATE,
                                &status);
+               }
                if (!NT_STATUS_IS_OK(status)) {
                        reply_nterror(req, status);
                        return;
@@ -8340,7 +8828,6 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
                }
 
                status = filename_convert(req, conn,
-                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
                                         fname,
                                         ucf_flags,
                                         NULL,
@@ -8449,6 +8936,7 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
        char *directory = NULL;
        NTSTATUS status = NT_STATUS_OK;
        struct ea_list *ea_list = NULL;
+       uint32_t ucf_flags = ucf_flags_from_smb_request(req);
        TALLOC_CTX *ctx = talloc_tos();
 
        if (!CAN_WRITE(conn)) {
@@ -8461,9 +8949,25 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
                return;
        }
 
-       srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
-                       total_params - 4, STR_TERMINATE,
+       if (req->posix_pathnames) {
+               srvstr_get_path_posix(ctx,
+                       params,
+                       req->flags2,
+                       &directory,
+                       &params[4],
+                       total_params - 4,
+                       STR_TERMINATE,
                        &status);
+       } else {
+               srvstr_get_path(ctx,
+                       params,
+                       req->flags2,
+                       &directory,
+                       &params[4],
+                       total_params - 4,
+                       STR_TERMINATE,
+                       &status);
+       }
        if (!NT_STATUS_IS_OK(status)) {
                reply_nterror(req, status);
                return;
@@ -8473,9 +8977,8 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
 
        status = filename_convert(ctx,
                                conn,
-                               req->flags2 & FLAGS2_DFS_PATHNAMES,
                                directory,
-                               0,
+                               ucf_flags,
                                NULL,
                                &smb_dname);
 
@@ -8572,7 +9075,7 @@ static void call_trans2findnotifyfirst(connection_struct *conn,
                                       unsigned int max_data_bytes)
 {
        char *params = *pparams;
-       uint16 info_level;
+       uint16_t info_level;
 
        if (total_params < 6) {
                reply_nterror(req, NT_STATUS_INVALID_PARAMETER);