]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
smbd: Move reply_trans2 to smb1_trans2.c
authorDavid Mulder <dmulder@suse.com>
Mon, 21 Mar 2022 18:29:26 +0000 (12:29 -0600)
committerJeremy Allison <jra@samba.org>
Thu, 7 Apr 2022 17:37:30 +0000 (17:37 +0000)
Signed-off-by: David Mulder <dmulder@suse.com>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/smbd/proto.h
source3/smbd/smb1_trans2.c
source3/smbd/smb1_trans2.h
source3/smbd/trans2.c

index e63e72e5ffebba4222d16bcea85500bf21ae4390..230ef07e169d560b3a280f9c1e6f3b6d0996e067 100644 (file)
@@ -1110,7 +1110,6 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
                           bool setting_write_time);
 void reply_findclose(struct smb_request *req);
 void reply_findnclose(struct smb_request *req);
-void reply_trans2(struct smb_request *req);
 void reply_transs2(struct smb_request *req);
 
 enum perm_type {
@@ -1125,6 +1124,13 @@ NTSTATUS unix_perms_from_wire(connection_struct *conn,
                              uint32_t perms,
                              enum perm_type ptype,
                              mode_t *ret_perms);
+struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata,
+                            size_t data_size);
+unsigned int estimate_ea_size(files_struct *fsp);
+NTSTATUS smb_set_fsquota(connection_struct *conn,
+                        struct smb_request *req,
+                        files_struct *fsp,
+                        const DATA_BLOB *qdata);
 
 /* The following definitions come from smbd/uid.c  */
 
index d63a239e2fd57fafc38970ec85bec8cfd7792546..bd14f592e893226889ad7edfc71a8e81b625783c 100644 (file)
@@ -47,6 +47,8 @@
 #include "source3/lib/substitute.h"
 #include "source3/lib/adouble.h"
 
