s3: smbd: Add dirfsp parameter to unlink_internals().
[samba.git] / source3 / smbd / smb1_reply.c
index 82da0257ba96958e016e52e7688383dc0879b138..dbdc910659c18b795a816076f062bda54407e567 100644 (file)
@@ -110,7 +110,7 @@ void reply_tcon(struct smb_request *req)
                return;
        }
 
-       reply_outbuf(req, 2, 0);
+       reply_smb1_outbuf(req, 2, 0);
        SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
        SSVAL(req->outbuf,smb_vwv1,conn->cnum);
        SSVAL(req->outbuf,smb_tid,conn->cnum);
@@ -359,7 +359,7 @@ void reply_tcon_and_X(struct smb_request *req)
                server_devicetype = "A:";
 
        if (get_Protocol() < PROTOCOL_NT1) {
-               reply_outbuf(req, 2, 0);
+               reply_smb1_outbuf(req, 2, 0);
                if (message_push_string(&req->outbuf, server_devicetype,
                                        STR_TERMINATE|STR_ASCII) == -1) {
                        reply_nterror(req, NT_STATUS_NO_MEMORY);
@@ -375,7 +375,7 @@ void reply_tcon_and_X(struct smb_request *req)
                        uint32_t perm1 = 0;
                        uint32_t perm2 = 0;
 
-                       reply_outbuf(req, 7, 0);
+                       reply_smb1_outbuf(req, 7, 0);
 
                        if (IS_IPC(conn)) {
                                perm1 = FILE_ALL_ACCESS;
@@ -387,7 +387,7 @@ void reply_tcon_and_X(struct smb_request *req)
                        SIVAL(req->outbuf, smb_vwv3, perm1);
                        SIVAL(req->outbuf, smb_vwv5, perm2);
                } else {
-                       reply_outbuf(req, 3, 0);
+                       reply_smb1_outbuf(req, 3, 0);
                }
 
                if ((message_push_string(&req->outbuf, server_devicetype,
@@ -481,7 +481,7 @@ void reply_ioctl(struct smb_request *req)
                    return;
        }
 
-       reply_outbuf(req, 8, replysize+1);
+       reply_smb1_outbuf(req, 8, replysize+1);
        SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
        SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
        SSVAL(req->outbuf,smb_vwv6,52);        /* Offset to data */
@@ -561,7 +561,9 @@ void reply_checkpath(struct smb_request *req)
        struct smb_filename *smb_fname = NULL;
        char *name = NULL;
        NTSTATUS status;
+       struct files_struct *dirfsp = NULL;
        uint32_t ucf_flags = ucf_flags_from_smb_request(req);
+       NTTIME twrp = 0;
        TALLOC_CTX *ctx = talloc_tos();
 
        START_PROFILE(SMBcheckpath);
@@ -578,13 +580,16 @@ void reply_checkpath(struct smb_request *req)
 
        DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
 
-       status = filename_convert(ctx,
-                               conn,
-                               name,
-                               ucf_flags,
-                               0,
-                               &smb_fname);
-
+       if (ucf_flags & UCF_GMT_PATHNAME) {
+               extract_snapshot_token(name, &twrp);
+       }
+       status = filename_convert_dirfsp(ctx,
+                                        conn,
+                                        name,
+                                        ucf_flags,
+                                        twrp,
+                                        &dirfsp,
+                                        &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,
@@ -609,7 +614,7 @@ void reply_checkpath(struct smb_request *req)
                goto out;
        }
 
-       reply_outbuf(req, 0, 0);
+       reply_smb1_outbuf(req, 0, 0);
 
  path_err:
        /* We special case this - as when a Windows machine
@@ -665,8 +670,10 @@ void reply_getatr(struct smb_request *req)
                goto out;
        }
 
-       /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
-               under WfWg - weird! */
+       /*
+        * dos sometimes asks for a stat of "" - it returns a "hidden
+        * directory" under WfWg - weird!
+        */
        if (*fname == '\0') {
                mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
                if (!CAN_WRITE(conn)) {
@@ -721,7 +728,7 @@ void reply_getatr(struct smb_request *req)
                }
        }
 
-       reply_outbuf(req, 10, 0);
+       reply_smb1_outbuf(req, 10, 0);
 
        SSVAL(req->outbuf,smb_vwv0,mode);
        if(lp_dos_filetime_resolution(SNUM(conn)) ) {
@@ -842,7 +849,7 @@ void reply_setatr(struct smb_request *req)
                goto out;
        }
 
-       reply_outbuf(req, 0, 0);
+       reply_smb1_outbuf(req, 0, 0);
 
        DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
                 mode));
@@ -898,7 +905,7 @@ void reply_dskattr(struct smb_request *req)
                }
        }
 
