s3: smbd: Change open_streams_for_delete() to take a struct smb_filename *.
[samba.git] / source3 / smbd / trans2.c
index 70d29f291ef460fbd98e2afaa7eb149a8b42f406..b1eb9a9d2af1948e9e129b59024d5d1ea90f332c 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,15 @@ static char *store_file_unix_basic_info2(connection_struct *conn,
                                files_struct *fsp,
                                const SMB_STRUCT_STAT *psbuf);
 
+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 +72,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;
 }
 
 /********************************************************************
@@ -179,7 +185,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)) {
@@ -388,7 +394,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);
 
        }
 
@@ -743,7 +749,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 +773,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;
        }
 
@@ -860,7 +866,6 @@ void send_trans2_replies(connection_struct *conn,
        int data_alignment_offset = 0;
        bool overflow = False;
        struct smbXsrv_connection *xconn = req->xconn;
-       struct smbd_server_connection *sconn = xconn->sconn;
        int max_send = xconn->smb1.sessions.max_send;
 
        /* Modify the data_to_send and datasize and set the error if
@@ -888,7 +893,7 @@ void send_trans2_replies(connection_struct *conn,
                                        __LINE__,__FILE__);
                }
                show_msg((char *)req->outbuf);
-               if (!srv_send_smb(sconn,
+               if (!srv_send_smb(xconn,
                                (char *)req->outbuf,
                                true, req->seqnum+1,
                                IS_CONN_ENCRYPTED(conn),
@@ -1028,7 +1033,7 @@ void send_trans2_replies(connection_struct *conn,
 
                /* Send the packet */
                show_msg((char *)req->outbuf);