+#define DIR_ENTRY_SAFETY_MARGIN 4096
+
 /****************************************************************************
   Send the required number of replies back.
   We assume all fields other than the data fields are
@@ -438,3 +440,2890 @@ static void smb_set_posix_lock_done(struct tevent_req *subreq)
        TALLOC_FREE(req);
        return;
 }
+
+/****************************************************************************
+ Read a list of EA names from an incoming data buffer. Create an ea_list with them.
+****************************************************************************/
+
+static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
+{
+       struct ea_list *ea_list_head = NULL;
+       size_t converted_size, offset = 0;
+
+       while (offset + 2 < data_size) {
+               struct ea_list *eal = talloc_zero(ctx, struct ea_list);
+               unsigned int namelen = CVAL(pdata,offset);
+
+               offset++; /* Go past the namelen byte. */
+
+               /* integer wrap paranioa. */
+               if ((offset + namelen < offset) || (offset + namelen < namelen) ||
+                               (offset > data_size) || (namelen > data_size) ||
+                               (offset + namelen >= data_size)) {
+                       break;
+               }
+               /* Ensure the name is null terminated. */
+               if (pdata[offset + namelen] != '\0') {
+                       return NULL;
+               }
+               if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
+                                      &converted_size)) {
+                       DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
+                                "failed: %s", strerror(errno)));
+               }
+               if (!eal->ea.name) {
+                       return NULL;
+               }
+
+               offset += (namelen + 1); /* Go past the name + terminating zero. */
+               DLIST_ADD_END(ea_list_head, eal);
+               DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
+       }
+
+       return ea_list_head;
+}
+
+/****************************************************************************
+ Reply to a TRANSACT2_OPEN.
+****************************************************************************/
+
+static void call_trans2open(connection_struct *conn,
+                           struct smb_request *req,
+                           char **pparams, int total_params,
+                           char **ppdata, int total_data,
+                           unsigned int max_data_bytes)
+{
+       struct smb_filename *smb_fname = NULL;
+       char *params = *pparams;
+       char *pdata = *ppdata;
+       int deny_mode;
+       int32_t open_attr;
+       bool oplock_request;
+#if 0
+       bool return_additional_info;
+       int16 open_sattr;
+       time_t open_time;
+#endif
+       int open_ofun;
+       uint32_t open_size;
+       char *pname;
+       char *fname = NULL;
+       off_t size=0;
+       int fattr=0,mtime=0;
+       SMB_INO_T inode = 0;
+       int smb_action = 0;
+       files_struct *fsp;
+       struct ea_list *ea_list = NULL;
+       uint16_t flags = 0;
+       NTSTATUS status;
+       uint32_t access_mask;
+       uint32_t share_mode;
+       uint32_t create_disposition;
+       uint32_t create_options = 0;
+       uint32_t private_flags = 0;
+       uint32_t ucf_flags = ucf_flags_from_smb_request(req);
+       TALLOC_CTX *ctx = talloc_tos();
+
+       /*
+        * Ensure we have enough parameters to perform the operation.
+        */
+
+       if (total_params < 29) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               goto out;
+       }
+
+       flags = SVAL(params, 0);
+       deny_mode = SVAL(params, 2);
+       open_attr = SVAL(params,6);
+        oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
+        if (oplock_request) {
+                oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
+        }
+
+#if 0
+       return_additional_info = BITSETW(params,0);
+       open_sattr = SVAL(params, 4);
+       open_time = make_unix_date3(params+8);
+#endif
+       open_ofun = SVAL(params,12);
+       open_size = IVAL(params,14);
+       pname = &params[28];
+
+       if (IS_IPC(conn)) {
+               reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
+               goto out;
+       }
+
+       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;
+       }
+
+       DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
+               fname, (unsigned int)deny_mode, (unsigned int)open_attr,
+               (unsigned int)open_ofun, open_size));
+
+       status = filename_convert(ctx,
+                               conn,
+                               fname,
+                               ucf_flags,
+                               0,
+                               &smb_fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+                       reply_botherror(req,
+                               NT_STATUS_PATH_NOT_COVERED,
+                               ERRSRV, ERRbadpath);
+                       goto out;
+               }
+               reply_nterror(req, status);
+               goto out;
+       }
+
+       if (open_ofun == 0) {
+               reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
+               goto out;
+       }
+
+       if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
+                                        open_ofun,
+                                        &access_mask, &share_mode,
+                                        &create_disposition,
+                                        &create_options,
+                                        &private_flags)) {
+               reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+               goto out;
+       }
+
+       /* Any data in this call is an EA list. */
+       if (total_data && (total_data != 4)) {
+               if (total_data < 10) {
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       goto out;
+               }
+
+               if (IVAL(pdata,0) > total_data) {
+                       DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
+                               IVAL(pdata,0), (unsigned int)total_data));
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       goto out;
+               }
+
+               ea_list = read_ea_list(talloc_tos(), pdata + 4,
+                                      total_data - 4);
+               if (!ea_list) {
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       goto out;
+               }
+
+               if (!lp_ea_support(SNUM(conn))) {
+                       reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
+                       goto out;
+               }
+
+               if (!req->posix_pathnames &&
+                               ea_list_has_invalid_name(ea_list)) {
+                       int param_len = 30;
+                       *pparams = (char *)SMB_REALLOC(*pparams, param_len);
+                       if(*pparams == NULL ) {
+                               reply_nterror(req, NT_STATUS_NO_MEMORY);
+                               goto out;
+                       }
+                       params = *pparams;
+                       memset(params, '\0', param_len);
+                       send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
+                               params, param_len, NULL, 0, max_data_bytes);
+                       goto out;
+               }
+       }
+
+       status = SMB_VFS_CREATE_FILE(
+               conn,                                   /* conn */
+               req,                                    /* req */
+               smb_fname,                              /* fname */
+               access_mask,                            /* access_mask */
+               share_mode,                             /* share_access */
+               create_disposition,                     /* create_disposition*/
+               create_options,                         /* create_options */
+               open_attr,                              /* file_attributes */
+               oplock_request,                         /* oplock_request */
+               NULL,                                   /* lease */
+               open_size,                              /* allocation_size */
+               private_flags,
+               NULL,                                   /* sd */
+               ea_list,                                /* ea_list */
+               &fsp,                                   /* result */
+               &smb_action,                            /* psbuf */
+               NULL, NULL);                            /* create context */
+
+       if (!NT_STATUS_IS_OK(status)) {
+               if (open_was_deferred(req->xconn, req->mid)) {
+                       /* We have re-scheduled this call. */
+                       goto out;
+               }
+
+               if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
+                       reply_openerror(req, status);
+                       goto out;
+               }
+
+               fsp = fcb_or_dos_open(
+                       req,
+                       smb_fname,
+                       access_mask,
+                       create_options,
+                       private_flags);
+               if (fsp == NULL) {
+                       bool ok = defer_smb1_sharing_violation(req);
+                       if (ok) {
+                               goto out;
+                       }
+                       reply_openerror(req, status);
+                       goto out;
+               }
+
+               smb_action = FILE_WAS_OPENED;
+       }
+
+       size = get_file_size_stat(&smb_fname->st);
+       fattr = fdos_mode(fsp);
+       mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
+       inode = smb_fname->st.st_ex_ino;
+       if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
+               close_file_free(req, &fsp, ERROR_CLOSE);
+               reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+               goto out;
+       }
+
+       /* Realloc the size of parameters and data we will return */
+       *pparams = (char *)SMB_REALLOC(*pparams, 30);
+       if(*pparams == NULL ) {
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               goto out;
+       }
+       params = *pparams;
+
+       SSVAL(params,0,fsp->fnum);
+       SSVAL(params,2,fattr);
+       srv_put_dos_date2(params,4, mtime);
+       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. */
+
+       if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
+               smb_action |= EXTENDED_OPLOCK_GRANTED;
+       }
+
+       SSVAL(params,18,smb_action);
+
+       /*
+        * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
+        */
+       SIVAL(params,20,inode);
+       SSVAL(params,24,0); /* Padding. */
+       if (flags & 8) {
+               uint32_t ea_size = estimate_ea_size(smb_fname->fsp);
+               SIVAL(params, 26, ea_size);
+       } else {
+               SIVAL(params, 26, 0);
+       }
+
+       /* Send the required number of replies */
+       send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
+ out:
+       TALLOC_FREE(smb_fname);
+}
+
+static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
+                               connection_struct *conn,
+                               struct dptr_struct *dirptr,
+                               uint16_t flags2,
+                               const char *path_mask,
+                               uint32_t dirtype,
+                               int info_level,
+                               bool requires_resume_key,
+                               bool dont_descend,
+                               bool ask_sharemode,
+                               char **ppdata,
+                               char *base_data,
+                               char *end_data,
+                               int space_remaining,
+                               bool *got_exact_match,
+                               int *last_entry_off,
+                               struct ea_list *name_list)
+{
+       uint8_t align = 4;
+       const bool do_pad = true;
+
+       if (info_level >= 1 && info_level <= 3) {
+               /* No alignment on earlier info levels. */
+               align = 1;
+       }
+
+       return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
+                                        path_mask, dirtype, info_level,
+                                        requires_resume_key, dont_descend, ask_sharemode,
+                                        true, align, do_pad,
+                                        ppdata, base_data, end_data,
+                                        space_remaining,
+                                        NULL,
+                                        got_exact_match,
+                                        last_entry_off, name_list, NULL);
+}
+
+/****************************************************************************
+ Reply to a TRANS2_FINDFIRST.
+****************************************************************************/
+
+static void call_trans2findfirst(connection_struct *conn,
+                                struct smb_request *req,
+                                char **pparams, int total_params,
+                                char **ppdata, int total_data,
+                                unsigned int max_data_bytes)
+{
+       /* We must be careful here that we don't return more than the
+               allowed number of data bytes. If this means returning fewer than
+               maxentries then so be it. We assume that the redirector has
+               enough room for the fixed number of parameter bytes it has
+               requested. */
+       struct smb_filename *smb_dname = NULL;
+       char *params = *pparams;
+       char *pdata = *ppdata;
+       char *data_end;
+       uint32_t dirtype;
+       int maxentries;
+       uint16_t findfirst_flags;
+       bool close_after_first;
+       bool close_if_end;
+       bool requires_resume_key;
+       int info_level;
+       char *directory = NULL;
+       char *mask = NULL;
+       char *p;
+       int last_entry_off=0;
+       int dptr_num = -1;
+       int numentries = 0;
+       int i;
+       bool finished = False;
+       bool dont_descend = False;
+       bool out_of_space = False;
+       int space_remaining;
+       struct ea_list *ea_list = NULL;
+       NTSTATUS ntstatus = NT_STATUS_OK;
+       bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
+       struct smbd_server_connection *sconn = req->sconn;
+       uint32_t ucf_flags = ucf_flags_from_smb_request(req);
+       bool backup_priv = false;
+       bool as_root = false;
+       files_struct *fsp = NULL;
+       const struct loadparm_substitution *lp_sub =
+               loadparm_s3_global_substitution();
+
+       if (total_params < 13) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               goto out;
+       }
+
+       dirtype = SVAL(params,0);
+       maxentries = SVAL(params,2);
+       findfirst_flags = SVAL(params,4);
+       close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
+       close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
+       requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
+       backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
+                               security_token_has_privilege(get_current_nttok(conn),
+                                               SEC_PRIV_BACKUP));
+
+       info_level = SVAL(params,6);
+
+       DBG_NOTICE("dirtype = %"PRIx32", maxentries = %d, "
+                  "close_after_first=%d, close_if_end = %d "
+                  "requires_resume_key = %d backup_priv = %d level = 0x%x, "
+                  "max_data_bytes = %d\n",
+                  dirtype,
+                  maxentries,
+                  close_after_first,
+                  close_if_end,
+                  requires_resume_key,
+                  backup_priv,
+                  info_level,
+                  max_data_bytes);
+
+       if (!maxentries) {
+               /* W2K3 seems to treat zero as 1. */
+               maxentries = 1;
+       }
+
+       switch (info_level) {
+               case SMB_FIND_INFO_STANDARD:
+               case SMB_FIND_EA_SIZE:
+               case SMB_FIND_EA_LIST:
+               case SMB_FIND_FILE_DIRECTORY_INFO:
+               case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
+               case SMB_FIND_FILE_NAMES_INFO:
+               case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
+               case SMB_FIND_ID_FULL_DIRECTORY_INFO:
+               case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
+                       break;
+               case SMB_FIND_FILE_UNIX:
+               case SMB_FIND_FILE_UNIX_INFO2:
+                       if (!lp_smb1_unix_extensions()) {
+                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                               goto out;
+                       }
+                       if (!req->posix_pathnames) {
+                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                               goto out;
+                       }
+                       break;
+               default:
+                       reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                       goto out;
+       }
+
+       if (req->posix_pathnames) {
+               /* Always use filesystem for UNIX mtime query. */
+               ask_sharemode = false;
+       }
+
+       if (req->posix_pathnames) {
+               srvstr_get_path_posix(talloc_tos(),
+                               params,
+                               req->flags2,
+                               &directory,
+                               params+12,
+                               total_params - 12,
+                               STR_TERMINATE,
+                               &ntstatus);
+       } else {
+               srvstr_get_path(talloc_tos(),
+                               params,
+                               req->flags2,
+                               &directory,
+                               params+12,
+                               total_params - 12,
+                               STR_TERMINATE,
+                               &ntstatus);
+       }
+       if (!NT_STATUS_IS_OK(ntstatus)) {
+               reply_nterror(req, ntstatus);
+               goto out;
+       }
+
+       if (backup_priv) {
+               become_root();
+               as_root = true;
+       }
+       ntstatus = filename_convert_smb1_search_path(talloc_tos(),
+                                                    conn,
+                                                    directory,
+                                                    ucf_flags,
+                                                    &smb_dname,
+                                                    &mask);
+
+       if (!NT_STATUS_IS_OK(ntstatus)) {
+               if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
+                       reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
+                                       ERRSRV, ERRbadpath);
+                       goto out;
+               }
+               reply_nterror(req, ntstatus);
+               goto out;
+       }
+
+       TALLOC_FREE(directory);
+       directory = smb_dname->base_name;
+
+       DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
+
+       if (info_level == SMB_FIND_EA_LIST) {
+               uint32_t ea_size;
+
+               if (total_data < 4) {
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       goto out;
+               }
+
+               ea_size = IVAL(pdata,0);
+               if (ea_size != total_data) {
+                       DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
+total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       goto out;
+               }
+
+               if (!lp_ea_support(SNUM(conn))) {
+                       reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
+                       goto out;
+               }
+
+               /* Pull out the list of names. */
+               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;
+               }
+       }
+
+       if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               goto out;
+       }
+
+       *ppdata = (char *)SMB_REALLOC(
+               *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
+       if(*ppdata == NULL ) {
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               goto out;
+       }
+       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) {
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               goto out;
+       }
+       params = *pparams;
+
+       /*
+        * Open an fsp on this directory for the dptr.
+        */
+       ntstatus = SMB_VFS_CREATE_FILE(
+                       conn, /* conn */
+                       req, /* req */
+                       smb_dname, /* dname */
+                       FILE_LIST_DIRECTORY, /* access_mask */
+                       FILE_SHARE_READ|
+                       FILE_SHARE_WRITE, /* share_access */
+                       FILE_OPEN, /* create_disposition*/
+                       FILE_DIRECTORY_FILE, /* create_options */
+                       FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
+                       NO_OPLOCK, /* oplock_request */
+                       NULL, /* lease */
+                       0, /* allocation_size */
+                       0, /* private_flags */
+                       NULL, /* sd */
+                       NULL, /* ea_list */
+                       &fsp, /* result */
+                       NULL, /* pinfo */
+                       NULL, /* in_context */
+                       NULL);/* out_context */
+
+       if (!NT_STATUS_IS_OK(ntstatus)) {
+               DBG_ERR("failed to open directory %s\n",
+                       smb_fname_str_dbg(smb_dname));
+               reply_nterror(req, ntstatus);
+               goto out;
+       }
+
+       /* Save the wildcard match and attribs we are using on this directory -
+               needed as lanman2 assumes these are being saved between calls */
+
+       ntstatus = dptr_create(conn,
+                               req,
+                               fsp, /* fsp */
+                               False,
+                               True,
+                               req->smbpid,
+                               mask,
+                               dirtype,
+                               &fsp->dptr);
+
+       if (!NT_STATUS_IS_OK(ntstatus)) {
+               /*
+                * Use NULL here for the first parameter (req)
+                * as this is not a client visible handle so
+                * can'tbe part of an SMB1 chain.
+                */
+               close_file_free(NULL, &fsp, NORMAL_CLOSE);
+               reply_nterror(req, ntstatus);
+               goto out;
+       }
+
+       if (backup_priv) {
+               /* Remember this in case we have
+                  to do a findnext. */
+               dptr_set_priv(fsp->dptr);
+       }
+
+       dptr_num = dptr_dnum(fsp->dptr);
+       DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
+
+       /* We don't need to check for VOL here as this is returned by
+               a different TRANS2 call. */
+
+       DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
+                directory,lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn))));
+       if (in_list(directory,
+                   lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn)),
+                       dptr_case_sensitive(fsp->dptr))) {
+               dont_descend = True;
+       }
+
+       p = pdata;
+       space_remaining = max_data_bytes;
+       out_of_space = False;
+
+       for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
+               bool got_exact_match = False;
+
+               /* this is a heuristic to avoid seeking the dirptr except when
+                       absolutely necessary. It allows for a filename of about 40 chars */
+               if (space_remaining < DIRLEN_GUESS && numentries > 0) {
+                       out_of_space = True;
+                       finished = False;
+               } else {
+                       ntstatus = get_lanman2_dir_entry(talloc_tos(),
+                                       conn,
+                                       fsp->dptr,
+                                       req->flags2,
+                                       mask,dirtype,info_level,
+                                       requires_resume_key,dont_descend,
+                                       ask_sharemode,
+                                       &p,pdata,data_end,
+                                       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)
+                       numentries++;
+
+               /*
+                * As an optimisation if we know we aren't looking
+                * for a wildcard name (ie. the name matches the wildcard exactly)
+                * then we can finish on any (first) match.
+                * This speeds up large directory searches. JRA.
+                */
+
+               if(got_exact_match)
+                       finished = True;
+
+               /* Ensure space_remaining never goes -ve. */
+               if (PTR_DIFF(p,pdata) > max_data_bytes) {
+                       space_remaining = 0;
+                       out_of_space = true;
+               } else {
+                       space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
+               }
+       }
+
+       /* Check if we can close the dirptr */
+       if(close_after_first || (finished && close_if_end)) {
+               DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
+               dptr_num = -1;
+               close_file_free(NULL, &fsp, NORMAL_CLOSE);
+       }
+
+       /*
+        * If there are no matching entries we must return ERRDOS/ERRbadfile -
+        * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
+        * the protocol level is less than NT1. Tested with smbclient. JRA.
+        * This should fix the OS/2 client bug #2335.
+        */
+
+       if(numentries == 0) {
+               dptr_num = -1;
+               /*
+                * We may have already closed the file in the
+                * close_after_first or finished case above.
+                */
+               if (fsp != NULL) {
+                       close_file_free(NULL, &fsp, NORMAL_CLOSE);
+               }
+               if (get_Protocol() < PROTOCOL_NT1) {
+                       reply_force_doserror(req, ERRDOS, ERRnofiles);
+                       goto out;
+               } else {
+                       reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
+                                       ERRDOS, ERRbadfile);
+                       goto out;
+               }
+       }
+
+       /* At this point pdata points to numentries directory entries. */
+
+       /* Set up the return parameter block */
+       SSVAL(params,0,dptr_num);
+       SSVAL(params,2,numentries);
+       SSVAL(params,4,finished);
+       SSVAL(params,6,0); /* Never an EA error */
+       SSVAL(params,8,last_entry_off);
+
+       send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
+                           max_data_bytes);
+
+       if ((! *directory) && dptr_path(sconn, dptr_num)) {
+               directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
+               if (!directory) {
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+               }
+       }
+
+       DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
+               smb_fn_name(req->cmd),
+               mask, directory, dirtype, numentries ) );
+
+       /*
+        * Force a name mangle here to ensure that the
+        * mask as an 8.3 name is top of the mangled cache.
+        * The reasons for this are subtle. Don't remove
+        * this code unless you know what you are doing
+        * (see PR#13758). JRA.
+        */
+
+       if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
+               char mangled_name[13];
+               name_to_8_3(mask, mangled_name, True, conn->params);
+       }
+ out:
+
+       if (as_root) {
+               unbecome_root();
+       }
+
+       TALLOC_FREE(smb_dname);
+       return;
+}
+
+/****************************************************************************
+ Reply to a TRANS2_FINDNEXT.
+****************************************************************************/
+
+static void call_trans2findnext(connection_struct *conn,
+                               struct smb_request *req,
+                               char **pparams, int total_params,
+                               char **ppdata, int total_data,
+                               unsigned int max_data_bytes)
+{
+       /* We must be careful here that we don't return more than the
+               allowed number of data bytes. If this means returning fewer than
+               maxentries then so be it. We assume that the redirector has
+               enough room for the fixed number of parameter bytes it has
+               requested. */
+       char *params = *pparams;
+       char *pdata = *ppdata;
+       char *data_end;
+       int dptr_num;
+       int maxentries;
+       uint16_t info_level;
+       uint32_t resume_key;
+       uint16_t findnext_flags;
+       bool close_after_request;
+       bool close_if_end;
+       bool requires_resume_key;
+       bool continue_bit;
+       char *resume_name = NULL;
+       const char *mask = NULL;
+       const char *directory = NULL;
+       char *p = NULL;
+       uint16_t dirtype;
+       int numentries = 0;
+       int i, last_entry_off=0;
+       bool finished = False;
+       bool dont_descend = False;
+       bool out_of_space = False;
+       int space_remaining;
+       struct ea_list *ea_list = NULL;
+       NTSTATUS ntstatus = NT_STATUS_OK;
+       bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
+       TALLOC_CTX *ctx = talloc_tos();
+       struct smbd_server_connection *sconn = req->sconn;
+       bool backup_priv = false;
+       bool as_root = false;
+       files_struct *fsp = NULL;
+       const struct loadparm_substitution *lp_sub =
+               loadparm_s3_global_substitution();
+
+       if (total_params < 13) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
+       }
+
+       dptr_num = SVAL(params,0);
+       maxentries = SVAL(params,2);
+       info_level = SVAL(params,4);
+       resume_key = IVAL(params,6);
+       findnext_flags = SVAL(params,10);
+       close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
+       close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
+       requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
+       continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
+
+       if (!continue_bit) {
+               /* We only need resume_name if continue_bit is zero. */
+               if (req->posix_pathnames) {
+                       srvstr_get_path_posix(ctx,
+                               params,
+                               req->flags2,
+                               &resume_name,
+                               params+12,
+                               total_params - 12,
+                               STR_TERMINATE,
+                               &ntstatus);
+               } else {
+                       srvstr_get_path(ctx,
+                               params,
+                               req->flags2,
+                               &resume_name,
+                               params+12,
+                               total_params - 12,
+                               STR_TERMINATE,
+                               &ntstatus);
+               }
+               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
+                          path or an invalid name). Catch this as the resume name is only compared, never used in
+                          a file access. JRA. */
+                       srvstr_pull_talloc(ctx, params, req->flags2,
+                               &resume_name, params+12,
+                               total_params - 12,
+                               STR_TERMINATE);
+
+                       if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
+                               reply_nterror(req, ntstatus);
+                               return;
+                       }
+               }
+       }
+
+       DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
+close_after_request=%d, close_if_end = %d requires_resume_key = %d \
+resume_key = %d resume name = %s continue=%d level = %d\n",
+               dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
+               requires_resume_key, resume_key,
+               resume_name ? resume_name : "(NULL)", continue_bit, info_level));
+
+       if (!maxentries) {
+               /* W2K3 seems to treat zero as 1. */
+               maxentries = 1;
+       }
+
+       switch (info_level) {
+               case SMB_FIND_INFO_STANDARD:
+               case SMB_FIND_EA_SIZE:
+               case SMB_FIND_EA_LIST:
+               case SMB_FIND_FILE_DIRECTORY_INFO:
+               case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
+               case SMB_FIND_FILE_NAMES_INFO:
+               case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
+               case SMB_FIND_ID_FULL_DIRECTORY_INFO:
+               case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
+                       break;
+               case SMB_FIND_FILE_UNIX:
+               case SMB_FIND_FILE_UNIX_INFO2:
+                       /* Always use filesystem for UNIX mtime query. */
+                       ask_sharemode = false;
+                       if (!lp_smb1_unix_extensions()) {
+                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                               return;
+                       }
+                       if (!req->posix_pathnames) {
+                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                               return;
+                       }
+                       break;
+               default:
+                       reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                       return;
+       }
+
+       if (info_level == SMB_FIND_EA_LIST) {
+               uint32_t ea_size;
+
+               if (total_data < 4) {
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       return;
+               }
+
+               ea_size = IVAL(pdata,0);
+               if (ea_size != total_data) {
+                       DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
+total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       return;
+               }
+
+               if (!lp_ea_support(SNUM(conn))) {
+                       reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
+                       return;
+               }
+
+               /* Pull out the list of names. */
+               ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
+               if (!ea_list) {
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       return;
+               }
+       }
+
+       if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
+       }
+
+       *ppdata = (char *)SMB_REALLOC(
+               *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
+       if(*ppdata == NULL) {
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               return;
+       }
+
+       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 ) {
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               return;
+       }
+
+       params = *pparams;
+
+       /* Check that the dptr is valid */
+       fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
+       if (fsp == NULL) {
+               reply_nterror(req, STATUS_NO_MORE_FILES);
+               return;
+       }
+
+       directory = dptr_path(sconn, dptr_num);
+
+       /* Get the wildcard mask from the dptr */
+       if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
+               DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
+               reply_nterror(req, STATUS_NO_MORE_FILES);
+               return;
+       }
+
+       /* Get the attr mask from the dptr */
+       dirtype = dptr_attr(sconn, dptr_num);
+
+       backup_priv = dptr_get_priv(fsp->dptr);
+
+       DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
+               "backup_priv = %d\n",
+               dptr_num, mask, dirtype,
+               (long)fsp->dptr,
+               dptr_TellDir(fsp->dptr),
+               (int)backup_priv));
+
+       /* We don't need to check for VOL here as this is returned by
+               a different TRANS2 call. */
+
+       DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
+                directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
+       if (in_list(directory,lp_dont_descend(ctx, lp_sub, SNUM(conn)),
+                       dptr_case_sensitive(fsp->dptr)))
+               dont_descend = True;
+
+       p = pdata;
+       space_remaining = max_data_bytes;
+       out_of_space = False;
+
+       if (backup_priv) {
+               become_root();
+               as_root = true;
+       }
+
+       /*
+        * Seek to the correct position. We no longer use the resume key but
+        * depend on the last file name instead.
+        */
+
+       if(!continue_bit && resume_name && *resume_name) {
+               SMB_STRUCT_STAT st;
+               bool posix_open = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN);
+
+               long current_pos = 0;
+               /*
+                * Remember, name_to_8_3 is called by
+                * get_lanman2_dir_entry(), so the resume name
+                * could be mangled. Ensure we check the unmangled name.
+                */
+
+               if (!posix_open &&
+                               mangle_is_mangled(resume_name, conn->params)) {
+                       char *new_resume_name = NULL;
+                       mangle_lookup_name_from_8_3(ctx,
+                                               resume_name,
+                                               &new_resume_name,
+                                               conn->params);
+                       if (new_resume_name) {
+                               resume_name = new_resume_name;
+                       }
+               }
+
+               /*
+                * Fix for NT redirector problem triggered by resume key indexes
+                * changing between directory scans. We now return a resume key of 0
+                * and instead look for the filename to continue from (also given
+                * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
+                * findfirst/findnext (as is usual) then the directory pointer
+                * should already be at the correct place.
+                */
+
+               finished = !dptr_SearchDir(fsp->dptr, resume_name, &current_pos, &st);
+       } /* end if resume_name && !continue_bit */
+
+       for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
+               bool got_exact_match = False;
+
+               /* this is a heuristic to avoid seeking the fsp->dptr except when
+                       absolutely necessary. It allows for a filename of about 40 chars */
+               if (space_remaining < DIRLEN_GUESS && numentries > 0) {
+                       out_of_space = True;
+                       finished = False;
+               } else {
+                       ntstatus = get_lanman2_dir_entry(ctx,
+                                               conn,
+                                               fsp->dptr,
+                                               req->flags2,
+                                               mask,dirtype,info_level,
+                                               requires_resume_key,dont_descend,
+                                               ask_sharemode,
+                                               &p,pdata,data_end,
+                                               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)
+                       numentries++;
+
+               /*
+                * As an optimisation if we know we aren't looking
+                * for a wildcard name (ie. the name matches the wildcard exactly)
+                * then we can finish on any (first) match.
+                * This speeds up large directory searches. JRA.
+                */
+
+               if(got_exact_match)
+                       finished = True;
+
+               space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
+       }
+
+       DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
+               smb_fn_name(req->cmd),
+               mask, directory, dirtype, numentries ) );
+
+       /* Check if we can close the fsp->dptr */
+       if(close_after_request || (finished && close_if_end)) {
+               DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
+               dptr_num = -1;
+               close_file_free(NULL, &fsp, NORMAL_CLOSE);
+       }
+
+       if (as_root) {
+               unbecome_root();
+       }
+
+       /* Set up the return parameter block */
+       SSVAL(params,0,numentries);
+       SSVAL(params,2,finished);
+       SSVAL(params,4,0); /* Never an EA error */
+       SSVAL(params,6,last_entry_off);
+
+       send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
+                           max_data_bytes);
+
+       return;
+}
+
+/****************************************************************************
+ Reply to a TRANS2_QFSINFO (query filesystem info).
+****************************************************************************/
+
+static void call_trans2qfsinfo(connection_struct *conn,
+                              struct smb_request *req,
+                              char **pparams, int total_params,
+                              char **ppdata, int total_data,
+                              unsigned int max_data_bytes)
+{
+       char *params = *pparams;
+       uint16_t info_level;
+       int data_len = 0;
+       size_t fixed_portion;
+       NTSTATUS status;
+
+       if (total_params < 2) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
+       }
+
+       info_level = SVAL(params,0);
+
+       if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
+               if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
+                       DEBUG(0,("call_trans2qfsinfo: encryption required "
+                               "and info level 0x%x sent.\n",
+                               (unsigned int)info_level));
+                       reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+                       return;
+               }
+       }
+
+       DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
+
+       status = smbd_do_qfsinfo(req->xconn, conn, req,
+                                info_level,
+                                req->flags2,
+                                max_data_bytes,
+                                &fixed_portion,
+                                NULL,
+                                ppdata, &data_len);
+       if (!NT_STATUS_IS_OK(status)) {
+               reply_nterror(req, status);
+               return;
+       }
+
+       send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
+                           max_data_bytes);
+
+       DEBUG( 4, ( "%s info_level = %d\n",
+                   smb_fn_name(req->cmd), info_level) );
+
+       return;
+}
+
+/****************************************************************************
+ Reply to a TRANS2_SETFSINFO (set filesystem info).
+****************************************************************************/
+
+static void call_trans2setfsinfo(connection_struct *conn,
+                                struct smb_request *req,
+                                char **pparams, int total_params,
+                                char **ppdata, int total_data,
+                                unsigned int max_data_bytes)
+{
+       const struct loadparm_substitution *lp_sub =
+               loadparm_s3_global_substitution();
+       struct smbXsrv_connection *xconn = req->xconn;
+       char *pdata = *ppdata;
+       char *params = *pparams;
+       uint16_t info_level;
+
+       DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
+                 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
+
+       /*  */
+       if (total_params < 4) {
+               DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
+                       total_params));
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
+       }
+
+       info_level = SVAL(params,2);
+
+       if (IS_IPC(conn)) {
+               if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
+                               info_level != SMB_SET_CIFS_UNIX_INFO) {
+                       DEBUG(0,("call_trans2setfsinfo: not an allowed "
+                               "info level (0x%x) on IPC$.\n",
+                               (unsigned int)info_level));
+                       reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+                       return;
+               }
+       }
+
+       if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
+               if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
+                       DEBUG(0,("call_trans2setfsinfo: encryption required "
+                               "and info level 0x%x sent.\n",
+                               (unsigned int)info_level));
+                       reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+                       return;
+               }
+       }
+
+       switch(info_level) {
+               case SMB_SET_CIFS_UNIX_INFO:
+                       if (!lp_smb1_unix_extensions()) {
+                               DEBUG(2,("call_trans2setfsinfo: "
+                                       "SMB_SET_CIFS_UNIX_INFO is invalid with "
+                                       "unix extensions off\n"));
+                               reply_nterror(req,
+                                             NT_STATUS_INVALID_LEVEL);
+                               return;
+                       }
+
+                       /* There should be 12 bytes of capabilities set. */
+                       if (total_data < 12) {
+                               reply_nterror(
+                                       req,
+                                       NT_STATUS_INVALID_PARAMETER);
+                               return;
+                       }
+                       xconn->smb1.unix_info.client_major = SVAL(pdata,0);
+                       xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
+                       xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
+                       xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
+                       /* Just print these values for now. */
+                       DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
+                                  "major = %u, minor = %u cap_low = 0x%x, "
+                                  "cap_high = 0x%xn",
+                                  (unsigned int)xconn->
+                                  smb1.unix_info.client_major,
+                                  (unsigned int)xconn->
+                                  smb1.unix_info.client_minor,
+                                  (unsigned int)xconn->
+                                  smb1.unix_info.client_cap_low,
+                                  (unsigned int)xconn->
+                                  smb1.unix_info.client_cap_high));
+
+                       /* Here is where we must switch to posix pathname processing... */
+                       if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
+                               lp_set_posix_pathnames();
+                               mangle_change_to_posix();
+                       }
+
+                       if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
+                           !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
+                               /* Client that knows how to do posix locks,
+                                * but not posix open/mkdir operations. Set a
+                                * default type for read/write checks. */
+
+                               lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
+
+                       }
+                       break;
+
+               case SMB_REQUEST_TRANSPORT_ENCRYPTION:
+                       {
+                               NTSTATUS status;
+                               size_t param_len = 0;
+                               size_t data_len = total_data;
+
+                               if (!lp_smb1_unix_extensions()) {
+                                       reply_nterror(
+                                               req,
+                                               NT_STATUS_INVALID_LEVEL);
+                                       return;
+                               }
+
+                               if (lp_server_smb_encrypt(SNUM(conn)) ==
+                                   SMB_ENCRYPTION_OFF) {
+                                       reply_nterror(
+                                               req,
+                                               NT_STATUS_NOT_SUPPORTED);
+                                       return;
+                               }
+
+                               if (xconn->smb1.echo_handler.trusted_fde) {
+                                       DEBUG( 2,("call_trans2setfsinfo: "
+                                               "request transport encryption disabled"
+                                               "with 'fork echo handler = yes'\n"));
+                                       reply_nterror(
+                                               req,
+                                               NT_STATUS_NOT_SUPPORTED);
+                                       return;
+                               }
+
+                               DEBUG( 4,("call_trans2setfsinfo: "
+                                       "request transport encryption.\n"));
+
+                               status = srv_request_encryption_setup(conn,
+                                                               (unsigned char **)ppdata,
+                                                               &data_len,
+                                                               (unsigned char **)pparams,
+                                                               &param_len);
+
+                               if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
+                                               !NT_STATUS_IS_OK(status)) {
+                                       reply_nterror(req, status);
+                                       return;
+                               }
+
+                               send_trans2_replies(conn, req,
+                                               NT_STATUS_OK,
+                                               *pparams,
+                                               param_len,
+                                               *ppdata,
+                                               data_len,
+                                               max_data_bytes);
+
+                               if (NT_STATUS_IS_OK(status)) {
+                                       /* Server-side transport
+                                        * encryption is now *on*. */
+                                       status = srv_encryption_start(conn);
+                                       if (!NT_STATUS_IS_OK(status)) {
+                                               char *reason = talloc_asprintf(talloc_tos(),
+                                                                              "Failure in setting "
+                                                                              "up encrypted transport: %s",
+                                                                              nt_errstr(status));
+                                               exit_server_cleanly(reason);
+                                       }
+                               }
+                               return;
+                       }
+
+               case SMB_FS_QUOTA_INFORMATION:
+                       {
+                               NTSTATUS status;
+                               DATA_BLOB qdata = {
+                                               .data = (uint8_t *)pdata,
+                                               .length = total_data
+                               };
+                               files_struct *fsp = NULL;
+                               fsp = file_fsp(req, SVAL(params,0));
+
+                               status = smb_set_fsquota(conn,
+                                                       req,
+                                                       fsp,
+                                                       &qdata);
+                               if (!NT_STATUS_IS_OK(status)) {
+                                       reply_nterror(req, status);
+                                       return;
+                               }
+                               break;
+                       }
+               default:
+                       DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
+                               info_level));
+                       reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                       return;
+                       break;
+       }
+
+       /*
+        * sending this reply works fine,
+        * but I'm not sure it's the same
+        * like windows do...
+        * --metze
+        */
+       reply_outbuf(req, 10, 0);
+}
+
+/****************************************************************************
+ Reply to a TRANSACT2_QFILEINFO on a PIPE !
+****************************************************************************/
+
+static void call_trans2qpipeinfo(connection_struct *conn,
+                                struct smb_request *req,
+                                unsigned int tran_call,
+                                char **pparams, int total_params,
+                                char **ppdata, int total_data,
+                                unsigned int max_data_bytes)
+{
+       char *params = *pparams;
+       char *pdata = *ppdata;
+       unsigned int data_size = 0;
+       unsigned int param_size = 2;
+       uint16_t info_level;
+       files_struct *fsp;
+
+       if (!params) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
+       }
+
+       if (total_params < 4) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
+       }
+
+       fsp = file_fsp(req, SVAL(params,0));
+       if (!fsp_is_np(fsp)) {
+               reply_nterror(req, NT_STATUS_INVALID_HANDLE);
+               return;
+       }
+
+       info_level = SVAL(params,2);
+
+       *pparams = (char *)SMB_REALLOC(*pparams,2);
+       if (*pparams == NULL) {
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               return;
+       }
+       params = *pparams;
+       SSVAL(params,0,0);
+       if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
+       }
+       data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
+       *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
+       if (*ppdata == NULL ) {
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               return;
+       }
+       pdata = *ppdata;
+
+       switch (info_level) {
+               case SMB_FILE_STANDARD_INFORMATION:
+                       memset(pdata,0,24);
+                       SOFF_T(pdata,0,4096LL);
+                       SIVAL(pdata,16,1);
+                       SIVAL(pdata,20,1);
+                       data_size = 24;
+                       break;
+
+               default:
+                       reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                       return;
+       }
+
+       send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
+                           max_data_bytes);
+
+       return;
+}
+
+/****************************************************************************
+ Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
+ file name or file id).
+****************************************************************************/
+
+static void call_trans2qfilepathinfo(connection_struct *conn,
+                                    struct smb_request *req,
+                                    unsigned int tran_call,
+                                    char **pparams, int total_params,
+                                    char **ppdata, int total_data,
+                                    unsigned int max_data_bytes)
+{
+       char *params = *pparams;
+       char *pdata = *ppdata;
+       uint16_t info_level;
+       unsigned int data_size = 0;
+       unsigned int param_size = 2;
+       struct smb_filename *smb_fname = NULL;
+       bool delete_pending = False;
+       struct timespec write_time_ts;
+       files_struct *fsp = NULL;
+       struct file_id fileid;
+       struct ea_list *ea_list = NULL;
+       int lock_data_count = 0;
+       char *lock_data = NULL;
+       size_t fixed_portion;
+       NTSTATUS status = NT_STATUS_OK;
+       int ret;
+
+       if (!params) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
+       }
+
+       ZERO_STRUCT(write_time_ts);
+
+       if (tran_call == TRANSACT2_QFILEINFO) {
+               if (total_params < 4) {
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       return;
+               }
+
+               if (IS_IPC(conn)) {
+                       call_trans2qpipeinfo(conn, req, tran_call,
+                                            pparams, total_params,
+                                            ppdata, total_data,
+                                            max_data_bytes);
+                       return;
+               }
+
+               fsp = file_fsp(req, SVAL(params,0));
+               info_level = SVAL(params,2);
+
+               DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
+
+               if (INFO_LEVEL_IS_UNIX(info_level)) {
+                       if (!lp_smb1_unix_extensions()) {
+                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                               return;
+                       }
+                       if (!req->posix_pathnames) {
+                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                               return;
+                       }
+               }
+
+               /* Initial check for valid fsp ptr. */
+               if (!check_fsp_open(conn, req, fsp)) {
+                       return;
+               }
+
+               smb_fname = fsp->fsp_name;
+
+               if(fsp->fake_file_handle) {
+                       /*
+                        * This is actually for the QUOTA_FAKE_FILE --metze
+                        */
+
+                       /* We know this name is ok, it's already passed the checks. */
+
+               } else if(fsp_get_pathref_fd(fsp) == -1) {
+                       /*
+                        * This is actually a QFILEINFO on a directory
+                        * handle (returned from an NT SMB). NT5.0 seems
+                        * to do this call. JRA.
+                        */
+                       ret = vfs_stat(conn, smb_fname);
+                       if (ret != 0) {
+                               DBG_NOTICE("vfs_stat of %s failed (%s)\n",
+                                        smb_fname_str_dbg(smb_fname),
+                                        strerror(errno));
+                               reply_nterror(req,
+                                       map_nt_error_from_unix(errno));
+                               return;
+                       }
+
+                       if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
+                               fileid = vfs_file_id_from_sbuf(
+                                       conn, &smb_fname->st);
+                               get_file_infos(fileid, fsp->name_hash,
+                                              &delete_pending,
+                                              &write_time_ts);
+                       }
+               } else {
+                       /*
+                        * Original code - this is an open file.
+                        */
+                       status = vfs_stat_fsp(fsp);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               DEBUG(3, ("fstat of %s failed (%s)\n",
+                                         fsp_fnum_dbg(fsp), nt_errstr(status)));
+                               reply_nterror(req, status);
+                               return;
+                       }
+                       if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
+                               fileid = vfs_file_id_from_sbuf(
+                                       conn, &smb_fname->st);
+                               get_file_infos(fileid, fsp->name_hash,
+                                              &delete_pending,
+                                              &write_time_ts);
+                       }
+               }
+
+       } else {
+               uint32_t name_hash;
+               char *fname = NULL;
+               uint32_t ucf_flags = ucf_flags_from_smb_request(req);
+
+               /* qpathinfo */
+               if (total_params < 7) {
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       return;
+               }
+
+               info_level = SVAL(params,0);
+
+               DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
+
+               if (INFO_LEVEL_IS_UNIX(info_level)) {
+                       if (!lp_smb1_unix_extensions()) {
+                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                               return;
+                       }
+                       if (!req->posix_pathnames) {
+                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                               return;
+                       }
+               }
+
+               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;
+               }
+
+               status = filename_convert(req,
+                                       conn,
+                                       fname,
+                                       ucf_flags,
+                                       0,
+                                       &smb_fname);
+               if (!NT_STATUS_IS_OK(status)) {
+                       if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+                               reply_botherror(req,
+                                               NT_STATUS_PATH_NOT_COVERED,
+                                               ERRSRV, ERRbadpath);
+                               return;
+                       }
+                       reply_nterror(req, status);
+                       return;
+               }
+
+               /*
+                * qpathinfo must operate on an existing file, so we
+                * can exit early if filename_convert() returned the "new file"
+                * NT_STATUS_OK, !VALID_STAT case.
+                */
+
+               if (!VALID_STAT(smb_fname->st)) {
+                       reply_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
+                       return;
+               }
+
+               /*
+                * smb_fname->fsp may be NULL if smb_fname points at a symlink
+                * and we're in POSIX context, so be careful when using fsp
+                * below, it can still be NULL.
+                */
+               fsp = smb_fname->fsp;
+
+               /* If this is a stream, check if there is a delete_pending. */
+               if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
+                   && is_ntfs_stream_smb_fname(smb_fname)) {
+                       struct smb_filename *smb_fname_base;
+
+                       /* Create an smb_filename with stream_name == NULL. */
+                       smb_fname_base = synthetic_smb_fname(
+                                               talloc_tos(),
+                                               smb_fname->base_name,
+                                               NULL,
+                                               NULL,
+                                               smb_fname->twrp,
+                                               smb_fname->flags);
+                       if (smb_fname_base == NULL) {
+                               reply_nterror(req, NT_STATUS_NO_MEMORY);
+                               return;
+                       }
+
+                       ret = vfs_stat(conn, smb_fname_base);
+                       if (ret != 0) {
+                               DBG_NOTICE("vfs_stat of %s failed "
+                                       "(%s)\n",
+                                       smb_fname_str_dbg(smb_fname_base),
+                                       strerror(errno));
+                               TALLOC_FREE(smb_fname_base);
+                               reply_nterror(req,
+                                       map_nt_error_from_unix(errno));
+                               return;
+                       }
+
+                       status = file_name_hash(conn,
+                                       smb_fname_str_dbg(smb_fname_base),
+                                       &name_hash);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               TALLOC_FREE(smb_fname_base);
+                               reply_nterror(req, status);
+                               return;
+                       }
+
+                       fileid = vfs_file_id_from_sbuf(conn,
+                                                      &smb_fname_base->st);
+                       TALLOC_FREE(smb_fname_base);
+                       get_file_infos(fileid, name_hash, &delete_pending, NULL);
+                       if (delete_pending) {
+                               reply_nterror(req, NT_STATUS_DELETE_PENDING);
+                               return;
+                       }
+               }
+
+               status = file_name_hash(conn,
+                               smb_fname_str_dbg(smb_fname),
+                               &name_hash);
+               if (!NT_STATUS_IS_OK(status)) {
+                       reply_nterror(req, status);
+                       return;
+               }
+
+               if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
+                       fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
+                       get_file_infos(fileid, name_hash, &delete_pending,
+                                      &write_time_ts);
+               }
+
+               if (delete_pending) {
+                       reply_nterror(req, NT_STATUS_DELETE_PENDING);
+                       return;
+               }
+       }
+
+       DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
+                "total_data=%d\n", smb_fname_str_dbg(smb_fname),
+                fsp_fnum_dbg(fsp),
+                info_level,tran_call,total_data));
+
+       /* Pull out any data sent here before we realloc. */
+       switch (info_level) {
+               case SMB_INFO_QUERY_EAS_FROM_LIST:
+               {
+                       /* Pull any EA list from the data portion. */
+                       uint32_t ea_size;
+
+                       if (total_data < 4) {
+                               reply_nterror(
+                                       req, NT_STATUS_INVALID_PARAMETER);
+                               return;
+                       }
+                       ea_size = IVAL(pdata,0);
+
+                       if (total_data > 0 && ea_size != total_data) {
+                               DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
+total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
+                               reply_nterror(
+                                       req, NT_STATUS_INVALID_PARAMETER);
+                               return;
+                       }
+
+                       if (!lp_ea_support(SNUM(conn))) {
+                               reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
+                               return;
+                       }
+
+                       /* Pull out the list of names. */
+                       ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
+                       if (!ea_list) {
+                               reply_nterror(
+                                       req, NT_STATUS_INVALID_PARAMETER);
+                               return;
+                       }
+                       break;
+               }
+
+               case SMB_QUERY_POSIX_LOCK:
+               {
+                       if (fsp == NULL ||
+                           fsp->fsp_flags.is_pathref ||
+                           fsp_get_io_fd(fsp) == -1)
+                       {
+                               reply_nterror(req, NT_STATUS_INVALID_HANDLE);
+                               return;
+                       }
+
+                       if (total_data != POSIX_LOCK_DATA_SIZE) {
+                               reply_nterror(
+                                       req, NT_STATUS_INVALID_PARAMETER);
+                               return;
+                       }
+
+                       /* Copy the lock range data. */
+                       lock_data = (char *)talloc_memdup(
+                               req, pdata, total_data);
+                       if (!lock_data) {
+                               reply_nterror(req, NT_STATUS_NO_MEMORY);
+                               return;
+                       }
+                       lock_data_count = total_data;
+                       break;
+               }
+               default:
+                       break;
+       }
+
+       *pparams = (char *)SMB_REALLOC(*pparams,2);
+       if (*pparams == NULL) {
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               return;
+       }
+       params = *pparams;
+       SSVAL(params,0,0);
+
+       /*
+        * draft-leach-cifs-v1-spec-02.txt
+        * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
+        * says:
+        *
+        *  The requested information is placed in the Data portion of the
+        *  transaction response. For the information levels greater than 0x100,
+        *  the transaction response has 1 parameter word which should be
+        *  ignored by the client.
+        *
+        * However Windows only follows this rule for the IS_NAME_VALID call.
+        */
+       switch (info_level) {
+       case SMB_INFO_IS_NAME_VALID:
+               param_size = 0;
+               break;
+       }
+
+       if ((info_level & SMB2_INFO_SPECIAL) == SMB2_INFO_SPECIAL) {
+               /*
+                * We use levels that start with 0xFF00
+                * internally to represent SMB2 specific levels
+                */
+               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+               return;
+       }
+
+       status = smbd_do_qfilepathinfo(conn, req, req, info_level,
+                                      fsp, smb_fname,
+                                      delete_pending, write_time_ts,
+                                      ea_list,
+                                      lock_data_count, lock_data,
+                                      req->flags2, max_data_bytes,
+                                      &fixed_portion,
+                                      ppdata, &data_size);
+       if (!NT_STATUS_IS_OK(status)) {
+               if (open_was_deferred(req->xconn, req->mid)) {
+                       /* We have re-scheduled this call. */
+                       return;
+               }
+               if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
+                       bool ok = defer_smb1_sharing_violation(req);
+                       if (ok) {
+                               return;
+                       }
+               }
+               reply_nterror(req, status);
+               return;
+       }
+       if (fixed_portion > max_data_bytes) {
+               reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
+               return;
+       }
+
+       send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
+                           max_data_bytes);
+
+       return;
+}
+
+/****************************************************************************
+ Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
+****************************************************************************/
+
+static void call_trans2setfilepathinfo(connection_struct *conn,
+                                      struct smb_request *req,
+                                      unsigned int tran_call,
+                                      char **pparams, int total_params,
+                                      char **ppdata, int total_data,
+                                      unsigned int max_data_bytes)
+{
+       char *params = *pparams;
+       char *pdata = *ppdata;
+       uint16_t info_level;
+       struct smb_filename *smb_fname = NULL;
+       files_struct *fsp = NULL;
+       NTSTATUS status = NT_STATUS_OK;
+       int data_return_size = 0;
+       int ret;
+
+       if (!params) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
+       }
+
+       if (tran_call == TRANSACT2_SETFILEINFO) {
+               if (total_params < 4) {
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       return;
+               }
+
+               fsp = file_fsp(req, SVAL(params,0));
+               /* Basic check for non-null fsp. */
+               if (!check_fsp_open(conn, req, fsp)) {
+                       return;
+               }
+               info_level = SVAL(params,2);
+
+               if (INFO_LEVEL_IS_UNIX(info_level)) {
+                       if (!lp_smb1_unix_extensions()) {
+                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                               return;
+                       }
+                       if (!req->posix_pathnames) {
+                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                               return;
+                       }
+               }
+
+               smb_fname = fsp->fsp_name;
+
+               if (fsp_get_pathref_fd(fsp) == -1) {
+                       /*
+                        * This is actually a SETFILEINFO on a directory
+                        * handle (returned from an NT SMB). NT5.0 seems
+                        * to do this call. JRA.
+                        */
+                       ret = vfs_stat(conn, smb_fname);
+                       if (ret != 0) {
+                               DBG_NOTICE("vfs_stat of %s failed (%s)\n",
+                                       smb_fname_str_dbg(smb_fname),
+                                       strerror(errno));
+                               reply_nterror(req,
+                                       map_nt_error_from_unix(errno));
+                               return;
+                       }
+               } else if (fsp->print_file) {
+                       /*
+                        * Doing a DELETE_ON_CLOSE should cancel a print job.
+                        */
+                       if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
+                               uint32_t new_private_options =
+                                       fh_get_private_options(fsp->fh);
+                               new_private_options |=
+                                       NTCREATEX_FLAG_DELETE_ON_CLOSE;
+                               fh_set_private_options(fsp->fh,
+                                                      new_private_options);
+
+                               DEBUG(3,("call_trans2setfilepathinfo: "
+                                        "Cancelling print job (%s)\n",
+                                        fsp_str_dbg(fsp)));
+
+                               SSVAL(params,0,0);
+                               send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
+                                                   *ppdata, 0,
+                                                   max_data_bytes);
+                               return;
+                       } else {
+                               reply_nterror(req,
+                                       NT_STATUS_OBJECT_PATH_NOT_FOUND);
+                               return;
+                       }
+               } else {
+                       /*
+                        * Original code - this is an open file.
+                        */
+                       status = vfs_stat_fsp(fsp);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               DEBUG(3,("call_trans2setfilepathinfo: fstat "
+                                        "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
+                                        nt_errstr(status)));
+                               reply_nterror(req, status);
+                               return;
+                       }
+               }
+       } else {
+               char *fname = NULL;
+               uint32_t ucf_flags = ucf_flags_from_smb_request(req);
+               bool require_existing_object = true;
+
+               /* set path info */
+               if (total_params < 7) {
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       return;
+               }
+
+               info_level = SVAL(params,0);
+
+               if (INFO_LEVEL_IS_UNIX(info_level)) {
+                       if (!lp_smb1_unix_extensions()) {
+                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                               return;
+                       }
+                       if (!req->posix_pathnames) {
+                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                               return;
+                       }
+               }
+
+               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;
+               }
+
+               status = filename_convert(req, conn,
+                                        fname,
+                                        ucf_flags,
+                                        0,
+                                        &smb_fname);
+               if (!NT_STATUS_IS_OK(status)) {
+                       if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+                               reply_botherror(req,
+                                               NT_STATUS_PATH_NOT_COVERED,
+                                               ERRSRV, ERRbadpath);
+                               return;
+                       }
+                       reply_nterror(req, status);
+                       return;
+               }
+
+               /*
+                * smb_fname->fsp may be NULL if smb_fname points at a symlink
+                * and we're in POSIX context, so be careful when using fsp
+                * below, it can still be NULL.
+                */
+               fsp = smb_fname->fsp;
+
+               /*
+                * There are 4 info levels which can
+                * create a new object in the filesystem.
+                * They are:
+                * SMB_SET_FILE_UNIX_LINK -> creates POSIX symlink.
+                * SMB_POSIX_PATH_OPEN -> creates POSIX file or directory.
+                * SMB_SET_FILE_UNIX_BASIC:
+                * SMB_SET_FILE_UNIX_INFO2: can create a POSIX special file.
+                *
+                * These info levels do not require an existing object.
+                */
+               switch (info_level) {
+               case SMB_SET_FILE_UNIX_LINK:
+               case SMB_POSIX_PATH_OPEN:
+               case SMB_SET_FILE_UNIX_BASIC:
+               case SMB_SET_FILE_UNIX_INFO2:
+                       require_existing_object = false;
+                       break;
+               default:
+                       break;
+               }
+
+               if (!VALID_STAT(smb_fname->st) && require_existing_object) {
+                       reply_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
+               }
+       }
+
+       DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
+                "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
+                fsp_fnum_dbg(fsp),
+                info_level,total_data));
+
+       /* Realloc the parameter size */
+       *pparams = (char *)SMB_REALLOC(*pparams,2);
+       if (*pparams == NULL) {
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               return;
+       }
+       params = *pparams;
+
+       SSVAL(params,0,0);
+
+       status = smbd_do_setfilepathinfo(conn, req, req,
+                                        info_level,
+                                        fsp,
+                                        smb_fname,
+                                        ppdata, total_data,
+                                        &data_return_size);
+       if (!NT_STATUS_IS_OK(status)) {
+               if (open_was_deferred(req->xconn, req->mid)) {
+                       /* We have re-scheduled this call. */
+                       return;
+               }
+               if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
+                       bool ok = defer_smb1_sharing_violation(req);
+                       if (ok) {
+                               return;
+                       }
+               }
+               if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
+                       /* We have re-scheduled this call. */
+                       return;
+               }
+               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+                       reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
+                                       ERRSRV, ERRbadpath);
+                       return;
+               }
+               if (info_level == SMB_POSIX_PATH_OPEN) {
+                       reply_openerror(req, status);
+                       return;
+               }
+
+               /*
+                * Invalid EA name needs to return 2 param bytes,
+                * not a zero-length error packet.
+                */
+               if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
+                       send_trans2_replies(conn, req, status, params, 2, NULL, 0,
+                                       max_data_bytes);
+               } else {
+                       reply_nterror(req, status);
+               }
+               return;
+       }
+
+       send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
+                           max_data_bytes);
+
+       return;
+}
+
+/****************************************************************************
+ Reply to a TRANS2_MKDIR (make directory with extended attributes).
+****************************************************************************/
+
+static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
+                            char **pparams, int total_params,
+                            char **ppdata, int total_data,
+                            unsigned int max_data_bytes)
+{
+       struct files_struct *fsp = NULL;
+       struct smb_filename *smb_dname = NULL;
+       char *params = *pparams;
+       char *pdata = *ppdata;
+       char *directory = NULL;
+       NTSTATUS status = NT_STATUS_OK;
+       struct ea_list *ea_list = NULL;
+       uint32_t ucf_flags = ucf_flags_from_smb_request(req);
+       TALLOC_CTX *ctx = talloc_tos();
+
+       if (!CAN_WRITE(conn)) {
+               reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+               return;
+       }
+
+       if (total_params < 5) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
+       }
+
+       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;
+       }
+
+       DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
+
+       status = filename_convert(ctx,
+                               conn,
+                               directory,
+                               ucf_flags,
+                               0,
+                               &smb_dname);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+                       reply_botherror(req,
+                               NT_STATUS_PATH_NOT_COVERED,
+                               ERRSRV, ERRbadpath);
+                       return;
+               }
+               reply_nterror(req, status);
+               return;
+        }
+
+       /*
+        * OS/2 workplace shell seems to send SET_EA requests of "null"
+        * length (4 bytes containing IVAL 4).
+        * They seem to have no effect. Bug #3212. JRA.
+        */
+
+       if (total_data && (total_data != 4)) {
+               /* Any data in this call is an EA list. */
+               if (total_data < 10) {
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       goto out;
+               }
+
+               if (IVAL(pdata,0) > total_data) {
+                       DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
+                               IVAL(pdata,0), (unsigned int)total_data));
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       goto out;
+               }
+
+               ea_list = read_ea_list(talloc_tos(), pdata + 4,
+                                      total_data - 4);
+               if (!ea_list) {
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       goto out;
+               }
+
+               if (!lp_ea_support(SNUM(conn))) {
+                       reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
+                       goto out;
+               }
+       }
+       /* If total_data == 4 Windows doesn't care what values
+        * are placed in that field, it just ignores them.
+        * The System i QNTC IBM SMB client puts bad values here,
+        * so ignore them. */
+
+       status = SMB_VFS_CREATE_FILE(
+               conn,                                   /* conn */
+               req,                                    /* req */
+               smb_dname,                              /* fname */
+               MAXIMUM_ALLOWED_ACCESS,                 /* access_mask */
+               FILE_SHARE_NONE,                        /* share_access */
+               FILE_CREATE,                            /* create_disposition*/
+               FILE_DIRECTORY_FILE,                    /* create_options */
+               FILE_ATTRIBUTE_DIRECTORY,               /* file_attributes */
+               0,                                      /* oplock_request */
+               NULL,                                   /* lease */
+               0,                                      /* allocation_size */
+               0,                                      /* private_flags */
+               NULL,                                   /* sd */
+               NULL,                                   /* ea_list */
+               &fsp,                                   /* result */
+               NULL,                                   /* pinfo */
+               NULL, NULL);                            /* create context */
+       if (!NT_STATUS_IS_OK(status)) {
+               reply_nterror(req, status);
+               goto out;
+       }
+
+       /* Try and set any given EA. */
+       if (ea_list) {
+               status = set_ea(conn, fsp, ea_list);
+               if (!NT_STATUS_IS_OK(status)) {
+                       reply_nterror(req, status);
+                       goto out;
+               }
+       }
+
+       /* Realloc the parameter and data sizes */
+       *pparams = (char *)SMB_REALLOC(*pparams,2);
+       if(*pparams == NULL) {
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               goto out;
+       }
+       params = *pparams;
+
+       SSVAL(params,0,0);
+
+       send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
+
+ out:
+       if (fsp != NULL) {
+               close_file_free(NULL, &fsp, NORMAL_CLOSE);
+       }
+       TALLOC_FREE(smb_dname);
+       return;
+}
+
+/****************************************************************************
+ Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
+ We don't actually do this - we just send a null response.
+****************************************************************************/
+
+static void call_trans2findnotifyfirst(connection_struct *conn,
+                                      struct smb_request *req,
+                                      char **pparams, int total_params,
+                                      char **ppdata, int total_data,
+                                      unsigned int max_data_bytes)
+{
+       char *params = *pparams;
+       uint16_t info_level;
+
+       if (total_params < 6) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
+       }
+
+       info_level = SVAL(params,4);
+       DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
+
+       switch (info_level) {
+               case 1:
+               case 2:
+                       break;
+               default:
+                       reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                       return;
+       }
+
+       /* Realloc the parameter and data sizes */
+       *pparams = (char *)SMB_REALLOC(*pparams,6);
+       if (*pparams == NULL) {
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               return;
+       }
+       params = *pparams;
+
+       SSVAL(params,0,fnf_handle);
+       SSVAL(params,2,0); /* No changes */
+       SSVAL(params,4,0); /* No EA errors */
+
+       fnf_handle++;
+
+       if(fnf_handle == 0)
+               fnf_handle = 257;
+
+       send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
+
+       return;
+}
+
+/****************************************************************************
+ Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
+ changes). Currently this does nothing.
+****************************************************************************/
+
+static void call_trans2findnotifynext(connection_struct *conn,
+                                     struct smb_request *req,
+                                     char **pparams, int total_params,
+                                     char **ppdata, int total_data,
+                                     unsigned int max_data_bytes)
+{
+       char *params = *pparams;
+
+       DEBUG(3,("call_trans2findnotifynext\n"));
+
+       /* Realloc the parameter and data sizes */
+       *pparams = (char *)SMB_REALLOC(*pparams,4);
+       if (*pparams == NULL) {
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               return;
+       }
+       params = *pparams;
+
+       SSVAL(params,0,0); /* No changes */
+       SSVAL(params,2,0); /* No EA errors */
+
+       send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
+
+       return;
+}
+
+/****************************************************************************
+ Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
+****************************************************************************/
+
+static void call_trans2getdfsreferral(connection_struct *conn,
+                                     struct smb_request *req,
+                                     char **pparams, int total_params,
+                                     char **ppdata, int total_data,
+                                     unsigned int max_data_bytes)
+{
+       char *params = *pparams;
+       char *pathname = NULL;
+       int reply_size = 0;
+       int max_referral_level;
+       NTSTATUS status = NT_STATUS_OK;
+       TALLOC_CTX *ctx = talloc_tos();
+
+       DEBUG(10,("call_trans2getdfsreferral\n"));
+
+       if (total_params < 3) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
+       }
+
+       max_referral_level = SVAL(params,0);
+
+       if(!lp_host_msdfs()) {
+               reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
+               return;
+       }
+
+       srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
+                   total_params - 2, STR_TERMINATE);
+       if (!pathname) {
+               reply_nterror(req, NT_STATUS_NOT_FOUND);
+               return;
+       }
+       if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
+                                           ppdata,&status)) < 0) {
+               reply_nterror(req, status);
+               return;
+       }
+
+       SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
+             SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
+       send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
+
+       return;
+}
+
+#define LMCAT_SPL       0x53
+#define LMFUNC_GETJOBID 0x60
+
+/****************************************************************************
+ Reply to a TRANS2_IOCTL - used for OS/2 printing.
+****************************************************************************/
+
+static void call_trans2ioctl(connection_struct *conn,
+                            struct smb_request *req,
+                            char **pparams, int total_params,
+                            char **ppdata, int total_data,
+                            unsigned int max_data_bytes)
+{
+       const struct loadparm_substitution *lp_sub =
+               loadparm_s3_global_substitution();
+       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 */
+
+       if (!fsp) {
+               reply_nterror(req, NT_STATUS_INVALID_HANDLE);
+               return;
+       }
+
+       if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
+           && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
+               *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
+               if (*ppdata == NULL) {
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                       return;
+               }
+               pdata = *ppdata;
+
+               /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
+                       CAN ACCEPT THIS IN UNICODE. JRA. */
+
+               /* Job number */
+               SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
+
+               status = srvstr_push(pdata, req->flags2, pdata + 2,
+                           lp_netbios_name(), 15,
+                           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(), lp_sub, SNUM(conn)), 13,
+                           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;
+       }
+
+       DEBUG(2,("Unknown TRANS2_IOCTL\n"));
+       reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
+}
+
+void handle_trans2(connection_struct *conn, struct smb_request *req,
+                  struct trans_state *state)
+{
+       if (get_Protocol() >= PROTOCOL_NT1) {
+               req->flags2 |= 0x40; /* IS_LONG_NAME */
+               SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
+       }
+
+       if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
+               if (state->call != TRANSACT2_QFSINFO &&
+                   state->call != TRANSACT2_SETFSINFO) {
+                       DEBUG(0,("handle_trans2: encryption required "
+                               "with call 0x%x\n",
+                               (unsigned int)state->call));
+                       reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+                       return;
+               }
+       }
+
+       SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
+
+       /* Now we must call the relevant TRANS2 function */
+       switch(state->call)  {
+       case TRANSACT2_OPEN:
+       {
+               START_PROFILE(Trans2_open);
+               call_trans2open(conn, req,
+                               &state->param, state->total_param,
+                               &state->data, state->total_data,
+                               state->max_data_return);
+               END_PROFILE(Trans2_open);
+               break;
+       }
+
+       case TRANSACT2_FINDFIRST:
+       {
+               START_PROFILE(Trans2_findfirst);
+               call_trans2findfirst(conn, req,
+                                    &state->param, state->total_param,
+                                    &state->data, state->total_data,
+                                    state->max_data_return);
+               END_PROFILE(Trans2_findfirst);
+               break;
+       }
+
+       case TRANSACT2_FINDNEXT:
+       {
+               START_PROFILE(Trans2_findnext);
+               call_trans2findnext(conn, req,
+                                   &state->param, state->total_param,
+                                   &state->data, state->total_data,
+                                   state->max_data_return);
+               END_PROFILE(Trans2_findnext);
+               break;
+       }
+
+       case TRANSACT2_QFSINFO:
+       {
+               START_PROFILE(Trans2_qfsinfo);
+               call_trans2qfsinfo(conn, req,
+                                  &state->param, state->total_param,
+                                  &state->data, state->total_data,
+                                  state->max_data_return);
+               END_PROFILE(Trans2_qfsinfo);
+           break;
+       }
+
+       case TRANSACT2_SETFSINFO:
+       {
+               START_PROFILE(Trans2_setfsinfo);
+               call_trans2setfsinfo(conn, req,
+                                    &state->param, state->total_param,
+                                    &state->data, state->total_data,
+                                    state->max_data_return);
+               END_PROFILE(Trans2_setfsinfo);
+               break;
+       }
+
+       case TRANSACT2_QPATHINFO:
+       case TRANSACT2_QFILEINFO:
+       {
+               START_PROFILE(Trans2_qpathinfo);
+               call_trans2qfilepathinfo(conn, req, state->call,
+                                        &state->param, state->total_param,
+                                        &state->data, state->total_data,
+                                        state->max_data_return);
+               END_PROFILE(Trans2_qpathinfo);
+               break;
+       }
+
+       case TRANSACT2_SETPATHINFO:
+       case TRANSACT2_SETFILEINFO:
+       {
+               START_PROFILE(Trans2_setpathinfo);
+               call_trans2setfilepathinfo(conn, req, state->call,
+                                          &state->param, state->total_param,
+                                          &state->data, state->total_data,
+                                          state->max_data_return);
+               END_PROFILE(Trans2_setpathinfo);
+               break;
+       }
+
+       case TRANSACT2_FINDNOTIFYFIRST:
+       {
+               START_PROFILE(Trans2_findnotifyfirst);
+               call_trans2findnotifyfirst(conn, req,
+                                          &state->param, state->total_param,
+                                          &state->data, state->total_data,
+                                          state->max_data_return);
+               END_PROFILE(Trans2_findnotifyfirst);
+               break;
+       }
+
+       case TRANSACT2_FINDNOTIFYNEXT:
+       {
+               START_PROFILE(Trans2_findnotifynext);
+               call_trans2findnotifynext(conn, req,
+                                         &state->param, state->total_param,
+                                         &state->data, state->total_data,
+                                         state->max_data_return);
+               END_PROFILE(Trans2_findnotifynext);
+               break;
+       }
+
+       case TRANSACT2_MKDIR:
+       {
+               START_PROFILE(Trans2_mkdir);
+               call_trans2mkdir(conn, req,
+                                &state->param, state->total_param,
+                                &state->data, state->total_data,
+                                state->max_data_return);
+               END_PROFILE(Trans2_mkdir);
+               break;
+       }
+
+       case TRANSACT2_GET_DFS_REFERRAL:
+       {
+               START_PROFILE(Trans2_get_dfs_referral);
+               call_trans2getdfsreferral(conn, req,
+                                         &state->param, state->total_param,
+                                         &state->data, state->total_data,
+                                         state->max_data_return);
+               END_PROFILE(Trans2_get_dfs_referral);
+               break;
+       }
+
+       case TRANSACT2_IOCTL:
+       {
+               START_PROFILE(Trans2_ioctl);
+               call_trans2ioctl(conn, req,
+                                &state->param, state->total_param,
+                                &state->data, state->total_data,
+                                state->max_data_return);
+               END_PROFILE(Trans2_ioctl);
+               break;
+       }
+
+       default:
+               /* Error in request */
+               DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
+               reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
+       }
+}
+
+/****************************************************************************
+ Reply to a SMBtrans2.
+ ****************************************************************************/
+
+void reply_trans2(struct smb_request *req)
+{
+       connection_struct *conn = req->conn;
+       unsigned int dsoff;
+       unsigned int dscnt;
+       unsigned int psoff;
+       unsigned int pscnt;
+       unsigned int tran_call;
+       struct trans_state *state;
+       NTSTATUS result;
+
+       START_PROFILE(SMBtrans2);
+
+       if (req->wct < 14) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBtrans2);
+               return;
+       }
+
+       dsoff = SVAL(req->vwv+12, 0);
+       dscnt = SVAL(req->vwv+11, 0);
+       psoff = SVAL(req->vwv+10, 0);
+       pscnt = SVAL(req->vwv+9, 0);
+       tran_call = SVAL(req->vwv+14, 0);
+
+       result = allow_new_trans(conn->pending_trans, req->mid);
+       if (!NT_STATUS_IS_OK(result)) {
+               DEBUG(2, ("Got invalid trans2 request: %s\n",
+                         nt_errstr(result)));
+               reply_nterror(req, result);
+               END_PROFILE(SMBtrans2);
+               return;
+       }
+
+       if (IS_IPC(conn)) {
+               switch (tran_call) {
+               /* List the allowed trans2 calls on IPC$ */
+               case TRANSACT2_OPEN:
+               case TRANSACT2_GET_DFS_REFERRAL:
+               case TRANSACT2_QFILEINFO:
+               case TRANSACT2_QFSINFO:
+               case TRANSACT2_SETFSINFO:
+                       break;
+               default:
+                       reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+                       END_PROFILE(SMBtrans2);
+                       return;
+               }
+       }
+
+       if ((state = talloc(conn, struct trans_state)) == NULL) {
+               DEBUG(0, ("talloc failed\n"));
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               END_PROFILE(SMBtrans2);
+               return;
+       }
+
+       state->cmd = SMBtrans2;
+
+       state->mid = req->mid;
+       state->vuid = req->vuid;
+       state->setup_count = SVAL(req->vwv+13, 0);
+       state->setup = NULL;
+       state->total_param = SVAL(req->vwv+0, 0);
+       state->param = NULL;
+       state->total_data =  SVAL(req->vwv+1, 0);
+       state->data = NULL;
+       state->max_param_return = SVAL(req->vwv+2, 0);
+       state->max_data_return  = SVAL(req->vwv+3, 0);
+       state->max_setup_return = SVAL(req->vwv+4, 0);
+       state->close_on_completion = BITSETW(req->vwv+5, 0);
+       state->one_way = BITSETW(req->vwv+5, 1);
+
+       state->call = tran_call;
+
+       /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
+          is so as a sanity check */
+       if (state->setup_count != 1) {
+               /*
+                * Need to have rc=0 for ioctl to get job id for OS/2.
+                *  Network printing will fail if function is not successful.
+                *  Similar function in reply.c will be used if protocol
+                *  is LANMAN1.0 instead of LM1.2X002.
+                *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
+                *  outbuf doesn't have to be set(only job id is used).
+                */
+               if ( (state->setup_count == 4)
+                    && (tran_call == TRANSACT2_IOCTL)
+                    && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
+                    && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
+                       DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
+               } else {
+                       DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
+                       DEBUG(2,("Transaction is %d\n",tran_call));
+                       TALLOC_FREE(state);
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       END_PROFILE(SMBtrans2);
+                       return;
+               }
+       }
+
+       if ((dscnt > state->total_data) || (pscnt > state->total_param))
+               goto bad_param;
+
+       if (state->total_data) {
+
+               if (smb_buffer_oob(state->total_data, 0, dscnt)
+                   || smb_buffer_oob(smb_len(req->inbuf), dsoff, dscnt)) {
+                       goto bad_param;
+               }
+
+               /* Can't use talloc here, the core routines do realloc on the
+                * params and data. */
+               state->data = (char *)SMB_MALLOC(state->total_data);
+               if (state->data == NULL) {
+                       DEBUG(0,("reply_trans2: data malloc fail for %u "
+                                "bytes !\n", (unsigned int)state->total_data));
+                       TALLOC_FREE(state);
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                       END_PROFILE(SMBtrans2);
+                       return;
+               }
+
+               memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
+       }
+
+       if (state->total_param) {
+
+               if (smb_buffer_oob(state->total_param, 0, pscnt)
+                   || smb_buffer_oob(smb_len(req->inbuf), psoff, pscnt)) {
+                       goto bad_param;
+               }
+
+               /* Can't use talloc here, the core routines do realloc on the
+                * params and data. */
+               state->param = (char *)SMB_MALLOC(state->total_param);
+               if (state->param == NULL) {
+                       DEBUG(0,("reply_trans: param malloc fail for %u "
+                                "bytes !\n", (unsigned int)state->total_param));
+                       SAFE_FREE(state->data);
+                       TALLOC_FREE(state);
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                       END_PROFILE(SMBtrans2);
+                       return;
+               }
+
+               memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
+       }
+
+       state->received_data  = dscnt;
+       state->received_param = pscnt;
+
+       if ((state->received_param == state->total_param) &&
+           (state->received_data == state->total_data)) {
+
+               handle_trans2(conn, req, state);
+
+               SAFE_FREE(state->data);
+               SAFE_FREE(state->param);
+               TALLOC_FREE(state);
+               END_PROFILE(SMBtrans2);
+               return;
+       }
+
+       DLIST_ADD(conn->pending_trans, state);
+
+       /* We need to send an interim response then receive the rest
+          of the parameter/data bytes */
+       reply_outbuf(req, 0, 0);
+       show_msg((char *)req->outbuf);
+       END_PROFILE(SMBtrans2);
+       return;
+
+  bad_param:
+
+       DEBUG(0,("reply_trans2: invalid trans parameters\n"));
+       SAFE_FREE(state->data);
+       SAFE_FREE(state->param);
+       TALLOC_FREE(state);
+       END_PROFILE(SMBtrans2);
+       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+}
index b462dc55541ae56997ac1e42d16b43f1dc52c7af..2df8468ccaf7cb829bbb7ff779e6fcde0923b228 100644 (file)
@@ -36,3 +36,6 @@ NTSTATUS smb_set_posix_lock(connection_struct *conn,
                            const char *pdata,
                            int total_data,
                            files_struct *fsp);