-       reply_outbuf(req, 5, 0);
+       reply_smb1_outbuf(req, 5, 0);
 
        if (get_Protocol() <= PROTOCOL_LANMAN2) {
                double total_space, free_space;
@@ -1034,7 +1041,7 @@ void reply_search(struct smb_request *req)
                expect_close = True;
        }
 
-       reply_outbuf(req, 1, 3);
+       reply_smb1_outbuf(req, 1, 3);
        maxentries = SVAL(req->vwv+0, 0);
        dirtype = SVAL(req->vwv+1, 0);
        p = (const char *)req->buf + 1;
@@ -1087,6 +1094,7 @@ void reply_search(struct smb_request *req)
                nt_status = SMB_VFS_CREATE_FILE(
                                conn, /* conn */
                                req, /* req */
+                               NULL, /* dirfsp */
                                smb_dname, /* dname */
                                FILE_LIST_DIRECTORY, /* access_mask */
                                FILE_SHARE_READ|
@@ -1382,7 +1390,7 @@ void reply_fclose(struct smb_request *req)
                dptr_num = -1;
        }
 
-       reply_outbuf(req, 1, 0);
+       reply_smb1_outbuf(req, 1, 0);
        SSVAL(req->outbuf,smb_vwv0,0);
 
        DEBUG(3,("search close\n"));
@@ -1404,6 +1412,7 @@ void reply_open(struct smb_request *req)
        off_t size = 0;
        time_t mtime=0;
        int info;
+       struct files_struct *dirfsp = NULL;
        files_struct *fsp;
        int oplock_request;
        int deny_mode;
@@ -1415,6 +1424,7 @@ void reply_open(struct smb_request *req)
        uint32_t private_flags = 0;
        NTSTATUS status;
        uint32_t ucf_flags;
+       NTTIME twrp = 0;
        TALLOC_CTX *ctx = talloc_tos();
 
        START_PROFILE(SMBopen);
@@ -1445,12 +1455,16 @@ void reply_open(struct smb_request *req)
 
        ucf_flags = filename_create_ucf_flags(req, create_disposition);
 