-               if (!srv_send_smb(sconn,
+               if (!srv_send_smb(xconn,
                                (char *)req->outbuf,
                                true, req->seqnum+1,
                                IS_CONN_ENCRYPTED(conn),
@@ -1068,7 +1073,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;
@@ -1076,7 +1081,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;
@@ -1085,13 +1090,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 = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
        TALLOC_CTX *ctx = talloc_tos();
 
        /*
@@ -1125,9 +1131,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;
@@ -1141,7 +1163,7 @@ static void call_trans2open(connection_struct *conn,
                                conn,
                                req->flags2 & FLAGS2_DFS_PATHNAMES,
                                fname,
-                               0,
+                               ucf_flags,
                                NULL,
                                &smb_fname);
        if (!NT_STATUS_IS_OK(status)) {
@@ -1228,10 +1250,11 @@ static void call_trans2open(connection_struct *conn,
                NULL,                                   /* sd */
                ea_list,                                /* ea_list */
                &fsp,                                   /* result */
-               &smb_action);                           /* psbuf */
+               &smb_action,                            /* psbuf */
+               NULL, NULL);                            /* create context */
 
        if (!NT_STATUS_IS_OK(status)) {
-               if (open_was_deferred(req->sconn, req->mid)) {
+               if (open_was_deferred(req->xconn, req->mid)) {
                        /* We have re-scheduled this call. */
                        goto out;
                }
@@ -1260,7 +1283,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 +1300,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 +1344,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 +1383,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)
 {
@@ -1469,6 +1492,31 @@ static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
 
        /* Mangle fname if it's an illegal name. */
        if (mangle_must_mangle(dname, state->conn->params)) {
+               /*
+                * Slow path - ensure we can push the original name as UCS2. If
+                * not, then just don't return this name.
+                */
+               NTSTATUS status;
+               size_t ret_len = 0;
+               size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
+               uint8_t *tmp = talloc_array(talloc_tos(),
+                                       uint8_t,
+                                       len);
+
+               status = srvstr_push(NULL,
+                       FLAGS2_UNICODE_STRINGS,
+                       tmp,
+                       dname,
+                       len,
+                       STR_TERMINATE,
+                       &ret_len);
+
+               TALLOC_FREE(tmp);
+
+               if (!NT_STATUS_IS_OK(status)) {
+                       return false;
+               }
+
                ok = name_to_8_3(dname, mangled_name,
                                 true, state->conn->params);
                if (!ok) {
@@ -1570,7 +1618,7 @@ static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
        return true;
 }
 
-static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
+static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                                    connection_struct *conn,
                                    uint16_t flags2,
                                    uint32_t info_level,
@@ -1586,7 +1634,6 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                                    char *base_data,
                                    char **ppdata,
                                    char *end_data,
-                                   bool *out_of_space,
                                    uint64_t *last_entry_off)
 {
        char *p, *q, *pdata = *ppdata;
@@ -1595,26 +1642,31 @@ static bool 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;
        bool was_8_3;
        int off;
        int pad = 0;
-
-       *out_of_space = false;
-
-       ZERO_STRUCT(mdate_ts);
-       ZERO_STRUCT(adate_ts);
-       ZERO_STRUCT(create_date_ts);
-       ZERO_STRUCT(cdate_ts);
+       NTSTATUS status;
+       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;
@@ -1641,12 +1693,11 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
        pad -= off;
 
        if (pad && pad > space_remaining) {
-               *out_of_space = true;
                DEBUG(9,("smbd_marshall_dir_entry: out of space "
                        "for padding (wanted %u, had %d)\n",
                        (unsigned int)pad,
                        space_remaining ));
-               return false; /* Not finished - just out of space */
+               return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
        }
 
        off += pad;
@@ -1676,17 +1727,20 @@ static bool 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;
                if (flags2 & FLAGS2_UNICODE_STRINGS) {
                        p += ucs2_align(base_data, p, 0);
                }
-               len = srvstr_push(base_data, flags2, p,
+               status = srvstr_push(base_data, flags2, p,
                                  fname, PTR_DIFF(end_data, p),
-                                 STR_TERMINATE);
+                                 STR_TERMINATE, &len);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
                if (flags2 & FLAGS2_UNICODE_STRINGS) {
                        if (len > 2) {
                                SCVAL(nameptr, -1, len - 2);
@@ -1712,8 +1766,8 @@ static bool 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,
@@ -1722,9 +1776,12 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                }
                p += 27;
                nameptr = p - 1;
-               len = srvstr_push(base_data, flags2,
+               status = srvstr_push(base_data, flags2,
                                  p, fname, PTR_DIFF(end_data, p),
-                                 STR_TERMINATE | STR_NOALIGN);
+                                 STR_TERMINATE | STR_NOALIGN, &len);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
                if (flags2 & FLAGS2_UNICODE_STRINGS) {
                        if (len > 2) {
                                len -= 2;
@@ -1747,11 +1804,10 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
        {
                struct ea_list *file_list = NULL;
                size_t ea_len = 0;
-               NTSTATUS status;
 
                DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
                if (!name_list) {
-                       return false;
+                       return NT_STATUS_INVALID_PARAMETER;
                }
                if (requires_resume_key) {
                        SIVAL(p,0,reskey);
@@ -1760,8 +1816,8 @@ static bool 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. */
 
@@ -1776,20 +1832,22 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                /* We need to determine if this entry will fit in the space available. */
                /* Max string size is 255 bytes. */
                if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
-                       *out_of_space = true;
                        DEBUG(9,("smbd_marshall_dir_entry: out of space "
                                "(wanted %u, had %d)\n",
                                (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
                                space_remaining ));
-                       return False; /* Not finished - just out of space */
+                       return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
                }
 
                /* Push the ea_data followed by the name. */
                p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
                nameptr = p;
-               len = srvstr_push(base_data, flags2,
+               status = srvstr_push(base_data, flags2,
                                  p + 1, fname, PTR_DIFF(end_data, p+1),
-                                 STR_TERMINATE | STR_NOALIGN);
+                                 STR_TERMINATE | STR_NOALIGN, &len);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
                if (flags2 & FLAGS2_UNICODE_STRINGS) {
                        if (len > 2) {
                                len -= 2;
@@ -1842,9 +1900,12 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                                memset(mangled_name,'\0',12);
                        }
                        mangled_name[12] = 0;
-                       len = srvstr_push(base_data, flags2,
+                       status = srvstr_push(base_data, flags2,
                                          p+2, mangled_name, 24,
-                                         STR_UPPER|STR_UNICODE);
+                                         STR_UPPER|STR_UNICODE, &len);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return status;
+                       }
                        if (len < 24) {
                                memset(p + 2 + len,'\0',24 - len);
                        }
@@ -1853,9 +1914,12 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                        memset(p,'\0',26);
                }
                p += 2 + 24;
-               len = srvstr_push(base_data, flags2, p,
+               status = srvstr_push(base_data, flags2, p,
                                  fname, PTR_DIFF(end_data, p),
-                                 STR_TERMINATE_ASCII);
+                                 STR_TERMINATE_ASCII, &len);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
                SIVAL(q,0,len);
                p += len;
 
@@ -1889,9 +1953,12 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                SOFF_T(p,0,file_size); p += 8;
                SOFF_T(p,0,allocation_size); p += 8;
                SIVAL(p,0,mode); p += 4;
-               len = srvstr_push(base_data, flags2,
+               status = srvstr_push(base_data, flags2,
                                  p + 4, fname, PTR_DIFF(end_data, p+4),
-                                 STR_TERMINATE_ASCII);
+                                 STR_TERMINATE_ASCII, &len);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
                SIVAL(p,0,len);
                p += 4 + len;
 
@@ -1932,9 +1999,12 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                        SIVAL(p,0,ea_size); /* Extended attributes */
                        p +=4;
                }
-               len = srvstr_push(base_data, flags2, p,
+               status = srvstr_push(base_data, flags2, p,
                                  fname, PTR_DIFF(end_data, p),
-                                 STR_TERMINATE_ASCII);
+                                 STR_TERMINATE_ASCII, &len);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
                SIVAL(q, 0, len);
                p += len;
 
@@ -1964,9 +2034,12 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                p += 4;
                /* this must *not* be null terminated or w2k gets in a loop trying to set an
                   acl on a dir (tridge) */
-               len = srvstr_push(base_data, flags2, p,
+               status = srvstr_push(base_data, flags2, p,
                                  fname, PTR_DIFF(end_data, p),
-                                 STR_TERMINATE_ASCII);
+                                 STR_TERMINATE_ASCII, &len);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
                SIVAL(p, -4, len);
                p += len;
 
@@ -2011,9 +2084,12 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                p += 4;
                SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
                SBVAL(p,0,file_index); p += 8;
-               len = srvstr_push(base_data, flags2, p,
+               status = srvstr_push(base_data, flags2, p,
                                  fname, PTR_DIFF(end_data, p),
-                                 STR_TERMINATE_ASCII);
+                                 STR_TERMINATE_ASCII, &len);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
                SIVAL(q, 0, len);
                p += len;
 
@@ -2051,17 +2127,41 @@ static bool 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)) {
@@ -2069,23 +2169,48 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                                memset(mangled_name,'\0',12);
                        }
                        mangled_name[12] = 0;
-                       len = srvstr_push(base_data, flags2,
+                       status = srvstr_push(base_data, flags2,
                                          p+2, mangled_name, 24,
-                                         STR_UPPER|STR_UNICODE);
+                                         STR_UPPER|STR_UNICODE, &len);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return status;
+                       }
                        SSVAL(p, 0, len);
                        if (len < 24) {
                                memset(p + 2 + len,'\0',24 - len);
                        }
                        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;
-               len = srvstr_push(base_data, flags2, p,
+               status = srvstr_push(base_data, flags2, p,
                                  fname, PTR_DIFF(end_data, p),
-                                 STR_TERMINATE_ASCII);
+                                 STR_TERMINATE_ASCII, &len);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
                SIVAL(q,0,len);
                p += len;
 
@@ -2121,17 +2246,23 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                        DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
                        p = store_file_unix_basic(conn, p,
                                                NULL, &smb_fname->st);
-                       len = srvstr_push(base_data, flags2, p,
+                       status = srvstr_push(base_data, flags2, p,
                                          fname, PTR_DIFF(end_data, p),
-                                         STR_TERMINATE);
+                                         STR_TERMINATE, &len);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return status;
+                       }
                } else {
                        DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
                        p = store_file_unix_basic_info2(conn, p,
                                                NULL, &smb_fname->st);
                        nameptr = p;
                        p += 4;
-                       len = srvstr_push(base_data, flags2, p, fname,
-                                         PTR_DIFF(end_data, p), 0);
+                       status = srvstr_push(base_data, flags2, p, fname,
+                                         PTR_DIFF(end_data, p), 0, &len);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return status;
+                       }
                        SIVAL(nameptr, 0, len);
                }
 
@@ -2159,16 +2290,15 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                break;
 
        default:
-               return false;
+               return NT_STATUS_INVALID_LEVEL;
        }
 
        if (PTR_DIFF(p,pdata) > space_remaining) {
-               *out_of_space = true;
                DEBUG(9,("smbd_marshall_dir_entry: out of space "
                        "(wanted %u, had %d)\n",
                        (unsigned int)PTR_DIFF(p,pdata),
                        space_remaining ));
-               return false; /* Not finished - just out of space */
+               return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
        }
 
        /* Setup the last entry pointer, as an offset from base_data */
@@ -2176,15 +2306,15 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
        /* Advance the data pointer to the next slot */
        *ppdata = p;
 
-       return true;
+       return NT_STATUS_OK;
 }
 