+void reply_trans2(struct smb_request *req);
+void handle_trans2(connection_struct *conn, struct smb_request *req,
+                  struct trans_state *state);
index 4d91eab8ee99f4e5f58913c0d8e19529d30002c6..2a379218d46ccbe43734f11ee297f3dd0ce8e807 100644 (file)
@@ -648,7 +648,7 @@ static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
        return NT_STATUS_OK;
 }
 
-static unsigned int estimate_ea_size(files_struct *fsp)
+unsigned int estimate_ea_size(files_struct *fsp)
 {
        size_t total_ea_len = 0;
        TALLOC_CTX *mem_ctx;
@@ -821,53 +821,12 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
        }
        return NT_STATUS_OK;
 }
-/****************************************************************************
- Read a list of EA names from an incoming data buffer. Create an ea_list with them.
-****************************************************************************/
-
-static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
-{
-       struct ea_list *ea_list_head = NULL;
-       size_t converted_size, offset = 0;
-
-       while (offset + 2 < data_size) {
-               struct ea_list *eal = talloc_zero(ctx, struct ea_list);
-               unsigned int namelen = CVAL(pdata,offset);
-
-               offset++; /* Go past the namelen byte. */
-
-               /* integer wrap paranioa. */
-               if ((offset + namelen < offset) || (offset + namelen < namelen) ||
-                               (offset > data_size) || (namelen > data_size) ||
-                               (offset + namelen >= data_size)) {
-                       break;
-               }
-               /* Ensure the name is null terminated. */
-               if (pdata[offset + namelen] != '\0') {
-                       return NULL;
-               }
-               if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
-                                      &converted_size)) {
-                       DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
-                                "failed: %s", strerror(errno)));
-               }
-               if (!eal->ea.name) {
-                       return NULL;
-               }
-
-               offset += (namelen + 1); /* Go past the name + terminating zero. */
-               DLIST_ADD_END(ea_list_head, eal);
-               DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
-       }
-
-       return ea_list_head;
-}
 
 /****************************************************************************
  Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
 ****************************************************************************/
 