-       status = filename_convert(ctx,
-                               conn,
-                               fname,
-                               ucf_flags,
-                               0,
-                               &smb_fname);
+       if (ucf_flags & UCF_GMT_PATHNAME) {
+               extract_snapshot_token(fname, &twrp);
+       }
+       status = filename_convert_dirfsp(ctx,
+                                        conn,
+                                        fname,
+                                        ucf_flags,
+                                        twrp,
+                                        &dirfsp,
+                                        &smb_fname);
        if (!NT_STATUS_IS_OK(status)) {
                if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
                        reply_botherror(req,
@@ -1465,6 +1479,7 @@ void reply_open(struct smb_request *req)
        status = SMB_VFS_CREATE_FILE(
                conn,                                   /* conn */
                req,                                    /* req */
+               dirfsp,                                 /* dirfsp */
                smb_fname,                              /* fname */
                access_mask,                            /* access_mask */
                share_mode,                             /* share_access */
@@ -1526,7 +1541,7 @@ void reply_open(struct smb_request *req)
                goto out;
        }
 
-       reply_outbuf(req, 7, 0);
+       reply_smb1_outbuf(req, 7, 0);
        SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
        SSVAL(req->outbuf,smb_vwv1,fattr);
        if(lp_dos_filetime_resolution(SNUM(conn)) ) {
@@ -1576,6 +1591,7 @@ void reply_open_and_X(struct smb_request *req)
        uint32_t fattr=0;
        int mtime=0;
        int smb_action = 0;
+       struct files_struct *dirfsp = NULL;
        files_struct *fsp;
        NTSTATUS status;
        uint64_t allocation_size;
@@ -1586,6 +1602,7 @@ void reply_open_and_X(struct smb_request *req)
        uint32_t create_options = 0;
        uint32_t private_flags = 0;
        uint32_t ucf_flags;
+       NTTIME twrp = 0;
        TALLOC_CTX *ctx = talloc_tos();
 
        START_PROFILE(SMBopenX);
@@ -1634,12 +1651,17 @@ void reply_open_and_X(struct smb_request *req)
 
        ucf_flags = filename_create_ucf_flags(req, create_disposition);
 
-       status = filename_convert(ctx,
-                               conn,
-                               fname,
-                               ucf_flags,
-                               0,
-                               &smb_fname);
+       if (ucf_flags & UCF_GMT_PATHNAME) {
+               extract_snapshot_token(fname, &twrp);
+       }
+
+       status = filename_convert_dirfsp(ctx,
+                                        conn,
+                                        fname,
+                                        ucf_flags,
+                                        twrp,
+                                        &dirfsp,
+                                        &smb_fname);
        if (!NT_STATUS_IS_OK(status)) {
                if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
                        reply_botherror(req,
@@ -1654,6 +1676,7 @@ void reply_open_and_X(struct smb_request *req)
        status = SMB_VFS_CREATE_FILE(
                conn,                                   /* conn */
                req,                                    /* req */
+               dirfsp,                                 /* dirfsp */
                smb_fname,                              /* fname */
                access_mask,                            /* access_mask */
                share_mode,                             /* share_access */
@@ -1750,9 +1773,9 @@ void reply_open_and_X(struct smb_request *req)
        */
 
        if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
-               reply_outbuf(req, 19, 0);
+               reply_smb1_outbuf(req, 19, 0);
        } else {
-               reply_outbuf(req, 15, 0);
+               reply_smb1_outbuf(req, 15, 0);
        }
 
        SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
@@ -1990,7 +2013,7 @@ static void reply_ulogoffX_done(struct tevent_req *req)
 
        TALLOC_FREE(session);
 
-       reply_outbuf(smb1req, 2, 0);
+       reply_smb1_outbuf(smb1req, 2, 0);
        SSVAL(smb1req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
        SSVAL(smb1req->outbuf, smb_vwv1, 0);    /* no andx offset */
 
@@ -2018,6 +2041,7 @@ void reply_mknew(struct smb_request *req)
        char *fname = NULL;
        uint32_t fattr = 0;
        struct smb_file_time ft;
+       struct files_struct *dirfsp = NULL;
        files_struct *fsp;
        int oplock_request = 0;
        NTSTATUS status;
@@ -2026,6 +2050,7 @@ void reply_mknew(struct smb_request *req)
        uint32_t create_disposition;
        uint32_t create_options = 0;
        uint32_t ucf_flags;
+       NTTIME twrp = 0;
        TALLOC_CTX *ctx = talloc_tos();
 
        START_PROFILE(SMBcreate);
@@ -2058,12 +2083,17 @@ void reply_mknew(struct smb_request *req)
        }
 
        ucf_flags = filename_create_ucf_flags(req, create_disposition);
-       status = filename_convert(ctx,
-                               conn,
-                               fname,
-                               ucf_flags,
-                               0,
-                               &smb_fname);
+       if (ucf_flags & UCF_GMT_PATHNAME) {
+               extract_snapshot_token(fname, &twrp);
+       }
+
+       status = filename_convert_dirfsp(ctx,
+                                        conn,
+                                        fname,
+                                        ucf_flags,
+                                        twrp,
+                                        &dirfsp,
+                                        &smb_fname);
        if (!NT_STATUS_IS_OK(status)) {
                if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
                        reply_botherror(req,
@@ -2084,6 +2114,7 @@ void reply_mknew(struct smb_request *req)
        status = SMB_VFS_CREATE_FILE(
                conn,                                   /* conn */
                req,                                    /* req */
+               dirfsp,                                 /* dirfsp */
                smb_fname,                              /* fname */
                access_mask,                            /* access_mask */
                share_mode,                             /* share_access */
@@ -2122,7 +2153,7 @@ void reply_mknew(struct smb_request *req)
                goto out;
        }
 
-       reply_outbuf(req, 1, 0);
+       reply_smb1_outbuf(req, 1, 0);
        SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
 
        if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
@@ -2157,12 +2188,14 @@ void reply_ctemp(struct smb_request *req)
        char *wire_name = NULL;
        char *fname = NULL;
        uint32_t fattr;
+       struct files_struct *dirfsp = NULL;
        files_struct *fsp;
        int oplock_request;
        char *s;
        NTSTATUS status;
        int i;
        uint32_t ucf_flags;
+       NTTIME twrp = 0;
        TALLOC_CTX *ctx = talloc_tos();
 
        START_PROFILE(SMBctemp);
@@ -2200,11 +2233,16 @@ void reply_ctemp(struct smb_request *req)
                }
 
                ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
-               status = filename_convert(ctx, conn,
-                               fname,
-                               ucf_flags,
-                               0,
-                               &smb_fname);
+               if (ucf_flags & UCF_GMT_PATHNAME) {
+                       extract_snapshot_token(fname, &twrp);
+               }
+               status = filename_convert_dirfsp(ctx,
+                                                conn,
+                                                fname,
+                                                ucf_flags,
+                                                twrp,
+                                                &dirfsp,
+                                                &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,
@@ -2219,6 +2257,7 @@ void reply_ctemp(struct smb_request *req)
                status = SMB_VFS_CREATE_FILE(
                        conn,                                   /* conn */
                        req,                                    /* req */
+                       dirfsp,                                 /* dirfsp */
                        smb_fname,                              /* fname */
                        FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
                        FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
@@ -2237,6 +2276,7 @@ void reply_ctemp(struct smb_request *req)
 
                if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
                        TALLOC_FREE(fname);
+                       TALLOC_FREE(dirfsp);
                        TALLOC_FREE(smb_fname);
                        continue;
                }
@@ -2266,7 +2306,7 @@ void reply_ctemp(struct smb_request *req)
                goto out;
        }
 
-       reply_outbuf(req, 1, 0);
+       reply_smb1_outbuf(req, 1, 0);
        SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
 
        /* the returned filename is relative to the directory */
@@ -2355,7 +2395,7 @@ void reply_unlink(struct smb_request *req)
 
        DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
 
-       status = unlink_internals(conn, req, dirtype, smb_fname);
+       status = unlink_internals(conn, req, dirtype, NULL, smb_fname);
        if (!NT_STATUS_IS_OK(status)) {
                if (open_was_deferred(req->xconn, req->mid)) {
                        /* We have re-scheduled this call. */
@@ -2371,7 +2411,7 @@ void reply_unlink(struct smb_request *req)
                goto out;
        }
 
-       reply_outbuf(req, 0, 0);
+       reply_smb1_outbuf(req, 0, 0);
  out:
        TALLOC_FREE(smb_fname);
        END_PROFILE(SMBunlink);
@@ -2837,7 +2877,7 @@ static void reply_lockread_locked(struct tevent_req *subreq)
        /*
         * However the requested READ size IS affected by max_send. Insanity.... JRA.
         */
-       maxtoread = req->xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
+       maxtoread = req->xconn->smb1.sessions.max_send - (MIN_SMB_SIZE + 5*2 + 3);
 
        if (numtoread > maxtoread) {
                DBG_WARNING("requested read size (%zu) is greater than "
@@ -2850,7 +2890,7 @@ static void reply_lockread_locked(struct tevent_req *subreq)
                numtoread = maxtoread;
        }
 
-       reply_outbuf(req, 5, numtoread + 3);
+       reply_smb1_outbuf(req, 5, numtoread + 3);
 
        data = smb_buf(req->outbuf) + 3;
 
@@ -2861,7 +2901,7 @@ static void reply_lockread_locked(struct tevent_req *subreq)
                goto send;
        }
 
-       srv_set_message((char *)req->outbuf, 5, nread+3, False);
+       srv_smb1_set_message((char *)req->outbuf, 5, nread+3, False);
 
        SSVAL(req->outbuf,smb_vwv0,nread);
        SSVAL(req->outbuf,smb_vwv5,nread+3);
@@ -2873,14 +2913,14 @@ static void reply_lockread_locked(struct tevent_req *subreq)
                 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
 
 send:
-       ok = srv_send_smb(req->xconn,
+       ok = smb1_srv_send(req->xconn,
                          (char *)req->outbuf,
                          true,
                          req->seqnum+1,
                          IS_CONN_ENCRYPTED(req->conn),
                          NULL);
        if (!ok) {
-               exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
+               exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
        }
        TALLOC_FREE(req);
        END_PROFILE(SMBlockread);
@@ -2933,7 +2973,7 @@ void reply_read(struct smb_request *req)
        /*
         * The requested read size cannot be greater than max_send. JRA.
         */
-       maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
+       maxtoread = xconn->smb1.sessions.max_send - (MIN_SMB_SIZE + 5*2 + 3);
 
        if (numtoread > maxtoread) {
                DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
@@ -2943,7 +2983,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
                numtoread = maxtoread;
        }
 
-       reply_outbuf(req, 5, numtoread+3);
+       reply_smb1_outbuf(req, 5, numtoread+3);
 
        data = smb_buf(req->outbuf) + 3;
 
@@ -2969,7 +3009,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
                goto out;
        }
 
-       srv_set_message((char *)req->outbuf, 5, nread+3, False);
+       srv_smb1_set_message((char *)req->outbuf, 5, nread+3, False);
 
        SSVAL(req->outbuf,smb_vwv0,nread);
        SSVAL(req->outbuf,smb_vwv5,nread+3);
@@ -2992,7 +3032,7 @@ size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
 {
        size_t outsize;
 
-       outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
+       outsize = srv_smb1_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
                                  False);
 
        memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
@@ -3078,7 +3118,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
 
                header = data_blob_const(headerbuf, sizeof(headerbuf));
 
-               construct_reply_common_req(req, (char *)headerbuf);
+               construct_smb1_reply_common_req(req, (char *)headerbuf);
                setup_readX_header((char *)headerbuf, smb_maxcnt);
 
                nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
@@ -3179,7 +3219,7 @@ normal_read:
                        goto nosendfile_read;
                }
 
-               construct_reply_common_req(req, (char *)headerbuf);
+               construct_smb1_reply_common_req(req, (char *)headerbuf);
                setup_readX_header((char *)headerbuf, smb_maxcnt);
 
                /* Send out the header. */
@@ -3215,7 +3255,7 @@ normal_read:
 
 nosendfile_read:
 
-       reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
+       reply_smb1_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
        SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
        SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
 
@@ -3420,7 +3460,7 @@ void error_to_writebrawerr(struct smb_request *req)
 {
        uint8_t *old_outbuf = req->outbuf;
 
-       reply_outbuf(req, 1, 0);
+       reply_smb1_outbuf(req, 1, 0);
 
        memcpy(req->outbuf, old_outbuf, smb_size);
        TALLOC_FREE(old_outbuf);
@@ -3600,16 +3640,16 @@ void reply_writebraw(struct smb_request *req)
         * it to send more bytes */
 
        memcpy(buf, req->inbuf, smb_size);
-       srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
+       srv_smb1_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
        SCVAL(buf,smb_com,SMBwritebraw);
        SSVALS(buf,smb_vwv0,0xFFFF);
        show_msg(buf);
-       if (!srv_send_smb(req->xconn,
+       if (!smb1_srv_send(req->xconn,
                          buf,
                          false, 0, /* no signing */
                          IS_CONN_ENCRYPTED(conn),
                          &req->pcd)) {
-               exit_server_cleanly("reply_writebraw: srv_send_smb "
+               exit_server_cleanly("reply_writebraw: smb1_srv_send "
                        "failed.");
        }
 
@@ -3621,7 +3661,7 @@ void reply_writebraw(struct smb_request *req)
        }
 
        /* Set up outbuf to return the correct size */
-       reply_outbuf(req, 1, 0);
+       reply_smb1_outbuf(req, 1, 0);
 
        if (numtowrite != 0) {
 
@@ -3833,7 +3873,7 @@ void reply_writeunlock(struct smb_request *req)
                }
        }
 
-       reply_outbuf(req, 1, 0);
+       reply_smb1_outbuf(req, 1, 0);
 
        SSVAL(req->outbuf,smb_vwv0,nwritten);
 
@@ -3967,7 +4007,7 @@ void reply_write(struct smb_request *req)
                goto out;
        }
 
-       reply_outbuf(req, 1, 0);
+       reply_smb1_outbuf(req, 1, 0);
 
        SSVAL(req->outbuf,smb_vwv0,nwritten);
 
@@ -4236,7 +4276,7 @@ void reply_write_and_X(struct smb_request *req)
                goto out;
        }
 
-       reply_outbuf(req, 6, 0);
+       reply_smb1_outbuf(req, 6, 0);
        SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
        SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
        SSVAL(req->outbuf,smb_vwv2,nwritten);
@@ -4346,7 +4386,7 @@ void reply_lseek(struct smb_request *req)
 
        fh_set_pos(fsp->fh, res);
 
-       reply_outbuf(req, 2, 0);
+       reply_smb1_outbuf(req, 2, 0);
        SIVAL(req->outbuf,smb_vwv0,res);
 
        DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
@@ -4417,7 +4457,7 @@ void reply_flush(struct smb_request *req)
                }
        }
 
-       reply_outbuf(req, 0, 0);
+       reply_smb1_outbuf(req, 0, 0);
 
        DEBUG(3,("flush\n"));
        END_PROFILE(SMBflush);
@@ -4643,7 +4683,7 @@ static void reply_exit_done(struct tevent_req *req)
                close_file_free(NULL, &fsp, SHUTDOWN_CLOSE);
        }
 
-       reply_outbuf(smb1req, 0, 0);
+       reply_smb1_outbuf(smb1req, 0, 0);
        /*
         * The following call is needed to push the
         * reply data back out the socket after async
@@ -4729,7 +4769,7 @@ done:
                return;
        }
 
-       reply_outbuf(smb1req, 0, 0);
+       reply_smb1_outbuf(smb1req, 0, 0);
        END_PROFILE(SMBclose);
        return;
 }
@@ -4849,7 +4889,7 @@ static void reply_close_done(struct tevent_req *req)
 
        status = close_file_free(smb1req, &state->fsp, NORMAL_CLOSE);
        if (NT_STATUS_IS_OK(status)) {
-               reply_outbuf(smb1req, 0, 0);
+               reply_smb1_outbuf(smb1req, 0, 0);
        } else {
                reply_nterror(smb1req, status);
        }
@@ -4959,7 +4999,7 @@ void reply_writeclose(struct smb_request *req)
                goto out;
        }
 
-       reply_outbuf(req, 1, 0);
+       reply_smb1_outbuf(req, 1, 0);
 
        SSVAL(req->outbuf,smb_vwv0,nwritten);
 
@@ -5055,19 +5095,19 @@ static void reply_lock_done(struct tevent_req *subreq)
        TALLOC_FREE(subreq);
 
        if (NT_STATUS_IS_OK(status)) {
-               reply_outbuf(req, 0, 0);
+               reply_smb1_outbuf(req, 0, 0);
        } else {
                reply_nterror(req, status);
        }
 
-       ok = srv_send_smb(req->xconn,
+       ok = smb1_srv_send(req->xconn,
                          (char *)req->outbuf,
                          true,
                          req->seqnum+1,
                          IS_CONN_ENCRYPTED(req->conn),
                          NULL);
        if (!ok) {
-               exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
+               exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
        }
        TALLOC_FREE(req);
        END_PROFILE(SMBlock);
@@ -5122,7 +5162,7 @@ void reply_unlock(struct smb_request *req)
                   lck.offset,
                   lck.count);
 
-       reply_outbuf(req, 0, 0);
+       reply_smb1_outbuf(req, 0, 0);
 
        END_PROFILE(SMBunlock);
        return;
@@ -5333,7 +5373,7 @@ static void reply_tdis_done(struct tevent_req *req)
 
        TALLOC_FREE(tcon);
 
-       reply_outbuf(smb1req, 0, 0);
+       reply_smb1_outbuf(smb1req, 0, 0);
        /*
         * The following call is needed to push the
         * reply data back out the socket after async
@@ -5368,7 +5408,7 @@ void reply_echo(struct smb_request *req)
 
        smb_reverb = SVAL(req->vwv+0, 0);
 
-       reply_outbuf(req, 1, req->buflen);
+       reply_smb1_outbuf(req, 1, req->buflen);
 
        /* copy any incoming data back out */
        if (req->buflen > 0) {
@@ -5393,12 +5433,12 @@ void reply_echo(struct smb_request *req)
                SSVAL(req->outbuf,smb_vwv0,seq_num);
 
                show_msg((char *)req->outbuf);
-               if (!srv_send_smb(req->xconn,
+               if (!smb1_srv_send(req->xconn,
                                (char *)req->outbuf,
                                true, req->seqnum+1,
                                IS_CONN_ENCRYPTED(conn)||req->encrypted,
                                cur_pcd))
-                       exit_server_cleanly("reply_echo: srv_send_smb failed.");
+                       exit_server_cleanly("reply_echo: smb1_srv_send failed.");
        }
 
        DEBUG(3,("echo %d times\n", smb_reverb));
@@ -5450,7 +5490,7 @@ void reply_printopen(struct smb_request *req)
                return;
        }
 
-       reply_outbuf(req, 1, 0);
+       reply_smb1_outbuf(req, 1, 0);
        SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
 
        DEBUG(3,("openprint fd=%d %s\n",
@@ -5502,7 +5542,7 @@ void reply_printclose(struct smb_request *req)
                return;
        }
 
-       reply_outbuf(req, 0, 0);
+       reply_smb1_outbuf(req, 0, 0);
 
        END_PROFILE(SMBsplclose);
        return;
@@ -5541,7 +5581,7 @@ void reply_printqueue(struct smb_request *req)
                return;
        }
 
-       reply_outbuf(req, 2, 3);
+       reply_smb1_outbuf(req, 2, 3);
        SSVAL(req->outbuf,smb_vwv0,0);
        SSVAL(req->outbuf,smb_vwv1,0);
        SCVAL(smb_buf(req->outbuf),0,1);
@@ -5742,7 +5782,7 @@ void reply_printwrite(struct smb_request *req)
 
        DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
 
-       reply_outbuf(req, 0, 0);
+       reply_smb1_outbuf(req, 0, 0);
 
        END_PROFILE(SMBsplwr);
        return;
@@ -5807,7 +5847,7 @@ void reply_mkdir(struct smb_request *req)
                goto out;
        }
 
-       reply_outbuf(req, 0, 0);
+       reply_smb1_outbuf(req, 0, 0);
 
        DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
  out:
@@ -5827,8 +5867,10 @@ void reply_rmdir(struct smb_request *req)
        char *directory = NULL;
        NTSTATUS status;
        TALLOC_CTX *ctx = talloc_tos();
+       struct files_struct *dirfsp = NULL;
        files_struct *fsp = NULL;
        int info = 0;
+       NTTIME twrp = 0;
        uint32_t ucf_flags = ucf_flags_from_smb_request(req);
 
        START_PROFILE(SMBrmdir);
@@ -5840,11 +5882,16 @@ void reply_rmdir(struct smb_request *req)
                goto out;
        }
 
-       status = filename_convert(ctx, conn,
-                                directory,
-                                ucf_flags,
-                                0,
-                                &smb_dname);
+       if (ucf_flags & UCF_GMT_PATHNAME) {
+               extract_snapshot_token(directory, &twrp);
+       }
+       status = filename_convert_dirfsp(ctx,
+                                        conn,
+                                        directory,
+                                        ucf_flags,
+                                        twrp,
+                                        &dirfsp,
+                                        &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,
@@ -5858,6 +5905,7 @@ void reply_rmdir(struct smb_request *req)
        status = SMB_VFS_CREATE_FILE(
                conn,                                   /* conn */
                req,                                    /* req */
+               dirfsp,                                 /* dirfsp */
                smb_dname,                              /* fname */
                DELETE_ACCESS,                          /* access_mask */
                (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
@@ -5909,7 +5957,7 @@ void reply_rmdir(struct smb_request *req)
        if (!NT_STATUS_IS_OK(status)) {
                reply_nterror(req, status);
        } else {
-               reply_outbuf(req, 0, 0);
+               reply_smb1_outbuf(req, 0, 0);
        }
 
        DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
@@ -6037,7 +6085,9 @@ void reply_mv(struct smb_request *req)
        status = rename_internals(ctx,
                                conn,
                                req,
+                               NULL, /* src_dirfsp */
                                smb_fname_src,
+                               NULL, /* dst_dirfsp */
                                smb_fname_dst,
                                dst_original_lcomp,
                                attrs,
@@ -6058,7 +6108,7 @@ void reply_mv(struct smb_request *req)
                goto out;
        }
 
-       reply_outbuf(req, 0, 0);
+       reply_smb1_outbuf(req, 0, 0);
  out:
        TALLOC_FREE(smb_fname_src);
        TALLOC_FREE(smb_fname_dst);
@@ -6299,7 +6349,7 @@ void reply_lockingX(struct smb_request *req)
                        ulocks[0],
                        NT_STATUS_OK);
                if (ok) {
-                       reply_outbuf(req, 2, 0);
+                       reply_smb1_outbuf(req, 2, 0);
                        SSVAL(req->outbuf, smb_vwv0, 0xff);
                        SSVAL(req->outbuf, smb_vwv1, 0);
                        END_PROFILE(SMBlockingX);
@@ -6350,7 +6400,7 @@ void reply_lockingX(struct smb_request *req)
 
                if (num_locks == 0) {
                        /* See smbtorture3 lock11 test */
-                       reply_outbuf(req, 2, 0);
+                       reply_smb1_outbuf(req, 2, 0);
                        /* andx chain ends */
                        SSVAL(req->outbuf, smb_vwv0, 0xff);
                        SSVAL(req->outbuf, smb_vwv1, 0);
@@ -6370,7 +6420,7 @@ void reply_lockingX(struct smb_request *req)
                        return;
                }
 
-               reply_outbuf(req, 2, 0);
+               reply_smb1_outbuf(req, 2, 0);
                SSVAL(req->outbuf, smb_vwv0, 0xff);
                SSVAL(req->outbuf, smb_vwv1, 0);
                END_PROFILE(SMBlockingX);
@@ -6412,21 +6462,21 @@ static void reply_lockingx_done(struct tevent_req *subreq)
        DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
 
        if (NT_STATUS_IS_OK(status)) {
-               reply_outbuf(req, 2, 0);
+               reply_smb1_outbuf(req, 2, 0);
                SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
                SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
        } else {
                reply_nterror(req, status);
        }
 
-       ok = srv_send_smb(req->xconn,
+       ok = smb1_srv_send(req->xconn,
                          (char *)req->outbuf,
                          true,
                          req->seqnum+1,
                          IS_CONN_ENCRYPTED(req->conn),
                          NULL);
        if (!ok) {
-               exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
+               exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
        }
        TALLOC_FREE(req);
        END_PROFILE(SMBlockingX);
@@ -6500,7 +6550,7 @@ void reply_setattrE(struct smb_request *req)
        ft.create_time = time_t_to_full_timespec(
            srv_make_unix_date2(req->vwv+1));
 
-       reply_outbuf(req, 0, 0);
+       reply_smb1_outbuf(req, 0, 0);
 
        /* 
         * Patch from Ray Frush <frush@engr.colostate.edu>
@@ -6616,7 +6666,7 @@ void reply_getattrE(struct smb_request *req)
         * this.
         */
 
-       reply_outbuf(req, 11, 0);
+       reply_smb1_outbuf(req, 11, 0);
 
        create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
        srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
@@ -6678,10 +6728,42 @@ void reply_findclose(struct smb_request *req)
                }
        }
 
-       reply_outbuf(req, 0, 0);
+       reply_smb1_outbuf(req, 0, 0);
 
        DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
 
        END_PROFILE(SMBfindclose);
        return;
 }
+
+/****************************************************************************
+ Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
+****************************************************************************/
+
+void reply_findnclose(struct smb_request *req)
+{
+       int dptr_num;
+
+       START_PROFILE(SMBfindnclose);
+
+       if (req->wct < 1) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBfindnclose);
+               return;
+       }
+
+       dptr_num = SVAL(req->vwv+0, 0);
+
+       DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
+
+       /* We never give out valid handles for a
+          findnotifyfirst - so any dptr_num is ok here.
+          Just ignore it. */
+
+       reply_smb1_outbuf(req, 0, 0);
+
+       DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
+
+       END_PROFILE(SMBfindnclose);
+       return;
+}