-bool smbd_dirptr_lanman2_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,
@@ -2195,7 +2325,6 @@ bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
                               char *base_data,
                               char *end_data,
                               int space_remaining,
-                              bool *out_of_space,
                               bool *got_exact_match,
                               int *_last_entry_off,
                               struct ea_list *name_list)
@@ -2209,6 +2338,7 @@ bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
        struct smbd_dirptr_lanman2_state state;
        bool ok;
        uint64_t last_entry_off = 0;
+       NTSTATUS status;
 
        ZERO_STRUCT(state);
        state.conn = conn;
@@ -2217,7 +2347,6 @@ bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
        state.has_wild = dptr_has_wild(dirptr);
        state.got_exact_match = false;
 
-       *out_of_space = false;
        *got_exact_match = false;
 
        p = strrchr_m(path_mask,'/');
@@ -2245,12 +2374,12 @@ bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
                                   &mode,
                                   &prev_dirpos);
        if (!ok) {
-               return false;
+               return NT_STATUS_END_OF_FILE;
        }
 
        *got_exact_match = state.got_exact_match;
 
-       ok = smbd_marshall_dir_entry(ctx,
+       status = smbd_marshall_dir_entry(ctx,
                                     conn,
                                     flags2,
                                     info_level,
@@ -2266,28 +2395,31 @@ bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
                                     base_data,
                                     ppdata,
                                     end_data,
-                                    out_of_space,
                                     &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)));