-static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
+struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
 {
        struct ea_list *ea_list_head = NULL;
        size_t offset = 0;
@@ -941,278 +900,6 @@ static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *
        return name_list;
 }
 
-/****************************************************************************
- Reply to a TRANSACT2_OPEN.
-****************************************************************************/
-
-static void call_trans2open(connection_struct *conn,
-                           struct smb_request *req,
-                           char **pparams, int total_params,
-                           char **ppdata, int total_data,
-                           unsigned int max_data_bytes)
-{
-       struct smb_filename *smb_fname = NULL;
-       char *params = *pparams;
-       char *pdata = *ppdata;
-       int deny_mode;
-       int32_t open_attr;
-       bool oplock_request;
-#if 0
-       bool return_additional_info;
-       int16 open_sattr;
-       time_t open_time;
-#endif
-       int open_ofun;
-       uint32_t open_size;
-       char *pname;
-       char *fname = NULL;
-       off_t size=0;
-       int fattr=0,mtime=0;
-       SMB_INO_T inode = 0;
-       int smb_action = 0;
-       files_struct *fsp;
-       struct ea_list *ea_list = NULL;
-       uint16_t flags = 0;
-       NTSTATUS status;
-       uint32_t access_mask;
-       uint32_t share_mode;
-       uint32_t create_disposition;
-       uint32_t create_options = 0;
-       uint32_t private_flags = 0;
-       uint32_t ucf_flags = ucf_flags_from_smb_request(req);
-       TALLOC_CTX *ctx = talloc_tos();
-
-       /*
-        * Ensure we have enough parameters to perform the operation.
-        */
-
-       if (total_params < 29) {
-               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-               goto out;
-       }
-
-       flags = SVAL(params, 0);
-       deny_mode = SVAL(params, 2);
-       open_attr = SVAL(params,6);
-        oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
-        if (oplock_request) {
-                oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
-        }
-
-#if 0
-       return_additional_info = BITSETW(params,0);
-       open_sattr = SVAL(params, 4);
-       open_time = make_unix_date3(params+8);
-#endif
-       open_ofun = SVAL(params,12);
-       open_size = IVAL(params,14);
-       pname = &params[28];
-
-       if (IS_IPC(conn)) {
-               reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
-               goto out;
-       }
-
-       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;
-       }
-
-       DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
-               fname, (unsigned int)deny_mode, (unsigned int)open_attr,
-               (unsigned int)open_ofun, open_size));
-
-       status = filename_convert(ctx,
-                               conn,
-                               fname,
-                               ucf_flags,
-                               0,
-                               &smb_fname);
-       if (!NT_STATUS_IS_OK(status)) {
-               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
-                       reply_botherror(req,
-                               NT_STATUS_PATH_NOT_COVERED,
-                               ERRSRV, ERRbadpath);
-                       goto out;
-               }
-               reply_nterror(req, status);
-               goto out;
-       }
-
-       if (open_ofun == 0) {
-               reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
-               goto out;
-       }
-
-       if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
-                                        open_ofun,
-                                        &access_mask, &share_mode,
-                                        &create_disposition,
-                                        &create_options,
-                                        &private_flags)) {
-               reply_nterror(req, NT_STATUS_ACCESS_DENIED);
-               goto out;
-       }
-
-       /* Any data in this call is an EA list. */
-       if (total_data && (total_data != 4)) {
-               if (total_data < 10) {
-                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-                       goto out;
-               }
-
-               if (IVAL(pdata,0) > total_data) {
-                       DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
-                               IVAL(pdata,0), (unsigned int)total_data));
-                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-                       goto out;
-               }
-
-               ea_list = read_ea_list(talloc_tos(), pdata + 4,
-                                      total_data - 4);
-               if (!ea_list) {
-                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-                       goto out;
-               }
-
-               if (!lp_ea_support(SNUM(conn))) {
-                       reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
-                       goto out;
-               }
-
-               if (!req->posix_pathnames &&
-                               ea_list_has_invalid_name(ea_list)) {
-                       int param_len = 30;
-                       *pparams = (char *)SMB_REALLOC(*pparams, param_len);
-                       if(*pparams == NULL ) {
-                               reply_nterror(req, NT_STATUS_NO_MEMORY);
-                               goto out;
-                       }
-                       params = *pparams;
-                       memset(params, '\0', param_len);
-                       send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
-                               params, param_len, NULL, 0, max_data_bytes);
-                       goto out;
-               }
-       }
-
-       status = SMB_VFS_CREATE_FILE(
-               conn,                                   /* conn */
-               req,                                    /* req */
-               smb_fname,                              /* fname */
-               access_mask,                            /* access_mask */
-               share_mode,                             /* share_access */
-               create_disposition,                     /* create_disposition*/
-               create_options,                         /* create_options */
-               open_attr,                              /* file_attributes */
-               oplock_request,                         /* oplock_request */
-               NULL,                                   /* lease */
-               open_size,                              /* allocation_size */
-               private_flags,
-               NULL,                                   /* sd */
-               ea_list,                                /* ea_list */
-               &fsp,                                   /* result */
-               &smb_action,                            /* psbuf */
-               NULL, NULL);                            /* create context */
-
-       if (!NT_STATUS_IS_OK(status)) {
-               if (open_was_deferred(req->xconn, req->mid)) {
-                       /* We have re-scheduled this call. */
-                       goto out;
-               }
-
-               if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
-                       reply_openerror(req, status);
-                       goto out;
-               }
-
-               fsp = fcb_or_dos_open(
-                       req,
-                       smb_fname,
-                       access_mask,
-                       create_options,
-                       private_flags);
-               if (fsp == NULL) {
-                       bool ok = defer_smb1_sharing_violation(req);
-                       if (ok) {
-                               goto out;
-                       }
-                       reply_openerror(req, status);
-                       goto out;
-               }
-
-               smb_action = FILE_WAS_OPENED;
-       }
-
-       size = get_file_size_stat(&smb_fname->st);
-       fattr = fdos_mode(fsp);
-       mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
-       inode = smb_fname->st.st_ex_ino;
-       if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
-               close_file_free(req, &fsp, ERROR_CLOSE);
-               reply_nterror(req, NT_STATUS_ACCESS_DENIED);
-               goto out;
-       }
-
-       /* Realloc the size of parameters and data we will return */
-       *pparams = (char *)SMB_REALLOC(*pparams, 30);
-       if(*pparams == NULL ) {
-               reply_nterror(req, NT_STATUS_NO_MEMORY);
-               goto out;
-       }
-       params = *pparams;
-
-       SSVAL(params,0,fsp->fnum);
-       SSVAL(params,2,fattr);
-       srv_put_dos_date2(params,4, mtime);
-       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. */
-
-       if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
-               smb_action |= EXTENDED_OPLOCK_GRANTED;
-       }
-
-       SSVAL(params,18,smb_action);
-
-       /*
-        * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
-        */
-       SIVAL(params,20,inode);
-       SSVAL(params,24,0); /* Padding. */
-       if (flags & 8) {
-               uint32_t ea_size = estimate_ea_size(smb_fname->fsp);
-               SIVAL(params, 26, ea_size);
-       } else {
-               SIVAL(params, 26, 0);
-       }
-
-       /* Send the required number of replies */
-       send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
- out:
-       TALLOC_FREE(smb_fname);
-}
-
 /*********************************************************
  Routine to check if a given string matches exactly.
  as a special case a mask of "." does NOT match. That
@@ -2363,971 +2050,291 @@ NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
        return NT_STATUS_OK;
 }
 
-static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
-                               connection_struct *conn,
-                               struct dptr_struct *dirptr,
-                               uint16_t flags2,
-                               const char *path_mask,
-                               uint32_t dirtype,
-                               int info_level,
-                               bool requires_resume_key,
-                               bool dont_descend,
-                               bool ask_sharemode,
-                               char **ppdata,
-                               char *base_data,
-                               char *end_data,
-                               int space_remaining,
-                               bool *got_exact_match,
-                               int *last_entry_off,
-                               struct ea_list *name_list)
+unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
 {
-       uint8_t align = 4;
-       const bool do_pad = true;
-
-       if (info_level >= 1 && info_level <= 3) {
-               /* No alignment on earlier info levels. */
-               align = 1;
-       }
-
-       return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
-                                        path_mask, dirtype, info_level,
-                                        requires_resume_key, dont_descend, ask_sharemode,
-                                        true, align, do_pad,
-                                        ppdata, base_data, end_data,
-                                        space_remaining,
-                                        NULL,
-                                        got_exact_match,
-                                        last_entry_off, name_list, NULL);
+       const struct loadparm_substitution *lp_sub =
+               loadparm_s3_global_substitution();
+
+       E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
+       return objid;
 }
 
-/****************************************************************************
- Reply to a TRANS2_FINDFIRST.
-****************************************************************************/
+static void samba_extended_info_version(struct smb_extended_info *extended_info)
+{
+       SMB_ASSERT(extended_info != NULL);
 
-static void call_trans2findfirst(connection_struct *conn,
-                                struct smb_request *req,
-                                char **pparams, int total_params,
-                                char **ppdata, int total_data,
-                                unsigned int max_data_bytes)
+       extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
+       extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
+                                      | ((SAMBA_VERSION_MINOR & 0xff) << 16)
+                                      | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
+#ifdef SAMBA_VERSION_REVISION
+       extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
+#endif
+       extended_info->samba_subversion = 0;
+#ifdef SAMBA_VERSION_RC_RELEASE
+       extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
+#else
+#ifdef SAMBA_VERSION_PRE_RELEASE
+       extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
+#endif
+#endif
+#ifdef SAMBA_VERSION_VENDOR_PATCH
+       extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
+#endif
+       extended_info->samba_gitcommitdate = 0;
+#ifdef SAMBA_VERSION_COMMIT_TIME
+       unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
+#endif
+
+       memset(extended_info->samba_version_string, 0,
+              sizeof(extended_info->samba_version_string));
+
+       snprintf (extended_info->samba_version_string,
+                 sizeof(extended_info->samba_version_string),
+                 "%s", samba_version_string());
+}
+
+NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
+                        connection_struct *conn,
+                        TALLOC_CTX *mem_ctx,
+                        uint16_t info_level,
+                        uint16_t flags2,
+                        unsigned int max_data_bytes,
+                        size_t *fixed_portion,
+                        struct smb_filename *fname,
+                        char **ppdata,
+                        int *ret_data_len)
 {
-       /* We must be careful here that we don't return more than the
-               allowed number of data bytes. If this means returning fewer than
-               maxentries then so be it. We assume that the redirector has
-               enough room for the fixed number of parameter bytes it has
-               requested. */
-       struct smb_filename *smb_dname = NULL;
-       char *params = *pparams;
-       char *pdata = *ppdata;
-       char *data_end;
-       uint32_t dirtype;
-       int maxentries;
-       uint16_t findfirst_flags;
-       bool close_after_first;
-       bool close_if_end;
-       bool requires_resume_key;
-       int info_level;
-       char *directory = NULL;
-       char *mask = NULL;
-       char *p;
-       int last_entry_off=0;
-       int dptr_num = -1;
-       int numentries = 0;
-       int i;
-       bool finished = False;
-       bool dont_descend = False;
-       bool out_of_space = False;
-       int space_remaining;
-       struct ea_list *ea_list = NULL;
-       NTSTATUS ntstatus = NT_STATUS_OK;
-       bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
-       struct smbd_server_connection *sconn = req->sconn;
-       uint32_t ucf_flags = ucf_flags_from_smb_request(req);
-       bool backup_priv = false;
-       bool as_root = false;
-       files_struct *fsp = NULL;
        const struct loadparm_substitution *lp_sub =
                loadparm_s3_global_substitution();
+       char *pdata, *end_data;
+       int data_len = 0;
+       size_t len = 0;
+       const char *vname = volume_label(talloc_tos(), SNUM(conn));
+       int snum = SNUM(conn);
+       const char *fstype = lp_fstype(SNUM(conn));
+       const char *filename = NULL;
+       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 (total_params < 13) {
-               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-               goto out;
+       if (fname == NULL || fname->base_name == NULL) {
+               filename = ".";
+       } else {
+               filename = fname->base_name;
        }
 
-       dirtype = SVAL(params,0);
-       maxentries = SVAL(params,2);
-       findfirst_flags = SVAL(params,4);
-       close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
-       close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
-       requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
-       backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
-                               security_token_has_privilege(get_current_nttok(conn),
-                                               SEC_PRIV_BACKUP));
-
-       info_level = SVAL(params,6);
-
-       DBG_NOTICE("dirtype = %"PRIx32", maxentries = %d, "
-                  "close_after_first=%d, close_if_end = %d "
-                  "requires_resume_key = %d backup_priv = %d level = 0x%x, "
-                  "max_data_bytes = %d\n",
-                  dirtype,
-                  maxentries,
-                  close_after_first,
-                  close_if_end,
-                  requires_resume_key,
-                  backup_priv,
-                  info_level,
-                  max_data_bytes);
-
-       if (!maxentries) {
-               /* W2K3 seems to treat zero as 1. */
-               maxentries = 1;
+       if (IS_IPC(conn)) {
+               if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
+                       DEBUG(0,("smbd_do_qfsinfo: not an allowed "
+                               "info level (0x%x) on IPC$.\n",
+                               (unsigned int)info_level));
+                       return NT_STATUS_ACCESS_DENIED;
+               }
        }
 
-       switch (info_level) {
-               case SMB_FIND_INFO_STANDARD:
-               case SMB_FIND_EA_SIZE:
-               case SMB_FIND_EA_LIST:
-               case SMB_FIND_FILE_DIRECTORY_INFO:
-               case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
-               case SMB_FIND_FILE_NAMES_INFO:
-               case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
-               case SMB_FIND_ID_FULL_DIRECTORY_INFO:
-               case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
-                       break;
-               case SMB_FIND_FILE_UNIX:
-               case SMB_FIND_FILE_UNIX_INFO2:
-                       if (!lp_smb1_unix_extensions()) {
-                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
-                               goto out;
-                       }
-                       if (!req->posix_pathnames) {
-                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
-                               goto out;
-                       }
-                       break;
-               default:
-                       reply_nterror(req, NT_STATUS_INVALID_LEVEL);
-                       goto out;
-       }
+       DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
 
-       if (req->posix_pathnames) {
-               /* Always use filesystem for UNIX mtime query. */
-               ask_sharemode = false;
-       }
+       smb_fname = (struct smb_filename) {
+               .base_name = discard_const_p(char, filename),
+               .flags = fname ? fname->flags : 0,
+               .twrp = fname ? fname->twrp : 0,
+       };
 
-       if (req->posix_pathnames) {
-               srvstr_get_path_posix(talloc_tos(),
-                               params,
-                               req->flags2,
-                               &directory,
-                               params+12,
-                               total_params - 12,
-                               STR_TERMINATE,
-                               &ntstatus);
-       } else {
-               srvstr_get_path(talloc_tos(),
-                               params,
-                               req->flags2,
-                               &directory,
-                               params+12,
-                               total_params - 12,
-                               STR_TERMINATE,
-                               &ntstatus);
-       }
-       if (!NT_STATUS_IS_OK(ntstatus)) {
-               reply_nterror(req, ntstatus);
-               goto out;
-       }
-
-       if (backup_priv) {
-               become_root();
-               as_root = true;
-       }
-       ntstatus = filename_convert_smb1_search_path(talloc_tos(),
-                                                    conn,
-                                                    directory,
-                                                    ucf_flags,
-                                                    &smb_dname,
-                                                    &mask);
-
-       if (!NT_STATUS_IS_OK(ntstatus)) {
-               if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
-                       reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
-                                       ERRSRV, ERRbadpath);
-                       goto out;
-               }
-               reply_nterror(req, ntstatus);
-               goto out;
+       if(info_level != SMB_FS_QUOTA_INFORMATION
+          && SMB_VFS_STAT(conn, &smb_fname) != 0) {
+               DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
+               return map_nt_error_from_unix(errno);
        }
 
-       TALLOC_FREE(directory);
-       directory = smb_dname->base_name;
-
-       DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
-
-       if (info_level == SMB_FIND_EA_LIST) {
-               uint32_t ea_size;
-
-               if (total_data < 4) {
-                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-                       goto out;
-               }
-
-               ea_size = IVAL(pdata,0);
-               if (ea_size != total_data) {
-                       DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
-total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
-                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-                       goto out;
-               }
-
-               if (!lp_ea_support(SNUM(conn))) {
-                       reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
-                       goto out;
-               }
-
-               /* Pull out the list of names. */
-               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;
-               }
-       }
+       st = smb_fname.st;
 
        if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
-               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-               goto out;
+               return NT_STATUS_INVALID_PARAMETER;
        }
 
        *ppdata = (char *)SMB_REALLOC(
                *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
-       if(*ppdata == NULL ) {
-               reply_nterror(req, NT_STATUS_NO_MEMORY);
-               goto out;
-       }
-       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) {
-               reply_nterror(req, NT_STATUS_NO_MEMORY);
-               goto out;
-       }
-       params = *pparams;
-
-       /*
-        * Open an fsp on this directory for the dptr.
-        */
-       ntstatus = SMB_VFS_CREATE_FILE(
-                       conn, /* conn */
-                       req, /* req */
-                       smb_dname, /* dname */
-                       FILE_LIST_DIRECTORY, /* access_mask */
-                       FILE_SHARE_READ|
-                       FILE_SHARE_WRITE, /* share_access */
-                       FILE_OPEN, /* create_disposition*/
-                       FILE_DIRECTORY_FILE, /* create_options */
-                       FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
-                       NO_OPLOCK, /* oplock_request */
-                       NULL, /* lease */
-                       0, /* allocation_size */
-                       0, /* private_flags */
-                       NULL, /* sd */
-                       NULL, /* ea_list */
-                       &fsp, /* result */
-                       NULL, /* pinfo */
-                       NULL, /* in_context */
-                       NULL);/* out_context */
-
-       if (!NT_STATUS_IS_OK(ntstatus)) {
-               DBG_ERR("failed to open directory %s\n",
-                       smb_fname_str_dbg(smb_dname));
-               reply_nterror(req, ntstatus);
-               goto out;
-       }
-
-       /* Save the wildcard match and attribs we are using on this directory -
-               needed as lanman2 assumes these are being saved between calls */
-
-       ntstatus = dptr_create(conn,
-                               req,
-                               fsp, /* fsp */
-                               False,
-                               True,
-                               req->smbpid,
-                               mask,
-                               dirtype,
-                               &fsp->dptr);
-
-       if (!NT_STATUS_IS_OK(ntstatus)) {
-               /*
-                * Use NULL here for the first parameter (req)
-                * as this is not a client visible handle so
-                * can'tbe part of an SMB1 chain.
-                */
-               close_file_free(NULL, &fsp, NORMAL_CLOSE);
-               reply_nterror(req, ntstatus);
-               goto out;
-       }
-
-       if (backup_priv) {
-               /* Remember this in case we have
-                  to do a findnext. */
-               dptr_set_priv(fsp->dptr);
+       if (*ppdata == NULL) {
+               return NT_STATUS_NO_MEMORY;
        }
 
-       dptr_num = dptr_dnum(fsp->dptr);
-       DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
-
-       /* We don't need to check for VOL here as this is returned by
-               a different TRANS2 call. */
-
-       DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
-                directory,lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn))));
-       if (in_list(directory,
-                   lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn)),
-                       dptr_case_sensitive(fsp->dptr))) {
-               dont_descend = True;
-       }
+       pdata = *ppdata;
+       memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
+       end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
 
-       p = pdata;
-       space_remaining = max_data_bytes;
-       out_of_space = False;
+       *fixed_portion = 0;
 
-       for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
-               bool got_exact_match = False;
+       switch (info_level) {
+               case SMB_INFO_ALLOCATION:
+               {
+                       uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
+                       data_len = 18;
+                       df_ret = get_dfree_info(conn, &smb_fname, &bsize,
+                                               &dfree, &dsize);
+                       if (df_ret == (uint64_t)-1) {
+                               return map_nt_error_from_unix(errno);
+                       }
 
-               /* this is a heuristic to avoid seeking the dirptr except when
-                       absolutely necessary. It allows for a filename of about 40 chars */
-               if (space_remaining < DIRLEN_GUESS && numentries > 0) {
-                       out_of_space = True;
-                       finished = False;
-               } else {
-                       ntstatus = get_lanman2_dir_entry(talloc_tos(),
-                                       conn,
-                                       fsp->dptr,
-                                       req->flags2,
-                                       mask,dirtype,info_level,
-                                       requires_resume_key,dont_descend,
-                                       ask_sharemode,
-                                       &p,pdata,data_end,
-                                       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;
+                       block_size = lp_block_size(snum);
+                       if (bsize < block_size) {
+                               uint64_t factor = block_size/bsize;
+                               bsize = block_size;
+                               dsize /= factor;
+                               dfree /= factor;
                        }
-                       if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
-                               out_of_space = true;
-                       } else {
-                               finished = !NT_STATUS_IS_OK(ntstatus);
+                       if (bsize > block_size) {
+                               uint64_t factor = bsize/block_size;
+                               bsize = block_size;
+                               dsize *= factor;
+                               dfree *= factor;
                        }
-               }
-
-               if (!finished && !out_of_space)
-                       numentries++;
-
-               /*
-                * As an optimisation if we know we aren't looking
-                * for a wildcard name (ie. the name matches the wildcard exactly)
-                * then we can finish on any (first) match.
-                * This speeds up large directory searches. JRA.
-                */
-
-               if(got_exact_match)
-                       finished = True;
-
-               /* Ensure space_remaining never goes -ve. */
-               if (PTR_DIFF(p,pdata) > max_data_bytes) {
-                       space_remaining = 0;
-                       out_of_space = true;
-               } else {
-                       space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
-               }
-       }
-
-       /* Check if we can close the dirptr */
-       if(close_after_first || (finished && close_if_end)) {
-               DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
-               dptr_num = -1;
-               close_file_free(NULL, &fsp, NORMAL_CLOSE);
-       }
-
-       /*
-        * If there are no matching entries we must return ERRDOS/ERRbadfile -
-        * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
-        * the protocol level is less than NT1. Tested with smbclient. JRA.
-        * This should fix the OS/2 client bug #2335.
-        */
-
-       if(numentries == 0) {
-               dptr_num = -1;
-               /*
-                * We may have already closed the file in the
-                * close_after_first or finished case above.
-                */
-               if (fsp != NULL) {
-                       close_file_free(NULL, &fsp, NORMAL_CLOSE);
-               }
-               if (get_Protocol() < PROTOCOL_NT1) {
-                       reply_force_doserror(req, ERRDOS, ERRnofiles);
-                       goto out;
-               } else {
-                       reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
-                                       ERRDOS, ERRbadfile);
-                       goto out;
-               }
-       }
-
-       /* At this point pdata points to numentries directory entries. */
+                       sectors_per_unit = bsize/bytes_per_sector;
 
-       /* Set up the return parameter block */
-       SSVAL(params,0,dptr_num);
-       SSVAL(params,2,numentries);
-       SSVAL(params,4,finished);
-       SSVAL(params,6,0); /* Never an EA error */
-       SSVAL(params,8,last_entry_off);
+                       DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
+cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
+                               (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
 
-       send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
-                           max_data_bytes);
+                       /*
+                        * For large drives, return max values and not modulo.
+                        */
+                       dsize = MIN(dsize, UINT32_MAX);
+                       dfree = MIN(dfree, UINT32_MAX);
 
-       if ((! *directory) && dptr_path(sconn, dptr_num)) {
-               directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
-               if (!directory) {
-                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                       SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
+                       SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
+                       SIVAL(pdata,l1_cUnit,dsize);
+                       SIVAL(pdata,l1_cUnitAvail,dfree);
+                       SSVAL(pdata,l1_cbSector,bytes_per_sector);
+                       break;
                }
-       }
-
-       DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
-               smb_fn_name(req->cmd),
-               mask, directory, dirtype, numentries ) );
-
-       /*
-        * Force a name mangle here to ensure that the
-        * mask as an 8.3 name is top of the mangled cache.
-        * The reasons for this are subtle. Don't remove
-        * this code unless you know what you are doing
-        * (see PR#13758). JRA.
-        */
-
-       if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
-               char mangled_name[13];
-               name_to_8_3(mask, mangled_name, True, conn->params);
-       }
- out:
-
-       if (as_root) {
-               unbecome_root();
-       }
-
-       TALLOC_FREE(smb_dname);
-       return;
-}
 