+       }
        TALLOC_FREE(fname);
        TALLOC_FREE(smb_fname);
-       if (*out_of_space) {
+       if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
                dptr_SeekDir(dirptr, prev_dirpos);
-               return false;
+               return status;
        }
-       if (!ok) {
-               return false;
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
 
        *_last_entry_off = last_entry_off;
-       return true;
+       return NT_STATUS_OK;
 }
 
-static bool get_lanman2_dir_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,
@@ -2296,7 +2428,6 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
                                char *base_data,
                                char *end_data,
                                int space_remaining,
-                               bool *out_of_space,
                                bool *got_exact_match,
                                int *last_entry_off,
                                struct ea_list *name_list)
@@ -2315,7 +2446,7 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
                                         align, do_pad,
                                         ppdata, base_data, end_data,
                                         space_remaining,
-                                        out_of_space, got_exact_match,
+                                        got_exact_match,
                                         last_entry_off, name_list);
 }
 
@@ -2338,9 +2469,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;
@@ -2360,11 +2491,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 |
+                       (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
        bool backup_priv = false;
+       bool as_root = false;
 
        if (total_params < 13) {
                reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
@@ -2420,9 +2552,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;
@@ -2430,7 +2580,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,
@@ -2438,7 +2589,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,
+               ntstatus = filename_convert(talloc_tos(), conn,
                                    req->flags2 & FLAGS2_DFS_PATHNAMES,
                                    directory,
                                    ucf_flags,
@@ -2464,7 +2615,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;
@@ -2482,12 +2633,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);
@@ -2508,7 +2661,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;
@@ -2528,7 +2681,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) {
@@ -2543,7 +2700,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
        ntstatus = dptr_create(conn,
                                req,
                                NULL, /* fsp */
-                               directory,
+                               smb_dname,
                                False,
                                True,
                                req->smbpid,
@@ -2573,9 +2730,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;
@@ -2590,7 +2750,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                        out_of_space = True;
                        finished = False;
                } else {
-                       finished = !get_lanman2_dir_entry(ctx,
+                       ntstatus = get_lanman2_dir_entry(talloc_tos(),
                                        conn,
                                        dirptr,
                                        req->flags2,
@@ -2598,14 +2758,24 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                                        requires_resume_key,dont_descend,
                                        ask_sharemode,
                                        &p,pdata,data_end,
-                                       space_remaining, &out_of_space,
+                                       space_remaining,
                                        &got_exact_match,
                                        &last_entry_off, ea_list);
+                       if (NT_STATUS_EQUAL(ntstatus,
+                                       NT_STATUS_ILLEGAL_CHARACTER)) {
+                               /*
+                                * Bad character conversion on name. Ignore this
+                                * entry.
+                                */
+                               continue;
+                       }
+                       if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
+                               out_of_space = true;
+                       } else {
+                               finished = !NT_STATUS_IS_OK(ntstatus);
+                       }
                }
 
-               if (finished && out_of_space)
-                       finished = False;
-
                if (!finished && !out_of_space)
                        numentries++;
 
@@ -2690,7 +2860,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();
        }
 
@@ -2718,9 +2888,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;
@@ -2730,7 +2900,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;
@@ -2744,6 +2914,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);
@@ -2762,10 +2933,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
@@ -2821,7 +3009,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);
@@ -2864,6 +3052,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 ) {
@@ -2917,6 +3110,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 
        if (backup_priv) {
                become_root();
+               as_root = true;
        }
 
        /*
@@ -2966,7 +3160,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                        out_of_space = True;
                        finished = False;
                } else {
-                       finished = !get_lanman2_dir_entry(ctx,
+                       ntstatus = get_lanman2_dir_entry(ctx,
                                                conn,
                                                dirptr,
                                                req->flags2,
@@ -2974,14 +3168,24 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                                                requires_resume_key,dont_descend,
                                                ask_sharemode,
                                                &p,pdata,data_end,
-                                               space_remaining, &out_of_space,
+                                               space_remaining,
                                                &got_exact_match,
                                                &last_entry_off, ea_list);
+                       if (NT_STATUS_EQUAL(ntstatus,
+                                       NT_STATUS_ILLEGAL_CHARACTER)) {
+                               /*
+                                * Bad character conversion on name. Ignore this
+                                * entry.
+                                */
+                               continue;
+                       }
+                       if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
+                               out_of_space = true;
+                       } else {
+                               finished = !NT_STATUS_IS_OK(ntstatus);
+                       }
                }
 
-               if (finished && out_of_space)
-                       finished = False;
-
                if (!finished && !out_of_space)
                        numentries++;
 
@@ -3008,7 +3212,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();
        }
 
@@ -3083,10 +3287,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 = ".";
@@ -3134,9 +3340,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, filename, &bsize, &dfree,
+                                               &dsize);
+                       if (df_ret == (uint64_t)-1) {
                                return map_nt_error_from_unix(errno);
                        }
 
@@ -3153,7 +3361,6 @@ 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, \
@@ -3181,11 +3388,14 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
                         * this call so try fixing this by adding a terminating null to
                         * the pushed string. The change here was adding the STR_TERMINATE. JRA.
                         */
-                       len = srvstr_push(
+                       status = srvstr_push(
                                pdata, flags2,
                                pdata+l2_vol_szVolLabel, vname,
                                PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
-                               STR_NOALIGN|STR_TERMINATE);
+                               STR_NOALIGN|STR_TERMINATE, &len);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return status;
+                       }
                        SCVAL(pdata,l2_vol_cch,len);
                        data_len = l2_vol_szVolLabel + len;
                        DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
@@ -3218,9 +3428,12 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
                        SIVAL(pdata,4,255); /* Max filename component length */
                        /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
                                and will think we can't do long filenames */
-                       len = srvstr_push(pdata, flags2, pdata+12, fstype,
+                       status = srvstr_push(pdata, flags2, pdata+12, fstype,
                                          PTR_DIFF(end_data, pdata+12),
-                                         STR_UNICODE);
+                                         STR_UNICODE, &len);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return status;
+                       }
                        SIVAL(pdata,8,len);
                        data_len = 12 + len;
                        if (max_data_bytes >= 16 && data_len > max_data_bytes) {
@@ -3234,8 +3447,11 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
 
                case SMB_QUERY_FS_LABEL_INFO:
                case SMB_FS_LABEL_INFORMATION:
-                       len = srvstr_push(pdata, flags2, pdata+4, vname,
-                                         PTR_DIFF(end_data, pdata+4), 0);
+                       status = srvstr_push(pdata, flags2, pdata+4, vname,
+                                         PTR_DIFF(end_data, pdata+4), 0, &len);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return status;
+                       }
                        data_len = 4 + len;
                        SIVAL(pdata,0,len);
                        break;