-/****************************************************************************
- Reply to a TRANS2_FINDNEXT.
-****************************************************************************/
+               case SMB_INFO_VOLUME:
+                       /* Return volume name */
+                       /* 
+                        * Add volume serial number - hash of a combination of
+                        * the called hostname and the service name.
+                        */
+                       SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^ (str_checksum(get_local_machine_name())<<16) );
+                       /*
+                        * Win2k3 and previous mess this up by sending a name length
+                        * one byte short. I believe only older clients (OS/2 Win9x) use
+                        * this call so try fixing this by adding a terminating null to
+                        * the pushed string. The change here was adding the STR_TERMINATE. JRA.
+                        */
+                       status = srvstr_push(
+                               pdata, flags2,
+                               pdata+l2_vol_szVolLabel, vname,
+                               PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
+                               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",
+                                (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
+                                (unsigned)len, vname));
+                       break;
 
-static void call_trans2findnext(connection_struct *conn,
-                               struct smb_request *req,
-                               char **pparams, int total_params,
-                               char **ppdata, int total_data,
-                               unsigned int max_data_bytes)
-{
-       /* We must be careful here that we don't return more than the
-               allowed number of data bytes. If this means returning fewer than
-               maxentries then so be it. We assume that the redirector has
-               enough room for the fixed number of parameter bytes it has
-               requested. */
-       char *params = *pparams;
-       char *pdata = *ppdata;
-       char *data_end;
-       int dptr_num;
-       int maxentries;
-       uint16_t info_level;
-       uint32_t resume_key;
-       uint16_t findnext_flags;
-       bool close_after_request;
-       bool close_if_end;
-       bool requires_resume_key;
-       bool continue_bit;
-       char *resume_name = NULL;
-       const char *mask = NULL;
-       const char *directory = NULL;
-       char *p = NULL;
-       uint16_t dirtype;
-       int numentries = 0;
-       int i, last_entry_off=0;
-       bool finished = False;
-       bool dont_descend = False;
-       bool out_of_space = False;
-       int space_remaining;
-       struct ea_list *ea_list = NULL;
-       NTSTATUS ntstatus = NT_STATUS_OK;
-       bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
-       TALLOC_CTX *ctx = talloc_tos();
-       struct smbd_server_connection *sconn = req->sconn;
-       bool backup_priv = false; 
-       bool as_root = false;
-       files_struct *fsp = NULL;
-       const struct loadparm_substitution *lp_sub =
-               loadparm_s3_global_substitution();
+               case SMB_QUERY_FS_ATTRIBUTE_INFO:
+               case SMB_FS_ATTRIBUTE_INFORMATION:
 
-       if (total_params < 13) {
-               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-               return;
-       }
+                       additional_flags = 0;
+#if defined(HAVE_SYS_QUOTAS)
+                       additional_flags |= FILE_VOLUME_QUOTAS;
+#endif
 
-       dptr_num = SVAL(params,0);
-       maxentries = SVAL(params,2);
-       info_level = SVAL(params,4);
-       resume_key = IVAL(params,6);
-       findnext_flags = SVAL(params,10);
-       close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
-       close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
-       requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
-       continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
-
-       if (!continue_bit) {
-               /* We only need resume_name if continue_bit is zero. */
-               if (req->posix_pathnames) {
-                       srvstr_get_path_posix(ctx,
-                               params,
-                               req->flags2,
-                               &resume_name,
-                               params+12,
-                               total_params - 12,
-                               STR_TERMINATE,
-                               &ntstatus);
-               } else {
-                       srvstr_get_path(ctx,
-                               params,
-                               req->flags2,
-                               &resume_name,
-                               params+12,
-                               total_params - 12,
-                               STR_TERMINATE,
-                               &ntstatus);
-               }
-               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
-                          path or an invalid name). Catch this as the resume name is only compared, never used in
-                          a file access. JRA. */
-                       srvstr_pull_talloc(ctx, params, req->flags2,
-                               &resume_name, params+12,
-                               total_params - 12,
-                               STR_TERMINATE);
-
-                       if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
-                               reply_nterror(req, ntstatus);
-                               return;
+                       if(lp_nt_acl_support(SNUM(conn))) {
+                               additional_flags |= FILE_PERSISTENT_ACLS;
                        }
-               }
-       }
 
-       DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
-close_after_request=%d, close_if_end = %d requires_resume_key = %d \
-resume_key = %d resume name = %s continue=%d level = %d\n",
-               dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
-               requires_resume_key, resume_key,
-               resume_name ? resume_name : "(NULL)", continue_bit, info_level));
+                       /* Capabilities are filled in at connection time through STATVFS call */
+                       additional_flags |= conn->fs_capabilities;
+                       additional_flags |= lp_parm_int(conn->params->service,
+                                                       "share", "fake_fscaps",
+                                                       0);
 
-       if (!maxentries) {
-               /* W2K3 seems to treat zero as 1. */
-               maxentries = 1;
-       }
+                       SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
+                               FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
+                               additional_flags); /* FS ATTRIBUTES */
 
-       switch (info_level) {
-               case SMB_FIND_INFO_STANDARD:
-               case SMB_FIND_EA_SIZE:
-               case SMB_FIND_EA_LIST:
-               case SMB_FIND_FILE_DIRECTORY_INFO:
-               case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
-               case SMB_FIND_FILE_NAMES_INFO:
-               case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
-               case SMB_FIND_ID_FULL_DIRECTORY_INFO:
-               case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
-                       break;
-               case SMB_FIND_FILE_UNIX:
-               case SMB_FIND_FILE_UNIX_INFO2:
-                       /* Always use filesystem for UNIX mtime query. */
-                       ask_sharemode = false;
-                       if (!lp_smb1_unix_extensions()) {
-                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
-                               return;
+                       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 */
+                       status = srvstr_push(pdata, flags2, pdata+12, fstype,
+                                         PTR_DIFF(end_data, pdata+12),
+                                         STR_UNICODE, &len);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return status;
                        }
-                       if (!req->posix_pathnames) {
-                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
-                               return;
+                       SIVAL(pdata,8,len);
+                       data_len = 12 + len;
+                       if (max_data_bytes >= 16 && data_len > max_data_bytes) {
+                               /* the client only requested a portion of the
+                                  file system name */
+                               data_len = max_data_bytes;
+                               status = STATUS_BUFFER_OVERFLOW;
                        }
+                       *fixed_portion = 16;
                        break;
-               default:
-                       reply_nterror(req, NT_STATUS_INVALID_LEVEL);
-                       return;
-       }
-
-       if (info_level == SMB_FIND_EA_LIST) {
-               uint32_t ea_size;
 
-               if (total_data < 4) {
-                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-                       return;
-               }
-
-               ea_size = IVAL(pdata,0);
-               if (ea_size != total_data) {
-                       DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
-total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
-                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-                       return;
-               }
+               case SMB_QUERY_FS_LABEL_INFO:
+               case SMB_FS_LABEL_INFORMATION:
+                       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;
 
-               if (!lp_ea_support(SNUM(conn))) {
-                       reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
-                       return;
-               }
+               case SMB_QUERY_FS_VOLUME_INFO:      
+               case SMB_FS_VOLUME_INFORMATION:
 
-               /* Pull out the list of names. */
-               ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
-               if (!ea_list) {
-                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-                       return;
-               }
-       }
-
-       if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
-               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-               return;
-       }
-
-       *ppdata = (char *)SMB_REALLOC(
-               *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
-       if(*ppdata == NULL) {
-               reply_nterror(req, NT_STATUS_NO_MEMORY);
-               return;
-       }
-
-       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 ) {
-               reply_nterror(req, NT_STATUS_NO_MEMORY);
-               return;
-       }
-
-       params = *pparams;
-
-       /* Check that the dptr is valid */
-       fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
-       if (fsp == NULL) {
-               reply_nterror(req, STATUS_NO_MORE_FILES);
-               return;
-       }
-
-       directory = dptr_path(sconn, dptr_num);
-
-       /* Get the wildcard mask from the dptr */
-       if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
-               DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
-               reply_nterror(req, STATUS_NO_MORE_FILES);
-               return;
-       }
-
-       /* Get the attr mask from the dptr */
-       dirtype = dptr_attr(sconn, dptr_num);
-
-       backup_priv = dptr_get_priv(fsp->dptr);
-
-       DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
-               "backup_priv = %d\n",
-               dptr_num, mask, dirtype,
-               (long)fsp->dptr,
-               dptr_TellDir(fsp->dptr),
-               (int)backup_priv));
-
-       /* We don't need to check for VOL here as this is returned by
-               a different TRANS2 call. */
-
-       DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
-                directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
-       if (in_list(directory,lp_dont_descend(ctx, lp_sub, SNUM(conn)),
-                       dptr_case_sensitive(fsp->dptr)))
-               dont_descend = True;
-
-       p = pdata;
-       space_remaining = max_data_bytes;
-       out_of_space = False;
-
-       if (backup_priv) {
-               become_root();
-               as_root = true;
-       }
-
-       /*
-        * Seek to the correct position. We no longer use the resume key but
-        * depend on the last file name instead.
-        */
-
-       if(!continue_bit && resume_name && *resume_name) {
-               SMB_STRUCT_STAT st;
-               bool posix_open = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN);
-
-               long current_pos = 0;
-               /*
-                * Remember, name_to_8_3 is called by
-                * get_lanman2_dir_entry(), so the resume name
-                * could be mangled. Ensure we check the unmangled name.
-                */
+                       /* 
+                        * Add volume serial number - hash of a combination of
+                        * the called hostname and the service name.
+                        */
+                       SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
+                               (str_checksum(get_local_machine_name())<<16));
 
-               if (!posix_open &&
-                               mangle_is_mangled(resume_name, conn->params)) {
-                       char *new_resume_name = NULL;
-                       mangle_lookup_name_from_8_3(ctx,
-                                               resume_name,
-                                               &new_resume_name,
-                                               conn->params);
-                       if (new_resume_name) {
-                               resume_name = new_resume_name;
+                       /* Max label len is 32 characters. */
+                       status = srvstr_push(pdata, flags2, pdata+18, vname,
+                                         PTR_DIFF(end_data, pdata+18),
+                                         STR_UNICODE, &len);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return status;
                        }
-               }
-
-               /*
-                * Fix for NT redirector problem triggered by resume key indexes
-                * changing between directory scans. We now return a resume key of 0
-                * and instead look for the filename to continue from (also given
-                * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
-                * findfirst/findnext (as is usual) then the directory pointer
-                * should already be at the correct place.
-                */
-
-               finished = !dptr_SearchDir(fsp->dptr, resume_name, &current_pos, &st);
-       } /* end if resume_name && !continue_bit */
-
-       for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
-               bool got_exact_match = False;
+                       SIVAL(pdata,12,len);
+                       data_len = 18+len;
 
-               /* this is a heuristic to avoid seeking the fsp->dptr except when
-                       absolutely necessary. It allows for a filename of about 40 chars */
-               if (space_remaining < DIRLEN_GUESS && numentries > 0) {
-                       out_of_space = True;
-                       finished = False;
-               } else {
-                       ntstatus = get_lanman2_dir_entry(ctx,
-                                               conn,
-                                               fsp->dptr,
-                                               req->flags2,
-                                               mask,dirtype,info_level,
-                                               requires_resume_key,dont_descend,
-                                               ask_sharemode,
-                                               &p,pdata,data_end,
-                                               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);
+                       DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
+                               (int)strlen(vname),vname,
+                               lp_servicename(talloc_tos(), lp_sub, snum)));
+                       if (max_data_bytes >= 24 && data_len > max_data_bytes) {
+                               /* the client only requested a portion of the
+                                  volume label */
+                               data_len = max_data_bytes;
+                               status = STATUS_BUFFER_OVERFLOW;
                        }
-               }
-
-               if (!finished && !out_of_space)
-                       numentries++;
-
-               /*
-                * As an optimisation if we know we aren't looking
-                * for a wildcard name (ie. the name matches the wildcard exactly)
-                * then we can finish on any (first) match.
-                * This speeds up large directory searches. JRA.
-                */
-
-               if(got_exact_match)
-                       finished = True;
-
-               space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
-       }
-
-       DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
-               smb_fn_name(req->cmd),
-               mask, directory, dirtype, numentries ) );
-
-       /* Check if we can close the fsp->dptr */
-       if(close_after_request || (finished && close_if_end)) {
-               DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
-               dptr_num = -1;
-               close_file_free(NULL, &fsp, NORMAL_CLOSE);
-       }
-
-       if (as_root) {
-               unbecome_root();
-       }
-
-       /* Set up the return parameter block */
-       SSVAL(params,0,numentries);
-       SSVAL(params,2,finished);
-       SSVAL(params,4,0); /* Never an EA error */
-       SSVAL(params,6,last_entry_off);
-
-       send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
-                           max_data_bytes);
-
-       return;
-}
-
-unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
-{
-       const struct loadparm_substitution *lp_sub =
-               loadparm_s3_global_substitution();
-
-       E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
-       return objid;
-}
-
-static void samba_extended_info_version(struct smb_extended_info *extended_info)
-{
-       SMB_ASSERT(extended_info != NULL);
-
-       extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
-       extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
-                                      | ((SAMBA_VERSION_MINOR & 0xff) << 16)
-                                      | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
-#ifdef SAMBA_VERSION_REVISION
-       extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
-#endif
-       extended_info->samba_subversion = 0;
-#ifdef SAMBA_VERSION_RC_RELEASE
-       extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
-#else
-#ifdef SAMBA_VERSION_PRE_RELEASE
-       extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
-#endif
-#endif
-#ifdef SAMBA_VERSION_VENDOR_PATCH
-       extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
-#endif
-       extended_info->samba_gitcommitdate = 0;
-#ifdef SAMBA_VERSION_COMMIT_TIME
-       unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
-#endif
-
-       memset(extended_info->samba_version_string, 0,
-              sizeof(extended_info->samba_version_string));
-
-       snprintf (extended_info->samba_version_string,
-                 sizeof(extended_info->samba_version_string),
-                 "%s", samba_version_string());
-}
-
-NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
-                        connection_struct *conn,
-                        TALLOC_CTX *mem_ctx,
-                        uint16_t info_level,
-                        uint16_t flags2,
-                        unsigned int max_data_bytes,
-                        size_t *fixed_portion,
-                        struct smb_filename *fname,
-                        char **ppdata,
-                        int *ret_data_len)
-{
-       const struct loadparm_substitution *lp_sub =
-               loadparm_s3_global_substitution();
-       char *pdata, *end_data;
-       int data_len = 0;
-       size_t len = 0;
-       const char *vname = volume_label(talloc_tos(), SNUM(conn));
-       int snum = SNUM(conn);
-       const char *fstype = lp_fstype(SNUM(conn));
-       const char *filename = NULL;
-       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 = ".";
-       } else {
-               filename = fname->base_name;
-       }
-
-       if (IS_IPC(conn)) {
-               if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
-                       DEBUG(0,("smbd_do_qfsinfo: not an allowed "
-                               "info level (0x%x) on IPC$.\n",
-                               (unsigned int)info_level));
-                       return NT_STATUS_ACCESS_DENIED;
-               }
-       }
-
-       DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
-
-       smb_fname = (struct smb_filename) {
-               .base_name = discard_const_p(char, filename),
-               .flags = fname ? fname->flags : 0,
-               .twrp = fname ? fname->twrp : 0,
-       };
-
-       if(info_level != SMB_FS_QUOTA_INFORMATION
-          && SMB_VFS_STAT(conn, &smb_fname) != 0) {
-               DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
-               return map_nt_error_from_unix(errno);
-       }
-
-       st = smb_fname.st;
-
-       if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       *ppdata = (char *)SMB_REALLOC(
-               *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
-       if (*ppdata == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       pdata = *ppdata;
-       memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
-       end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
-
-       *fixed_portion = 0;
+                       *fixed_portion = 24;
+                       break;
 
-       switch (info_level) {
-               case SMB_INFO_ALLOCATION:
+               case SMB_QUERY_FS_SIZE_INFO:
+               case SMB_FS_SIZE_INFORMATION:
                {
                        uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
-                       data_len = 18;
+                       data_len = 24;
                        df_ret = get_dfree_info(conn, &smb_fname, &bsize,
                                                &dfree, &dsize);
                        if (df_ret == (uint64_t)-1) {
                                return map_nt_error_from_unix(errno);
                        }
-
                        block_size = lp_block_size(snum);
                        if (bsize < block_size) {
                                uint64_t factor = block_size/bsize;
@@ -3342,170 +2349,14 @@ NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
                                dfree *= factor;
                        }
                        sectors_per_unit = bsize/bytes_per_sector;
-
-                       DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
-cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
+                       DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
+cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
                                (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
-
-                       /*
-                        * For large drives, return max values and not modulo.
-                        */
-                       dsize = MIN(dsize, UINT32_MAX);
-                       dfree = MIN(dfree, UINT32_MAX);
-
-                       SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
-                       SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
-                       SIVAL(pdata,l1_cUnit,dsize);
-                       SIVAL(pdata,l1_cUnitAvail,dfree);
-                       SSVAL(pdata,l1_cbSector,bytes_per_sector);
-                       break;
-               }
-
-               case SMB_INFO_VOLUME:
-                       /* Return volume name */
-                       /* 
-                        * Add volume serial number - hash of a combination of
-                        * the called hostname and the service name.
-                        */
-                       SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^ (str_checksum(get_local_machine_name())<<16) );
-                       /*
-                        * Win2k3 and previous mess this up by sending a name length
-                        * one byte short. I believe only older clients (OS/2 Win9x) use
-                        * this call so try fixing this by adding a terminating null to
-                        * the pushed string. The change here was adding the STR_TERMINATE. JRA.
-                        */
-                       status = srvstr_push(
-                               pdata, flags2,
-                               pdata+l2_vol_szVolLabel, vname,
-                               PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
-                               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",
-                                (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
-                                (unsigned)len, vname));
-                       break;
-
-               case SMB_QUERY_FS_ATTRIBUTE_INFO:
-               case SMB_FS_ATTRIBUTE_INFORMATION:
-
-                       additional_flags = 0;
-#if defined(HAVE_SYS_QUOTAS)
-                       additional_flags |= FILE_VOLUME_QUOTAS;
-#endif
-
-                       if(lp_nt_acl_support(SNUM(conn))) {
-                               additional_flags |= FILE_PERSISTENT_ACLS;
-                       }
-
-                       /* Capabilities are filled in at connection time through STATVFS call */
-                       additional_flags |= conn->fs_capabilities;
-                       additional_flags |= lp_parm_int(conn->params->service,
-                                                       "share", "fake_fscaps",
-                                                       0);
-
-                       SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
-                               FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
-                               additional_flags); /* FS ATTRIBUTES */
-
-                       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 */
-                       status = srvstr_push(pdata, flags2, pdata+12, fstype,
-                                         PTR_DIFF(end_data, pdata+12),
-                                         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) {
-                               /* the client only requested a portion of the
-                                  file system name */
-                               data_len = max_data_bytes;
-                               status = STATUS_BUFFER_OVERFLOW;
-                       }
-                       *fixed_portion = 16;
-                       break;
-
-               case SMB_QUERY_FS_LABEL_INFO:
-               case SMB_FS_LABEL_INFORMATION:
-                       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;
-
-               case SMB_QUERY_FS_VOLUME_INFO:      
-               case SMB_FS_VOLUME_INFORMATION:
-
-                       /* 
-                        * Add volume serial number - hash of a combination of
-                        * the called hostname and the service name.
-                        */
-                       SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
-                               (str_checksum(get_local_machine_name())<<16));
-
-                       /* Max label len is 32 characters. */
-                       status = srvstr_push(pdata, flags2, pdata+18, vname,
-                                         PTR_DIFF(end_data, pdata+18),
-                                         STR_UNICODE, &len);
-                       if (!NT_STATUS_IS_OK(status)) {
-                               return status;
-                       }
-                       SIVAL(pdata,12,len);
-                       data_len = 18+len;
-
-                       DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
-                               (int)strlen(vname),vname,
-                               lp_servicename(talloc_tos(), lp_sub, snum)));
-                       if (max_data_bytes >= 24 && data_len > max_data_bytes) {
-                               /* the client only requested a portion of the
-                                  volume label */
-                               data_len = max_data_bytes;
-                               status = STATUS_BUFFER_OVERFLOW;
-                       }
-                       *fixed_portion = 24;
-                       break;
-
-               case SMB_QUERY_FS_SIZE_INFO:
-               case SMB_FS_SIZE_INFORMATION:
-               {
-                       uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
-                       data_len = 24;
-                       df_ret = get_dfree_info(conn, &smb_fname, &bsize,
-                                               &dfree, &dsize);
-                       if (df_ret == (uint64_t)-1) {
-                               return map_nt_error_from_unix(errno);
-                       }
-                       block_size = lp_block_size(snum);
-                       if (bsize < block_size) {
-                               uint64_t factor = block_size/bsize;
-                               bsize = block_size;
-                               dsize /= factor;
-                               dfree /= factor;
-                       }
-                       if (bsize > block_size) {
-                               uint64_t factor = bsize/block_size;
-                               bsize = block_size;
-                               dsize *= factor;
-                               dfree *= factor;
-                       }
-                       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,
-                               (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
-                       SBIG_UINT(pdata,0,dsize);
-                       SBIG_UINT(pdata,8,dfree);
-                       SIVAL(pdata,16,sectors_per_unit);
-                       SIVAL(pdata,20,bytes_per_sector);
-                       *fixed_portion = 24;
+                       SBIG_UINT(pdata,0,dsize);
+                       SBIG_UINT(pdata,8,dfree);
+                       SIVAL(pdata,16,sectors_per_unit);
+                       SIVAL(pdata,20,bytes_per_sector);
+                       *fixed_portion = 24;
                        break;
                }
 
@@ -3884,10 +2735,10 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
        return status;
 }
 
-static NTSTATUS smb_set_fsquota(connection_struct *conn,
-                       struct smb_request *req,
-                       files_struct *fsp,
-                       const DATA_BLOB *qdata)
+NTSTATUS smb_set_fsquota(connection_struct *conn,
+                        struct smb_request *req,
+                        files_struct *fsp,
+                        const DATA_BLOB *qdata)
 {
        const struct loadparm_substitution *lp_sub =
                loadparm_s3_global_substitution();
@@ -3966,271 +2817,6 @@ NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
        return NT_STATUS_INVALID_LEVEL;
 }
 