@@ -3251,9 +3467,12 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
                                (str_checksum(get_local_machine_name())<<16));
 
                        /* Max label len is 32 characters. */
-                       len = srvstr_push(pdata, flags2, pdata+18, vname,
+                       status = srvstr_push(pdata, flags2, pdata+18, vname,
                                          PTR_DIFF(end_data, pdata+18),
-                                         STR_UNICODE);
+                                         STR_UNICODE, &len);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return status;
+                       }
                        SIVAL(pdata,12,len);
                        data_len = 18+len;
 
@@ -3272,9 +3491,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, filename, &bsize, &dfree,
+                                               &dsize);
+                       if (df_ret == (uint64_t)-1) {
                                return map_nt_error_from_unix(errno);
                        }
                        block_size = lp_block_size(snum);
@@ -3290,7 +3511,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,
@@ -3305,9 +3525,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, filename, &bsize, &dfree,
+                                               &dsize);
+                       if (df_ret == (uint64_t)-1) {
                                return map_nt_error_from_unix(errno);
                        }
                        block_size = lp_block_size(snum);
@@ -3323,7 +3545,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,
@@ -3441,6 +3662,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.
@@ -3461,6 +3710,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;
@@ -3617,7 +3867,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;
                        }
@@ -3713,7 +3964,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))));
@@ -3885,7 +4136,7 @@ static void call_trans2setfsinfo(connection_struct *conn,
                                        return;
                                }
 
-                               /* note: normaly there're 48 bytes,
+                               /* note: normally there're 48 bytes,
                                 * but we didn't use the last 6 bytes for now 
                                 * --metze 
                                 */
@@ -4164,7 +4415,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;
 
@@ -4177,11 +4428,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;
@@ -4221,8 +4472,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);
 
@@ -4334,7 +4585,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) {
@@ -4557,8 +4808,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;
 
@@ -4572,8 +4823,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;
@@ -4735,10 +4986,13 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                                                True,conn->params)) {
                                return NT_STATUS_NO_MEMORY;
                        }
-                       len = srvstr_push(dstart, flags2,
+                       status = srvstr_push(dstart, flags2,
                                          pdata+4, mangled_name,
                                          PTR_DIFF(dend, pdata+4),
-                                         STR_UNICODE);
+                                         STR_UNICODE, &len);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return status;
+                       }
                        data_size = 4 + len;
                        SIVAL(pdata,0,len);
                        *fixed_portion = 8;
@@ -4750,10 +5004,13 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                        /*
                          this must be *exactly* right for ACLs on mapped drives to work
                         */
-                       len = srvstr_push(dstart, flags2,
+                       status = srvstr_push(dstart, flags2,
                                          pdata+4, dos_fname,
                                          PTR_DIFF(dend, pdata+4),
-                                         STR_UNICODE);
+                                         STR_UNICODE, &len);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return status;
+                       }
                        DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
                        data_size = 4 + len;
                        SIVAL(pdata,0,len);
@@ -4796,10 +5053,13 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                        pdata += 24;
                        SIVAL(pdata,0,ea_size);
                        pdata += 4; /* EA info */
-                       len = srvstr_push(dstart, flags2,
+                       status = srvstr_push(dstart, flags2,
                                          pdata+4, dos_fname,
                                          PTR_DIFF(dend, pdata+4),
-                                         STR_UNICODE);
+                                         STR_UNICODE, &len);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return status;
+                       }
                        SIVAL(pdata,0,len);
                        pdata += 4 + len;
                        data_size = PTR_DIFF(pdata,(*ppdata));
@@ -4833,10 +5093,13 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
 
                        pdata += 0x60;
 