-/****************************************************************************
- Reply to a TRANS2_QFSINFO (query filesystem info).
-****************************************************************************/
-
-static void call_trans2qfsinfo(connection_struct *conn,
-                              struct smb_request *req,
-                              char **pparams, int total_params,
-                              char **ppdata, int total_data,
-                              unsigned int max_data_bytes)
-{
-       char *params = *pparams;
-       uint16_t info_level;
-       int data_len = 0;
-       size_t fixed_portion;
-       NTSTATUS status;
-
-       if (total_params < 2) {
-               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-               return;
-       }
-
-       info_level = SVAL(params,0);
-
-       if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
-               if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
-                       DEBUG(0,("call_trans2qfsinfo: encryption required "
-                               "and info level 0x%x sent.\n",
-                               (unsigned int)info_level));
-                       reply_nterror(req, NT_STATUS_ACCESS_DENIED);
-                       return;
-               }
-       }
-
-       DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
-
-       status = smbd_do_qfsinfo(req->xconn, conn, req,
-                                info_level,
-                                req->flags2,
-                                max_data_bytes,
-                                &fixed_portion,
-                                NULL,
-                                ppdata, &data_len);
-       if (!NT_STATUS_IS_OK(status)) {
-               reply_nterror(req, status);
-               return;
-       }
-
-       send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
-                           max_data_bytes);
-
-       DEBUG( 4, ( "%s info_level = %d\n",
-                   smb_fn_name(req->cmd), info_level) );
-
-       return;
-}
-
-/****************************************************************************
- Reply to a TRANS2_SETFSINFO (set filesystem info).
-****************************************************************************/
-
-static void call_trans2setfsinfo(connection_struct *conn,
-                                struct smb_request *req,
-                                char **pparams, int total_params,
-                                char **ppdata, int total_data,
-                                unsigned int max_data_bytes)
-{
-       const struct loadparm_substitution *lp_sub =
-               loadparm_s3_global_substitution();
-       struct smbXsrv_connection *xconn = req->xconn;
-       char *pdata = *ppdata;
-       char *params = *pparams;
-       uint16_t info_level;
-
-       DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
-                 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
-
-       /*  */
-       if (total_params < 4) {
-               DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
-                       total_params));
-               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-               return;
-       }
-
-       info_level = SVAL(params,2);
-
-       if (IS_IPC(conn)) {
-               if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
-                               info_level != SMB_SET_CIFS_UNIX_INFO) {
-                       DEBUG(0,("call_trans2setfsinfo: not an allowed "
-                               "info level (0x%x) on IPC$.\n",
-                               (unsigned int)info_level));
-                       reply_nterror(req, NT_STATUS_ACCESS_DENIED);
-                       return;
-               }
-       }
-
-       if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
-               if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
-                       DEBUG(0,("call_trans2setfsinfo: encryption required "
-                               "and info level 0x%x sent.\n",
-                               (unsigned int)info_level));
-                       reply_nterror(req, NT_STATUS_ACCESS_DENIED);
-                       return;
-               }
-       }
-
-       switch(info_level) {
-               case SMB_SET_CIFS_UNIX_INFO:
-                       if (!lp_smb1_unix_extensions()) {
-                               DEBUG(2,("call_trans2setfsinfo: "
-                                       "SMB_SET_CIFS_UNIX_INFO is invalid with "
-                                       "unix extensions off\n"));
-                               reply_nterror(req,
-                                             NT_STATUS_INVALID_LEVEL);
-                               return;
-                       }
-
-                       /* There should be 12 bytes of capabilities set. */
-                       if (total_data < 12) {
-                               reply_nterror(
-                                       req,
-                                       NT_STATUS_INVALID_PARAMETER);
-                               return;
-                       }
-                       xconn->smb1.unix_info.client_major = SVAL(pdata,0);
-                       xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
-                       xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
-                       xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
-                       /* Just print these values for now. */
-                       DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
-                                  "major = %u, minor = %u cap_low = 0x%x, "
-                                  "cap_high = 0x%xn",
-                                  (unsigned int)xconn->
-                                  smb1.unix_info.client_major,
-                                  (unsigned int)xconn->
-                                  smb1.unix_info.client_minor,
-                                  (unsigned int)xconn->
-                                  smb1.unix_info.client_cap_low,
-                                  (unsigned int)xconn->
-                                  smb1.unix_info.client_cap_high));
-
-                       /* Here is where we must switch to posix pathname processing... */
-                       if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
-                               lp_set_posix_pathnames();
-                               mangle_change_to_posix();
-                       }
-
-                       if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
-                           !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
-                               /* Client that knows how to do posix locks,
-                                * but not posix open/mkdir operations. Set a
-                                * default type for read/write checks. */
-
-                               lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
-
-                       }
-                       break;
-
-               case SMB_REQUEST_TRANSPORT_ENCRYPTION:
-                       {
-                               NTSTATUS status;
-                               size_t param_len = 0;
-                               size_t data_len = total_data;
-
-                               if (!lp_smb1_unix_extensions()) {
-                                       reply_nterror(
-                                               req,
-                                               NT_STATUS_INVALID_LEVEL);
-                                       return;
-                               }
-
-                               if (lp_server_smb_encrypt(SNUM(conn)) ==
-                                   SMB_ENCRYPTION_OFF) {
-                                       reply_nterror(
-                                               req,
-                                               NT_STATUS_NOT_SUPPORTED);
-                                       return;
-                               }
-
-                               if (xconn->smb1.echo_handler.trusted_fde) {
-                                       DEBUG( 2,("call_trans2setfsinfo: "
-                                               "request transport encryption disabled"
-                                               "with 'fork echo handler = yes'\n"));
-                                       reply_nterror(
-                                               req,
-                                               NT_STATUS_NOT_SUPPORTED);
-                                       return;
-                               }
-
-                               DEBUG( 4,("call_trans2setfsinfo: "
-                                       "request transport encryption.\n"));
-
-                               status = srv_request_encryption_setup(conn,
-                                                               (unsigned char **)ppdata,
-                                                               &data_len,
-                                                               (unsigned char **)pparams,
-                                                               &param_len);
-
-                               if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
-                                               !NT_STATUS_IS_OK(status)) {
-                                       reply_nterror(req, status);
-                                       return;
-                               }
-
-                               send_trans2_replies(conn, req,
-                                               NT_STATUS_OK,
-                                               *pparams,
-                                               param_len,
-                                               *ppdata,
-                                               data_len,
-                                               max_data_bytes);
-
-                               if (NT_STATUS_IS_OK(status)) {
-                                       /* Server-side transport
-                                        * encryption is now *on*. */
-                                       status = srv_encryption_start(conn);
-                                       if (!NT_STATUS_IS_OK(status)) {
-                                               char *reason = talloc_asprintf(talloc_tos(),
-                                                                              "Failure in setting "
-                                                                              "up encrypted transport: %s",
-                                                                              nt_errstr(status));
-                                               exit_server_cleanly(reason);
-                                       }
-                               }
-                               return;
-                       }
-
-               case SMB_FS_QUOTA_INFORMATION:
-                       {
-                               NTSTATUS status;
-                               DATA_BLOB qdata = {
-                                               .data = (uint8_t *)pdata,
-                                               .length = total_data
-                               };
-                               files_struct *fsp = NULL;
-                               fsp = file_fsp(req, SVAL(params,0));
-
-                               status = smb_set_fsquota(conn,
-                                                       req,
-                                                       fsp,
-                                                       &qdata);
-                               if (!NT_STATUS_IS_OK(status)) {
-                                       reply_nterror(req, status);
-                                       return;
-                               }
-                               break;
-                       }
-               default:
-                       DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
-                               info_level));
-                       reply_nterror(req, NT_STATUS_INVALID_LEVEL);
-                       return;
-                       break;
-       }
-
-       /* 
-        * sending this reply works fine, 
-        * but I'm not sure it's the same 
-        * like windows do...
-        * --metze
-        */
-       reply_outbuf(req, 10, 0);
-}
-
 #if defined(HAVE_POSIX_ACLS)
 /****************************************************************************
  Utility function to count the number of entries in a POSIX acl.
@@ -4822,81 +3408,6 @@ static NTSTATUS smb_query_posix_acl(connection_struct *conn,
 }
 #endif
 
-/****************************************************************************
- Reply to a TRANSACT2_QFILEINFO on a PIPE !
-****************************************************************************/
-
-static void call_trans2qpipeinfo(connection_struct *conn,
-                                struct smb_request *req,
-                                unsigned int tran_call,
-                                char **pparams, int total_params,
-                                char **ppdata, int total_data,
-                                unsigned int max_data_bytes)
-{
-       char *params = *pparams;
-       char *pdata = *ppdata;
-       unsigned int data_size = 0;
-       unsigned int param_size = 2;
-       uint16_t info_level;
-       files_struct *fsp;
-
-       if (!params) {
-               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-               return;
-       }
-
-       if (total_params < 4) {
-               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-               return;
-       }
-
-       fsp = file_fsp(req, SVAL(params,0));
-       if (!fsp_is_np(fsp)) {
-               reply_nterror(req, NT_STATUS_INVALID_HANDLE);
-               return;
-       }
-
-       info_level = SVAL(params,2);
-
-       *pparams = (char *)SMB_REALLOC(*pparams,2);
-       if (*pparams == NULL) {
-               reply_nterror(req, NT_STATUS_NO_MEMORY);
-               return;
-       }
-       params = *pparams;
-       SSVAL(params,0,0);
-       if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
-               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-               return;
-       }
-       data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
-       *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
-       if (*ppdata == NULL ) {
-               reply_nterror(req, NT_STATUS_NO_MEMORY);
-               return;
-       }
-       pdata = *ppdata;
-
-       switch (info_level) {
-               case SMB_FILE_STANDARD_INFORMATION:
-                       memset(pdata,0,24);
-                       SOFF_T(pdata,0,4096LL);
-                       SIVAL(pdata,16,1);
-                       SIVAL(pdata,20,1);
-                       data_size = 24;
-                       break;
-
-               default:
-                       reply_nterror(req, NT_STATUS_INVALID_LEVEL);
-                       return;
-       }
-
-       send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
-                           max_data_bytes);
-
-       return;
-}
-
 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                               TALLOC_CTX *mem_ctx,
                               struct smb_request *req,
@@ -5707,423 +4218,6 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
        return NT_STATUS_OK;
 }
 
-/****************************************************************************
- Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
- file name or file id).
-****************************************************************************/
-
-static void call_trans2qfilepathinfo(connection_struct *conn,
-                                    struct smb_request *req,
-                                    unsigned int tran_call,
-                                    char **pparams, int total_params,
-                                    char **ppdata, int total_data,
-                                    unsigned int max_data_bytes)
-{
-       char *params = *pparams;
-       char *pdata = *ppdata;
-       uint16_t info_level;
-       unsigned int data_size = 0;
-       unsigned int param_size = 2;
-       struct smb_filename *smb_fname = NULL;
-       bool delete_pending = False;
-       struct timespec write_time_ts;
-       files_struct *fsp = NULL;
-       struct file_id fileid;
-       struct ea_list *ea_list = NULL;
-       int lock_data_count = 0;
-       char *lock_data = NULL;
-       size_t fixed_portion;
-       NTSTATUS status = NT_STATUS_OK;
-       int ret;
-
-       if (!params) {
-               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-               return;
-       }
-
-       ZERO_STRUCT(write_time_ts);
-
-       if (tran_call == TRANSACT2_QFILEINFO) {
-               if (total_params < 4) {
-                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-                       return;
-               }
-
-               if (IS_IPC(conn)) {
-                       call_trans2qpipeinfo(conn, req, tran_call,
-                                            pparams, total_params,
-                                            ppdata, total_data,
-                                            max_data_bytes);
-                       return;
-               }
-
-               fsp = file_fsp(req, SVAL(params,0));
-               info_level = SVAL(params,2);
-
-               DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
-
-               if (INFO_LEVEL_IS_UNIX(info_level)) {
-                       if (!lp_smb1_unix_extensions()) {
-                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
-                               return;
-                       }
-                       if (!req->posix_pathnames) {
-                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
-                               return;
-                       }
-               }
-
-               /* Initial check for valid fsp ptr. */
-               if (!check_fsp_open(conn, req, fsp)) {
-                       return;
-               }
-
-               smb_fname = fsp->fsp_name;
-
-               if(fsp->fake_file_handle) {
-                       /*
-                        * This is actually for the QUOTA_FAKE_FILE --metze
-                        */
-
-                       /* We know this name is ok, it's already passed the checks. */
-
-               } else if(fsp_get_pathref_fd(fsp) == -1) {
-                       /*
-                        * This is actually a QFILEINFO on a directory
-                        * handle (returned from an NT SMB). NT5.0 seems
-                        * to do this call. JRA.
-                        */
-                       ret = vfs_stat(conn, smb_fname);
-                       if (ret != 0) {
-                               DBG_NOTICE("vfs_stat of %s failed (%s)\n",
-                                        smb_fname_str_dbg(smb_fname),
-                                        strerror(errno));
-                               reply_nterror(req,
-                                       map_nt_error_from_unix(errno));
-                               return;
-                       }
-
-                       if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
-                               fileid = vfs_file_id_from_sbuf(
-                                       conn, &smb_fname->st);
-                               get_file_infos(fileid, fsp->name_hash,
-                                              &delete_pending,
-                                              &write_time_ts);
-                       }
-               } else {
-                       /*
-                        * Original code - this is an open file.
-                        */
-                       status = vfs_stat_fsp(fsp);
-                       if (!NT_STATUS_IS_OK(status)) {
-                               DEBUG(3, ("fstat of %s failed (%s)\n",
-                                         fsp_fnum_dbg(fsp), nt_errstr(status)));
-                               reply_nterror(req, status);
-                               return;
-                       }
-                       if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
-                               fileid = vfs_file_id_from_sbuf(
-                                       conn, &smb_fname->st);
-                               get_file_infos(fileid, fsp->name_hash,
-                                              &delete_pending,
-                                              &write_time_ts);
-                       }
-               }
-
-       } else {
-               uint32_t name_hash;
-               char *fname = NULL;
-               uint32_t ucf_flags = ucf_flags_from_smb_request(req);
-
-               /* qpathinfo */
-               if (total_params < 7) {
-                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-                       return;
-               }
-
-               info_level = SVAL(params,0);
-
-               DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
-
-               if (INFO_LEVEL_IS_UNIX(info_level)) {
-                       if (!lp_smb1_unix_extensions()) {
-                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
-                               return;
-                       }
-                       if (!req->posix_pathnames) {
-                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
-                               return;
-                       }
-               }
-
-               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;
-               }
-
-               status = filename_convert(req,
-                                       conn,
-                                       fname,
-                                       ucf_flags,
-                                       0,
-                                       &smb_fname);
-               if (!NT_STATUS_IS_OK(status)) {
-                       if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
-                               reply_botherror(req,
-                                               NT_STATUS_PATH_NOT_COVERED,
-                                               ERRSRV, ERRbadpath);
-                               return;
-                       }
-                       reply_nterror(req, status);
-                       return;
-               }
-
-               /*
-                * qpathinfo must operate on an existing file, so we
-                * can exit early if filename_convert() returned the "new file"
-                * NT_STATUS_OK, !VALID_STAT case.
-                */
-
-               if (!VALID_STAT(smb_fname->st)) {
-                       reply_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
-                       return;
-               }
-
-               /*
-                * smb_fname->fsp may be NULL if smb_fname points at a symlink
-                * and we're in POSIX context, so be careful when using fsp
-                * below, it can still be NULL.
-                */
-               fsp = smb_fname->fsp;
-
-               /* If this is a stream, check if there is a delete_pending. */
-               if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
-                   && is_ntfs_stream_smb_fname(smb_fname)) {
-                       struct smb_filename *smb_fname_base;
-
-                       /* Create an smb_filename with stream_name == NULL. */
-                       smb_fname_base = synthetic_smb_fname(
-                                               talloc_tos(),
-                                               smb_fname->base_name,
-                                               NULL,
-                                               NULL,
-                                               smb_fname->twrp,
-                                               smb_fname->flags);
-                       if (smb_fname_base == NULL) {
-                               reply_nterror(req, NT_STATUS_NO_MEMORY);
-                               return;
-                       }
-
-                       ret = vfs_stat(conn, smb_fname_base);
-                       if (ret != 0) {
-                               DBG_NOTICE("vfs_stat of %s failed "
-                                       "(%s)\n",
-                                       smb_fname_str_dbg(smb_fname_base),
-                                       strerror(errno));
-                               TALLOC_FREE(smb_fname_base);
-                               reply_nterror(req,
-                                       map_nt_error_from_unix(errno));
-                               return;
-                       }
-
-                       status = file_name_hash(conn,
-                                       smb_fname_str_dbg(smb_fname_base),
-                                       &name_hash);
-                       if (!NT_STATUS_IS_OK(status)) {
-                               TALLOC_FREE(smb_fname_base);
-                               reply_nterror(req, status);
-                               return;
-                       }
-
-                       fileid = vfs_file_id_from_sbuf(conn,
-                                                      &smb_fname_base->st);
-                       TALLOC_FREE(smb_fname_base);
-                       get_file_infos(fileid, name_hash, &delete_pending, NULL);
-                       if (delete_pending) {
-                               reply_nterror(req, NT_STATUS_DELETE_PENDING);
-                               return;
-                       }
-               }
-
-               status = file_name_hash(conn,
-                               smb_fname_str_dbg(smb_fname),
-                               &name_hash);
-               if (!NT_STATUS_IS_OK(status)) {
-                       reply_nterror(req, status);
-                       return;
-               }
-
-               if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
-                       fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
-                       get_file_infos(fileid, name_hash, &delete_pending,
-                                      &write_time_ts);
-               }
-
-               if (delete_pending) {
-                       reply_nterror(req, NT_STATUS_DELETE_PENDING);
-                       return;
-               }
-       }
-
-       DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
-                "total_data=%d\n", smb_fname_str_dbg(smb_fname),
-                fsp_fnum_dbg(fsp),
-                info_level,tran_call,total_data));
-
-       /* Pull out any data sent here before we realloc. */
-       switch (info_level) {
-               case SMB_INFO_QUERY_EAS_FROM_LIST:
-               {
-                       /* Pull any EA list from the data portion. */
-                       uint32_t ea_size;
-
-                       if (total_data < 4) {
-                               reply_nterror(
-                                       req, NT_STATUS_INVALID_PARAMETER);
-                               return;
-                       }
-                       ea_size = IVAL(pdata,0);
-
-                       if (total_data > 0 && ea_size != total_data) {
-                               DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
-total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
-                               reply_nterror(
-                                       req, NT_STATUS_INVALID_PARAMETER);
-                               return;
-                       }
-
-                       if (!lp_ea_support(SNUM(conn))) {
-                               reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
-                               return;
-                       }
-
-                       /* Pull out the list of names. */
-                       ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
-                       if (!ea_list) {
-                               reply_nterror(
-                                       req, NT_STATUS_INVALID_PARAMETER);
-                               return;
-                       }
-                       break;
-               }
-
-               case SMB_QUERY_POSIX_LOCK:
-               {
-                       if (fsp == NULL ||
-                           fsp->fsp_flags.is_pathref ||
-                           fsp_get_io_fd(fsp) == -1)
-                       {
-                               reply_nterror(req, NT_STATUS_INVALID_HANDLE);
-                               return;
-                       }
-
-                       if (total_data != POSIX_LOCK_DATA_SIZE) {
-                               reply_nterror(
-                                       req, NT_STATUS_INVALID_PARAMETER);
-                               return;
-                       }
-
-                       /* Copy the lock range data. */
-                       lock_data = (char *)talloc_memdup(
-                               req, pdata, total_data);
-                       if (!lock_data) {
-                               reply_nterror(req, NT_STATUS_NO_MEMORY);
-                               return;
-                       }
-                       lock_data_count = total_data;
-                       break;
-               }
-               default:
-                       break;
-       }
-
-       *pparams = (char *)SMB_REALLOC(*pparams,2);
-       if (*pparams == NULL) {
-               reply_nterror(req, NT_STATUS_NO_MEMORY);
-               return;
-       }
-       params = *pparams;
-       SSVAL(params,0,0);
-
-       /*
-        * draft-leach-cifs-v1-spec-02.txt
-        * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
-        * says:
-        *
-        *  The requested information is placed in the Data portion of the
-        *  transaction response. For the information levels greater than 0x100,
-        *  the transaction response has 1 parameter word which should be
-        *  ignored by the client.
-        *
-        * However Windows only follows this rule for the IS_NAME_VALID call.
-        */
-       switch (info_level) {
-       case SMB_INFO_IS_NAME_VALID:
-               param_size = 0;
-               break;
-       }
-
-       if ((info_level & SMB2_INFO_SPECIAL) == SMB2_INFO_SPECIAL) {
-               /*
-                * We use levels that start with 0xFF00
-                * internally to represent SMB2 specific levels
-                */
-               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
-               return;
-       }
-
-       status = smbd_do_qfilepathinfo(conn, req, req, info_level,
-                                      fsp, smb_fname,
-                                      delete_pending, write_time_ts,
-                                      ea_list,
-                                      lock_data_count, lock_data,
-                                      req->flags2, max_data_bytes,
-                                      &fixed_portion,
-                                      ppdata, &data_size);
-       if (!NT_STATUS_IS_OK(status)) {
-               if (open_was_deferred(req->xconn, req->mid)) {
-                       /* We have re-scheduled this call. */
-                       return;
-               }
-               if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
-                       bool ok = defer_smb1_sharing_violation(req);
-                       if (ok) {
-                               return;
-                       }
-               }
-               reply_nterror(req, status);
-               return;
-       }
-       if (fixed_portion > max_data_bytes) {
-               reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
-               return;
-       }
-
-       send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
-                           max_data_bytes);
-
-       return;
-}
-
 /****************************************************************************
  Set a hard link (called by UNIX extensions and by NT rename with HARD link
  code.
@@ -8255,991 +6349,207 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
                                create_disp = FILE_OVERWRITE;
                                break;
                        default:
-                               /* Cannot get here. */
-                               smb_panic("smb_posix_open: logic error");
-                               return NT_STATUS_INVALID_PARAMETER;
-               }
-       }
-
-       raw_unixmode = IVAL(pdata,8);
-       /* Next 4 bytes are not yet defined. */
-
-       status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
-                                     (VALID_STAT(smb_fname->st) ?
-                                         PERM_EXISTING_FILE : PERM_NEW_FILE),
-                                     &unixmode);
-
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
-
-       status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
-       if (!NT_STATUS_IS_OK(status)) {
-               DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
-                           nt_errstr(status));
-               return status;
-       }
-
-       if (wire_open_mode & SMB_O_SYNC) {
-               create_options |= FILE_WRITE_THROUGH;
-       }
-       if (wire_open_mode & SMB_O_APPEND) {
-               access_mask |= FILE_APPEND_DATA;
-       }
-       if (wire_open_mode & SMB_O_DIRECT) {
-               attributes |= FILE_FLAG_NO_BUFFERING;
-       }
-
-       if ((wire_open_mode & SMB_O_DIRECTORY) ||
-                       VALID_STAT_OF_DIR(smb_fname->st)) {
-               if (access_mask != SMB_O_RDONLY_MAPPING) {
-                       return NT_STATUS_FILE_IS_A_DIRECTORY;
-               }
-               create_options &= ~FILE_NON_DIRECTORY_FILE;
-               create_options |= FILE_DIRECTORY_FILE;
-       }
-
-       DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
-               smb_fname_str_dbg(smb_fname),
-               (unsigned int)wire_open_mode,
-               (unsigned int)unixmode ));
-
-        status = SMB_VFS_CREATE_FILE(
-               conn,                                   /* conn */
-               req,                                    /* req */
-               smb_fname,                              /* fname */
-               access_mask,                            /* access_mask */
-               (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
-                   FILE_SHARE_DELETE),
-               create_disp,                            /* create_disposition*/
-               create_options,                         /* create_options */
-               attributes,                             /* file_attributes */
-               oplock_request,                         /* oplock_request */
-               NULL,                                   /* lease */
-               0,                                      /* allocation_size */
-               0,                                      /* private_flags */
-               NULL,                                   /* sd */
-               NULL,                                   /* ea_list */
-               &fsp,                                   /* result */
-               &info,                                  /* pinfo */
-               posx,                                   /* in_context_blobs */
-               NULL);                                  /* out_context_blobs */
-
-       TALLOC_FREE(posx);
-
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
-
-       if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
-               extended_oplock_granted = True;
-       }
-
-       if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
-               extended_oplock_granted = True;
-       }
-
-       info_level_return = SVAL(pdata,16);
-       /* Allocate the correct return size. */
-
-       if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
-               *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
-       } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
-               *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
-       } else {
-               *pdata_return_size = 12;
-       }
-
-       /* Realloc the data size */
-       *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
-       if (*ppdata == NULL) {
-               close_file_free(req, &fsp, ERROR_CLOSE);
-               *pdata_return_size = 0;
-               return NT_STATUS_NO_MEMORY;
-       }
-       pdata = *ppdata;
-
-       if (extended_oplock_granted) {
-               if (flags & REQUEST_BATCH_OPLOCK) {
-                       SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
-               } else {
-                       SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
-               }
-       } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
-               SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
-       } else {
-               SSVAL(pdata,0,NO_OPLOCK_RETURN);
-       }
-
-       SSVAL(pdata,2,fsp->fnum);
-       SIVAL(pdata,4,info); /* Was file created etc. */
-
-       switch (info_level_return) {
-               case SMB_QUERY_FILE_UNIX_BASIC:
-                       SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
-                       SSVAL(pdata,10,0); /* padding. */
-                       store_file_unix_basic(conn, pdata + 12, fsp,
-                                             &smb_fname->st);
-                       break;
-               case SMB_QUERY_FILE_UNIX_INFO2:
-                       SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
-                       SSVAL(pdata,10,0); /* padding. */
-                       store_file_unix_basic_info2(conn, pdata + 12, fsp,
-                                                   &smb_fname->st);
-                       break;
-               default:
-                       SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
-                       SSVAL(pdata,10,0); /* padding. */
-                       break;
-       }
-       return NT_STATUS_OK;
-}
-
-/****************************************************************************
- Delete a file with POSIX semantics.
-****************************************************************************/
-
-static NTSTATUS smb_posix_unlink(connection_struct *conn,
-                                struct smb_request *req,
-                               const char *pdata,
-                               int total_data,
-                               struct smb_filename *smb_fname)
-{
-       NTSTATUS status = NT_STATUS_OK;
-       files_struct *fsp = NULL;
-       uint16_t flags = 0;
-       char del = 1;
-       int info = 0;
-       int create_options = 0;
-       struct share_mode_lock *lck = NULL;
-       bool other_nonposix_opens;
-       struct smb2_create_blobs *posx = NULL;
-
-       if (total_data < 2) {
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       flags = SVAL(pdata,0);
-
-       if (!VALID_STAT(smb_fname->st)) {
-               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
-       }
-
-       if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
-                       !VALID_STAT_OF_DIR(smb_fname->st)) {
-               return NT_STATUS_NOT_A_DIRECTORY;
-       }
-
-       DEBUG(10,("smb_posix_unlink: %s %s\n",
-               (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
-               smb_fname_str_dbg(smb_fname)));
-
-       if (VALID_STAT_OF_DIR(smb_fname->st)) {
-               create_options |= FILE_DIRECTORY_FILE;
-       }
-
-       status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
-       if (!NT_STATUS_IS_OK(status)) {
-               DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
-                           nt_errstr(status));
-               return status;
-       }
-
-        status = SMB_VFS_CREATE_FILE(
-               conn,                                   /* conn */
-               req,                                    /* req */
-               smb_fname,                              /* fname */
-               DELETE_ACCESS,                          /* access_mask */
-               (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
-                   FILE_SHARE_DELETE),
-               FILE_OPEN,                              /* create_disposition*/
-               create_options,                         /* create_options */
-               0,                                      /* file_attributes */
-               0,                                      /* oplock_request */
-               NULL,                                   /* lease */
-               0,                                      /* allocation_size */
-               0,                                      /* private_flags */
-               NULL,                                   /* sd */
-               NULL,                                   /* ea_list */
-               &fsp,                                   /* result */
-               &info,                                  /* pinfo */
-               posx,                                   /* in_context_blobs */
-               NULL);                                  /* out_context_blobs */
-
-       TALLOC_FREE(posx);
-
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
-
-       /*
-        * Don't lie to client. If we can't really delete due to
-        * non-POSIX opens return SHARING_VIOLATION.
-        */
-
-       lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
-       if (lck == NULL) {
-               DEBUG(0, ("smb_posix_unlink: Could not get share mode "
-                         "lock for file %s\n", fsp_str_dbg(fsp)));
-               close_file_free(req, &fsp, NORMAL_CLOSE);
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       other_nonposix_opens = has_other_nonposix_opens(lck, fsp);
-       if (other_nonposix_opens) {
-               /* Fail with sharing violation. */
-               TALLOC_FREE(lck);
-               close_file_free(req, &fsp, NORMAL_CLOSE);
-               return NT_STATUS_SHARING_VIOLATION;
-       }
-
-       /*
-        * Set the delete on close.
-        */
-       status = smb_set_file_disposition_info(conn,
-                                               &del,
-                                               1,
-                                               fsp,
-                                               smb_fname);
-
-       TALLOC_FREE(lck);
-
-       if (!NT_STATUS_IS_OK(status)) {
-               close_file_free(req, &fsp, NORMAL_CLOSE);
-               return status;
-       }
-       return close_file_free(req, &fsp, NORMAL_CLOSE);
-}
-
-static NTSTATUS smbd_do_posix_setfilepathinfo(struct connection_struct *conn,
-                                             struct smb_request *req,
-                                             TALLOC_CTX *mem_ctx,
-                                             uint16_t info_level,
-                                             struct smb_filename *smb_fname,
-                                             files_struct *fsp,
-                                             char **ppdata,
-                                             int total_data,
-                                             int *ret_data_size)
-{
-       char *pdata = *ppdata;
-       NTSTATUS status = NT_STATUS_OK;
-       int data_return_size = 0;
-
-       *ret_data_size = 0;
-
-       if (!CAN_WRITE(conn)) {
-               /* Allow POSIX opens. The open path will deny
-                * any non-readonly opens. */
-               if (info_level != SMB_POSIX_PATH_OPEN) {
-                       return NT_STATUS_DOS(ERRSRV, ERRaccess);
-               }
-       }
-
-       DBG_DEBUG("file=%s (%s) info_level=%d totdata=%d\n",
-                 smb_fname_str_dbg(smb_fname),
-                 fsp_fnum_dbg(fsp),
-                 info_level,
-                 total_data);
-
-       switch (info_level) {
-               case SMB_SET_FILE_UNIX_BASIC:
-               {
-                       status = smb_set_file_unix_basic(conn, req,
-                                                       pdata,
-                                                       total_data,
-                                                       fsp,
-                                                       smb_fname);
-                       break;
-               }
-
-               case SMB_SET_FILE_UNIX_INFO2:
-               {
-                       status = smb_set_file_unix_info2(conn, req,
-                                                       pdata,
-                                                       total_data,
-                                                       fsp,
-                                                       smb_fname);
-                       break;
-               }
-
-               case SMB_SET_FILE_UNIX_LINK:
-               {
-                       if (smb_fname == NULL) {
-                               /* We must have a pathname for this. */
-                               return NT_STATUS_INVALID_LEVEL;
-                       }
-                       status = smb_set_file_unix_link(conn, req, pdata,
-                                                       total_data, smb_fname);
-                       break;
-               }
-
-               case SMB_SET_FILE_UNIX_HLINK:
-               {
-                       if (smb_fname == NULL) {
-                               /* We must have a pathname for this. */
-                               return NT_STATUS_INVALID_LEVEL;
-                       }
-                       status = smb_set_file_unix_hlink(conn, req,
-                                                        pdata, total_data,
-                                                        smb_fname);
-                       break;
-               }
-
-#if defined(HAVE_POSIX_ACLS)
-               case SMB_SET_POSIX_ACL:
-               {
-                       status = smb_set_posix_acl(conn,
-                                               req,
-                                               pdata,
-                                               total_data,
-                                               fsp,
-                                               smb_fname);
-                       break;
-               }
-#endif
-
-               case SMB_SET_POSIX_LOCK:
-               {
-                       if (fsp == NULL) {
-                               return NT_STATUS_INVALID_LEVEL;
-                       }
-                       status = smb_set_posix_lock(conn, req,
-                                                   pdata, total_data, fsp);
-                       break;
-               }
-
-               case SMB_POSIX_PATH_OPEN:
-               {
-                       if (smb_fname == NULL) {
-                               /* We must have a pathname for this. */
-                               return NT_STATUS_INVALID_LEVEL;
-                       }
-
-                       status = smb_posix_open(conn, req,
-                                               ppdata,
-                                               total_data,
-                                               smb_fname,
-                                               &data_return_size);
-                       break;
-               }
-
-               case SMB_POSIX_PATH_UNLINK:
-               {
-                       if (smb_fname == NULL) {
-                               /* We must have a pathname for this. */
-                               return NT_STATUS_INVALID_LEVEL;
-                       }
-
-                       status = smb_posix_unlink(conn, req,
-                                               pdata,
-                                               total_data,
-                                               smb_fname);
-                       break;
-               }
-
-               default:
-                       return NT_STATUS_INVALID_LEVEL;
-       }
-
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
-
-       *ret_data_size = data_return_size;
-       return NT_STATUS_OK;
-}
-
-NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
-                               struct smb_request *req,
-                               TALLOC_CTX *mem_ctx,
-                               uint16_t info_level,
-                               files_struct *fsp,
-                               struct smb_filename *smb_fname,
-                               char **ppdata, int total_data,
-                               int *ret_data_size)
-{
-       char *pdata = *ppdata;
-       NTSTATUS status = NT_STATUS_OK;
-       int data_return_size = 0;
-
-       if (INFO_LEVEL_IS_UNIX(info_level)) {
-               if (!lp_smb1_unix_extensions()) {
-                       return NT_STATUS_INVALID_LEVEL;
-               }
-               if (!req->posix_pathnames) {
-                       return NT_STATUS_INVALID_LEVEL;
-               }
-               status = smbd_do_posix_setfilepathinfo(conn,
-                                                      req,
-                                                      req,
-                                                      info_level,
-                                                      smb_fname,
-                                                      fsp,
-                                                      ppdata,
-                                                      total_data,
-                                                      &data_return_size);
-               if (!NT_STATUS_IS_OK(status)) {
-                       return status;
-               }
-               *ret_data_size = data_return_size;
-               return NT_STATUS_OK;
-       }
-
-       *ret_data_size = 0;
-
-       DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
-                "totdata=%d\n", smb_fname_str_dbg(smb_fname),
-                fsp_fnum_dbg(fsp),
-                info_level, total_data));
-
-       switch (info_level) {
-
-               case SMB_INFO_STANDARD:
-               {
-                       status = smb_set_info_standard(conn,
-                                       pdata,
-                                       total_data,
-                                       fsp,
-                                       smb_fname);
-                       break;
-               }
-
-               case SMB_INFO_SET_EA:
-               {
-                       status = smb_info_set_ea(conn,
-                                               pdata,
-                                               total_data,
-                                               fsp,
-                                               smb_fname);
-                       break;
-               }
-
-               case SMB_SET_FILE_BASIC_INFO:
-               case SMB_FILE_BASIC_INFORMATION:
-               {
-                       status = smb_set_file_basic_info(conn,
-                                                       pdata,
-                                                       total_data,
-                                                       fsp,
-                                                       smb_fname);
-                       break;
-               }
-
-               case SMB_FILE_ALLOCATION_INFORMATION:
-               case SMB_SET_FILE_ALLOCATION_INFO:
-               {
-                       status = smb_set_file_allocation_info(conn, req,
-                                                               pdata,
-                                                               total_data,
-                                                               fsp,
-                                                               smb_fname);
-                       break;
-               }
-
-               case SMB_FILE_END_OF_FILE_INFORMATION:
-               case SMB_SET_FILE_END_OF_FILE_INFO:
-               {
-                       /*
-                        * XP/Win7 both fail after the createfile with
-                        * SMB_SET_FILE_END_OF_FILE_INFO but not
-                        * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
-                        * The level is known here, so pass it down
-                        * appropriately.
-                        */
-                       bool should_fail =
-                           (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
-
-                       status = smb_set_file_end_of_file_info(conn, req,
-                                                               pdata,
-                                                               total_data,
-                                                               fsp,
-                                                               smb_fname,
-                                                               should_fail);
-                       break;
-               }
-
-               case SMB_FILE_DISPOSITION_INFORMATION:
-               case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
-               {
-#if 0
-                       /* JRA - We used to just ignore this on a path ? 
-                        * Shouldn't this be invalid level on a pathname
-                        * based call ?
-                        */
-                       if (tran_call != TRANSACT2_SETFILEINFO) {
-                               return ERROR_NT(NT_STATUS_INVALID_LEVEL);
-                       }
-#endif
-                       status = smb_set_file_disposition_info(conn,
-                                               pdata,
-                                               total_data,
-                                               fsp,
-                                               smb_fname);
-                       break;
-               }
-
-               case SMB_FILE_POSITION_INFORMATION:
-               {
-                       status = smb_file_position_information(conn,
-                                               pdata,
-                                               total_data,
-                                               fsp);
-                       break;
-               }
-
-               case SMB_FILE_FULL_EA_INFORMATION:
-               {
-                       status = smb_set_file_full_ea_info(conn,
-                                               pdata,
-                                               total_data,
-                                               fsp);
-                       break;
-               }
-
-               /* From tridge Samba4 : 
-                * MODE_INFORMATION in setfileinfo (I have no
-                * idea what "mode information" on a file is - it takes a value of 0,
-                * 2, 4 or 6. What could it be?).
-                */
-
-               case SMB_FILE_MODE_INFORMATION:
-               {
-                       status = smb_file_mode_information(conn,
-                                               pdata,
-                                               total_data);
-                       break;
-               }
-
-               /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
-               case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
-               case SMB_FILE_SHORT_NAME_INFORMATION:
-                       return NT_STATUS_NOT_SUPPORTED;
-
-               case SMB_FILE_RENAME_INFORMATION:
-               {
-                       status = smb_file_rename_information(conn, req,
-                                                            pdata, total_data,
-                                                            fsp, smb_fname);
-                       break;
-               }
-
-               case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
-               {
-                       /* SMB2 rename information. */
-                       status = smb2_file_rename_information(conn, req,
-                                                            pdata, total_data,
-                                                            fsp, smb_fname);
-                       break;
-               }
-
-               case SMB_FILE_LINK_INFORMATION:
-               {
-                       status = smb_file_link_information(conn, req,
-                                                       pdata, total_data,
-                                                       fsp, smb_fname);
-                       break;
-               }
-
-               default:
-                       return NT_STATUS_INVALID_LEVEL;
-       }
-
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
-
-       *ret_data_size = data_return_size;
-       return NT_STATUS_OK;
-}
-
-/****************************************************************************
- Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
-****************************************************************************/
-
-static void call_trans2setfilepathinfo(connection_struct *conn,
-                                      struct smb_request *req,
-                                      unsigned int tran_call,
-                                      char **pparams, int total_params,
-                                      char **ppdata, int total_data,
-                                      unsigned int max_data_bytes)
-{
-       char *params = *pparams;
-       char *pdata = *ppdata;
-       uint16_t info_level;
-       struct smb_filename *smb_fname = NULL;
-       files_struct *fsp = NULL;
-       NTSTATUS status = NT_STATUS_OK;
-       int data_return_size = 0;
-       int ret;
-
-       if (!params) {
-               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-               return;
-       }
-
-       if (tran_call == TRANSACT2_SETFILEINFO) {
-               if (total_params < 4) {
-                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-                       return;
-               }
-
-               fsp = file_fsp(req, SVAL(params,0));
-               /* Basic check for non-null fsp. */
-               if (!check_fsp_open(conn, req, fsp)) {
-                       return;
-               }
-               info_level = SVAL(params,2);
-
-               if (INFO_LEVEL_IS_UNIX(info_level)) {
-                       if (!lp_smb1_unix_extensions()) {
-                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
-                               return;
-                       }
-                       if (!req->posix_pathnames) {
-                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
-                               return;
-                       }
-               }
-
-               smb_fname = fsp->fsp_name;
-
-               if (fsp_get_pathref_fd(fsp) == -1) {
-                       /*
-                        * This is actually a SETFILEINFO on a directory
-                        * handle (returned from an NT SMB). NT5.0 seems
-                        * to do this call. JRA.
-                        */
-                       ret = vfs_stat(conn, smb_fname);
-                       if (ret != 0) {
-                               DBG_NOTICE("vfs_stat of %s failed (%s)\n",
-                                       smb_fname_str_dbg(smb_fname),
-                                       strerror(errno));
-                               reply_nterror(req,
-                                       map_nt_error_from_unix(errno));
-                               return;
-                       }
-               } else if (fsp->print_file) {
-                       /*
-                        * Doing a DELETE_ON_CLOSE should cancel a print job.
-                        */
-                       if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
-                               uint32_t new_private_options =
-                                       fh_get_private_options(fsp->fh);
-                               new_private_options |=
-                                       NTCREATEX_FLAG_DELETE_ON_CLOSE;
-                               fh_set_private_options(fsp->fh,
-                                                      new_private_options);
-
-                               DEBUG(3,("call_trans2setfilepathinfo: "
-                                        "Cancelling print job (%s)\n",
-                                        fsp_str_dbg(fsp)));
-
-                               SSVAL(params,0,0);
-                               send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
-                                                   *ppdata, 0,
-                                                   max_data_bytes);
-                               return;
-                       } else {
-                               reply_nterror(req,
-                                       NT_STATUS_OBJECT_PATH_NOT_FOUND);
-                               return;
-                       }
-               } else {
-                       /*
-                        * Original code - this is an open file.
-                        */
-                       status = vfs_stat_fsp(fsp);
-                       if (!NT_STATUS_IS_OK(status)) {
-                               DEBUG(3,("call_trans2setfilepathinfo: fstat "
-                                        "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
-                                        nt_errstr(status)));
-                               reply_nterror(req, status);
-                               return;
-                       }
+                               /* Cannot get here. */
+                               smb_panic("smb_posix_open: logic error");
+                               return NT_STATUS_INVALID_PARAMETER;
                }
-       } else {
-               char *fname = NULL;
-               uint32_t ucf_flags = ucf_flags_from_smb_request(req);
-               bool require_existing_object = true;
+       }
 
-               /* set path info */
-               if (total_params < 7) {
-                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-                       return;
-               }
+       raw_unixmode = IVAL(pdata,8);
+       /* Next 4 bytes are not yet defined. */
 
-               info_level = SVAL(params,0);
+       status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
+                                     (VALID_STAT(smb_fname->st) ?
+                                         PERM_EXISTING_FILE : PERM_NEW_FILE),
+                                     &unixmode);
 
-               if (INFO_LEVEL_IS_UNIX(info_level)) {
-                       if (!lp_smb1_unix_extensions()) {
-                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
-                               return;
-                       }
-                       if (!req->posix_pathnames) {
-                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
-                               return;
-                       }
-               }
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
 
-               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;
-               }
+       status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
+       if (!NT_STATUS_IS_OK(status)) {
+               DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
+                           nt_errstr(status));
+               return status;
+       }
 
-               status = filename_convert(req, conn,
-                                        fname,
-                                        ucf_flags,
-                                        0,
-                                        &smb_fname);
-               if (!NT_STATUS_IS_OK(status)) {
-                       if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
-                               reply_botherror(req,
-                                               NT_STATUS_PATH_NOT_COVERED,
-                                               ERRSRV, ERRbadpath);
-                               return;
-                       }
-                       reply_nterror(req, status);
-                       return;
+       if (wire_open_mode & SMB_O_SYNC) {
+               create_options |= FILE_WRITE_THROUGH;
+       }
+       if (wire_open_mode & SMB_O_APPEND) {
+               access_mask |= FILE_APPEND_DATA;
+       }
+       if (wire_open_mode & SMB_O_DIRECT) {
+               attributes |= FILE_FLAG_NO_BUFFERING;
+       }
+
+       if ((wire_open_mode & SMB_O_DIRECTORY) ||
+                       VALID_STAT_OF_DIR(smb_fname->st)) {
+               if (access_mask != SMB_O_RDONLY_MAPPING) {
+                       return NT_STATUS_FILE_IS_A_DIRECTORY;
                }
+               create_options &= ~FILE_NON_DIRECTORY_FILE;
+               create_options |= FILE_DIRECTORY_FILE;
+       }
 
-               /*
-                * smb_fname->fsp may be NULL if smb_fname points at a symlink
-                * and we're in POSIX context, so be careful when using fsp
-                * below, it can still be NULL.
-                */
-               fsp = smb_fname->fsp;
+       DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
+               smb_fname_str_dbg(smb_fname),
+               (unsigned int)wire_open_mode,
+               (unsigned int)unixmode ));
 
-               /*
-                * There are 4 info levels which can
-                * create a new object in the filesystem.
-                * They are:
-                * SMB_SET_FILE_UNIX_LINK -> creates POSIX symlink.
-                * SMB_POSIX_PATH_OPEN -> creates POSIX file or directory.
-                * SMB_SET_FILE_UNIX_BASIC:
-                * SMB_SET_FILE_UNIX_INFO2: can create a POSIX special file.
-                *
-                * These info levels do not require an existing object.
-                */
-               switch (info_level) {
-               case SMB_SET_FILE_UNIX_LINK:
-               case SMB_POSIX_PATH_OPEN:
-               case SMB_SET_FILE_UNIX_BASIC:
-               case SMB_SET_FILE_UNIX_INFO2:
-                       require_existing_object = false;
-                       break;
-               default:
-                       break;
-               }
+        status = SMB_VFS_CREATE_FILE(
+               conn,                                   /* conn */
+               req,                                    /* req */
+               smb_fname,                              /* fname */
+               access_mask,                            /* access_mask */
+               (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
+                   FILE_SHARE_DELETE),
+               create_disp,                            /* create_disposition*/
+               create_options,                         /* create_options */
+               attributes,                             /* file_attributes */
+               oplock_request,                         /* oplock_request */
+               NULL,                                   /* lease */
+               0,                                      /* allocation_size */
+               0,                                      /* private_flags */
+               NULL,                                   /* sd */
+               NULL,                                   /* ea_list */
+               &fsp,                                   /* result */
+               &info,                                  /* pinfo */
+               posx,                                   /* in_context_blobs */
+               NULL);                                  /* out_context_blobs */
 
-               if (!VALID_STAT(smb_fname->st) && require_existing_object) {
-                       reply_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
-               }
+       TALLOC_FREE(posx);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
 
-       DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
-                "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
-                fsp_fnum_dbg(fsp),
-                info_level,total_data));
+       if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
+               extended_oplock_granted = True;
+       }
 
-       /* Realloc the parameter size */
-       *pparams = (char *)SMB_REALLOC(*pparams,2);
-       if (*pparams == NULL) {
-               reply_nterror(req, NT_STATUS_NO_MEMORY);
-               return;
+       if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
+               extended_oplock_granted = True;
        }
-       params = *pparams;
 
-       SSVAL(params,0,0);
+       info_level_return = SVAL(pdata,16);
+       /* Allocate the correct return size. */
 
-       status = smbd_do_setfilepathinfo(conn, req, req,
-                                        info_level,
-                                        fsp,
-                                        smb_fname,
-                                        ppdata, total_data,
-                                        &data_return_size);
-       if (!NT_STATUS_IS_OK(status)) {
-               if (open_was_deferred(req->xconn, req->mid)) {
-                       /* We have re-scheduled this call. */
-                       return;
-               }
-               if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
-                       bool ok = defer_smb1_sharing_violation(req);
-                       if (ok) {
-                               return;
-                       }
-               }
-               if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
-                       /* We have re-scheduled this call. */
-                       return;
-               }
-               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
-                       reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
-                                       ERRSRV, ERRbadpath);
-                       return;
-               }
-               if (info_level == SMB_POSIX_PATH_OPEN) {
-                       reply_openerror(req, status);
-                       return;
-               }
+       if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
+               *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
+       } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
+               *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
+       } else {
+               *pdata_return_size = 12;
+       }
 
-               /*
-                * Invalid EA name needs to return 2 param bytes,
-                * not a zero-length error packet.
-                */
-               if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
-                       send_trans2_replies(conn, req, status, params, 2, NULL, 0,
-                                       max_data_bytes);
+       /* Realloc the data size */
+       *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
+       if (*ppdata == NULL) {
+               close_file_free(req, &fsp, ERROR_CLOSE);
+               *pdata_return_size = 0;
+               return NT_STATUS_NO_MEMORY;
+       }
+       pdata = *ppdata;
+
+       if (extended_oplock_granted) {
+               if (flags & REQUEST_BATCH_OPLOCK) {
+                       SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
                } else {
-                       reply_nterror(req, status);
+                       SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
                }
-               return;
+       } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
+               SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
+       } else {
+               SSVAL(pdata,0,NO_OPLOCK_RETURN);
        }
 
-       send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
-                           max_data_bytes);
+       SSVAL(pdata,2,fsp->fnum);
+       SIVAL(pdata,4,info); /* Was file created etc. */
 
-       return;
+       switch (info_level_return) {
+               case SMB_QUERY_FILE_UNIX_BASIC:
+                       SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
+                       SSVAL(pdata,10,0); /* padding. */
+                       store_file_unix_basic(conn, pdata + 12, fsp,
+                                             &smb_fname->st);
+                       break;
+               case SMB_QUERY_FILE_UNIX_INFO2:
+                       SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
+                       SSVAL(pdata,10,0); /* padding. */
+                       store_file_unix_basic_info2(conn, pdata + 12, fsp,
+                                                   &smb_fname->st);
+                       break;
+               default:
+                       SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
+                       SSVAL(pdata,10,0); /* padding. */
+                       break;
+       }
+       return NT_STATUS_OK;
 }
 
 /****************************************************************************
Reply to a TRANS2_MKDIR (make directory with extended attributes).
Delete a file with POSIX semantics.
 ****************************************************************************/
 
-static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
-                            char **pparams, int total_params,
-                            char **ppdata, int total_data,
-                            unsigned int max_data_bytes)
+static NTSTATUS smb_posix_unlink(connection_struct *conn,
+                                struct smb_request *req,
+                               const char *pdata,
+                               int total_data,
+                               struct smb_filename *smb_fname)
 {
-       struct files_struct *fsp = NULL;
-       struct smb_filename *smb_dname = NULL;
-       char *params = *pparams;
-       char *pdata = *ppdata;
-       char *directory = NULL;
        NTSTATUS status = NT_STATUS_OK;
-       struct ea_list *ea_list = NULL;
-       uint32_t ucf_flags = ucf_flags_from_smb_request(req);
-       TALLOC_CTX *ctx = talloc_tos();
+       files_struct *fsp = NULL;
+       uint16_t flags = 0;
+       char del = 1;
+       int info = 0;
+       int create_options = 0;
+       struct share_mode_lock *lck = NULL;
+       bool other_nonposix_opens;
+       struct smb2_create_blobs *posx = NULL;
 
-       if (!CAN_WRITE(conn)) {
-               reply_nterror(req, NT_STATUS_ACCESS_DENIED);
-               return;
+       if (total_data < 2) {
+               return NT_STATUS_INVALID_PARAMETER;
        }
 
-       if (total_params < 5) {
-               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-               return;
-       }
+       flags = SVAL(pdata,0);
 
-       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 (!VALID_STAT(smb_fname->st)) {
+               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
        }
-       if (!NT_STATUS_IS_OK(status)) {
-               reply_nterror(req, status);
-               return;
+
+       if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
+                       !VALID_STAT_OF_DIR(smb_fname->st)) {
+               return NT_STATUS_NOT_A_DIRECTORY;
        }
 
-       DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
+       DEBUG(10,("smb_posix_unlink: %s %s\n",
+               (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
+               smb_fname_str_dbg(smb_fname)));
 
-       status = filename_convert(ctx,
-                               conn,
-                               directory,
-                               ucf_flags,
-                               0,
-                               &smb_dname);
+       if (VALID_STAT_OF_DIR(smb_fname->st)) {
+               create_options |= FILE_DIRECTORY_FILE;
+       }
 
+       status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
        if (!NT_STATUS_IS_OK(status)) {
-               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
-                       reply_botherror(req,
-                               NT_STATUS_PATH_NOT_COVERED,
-                               ERRSRV, ERRbadpath);
-                       return;
-               }
-               reply_nterror(req, status);
-               return;
-        }
-
-       /*
-        * OS/2 workplace shell seems to send SET_EA requests of "null"
-        * length (4 bytes containing IVAL 4).
-        * They seem to have no effect. Bug #3212. JRA.
-        */
-
-       if (total_data && (total_data != 4)) {
-               /* Any data in this call is an EA list. */
-               if (total_data < 10) {
-                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-                       goto out;
-               }
-
-               if (IVAL(pdata,0) > total_data) {
-                       DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
-                               IVAL(pdata,0), (unsigned int)total_data));
-                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-                       goto out;
-               }
-
-               ea_list = read_ea_list(talloc_tos(), pdata + 4,
-                                      total_data - 4);
-               if (!ea_list) {
-                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-                       goto out;
-               }
-
-               if (!lp_ea_support(SNUM(conn))) {
-                       reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
-                       goto out;
-               }
+               DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
+                           nt_errstr(status));
+               return status;
        }
-       /* If total_data == 4 Windows doesn't care what values
-        * are placed in that field, it just ignores them.
-        * The System i QNTC IBM SMB client puts bad values here,
-        * so ignore them. */
 
-       status = SMB_VFS_CREATE_FILE(
+        status = SMB_VFS_CREATE_FILE(
                conn,                                   /* conn */
                req,                                    /* req */
-               smb_dname,                              /* fname */
-               MAXIMUM_ALLOWED_ACCESS,                 /* access_mask */
-               FILE_SHARE_NONE,                        /* share_access */
-               FILE_CREATE,                            /* create_disposition*/
-               FILE_DIRECTORY_FILE,                    /* create_options */
-               FILE_ATTRIBUTE_DIRECTORY,               /* file_attributes */
+               smb_fname,                              /* fname */
+               DELETE_ACCESS,                          /* access_mask */
+               (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
+                   FILE_SHARE_DELETE),
+               FILE_OPEN,                              /* create_disposition*/
+               create_options,                         /* create_options */
+               0,                                      /* file_attributes */
                0,                                      /* oplock_request */
                NULL,                                   /* lease */
                0,                                      /* allocation_size */
@@ -9247,239 +6557,394 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
                NULL,                                   /* sd */
                NULL,                                   /* ea_list */
                &fsp,                                   /* result */
-               NULL,                                   /* pinfo */
-               NULL, NULL);                            /* create context */
+               &info,                                  /* pinfo */
+               posx,                                   /* in_context_blobs */
+               NULL);                                  /* out_context_blobs */
+
+       TALLOC_FREE(posx);
+
        if (!NT_STATUS_IS_OK(status)) {
-               reply_nterror(req, status);
-               goto out;
+               return status;
        }
 