-                       len = srvstr_push(dstart, flags2,
+                       status = srvstr_push(dstart, flags2,
                                          pdata+4, dos_fname,
                                          PTR_DIFF(dend, pdata+4),
-                                         STR_UNICODE);
+                                         STR_UNICODE, &len);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return status;
+                       }
                        SIVAL(pdata,0,len);
                        pdata += 4 + len;
                        data_size = PTR_DIFF(pdata,(*ppdata));
@@ -4917,8 +5180,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",
@@ -5030,10 +5297,13 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                                        return map_nt_error_from_unix(errno);
                                }
                                buffer[link_len] = 0;
-                               len = srvstr_push(dstart, flags2,
+                               status = srvstr_push(dstart, flags2,
                                                  pdata, buffer,
                                                  PTR_DIFF(dend, pdata),
-                                                 STR_TERMINATE);
+                                                 STR_TERMINATE, &len);
+                               if (!NT_STATUS_IS_OK(status)) {
+                                       return status;
+                               }
                                pdata += len;
                                data_size = PTR_DIFF(pdata,(*ppdata));
 
@@ -5045,8 +5315,8 @@ 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;
 
                                if (fsp && fsp->fh->fd != -1) {
                                        file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
@@ -5221,7 +5491,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;
@@ -5333,7 +5603,8 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
        } else {
                uint32_t name_hash;
                char *fname = NULL;
-               uint32_t ucf_flags = 0;
+               uint32_t ucf_flags = (req->posix_pathnames ?
+                               UCF_POSIX_PATHNAMES : 0);
 
                /* qpathinfo */
                if (total_params < 7) {
@@ -5357,9 +5628,25 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
                        }
                }
 
-               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);
+                               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;
@@ -5493,7 +5780,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(
@@ -5684,7 +5971,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;
@@ -5779,7 +6066,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;
@@ -5894,7 +6181,8 @@ static NTSTATUS smb_set_file_size(connection_struct *conn,
                NULL,                                   /* sd */
                NULL,                                   /* ea_list */
                &new_fsp,                               /* result */
-               NULL);                                  /* pinfo */
+               NULL,                                   /* pinfo */
+               NULL, NULL);                            /* create context */
 
        TALLOC_FREE(smb_fname_tmp);
 
@@ -6024,7 +6312,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;
@@ -6097,7 +6385,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;
@@ -6162,6 +6450,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 = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
        TALLOC_CTX *ctx = talloc_tos();
        NTSTATUS status = NT_STATUS_OK;
 
@@ -6170,8 +6459,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;
        }
@@ -6183,7 +6489,7 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
                                conn,
                                req->flags2 & FLAGS2_DFS_PATHNAMES,
                                oldname,
-                               0,
+                               ucf_flags,
                                NULL,
                                &smb_fname_old);
        if (!NT_STATUS_IS_OK(status)) {
@@ -6209,6 +6515,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 |
+               (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
        NTSTATUS status = NT_STATUS_OK;
        TALLOC_CTX *ctx = talloc_tos();
 
@@ -6227,9 +6535,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;
        }
@@ -6241,7 +6565,7 @@ static NTSTATUS smb2_file_rename_information(connection_struct *conn,
                                conn,
                                req->flags2 & FLAGS2_DFS_PATHNAMES,
                                newname,
-                               UCF_SAVE_LCOMP,
+                               ucf_flags,
                                NULL,
                                &smb_fname_dst);
        if (!NT_STATUS_IS_OK(status)) {
@@ -6301,6 +6625,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 |
+               (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
        TALLOC_CTX *ctx = talloc_tos();
 
        if (!fsp) {
@@ -6318,9 +6644,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;
        }
@@ -6332,7 +6674,7 @@ static NTSTATUS smb_file_link_information(connection_struct *conn,
                                conn,
                                req->flags2 & FLAGS2_DFS_PATHNAMES,
                                newname,
-                               UCF_SAVE_LCOMP,
+                               ucf_flags,
                                NULL,
                                &smb_fname_dst);
        if (!NT_STATUS_IS_OK(status)) {
@@ -6371,8 +6713,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;
@@ -6392,9 +6734,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;
        }
@@ -6539,9 +6899,9 @@ 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;
 
@@ -6722,7 +7082,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);
@@ -6880,7 +7240,8 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
                NULL,                                   /* sd */
                NULL,                                   /* ea_list */
                &new_fsp,                               /* result */
-               NULL);                                  /* pinfo */
+               NULL,                                   /* pinfo */
+               NULL, NULL);                            /* create context */
 
        if (!NT_STATUS_IS_OK(status)) {
                /* NB. We check for open_was_deferred in the caller. */
@@ -6947,13 +7308,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;
 
@@ -7035,7 +7396,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;
@@ -7157,7 +7518,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);
@@ -7184,7 +7545,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);
                }
 
@@ -7216,7 +7577,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) {
@@ -7291,8 +7652,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;
@@ -7353,11 +7714,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;
 
@@ -7374,7 +7735,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));
@@ -7396,7 +7757,8 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
                NULL,                                   /* sd */
                NULL,                                   /* ea_list */
                &fsp,                                   /* result */
-               &info);                                 /* pinfo */
+               &info,                                  /* pinfo */
+               NULL, NULL);                            /* create context */
 
         if (NT_STATUS_IS_OK(status)) {
                 close_file(req, fsp, NORMAL_CLOSE);
@@ -7462,19 +7824,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;
@@ -7585,7 +7947,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;
@@ -7629,7 +7991,8 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
                NULL,                                   /* sd */
                NULL,                                   /* ea_list */
                &fsp,                                   /* result */
-               &info);                                 /* pinfo */
+               &info,                                  /* pinfo */
+               NULL, NULL);                            /* create context */
 
        if (!NT_STATUS_IS_OK(status)) {
                return status;
@@ -7712,7 +8075,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;
@@ -7760,7 +8123,8 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
                NULL,                                   /* sd */
                NULL,                                   /* ea_list */
                &fsp,                                   /* result */
-               &info);                                 /* pinfo */
+               &info,                                  /* pinfo */
+               NULL, NULL);                            /* create context */
 
        if (!NT_STATUS_IS_OK(status)) {
                return status;
@@ -8116,7 +8480,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;
@@ -8208,7 +8572,8 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
                }
        } else {
                char *fname = NULL;
-               uint32_t ucf_flags = 0;
+               uint32_t ucf_flags = (req->posix_pathnames ?
+                       UCF_POSIX_PATHNAMES : 0);
 
                /* set path info */
                if (total_params < 7) {
@@ -8217,9 +8582,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;
@@ -8290,7 +8671,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
                                         ppdata, total_data,
                                         &data_return_size);
        if (!NT_STATUS_IS_OK(status)) {
-               if (open_was_deferred(req->sconn, req->mid)) {
+               if (open_was_deferred(req->xconn, req->mid)) {
                        /* We have re-scheduled this call. */
                        return;
                }
@@ -8342,6 +8723,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 = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
        TALLOC_CTX *ctx = talloc_tos();
 
        if (!CAN_WRITE(conn)) {
@@ -8354,9 +8736,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;
@@ -8368,7 +8766,7 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
                                conn,
                                req->flags2 & FLAGS2_DFS_PATHNAMES,
                                directory,
-                               0,
+                               ucf_flags,
                                NULL,
                                &smb_dname);
 
@@ -8465,7 +8863,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);
@@ -8602,6 +9000,8 @@ static void call_trans2ioctl(connection_struct *conn,
 {
        char *pdata = *ppdata;
        files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
+       NTSTATUS status;
+       size_t len = 0;
 
        /* check for an invalid fid before proceeding */
 
@@ -8625,12 +9025,20 @@ static void call_trans2ioctl(connection_struct *conn,
                /* Job number */
                SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
 
-               srvstr_push(pdata, req->flags2, pdata + 2,
+               status = srvstr_push(pdata, req->flags2, pdata + 2,
                            lp_netbios_name(), 15,
-                           STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
-               srvstr_push(pdata, req->flags2, pdata+18,
+                           STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
+               if (!NT_STATUS_IS_OK(status)) {
+                       reply_nterror(req, status);
+                       return;
+               }
+               status = srvstr_push(pdata, req->flags2, pdata+18,
                            lp_servicename(talloc_tos(), SNUM(conn)), 13,
-                           STR_ASCII|STR_TERMINATE); /* Service name */
+                           STR_ASCII|STR_TERMINATE, &len); /* Service name */
+               if (!NT_STATUS_IS_OK(status)) {
+                       reply_nterror(req, status);
+                       return;
+               }
                send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
                                    max_data_bytes);
                return;