-       /* Try and set any given EA. */
-       if (ea_list) {
-               status = set_ea(conn, fsp, ea_list);
-               if (!NT_STATUS_IS_OK(status)) {
-                       reply_nterror(req, status);
-                       goto out;
-               }
+       /*
+        * Don't lie to client. If we can't really delete due to
+        * non-POSIX opens return SHARING_VIOLATION.
+        */
+
+       lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
+       if (lck == NULL) {
+               DEBUG(0, ("smb_posix_unlink: Could not get share mode "
+                         "lock for file %s\n", fsp_str_dbg(fsp)));
+               close_file_free(req, &fsp, NORMAL_CLOSE);
+               return NT_STATUS_INVALID_PARAMETER;
        }
 
-       /* Realloc the parameter and data sizes */
-       *pparams = (char *)SMB_REALLOC(*pparams,2);
-       if(*pparams == NULL) {
-               reply_nterror(req, NT_STATUS_NO_MEMORY);
-               goto out;
+       other_nonposix_opens = has_other_nonposix_opens(lck, fsp);
+       if (other_nonposix_opens) {
+               /* Fail with sharing violation. */
+               TALLOC_FREE(lck);
+               close_file_free(req, &fsp, NORMAL_CLOSE);
+               return NT_STATUS_SHARING_VIOLATION;
        }
-       params = *pparams;
 
-       SSVAL(params,0,0);
+       /*
+        * Set the delete on close.
+        */
+       status = smb_set_file_disposition_info(conn,
+                                               &del,
+                                               1,
+                                               fsp,
+                                               smb_fname);
 
-       send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
+       TALLOC_FREE(lck);
 
- out:
-       if (fsp != NULL) {
-               close_file_free(NULL, &fsp, NORMAL_CLOSE);
+       if (!NT_STATUS_IS_OK(status)) {
+               close_file_free(req, &fsp, NORMAL_CLOSE);
+               return status;
        }
-       TALLOC_FREE(smb_dname);
-       return;
+       return close_file_free(req, &fsp, NORMAL_CLOSE);
 }
 
-/****************************************************************************
- Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
- We don't actually do this - we just send a null response.
-****************************************************************************/
-
-static void call_trans2findnotifyfirst(connection_struct *conn,
-                                      struct smb_request *req,
-                                      char **pparams, int total_params,
-                                      char **ppdata, int total_data,
-                                      unsigned int max_data_bytes)
+static NTSTATUS smbd_do_posix_setfilepathinfo(struct connection_struct *conn,
+                                             struct smb_request *req,
+                                             TALLOC_CTX *mem_ctx,
+                                             uint16_t info_level,
+                                             struct smb_filename *smb_fname,
+                                             files_struct *fsp,
+                                             char **ppdata,
+                                             int total_data,
+                                             int *ret_data_size)
 {
-       char *params = *pparams;
-       uint16_t info_level;
+       char *pdata = *ppdata;
+       NTSTATUS status = NT_STATUS_OK;
+       int data_return_size = 0;
 
-       if (total_params < 6) {
-               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-               return;
+       *ret_data_size = 0;
+
+       if (!CAN_WRITE(conn)) {
+               /* Allow POSIX opens. The open path will deny
+                * any non-readonly opens. */
+               if (info_level != SMB_POSIX_PATH_OPEN) {
+                       return NT_STATUS_DOS(ERRSRV, ERRaccess);
+               }
        }
 
-       info_level = SVAL(params,4);
-       DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
+       DBG_DEBUG("file=%s (%s) info_level=%d totdata=%d\n",
+                 smb_fname_str_dbg(smb_fname),
+                 fsp_fnum_dbg(fsp),
+                 info_level,
+                 total_data);
 
        switch (info_level) {
-               case 1:
-               case 2:
+               case SMB_SET_FILE_UNIX_BASIC:
+               {
+                       status = smb_set_file_unix_basic(conn, req,
+                                                       pdata,
+                                                       total_data,
+                                                       fsp,
+                                                       smb_fname);
                        break;
-               default:
-                       reply_nterror(req, NT_STATUS_INVALID_LEVEL);
-                       return;
-       }
+               }
 
-       /* Realloc the parameter and data sizes */
-       *pparams = (char *)SMB_REALLOC(*pparams,6);
-       if (*pparams == NULL) {
-               reply_nterror(req, NT_STATUS_NO_MEMORY);
-               return;
-       }
-       params = *pparams;
+               case SMB_SET_FILE_UNIX_INFO2:
+               {
+                       status = smb_set_file_unix_info2(conn, req,
+                                                       pdata,
+                                                       total_data,
+                                                       fsp,
+                                                       smb_fname);
+                       break;
+               }
 
-       SSVAL(params,0,fnf_handle);
-       SSVAL(params,2,0); /* No changes */
-       SSVAL(params,4,0); /* No EA errors */
+               case SMB_SET_FILE_UNIX_LINK:
+               {
+                       if (smb_fname == NULL) {
+                               /* We must have a pathname for this. */
+                               return NT_STATUS_INVALID_LEVEL;
+                       }
+                       status = smb_set_file_unix_link(conn, req, pdata,
+                                                       total_data, smb_fname);
+                       break;
+               }
 
-       fnf_handle++;
+               case SMB_SET_FILE_UNIX_HLINK:
+               {
+                       if (smb_fname == NULL) {
+                               /* We must have a pathname for this. */
+                               return NT_STATUS_INVALID_LEVEL;
+                       }
+                       status = smb_set_file_unix_hlink(conn, req,
+                                                        pdata, total_data,
+                                                        smb_fname);
+                       break;
+               }
 
-       if(fnf_handle == 0)
-               fnf_handle = 257;
+#if defined(HAVE_POSIX_ACLS)
+               case SMB_SET_POSIX_ACL:
+               {
+                       status = smb_set_posix_acl(conn,
+                                               req,
+                                               pdata,
+                                               total_data,
+                                               fsp,
+                                               smb_fname);
+                       break;
+               }
+#endif
 
-       send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
+               case SMB_SET_POSIX_LOCK:
+               {
+                       if (fsp == NULL) {
+                               return NT_STATUS_INVALID_LEVEL;
+                       }
+                       status = smb_set_posix_lock(conn, req,
+                                                   pdata, total_data, fsp);
+                       break;
+               }
 
-       return;
-}
+               case SMB_POSIX_PATH_OPEN:
+               {
+                       if (smb_fname == NULL) {
+                               /* We must have a pathname for this. */
+                               return NT_STATUS_INVALID_LEVEL;
+                       }
 
-/****************************************************************************
- Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
- changes). Currently this does nothing.
-****************************************************************************/
+                       status = smb_posix_open(conn, req,
+                                               ppdata,
+                                               total_data,
+                                               smb_fname,
+                                               &data_return_size);
+                       break;
+               }
 
-static void call_trans2findnotifynext(connection_struct *conn,
-                                     struct smb_request *req,
-                                     char **pparams, int total_params,
-                                     char **ppdata, int total_data,
-                                     unsigned int max_data_bytes)
-{
-       char *params = *pparams;
+               case SMB_POSIX_PATH_UNLINK:
+               {
+                       if (smb_fname == NULL) {
+                               /* We must have a pathname for this. */
+                               return NT_STATUS_INVALID_LEVEL;
+                       }
 
-       DEBUG(3,("call_trans2findnotifynext\n"));
+                       status = smb_posix_unlink(conn, req,
+                                               pdata,
+                                               total_data,
+                                               smb_fname);
+                       break;
+               }
 
-       /* Realloc the parameter and data sizes */
-       *pparams = (char *)SMB_REALLOC(*pparams,4);
-       if (*pparams == NULL) {
-               reply_nterror(req, NT_STATUS_NO_MEMORY);
-               return;
+               default:
+                       return NT_STATUS_INVALID_LEVEL;
        }
-       params = *pparams;
-
-       SSVAL(params,0,0); /* No changes */
-       SSVAL(params,2,0); /* No EA errors */
 
-       send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
 
-       return;
+       *ret_data_size = data_return_size;
+       return NT_STATUS_OK;
 }
 
-/****************************************************************************
- Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
-****************************************************************************/
-
-static void call_trans2getdfsreferral(connection_struct *conn,
-                                     struct smb_request *req,
-                                     char **pparams, int total_params,
-                                     char **ppdata, int total_data,
-                                     unsigned int max_data_bytes)
+NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
+                               struct smb_request *req,
+                               TALLOC_CTX *mem_ctx,
+                               uint16_t info_level,
+                               files_struct *fsp,
+                               struct smb_filename *smb_fname,
+                               char **ppdata, int total_data,
+                               int *ret_data_size)
 {
-       char *params = *pparams;
-       char *pathname = NULL;
-       int reply_size = 0;
-       int max_referral_level;
+       char *pdata = *ppdata;
        NTSTATUS status = NT_STATUS_OK;
-       TALLOC_CTX *ctx = talloc_tos();
-
-       DEBUG(10,("call_trans2getdfsreferral\n"));
+       int data_return_size = 0;
 
-       if (total_params < 3) {
-               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-               return;
+       if (INFO_LEVEL_IS_UNIX(info_level)) {
+               if (!lp_smb1_unix_extensions()) {
+                       return NT_STATUS_INVALID_LEVEL;
+               }
+               if (!req->posix_pathnames) {
+                       return NT_STATUS_INVALID_LEVEL;
+               }
+               status = smbd_do_posix_setfilepathinfo(conn,
+                                                      req,
+                                                      req,
+                                                      info_level,
+                                                      smb_fname,
+                                                      fsp,
+                                                      ppdata,
+                                                      total_data,
+                                                      &data_return_size);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+               *ret_data_size = data_return_size;
+               return NT_STATUS_OK;
        }
 
-       max_referral_level = SVAL(params,0);
+       *ret_data_size = 0;
 
-       if(!lp_host_msdfs()) {
-               reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
-               return;
-       }
+       DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
+                "totdata=%d\n", smb_fname_str_dbg(smb_fname),
+                fsp_fnum_dbg(fsp),
+                info_level, total_data));
 
-       srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
-                   total_params - 2, STR_TERMINATE);
-       if (!pathname) {
-               reply_nterror(req, NT_STATUS_NOT_FOUND);
-               return;
-       }
-       if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
-                                           ppdata,&status)) < 0) {
-               reply_nterror(req, status);
-               return;
-       }
+       switch (info_level) {
+
+               case SMB_INFO_STANDARD:
+               {
+                       status = smb_set_info_standard(conn,
+                                       pdata,
+                                       total_data,
+                                       fsp,
+                                       smb_fname);
+                       break;
+               }
+
+               case SMB_INFO_SET_EA:
+               {
+                       status = smb_info_set_ea(conn,
+                                               pdata,
+                                               total_data,
+                                               fsp,
+                                               smb_fname);
+                       break;
+               }
+
+               case SMB_SET_FILE_BASIC_INFO:
+               case SMB_FILE_BASIC_INFORMATION:
+               {
+                       status = smb_set_file_basic_info(conn,
+                                                       pdata,
+                                                       total_data,
+                                                       fsp,
+                                                       smb_fname);
+                       break;
+               }
 
-       SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
-             SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
-       send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
+               case SMB_FILE_ALLOCATION_INFORMATION:
+               case SMB_SET_FILE_ALLOCATION_INFO:
+               {
+                       status = smb_set_file_allocation_info(conn, req,
+                                                               pdata,
+                                                               total_data,
+                                                               fsp,
+                                                               smb_fname);
+                       break;
+               }
 
-       return;
-}
+               case SMB_FILE_END_OF_FILE_INFORMATION:
+               case SMB_SET_FILE_END_OF_FILE_INFO:
+               {
+                       /*
+                        * XP/Win7 both fail after the createfile with
+                        * SMB_SET_FILE_END_OF_FILE_INFO but not
+                        * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
+                        * The level is known here, so pass it down
+                        * appropriately.
+                        */
+                       bool should_fail =
+                           (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
 
-#define LMCAT_SPL       0x53
-#define LMFUNC_GETJOBID 0x60
+                       status = smb_set_file_end_of_file_info(conn, req,
+                                                               pdata,
+                                                               total_data,
+                                                               fsp,
+                                                               smb_fname,
+                                                               should_fail);
+                       break;
+               }
 
-/****************************************************************************
- Reply to a TRANS2_IOCTL - used for OS/2 printing.
-****************************************************************************/
+               case SMB_FILE_DISPOSITION_INFORMATION:
+               case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
+               {
+#if 0
+                       /* JRA - We used to just ignore this on a path ? 
+                        * Shouldn't this be invalid level on a pathname
+                        * based call ?
+                        */
+                       if (tran_call != TRANSACT2_SETFILEINFO) {
+                               return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+                       }
+#endif
+                       status = smb_set_file_disposition_info(conn,
+                                               pdata,
+                                               total_data,
+                                               fsp,
+                                               smb_fname);
+                       break;
+               }
 
-static void call_trans2ioctl(connection_struct *conn,
-                            struct smb_request *req,
-                            char **pparams, int total_params,
-                            char **ppdata, int total_data,
-                            unsigned int max_data_bytes)
-{
-       const struct loadparm_substitution *lp_sub =
-               loadparm_s3_global_substitution();
-       char *pdata = *ppdata;
-       files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
-       NTSTATUS status;
-       size_t len = 0;
+               case SMB_FILE_POSITION_INFORMATION:
+               {
+                       status = smb_file_position_information(conn,
+                                               pdata,
+                                               total_data,
+                                               fsp);
+                       break;
+               }
 
-       /* check for an invalid fid before proceeding */
+               case SMB_FILE_FULL_EA_INFORMATION:
+               {
+                       status = smb_set_file_full_ea_info(conn,
+                                               pdata,
+                                               total_data,
+                                               fsp);
+                       break;
+               }
 
-       if (!fsp) {
-               reply_nterror(req, NT_STATUS_INVALID_HANDLE);
-               return;
-       }
+               /* From tridge Samba4 : 
+                * MODE_INFORMATION in setfileinfo (I have no
+                * idea what "mode information" on a file is - it takes a value of 0,
+                * 2, 4 or 6. What could it be?).
+                */
 
-       if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
-           && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
-               *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
-               if (*ppdata == NULL) {
-                       reply_nterror(req, NT_STATUS_NO_MEMORY);
-                       return;
+               case SMB_FILE_MODE_INFORMATION:
+               {
+                       status = smb_file_mode_information(conn,
+                                               pdata,
+                                               total_data);
+                       break;
                }
-               pdata = *ppdata;
 
-               /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
-                       CAN ACCEPT THIS IN UNICODE. JRA. */
+               /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
+               case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
+               case SMB_FILE_SHORT_NAME_INFORMATION:
+                       return NT_STATUS_NOT_SUPPORTED;
 
-               /* Job number */
-               SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
+               case SMB_FILE_RENAME_INFORMATION:
+               {
+                       status = smb_file_rename_information(conn, req,
+                                                            pdata, total_data,
+                                                            fsp, smb_fname);
+                       break;
+               }
 
-               status = srvstr_push(pdata, req->flags2, pdata + 2,
-                           lp_netbios_name(), 15,
-                           STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
-               if (!NT_STATUS_IS_OK(status)) {
-                       reply_nterror(req, status);
-                       return;
+               case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
+               {
+                       /* SMB2 rename information. */
+                       status = smb2_file_rename_information(conn, req,
+                                                            pdata, total_data,
+                                                            fsp, smb_fname);
+                       break;
                }
-               status = srvstr_push(pdata, req->flags2, pdata+18,
-                           lp_servicename(talloc_tos(), lp_sub, SNUM(conn)), 13,
-                           STR_ASCII|STR_TERMINATE, &len); /* Service name */
-               if (!NT_STATUS_IS_OK(status)) {
-                       reply_nterror(req, status);
-                       return;
+
+               case SMB_FILE_LINK_INFORMATION:
+               {
+                       status = smb_file_link_information(conn, req,
+                                                       pdata, total_data,
+                                                       fsp, smb_fname);
+                       break;
                }
-               send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
-                                   max_data_bytes);
-               return;
+
+               default:
+                       return NT_STATUS_INVALID_LEVEL;
+       }
+
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
 
-       DEBUG(2,("Unknown TRANS2_IOCTL\n"));
-       reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
+       *ret_data_size = data_return_size;
+       return NT_STATUS_OK;
 }
 
 /****************************************************************************
@@ -9558,358 +7023,6 @@ void reply_findnclose(struct smb_request *req)
        return;
 }
 
-static void handle_trans2(connection_struct *conn, struct smb_request *req,
-                         struct trans_state *state)
-{
-       if (get_Protocol() >= PROTOCOL_NT1) {
-               req->flags2 |= 0x40; /* IS_LONG_NAME */
-               SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
-       }
-
-       if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
-               if (state->call != TRANSACT2_QFSINFO &&
-                   state->call != TRANSACT2_SETFSINFO) {
-                       DEBUG(0,("handle_trans2: encryption required "
-                               "with call 0x%x\n",
-                               (unsigned int)state->call));
-                       reply_nterror(req, NT_STATUS_ACCESS_DENIED);
-                       return;
-               }
-       }
-
-       SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
-
-       /* Now we must call the relevant TRANS2 function */
-       switch(state->call)  {
-       case TRANSACT2_OPEN:
-       {
-               START_PROFILE(Trans2_open);
-               call_trans2open(conn, req,
-                               &state->param, state->total_param,
-                               &state->data, state->total_data,
-                               state->max_data_return);
-               END_PROFILE(Trans2_open);
-               break;
-       }
-
-       case TRANSACT2_FINDFIRST:
-       {
-               START_PROFILE(Trans2_findfirst);
-               call_trans2findfirst(conn, req,
-                                    &state->param, state->total_param,
-                                    &state->data, state->total_data,
-                                    state->max_data_return);
-               END_PROFILE(Trans2_findfirst);
-               break;
-       }
-
-       case TRANSACT2_FINDNEXT:
-       {
-               START_PROFILE(Trans2_findnext);
-               call_trans2findnext(conn, req,
-                                   &state->param, state->total_param,
-                                   &state->data, state->total_data,
-                                   state->max_data_return);
-               END_PROFILE(Trans2_findnext);
-               break;
-       }
-
-       case TRANSACT2_QFSINFO:
-       {
-               START_PROFILE(Trans2_qfsinfo);
-               call_trans2qfsinfo(conn, req,
-                                  &state->param, state->total_param,
-                                  &state->data, state->total_data,
-                                  state->max_data_return);
-               END_PROFILE(Trans2_qfsinfo);
-           break;
-       }
-
-       case TRANSACT2_SETFSINFO:
-       {
-               START_PROFILE(Trans2_setfsinfo);
-               call_trans2setfsinfo(conn, req,
-                                    &state->param, state->total_param,
-                                    &state->data, state->total_data,
-                                    state->max_data_return);
-               END_PROFILE(Trans2_setfsinfo);
-               break;
-       }
-
-       case TRANSACT2_QPATHINFO:
-       case TRANSACT2_QFILEINFO:
-       {
-               START_PROFILE(Trans2_qpathinfo);
-               call_trans2qfilepathinfo(conn, req, state->call,
-                                        &state->param, state->total_param,
-                                        &state->data, state->total_data,
-                                        state->max_data_return);
-               END_PROFILE(Trans2_qpathinfo);
-               break;
-       }
-
-       case TRANSACT2_SETPATHINFO:
-       case TRANSACT2_SETFILEINFO:
-       {
-               START_PROFILE(Trans2_setpathinfo);
-               call_trans2setfilepathinfo(conn, req, state->call,
-                                          &state->param, state->total_param,
-                                          &state->data, state->total_data,
-                                          state->max_data_return);
-               END_PROFILE(Trans2_setpathinfo);
-               break;
-       }
-
-       case TRANSACT2_FINDNOTIFYFIRST:
-       {
-               START_PROFILE(Trans2_findnotifyfirst);
-               call_trans2findnotifyfirst(conn, req,
-                                          &state->param, state->total_param,
-                                          &state->data, state->total_data,
-                                          state->max_data_return);
-               END_PROFILE(Trans2_findnotifyfirst);
-               break;
-       }
-
-       case TRANSACT2_FINDNOTIFYNEXT:
-       {
-               START_PROFILE(Trans2_findnotifynext);
-               call_trans2findnotifynext(conn, req,
-                                         &state->param, state->total_param,
-                                         &state->data, state->total_data,
-                                         state->max_data_return);
-               END_PROFILE(Trans2_findnotifynext);
-               break;
-       }
-
-       case TRANSACT2_MKDIR:
-       {
-               START_PROFILE(Trans2_mkdir);
-               call_trans2mkdir(conn, req,
-                                &state->param, state->total_param,
-                                &state->data, state->total_data,
-                                state->max_data_return);
-               END_PROFILE(Trans2_mkdir);
-               break;
-       }
-
-       case TRANSACT2_GET_DFS_REFERRAL:
-       {
-               START_PROFILE(Trans2_get_dfs_referral);
-               call_trans2getdfsreferral(conn, req,
-                                         &state->param, state->total_param,
-                                         &state->data, state->total_data,
-                                         state->max_data_return);
-               END_PROFILE(Trans2_get_dfs_referral);
-               break;
-       }
-
-       case TRANSACT2_IOCTL:
-       {
-               START_PROFILE(Trans2_ioctl);
-               call_trans2ioctl(conn, req,
-                                &state->param, state->total_param,
-                                &state->data, state->total_data,
-                                state->max_data_return);
-               END_PROFILE(Trans2_ioctl);
-               break;
-       }
-
-       default:
-               /* Error in request */
-               DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
-               reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
-       }
-}
-
-/****************************************************************************
- Reply to a SMBtrans2.
- ****************************************************************************/
-
-void reply_trans2(struct smb_request *req)
-{
-       connection_struct *conn = req->conn;
-       unsigned int dsoff;
-       unsigned int dscnt;
-       unsigned int psoff;
-       unsigned int pscnt;
-       unsigned int tran_call;
-       struct trans_state *state;
-       NTSTATUS result;
-
-       START_PROFILE(SMBtrans2);
-
-       if (req->wct < 14) {
-               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-               END_PROFILE(SMBtrans2);
-               return;
-       }
-
-       dsoff = SVAL(req->vwv+12, 0);
-       dscnt = SVAL(req->vwv+11, 0);
-       psoff = SVAL(req->vwv+10, 0);
-       pscnt = SVAL(req->vwv+9, 0);
-       tran_call = SVAL(req->vwv+14, 0);
-
-       result = allow_new_trans(conn->pending_trans, req->mid);
-       if (!NT_STATUS_IS_OK(result)) {
-               DEBUG(2, ("Got invalid trans2 request: %s\n",
-                         nt_errstr(result)));
-               reply_nterror(req, result);
-               END_PROFILE(SMBtrans2);
-               return;
-       }
-
-       if (IS_IPC(conn)) {
-               switch (tran_call) {
-               /* List the allowed trans2 calls on IPC$ */
-               case TRANSACT2_OPEN:
-               case TRANSACT2_GET_DFS_REFERRAL:
-               case TRANSACT2_QFILEINFO:
-               case TRANSACT2_QFSINFO:
-               case TRANSACT2_SETFSINFO:
-                       break;
-               default:
-                       reply_nterror(req, NT_STATUS_ACCESS_DENIED);
-                       END_PROFILE(SMBtrans2);
-                       return;
-               }
-       }
-
-       if ((state = talloc(conn, struct trans_state)) == NULL) {
-               DEBUG(0, ("talloc failed\n"));
-               reply_nterror(req, NT_STATUS_NO_MEMORY);
-               END_PROFILE(SMBtrans2);
-               return;
-       }
-
-       state->cmd = SMBtrans2;
-
-       state->mid = req->mid;
-       state->vuid = req->vuid;
-       state->setup_count = SVAL(req->vwv+13, 0);
-       state->setup = NULL;
-       state->total_param = SVAL(req->vwv+0, 0);
-       state->param = NULL;
-       state->total_data =  SVAL(req->vwv+1, 0);
-       state->data = NULL;
-       state->max_param_return = SVAL(req->vwv+2, 0);
-       state->max_data_return  = SVAL(req->vwv+3, 0);
-       state->max_setup_return = SVAL(req->vwv+4, 0);
-       state->close_on_completion = BITSETW(req->vwv+5, 0);
-       state->one_way = BITSETW(req->vwv+5, 1);
-
-       state->call = tran_call;
-
-       /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
-          is so as a sanity check */
-       if (state->setup_count != 1) {
-               /*
-                * Need to have rc=0 for ioctl to get job id for OS/2.
-                *  Network printing will fail if function is not successful.
-                *  Similar function in reply.c will be used if protocol
-                *  is LANMAN1.0 instead of LM1.2X002.
-                *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
-                *  outbuf doesn't have to be set(only job id is used).
-                */
-               if ( (state->setup_count == 4)
-                    && (tran_call == TRANSACT2_IOCTL)
-                    && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
-                    && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
-                       DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
-               } else {
-                       DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
-                       DEBUG(2,("Transaction is %d\n",tran_call));
-                       TALLOC_FREE(state);
-                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-                       END_PROFILE(SMBtrans2);
-                       return;
-               }
-       }
-
-       if ((dscnt > state->total_data) || (pscnt > state->total_param))
-               goto bad_param;
-
-       if (state->total_data) {
-
-               if (smb_buffer_oob(state->total_data, 0, dscnt)
-                   || smb_buffer_oob(smb_len(req->inbuf), dsoff, dscnt)) {
-                       goto bad_param;
-               }
-
-               /* Can't use talloc here, the core routines do realloc on the
-                * params and data. */
-               state->data = (char *)SMB_MALLOC(state->total_data);
-               if (state->data == NULL) {
-                       DEBUG(0,("reply_trans2: data malloc fail for %u "
-                                "bytes !\n", (unsigned int)state->total_data));
-                       TALLOC_FREE(state);
-                       reply_nterror(req, NT_STATUS_NO_MEMORY);
-                       END_PROFILE(SMBtrans2);
-                       return;
-               }
-
-               memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
-       }
-
-       if (state->total_param) {
-
-               if (smb_buffer_oob(state->total_param, 0, pscnt)
-                   || smb_buffer_oob(smb_len(req->inbuf), psoff, pscnt)) {
-                       goto bad_param;
-               }
-
-               /* Can't use talloc here, the core routines do realloc on the
-                * params and data. */
-               state->param = (char *)SMB_MALLOC(state->total_param);
-               if (state->param == NULL) {
-                       DEBUG(0,("reply_trans: param malloc fail for %u "
-                                "bytes !\n", (unsigned int)state->total_param));
-                       SAFE_FREE(state->data);
-                       TALLOC_FREE(state);
-                       reply_nterror(req, NT_STATUS_NO_MEMORY);
-                       END_PROFILE(SMBtrans2);
-                       return;
-               } 
-
-               memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
-       }
-
-       state->received_data  = dscnt;
-       state->received_param = pscnt;
-
-       if ((state->received_param == state->total_param) &&
-           (state->received_data == state->total_data)) {
-
-               handle_trans2(conn, req, state);
-
-               SAFE_FREE(state->data);
-               SAFE_FREE(state->param);
-               TALLOC_FREE(state);
-               END_PROFILE(SMBtrans2);
-               return;
-       }
-
-       DLIST_ADD(conn->pending_trans, state);
-
-       /* We need to send an interim response then receive the rest
-          of the parameter/data bytes */
-       reply_outbuf(req, 0, 0);
-       show_msg((char *)req->outbuf);
-       END_PROFILE(SMBtrans2);
-       return;
-
-  bad_param:
-
-       DEBUG(0,("reply_trans2: invalid trans parameters\n"));
-       SAFE_FREE(state->data);
-       SAFE_FREE(state->param);
-       TALLOC_FREE(state);
-       END_PROFILE(SMBtrans2);
-       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-}
-
-
 /****************************************************************************
  Reply to a SMBtranss2
  ****************************************************************************/