s3-rpc_client: add and use rpc_client/rpc_client.h.
[samba.git] / source3 / smbd / reply.c
1 /*
2    Unix SMB/CIFS implementation.
3    Main SMB reply routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Andrew Bartlett      2001
6    Copyright (C) Jeremy Allison 1992-2007.
7    Copyright (C) Volker Lendecke 2007
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22 /*
23    This file handles most of the reply_ calls that the server
24    makes to handle specific protocols
25 */
26
27 #include "includes.h"
28 #include "system/filesys.h"
29 #include "printing.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "fake_file.h"
33 #include "rpc_client/rpc_client.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "rpc_client/cli_spoolss.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_server/rpc_ncacn_np.h"
38 #include "libcli/security/security.h"
39 #include "libsmb/nmblib.h"
40 #include "auth.h"
41
42 /****************************************************************************
43  Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
44  path or anything including wildcards.
45  We're assuming here that '/' is not the second byte in any multibyte char
46  set (a safe assumption). '\\' *may* be the second byte in a multibyte char
47  set.
48 ****************************************************************************/
49
50 /* Custom version for processing POSIX paths. */
51 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
52
53 static NTSTATUS check_path_syntax_internal(char *path,
54                                            bool posix_path,
55                                            bool *p_last_component_contains_wcard)
56 {
57         char *d = path;
58         const char *s = path;
59         NTSTATUS ret = NT_STATUS_OK;
60         bool start_of_name_component = True;
61         bool stream_started = false;
62
63         *p_last_component_contains_wcard = False;
64
65         while (*s) {
66                 if (stream_started) {
67                         switch (*s) {
68                         case '/':
69                         case '\\':
70                                 return NT_STATUS_OBJECT_NAME_INVALID;
71                         case ':':
72                                 if (s[1] == '\0') {
73                                         return NT_STATUS_OBJECT_NAME_INVALID;
74                                 }
75                                 if (strchr_m(&s[1], ':')) {
76                                         return NT_STATUS_OBJECT_NAME_INVALID;
77                                 }
78                                 break;
79                         }
80                 }
81
82                 if ((*s == ':') && !posix_path && !stream_started) {
83                         if (*p_last_component_contains_wcard) {
84                                 return NT_STATUS_OBJECT_NAME_INVALID;
85                         }
86                         /* Stream names allow more characters than file names.
87                            We're overloading posix_path here to allow a wider
88                            range of characters. If stream_started is true this
89                            is still a Windows path even if posix_path is true.
90                            JRA.
91                         */
92                         stream_started = true;
93                         start_of_name_component = false;
94                         posix_path = true;
95
96                         if (s[1] == '\0') {
97                                 return NT_STATUS_OBJECT_NAME_INVALID;
98                         }
99                 }
100
101                 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
102                         /*
103                          * Safe to assume is not the second part of a mb char
104                          * as this is handled below.
105                          */
106                         /* Eat multiple '/' or '\\' */
107                         while (IS_PATH_SEP(*s,posix_path)) {
108                                 s++;
109                         }
110                         if ((d != path) && (*s != '\0')) {
111                                 /* We only care about non-leading or trailing '/' or '\\' */
112                                 *d++ = '/';
113                         }
114
115                         start_of_name_component = True;
116                         /* New component. */
117                         *p_last_component_contains_wcard = False;
118                         continue;
119                 }
120
121                 if (start_of_name_component) {
122                         if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
123                                 /* Uh oh - "/../" or "\\..\\"  or "/..\0" or "\\..\0" ! */
124
125                                 /*
126                                  * No mb char starts with '.' so we're safe checking the directory separator here.
127                                  */
128
129                                 /* If  we just added a '/' - delete it */
130                                 if ((d > path) && (*(d-1) == '/')) {
131                                         *(d-1) = '\0';
132                                         d--;
133                                 }
134
135                                 /* Are we at the start ? Can't go back further if so. */
136                                 if (d <= path) {
137                                         ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
138                                         break;
139                                 }
140                                 /* Go back one level... */
141                                 /* We know this is safe as '/' cannot be part of a mb sequence. */
142                                 /* NOTE - if this assumption is invalid we are not in good shape... */
143                                 /* Decrement d first as d points to the *next* char to write into. */
144                                 for (d--; d > path; d--) {
145                                         if (*d == '/')
146                                                 break;
147                                 }
148                                 s += 2; /* Else go past the .. */
149                                 /* We're still at the start of a name component, just the previous one. */
150                                 continue;
151
152                         } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
153                                 if (posix_path) {
154                                         /* Eat the '.' */
155                                         s++;
156                                         continue;
157                                 }
158                         }
159
160                 }
161
162                 if (!(*s & 0x80)) {
163                         if (!posix_path) {
164                                 if (*s <= 0x1f || *s == '|') {
165                                         return NT_STATUS_OBJECT_NAME_INVALID;
166                                 }
167                                 switch (*s) {
168                                         case '*':
169                                         case '?':
170                                         case '<':
171                                         case '>':
172                                         case '"':
173                                                 *p_last_component_contains_wcard = True;
174                                                 break;
175                                         default:
176                                                 break;
177                                 }
178                         }
179                         *d++ = *s++;
180                 } else {
181                         size_t siz;
182                         /* Get the size of the next MB character. */
183                         next_codepoint(s,&siz);
184                         switch(siz) {
185                                 case 5:
186                                         *d++ = *s++;
187                                         /*fall through*/
188                                 case 4:
189                                         *d++ = *s++;
190                                         /*fall through*/
191                                 case 3:
192                                         *d++ = *s++;
193                                         /*fall through*/
194                                 case 2:
195                                         *d++ = *s++;
196                                         /*fall through*/
197                                 case 1:
198                                         *d++ = *s++;
199                                         break;
200                                 default:
201                                         DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
202                                         *d = '\0';
203                                         return NT_STATUS_INVALID_PARAMETER;
204                         }
205                 }
206                 start_of_name_component = False;
207         }
208
209         *d = '\0';
210
211         return ret;
212 }
213
214 /****************************************************************************
215  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
216  No wildcards allowed.
217 ****************************************************************************/
218
219 NTSTATUS check_path_syntax(char *path)
220 {
221         bool ignore;
222         return check_path_syntax_internal(path, False, &ignore);
223 }
224
225 /****************************************************************************
226  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
227  Wildcards allowed - p_contains_wcard returns true if the last component contained
228  a wildcard.
229 ****************************************************************************/
230
231 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
232 {
233         return check_path_syntax_internal(path, False, p_contains_wcard);
234 }
235
236 /****************************************************************************
237  Check the path for a POSIX client.
238  We're assuming here that '/' is not the second byte in any multibyte char
239  set (a safe assumption).
240 ****************************************************************************/
241
242 NTSTATUS check_path_syntax_posix(char *path)
243 {
244         bool ignore;
245         return check_path_syntax_internal(path, True, &ignore);
246 }
247
248 /****************************************************************************
249  Pull a string and check the path allowing a wilcard - provide for error return.
250 ****************************************************************************/
251
252 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
253                         const char *base_ptr,
254                         uint16 smb_flags2,
255                         char **pp_dest,
256                         const char *src,
257                         size_t src_len,
258                         int flags,
259                         NTSTATUS *err,
260                         bool *contains_wcard)
261 {
262         size_t ret;
263
264         *pp_dest = NULL;
265
266         ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
267                                  src_len, flags);
268
269         if (!*pp_dest) {
270                 *err = NT_STATUS_INVALID_PARAMETER;
271                 return ret;
272         }
273
274         *contains_wcard = False;
275
276         if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
277                 /*
278                  * For a DFS path the function parse_dfs_path()
279                  * will do the path processing, just make a copy.
280                  */
281                 *err = NT_STATUS_OK;
282                 return ret;
283         }
284
285         if (lp_posix_pathnames()) {
286                 *err = check_path_syntax_posix(*pp_dest);
287         } else {
288                 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
289         }
290
291         return ret;
292 }
293
294 /****************************************************************************
295  Pull a string and check the path - provide for error return.
296 ****************************************************************************/
297
298 size_t srvstr_get_path(TALLOC_CTX *ctx,
299                         const char *base_ptr,
300                         uint16 smb_flags2,
301                         char **pp_dest,
302                         const char *src,
303                         size_t src_len,
304                         int flags,
305                         NTSTATUS *err)
306 {
307         bool ignore;
308         return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
309                                      src_len, flags, err, &ignore);
310 }
311
312 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
313                                  char **pp_dest, const char *src, int flags,
314                                  NTSTATUS *err, bool *contains_wcard)
315 {
316         return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
317                                      pp_dest, src, smbreq_bufrem(req, src),
318                                      flags, err, contains_wcard);
319 }
320
321 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
322                            char **pp_dest, const char *src, int flags,
323                            NTSTATUS *err)
324 {
325         bool ignore;
326         return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
327                                          flags, err, &ignore);
328 }
329
330 /****************************************************************************
331  Check if we have a correct fsp pointing to a file. Basic check for open fsp.
332 ****************************************************************************/
333
334 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
335                     files_struct *fsp)
336 {
337         if ((fsp == NULL) || (conn == NULL)) {
338                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
339                 return False;
340         }
341         if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
342                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
343                 return False;
344         }
345         return True;
346 }
347
348 /****************************************************************************
349  Check if we have a correct fsp pointing to a file.
350 ****************************************************************************/
351
352 bool check_fsp(connection_struct *conn, struct smb_request *req,
353                files_struct *fsp)
354 {
355         if (!check_fsp_open(conn, req, fsp)) {
356                 return False;
357         }
358         if (fsp->is_directory) {
359                 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
360                 return False;
361         }
362         if (fsp->fh->fd == -1) {
363                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
364                 return False;
365         }
366         fsp->num_smb_operations++;
367         return True;
368 }
369
370 /****************************************************************************
371  Check if we have a correct fsp pointing to a quota fake file. Replacement for
372  the CHECK_NTQUOTA_HANDLE_OK macro.
373 ****************************************************************************/
374
375 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
376                               files_struct *fsp)
377 {
378         if (!check_fsp_open(conn, req, fsp)) {
379                 return false;
380         }
381
382         if (fsp->is_directory) {
383                 return false;
384         }
385
386         if (fsp->fake_file_handle == NULL) {
387                 return false;
388         }
389
390         if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
391                 return false;
392         }
393
394         if (fsp->fake_file_handle->private_data == NULL) {
395                 return false;
396         }
397
398         return true;
399 }
400
401 static bool netbios_session_retarget(struct smbd_server_connection *sconn,
402                                      const char *name, int name_type)
403 {
404         char *trim_name;
405         char *trim_name_type;
406         const char *retarget_parm;
407         char *retarget;
408         char *p;
409         int retarget_type = 0x20;
410         int retarget_port = 139;
411         struct sockaddr_storage retarget_addr;
412         struct sockaddr_in *in_addr;
413         bool ret = false;
414         uint8_t outbuf[10];
415
416         if (get_socket_port(sconn->sock) != 139) {
417                 return false;
418         }
419
420         trim_name = talloc_strdup(talloc_tos(), name);
421         if (trim_name == NULL) {
422                 goto fail;
423         }
424         trim_char(trim_name, ' ', ' ');
425
426         trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
427                                          name_type);
428         if (trim_name_type == NULL) {
429                 goto fail;
430         }
431
432         retarget_parm = lp_parm_const_string(-1, "netbios retarget",
433                                              trim_name_type, NULL);
434         if (retarget_parm == NULL) {
435                 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
436                                                      trim_name, NULL);
437         }
438         if (retarget_parm == NULL) {
439                 goto fail;
440         }
441
442         retarget = talloc_strdup(trim_name, retarget_parm);
443         if (retarget == NULL) {
444                 goto fail;
445         }
446
447         DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
448
449         p = strchr(retarget, ':');
450         if (p != NULL) {
451                 *p++ = '\0';
452                 retarget_port = atoi(p);
453         }
454
455         p = strchr_m(retarget, '#');
456         if (p != NULL) {
457                 *p++ = '\0';
458                 sscanf(p, "%x", &retarget_type);
459         }
460
461         ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
462         if (!ret) {
463                 DEBUG(10, ("could not resolve %s\n", retarget));
464                 goto fail;
465         }
466
467         if (retarget_addr.ss_family != AF_INET) {
468                 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
469                 goto fail;
470         }
471
472         in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
473
474         _smb_setlen(outbuf, 6);
475         SCVAL(outbuf, 0, 0x84);
476         *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
477         *(uint16_t *)(outbuf+8) = htons(retarget_port);
478
479         if (!srv_send_smb(sconn, (char *)outbuf, false, 0, false,
480                           NULL)) {
481                 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
482                                     "failed.");
483         }
484
485         ret = true;
486  fail:
487         TALLOC_FREE(trim_name);
488         return ret;
489 }
490
491 /****************************************************************************
492  Reply to a (netbios-level) special message. 
493 ****************************************************************************/
494
495 void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inbuf_size)
496 {
497         int msg_type = CVAL(inbuf,0);
498         int msg_flags = CVAL(inbuf,1);
499         /*
500          * We only really use 4 bytes of the outbuf, but for the smb_setlen
501          * calculation & friends (srv_send_smb uses that) we need the full smb
502          * header.
503          */
504         char outbuf[smb_size];
505
506         memset(outbuf, '\0', sizeof(outbuf));
507
508         smb_setlen(outbuf,0);
509
510         switch (msg_type) {
511         case 0x81: /* session request */
512         {
513                 /* inbuf_size is guarenteed to be at least 4. */
514                 fstring name1,name2;
515                 int name_type1, name_type2;
516                 int name_len1, name_len2;
517
518                 *name1 = *name2 = 0;
519
520                 if (sconn->nbt.got_session) {
521                         exit_server_cleanly("multiple session request not permitted");
522                 }
523
524                 SCVAL(outbuf,0,0x82);
525                 SCVAL(outbuf,3,0);
526
527                 /* inbuf_size is guaranteed to be at least 4. */
528                 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
529                 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
530                         DEBUG(0,("Invalid name length in session request\n"));
531                         break;
532                 }
533                 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
534                 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
535                         DEBUG(0,("Invalid name length in session request\n"));
536                         break;
537                 }
538
539                 name_type1 = name_extract((unsigned char *)inbuf,
540                                 inbuf_size,(unsigned int)4,name1);
541                 name_type2 = name_extract((unsigned char *)inbuf,
542                                 inbuf_size,(unsigned int)(4 + name_len1),name2);
543
544                 if (name_type1 == -1 || name_type2 == -1) {
545                         DEBUG(0,("Invalid name type in session request\n"));
546                         break;
547                 }
548
549                 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
550                          name1, name_type1, name2, name_type2));
551
552                 if (netbios_session_retarget(sconn, name1, name_type1)) {
553                         exit_server_cleanly("retargeted client");
554                 }
555
556                 /*
557                  * Windows NT/2k uses "*SMBSERVER" and XP uses
558                  * "*SMBSERV" arrggg!!!
559                  */
560                 if (strequal(name1, "*SMBSERVER     ")
561                     || strequal(name1, "*SMBSERV       "))  {
562                         fstrcpy(name1, sconn->client_id.addr);
563                 }
564
565                 set_local_machine_name(name1, True);
566                 set_remote_machine_name(name2, True);
567
568                 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
569                          get_local_machine_name(), get_remote_machine_name(),
570                          name_type2));
571
572                 if (name_type2 == 'R') {
573                         /* We are being asked for a pathworks session --- 
574                            no thanks! */
575                         SCVAL(outbuf, 0,0x83);
576                         break;
577                 }
578
579                 /* only add the client's machine name to the list
580                    of possibly valid usernames if we are operating
581                    in share mode security */
582                 if (lp_security() == SEC_SHARE) {
583                         add_session_user(sconn, get_remote_machine_name());
584                 }
585
586                 reload_services(sconn->msg_ctx, sconn->sock, True);
587                 reopen_logs();
588
589                 sconn->nbt.got_session = true;
590                 break;
591         }
592
593         case 0x89: /* session keepalive request 
594                       (some old clients produce this?) */
595                 SCVAL(outbuf,0,SMBkeepalive);
596                 SCVAL(outbuf,3,0);
597                 break;
598
599         case 0x82: /* positive session response */
600         case 0x83: /* negative session response */
601         case 0x84: /* retarget session response */
602                 DEBUG(0,("Unexpected session response\n"));
603                 break;
604
605         case SMBkeepalive: /* session keepalive */
606         default:
607                 return;
608         }
609
610         DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
611                     msg_type, msg_flags));
612
613         srv_send_smb(sconn, outbuf, false, 0, false, NULL);
614         return;
615 }
616
617 /****************************************************************************
618  Reply to a tcon.
619  conn POINTER CAN BE NULL HERE !
620 ****************************************************************************/
621
622 void reply_tcon(struct smb_request *req)
623 {
624         connection_struct *conn = req->conn;
625         const char *service;
626         char *service_buf = NULL;
627         char *password = NULL;
628         char *dev = NULL;
629         int pwlen=0;
630         NTSTATUS nt_status;
631         const char *p;
632         DATA_BLOB password_blob;
633         TALLOC_CTX *ctx = talloc_tos();
634         struct smbd_server_connection *sconn = req->sconn;
635
636         START_PROFILE(SMBtcon);
637
638         if (req->buflen < 4) {
639                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
640                 END_PROFILE(SMBtcon);
641                 return;
642         }
643
644         p = (const char *)req->buf + 1;
645         p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
646         p += 1;
647         pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
648         p += pwlen+1;
649         p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
650         p += 1;
651
652         if (service_buf == NULL || password == NULL || dev == NULL) {
653                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
654                 END_PROFILE(SMBtcon);
655                 return;
656         }
657         p = strrchr_m(service_buf,'\\');
658         if (p) {
659                 service = p+1;
660         } else {
661                 service = service_buf;
662         }
663
664         password_blob = data_blob(password, pwlen+1);
665
666         conn = make_connection(sconn,service,password_blob,dev,
667                                req->vuid,&nt_status);
668         req->conn = conn;
669
670         data_blob_clear_free(&password_blob);
671
672         if (!conn) {
673                 reply_nterror(req, nt_status);
674                 END_PROFILE(SMBtcon);
675                 return;
676         }
677
678         reply_outbuf(req, 2, 0);
679         SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
680         SSVAL(req->outbuf,smb_vwv1,conn->cnum);
681         SSVAL(req->outbuf,smb_tid,conn->cnum);
682
683         DEBUG(3,("tcon service=%s cnum=%d\n",
684                  service, conn->cnum));
685
686         END_PROFILE(SMBtcon);
687         return;
688 }
689
690 /****************************************************************************
691  Reply to a tcon and X.
692  conn POINTER CAN BE NULL HERE !
693 ****************************************************************************/
694
695 void reply_tcon_and_X(struct smb_request *req)
696 {
697         connection_struct *conn = req->conn;
698         const char *service = NULL;
699         DATA_BLOB password;
700         TALLOC_CTX *ctx = talloc_tos();
701         /* what the cleint thinks the device is */
702         char *client_devicetype = NULL;
703         /* what the server tells the client the share represents */
704         const char *server_devicetype;
705         NTSTATUS nt_status;
706         int passlen;
707         char *path = NULL;
708         const char *p, *q;
709         uint16 tcon_flags;
710         struct smbd_server_connection *sconn = req->sconn;
711
712         START_PROFILE(SMBtconX);
713
714         if (req->wct < 4) {
715                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
716                 END_PROFILE(SMBtconX);
717                 return;
718         }
719
720         passlen = SVAL(req->vwv+3, 0);
721         tcon_flags = SVAL(req->vwv+2, 0);
722
723         /* we might have to close an old one */
724         if ((tcon_flags & 0x1) && conn) {
725                 close_cnum(conn,req->vuid);
726                 req->conn = NULL;
727                 conn = NULL;
728         }
729
730         if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
731                 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
732                 END_PROFILE(SMBtconX);
733                 return;
734         }
735
736         if (sconn->smb1.negprot.encrypted_passwords) {
737                 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
738                 if (lp_security() == SEC_SHARE) {
739                         /*
740                          * Security = share always has a pad byte
741                          * after the password.
742                          */
743                         p = (const char *)req->buf + passlen + 1;
744                 } else {
745                         p = (const char *)req->buf + passlen;
746                 }
747         } else {
748                 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
749                 /* Ensure correct termination */
750                 password.data[passlen]=0;
751                 p = (const char *)req->buf + passlen + 1;
752         }
753
754         p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
755
756         if (path == NULL) {
757                 data_blob_clear_free(&password);
758                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
759                 END_PROFILE(SMBtconX);
760                 return;
761         }
762
763         /*
764          * the service name can be either: \\server\share
765          * or share directly like on the DELL PowerVault 705
766          */
767         if (*path=='\\') {
768                 q = strchr_m(path+2,'\\');
769                 if (!q) {
770                         data_blob_clear_free(&password);
771                         reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
772                         END_PROFILE(SMBtconX);
773                         return;
774                 }
775                 service = q+1;
776         } else {
777                 service = path;
778         }
779
780         p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
781                                 &client_devicetype, p,
782                                 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
783
784         if (client_devicetype == NULL) {
785                 data_blob_clear_free(&password);
786                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
787                 END_PROFILE(SMBtconX);
788                 return;
789         }
790
791         DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
792
793         conn = make_connection(sconn, service, password, client_devicetype,
794                                req->vuid, &nt_status);
795         req->conn =conn;
796
797         data_blob_clear_free(&password);
798
799         if (!conn) {
800                 reply_nterror(req, nt_status);
801                 END_PROFILE(SMBtconX);
802                 return;
803         }
804
805         if ( IS_IPC(conn) )
806                 server_devicetype = "IPC";
807         else if ( IS_PRINT(conn) )
808                 server_devicetype = "LPT1:";
809         else
810                 server_devicetype = "A:";
811
812         if (get_Protocol() < PROTOCOL_NT1) {
813                 reply_outbuf(req, 2, 0);
814                 if (message_push_string(&req->outbuf, server_devicetype,
815                                         STR_TERMINATE|STR_ASCII) == -1) {
816                         reply_nterror(req, NT_STATUS_NO_MEMORY);
817                         END_PROFILE(SMBtconX);
818                         return;
819                 }
820         } else {
821                 /* NT sets the fstype of IPC$ to the null string */
822                 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
823
824                 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
825                         /* Return permissions. */
826                         uint32 perm1 = 0;
827                         uint32 perm2 = 0;
828
829                         reply_outbuf(req, 7, 0);
830
831                         if (IS_IPC(conn)) {
832                                 perm1 = FILE_ALL_ACCESS;
833                                 perm2 = FILE_ALL_ACCESS;
834                         } else {
835                                 perm1 = CAN_WRITE(conn) ?
836                                                 SHARE_ALL_ACCESS :
837                                                 SHARE_READ_ONLY;
838                         }
839
840                         SIVAL(req->outbuf, smb_vwv3, perm1);
841                         SIVAL(req->outbuf, smb_vwv5, perm2);
842                 } else {
843                         reply_outbuf(req, 3, 0);
844                 }
845
846                 if ((message_push_string(&req->outbuf, server_devicetype,
847                                          STR_TERMINATE|STR_ASCII) == -1)
848                     || (message_push_string(&req->outbuf, fstype,
849                                             STR_TERMINATE) == -1)) {
850                         reply_nterror(req, NT_STATUS_NO_MEMORY);
851                         END_PROFILE(SMBtconX);
852                         return;
853                 }
854
855                 /* what does setting this bit do? It is set by NT4 and
856                    may affect the ability to autorun mounted cdroms */
857                 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
858                       (lp_csc_policy(SNUM(conn)) << 2));
859
860                 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
861                         DEBUG(2,("Serving %s as a Dfs root\n",
862                                  lp_servicename(SNUM(conn)) ));
863                         SSVAL(req->outbuf, smb_vwv2,
864                               SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
865                 }
866         }
867
868
869         DEBUG(3,("tconX service=%s \n",
870                  service));
871
872         /* set the incoming and outgoing tid to the just created one */
873         SSVAL(req->inbuf,smb_tid,conn->cnum);
874         SSVAL(req->outbuf,smb_tid,conn->cnum);
875
876         END_PROFILE(SMBtconX);
877
878         req->tid = conn->cnum;
879         chain_reply(req);
880         return;
881 }
882
883 /****************************************************************************
884  Reply to an unknown type.
885 ****************************************************************************/
886
887 void reply_unknown_new(struct smb_request *req, uint8 type)
888 {
889         DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
890                   smb_fn_name(type), type, type));
891         reply_force_doserror(req, ERRSRV, ERRunknownsmb);
892         return;
893 }
894
895 /****************************************************************************
896  Reply to an ioctl.
897  conn POINTER CAN BE NULL HERE !
898 ****************************************************************************/
899
900 void reply_ioctl(struct smb_request *req)
901 {
902         connection_struct *conn = req->conn;
903         uint16 device;
904         uint16 function;
905         uint32 ioctl_code;
906         int replysize;
907         char *p;
908
909         START_PROFILE(SMBioctl);
910
911         if (req->wct < 3) {
912                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
913                 END_PROFILE(SMBioctl);
914                 return;
915         }
916
917         device     = SVAL(req->vwv+1, 0);
918         function   = SVAL(req->vwv+2, 0);
919         ioctl_code = (device << 16) + function;
920
921         DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
922
923         switch (ioctl_code) {
924             case IOCTL_QUERY_JOB_INFO:
925                     replysize = 32;
926                     break;
927             default:
928                     reply_force_doserror(req, ERRSRV, ERRnosupport);
929                     END_PROFILE(SMBioctl);
930                     return;
931         }
932
933         reply_outbuf(req, 8, replysize+1);
934         SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
935         SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
936         SSVAL(req->outbuf,smb_vwv6,52);        /* Offset to data */
937         p = smb_buf(req->outbuf);
938         memset(p, '\0', replysize+1); /* valgrind-safe. */
939         p += 1;          /* Allow for alignment */
940
941         switch (ioctl_code) {
942                 case IOCTL_QUERY_JOB_INFO:                  
943                 {
944                         files_struct *fsp = file_fsp(
945                                 req, SVAL(req->vwv+0, 0));
946                         if (!fsp) {
947                                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
948                                 END_PROFILE(SMBioctl);
949                                 return;
950                         }
951                         /* Job number */
952                         if (fsp->print_file) {
953                                 SSVAL(p, 0, fsp->print_file->rap_jobid);
954                         } else {
955                                 SSVAL(p, 0, 0);
956                         }
957                         srvstr_push((char *)req->outbuf, req->flags2, p+2,
958                                     global_myname(), 15,
959                                     STR_TERMINATE|STR_ASCII);
960                         if (conn) {
961                                 srvstr_push((char *)req->outbuf, req->flags2,
962                                             p+18, lp_servicename(SNUM(conn)),
963                                             13, STR_TERMINATE|STR_ASCII);
964                         } else {
965                                 memset(p+18, 0, 13);
966                         }
967                         break;
968                 }
969         }
970
971         END_PROFILE(SMBioctl);
972         return;
973 }
974
975 /****************************************************************************
976  Strange checkpath NTSTATUS mapping.
977 ****************************************************************************/
978
979 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
980 {
981         /* Strange DOS error code semantics only for checkpath... */
982         if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
983                 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
984                         /* We need to map to ERRbadpath */
985                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
986                 }
987         }
988         return status;
989 }
990
991 /****************************************************************************
992  Reply to a checkpath.
993 ****************************************************************************/
994
995 void reply_checkpath(struct smb_request *req)
996 {
997         connection_struct *conn = req->conn;
998         struct smb_filename *smb_fname = NULL;
999         char *name = NULL;
1000         NTSTATUS status;
1001         TALLOC_CTX *ctx = talloc_tos();
1002
1003         START_PROFILE(SMBcheckpath);
1004
1005         srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1006                             STR_TERMINATE, &status);
1007
1008         if (!NT_STATUS_IS_OK(status)) {
1009                 status = map_checkpath_error(req->flags2, status);
1010                 reply_nterror(req, status);
1011                 END_PROFILE(SMBcheckpath);
1012                 return;
1013         }
1014
1015         DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1016
1017         status = filename_convert(ctx,
1018                                 conn,
1019                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
1020                                 name,
1021                                 0,
1022                                 NULL,
1023                                 &smb_fname);
1024
1025         if (!NT_STATUS_IS_OK(status)) {
1026                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1027                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1028                                         ERRSRV, ERRbadpath);
1029                         END_PROFILE(SMBcheckpath);
1030                         return;
1031                 }
1032                 goto path_err;
1033         }
1034
1035         if (!VALID_STAT(smb_fname->st) &&
1036             (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1037                 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1038                         smb_fname_str_dbg(smb_fname), strerror(errno)));
1039                 status = map_nt_error_from_unix(errno);
1040                 goto path_err;
1041         }
1042
1043         if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1044                 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1045                                 ERRDOS, ERRbadpath);
1046                 goto out;
1047         }
1048
1049         reply_outbuf(req, 0, 0);
1050
1051  path_err:
1052         /* We special case this - as when a Windows machine
1053                 is parsing a path is steps through the components
1054                 one at a time - if a component fails it expects
1055                 ERRbadpath, not ERRbadfile.
1056         */
1057         status = map_checkpath_error(req->flags2, status);
1058         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1059                 /*
1060                  * Windows returns different error codes if
1061                  * the parent directory is valid but not the
1062                  * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1063                  * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1064                  * if the path is invalid.
1065                  */
1066                 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1067                                 ERRDOS, ERRbadpath);
1068                 goto out;
1069         }
1070
1071         reply_nterror(req, status);
1072
1073  out:
1074         TALLOC_FREE(smb_fname);
1075         END_PROFILE(SMBcheckpath);
1076         return;
1077 }
1078
1079 /****************************************************************************
1080  Reply to a getatr.
1081 ****************************************************************************/
1082
1083 void reply_getatr(struct smb_request *req)
1084 {
1085         connection_struct *conn = req->conn;
1086         struct smb_filename *smb_fname = NULL;
1087         char *fname = NULL;
1088         int mode=0;
1089         SMB_OFF_T size=0;
1090         time_t mtime=0;
1091         const char *p;
1092         NTSTATUS status;
1093         TALLOC_CTX *ctx = talloc_tos();
1094         bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1095
1096         START_PROFILE(SMBgetatr);
1097
1098         p = (const char *)req->buf + 1;
1099         p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1100         if (!NT_STATUS_IS_OK(status)) {
1101                 reply_nterror(req, status);
1102                 goto out;
1103         }
1104
1105         /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1106                 under WfWg - weird! */
1107         if (*fname == '\0') {
1108                 mode = aHIDDEN | aDIR;
1109                 if (!CAN_WRITE(conn)) {
1110                         mode |= aRONLY;
1111                 }
1112                 size = 0;
1113                 mtime = 0;
1114         } else {
1115                 status = filename_convert(ctx,
1116                                 conn,
1117                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
1118                                 fname,
1119                                 0,
1120                                 NULL,
1121                                 &smb_fname);
1122                 if (!NT_STATUS_IS_OK(status)) {
1123                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1124                                 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1125                                                 ERRSRV, ERRbadpath);
1126                                 goto out;
1127                         }
1128                         reply_nterror(req, status);
1129                         goto out;
1130                 }
1131                 if (!VALID_STAT(smb_fname->st) &&
1132                     (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1133                         DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1134                                  smb_fname_str_dbg(smb_fname),
1135                                  strerror(errno)));
1136                         reply_nterror(req,  map_nt_error_from_unix(errno));
1137                         goto out;
1138                 }
1139
1140                 mode = dos_mode(conn, smb_fname);
1141                 size = smb_fname->st.st_ex_size;
1142
1143                 if (ask_sharemode) {
1144                         struct timespec write_time_ts;
1145                         struct file_id fileid;
1146
1147                         ZERO_STRUCT(write_time_ts);
1148                         fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1149                         get_file_infos(fileid, 0, NULL, &write_time_ts);
1150                         if (!null_timespec(write_time_ts)) {
1151                                 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1152                         }
1153                 }
1154
1155                 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1156                 if (mode & aDIR) {
1157                         size = 0;
1158                 }
1159         }
1160
1161         reply_outbuf(req, 10, 0);
1162
1163         SSVAL(req->outbuf,smb_vwv0,mode);
1164         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1165                 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1166         } else {
1167                 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1168         }
1169         SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1170
1171         if (get_Protocol() >= PROTOCOL_NT1) {
1172                 SSVAL(req->outbuf, smb_flg2,
1173                       SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1174         }
1175
1176         DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1177                  smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1178
1179  out:
1180         TALLOC_FREE(smb_fname);
1181         TALLOC_FREE(fname);
1182         END_PROFILE(SMBgetatr);
1183         return;
1184 }
1185
1186 /****************************************************************************
1187  Reply to a setatr.
1188 ****************************************************************************/
1189
1190 void reply_setatr(struct smb_request *req)
1191 {
1192         struct smb_file_time ft;
1193         connection_struct *conn = req->conn;
1194         struct smb_filename *smb_fname = NULL;
1195         char *fname = NULL;
1196         int mode;
1197         time_t mtime;
1198         const char *p;
1199         NTSTATUS status;
1200         TALLOC_CTX *ctx = talloc_tos();
1201
1202         START_PROFILE(SMBsetatr);
1203
1204         ZERO_STRUCT(ft);
1205
1206         if (req->wct < 2) {
1207                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1208                 goto out;
1209         }
1210
1211         p = (const char *)req->buf + 1;
1212         p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1213         if (!NT_STATUS_IS_OK(status)) {
1214                 reply_nterror(req, status);
1215                 goto out;
1216         }
1217
1218         status = filename_convert(ctx,
1219                                 conn,
1220                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
1221                                 fname,
1222                                 0,
1223                                 NULL,
1224                                 &smb_fname);
1225         if (!NT_STATUS_IS_OK(status)) {
1226                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1227                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1228                                         ERRSRV, ERRbadpath);
1229                         goto out;
1230                 }
1231                 reply_nterror(req, status);
1232                 goto out;
1233         }
1234
1235         if (smb_fname->base_name[0] == '.' &&
1236             smb_fname->base_name[1] == '\0') {
1237                 /*
1238                  * Not sure here is the right place to catch this
1239                  * condition. Might be moved to somewhere else later -- vl
1240                  */
1241                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1242                 goto out;
1243         }
1244
1245         mode = SVAL(req->vwv+0, 0);
1246         mtime = srv_make_unix_date3(req->vwv+1);
1247
1248         ft.mtime = convert_time_t_to_timespec(mtime);
1249         status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1250         if (!NT_STATUS_IS_OK(status)) {
1251                 reply_nterror(req, status);
1252                 goto out;
1253         }
1254
1255         if (mode != FILE_ATTRIBUTE_NORMAL) {
1256                 if (VALID_STAT_OF_DIR(smb_fname->st))
1257                         mode |= aDIR;
1258                 else
1259                         mode &= ~aDIR;
1260
1261                 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1262                                      false) != 0) {
1263                         reply_nterror(req, map_nt_error_from_unix(errno));
1264                         goto out;
1265                 }
1266         }
1267
1268         reply_outbuf(req, 0, 0);
1269
1270         DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1271                  mode));
1272  out:
1273         TALLOC_FREE(smb_fname);
1274         END_PROFILE(SMBsetatr);
1275         return;
1276 }
1277
1278 /****************************************************************************
1279  Reply to a dskattr.
1280 ****************************************************************************/
1281
1282 void reply_dskattr(struct smb_request *req)
1283 {
1284         connection_struct *conn = req->conn;
1285         uint64_t dfree,dsize,bsize;
1286         START_PROFILE(SMBdskattr);
1287
1288         if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1289                 reply_nterror(req, map_nt_error_from_unix(errno));
1290                 END_PROFILE(SMBdskattr);
1291                 return;
1292         }
1293
1294         reply_outbuf(req, 5, 0);
1295
1296         if (get_Protocol() <= PROTOCOL_LANMAN2) {
1297                 double total_space, free_space;
1298                 /* we need to scale this to a number that DOS6 can handle. We
1299                    use floating point so we can handle large drives on systems
1300                    that don't have 64 bit integers 
1301
1302                    we end up displaying a maximum of 2G to DOS systems
1303                 */
1304                 total_space = dsize * (double)bsize;
1305                 free_space = dfree * (double)bsize;
1306
1307                 dsize = (uint64_t)((total_space+63*512) / (64*512));
1308                 dfree = (uint64_t)((free_space+63*512) / (64*512));
1309
1310                 if (dsize > 0xFFFF) dsize = 0xFFFF;
1311                 if (dfree > 0xFFFF) dfree = 0xFFFF;
1312
1313                 SSVAL(req->outbuf,smb_vwv0,dsize);
1314                 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1315                 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1316                 SSVAL(req->outbuf,smb_vwv3,dfree);
1317         } else {
1318                 SSVAL(req->outbuf,smb_vwv0,dsize);
1319                 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1320                 SSVAL(req->outbuf,smb_vwv2,512);
1321                 SSVAL(req->outbuf,smb_vwv3,dfree);
1322         }
1323
1324         DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1325
1326         END_PROFILE(SMBdskattr);
1327         return;
1328 }
1329
1330 /*
1331  * Utility function to split the filename from the directory.
1332  */
1333 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1334                                      char **fname_dir_out,
1335                                      char **fname_mask_out)
1336 {
1337         const char *p = NULL;
1338         char *fname_dir = NULL;
1339         char *fname_mask = NULL;
1340
1341         p = strrchr_m(fname_in, '/');
1342         if (!p) {
1343                 fname_dir = talloc_strdup(ctx, ".");
1344                 fname_mask = talloc_strdup(ctx, fname_in);
1345         } else {
1346                 fname_dir = talloc_strndup(ctx, fname_in,
1347                     PTR_DIFF(p, fname_in));
1348                 fname_mask = talloc_strdup(ctx, p+1);
1349         }
1350
1351         if (!fname_dir || !fname_mask) {
1352                 TALLOC_FREE(fname_dir);
1353                 TALLOC_FREE(fname_mask);
1354                 return NT_STATUS_NO_MEMORY;
1355         }
1356
1357         *fname_dir_out = fname_dir;
1358         *fname_mask_out = fname_mask;
1359         return NT_STATUS_OK;
1360 }
1361
1362 /****************************************************************************
1363  Reply to a search.
1364  Can be called from SMBsearch, SMBffirst or SMBfunique.
1365 ****************************************************************************/
1366
1367 void reply_search(struct smb_request *req)
1368 {
1369         connection_struct *conn = req->conn;
1370         char *path = NULL;
1371         const char *mask = NULL;
1372         char *directory = NULL;
1373         struct smb_filename *smb_fname = NULL;
1374         char *fname = NULL;
1375         SMB_OFF_T size;
1376         uint32 mode;
1377         struct timespec date;
1378         uint32 dirtype;
1379         unsigned int numentries = 0;
1380         unsigned int maxentries = 0;
1381         bool finished = False;
1382         const char *p;
1383         int status_len;
1384         char status[21];
1385         int dptr_num= -1;
1386         bool check_descend = False;
1387         bool expect_close = False;
1388         NTSTATUS nt_status;
1389         bool mask_contains_wcard = False;
1390         bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1391         TALLOC_CTX *ctx = talloc_tos();
1392         bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1393         struct dptr_struct *dirptr = NULL;
1394         struct smbd_server_connection *sconn = req->sconn;
1395
1396         START_PROFILE(SMBsearch);
1397
1398         if (req->wct < 2) {
1399                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1400                 goto out;
1401         }
1402
1403         if (lp_posix_pathnames()) {
1404                 reply_unknown_new(req, req->cmd);
1405                 goto out;
1406         }
1407
1408         /* If we were called as SMBffirst then we must expect close. */
1409         if(req->cmd == SMBffirst) {
1410                 expect_close = True;
1411         }
1412
1413         reply_outbuf(req, 1, 3);
1414         maxentries = SVAL(req->vwv+0, 0);
1415         dirtype = SVAL(req->vwv+1, 0);
1416         p = (const char *)req->buf + 1;
1417         p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1418                                        &nt_status, &mask_contains_wcard);
1419         if (!NT_STATUS_IS_OK(nt_status)) {
1420                 reply_nterror(req, nt_status);
1421                 goto out;
1422         }
1423
1424         p++;
1425         status_len = SVAL(p, 0);
1426         p += 2;
1427
1428         /* dirtype &= ~aDIR; */
1429
1430         if (status_len == 0) {
1431                 nt_status = filename_convert(ctx, conn,
1432                                              req->flags2 & FLAGS2_DFS_PATHNAMES,
1433                                              path,
1434                                              UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1435                                              &mask_contains_wcard,
1436                                              &smb_fname);
1437                 if (!NT_STATUS_IS_OK(nt_status)) {
1438                         if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1439                                 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1440                                                 ERRSRV, ERRbadpath);
1441                                 goto out;
1442                         }
1443                         reply_nterror(req, nt_status);
1444                         goto out;
1445                 }
1446
1447                 directory = smb_fname->base_name;
1448
1449                 p = strrchr_m(directory,'/');
1450                 if ((p != NULL) && (*directory != '/')) {
1451                         mask = p + 1;
1452                         directory = talloc_strndup(ctx, directory,
1453                                                    PTR_DIFF(p, directory));
1454                 } else {
1455                         mask = directory;
1456                         directory = talloc_strdup(ctx,".");
1457                 }
1458
1459                 if (!directory) {
1460                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1461                         goto out;
1462                 }
1463
1464                 memset((char *)status,'\0',21);
1465                 SCVAL(status,0,(dirtype & 0x1F));
1466
1467                 nt_status = dptr_create(conn,
1468                                         NULL, /* fsp */
1469                                         directory,
1470                                         True,
1471                                         expect_close,
1472                                         req->smbpid,
1473                                         mask,
1474                                         mask_contains_wcard,
1475                                         dirtype,
1476                                         &dirptr);
1477                 if (!NT_STATUS_IS_OK(nt_status)) {
1478                         reply_nterror(req, nt_status);
1479                         goto out;
1480                 }
1481                 dptr_num = dptr_dnum(dirptr);
1482         } else {
1483                 int status_dirtype;
1484                 const char *dirpath;
1485
1486                 memcpy(status,p,21);
1487                 status_dirtype = CVAL(status,0) & 0x1F;
1488                 if (status_dirtype != (dirtype & 0x1F)) {
1489                         dirtype = status_dirtype;
1490                 }
1491
1492                 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1493                 if (!dirptr) {
1494                         goto SearchEmpty;
1495                 }
1496                 dirpath = dptr_path(sconn, dptr_num);
1497                 directory = talloc_strdup(ctx, dirpath);
1498                 if (!directory) {
1499                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1500                         goto out;
1501                 }
1502
1503                 mask = dptr_wcard(sconn, dptr_num);
1504                 if (!mask) {
1505                         goto SearchEmpty;
1506                 }
1507                 /*
1508                  * For a 'continue' search we have no string. So
1509                  * check from the initial saved string.
1510                  */
1511                 mask_contains_wcard = ms_has_wild(mask);
1512                 dirtype = dptr_attr(sconn, dptr_num);
1513         }
1514
1515         DEBUG(4,("dptr_num is %d\n",dptr_num));
1516
1517         /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1518         dptr_init_search_op(dirptr);
1519
1520         if ((dirtype&0x1F) == aVOLID) {
1521                 char buf[DIR_STRUCT_SIZE];
1522                 memcpy(buf,status,21);
1523                 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1524                                 0,aVOLID,0,!allow_long_path_components)) {
1525                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1526                         goto out;
1527                 }
1528                 dptr_fill(sconn, buf+12,dptr_num);
1529                 if (dptr_zero(buf+12) && (status_len==0)) {
1530                         numentries = 1;
1531                 } else {
1532                         numentries = 0;
1533                 }
1534                 if (message_push_blob(&req->outbuf,
1535                                       data_blob_const(buf, sizeof(buf)))
1536                     == -1) {
1537                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1538                         goto out;
1539                 }
1540         } else {
1541                 unsigned int i;
1542                 maxentries = MIN(
1543                         maxentries,
1544                         ((BUFFER_SIZE -
1545                           ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1546                          /DIR_STRUCT_SIZE));
1547
1548                 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1549                         directory,lp_dontdescend(SNUM(conn))));
1550                 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1551                         check_descend = True;
1552                 }
1553
1554                 for (i=numentries;(i<maxentries) && !finished;i++) {
1555                         finished = !get_dir_entry(ctx,
1556                                                   dirptr,
1557                                                   mask,
1558                                                   dirtype,
1559                                                   &fname,
1560                                                   &size,
1561                                                   &mode,
1562                                                   &date,
1563                                                   check_descend,
1564                                                   ask_sharemode);
1565                         if (!finished) {
1566                                 char buf[DIR_STRUCT_SIZE];
1567                                 memcpy(buf,status,21);
1568                                 if (!make_dir_struct(ctx,
1569                                                 buf,
1570                                                 mask,
1571                                                 fname,
1572                                                 size,
1573                                                 mode,
1574                                                 convert_timespec_to_time_t(date),
1575                                                 !allow_long_path_components)) {
1576                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1577                                         goto out;
1578                                 }
1579                                 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1580                                         break;
1581                                 }
1582                                 if (message_push_blob(&req->outbuf,
1583                                                       data_blob_const(buf, sizeof(buf)))
1584                                     == -1) {
1585                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1586                                         goto out;
1587                                 }
1588                                 numentries++;
1589                         }
1590                 }
1591         }
1592
1593   SearchEmpty:
1594
1595         /* If we were called as SMBffirst with smb_search_id == NULL
1596                 and no entries were found then return error and close dirptr 
1597                 (X/Open spec) */
1598
1599         if (numentries == 0) {
1600                 dptr_close(sconn, &dptr_num);
1601         } else if(expect_close && status_len == 0) {
1602                 /* Close the dptr - we know it's gone */
1603                 dptr_close(sconn, &dptr_num);
1604         }
1605
1606         /* If we were called as SMBfunique, then we can close the dirptr now ! */
1607         if(dptr_num >= 0 && req->cmd == SMBfunique) {
1608                 dptr_close(sconn, &dptr_num);
1609         }
1610
1611         if ((numentries == 0) && !mask_contains_wcard) {
1612                 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1613                 goto out;
1614         }
1615
1616         SSVAL(req->outbuf,smb_vwv0,numentries);
1617         SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1618         SCVAL(smb_buf(req->outbuf),0,5);
1619         SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1620
1621         /* The replies here are never long name. */
1622         SSVAL(req->outbuf, smb_flg2,
1623               SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1624         if (!allow_long_path_components) {
1625                 SSVAL(req->outbuf, smb_flg2,
1626                       SVAL(req->outbuf, smb_flg2)
1627                       & (~FLAGS2_LONG_PATH_COMPONENTS));
1628         }
1629
1630         /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1631         SSVAL(req->outbuf, smb_flg2,
1632               (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1633
1634         DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1635                 smb_fn_name(req->cmd),
1636                 mask,
1637                 directory,
1638                 dirtype,
1639                 numentries,
1640                 maxentries ));
1641  out:
1642         TALLOC_FREE(directory);
1643         TALLOC_FREE(smb_fname);
1644         END_PROFILE(SMBsearch);
1645         return;
1646 }
1647
1648 /****************************************************************************
1649  Reply to a fclose (stop directory search).
1650 ****************************************************************************/
1651
1652 void reply_fclose(struct smb_request *req)
1653 {
1654         int status_len;
1655         char status[21];
1656         int dptr_num= -2;
1657         const char *p;
1658         char *path = NULL;
1659         NTSTATUS err;
1660         bool path_contains_wcard = False;
1661         TALLOC_CTX *ctx = talloc_tos();
1662         struct smbd_server_connection *sconn = req->sconn;
1663
1664         START_PROFILE(SMBfclose);
1665
1666         if (lp_posix_pathnames()) {
1667                 reply_unknown_new(req, req->cmd);
1668                 END_PROFILE(SMBfclose);
1669                 return;
1670         }
1671
1672         p = (const char *)req->buf + 1;
1673         p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1674                                        &err, &path_contains_wcard);
1675         if (!NT_STATUS_IS_OK(err)) {
1676                 reply_nterror(req, err);
1677                 END_PROFILE(SMBfclose);
1678                 return;
1679         }
1680         p++;
1681         status_len = SVAL(p,0);
1682         p += 2;
1683
1684         if (status_len == 0) {
1685                 reply_force_doserror(req, ERRSRV, ERRsrverror);
1686                 END_PROFILE(SMBfclose);
1687                 return;
1688         }
1689
1690         memcpy(status,p,21);
1691
1692         if(dptr_fetch(sconn, status+12,&dptr_num)) {
1693                 /*  Close the dptr - we know it's gone */
1694                 dptr_close(sconn, &dptr_num);
1695         }
1696
1697         reply_outbuf(req, 1, 0);
1698         SSVAL(req->outbuf,smb_vwv0,0);
1699
1700         DEBUG(3,("search close\n"));
1701
1702         END_PROFILE(SMBfclose);
1703         return;
1704 }
1705
1706 /****************************************************************************
1707  Reply to an open.
1708 ****************************************************************************/
1709
1710 void reply_open(struct smb_request *req)
1711 {
1712         connection_struct *conn = req->conn;
1713         struct smb_filename *smb_fname = NULL;
1714         char *fname = NULL;
1715         uint32 fattr=0;
1716         SMB_OFF_T size = 0;
1717         time_t mtime=0;
1718         int info;
1719         files_struct *fsp;
1720         int oplock_request;
1721         int deny_mode;
1722         uint32 dos_attr;
1723         uint32 access_mask;
1724         uint32 share_mode;
1725         uint32 create_disposition;
1726         uint32 create_options = 0;
1727         uint32_t private_flags = 0;
1728         NTSTATUS status;
1729         bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1730         TALLOC_CTX *ctx = talloc_tos();
1731
1732         START_PROFILE(SMBopen);
1733
1734         if (req->wct < 2) {
1735                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1736                 goto out;
1737         }
1738
1739         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1740         deny_mode = SVAL(req->vwv+0, 0);
1741         dos_attr = SVAL(req->vwv+1, 0);
1742
1743         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1744                             STR_TERMINATE, &status);
1745         if (!NT_STATUS_IS_OK(status)) {
1746                 reply_nterror(req, status);
1747                 goto out;
1748         }
1749
1750         status = filename_convert(ctx,
1751                                 conn,
1752                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
1753                                 fname,
1754                                 0,
1755                                 NULL,
1756                                 &smb_fname);
1757         if (!NT_STATUS_IS_OK(status)) {
1758                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1759                         reply_botherror(req,
1760                                         NT_STATUS_PATH_NOT_COVERED,
1761                                         ERRSRV, ERRbadpath);
1762                         goto out;
1763                 }
1764                 reply_nterror(req, status);
1765                 goto out;
1766         }
1767
1768         if (!map_open_params_to_ntcreate(smb_fname, deny_mode,
1769                                          OPENX_FILE_EXISTS_OPEN, &access_mask,
1770                                          &share_mode, &create_disposition,
1771                                          &create_options, &private_flags)) {
1772                 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1773                 goto out;
1774         }
1775
1776         status = SMB_VFS_CREATE_FILE(
1777                 conn,                                   /* conn */
1778                 req,                                    /* req */
1779                 0,                                      /* root_dir_fid */
1780                 smb_fname,                              /* fname */
1781                 access_mask,                            /* access_mask */
1782                 share_mode,                             /* share_access */
1783                 create_disposition,                     /* create_disposition*/
1784                 create_options,                         /* create_options */
1785                 dos_attr,                               /* file_attributes */
1786                 oplock_request,                         /* oplock_request */
1787                 0,                                      /* allocation_size */
1788                 private_flags,
1789                 NULL,                                   /* sd */
1790                 NULL,                                   /* ea_list */
1791                 &fsp,                                   /* result */
1792                 &info);                                 /* pinfo */
1793
1794         if (!NT_STATUS_IS_OK(status)) {
1795                 if (open_was_deferred(req->mid)) {
1796                         /* We have re-scheduled this call. */
1797                         goto out;
1798                 }
1799                 reply_openerror(req, status);
1800                 goto out;
1801         }
1802
1803         size = smb_fname->st.st_ex_size;
1804         fattr = dos_mode(conn, smb_fname);
1805
1806         /* Deal with other possible opens having a modified
1807            write time. JRA. */
1808         if (ask_sharemode) {
1809                 struct timespec write_time_ts;
1810
1811                 ZERO_STRUCT(write_time_ts);
1812                 get_file_infos(fsp->file_id, 0, NULL, &write_time_ts);
1813                 if (!null_timespec(write_time_ts)) {
1814                         update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1815                 }
1816         }
1817
1818         mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1819
1820         if (fattr & aDIR) {
1821                 DEBUG(3,("attempt to open a directory %s\n",
1822                          fsp_str_dbg(fsp)));
1823                 close_file(req, fsp, ERROR_CLOSE);
1824                 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1825                         ERRDOS, ERRnoaccess);
1826                 goto out;
1827         }
1828
1829         reply_outbuf(req, 7, 0);
1830         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1831         SSVAL(req->outbuf,smb_vwv1,fattr);
1832         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1833                 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1834         } else {
1835                 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1836         }
1837         SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1838         SSVAL(req->outbuf,smb_vwv6,deny_mode);
1839
1840         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1841                 SCVAL(req->outbuf,smb_flg,
1842                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1843         }
1844
1845         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1846                 SCVAL(req->outbuf,smb_flg,
1847                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1848         }
1849  out:
1850         TALLOC_FREE(smb_fname);
1851         END_PROFILE(SMBopen);
1852         return;
1853 }
1854
1855 /****************************************************************************
1856  Reply to an open and X.
1857 ****************************************************************************/
1858
1859 void reply_open_and_X(struct smb_request *req)
1860 {
1861         connection_struct *conn = req->conn;
1862         struct smb_filename *smb_fname = NULL;
1863         char *fname = NULL;
1864         uint16 open_flags;
1865         int deny_mode;
1866         uint32 smb_attr;
1867         /* Breakout the oplock request bits so we can set the
1868                 reply bits separately. */
1869         int ex_oplock_request;
1870         int core_oplock_request;
1871         int oplock_request;
1872 #if 0
1873         int smb_sattr = SVAL(req->vwv+4, 0);
1874         uint32 smb_time = make_unix_date3(req->vwv+6);
1875 #endif
1876         int smb_ofun;
1877         uint32 fattr=0;
1878         int mtime=0;
1879         int smb_action = 0;
1880         files_struct *fsp;
1881         NTSTATUS status;
1882         uint64_t allocation_size;
1883         ssize_t retval = -1;
1884         uint32 access_mask;
1885         uint32 share_mode;
1886         uint32 create_disposition;
1887         uint32 create_options = 0;
1888         uint32_t private_flags = 0;
1889         TALLOC_CTX *ctx = talloc_tos();
1890
1891         START_PROFILE(SMBopenX);
1892
1893         if (req->wct < 15) {
1894                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1895                 goto out;
1896         }
1897
1898         open_flags = SVAL(req->vwv+2, 0);
1899         deny_mode = SVAL(req->vwv+3, 0);
1900         smb_attr = SVAL(req->vwv+5, 0);
1901         ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1902         core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1903         oplock_request = ex_oplock_request | core_oplock_request;
1904         smb_ofun = SVAL(req->vwv+8, 0);
1905         allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1906
1907         /* If it's an IPC, pass off the pipe handler. */
1908         if (IS_IPC(conn)) {
1909                 if (lp_nt_pipe_support()) {
1910                         reply_open_pipe_and_X(conn, req);
1911                 } else {
1912                         reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1913                 }
1914                 goto out;
1915         }
1916
1917         /* XXXX we need to handle passed times, sattr and flags */
1918         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1919                         STR_TERMINATE, &status);
1920         if (!NT_STATUS_IS_OK(status)) {
1921                 reply_nterror(req, status);
1922                 goto out;
1923         }
1924
1925         status = filename_convert(ctx,
1926                                 conn,
1927                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
1928                                 fname,
1929                                 0,
1930                                 NULL,
1931                                 &smb_fname);
1932         if (!NT_STATUS_IS_OK(status)) {
1933                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1934                         reply_botherror(req,
1935                                         NT_STATUS_PATH_NOT_COVERED,
1936                                         ERRSRV, ERRbadpath);
1937                         goto out;
1938                 }
1939                 reply_nterror(req, status);
1940                 goto out;
1941         }
1942
1943         if (!map_open_params_to_ntcreate(smb_fname, deny_mode, smb_ofun,
1944                                          &access_mask, &share_mode,
1945                                          &create_disposition,
1946                                          &create_options,
1947                                          &private_flags)) {
1948                 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1949                 goto out;
1950         }
1951
1952         status = SMB_VFS_CREATE_FILE(
1953                 conn,                                   /* conn */
1954                 req,                                    /* req */
1955                 0,                                      /* root_dir_fid */
1956                 smb_fname,                              /* fname */
1957                 access_mask,                            /* access_mask */
1958                 share_mode,                             /* share_access */
1959                 create_disposition,                     /* create_disposition*/
1960                 create_options,                         /* create_options */
1961                 smb_attr,                               /* file_attributes */
1962                 oplock_request,                         /* oplock_request */
1963                 0,                                      /* allocation_size */
1964                 private_flags,
1965                 NULL,                                   /* sd */
1966                 NULL,                                   /* ea_list */
1967                 &fsp,                                   /* result */
1968                 &smb_action);                           /* pinfo */
1969
1970         if (!NT_STATUS_IS_OK(status)) {
1971                 if (open_was_deferred(req->mid)) {
1972                         /* We have re-scheduled this call. */
1973                         goto out;
1974                 }
1975                 reply_openerror(req, status);
1976                 goto out;
1977         }
1978
1979         /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1980            if the file is truncated or created. */
1981         if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1982                 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1983                 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1984                         close_file(req, fsp, ERROR_CLOSE);
1985                         reply_nterror(req, NT_STATUS_DISK_FULL);
1986                         goto out;
1987                 }
1988                 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1989                 if (retval < 0) {
1990                         close_file(req, fsp, ERROR_CLOSE);
1991                         reply_nterror(req, NT_STATUS_DISK_FULL);
1992                         goto out;
1993                 }
1994                 status = vfs_stat_fsp(fsp);
1995                 if (!NT_STATUS_IS_OK(status)) {
1996                         close_file(req, fsp, ERROR_CLOSE);
1997                         reply_nterror(req, status);
1998                         goto out;
1999                 }
2000         }
2001
2002         fattr = dos_mode(conn, fsp->fsp_name);
2003         mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2004         if (fattr & aDIR) {
2005                 close_file(req, fsp, ERROR_CLOSE);
2006                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2007                 goto out;
2008         }
2009
2010         /* If the caller set the extended oplock request bit
2011                 and we granted one (by whatever means) - set the
2012                 correct bit for extended oplock reply.
2013         */
2014
2015         if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2016                 smb_action |= EXTENDED_OPLOCK_GRANTED;
2017         }
2018
2019         if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2020                 smb_action |= EXTENDED_OPLOCK_GRANTED;
2021         }
2022
2023         /* If the caller set the core oplock request bit
2024                 and we granted one (by whatever means) - set the
2025                 correct bit for core oplock reply.
2026         */
2027
2028         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2029                 reply_outbuf(req, 19, 0);
2030         } else {
2031                 reply_outbuf(req, 15, 0);
2032         }
2033
2034         if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2035                 SCVAL(req->outbuf, smb_flg,
2036                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2037         }
2038
2039         if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2040                 SCVAL(req->outbuf, smb_flg,
2041                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2042         }
2043
2044         SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2045         SSVAL(req->outbuf,smb_vwv3,fattr);
2046         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2047                 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2048         } else {
2049                 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2050         }
2051         SIVAL(req->outbuf,smb_vwv6,(uint32)fsp->fsp_name->st.st_ex_size);
2052         SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2053         SSVAL(req->outbuf,smb_vwv11,smb_action);
2054
2055         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2056                 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2057         }
2058
2059         chain_reply(req);
2060  out:
2061         TALLOC_FREE(smb_fname);
2062         END_PROFILE(SMBopenX);
2063         return;
2064 }
2065
2066 /****************************************************************************
2067  Reply to a SMBulogoffX.
2068 ****************************************************************************/
2069
2070 void reply_ulogoffX(struct smb_request *req)
2071 {
2072         struct smbd_server_connection *sconn = req->sconn;
2073         user_struct *vuser;
2074
2075         START_PROFILE(SMBulogoffX);
2076
2077         vuser = get_valid_user_struct(sconn, req->vuid);
2078
2079         if(vuser == NULL) {
2080                 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2081                          req->vuid));
2082         }
2083
2084         /* in user level security we are supposed to close any files
2085                 open by this user */
2086         if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2087                 file_close_user(sconn, req->vuid);
2088         }
2089
2090         invalidate_vuid(sconn, req->vuid);
2091
2092         reply_outbuf(req, 2, 0);
2093
2094         DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2095
2096         END_PROFILE(SMBulogoffX);
2097         req->vuid = UID_FIELD_INVALID;
2098         chain_reply(req);
2099 }
2100
2101 /****************************************************************************
2102  Reply to a mknew or a create.
2103 ****************************************************************************/
2104
2105 void reply_mknew(struct smb_request *req)
2106 {
2107         connection_struct *conn = req->conn;
2108         struct smb_filename *smb_fname = NULL;
2109         char *fname = NULL;
2110         uint32 fattr = 0;
2111         struct smb_file_time ft;
2112         files_struct *fsp;
2113         int oplock_request = 0;
2114         NTSTATUS status;
2115         uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2116         uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2117         uint32 create_disposition;
2118         uint32 create_options = 0;
2119         TALLOC_CTX *ctx = talloc_tos();
2120
2121         START_PROFILE(SMBcreate);
2122         ZERO_STRUCT(ft);
2123
2124         if (req->wct < 3) {
2125                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2126                 goto out;
2127         }
2128
2129         fattr = SVAL(req->vwv+0, 0);
2130         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2131
2132         /* mtime. */
2133         ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2134
2135         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2136                             STR_TERMINATE, &status);
2137         if (!NT_STATUS_IS_OK(status)) {
2138                 reply_nterror(req, status);
2139                 goto out;
2140         }
2141
2142         status = filename_convert(ctx,
2143                                 conn,
2144                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
2145                                 fname,
2146                                 0,
2147                                 NULL,
2148                                 &smb_fname);
2149         if (!NT_STATUS_IS_OK(status)) {
2150                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2151                         reply_botherror(req,
2152                                         NT_STATUS_PATH_NOT_COVERED,
2153                                         ERRSRV, ERRbadpath);
2154                         goto out;
2155                 }
2156                 reply_nterror(req, status);
2157                 goto out;
2158         }
2159
2160         if (fattr & aVOLID) {
2161                 DEBUG(0,("Attempt to create file (%s) with volid set - "
2162                          "please report this\n",
2163                          smb_fname_str_dbg(smb_fname)));
2164         }
2165
2166         if(req->cmd == SMBmknew) {
2167                 /* We should fail if file exists. */
2168                 create_disposition = FILE_CREATE;
2169         } else {
2170                 /* Create if file doesn't exist, truncate if it does. */
2171                 create_disposition = FILE_OVERWRITE_IF;
2172         }
2173
2174         status = SMB_VFS_CREATE_FILE(
2175                 conn,                                   /* conn */
2176                 req,                                    /* req */
2177                 0,                                      /* root_dir_fid */
2178                 smb_fname,                              /* fname */
2179                 access_mask,                            /* access_mask */
2180                 share_mode,                             /* share_access */
2181                 create_disposition,                     /* create_disposition*/
2182                 create_options,                         /* create_options */
2183                 fattr,                                  /* file_attributes */
2184                 oplock_request,                         /* oplock_request */
2185                 0,                                      /* allocation_size */
2186                 0,                                      /* private_flags */
2187                 NULL,                                   /* sd */
2188                 NULL,                                   /* ea_list */
2189                 &fsp,                                   /* result */
2190                 NULL);                                  /* pinfo */
2191
2192         if (!NT_STATUS_IS_OK(status)) {
2193                 if (open_was_deferred(req->mid)) {
2194                         /* We have re-scheduled this call. */
2195                         goto out;
2196                 }
2197                 reply_openerror(req, status);
2198                 goto out;
2199         }
2200
2201         ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2202         status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2203         if (!NT_STATUS_IS_OK(status)) {
2204                 END_PROFILE(SMBcreate);
2205                 goto out;
2206         }
2207
2208         reply_outbuf(req, 1, 0);
2209         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2210
2211         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2212                 SCVAL(req->outbuf,smb_flg,
2213                                 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2214         }
2215
2216         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2217                 SCVAL(req->outbuf,smb_flg,
2218                                 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2219         }
2220
2221         DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2222         DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2223                   smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2224                   (unsigned int)fattr));
2225
2226  out:
2227         TALLOC_FREE(smb_fname);
2228         END_PROFILE(SMBcreate);
2229         return;
2230 }
2231
2232 /****************************************************************************
2233  Reply to a create temporary file.
2234 ****************************************************************************/
2235
2236 void reply_ctemp(struct smb_request *req)
2237 {
2238         connection_struct *conn = req->conn;
2239         struct smb_filename *smb_fname = NULL;
2240         char *fname = NULL;
2241         uint32 fattr;
2242         files_struct *fsp;
2243         int oplock_request;
2244         int tmpfd;
2245         char *s;
2246         NTSTATUS status;
2247         TALLOC_CTX *ctx = talloc_tos();
2248
2249         START_PROFILE(SMBctemp);
2250
2251         if (req->wct < 3) {
2252                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2253                 goto out;
2254         }
2255
2256         fattr = SVAL(req->vwv+0, 0);
2257         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2258
2259         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2260                             STR_TERMINATE, &status);
2261         if (!NT_STATUS_IS_OK(status)) {
2262                 reply_nterror(req, status);
2263                 goto out;
2264         }
2265         if (*fname) {
2266                 fname = talloc_asprintf(ctx,
2267                                 "%s/TMXXXXXX",
2268                                 fname);
2269         } else {
2270                 fname = talloc_strdup(ctx, "TMXXXXXX");
2271         }
2272
2273         if (!fname) {
2274                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2275                 goto out;
2276         }
2277
2278         status = filename_convert(ctx, conn,
2279                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
2280                                 fname,
2281                                 0,
2282                                 NULL,
2283                                 &smb_fname);
2284         if (!NT_STATUS_IS_OK(status)) {
2285                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2286                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2287                                         ERRSRV, ERRbadpath);
2288                         goto out;
2289                 }
2290                 reply_nterror(req, status);
2291                 goto out;
2292         }
2293
2294         tmpfd = mkstemp(smb_fname->base_name);
2295         if (tmpfd == -1) {
2296                 reply_nterror(req, map_nt_error_from_unix(errno));
2297                 goto out;
2298         }
2299
2300         SMB_VFS_STAT(conn, smb_fname);
2301
2302         /* We should fail if file does not exist. */
2303         status = SMB_VFS_CREATE_FILE(
2304                 conn,                                   /* conn */
2305                 req,                                    /* req */
2306                 0,                                      /* root_dir_fid */
2307                 smb_fname,                              /* fname */
2308                 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2309                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
2310                 FILE_OPEN,                              /* create_disposition*/
2311                 0,                                      /* create_options */
2312                 fattr,                                  /* file_attributes */
2313                 oplock_request,                         /* oplock_request */
2314                 0,                                      /* allocation_size */
2315                 0,                                      /* private_flags */
2316                 NULL,                                   /* sd */
2317                 NULL,                                   /* ea_list */
2318                 &fsp,                                   /* result */
2319                 NULL);                                  /* pinfo */
2320
2321         /* close fd from mkstemp() */
2322         close(tmpfd);
2323
2324         if (!NT_STATUS_IS_OK(status)) {
2325                 if (open_was_deferred(req->mid)) {
2326                         /* We have re-scheduled this call. */
2327                         goto out;
2328                 }
2329                 reply_openerror(req, status);
2330                 goto out;
2331         }
2332
2333         reply_outbuf(req, 1, 0);
2334         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2335
2336         /* the returned filename is relative to the directory */
2337         s = strrchr_m(fsp->fsp_name->base_name, '/');
2338         if (!s) {
2339                 s = fsp->fsp_name->base_name;
2340         } else {
2341                 s++;
2342         }
2343
2344 #if 0
2345         /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2346            thing in the byte section. JRA */
2347         SSVALS(p, 0, -1); /* what is this? not in spec */
2348 #endif
2349         if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2350             == -1) {
2351                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2352                 goto out;
2353         }
2354
2355         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2356                 SCVAL(req->outbuf, smb_flg,
2357                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2358         }
2359
2360         if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2361                 SCVAL(req->outbuf, smb_flg,
2362                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2363         }
2364
2365         DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2366         DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2367                     fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2368  out:
2369         TALLOC_FREE(smb_fname);
2370         END_PROFILE(SMBctemp);
2371         return;
2372 }
2373
2374 /*******************************************************************
2375  Check if a user is allowed to rename a file.
2376 ********************************************************************/
2377
2378 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2379                         uint16 dirtype)
2380 {
2381         uint32 fmode;
2382
2383         if (!CAN_WRITE(conn)) {
2384                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2385         }
2386
2387         fmode = dos_mode(conn, fsp->fsp_name);
2388         if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2389                 return NT_STATUS_NO_SUCH_FILE;
2390         }
2391
2392         if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2393                 if (fsp->posix_open) {
2394                         return NT_STATUS_OK;
2395                 }
2396
2397                 /* If no pathnames are open below this
2398                    directory, allow the rename. */
2399
2400                 if (file_find_subpath(fsp)) {
2401                         return NT_STATUS_ACCESS_DENIED;
2402                 }
2403                 return NT_STATUS_OK;
2404         }
2405
2406         if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2407                 return NT_STATUS_OK;
2408         }
2409
2410         return NT_STATUS_ACCESS_DENIED;
2411 }
2412
2413 /*******************************************************************
2414  * unlink a file with all relevant access checks
2415  *******************************************************************/
2416
2417 static NTSTATUS do_unlink(connection_struct *conn,
2418                         struct smb_request *req,
2419                         struct smb_filename *smb_fname,
2420                         uint32 dirtype)
2421 {
2422         uint32 fattr;
2423         files_struct *fsp;
2424         uint32 dirtype_orig = dirtype;
2425         NTSTATUS status;
2426         int ret;
2427         bool posix_paths = lp_posix_pathnames();
2428
2429         DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2430                   smb_fname_str_dbg(smb_fname),
2431                   dirtype));
2432
2433         if (!CAN_WRITE(conn)) {
2434                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2435         }
2436
2437         if (posix_paths) {
2438                 ret = SMB_VFS_LSTAT(conn, smb_fname);
2439         } else {
2440                 ret = SMB_VFS_STAT(conn, smb_fname);
2441         }
2442         if (ret != 0) {
2443                 return map_nt_error_from_unix(errno);
2444         }
2445
2446         fattr = dos_mode(conn, smb_fname);
2447
2448         if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2449                 dirtype = aDIR|aARCH|aRONLY;
2450         }
2451
2452         dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2453         if (!dirtype) {
2454                 return NT_STATUS_NO_SUCH_FILE;
2455         }
2456
2457         if (!dir_check_ftype(conn, fattr, dirtype)) {
2458                 if (fattr & aDIR) {
2459                         return NT_STATUS_FILE_IS_A_DIRECTORY;
2460                 }
2461                 return NT_STATUS_NO_SUCH_FILE;
2462         }
2463
2464         if (dirtype_orig & 0x8000) {
2465                 /* These will never be set for POSIX. */
2466                 return NT_STATUS_NO_SUCH_FILE;
2467         }
2468
2469 #if 0
2470         if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2471                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2472         }
2473
2474         if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2475                 return NT_STATUS_NO_SUCH_FILE;
2476         }
2477
2478         if (dirtype & 0xFF00) {
2479                 /* These will never be set for POSIX. */
2480                 return NT_STATUS_NO_SUCH_FILE;
2481         }
2482
2483         dirtype &= 0xFF;
2484         if (!dirtype) {
2485                 return NT_STATUS_NO_SUCH_FILE;
2486         }
2487
2488         /* Can't delete a directory. */
2489         if (fattr & aDIR) {
2490                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2491         }
2492 #endif
2493
2494 #if 0 /* JRATEST */
2495         else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2496                 return NT_STATUS_OBJECT_NAME_INVALID;
2497 #endif /* JRATEST */
2498
2499         /* On open checks the open itself will check the share mode, so
2500            don't do it here as we'll get it wrong. */
2501
2502         status = SMB_VFS_CREATE_FILE
2503                 (conn,                  /* conn */
2504                  req,                   /* req */
2505                  0,                     /* root_dir_fid */
2506                  smb_fname,             /* fname */
2507                  DELETE_ACCESS,         /* access_mask */
2508                  FILE_SHARE_NONE,       /* share_access */
2509                  FILE_OPEN,             /* create_disposition*/
2510                  FILE_NON_DIRECTORY_FILE, /* create_options */
2511                                         /* file_attributes */
2512                  posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2513                                 FILE_ATTRIBUTE_NORMAL,
2514                  0,                     /* oplock_request */
2515                  0,                     /* allocation_size */
2516                  0,                     /* private_flags */
2517                  NULL,                  /* sd */
2518                  NULL,                  /* ea_list */
2519                  &fsp,                  /* result */
2520                  NULL);                 /* pinfo */
2521
2522         if (!NT_STATUS_IS_OK(status)) {
2523                 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2524                            nt_errstr(status)));
2525                 return status;
2526         }
2527
2528         status = can_set_delete_on_close(fsp, fattr);
2529         if (!NT_STATUS_IS_OK(status)) {
2530                 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2531                         "(%s)\n",
2532                         smb_fname_str_dbg(smb_fname),
2533                         nt_errstr(status)));
2534                 close_file(req, fsp, NORMAL_CLOSE);
2535                 return status;
2536         }
2537
2538         /* The set is across all open files on this dev/inode pair. */
2539         if (!set_delete_on_close(fsp, True, &conn->session_info->utok)) {
2540                 close_file(req, fsp, NORMAL_CLOSE);
2541                 return NT_STATUS_ACCESS_DENIED;
2542         }
2543
2544         return close_file(req, fsp, NORMAL_CLOSE);
2545 }
2546
2547 /****************************************************************************
2548  The guts of the unlink command, split out so it may be called by the NT SMB
2549  code.
2550 ****************************************************************************/
2551
2552 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2553                           uint32 dirtype, struct smb_filename *smb_fname,
2554                           bool has_wild)
2555 {
2556         char *fname_dir = NULL;
2557         char *fname_mask = NULL;
2558         int count=0;
2559         NTSTATUS status = NT_STATUS_OK;
2560         TALLOC_CTX *ctx = talloc_tos();
2561
2562         /* Split up the directory from the filename/mask. */
2563         status = split_fname_dir_mask(ctx, smb_fname->base_name,
2564                                       &fname_dir, &fname_mask);
2565         if (!NT_STATUS_IS_OK(status)) {
2566                 goto out;
2567         }
2568
2569         /*
2570          * We should only check the mangled cache
2571          * here if unix_convert failed. This means
2572          * that the path in 'mask' doesn't exist
2573          * on the file system and so we need to look
2574          * for a possible mangle. This patch from
2575          * Tine Smukavec <valentin.smukavec@hermes.si>.
2576          */
2577
2578         if (!VALID_STAT(smb_fname->st) &&
2579             mangle_is_mangled(fname_mask, conn->params)) {
2580                 char *new_mask = NULL;
2581                 mangle_lookup_name_from_8_3(ctx, fname_mask,
2582                                             &new_mask, conn->params);
2583                 if (new_mask) {
2584                         TALLOC_FREE(fname_mask);
2585                         fname_mask = new_mask;
2586                 }
2587         }
2588
2589         if (!has_wild) {
2590
2591                 /*
2592                  * Only one file needs to be unlinked. Append the mask back
2593                  * onto the directory.
2594                  */
2595                 TALLOC_FREE(smb_fname->base_name);
2596                 if (ISDOT(fname_dir)) {
2597                         /* Ensure we use canonical names on open. */
2598                         smb_fname->base_name = talloc_asprintf(smb_fname,
2599                                                         "%s",
2600                                                         fname_mask);
2601                 } else {
2602                         smb_fname->base_name = talloc_asprintf(smb_fname,
2603                                                         "%s/%s",
2604                                                         fname_dir,
2605                                                         fname_mask);
2606                 }
2607                 if (!smb_fname->base_name) {
2608                         status = NT_STATUS_NO_MEMORY;
2609                         goto out;
2610                 }
2611                 if (dirtype == 0) {
2612                         dirtype = FILE_ATTRIBUTE_NORMAL;
2613                 }
2614
2615                 status = check_name(conn, smb_fname->base_name);
2616                 if (!NT_STATUS_IS_OK(status)) {
2617                         goto out;
2618                 }
2619
2620                 status = do_unlink(conn, req, smb_fname, dirtype);
2621                 if (!NT_STATUS_IS_OK(status)) {
2622                         goto out;
2623                 }
2624
2625                 count++;
2626         } else {
2627                 struct smb_Dir *dir_hnd = NULL;
2628                 long offset = 0;
2629                 const char *dname = NULL;
2630                 char *talloced = NULL;
2631
2632                 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2633                         status = NT_STATUS_OBJECT_NAME_INVALID;
2634                         goto out;
2635                 }
2636
2637                 if (strequal(fname_mask,"????????.???")) {
2638                         TALLOC_FREE(fname_mask);
2639                         fname_mask = talloc_strdup(ctx, "*");
2640                         if (!fname_mask) {
2641                                 status = NT_STATUS_NO_MEMORY;
2642                                 goto out;
2643                         }
2644                 }
2645
2646                 status = check_name(conn, fname_dir);
2647                 if (!NT_STATUS_IS_OK(status)) {
2648                         goto out;
2649                 }
2650
2651                 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2652                                   dirtype);
2653                 if (dir_hnd == NULL) {
2654                         status = map_nt_error_from_unix(errno);
2655                         goto out;
2656                 }
2657
2658                 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2659                    the pattern matches against the long name, otherwise the short name 
2660                    We don't implement this yet XXXX
2661                 */
2662
2663                 status = NT_STATUS_NO_SUCH_FILE;
2664
2665                 while ((dname = ReadDirName(dir_hnd, &offset,
2666                                             &smb_fname->st, &talloced))) {
2667                         TALLOC_CTX *frame = talloc_stackframe();
2668
2669                         if (!is_visible_file(conn, fname_dir, dname,
2670                                              &smb_fname->st, true)) {
2671                                 TALLOC_FREE(frame);
2672                                 TALLOC_FREE(talloced);
2673                                 continue;
2674                         }
2675
2676                         /* Quick check for "." and ".." */
2677                         if (ISDOT(dname) || ISDOTDOT(dname)) {
2678                                 TALLOC_FREE(frame);
2679                                 TALLOC_FREE(talloced);
2680                                 continue;
2681                         }
2682
2683                         if(!mask_match(dname, fname_mask,
2684                                        conn->case_sensitive)) {
2685                                 TALLOC_FREE(frame);
2686                                 TALLOC_FREE(talloced);
2687                                 continue;
2688                         }
2689
2690                         TALLOC_FREE(smb_fname->base_name);
2691                         if (ISDOT(fname_dir)) {
2692                                 /* Ensure we use canonical names on open. */
2693                                 smb_fname->base_name =
2694                                         talloc_asprintf(smb_fname, "%s",
2695                                                 dname);
2696                         } else {
2697                                 smb_fname->base_name =
2698                                         talloc_asprintf(smb_fname, "%s/%s",
2699                                                 fname_dir, dname);
2700                         }
2701
2702                         if (!smb_fname->base_name) {
2703                                 TALLOC_FREE(dir_hnd);
2704                                 status = NT_STATUS_NO_MEMORY;
2705                                 TALLOC_FREE(frame);
2706                                 TALLOC_FREE(talloced);
2707                                 goto out;
2708                         }
2709
2710                         status = check_name(conn, smb_fname->base_name);
2711                         if (!NT_STATUS_IS_OK(status)) {
2712                                 TALLOC_FREE(dir_hnd);
2713                                 TALLOC_FREE(frame);
2714                                 TALLOC_FREE(talloced);
2715                                 goto out;
2716                         }
2717
2718                         status = do_unlink(conn, req, smb_fname, dirtype);
2719                         if (!NT_STATUS_IS_OK(status)) {
2720                                 TALLOC_FREE(frame);
2721                                 TALLOC_FREE(talloced);
2722                                 continue;
2723                         }
2724
2725                         count++;
2726                         DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2727                                  smb_fname->base_name));
2728
2729                         TALLOC_FREE(frame);
2730                         TALLOC_FREE(talloced);
2731                 }
2732                 TALLOC_FREE(dir_hnd);
2733         }
2734
2735         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2736                 status = map_nt_error_from_unix(errno);
2737         }
2738
2739  out:
2740         TALLOC_FREE(fname_dir);
2741         TALLOC_FREE(fname_mask);
2742         return status;
2743 }
2744
2745 /****************************************************************************
2746  Reply to a unlink
2747 ****************************************************************************/
2748
2749 void reply_unlink(struct smb_request *req)
2750 {
2751         connection_struct *conn = req->conn;
2752         char *name = NULL;
2753         struct smb_filename *smb_fname = NULL;
2754         uint32 dirtype;
2755         NTSTATUS status;
2756         bool path_contains_wcard = False;
2757         TALLOC_CTX *ctx = talloc_tos();
2758
2759         START_PROFILE(SMBunlink);
2760
2761         if (req->wct < 1) {
2762                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2763                 goto out;
2764         }
2765
2766         dirtype = SVAL(req->vwv+0, 0);
2767
2768         srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2769                                   STR_TERMINATE, &status,
2770                                   &path_contains_wcard);
2771         if (!NT_STATUS_IS_OK(status)) {
2772                 reply_nterror(req, status);
2773                 goto out;
2774         }
2775
2776         status = filename_convert(ctx, conn,
2777                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
2778                                   name,
2779                                   UCF_COND_ALLOW_WCARD_LCOMP,
2780                                   &path_contains_wcard,
2781                                   &smb_fname);
2782         if (!NT_STATUS_IS_OK(status)) {
2783                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2784                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2785                                         ERRSRV, ERRbadpath);
2786                         goto out;
2787                 }
2788                 reply_nterror(req, status);
2789                 goto out;
2790         }
2791
2792         DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2793
2794         status = unlink_internals(conn, req, dirtype, smb_fname,
2795                                   path_contains_wcard);
2796         if (!NT_STATUS_IS_OK(status)) {
2797                 if (open_was_deferred(req->mid)) {
2798                         /* We have re-scheduled this call. */
2799                         goto out;
2800                 }
2801                 reply_nterror(req, status);
2802                 goto out;
2803         }
2804
2805         reply_outbuf(req, 0, 0);
2806  out:
2807         TALLOC_FREE(smb_fname);
2808         END_PROFILE(SMBunlink);
2809         return;
2810 }
2811
2812 /****************************************************************************
2813  Fail for readbraw.
2814 ****************************************************************************/
2815
2816 static void fail_readraw(void)
2817 {
2818         const char *errstr = talloc_asprintf(talloc_tos(),
2819                         "FAIL ! reply_readbraw: socket write fail (%s)",
2820                         strerror(errno));
2821         if (!errstr) {
2822                 errstr = "";
2823         }
2824         exit_server_cleanly(errstr);
2825 }
2826
2827 /****************************************************************************
2828  Fake (read/write) sendfile. Returns -1 on read or write fail.
2829 ****************************************************************************/
2830
2831 ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread)
2832 {
2833         size_t bufsize;
2834         size_t tosend = nread;
2835         char *buf;
2836
2837         if (nread == 0) {
2838                 return 0;
2839         }
2840
2841         bufsize = MIN(nread, 65536);
2842
2843         if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2844                 return -1;
2845         }
2846
2847         while (tosend > 0) {
2848                 ssize_t ret;
2849                 size_t cur_read;
2850
2851                 if (tosend > bufsize) {
2852                         cur_read = bufsize;
2853                 } else {
2854                         cur_read = tosend;
2855                 }
2856                 ret = read_file(fsp,buf,startpos,cur_read);
2857                 if (ret == -1) {
2858                         SAFE_FREE(buf);
2859                         return -1;
2860                 }
2861
2862                 /* If we had a short read, fill with zeros. */
2863                 if (ret < cur_read) {
2864                         memset(buf + ret, '\0', cur_read - ret);
2865                 }
2866
2867                 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
2868                     != cur_read) {
2869                         char addr[INET6_ADDRSTRLEN];
2870                         /*
2871                          * Try and give an error message saying what
2872                          * client failed.
2873                          */
2874                         DEBUG(0, ("write_data failed for client %s. "
2875                                   "Error %s\n",
2876                                   get_peer_addr(fsp->conn->sconn->sock, addr,
2877                                                 sizeof(addr)),
2878                                   strerror(errno)));
2879                         SAFE_FREE(buf);
2880                         return -1;
2881                 }
2882                 tosend -= cur_read;
2883                 startpos += cur_read;
2884         }
2885
2886         SAFE_FREE(buf);
2887         return (ssize_t)nread;
2888 }
2889
2890 /****************************************************************************
2891  Deal with the case of sendfile reading less bytes from the file than
2892  requested. Fill with zeros (all we can do).
2893 ****************************************************************************/
2894
2895 void sendfile_short_send(files_struct *fsp,
2896                                 ssize_t nread,
2897                                 size_t headersize,
2898                                 size_t smb_maxcnt)
2899 {
2900 #define SHORT_SEND_BUFSIZE 1024
2901         if (nread < headersize) {
2902                 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2903                         "header for file %s (%s). Terminating\n",
2904                         fsp_str_dbg(fsp), strerror(errno)));
2905                 exit_server_cleanly("sendfile_short_send failed");
2906         }
2907
2908         nread -= headersize;
2909
2910         if (nread < smb_maxcnt) {
2911                 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2912                 if (!buf) {
2913                         exit_server_cleanly("sendfile_short_send: "
2914                                 "malloc failed");
2915                 }
2916
2917                 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2918                         "with zeros !\n", fsp_str_dbg(fsp)));
2919
2920                 while (nread < smb_maxcnt) {
2921                         /*
2922                          * We asked for the real file size and told sendfile
2923                          * to not go beyond the end of the file. But it can
2924                          * happen that in between our fstat call and the
2925                          * sendfile call the file was truncated. This is very
2926                          * bad because we have already announced the larger
2927                          * number of bytes to the client.
2928                          *
2929                          * The best we can do now is to send 0-bytes, just as
2930                          * a read from a hole in a sparse file would do.
2931                          *
2932                          * This should happen rarely enough that I don't care
2933                          * about efficiency here :-)
2934                          */
2935                         size_t to_write;
2936
2937                         to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2938                         if (write_data(fsp->conn->sconn->sock, buf, to_write)
2939                             != to_write) {
2940                                 char addr[INET6_ADDRSTRLEN];
2941                                 /*
2942                                  * Try and give an error message saying what
2943                                  * client failed.
2944                                  */
2945                                 DEBUG(0, ("write_data failed for client %s. "
2946                                           "Error %s\n",
2947                                           get_peer_addr(
2948                                                   fsp->conn->sconn->sock, addr,
2949                                                   sizeof(addr)),
2950                                           strerror(errno)));
2951                                 exit_server_cleanly("sendfile_short_send: "
2952                                                     "write_data failed");
2953                         }
2954                         nread += to_write;
2955                 }
2956                 SAFE_FREE(buf);
2957         }
2958 }
2959
2960 /****************************************************************************
2961  Return a readbraw error (4 bytes of zero).
2962 ****************************************************************************/
2963
2964 static void reply_readbraw_error(struct smbd_server_connection *sconn)
2965 {
2966         char header[4];
2967
2968         SIVAL(header,0,0);
2969
2970         smbd_lock_socket(sconn);
2971         if (write_data(sconn->sock,header,4) != 4) {
2972                 char addr[INET6_ADDRSTRLEN];
2973                 /*
2974                  * Try and give an error message saying what
2975                  * client failed.
2976                  */
2977                 DEBUG(0, ("write_data failed for client %s. "
2978                           "Error %s\n",
2979                           get_peer_addr(sconn->sock, addr, sizeof(addr)),
2980                           strerror(errno)));
2981
2982                 fail_readraw();
2983         }
2984         smbd_unlock_socket(sconn);
2985 }
2986
2987 /****************************************************************************
2988  Use sendfile in readbraw.
2989 ****************************************************************************/
2990
2991 static void send_file_readbraw(connection_struct *conn,
2992                                struct smb_request *req,
2993                                files_struct *fsp,
2994                                SMB_OFF_T startpos,
2995                                size_t nread,
2996                                ssize_t mincount)
2997 {
2998         struct smbd_server_connection *sconn = req->sconn;
2999         char *outbuf = NULL;
3000         ssize_t ret=0;
3001
3002         /*
3003          * We can only use sendfile on a non-chained packet 
3004          * but we can use on a non-oplocked file. tridge proved this
3005          * on a train in Germany :-). JRA.
3006          * reply_readbraw has already checked the length.
3007          */
3008
3009         if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3010             (fsp->wcp == NULL) &&
3011             lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3012                 ssize_t sendfile_read = -1;
3013                 char header[4];
3014                 DATA_BLOB header_blob;
3015
3016                 _smb_setlen(header,nread);
3017                 header_blob = data_blob_const(header, 4);
3018
3019                 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
3020                                                  &header_blob, startpos,
3021                                                  nread);
3022                 if (sendfile_read == -1) {
3023                         /* Returning ENOSYS means no data at all was sent.
3024                          * Do this as a normal read. */
3025                         if (errno == ENOSYS) {
3026                                 goto normal_readbraw;
3027                         }
3028
3029                         /*
3030                          * Special hack for broken Linux with no working sendfile. If we
3031                          * return EINTR we sent the header but not the rest of the data.
3032                          * Fake this up by doing read/write calls.
3033                          */
3034                         if (errno == EINTR) {
3035                                 /* Ensure we don't do this again. */
3036                                 set_use_sendfile(SNUM(conn), False);
3037                                 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3038
3039                                 if (fake_sendfile(fsp, startpos, nread) == -1) {
3040                                         DEBUG(0,("send_file_readbraw: "
3041                                                  "fake_sendfile failed for "
3042                                                  "file %s (%s).\n",
3043                                                  fsp_str_dbg(fsp),
3044                                                  strerror(errno)));
3045                                         exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3046                                 }
3047                                 return;
3048                         }
3049
3050                         DEBUG(0,("send_file_readbraw: sendfile failed for "
3051                                  "file %s (%s). Terminating\n",
3052                                  fsp_str_dbg(fsp), strerror(errno)));
3053                         exit_server_cleanly("send_file_readbraw sendfile failed");
3054                 } else if (sendfile_read == 0) {
3055                         /*
3056                          * Some sendfile implementations return 0 to indicate
3057                          * that there was a short read, but nothing was
3058                          * actually written to the socket.  In this case,
3059                          * fallback to the normal read path so the header gets
3060                          * the correct byte count.
3061                          */
3062                         DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3063                                   "bytes falling back to the normal read: "
3064                                   "%s\n", fsp_str_dbg(fsp)));
3065                         goto normal_readbraw;
3066                 }
3067
3068                 /* Deal with possible short send. */
3069                 if (sendfile_read != 4+nread) {
3070                         sendfile_short_send(fsp, sendfile_read, 4, nread);
3071                 }
3072                 return;
3073         }
3074
3075 normal_readbraw:
3076
3077         outbuf = TALLOC_ARRAY(NULL, char, nread+4);
3078         if (!outbuf) {
3079                 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
3080                         (unsigned)(nread+4)));
3081                 reply_readbraw_error(sconn);
3082                 return;
3083         }
3084
3085         if (nread > 0) {
3086                 ret = read_file(fsp,outbuf+4,startpos,nread);
3087 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3088                 if (ret < mincount)
3089                         ret = 0;
3090 #else
3091                 if (ret < nread)
3092                         ret = 0;
3093 #endif
3094         }
3095
3096         _smb_setlen(outbuf,ret);
3097         if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
3098                 char addr[INET6_ADDRSTRLEN];
3099                 /*
3100                  * Try and give an error message saying what
3101                  * client failed.
3102                  */
3103                 DEBUG(0, ("write_data failed for client %s. "
3104                           "Error %s\n",
3105                           get_peer_addr(fsp->conn->sconn->sock, addr,
3106                                         sizeof(addr)),
3107                           strerror(errno)));
3108
3109                 fail_readraw();
3110         }
3111
3112         TALLOC_FREE(outbuf);
3113 }
3114
3115 /****************************************************************************
3116  Reply to a readbraw (core+ protocol).
3117 ****************************************************************************/
3118
3119 void reply_readbraw(struct smb_request *req)
3120 {
3121         connection_struct *conn = req->conn;
3122         struct smbd_server_connection *sconn = req->sconn;
3123         ssize_t maxcount,mincount;
3124         size_t nread = 0;
3125         SMB_OFF_T startpos;
3126         files_struct *fsp;
3127         struct lock_struct lock;
3128         SMB_OFF_T size = 0;
3129
3130         START_PROFILE(SMBreadbraw);
3131
3132         if (srv_is_signing_active(sconn) ||
3133             is_encrypted_packet(req->inbuf)) {
3134                 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3135                         "raw reads/writes are disallowed.");
3136         }
3137
3138         if (req->wct < 8) {
3139                 reply_readbraw_error(sconn);
3140                 END_PROFILE(SMBreadbraw);
3141                 return;
3142         }
3143
3144         if (sconn->smb1.echo_handler.trusted_fde) {
3145                 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3146                          "'async smb echo handler = yes'\n"));
3147                 reply_readbraw_error(sconn);
3148                 END_PROFILE(SMBreadbraw);
3149                 return;
3150         }
3151
3152         /*
3153          * Special check if an oplock break has been issued
3154          * and the readraw request croses on the wire, we must
3155          * return a zero length response here.
3156          */
3157
3158         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3159
3160         /*
3161          * We have to do a check_fsp by hand here, as
3162          * we must always return 4 zero bytes on error,
3163          * not a NTSTATUS.
3164          */
3165
3166         if (!fsp || !conn || conn != fsp->conn ||
3167                         req->vuid != fsp->vuid ||
3168                         fsp->is_directory || fsp->fh->fd == -1) {
3169                 /*
3170                  * fsp could be NULL here so use the value from the packet. JRA.
3171                  */
3172                 DEBUG(3,("reply_readbraw: fnum %d not valid "
3173                         "- cache prime?\n",
3174                         (int)SVAL(req->vwv+0, 0)));
3175                 reply_readbraw_error(sconn);
3176                 END_PROFILE(SMBreadbraw);
3177                 return;
3178         }
3179
3180         /* Do a "by hand" version of CHECK_READ. */
3181         if (!(fsp->can_read ||
3182                         ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3183                                 (fsp->access_mask & FILE_EXECUTE)))) {
3184                 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3185                                 (int)SVAL(req->vwv+0, 0)));
3186                 reply_readbraw_error(sconn);
3187                 END_PROFILE(SMBreadbraw);
3188                 return;
3189         }
3190
3191         flush_write_cache(fsp, READRAW_FLUSH);
3192
3193         startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3194         if(req->wct == 10) {
3195                 /*
3196                  * This is a large offset (64 bit) read.
3197                  */
3198 #ifdef LARGE_SMB_OFF_T
3199
3200                 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3201
3202 #else /* !LARGE_SMB_OFF_T */
3203
3204                 /*
3205                  * Ensure we haven't been sent a >32 bit offset.
3206                  */
3207
3208                 if(IVAL(req->vwv+8, 0) != 0) {
3209                         DEBUG(0,("reply_readbraw: large offset "
3210                                 "(%x << 32) used and we don't support "
3211                                 "64 bit offsets.\n",
3212                         (unsigned int)IVAL(req->vwv+8, 0) ));
3213                         reply_readbraw_error();
3214                         END_PROFILE(SMBreadbraw);
3215                         return;
3216                 }
3217
3218 #endif /* LARGE_SMB_OFF_T */
3219
3220                 if(startpos < 0) {
3221                         DEBUG(0,("reply_readbraw: negative 64 bit "
3222                                 "readraw offset (%.0f) !\n",
3223                                 (double)startpos ));
3224                         reply_readbraw_error(sconn);
3225                         END_PROFILE(SMBreadbraw);
3226                         return;
3227                 }
3228         }
3229
3230         maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3231         mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3232
3233         /* ensure we don't overrun the packet size */
3234         maxcount = MIN(65535,maxcount);
3235
3236         init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3237             (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3238             &lock);
3239
3240         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3241                 reply_readbraw_error(sconn);
3242                 END_PROFILE(SMBreadbraw);
3243                 return;
3244         }
3245
3246         if (fsp_stat(fsp) == 0) {
3247                 size = fsp->fsp_name->st.st_ex_size;
3248         }
3249
3250         if (startpos >= size) {
3251                 nread = 0;
3252         } else {
3253                 nread = MIN(maxcount,(size - startpos));
3254         }
3255
3256 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3257         if (nread < mincount)
3258                 nread = 0;
3259 #endif
3260
3261         DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3262                 "min=%lu nread=%lu\n",
3263                 fsp->fnum, (double)startpos,
3264                 (unsigned long)maxcount,
3265                 (unsigned long)mincount,
3266                 (unsigned long)nread ) );
3267
3268         send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3269
3270         DEBUG(5,("reply_readbraw finished\n"));
3271
3272         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3273
3274         END_PROFILE(SMBreadbraw);
3275         return;
3276 }
3277
3278 #undef DBGC_CLASS
3279 #define DBGC_CLASS DBGC_LOCKING
3280
3281 /****************************************************************************
3282  Reply to a lockread (core+ protocol).
3283 ****************************************************************************/
3284
3285 void reply_lockread(struct smb_request *req)
3286 {
3287         connection_struct *conn = req->conn;
3288         ssize_t nread = -1;
3289         char *data;
3290         SMB_OFF_T startpos;
3291         size_t numtoread;
3292         NTSTATUS status;
3293         files_struct *fsp;
3294         struct byte_range_lock *br_lck = NULL;
3295         char *p = NULL;
3296         struct smbd_server_connection *sconn = req->sconn;
3297
3298         START_PROFILE(SMBlockread);
3299
3300         if (req->wct < 5) {
3301                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3302                 END_PROFILE(SMBlockread);
3303                 return;
3304         }
3305
3306         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3307
3308         if (!check_fsp(conn, req, fsp)) {
3309                 END_PROFILE(SMBlockread);
3310                 return;
3311         }
3312
3313         if (!CHECK_READ(fsp,req)) {
3314                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3315                 END_PROFILE(SMBlockread);
3316                 return;
3317         }
3318
3319         numtoread = SVAL(req->vwv+1, 0);
3320         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3321
3322         numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3323
3324         reply_outbuf(req, 5, numtoread + 3);
3325
3326         data = smb_buf(req->outbuf) + 3;
3327
3328         /*
3329          * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3330          * protocol request that predates the read/write lock concept. 
3331          * Thus instead of asking for a read lock here we need to ask
3332          * for a write lock. JRA.
3333          * Note that the requested lock size is unaffected by max_recv.
3334          */
3335
3336         br_lck = do_lock(req->sconn->msg_ctx,
3337                         fsp,
3338                         (uint64_t)req->smbpid,
3339                         (uint64_t)numtoread,
3340                         (uint64_t)startpos,
3341                         WRITE_LOCK,
3342                         WINDOWS_LOCK,
3343                         False, /* Non-blocking lock. */
3344                         &status,
3345                         NULL,
3346                         NULL);
3347         TALLOC_FREE(br_lck);
3348
3349         if (NT_STATUS_V(status)) {
3350                 reply_nterror(req, status);
3351                 END_PROFILE(SMBlockread);
3352                 return;
3353         }
3354
3355         /*
3356          * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3357          */
3358
3359         if (numtoread > sconn->smb1.negprot.max_recv) {
3360                 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3361 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3362                         (unsigned int)numtoread,
3363                         (unsigned int)sconn->smb1.negprot.max_recv));
3364                 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3365         }
3366         nread = read_file(fsp,data,startpos,numtoread);
3367
3368         if (nread < 0) {
3369                 reply_nterror(req, map_nt_error_from_unix(errno));
3370                 END_PROFILE(SMBlockread);
3371                 return;
3372         }
3373
3374         srv_set_message((char *)req->outbuf, 5, nread+3, False);
3375
3376         SSVAL(req->outbuf,smb_vwv0,nread);
3377         SSVAL(req->outbuf,smb_vwv5,nread+3);
3378         p = smb_buf(req->outbuf);
3379         SCVAL(p,0,0); /* pad byte. */
3380         SSVAL(p,1,nread);
3381
3382         DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3383                  fsp->fnum, (int)numtoread, (int)nread));
3384
3385         END_PROFILE(SMBlockread);
3386         return;
3387 }
3388
3389 #undef DBGC_CLASS
3390 #define DBGC_CLASS DBGC_ALL
3391
3392 /****************************************************************************
3393  Reply to a read.
3394 ****************************************************************************/
3395
3396 void reply_read(struct smb_request *req)
3397 {
3398         connection_struct *conn = req->conn;
3399         size_t numtoread;
3400         ssize_t nread = 0;
3401         char *data;
3402         SMB_OFF_T startpos;
3403         int outsize = 0;
3404         files_struct *fsp;
3405         struct lock_struct lock;
3406         struct smbd_server_connection *sconn = req->sconn;
3407
3408         START_PROFILE(SMBread);
3409
3410         if (req->wct < 3) {
3411                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3412                 END_PROFILE(SMBread);
3413                 return;
3414         }
3415
3416         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3417
3418         if (!check_fsp(conn, req, fsp)) {
3419                 END_PROFILE(SMBread);
3420                 return;
3421         }
3422
3423         if (!CHECK_READ(fsp,req)) {
3424                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3425                 END_PROFILE(SMBread);
3426                 return;
3427         }
3428
3429         numtoread = SVAL(req->vwv+1, 0);
3430         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3431
3432         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3433
3434         /*
3435          * The requested read size cannot be greater than max_recv. JRA.
3436          */
3437         if (numtoread > sconn->smb1.negprot.max_recv) {
3438                 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3439 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3440                         (unsigned int)numtoread,
3441                         (unsigned int)sconn->smb1.negprot.max_recv));
3442                 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3443         }
3444
3445         reply_outbuf(req, 5, numtoread+3);
3446
3447         data = smb_buf(req->outbuf) + 3;
3448
3449         init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3450             (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3451             &lock);
3452
3453         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3454                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3455                 END_PROFILE(SMBread);
3456                 return;
3457         }
3458
3459         if (numtoread > 0)
3460                 nread = read_file(fsp,data,startpos,numtoread);
3461
3462         if (nread < 0) {
3463                 reply_nterror(req, map_nt_error_from_unix(errno));
3464                 goto strict_unlock;
3465         }
3466
3467         srv_set_message((char *)req->outbuf, 5, nread+3, False);
3468
3469         SSVAL(req->outbuf,smb_vwv0,nread);
3470         SSVAL(req->outbuf,smb_vwv5,nread+3);
3471         SCVAL(smb_buf(req->outbuf),0,1);
3472         SSVAL(smb_buf(req->outbuf),1,nread);
3473
3474         DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3475                 fsp->fnum, (int)numtoread, (int)nread ) );
3476
3477 strict_unlock:
3478         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3479
3480         END_PROFILE(SMBread);
3481         return;
3482 }
3483
3484 /****************************************************************************
3485  Setup readX header.
3486 ****************************************************************************/
3487
3488 static int setup_readX_header(struct smb_request *req, char *outbuf,
3489                               size_t smb_maxcnt)
3490 {
3491         int outsize;
3492         char *data;
3493
3494         outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3495         data = smb_buf(outbuf);
3496
3497         memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3498
3499         SCVAL(outbuf,smb_vwv0,0xFF);
3500         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3501         SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3502         SSVAL(outbuf,smb_vwv6,
3503               req_wct_ofs(req)
3504               + 1               /* the wct field */
3505               + 12 * sizeof(uint16_t) /* vwv */
3506               + 2);             /* the buflen field */
3507         SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3508         SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3509         /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3510         _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3511         return outsize;
3512 }
3513
3514 /****************************************************************************
3515  Reply to a read and X - possibly using sendfile.
3516 ****************************************************************************/
3517
3518 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3519                             files_struct *fsp, SMB_OFF_T startpos,
3520                             size_t smb_maxcnt)
3521 {
3522         ssize_t nread = -1;
3523         struct lock_struct lock;
3524         int saved_errno = 0;
3525
3526         if(fsp_stat(fsp) == -1) {
3527                 reply_nterror(req, map_nt_error_from_unix(errno));
3528                 return;
3529         }
3530
3531         init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3532             (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3533             &lock);
3534
3535         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3536                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3537                 return;
3538         }
3539
3540         if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3541                         (startpos > fsp->fsp_name->st.st_ex_size)
3542                         || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3543                 /*
3544                  * We already know that we would do a short read, so don't
3545                  * try the sendfile() path.
3546                  */
3547                 goto nosendfile_read;
3548         }
3549
3550         /*
3551          * We can only use sendfile on a non-chained packet
3552          * but we can use on a non-oplocked file. tridge proved this
3553          * on a train in Germany :-). JRA.
3554          */
3555
3556         if (!req_is_in_chain(req) &&
3557             !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3558             (fsp->wcp == NULL) &&
3559             lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3560                 uint8 headerbuf[smb_size + 12 * 2];
3561                 DATA_BLOB header;
3562
3563                 /*
3564                  * Set up the packet header before send. We
3565                  * assume here the sendfile will work (get the
3566                  * correct amount of data).
3567                  */
3568
3569                 header = data_blob_const(headerbuf, sizeof(headerbuf));
3570
3571                 construct_reply_common_req(req, (char *)headerbuf);
3572                 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3573
3574                 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3575                                          startpos, smb_maxcnt);
3576                 if (nread == -1) {
3577                         /* Returning ENOSYS means no data at all was sent.
3578                            Do this as a normal read. */
3579                         if (errno == ENOSYS) {
3580                                 goto normal_read;
3581                         }
3582
3583                         /*
3584                          * Special hack for broken Linux with no working sendfile. If we
3585                          * return EINTR we sent the header but not the rest of the data.
3586                          * Fake this up by doing read/write calls.
3587                          */
3588
3589                         if (errno == EINTR) {
3590                                 /* Ensure we don't do this again. */
3591                                 set_use_sendfile(SNUM(conn), False);
3592                                 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3593                                 nread = fake_sendfile(fsp, startpos,
3594                                                       smb_maxcnt);
3595                                 if (nread == -1) {
3596                                         DEBUG(0,("send_file_readX: "
3597                                                  "fake_sendfile failed for "
3598                                                  "file %s (%s).\n",
3599                                                  fsp_str_dbg(fsp),
3600                                                  strerror(errno)));
3601                                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
3602                                 }
3603                                 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3604                                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3605                                 /* No outbuf here means successful sendfile. */
3606                                 goto strict_unlock;
3607                         }
3608
3609                         DEBUG(0,("send_file_readX: sendfile failed for file "
3610                                  "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3611                                  strerror(errno)));
3612                         exit_server_cleanly("send_file_readX sendfile failed");
3613                 } else if (nread == 0) {
3614                         /*
3615                          * Some sendfile implementations return 0 to indicate
3616                          * that there was a short read, but nothing was
3617                          * actually written to the socket.  In this case,
3618                          * fallback to the normal read path so the header gets
3619                          * the correct byte count.
3620                          */
3621                         DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3622                                   "falling back to the normal read: %s\n",
3623                                   fsp_str_dbg(fsp)));
3624                         goto normal_read;
3625                 }
3626
3627                 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3628                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3629
3630                 /* Deal with possible short send. */
3631                 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3632                         sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3633                 }
3634                 /* No outbuf here means successful sendfile. */
3635                 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3636                 SMB_PERFCOUNT_END(&req->pcd);
3637                 goto strict_unlock;
3638         }
3639
3640 normal_read:
3641
3642         if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3643                 uint8 headerbuf[smb_size + 2*12];
3644
3645                 construct_reply_common_req(req, (char *)headerbuf);
3646                 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3647
3648                 /* Send out the header. */
3649                 if (write_data(req->sconn->sock, (char *)headerbuf,
3650                                sizeof(headerbuf)) != sizeof(headerbuf)) {
3651
3652                         char addr[INET6_ADDRSTRLEN];
3653                         /*
3654                          * Try and give an error message saying what
3655                          * client failed.
3656                          */
3657                         DEBUG(0, ("write_data failed for client %s. "
3658                                   "Error %s\n",
3659                                   get_peer_addr(req->sconn->sock, addr,
3660                                                 sizeof(addr)),
3661                                   strerror(errno)));
3662
3663                         DEBUG(0,("send_file_readX: write_data failed for file "
3664                                  "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3665                                  strerror(errno)));
3666                         exit_server_cleanly("send_file_readX sendfile failed");
3667                 }
3668                 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3669                 if (nread == -1) {
3670                         DEBUG(0,("send_file_readX: fake_sendfile failed for "
3671                                  "file %s (%s).\n", fsp_str_dbg(fsp),
3672                                  strerror(errno)));
3673                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
3674                 }
3675                 goto strict_unlock;
3676         }
3677
3678 nosendfile_read:
3679
3680         reply_outbuf(req, 12, smb_maxcnt);
3681
3682         nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3683         saved_errno = errno;
3684
3685         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3686
3687         if (nread < 0) {
3688                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3689                 return;
3690         }
3691
3692         setup_readX_header(req, (char *)req->outbuf, nread);
3693
3694         DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3695                     fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3696
3697         chain_reply(req);
3698         return;
3699
3700  strict_unlock:
3701         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3702         TALLOC_FREE(req->outbuf);
3703         return;
3704 }
3705
3706 /****************************************************************************
3707  Reply to a read and X.
3708 ****************************************************************************/
3709
3710 void reply_read_and_X(struct smb_request *req)
3711 {
3712         connection_struct *conn = req->conn;
3713         files_struct *fsp;
3714         SMB_OFF_T startpos;
3715         size_t smb_maxcnt;
3716         bool big_readX = False;
3717 #if 0
3718         size_t smb_mincnt = SVAL(req->vwv+6, 0);
3719 #endif
3720
3721         START_PROFILE(SMBreadX);
3722
3723         if ((req->wct != 10) && (req->wct != 12)) {
3724                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3725                 return;
3726         }
3727
3728         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3729         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3730         smb_maxcnt = SVAL(req->vwv+5, 0);
3731
3732         /* If it's an IPC, pass off the pipe handler. */
3733         if (IS_IPC(conn)) {
3734                 reply_pipe_read_and_X(req);
3735                 END_PROFILE(SMBreadX);
3736                 return;
3737         }
3738
3739         if (!check_fsp(conn, req, fsp)) {
3740                 END_PROFILE(SMBreadX);
3741                 return;
3742         }
3743
3744         if (!CHECK_READ(fsp,req)) {
3745                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3746                 END_PROFILE(SMBreadX);
3747                 return;
3748         }
3749
3750         if (global_client_caps & CAP_LARGE_READX) {
3751                 size_t upper_size = SVAL(req->vwv+7, 0);
3752                 smb_maxcnt |= (upper_size<<16);
3753                 if (upper_size > 1) {
3754                         /* Can't do this on a chained packet. */
3755                         if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3756                                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3757                                 END_PROFILE(SMBreadX);
3758                                 return;
3759                         }
3760                         /* We currently don't do this on signed or sealed data. */
3761                         if (srv_is_signing_active(req->sconn) ||
3762                             is_encrypted_packet(req->inbuf)) {
3763                                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3764                                 END_PROFILE(SMBreadX);
3765                                 return;
3766                         }
3767                         /* Is there room in the reply for this data ? */
3768                         if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2)))  {
3769                                 reply_nterror(req,
3770                                               NT_STATUS_INVALID_PARAMETER);
3771                                 END_PROFILE(SMBreadX);
3772                                 return;
3773                         }
3774                         big_readX = True;
3775                 }
3776         }
3777
3778         if (req->wct == 12) {
3779 #ifdef LARGE_SMB_OFF_T
3780                 /*
3781                  * This is a large offset (64 bit) read.
3782                  */
3783                 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3784
3785 #else /* !LARGE_SMB_OFF_T */
3786
3787                 /*
3788                  * Ensure we haven't been sent a >32 bit offset.
3789                  */
3790
3791                 if(IVAL(req->vwv+10, 0) != 0) {
3792                         DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3793                                  "used and we don't support 64 bit offsets.\n",
3794                                  (unsigned int)IVAL(req->vwv+10, 0) ));
3795                         END_PROFILE(SMBreadX);
3796                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3797                         return;
3798                 }
3799
3800 #endif /* LARGE_SMB_OFF_T */
3801
3802         }
3803
3804         if (!big_readX) {
3805                 NTSTATUS status = schedule_aio_read_and_X(conn,
3806                                         req,
3807                                         fsp,
3808                                         startpos,
3809                                         smb_maxcnt);
3810                 if (NT_STATUS_IS_OK(status)) {
3811                         /* Read scheduled - we're done. */
3812                         goto out;
3813                 }
3814                 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3815                         /* Real error - report to client. */
3816                         END_PROFILE(SMBreadX);
3817                         reply_nterror(req, status);
3818                         return;
3819                 }
3820                 /* NT_STATUS_RETRY - fall back to sync read. */
3821         }
3822
3823         smbd_lock_socket(req->sconn);
3824         send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3825         smbd_unlock_socket(req->sconn);
3826
3827  out:
3828         END_PROFILE(SMBreadX);
3829         return;
3830 }
3831
3832 /****************************************************************************
3833  Error replies to writebraw must have smb_wct == 1. Fix this up.
3834 ****************************************************************************/
3835
3836 void error_to_writebrawerr(struct smb_request *req)
3837 {
3838         uint8 *old_outbuf = req->outbuf;
3839
3840         reply_outbuf(req, 1, 0);
3841
3842         memcpy(req->outbuf, old_outbuf, smb_size);
3843         TALLOC_FREE(old_outbuf);
3844 }
3845
3846 /****************************************************************************
3847  Read 4 bytes of a smb packet and return the smb length of the packet.
3848  Store the result in the buffer. This version of the function will
3849  never return a session keepalive (length of zero).
3850  Timeout is in milliseconds.
3851 ****************************************************************************/
3852
3853 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3854                                 size_t *len)
3855 {
3856         uint8_t msgtype = SMBkeepalive;
3857
3858         while (msgtype == SMBkeepalive) {
3859                 NTSTATUS status;
3860
3861                 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3862                                                           len);
3863                 if (!NT_STATUS_IS_OK(status)) {
3864                         char addr[INET6_ADDRSTRLEN];
3865                         /* Try and give an error message
3866                          * saying what client failed. */
3867                         DEBUG(0, ("read_fd_with_timeout failed for "
3868                                   "client %s read error = %s.\n",
3869                                   get_peer_addr(fd,addr,sizeof(addr)),
3870                                   nt_errstr(status)));
3871                         return status;
3872                 }
3873
3874                 msgtype = CVAL(inbuf, 0);
3875         }
3876
3877         DEBUG(10,("read_smb_length: got smb length of %lu\n",
3878                   (unsigned long)len));
3879
3880         return NT_STATUS_OK;
3881 }
3882
3883 /****************************************************************************
3884  Reply to a writebraw (core+ or LANMAN1.0 protocol).
3885 ****************************************************************************/
3886
3887 void reply_writebraw(struct smb_request *req)
3888 {
3889         connection_struct *conn = req->conn;
3890         char *buf = NULL;
3891         ssize_t nwritten=0;
3892         ssize_t total_written=0;
3893         size_t numtowrite=0;
3894         size_t tcount;
3895         SMB_OFF_T startpos;
3896         char *data=NULL;
3897         bool write_through;
3898         files_struct *fsp;
3899         struct lock_struct lock;
3900         NTSTATUS status;
3901
3902         START_PROFILE(SMBwritebraw);
3903
3904         /*
3905          * If we ever reply with an error, it must have the SMB command
3906          * type of SMBwritec, not SMBwriteBraw, as this tells the client
3907          * we're finished.
3908          */
3909         SCVAL(req->inbuf,smb_com,SMBwritec);
3910
3911         if (srv_is_signing_active(req->sconn)) {
3912                 END_PROFILE(SMBwritebraw);
3913                 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3914                                 "raw reads/writes are disallowed.");
3915         }
3916
3917         if (req->wct < 12) {
3918                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3919                 error_to_writebrawerr(req);
3920                 END_PROFILE(SMBwritebraw);
3921                 return;
3922         }
3923
3924         if (req->sconn->smb1.echo_handler.trusted_fde) {
3925                 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3926                          "'async smb echo handler = yes'\n"));
3927                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3928                 error_to_writebrawerr(req);
3929                 END_PROFILE(SMBwritebraw);
3930                 return;
3931         }
3932
3933         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3934         if (!check_fsp(conn, req, fsp)) {
3935                 error_to_writebrawerr(req);
3936                 END_PROFILE(SMBwritebraw);
3937                 return;
3938         }
3939
3940         if (!CHECK_WRITE(fsp)) {
3941                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3942                 error_to_writebrawerr(req);
3943                 END_PROFILE(SMBwritebraw);
3944                 return;
3945         }
3946
3947         tcount = IVAL(req->vwv+1, 0);
3948         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3949         write_through = BITSETW(req->vwv+7,0);
3950
3951         /* We have to deal with slightly different formats depending
3952                 on whether we are using the core+ or lanman1.0 protocol */
3953
3954         if(get_Protocol() <= PROTOCOL_COREPLUS) {
3955                 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3956                 data = smb_buf(req->inbuf);
3957         } else {
3958                 numtowrite = SVAL(req->vwv+10, 0);
3959                 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3960         }
3961
3962         /* Ensure we don't write bytes past the end of this packet. */
3963         if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3964                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3965                 error_to_writebrawerr(req);
3966                 END_PROFILE(SMBwritebraw);
3967                 return;
3968         }
3969
3970         if (!fsp->print_file) {
3971                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3972                     (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3973                     &lock);
3974
3975                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3976                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3977                         error_to_writebrawerr(req);
3978                         END_PROFILE(SMBwritebraw);
3979                         return;
3980                 }
3981         }
3982
3983         if (numtowrite>0) {
3984                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3985         }
3986
3987         DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3988                         "wrote=%d sync=%d\n",
3989                 fsp->fnum, (double)startpos, (int)numtowrite,
3990                 (int)nwritten, (int)write_through));
3991
3992         if (nwritten < (ssize_t)numtowrite)  {
3993                 reply_nterror(req, NT_STATUS_DISK_FULL);
3994                 error_to_writebrawerr(req);
3995                 goto strict_unlock;
3996         }
3997
3998         total_written = nwritten;
3999
4000         /* Allocate a buffer of 64k + length. */
4001         buf = TALLOC_ARRAY(NULL, char, 65540);
4002         if (!buf) {
4003                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4004                 error_to_writebrawerr(req);
4005                 goto strict_unlock;
4006         }
4007
4008         /* Return a SMBwritebraw message to the redirector to tell
4009          * it to send more bytes */
4010
4011         memcpy(buf, req->inbuf, smb_size);
4012         srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4013         SCVAL(buf,smb_com,SMBwritebraw);
4014         SSVALS(buf,smb_vwv0,0xFFFF);
4015         show_msg(buf);
4016         if (!srv_send_smb(req->sconn,
4017                           buf,
4018                           false, 0, /* no signing */
4019                           IS_CONN_ENCRYPTED(conn),
4020                           &req->pcd)) {
4021                 exit_server_cleanly("reply_writebraw: srv_send_smb "
4022                         "failed.");
4023         }
4024
4025         /* Now read the raw data into the buffer and write it */
4026         status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
4027                                  &numtowrite);
4028         if (!NT_STATUS_IS_OK(status)) {
4029                 exit_server_cleanly("secondary writebraw failed");
4030         }
4031
4032         /* Set up outbuf to return the correct size */
4033         reply_outbuf(req, 1, 0);
4034
4035         if (numtowrite != 0) {
4036
4037                 if (numtowrite > 0xFFFF) {
4038                         DEBUG(0,("reply_writebraw: Oversize secondary write "
4039                                 "raw requested (%u). Terminating\n",
4040                                 (unsigned int)numtowrite ));
4041                         exit_server_cleanly("secondary writebraw failed");
4042                 }
4043
4044                 if (tcount > nwritten+numtowrite) {
4045                         DEBUG(3,("reply_writebraw: Client overestimated the "
4046                                 "write %d %d %d\n",
4047                                 (int)tcount,(int)nwritten,(int)numtowrite));
4048                 }
4049
4050                 status = read_data(req->sconn->sock, buf+4, numtowrite);
4051
4052                 if (!NT_STATUS_IS_OK(status)) {
4053                         char addr[INET6_ADDRSTRLEN];
4054                         /* Try and give an error message
4055                          * saying what client failed. */
4056                         DEBUG(0, ("reply_writebraw: Oversize secondary write "
4057                                   "raw read failed (%s) for client %s. "
4058                                   "Terminating\n", nt_errstr(status),
4059                                   get_peer_addr(req->sconn->sock, addr,
4060                                                 sizeof(addr))));
4061                         exit_server_cleanly("secondary writebraw failed");
4062                 }
4063
4064                 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4065                 if (nwritten == -1) {
4066                         TALLOC_FREE(buf);
4067                         reply_nterror(req, map_nt_error_from_unix(errno));
4068                         error_to_writebrawerr(req);
4069                         goto strict_unlock;
4070                 }
4071
4072                 if (nwritten < (ssize_t)numtowrite) {
4073                         SCVAL(req->outbuf,smb_rcls,ERRHRD);
4074                         SSVAL(req->outbuf,smb_err,ERRdiskfull);
4075                 }
4076
4077                 if (nwritten > 0) {
4078                         total_written += nwritten;
4079                 }
4080         }
4081
4082         TALLOC_FREE(buf);
4083         SSVAL(req->outbuf,smb_vwv0,total_written);
4084
4085         status = sync_file(conn, fsp, write_through);
4086         if (!NT_STATUS_IS_OK(status)) {
4087                 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4088                          fsp_str_dbg(fsp), nt_errstr(status)));
4089                 reply_nterror(req, status);
4090                 error_to_writebrawerr(req);
4091                 goto strict_unlock;
4092         }
4093
4094         DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4095                 "wrote=%d\n",
4096                 fsp->fnum, (double)startpos, (int)numtowrite,
4097                 (int)total_written));
4098
4099         if (!fsp->print_file) {
4100                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4101         }
4102
4103         /* We won't return a status if write through is not selected - this
4104          * follows what WfWg does */
4105         END_PROFILE(SMBwritebraw);
4106
4107         if (!write_through && total_written==tcount) {
4108
4109 #if RABBIT_PELLET_FIX
4110                 /*
4111                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4112                  * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
4113                  * JRA.
4114                  */
4115                 if (!send_keepalive(req->sconn->sock)) {
4116                         exit_server_cleanly("reply_writebraw: send of "
4117                                 "keepalive failed");
4118                 }
4119 #endif
4120                 TALLOC_FREE(req->outbuf);
4121         }
4122         return;
4123
4124 strict_unlock:
4125         if (!fsp->print_file) {
4126                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4127         }
4128
4129         END_PROFILE(SMBwritebraw);
4130         return;
4131 }
4132
4133 #undef DBGC_CLASS
4134 #define DBGC_CLASS DBGC_LOCKING
4135
4136 /****************************************************************************
4137  Reply to a writeunlock (core+).
4138 ****************************************************************************/
4139
4140 void reply_writeunlock(struct smb_request *req)
4141 {
4142         connection_struct *conn = req->conn;
4143         ssize_t nwritten = -1;
4144         size_t numtowrite;
4145         SMB_OFF_T startpos;
4146         const char *data;
4147         NTSTATUS status = NT_STATUS_OK;
4148         files_struct *fsp;
4149         struct lock_struct lock;
4150         int saved_errno = 0;
4151
4152         START_PROFILE(SMBwriteunlock);
4153
4154         if (req->wct < 5) {
4155                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4156                 END_PROFILE(SMBwriteunlock);
4157                 return;
4158         }
4159
4160         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4161
4162         if (!check_fsp(conn, req, fsp)) {
4163                 END_PROFILE(SMBwriteunlock);
4164                 return;
4165         }
4166
4167         if (!CHECK_WRITE(fsp)) {
4168                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4169                 END_PROFILE(SMBwriteunlock);
4170                 return;
4171         }
4172
4173         numtowrite = SVAL(req->vwv+1, 0);
4174         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4175         data = (const char *)req->buf + 3;
4176
4177         if (!fsp->print_file && numtowrite > 0) {
4178                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4179                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4180                     &lock);
4181
4182                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4183                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4184                         END_PROFILE(SMBwriteunlock);
4185                         return;
4186                 }
4187         }
4188
4189         /* The special X/Open SMB protocol handling of
4190            zero length writes is *NOT* done for
4191            this call */
4192         if(numtowrite == 0) {
4193                 nwritten = 0;
4194         } else {
4195                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4196                 saved_errno = errno;
4197         }
4198
4199         status = sync_file(conn, fsp, False /* write through */);
4200         if (!NT_STATUS_IS_OK(status)) {
4201                 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4202                          fsp_str_dbg(fsp), nt_errstr(status)));
4203                 reply_nterror(req, status);
4204                 goto strict_unlock;
4205         }
4206
4207         if(nwritten < 0) {
4208                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4209                 goto strict_unlock;
4210         }
4211
4212         if((nwritten < numtowrite) && (numtowrite != 0)) {
4213                 reply_nterror(req, NT_STATUS_DISK_FULL);
4214                 goto strict_unlock;
4215         }
4216
4217         if (numtowrite && !fsp->print_file) {
4218                 status = do_unlock(req->sconn->msg_ctx,
4219                                 fsp,
4220                                 (uint64_t)req->smbpid,
4221                                 (uint64_t)numtowrite, 
4222                                 (uint64_t)startpos,
4223                                 WINDOWS_LOCK);
4224
4225                 if (NT_STATUS_V(status)) {
4226                         reply_nterror(req, status);
4227                         goto strict_unlock;
4228                 }
4229         }
4230
4231         reply_outbuf(req, 1, 0);
4232
4233         SSVAL(req->outbuf,smb_vwv0,nwritten);
4234
4235         DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4236                  fsp->fnum, (int)numtowrite, (int)nwritten));
4237
4238 strict_unlock:
4239         if (numtowrite && !fsp->print_file) {
4240                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4241         }
4242
4243         END_PROFILE(SMBwriteunlock);
4244         return;
4245 }
4246
4247 #undef DBGC_CLASS
4248 #define DBGC_CLASS DBGC_ALL
4249
4250 /****************************************************************************
4251  Reply to a write.
4252 ****************************************************************************/
4253
4254 void reply_write(struct smb_request *req)
4255 {
4256         connection_struct *conn = req->conn;
4257         size_t numtowrite;
4258         ssize_t nwritten = -1;
4259         SMB_OFF_T startpos;
4260         const char *data;
4261         files_struct *fsp;
4262         struct lock_struct lock;
4263         NTSTATUS status;
4264         int saved_errno = 0;
4265
4266         START_PROFILE(SMBwrite);
4267
4268         if (req->wct < 5) {
4269                 END_PROFILE(SMBwrite);
4270                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4271                 return;
4272         }
4273
4274         /* If it's an IPC, pass off the pipe handler. */
4275         if (IS_IPC(conn)) {
4276                 reply_pipe_write(req);
4277                 END_PROFILE(SMBwrite);
4278                 return;
4279         }
4280
4281         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4282
4283         if (!check_fsp(conn, req, fsp)) {
4284                 END_PROFILE(SMBwrite);
4285                 return;
4286         }
4287
4288         if (!CHECK_WRITE(fsp)) {
4289                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4290                 END_PROFILE(SMBwrite);
4291                 return;
4292         }
4293
4294         numtowrite = SVAL(req->vwv+1, 0);
4295         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4296         data = (const char *)req->buf + 3;
4297
4298         if (!fsp->print_file) {
4299                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4300                         (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4301                         &lock);
4302
4303                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4304                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4305                         END_PROFILE(SMBwrite);
4306                         return;
4307                 }
4308         }
4309
4310         /*
4311          * X/Open SMB protocol says that if smb_vwv1 is
4312          * zero then the file size should be extended or
4313          * truncated to the size given in smb_vwv[2-3].
4314          */
4315
4316         if(numtowrite == 0) {
4317                 /*
4318                  * This is actually an allocate call, and set EOF. JRA.
4319                  */
4320                 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4321                 if (nwritten < 0) {
4322                         reply_nterror(req, NT_STATUS_DISK_FULL);
4323                         goto strict_unlock;
4324                 }
4325                 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4326                 if (nwritten < 0) {
4327                         reply_nterror(req, NT_STATUS_DISK_FULL);
4328                         goto strict_unlock;
4329                 }
4330                 trigger_write_time_update_immediate(fsp);
4331         } else {
4332                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4333         }
4334
4335         status = sync_file(conn, fsp, False);
4336         if (!NT_STATUS_IS_OK(status)) {
4337                 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4338                          fsp_str_dbg(fsp), nt_errstr(status)));
4339                 reply_nterror(req, status);
4340                 goto strict_unlock;
4341         }
4342
4343         if(nwritten < 0) {
4344                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4345                 goto strict_unlock;
4346         }
4347
4348         if((nwritten == 0) && (numtowrite != 0)) {
4349                 reply_nterror(req, NT_STATUS_DISK_FULL);
4350                 goto strict_unlock;
4351         }
4352
4353         reply_outbuf(req, 1, 0);
4354
4355         SSVAL(req->outbuf,smb_vwv0,nwritten);
4356
4357         if (nwritten < (ssize_t)numtowrite) {
4358                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4359                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4360         }
4361
4362         DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4363
4364 strict_unlock:
4365         if (!fsp->print_file) {
4366                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4367         }
4368
4369         END_PROFILE(SMBwrite);
4370         return;
4371 }
4372
4373 /****************************************************************************
4374  Ensure a buffer is a valid writeX for recvfile purposes.
4375 ****************************************************************************/
4376
4377 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4378                                                 (2*14) + /* word count (including bcc) */ \
4379                                                 1 /* pad byte */)
4380
4381 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4382                             const uint8_t *inbuf)
4383 {
4384         size_t numtowrite;
4385         connection_struct *conn = NULL;
4386         unsigned int doff = 0;
4387         size_t len = smb_len_large(inbuf);
4388
4389         if (is_encrypted_packet(inbuf)) {
4390                 /* Can't do this on encrypted
4391                  * connections. */
4392                 return false;
4393         }
4394
4395         if (CVAL(inbuf,smb_com) != SMBwriteX) {
4396                 return false;
4397         }
4398
4399         if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4400                         CVAL(inbuf,smb_wct) != 14) {
4401                 DEBUG(10,("is_valid_writeX_buffer: chained or "
4402                         "invalid word length.\n"));
4403                 return false;
4404         }
4405
4406         conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4407         if (conn == NULL) {
4408                 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4409                 return false;
4410         }
4411         if (IS_IPC(conn)) {
4412                 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4413                 return false;
4414         }
4415         if (IS_PRINT(conn)) {
4416                 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4417                 return false;
4418         }
4419         doff = SVAL(inbuf,smb_vwv11);
4420
4421         numtowrite = SVAL(inbuf,smb_vwv10);
4422
4423         if (len > doff && len - doff > 0xFFFF) {
4424                 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4425         }
4426
4427         if (numtowrite == 0) {
4428                 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4429                 return false;
4430         }
4431
4432         /* Ensure the sizes match up. */
4433         if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4434                 /* no pad byte...old smbclient :-( */
4435                 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4436                         (unsigned int)doff,
4437                         (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4438                 return false;
4439         }
4440
4441         if (len - doff != numtowrite) {
4442                 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4443                         "len = %u, doff = %u, numtowrite = %u\n",
4444                         (unsigned int)len,
4445                         (unsigned int)doff,
4446                         (unsigned int)numtowrite ));
4447                 return false;
4448         }
4449
4450         DEBUG(10,("is_valid_writeX_buffer: true "
4451                 "len = %u, doff = %u, numtowrite = %u\n",
4452                 (unsigned int)len,
4453                 (unsigned int)doff,
4454                 (unsigned int)numtowrite ));
4455
4456         return true;
4457 }
4458
4459 /****************************************************************************
4460  Reply to a write and X.
4461 ****************************************************************************/
4462
4463 void reply_write_and_X(struct smb_request *req)
4464 {
4465         connection_struct *conn = req->conn;
4466         files_struct *fsp;
4467         struct lock_struct lock;
4468         SMB_OFF_T startpos;
4469         size_t numtowrite;
4470         bool write_through;
4471         ssize_t nwritten;
4472         unsigned int smb_doff;
4473         unsigned int smblen;
4474         char *data;
4475         NTSTATUS status;
4476         int saved_errno = 0;
4477
4478         START_PROFILE(SMBwriteX);
4479
4480         if ((req->wct != 12) && (req->wct != 14)) {
4481                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4482                 END_PROFILE(SMBwriteX);
4483                 return;
4484         }
4485
4486         numtowrite = SVAL(req->vwv+10, 0);
4487         smb_doff = SVAL(req->vwv+11, 0);
4488         smblen = smb_len(req->inbuf);
4489
4490         if (req->unread_bytes > 0xFFFF ||
4491                         (smblen > smb_doff &&
4492                                 smblen - smb_doff > 0xFFFF)) {
4493                 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4494         }
4495
4496         if (req->unread_bytes) {
4497                 /* Can't do a recvfile write on IPC$ */
4498                 if (IS_IPC(conn)) {
4499                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4500                         END_PROFILE(SMBwriteX);
4501                         return;
4502                 }
4503                 if (numtowrite != req->unread_bytes) {
4504                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4505                         END_PROFILE(SMBwriteX);
4506                         return;
4507                 }
4508         } else {
4509                 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4510                                 smb_doff + numtowrite > smblen) {
4511                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4512                         END_PROFILE(SMBwriteX);
4513                         return;
4514                 }
4515         }
4516
4517         /* If it's an IPC, pass off the pipe handler. */
4518         if (IS_IPC(conn)) {
4519                 if (req->unread_bytes) {
4520                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4521                         END_PROFILE(SMBwriteX);
4522                         return;
4523                 }
4524                 reply_pipe_write_and_X(req);
4525                 END_PROFILE(SMBwriteX);
4526                 return;
4527         }
4528
4529         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4530         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4531         write_through = BITSETW(req->vwv+7,0);
4532
4533         if (!check_fsp(conn, req, fsp)) {
4534                 END_PROFILE(SMBwriteX);
4535                 return;
4536         }
4537
4538         if (!CHECK_WRITE(fsp)) {
4539                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4540                 END_PROFILE(SMBwriteX);
4541                 return;
4542         }
4543
4544         data = smb_base(req->inbuf) + smb_doff;
4545
4546         if(req->wct == 14) {
4547 #ifdef LARGE_SMB_OFF_T
4548                 /*
4549                  * This is a large offset (64 bit) write.
4550                  */
4551                 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4552
4553 #else /* !LARGE_SMB_OFF_T */
4554
4555                 /*
4556                  * Ensure we haven't been sent a >32 bit offset.
4557                  */
4558
4559                 if(IVAL(req->vwv+12, 0) != 0) {
4560                         DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4561                                  "used and we don't support 64 bit offsets.\n",
4562                                  (unsigned int)IVAL(req->vwv+12, 0) ));
4563                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4564                         END_PROFILE(SMBwriteX);
4565                         return;
4566                 }
4567
4568 #endif /* LARGE_SMB_OFF_T */
4569         }
4570
4571         /* X/Open SMB protocol says that, unlike SMBwrite
4572         if the length is zero then NO truncation is
4573         done, just a write of zero. To truncate a file,
4574         use SMBwrite. */
4575
4576         if(numtowrite == 0) {
4577                 nwritten = 0;
4578         } else {
4579                 if (req->unread_bytes == 0) {
4580                         status = schedule_aio_write_and_X(conn,
4581                                                 req,
4582                                                 fsp,
4583                                                 data,
4584                                                 startpos,
4585                                                 numtowrite);
4586
4587                         if (NT_STATUS_IS_OK(status)) {
4588                                 /* write scheduled - we're done. */
4589                                 goto out;
4590                         }
4591                         if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4592                                 /* Real error - report to client. */
4593                                 reply_nterror(req, status);
4594                                 goto out;
4595                         }
4596                         /* NT_STATUS_RETRY - fall through to sync write. */
4597                 }
4598
4599                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4600                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4601                     &lock);
4602
4603                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4604                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4605                         goto out;
4606                 }
4607
4608                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4609                 saved_errno = errno;
4610
4611                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4612         }
4613
4614         if(nwritten < 0) {
4615                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4616                 goto out;
4617         }
4618
4619         if((nwritten == 0) && (numtowrite != 0)) {
4620                 reply_nterror(req, NT_STATUS_DISK_FULL);
4621                 goto out;
4622         }
4623
4624         reply_outbuf(req, 6, 0);
4625         SSVAL(req->outbuf,smb_vwv2,nwritten);
4626         SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4627
4628         if (nwritten < (ssize_t)numtowrite) {
4629                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4630                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4631         }
4632
4633         DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4634                 fsp->fnum, (int)numtowrite, (int)nwritten));
4635
4636         status = sync_file(conn, fsp, write_through);
4637         if (!NT_STATUS_IS_OK(status)) {
4638                 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4639                          fsp_str_dbg(fsp), nt_errstr(status)));
4640                 reply_nterror(req, status);
4641                 goto out;
4642         }
4643
4644         END_PROFILE(SMBwriteX);
4645         chain_reply(req);
4646         return;
4647
4648 out:
4649         END_PROFILE(SMBwriteX);
4650         return;
4651 }
4652
4653 /****************************************************************************
4654  Reply to a lseek.
4655 ****************************************************************************/
4656
4657 void reply_lseek(struct smb_request *req)
4658 {
4659         connection_struct *conn = req->conn;
4660         SMB_OFF_T startpos;
4661         SMB_OFF_T res= -1;
4662         int mode,umode;
4663         files_struct *fsp;
4664
4665         START_PROFILE(SMBlseek);
4666
4667         if (req->wct < 4) {
4668                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4669                 END_PROFILE(SMBlseek);
4670                 return;
4671         }
4672
4673         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4674
4675         if (!check_fsp(conn, req, fsp)) {
4676                 return;
4677         }
4678
4679         flush_write_cache(fsp, SEEK_FLUSH);
4680
4681         mode = SVAL(req->vwv+1, 0) & 3;
4682         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4683         startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4684
4685         switch (mode) {
4686                 case 0:
4687                         umode = SEEK_SET;
4688                         res = startpos;
4689                         break;
4690                 case 1:
4691                         umode = SEEK_CUR;
4692                         res = fsp->fh->pos + startpos;
4693                         break;
4694                 case 2:
4695                         umode = SEEK_END;
4696                         break;
4697                 default:
4698                         umode = SEEK_SET;
4699                         res = startpos;
4700                         break;
4701         }
4702
4703         if (umode == SEEK_END) {
4704                 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4705                         if(errno == EINVAL) {
4706                                 SMB_OFF_T current_pos = startpos;
4707
4708                                 if(fsp_stat(fsp) == -1) {
4709                                         reply_nterror(req,
4710                                                 map_nt_error_from_unix(errno));
4711                                         END_PROFILE(SMBlseek);
4712                                         return;
4713                                 }
4714
4715                                 current_pos += fsp->fsp_name->st.st_ex_size;
4716                                 if(current_pos < 0)
4717                                         res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4718                         }
4719                 }
4720
4721                 if(res == -1) {
4722                         reply_nterror(req, map_nt_error_from_unix(errno));
4723                         END_PROFILE(SMBlseek);
4724                         return;
4725                 }
4726         }
4727
4728         fsp->fh->pos = res;
4729
4730         reply_outbuf(req, 2, 0);
4731         SIVAL(req->outbuf,smb_vwv0,res);
4732
4733         DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4734                 fsp->fnum, (double)startpos, (double)res, mode));
4735
4736         END_PROFILE(SMBlseek);
4737         return;
4738 }
4739
4740 /****************************************************************************
4741  Reply to a flush.
4742 ****************************************************************************/
4743
4744 void reply_flush(struct smb_request *req)
4745 {
4746         connection_struct *conn = req->conn;
4747         uint16 fnum;
4748         files_struct *fsp;
4749
4750         START_PROFILE(SMBflush);
4751
4752         if (req->wct < 1) {
4753                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4754                 return;
4755         }
4756
4757         fnum = SVAL(req->vwv+0, 0);
4758         fsp = file_fsp(req, fnum);
4759
4760         if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4761                 return;
4762         }
4763
4764         if (!fsp) {
4765                 file_sync_all(conn);
4766         } else {
4767                 NTSTATUS status = sync_file(conn, fsp, True);
4768                 if (!NT_STATUS_IS_OK(status)) {
4769                         DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4770                                 fsp_str_dbg(fsp), nt_errstr(status)));
4771                         reply_nterror(req, status);
4772                         END_PROFILE(SMBflush);
4773                         return;
4774                 }
4775         }
4776
4777         reply_outbuf(req, 0, 0);
4778
4779         DEBUG(3,("flush\n"));
4780         END_PROFILE(SMBflush);
4781         return;
4782 }
4783
4784 /****************************************************************************
4785  Reply to a exit.
4786  conn POINTER CAN BE NULL HERE !
4787 ****************************************************************************/
4788
4789 void reply_exit(struct smb_request *req)
4790 {
4791         START_PROFILE(SMBexit);
4792
4793         file_close_pid(req->sconn, req->smbpid, req->vuid);
4794
4795         reply_outbuf(req, 0, 0);
4796
4797         DEBUG(3,("exit\n"));
4798
4799         END_PROFILE(SMBexit);
4800         return;
4801 }
4802
4803 /****************************************************************************
4804  Reply to a close - has to deal with closing a directory opened by NT SMB's.
4805 ****************************************************************************/
4806
4807 void reply_close(struct smb_request *req)
4808 {
4809         connection_struct *conn = req->conn;
4810         NTSTATUS status = NT_STATUS_OK;
4811         files_struct *fsp = NULL;
4812         START_PROFILE(SMBclose);
4813
4814         if (req->wct < 3) {
4815                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4816                 END_PROFILE(SMBclose);
4817                 return;
4818         }
4819
4820         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4821
4822         /*
4823          * We can only use check_fsp if we know it's not a directory.
4824          */
4825
4826         if (!check_fsp_open(conn, req, fsp)) {
4827                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4828                 END_PROFILE(SMBclose);
4829                 return;
4830         }
4831
4832         if(fsp->is_directory) {
4833                 /*
4834                  * Special case - close NT SMB directory handle.
4835                  */
4836                 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4837                 status = close_file(req, fsp, NORMAL_CLOSE);
4838         } else {
4839                 time_t t;
4840                 /*
4841                  * Close ordinary file.
4842                  */
4843
4844                 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4845                          fsp->fh->fd, fsp->fnum,
4846                          conn->num_files_open));
4847
4848                 /*
4849                  * Take care of any time sent in the close.
4850                  */
4851
4852                 t = srv_make_unix_date3(req->vwv+1);
4853                 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4854
4855                 /*
4856                  * close_file() returns the unix errno if an error
4857                  * was detected on close - normally this is due to
4858                  * a disk full error. If not then it was probably an I/O error.
4859                  */
4860
4861                 status = close_file(req, fsp, NORMAL_CLOSE);
4862         }  
4863
4864         if (!NT_STATUS_IS_OK(status)) {
4865                 reply_nterror(req, status);
4866                 END_PROFILE(SMBclose);
4867                 return;
4868         }
4869
4870         reply_outbuf(req, 0, 0);
4871         END_PROFILE(SMBclose);
4872         return;
4873 }
4874
4875 /****************************************************************************
4876  Reply to a writeclose (Core+ protocol).
4877 ****************************************************************************/
4878
4879 void reply_writeclose(struct smb_request *req)
4880 {
4881         connection_struct *conn = req->conn;
4882         size_t numtowrite;
4883         ssize_t nwritten = -1;
4884         NTSTATUS close_status = NT_STATUS_OK;
4885         SMB_OFF_T startpos;
4886         const char *data;
4887         struct timespec mtime;
4888         files_struct *fsp;
4889         struct lock_struct lock;
4890
4891         START_PROFILE(SMBwriteclose);
4892
4893         if (req->wct < 6) {
4894                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4895                 END_PROFILE(SMBwriteclose);
4896                 return;
4897         }
4898
4899         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4900
4901         if (!check_fsp(conn, req, fsp)) {
4902                 END_PROFILE(SMBwriteclose);
4903                 return;
4904         }
4905         if (!CHECK_WRITE(fsp)) {
4906                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4907                 END_PROFILE(SMBwriteclose);
4908                 return;
4909         }
4910
4911         numtowrite = SVAL(req->vwv+1, 0);
4912         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4913         mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4914         data = (const char *)req->buf + 1;
4915
4916         if (!fsp->print_file) {
4917                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4918                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4919                     &lock);
4920
4921                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4922                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4923                         END_PROFILE(SMBwriteclose);
4924                         return;
4925                 }
4926         }
4927
4928         nwritten = write_file(req,fsp,data,startpos,numtowrite);
4929
4930         set_close_write_time(fsp, mtime);
4931
4932         /*
4933          * More insanity. W2K only closes the file if writelen > 0.
4934          * JRA.
4935          */
4936
4937         if (numtowrite) {
4938                 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4939                          "file %s\n", fsp_str_dbg(fsp)));
4940                 close_status = close_file(req, fsp, NORMAL_CLOSE);
4941         }
4942
4943         DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4944                  fsp->fnum, (int)numtowrite, (int)nwritten,
4945                  conn->num_files_open));
4946
4947         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4948                 reply_nterror(req, NT_STATUS_DISK_FULL);
4949                 goto strict_unlock;
4950         }
4951
4952         if(!NT_STATUS_IS_OK(close_status)) {
4953                 reply_nterror(req, close_status);
4954                 goto strict_unlock;
4955         }
4956
4957         reply_outbuf(req, 1, 0);
4958
4959         SSVAL(req->outbuf,smb_vwv0,nwritten);
4960
4961 strict_unlock:
4962         if (numtowrite && !fsp->print_file) {
4963                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4964         }
4965
4966         END_PROFILE(SMBwriteclose);
4967         return;
4968 }
4969
4970 #undef DBGC_CLASS
4971 #define DBGC_CLASS DBGC_LOCKING
4972
4973 /****************************************************************************
4974  Reply to a lock.
4975 ****************************************************************************/
4976
4977 void reply_lock(struct smb_request *req)
4978 {
4979         connection_struct *conn = req->conn;
4980         uint64_t count,offset;
4981         NTSTATUS status;
4982         files_struct *fsp;
4983         struct byte_range_lock *br_lck = NULL;
4984
4985         START_PROFILE(SMBlock);
4986
4987         if (req->wct < 5) {
4988                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4989                 END_PROFILE(SMBlock);
4990                 return;
4991         }
4992
4993         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4994
4995         if (!check_fsp(conn, req, fsp)) {
4996                 END_PROFILE(SMBlock);
4997                 return;
4998         }
4999
5000         count = (uint64_t)IVAL(req->vwv+1, 0);
5001         offset = (uint64_t)IVAL(req->vwv+3, 0);
5002
5003         DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5004                  fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
5005
5006         br_lck = do_lock(req->sconn->msg_ctx,
5007                         fsp,
5008                         (uint64_t)req->smbpid,
5009                         count,
5010                         offset,
5011                         WRITE_LOCK,
5012                         WINDOWS_LOCK,
5013                         False, /* Non-blocking lock. */
5014                         &status,
5015                         NULL,
5016                         NULL);
5017
5018         TALLOC_FREE(br_lck);
5019
5020         if (NT_STATUS_V(status)) {
5021                 reply_nterror(req, status);
5022                 END_PROFILE(SMBlock);
5023                 return;
5024         }
5025
5026         reply_outbuf(req, 0, 0);
5027
5028         END_PROFILE(SMBlock);
5029         return;
5030 }
5031
5032 /****************************************************************************
5033  Reply to a unlock.
5034 ****************************************************************************/
5035
5036 void reply_unlock(struct smb_request *req)
5037 {
5038         connection_struct *conn = req->conn;
5039         uint64_t count,offset;
5040         NTSTATUS status;
5041         files_struct *fsp;
5042
5043         START_PROFILE(SMBunlock);
5044
5045         if (req->wct < 5) {
5046                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5047                 END_PROFILE(SMBunlock);
5048                 return;
5049         }
5050
5051         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5052
5053         if (!check_fsp(conn, req, fsp)) {
5054                 END_PROFILE(SMBunlock);
5055                 return;
5056         }
5057
5058         count = (uint64_t)IVAL(req->vwv+1, 0);
5059         offset = (uint64_t)IVAL(req->vwv+3, 0);
5060
5061         status = do_unlock(req->sconn->msg_ctx,
5062                         fsp,
5063                         (uint64_t)req->smbpid,
5064                         count,
5065                         offset,
5066                         WINDOWS_LOCK);
5067
5068         if (NT_STATUS_V(status)) {
5069                 reply_nterror(req, status);
5070                 END_PROFILE(SMBunlock);
5071                 return;
5072         }
5073
5074         DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5075                     fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
5076
5077         reply_outbuf(req, 0, 0);
5078
5079         END_PROFILE(SMBunlock);
5080         return;
5081 }
5082
5083 #undef DBGC_CLASS
5084 #define DBGC_CLASS DBGC_ALL
5085
5086 /****************************************************************************
5087  Reply to a tdis.
5088  conn POINTER CAN BE NULL HERE !
5089 ****************************************************************************/
5090
5091 void reply_tdis(struct smb_request *req)
5092 {
5093         connection_struct *conn = req->conn;
5094         START_PROFILE(SMBtdis);
5095
5096         if (!conn) {
5097                 DEBUG(4,("Invalid connection in tdis\n"));
5098                 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
5099                 END_PROFILE(SMBtdis);
5100                 return;
5101         }
5102
5103         conn->used = False;
5104
5105         close_cnum(conn,req->vuid);
5106         req->conn = NULL;
5107
5108         reply_outbuf(req, 0, 0);
5109         END_PROFILE(SMBtdis);
5110         return;
5111 }
5112
5113 /****************************************************************************
5114  Reply to a echo.
5115  conn POINTER CAN BE NULL HERE !
5116 ****************************************************************************/
5117
5118 void reply_echo(struct smb_request *req)
5119 {
5120         connection_struct *conn = req->conn;
5121         struct smb_perfcount_data local_pcd;
5122         struct smb_perfcount_data *cur_pcd;
5123         int smb_reverb;
5124         int seq_num;
5125
5126         START_PROFILE(SMBecho);
5127
5128         smb_init_perfcount_data(&local_pcd);
5129
5130         if (req->wct < 1) {
5131                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5132                 END_PROFILE(SMBecho);
5133                 return;
5134         }
5135
5136         smb_reverb = SVAL(req->vwv+0, 0);
5137
5138         reply_outbuf(req, 1, req->buflen);
5139
5140         /* copy any incoming data back out */
5141         if (req->buflen > 0) {
5142                 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5143         }
5144
5145         if (smb_reverb > 100) {
5146                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5147                 smb_reverb = 100;
5148         }
5149
5150         for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5151
5152                 /* this makes sure we catch the request pcd */
5153                 if (seq_num == smb_reverb) {
5154                         cur_pcd = &req->pcd;
5155                 } else {
5156                         SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5157                         cur_pcd = &local_pcd;
5158                 }
5159
5160                 SSVAL(req->outbuf,smb_vwv0,seq_num);
5161
5162                 show_msg((char *)req->outbuf);
5163                 if (!srv_send_smb(req->sconn,
5164                                 (char *)req->outbuf,
5165                                 true, req->seqnum+1,
5166                                 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5167                                 cur_pcd))
5168                         exit_server_cleanly("reply_echo: srv_send_smb failed.");
5169         }
5170
5171         DEBUG(3,("echo %d times\n", smb_reverb));
5172
5173         TALLOC_FREE(req->outbuf);
5174
5175         END_PROFILE(SMBecho);
5176         return;
5177 }
5178
5179 /****************************************************************************
5180  Reply to a printopen.
5181 ****************************************************************************/
5182
5183 void reply_printopen(struct smb_request *req)
5184 {
5185         connection_struct *conn = req->conn;
5186         files_struct *fsp;
5187         NTSTATUS status;
5188
5189         START_PROFILE(SMBsplopen);
5190
5191         if (req->wct < 2) {
5192                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5193                 END_PROFILE(SMBsplopen);
5194                 return;
5195         }
5196
5197         if (!CAN_PRINT(conn)) {
5198                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5199                 END_PROFILE(SMBsplopen);
5200                 return;
5201         }
5202
5203         status = file_new(req, conn, &fsp);
5204         if(!NT_STATUS_IS_OK(status)) {
5205                 reply_nterror(req, status);
5206                 END_PROFILE(SMBsplopen);
5207                 return;
5208         }
5209
5210         /* Open for exclusive use, write only. */
5211         status = print_spool_open(fsp, NULL, req->vuid);
5212
5213         if (!NT_STATUS_IS_OK(status)) {
5214                 file_free(req, fsp);
5215                 reply_nterror(req, status);
5216                 END_PROFILE(SMBsplopen);
5217                 return;
5218         }
5219
5220         reply_outbuf(req, 1, 0);
5221         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5222
5223         DEBUG(3,("openprint fd=%d fnum=%d\n",
5224                  fsp->fh->fd, fsp->fnum));
5225
5226         END_PROFILE(SMBsplopen);
5227         return;
5228 }
5229
5230 /****************************************************************************
5231  Reply to a printclose.
5232 ****************************************************************************/
5233
5234 void reply_printclose(struct smb_request *req)
5235 {
5236         connection_struct *conn = req->conn;
5237         files_struct *fsp;
5238         NTSTATUS status;
5239
5240         START_PROFILE(SMBsplclose);
5241
5242         if (req->wct < 1) {
5243                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5244                 END_PROFILE(SMBsplclose);
5245                 return;
5246         }
5247
5248         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5249
5250         if (!check_fsp(conn, req, fsp)) {
5251                 END_PROFILE(SMBsplclose);
5252                 return;
5253         }
5254
5255         if (!CAN_PRINT(conn)) {
5256                 reply_force_doserror(req, ERRSRV, ERRerror);
5257                 END_PROFILE(SMBsplclose);
5258                 return;
5259         }
5260
5261         DEBUG(3,("printclose fd=%d fnum=%d\n",
5262                  fsp->fh->fd,fsp->fnum));
5263
5264         status = close_file(req, fsp, NORMAL_CLOSE);
5265
5266         if(!NT_STATUS_IS_OK(status)) {
5267                 reply_nterror(req, status);
5268                 END_PROFILE(SMBsplclose);
5269                 return;
5270         }
5271
5272         reply_outbuf(req, 0, 0);
5273
5274         END_PROFILE(SMBsplclose);
5275         return;
5276 }
5277
5278 /****************************************************************************
5279  Reply to a printqueue.
5280 ****************************************************************************/
5281
5282 void reply_printqueue(struct smb_request *req)
5283 {
5284         connection_struct *conn = req->conn;
5285         int max_count;
5286         int start_index;
5287
5288         START_PROFILE(SMBsplretq);
5289
5290         if (req->wct < 2) {
5291                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5292                 END_PROFILE(SMBsplretq);
5293                 return;
5294         }
5295
5296         max_count = SVAL(req->vwv+0, 0);
5297         start_index = SVAL(req->vwv+1, 0);
5298
5299         /* we used to allow the client to get the cnum wrong, but that
5300            is really quite gross and only worked when there was only
5301            one printer - I think we should now only accept it if they
5302            get it right (tridge) */
5303         if (!CAN_PRINT(conn)) {
5304                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5305                 END_PROFILE(SMBsplretq);
5306                 return;
5307         }
5308
5309         reply_outbuf(req, 2, 3);
5310         SSVAL(req->outbuf,smb_vwv0,0);
5311         SSVAL(req->outbuf,smb_vwv1,0);
5312         SCVAL(smb_buf(req->outbuf),0,1);
5313         SSVAL(smb_buf(req->outbuf),1,0);
5314
5315         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5316                  start_index, max_count));
5317
5318         {
5319                 TALLOC_CTX *mem_ctx = talloc_tos();
5320                 NTSTATUS status;
5321                 WERROR werr;
5322                 const char *sharename = lp_servicename(SNUM(conn));
5323                 struct rpc_pipe_client *cli = NULL;
5324                 struct dcerpc_binding_handle *b = NULL;
5325                 struct policy_handle handle;
5326                 struct spoolss_DevmodeContainer devmode_ctr;
5327                 union spoolss_JobInfo *info;
5328                 uint32_t count;
5329                 uint32_t num_to_get;
5330                 uint32_t first;
5331                 uint32_t i;
5332
5333                 ZERO_STRUCT(handle);
5334
5335                 status = rpc_pipe_open_interface(conn,
5336                                                  &ndr_table_spoolss.syntax_id,
5337                                                  conn->session_info,
5338                                                  &conn->sconn->client_id,
5339                                                  conn->sconn->msg_ctx,
5340                                                  &cli);
5341                 if (!NT_STATUS_IS_OK(status)) {
5342                         DEBUG(0, ("reply_printqueue: "
5343                                   "could not connect to spoolss: %s\n",
5344                                   nt_errstr(status)));
5345                         reply_nterror(req, status);
5346                         goto out;
5347                 }
5348                 b = cli->binding_handle;
5349
5350                 ZERO_STRUCT(devmode_ctr);
5351
5352                 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5353                                                 sharename,
5354                                                 NULL, devmode_ctr,
5355                                                 SEC_FLAG_MAXIMUM_ALLOWED,
5356                                                 &handle,
5357                                                 &werr);
5358                 if (!NT_STATUS_IS_OK(status)) {
5359                         reply_nterror(req, status);
5360                         goto out;
5361                 }
5362                 if (!W_ERROR_IS_OK(werr)) {
5363                         reply_nterror(req, werror_to_ntstatus(werr));
5364                         goto out;
5365                 }
5366
5367                 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5368                                                &handle,
5369                                                0, /* firstjob */
5370                                                0xff, /* numjobs */
5371                                                2, /* level */
5372                                                0, /* offered */
5373                                                &count,
5374                                                &info);
5375                 if (!W_ERROR_IS_OK(werr)) {
5376                         reply_nterror(req, werror_to_ntstatus(werr));
5377                         goto out;
5378                 }
5379
5380                 if (max_count > 0) {
5381                         first = start_index;
5382                 } else {
5383                         first = start_index + max_count + 1;
5384                 }
5385
5386                 if (first >= count) {
5387                         num_to_get = first;
5388                 } else {
5389                         num_to_get = first + MIN(ABS(max_count), count - first);
5390                 }
5391
5392                 for (i = first; i < num_to_get; i++) {
5393                         char blob[28];
5394                         char *p = blob;
5395                         time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5396                         int qstatus;
5397                         uint16_t qrapjobid = pjobid_to_rap(sharename,
5398                                                         info[i].info2.job_id);
5399
5400                         if (info[i].info2.status == JOB_STATUS_PRINTING) {
5401                                 qstatus = 2;
5402                         } else {
5403                                 qstatus = 3;
5404                         }
5405
5406                         srv_put_dos_date2(p, 0, qtime);
5407                         SCVAL(p, 4, qstatus);
5408                         SSVAL(p, 5, qrapjobid);
5409                         SIVAL(p, 7, info[i].info2.size);
5410                         SCVAL(p, 11, 0);
5411                         srvstr_push(blob, req->flags2, p+12,
5412                                     info[i].info2.notify_name, 16, STR_ASCII);
5413
5414                         if (message_push_blob(
5415                                     &req->outbuf,
5416                                     data_blob_const(
5417                                             blob, sizeof(blob))) == -1) {
5418                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
5419                                 goto out;
5420                         }
5421                 }
5422
5423                 if (count > 0) {
5424                         SSVAL(req->outbuf,smb_vwv0,count);
5425                         SSVAL(req->outbuf,smb_vwv1,
5426                               (max_count>0?first+count:first-1));
5427                         SCVAL(smb_buf(req->outbuf),0,1);
5428                         SSVAL(smb_buf(req->outbuf),1,28*count);
5429                 }
5430
5431
5432                 DEBUG(3, ("%u entries returned in queue\n",
5433                           (unsigned)count));
5434
5435 out:
5436                 if (b && is_valid_policy_hnd(&handle)) {
5437                         dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5438                 }
5439
5440         }
5441
5442         END_PROFILE(SMBsplretq);
5443         return;
5444 }
5445
5446 /****************************************************************************
5447  Reply to a printwrite.
5448 ****************************************************************************/
5449
5450 void reply_printwrite(struct smb_request *req)
5451 {
5452         connection_struct *conn = req->conn;
5453         int numtowrite;
5454         const char *data;
5455         files_struct *fsp;
5456
5457         START_PROFILE(SMBsplwr);
5458
5459         if (req->wct < 1) {
5460                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5461                 END_PROFILE(SMBsplwr);
5462                 return;
5463         }
5464
5465         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5466
5467         if (!check_fsp(conn, req, fsp)) {
5468                 END_PROFILE(SMBsplwr);
5469                 return;
5470         }
5471
5472         if (!fsp->print_file) {
5473                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5474                 END_PROFILE(SMBsplwr);
5475                 return;
5476         }
5477
5478         if (!CHECK_WRITE(fsp)) {
5479                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5480                 END_PROFILE(SMBsplwr);
5481                 return;
5482         }
5483
5484         numtowrite = SVAL(req->buf, 1);
5485
5486         if (req->buflen < numtowrite + 3) {
5487                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5488                 END_PROFILE(SMBsplwr);
5489                 return;
5490         }
5491
5492         data = (const char *)req->buf + 3;
5493
5494         if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5495                 reply_nterror(req, map_nt_error_from_unix(errno));
5496                 END_PROFILE(SMBsplwr);
5497                 return;
5498         }
5499
5500         DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5501
5502         END_PROFILE(SMBsplwr);
5503         return;
5504 }
5505
5506 /****************************************************************************
5507  Reply to a mkdir.
5508 ****************************************************************************/
5509
5510 void reply_mkdir(struct smb_request *req)
5511 {
5512         connection_struct *conn = req->conn;
5513         struct smb_filename *smb_dname = NULL;
5514         char *directory = NULL;
5515         NTSTATUS status;
5516         TALLOC_CTX *ctx = talloc_tos();
5517
5518         START_PROFILE(SMBmkdir);
5519
5520         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5521                             STR_TERMINATE, &status);
5522         if (!NT_STATUS_IS_OK(status)) {
5523                 reply_nterror(req, status);
5524                 goto out;
5525         }
5526
5527         status = filename_convert(ctx, conn,
5528                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
5529                                  directory,
5530                                  0,
5531                                  NULL,
5532                                  &smb_dname);
5533         if (!NT_STATUS_IS_OK(status)) {
5534                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5535                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5536                                         ERRSRV, ERRbadpath);
5537                         goto out;
5538                 }
5539                 reply_nterror(req, status);
5540                 goto out;
5541         }
5542
5543         status = create_directory(conn, req, smb_dname);
5544
5545         DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5546
5547         if (!NT_STATUS_IS_OK(status)) {
5548
5549                 if (!use_nt_status()
5550                     && NT_STATUS_EQUAL(status,
5551                                        NT_STATUS_OBJECT_NAME_COLLISION)) {
5552                         /*
5553                          * Yes, in the DOS error code case we get a
5554                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5555                          * samba4 torture test.
5556                          */
5557                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5558                 }
5559
5560                 reply_nterror(req, status);
5561                 goto out;
5562         }
5563
5564         reply_outbuf(req, 0, 0);
5565
5566         DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5567  out:
5568         TALLOC_FREE(smb_dname);
5569         END_PROFILE(SMBmkdir);
5570         return;
5571 }
5572
5573 /****************************************************************************
5574  Reply to a rmdir.
5575 ****************************************************************************/
5576
5577 void reply_rmdir(struct smb_request *req)
5578 {
5579         connection_struct *conn = req->conn;
5580         struct smb_filename *smb_dname = NULL;
5581         char *directory = NULL;
5582         NTSTATUS status;
5583         TALLOC_CTX *ctx = talloc_tos();
5584         files_struct *fsp = NULL;
5585         int info = 0;
5586         struct smbd_server_connection *sconn = req->sconn;
5587
5588         START_PROFILE(SMBrmdir);
5589
5590         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5591                             STR_TERMINATE, &status);
5592         if (!NT_STATUS_IS_OK(status)) {
5593                 reply_nterror(req, status);
5594                 goto out;
5595         }
5596
5597         status = filename_convert(ctx, conn,
5598                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
5599                                  directory,
5600                                  0,
5601                                  NULL,
5602                                  &smb_dname);
5603         if (!NT_STATUS_IS_OK(status)) {
5604                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5605                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5606                                         ERRSRV, ERRbadpath);
5607                         goto out;
5608                 }
5609                 reply_nterror(req, status);
5610                 goto out;
5611         }
5612
5613         if (is_ntfs_stream_smb_fname(smb_dname)) {
5614                 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5615                 goto out;
5616         }
5617
5618         status = SMB_VFS_CREATE_FILE(
5619                 conn,                                   /* conn */
5620                 req,                                    /* req */
5621                 0,                                      /* root_dir_fid */
5622                 smb_dname,                              /* fname */
5623                 DELETE_ACCESS,                          /* access_mask */
5624                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
5625                         FILE_SHARE_DELETE),
5626                 FILE_OPEN,                              /* create_disposition*/
5627                 FILE_DIRECTORY_FILE,                    /* create_options */
5628                 FILE_ATTRIBUTE_DIRECTORY,               /* file_attributes */
5629                 0,                                      /* oplock_request */
5630                 0,                                      /* allocation_size */
5631                 0,                                      /* private_flags */
5632                 NULL,                                   /* sd */
5633                 NULL,                                   /* ea_list */
5634                 &fsp,                                   /* result */
5635                 &info);                                 /* pinfo */
5636
5637         if (!NT_STATUS_IS_OK(status)) {
5638                 if (open_was_deferred(req->mid)) {
5639                         /* We have re-scheduled this call. */
5640                         goto out;
5641                 }
5642                 reply_nterror(req, status);
5643                 goto out;
5644         }
5645
5646         status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5647         if (!NT_STATUS_IS_OK(status)) {
5648                 close_file(req, fsp, ERROR_CLOSE);
5649                 reply_nterror(req, status);
5650                 goto out;
5651         }
5652
5653         if (!set_delete_on_close(fsp, true, &conn->session_info->utok)) {
5654                 close_file(req, fsp, ERROR_CLOSE);
5655                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5656                 goto out;
5657         }
5658
5659         status = close_file(req, fsp, NORMAL_CLOSE);
5660         if (!NT_STATUS_IS_OK(status)) {
5661                 reply_nterror(req, status);
5662         } else {
5663                 reply_outbuf(req, 0, 0);
5664         }
5665
5666         dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5667
5668         DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5669  out:
5670         TALLOC_FREE(smb_dname);
5671         END_PROFILE(SMBrmdir);
5672         return;
5673 }
5674
5675 /*******************************************************************
5676  Resolve wildcards in a filename rename.
5677 ********************************************************************/
5678
5679 static bool resolve_wildcards(TALLOC_CTX *ctx,
5680                                 const char *name1,
5681                                 const char *name2,
5682                                 char **pp_newname)
5683 {
5684         char *name2_copy = NULL;
5685         char *root1 = NULL;
5686         char *root2 = NULL;
5687         char *ext1 = NULL;
5688         char *ext2 = NULL;
5689         char *p,*p2, *pname1, *pname2;
5690
5691         name2_copy = talloc_strdup(ctx, name2);
5692         if (!name2_copy) {
5693                 return False;
5694         }
5695
5696         pname1 = strrchr_m(name1,'/');
5697         pname2 = strrchr_m(name2_copy,'/');
5698
5699         if (!pname1 || !pname2) {
5700                 return False;
5701         }
5702
5703         /* Truncate the copy of name2 at the last '/' */
5704         *pname2 = '\0';
5705
5706         /* Now go past the '/' */
5707         pname1++;
5708         pname2++;
5709
5710         root1 = talloc_strdup(ctx, pname1);
5711         root2 = talloc_strdup(ctx, pname2);
5712
5713         if (!root1 || !root2) {
5714                 return False;
5715         }
5716
5717         p = strrchr_m(root1,'.');
5718         if (p) {
5719                 *p = 0;
5720                 ext1 = talloc_strdup(ctx, p+1);
5721         } else {
5722                 ext1 = talloc_strdup(ctx, "");
5723         }
5724         p = strrchr_m(root2,'.');
5725         if (p) {
5726                 *p = 0;
5727                 ext2 = talloc_strdup(ctx, p+1);
5728         } else {
5729                 ext2 = talloc_strdup(ctx, "");
5730         }
5731
5732         if (!ext1 || !ext2) {
5733                 return False;
5734         }
5735
5736         p = root1;
5737         p2 = root2;
5738         while (*p2) {
5739                 if (*p2 == '?') {
5740                         /* Hmmm. Should this be mb-aware ? */
5741                         *p2 = *p;
5742                         p2++;
5743                 } else if (*p2 == '*') {
5744                         *p2 = '\0';
5745                         root2 = talloc_asprintf(ctx, "%s%s",
5746                                                 root2,
5747                                                 p);
5748                         if (!root2) {
5749                                 return False;
5750                         }
5751                         break;
5752                 } else {
5753                         p2++;
5754                 }
5755                 if (*p) {
5756                         p++;
5757                 }
5758         }
5759
5760         p = ext1;
5761         p2 = ext2;
5762         while (*p2) {
5763                 if (*p2 == '?') {
5764                         /* Hmmm. Should this be mb-aware ? */
5765                         *p2 = *p;
5766                         p2++;
5767                 } else if (*p2 == '*') {
5768                         *p2 = '\0';
5769                         ext2 = talloc_asprintf(ctx, "%s%s",
5770                                                 ext2,
5771                                                 p);
5772                         if (!ext2) {
5773                                 return False;
5774                         }
5775                         break;
5776                 } else {
5777                         p2++;
5778                 }
5779                 if (*p) {
5780                         p++;
5781                 }
5782         }
5783
5784         if (*ext2) {
5785                 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5786                                 name2_copy,
5787                                 root2,
5788                                 ext2);
5789         } else {
5790                 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5791                                 name2_copy,
5792                                 root2);
5793         }
5794
5795         if (!*pp_newname) {
5796                 return False;
5797         }
5798
5799         return True;
5800 }
5801
5802 /****************************************************************************
5803  Ensure open files have their names updated. Updated to notify other smbd's
5804  asynchronously.
5805 ****************************************************************************/
5806
5807 static void rename_open_files(connection_struct *conn,
5808                               struct share_mode_lock *lck,
5809                               uint32_t orig_name_hash,
5810                               const struct smb_filename *smb_fname_dst)
5811 {
5812         files_struct *fsp;
5813         bool did_rename = False;
5814         NTSTATUS status;
5815         uint32_t new_name_hash;
5816
5817         for(fsp = file_find_di_first(conn->sconn, lck->id); fsp;
5818             fsp = file_find_di_next(fsp)) {
5819                 /* fsp_name is a relative path under the fsp. To change this for other
5820                    sharepaths we need to manipulate relative paths. */
5821                 /* TODO - create the absolute path and manipulate the newname
5822                    relative to the sharepath. */
5823                 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5824                         continue;
5825                 }
5826                 if (fsp->name_hash != orig_name_hash) {
5827                         continue;
5828                 }
5829                 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5830                            "(file_id %s) from %s -> %s\n", fsp->fnum,
5831                            file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5832                            smb_fname_str_dbg(smb_fname_dst)));
5833
5834                 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5835                 if (NT_STATUS_IS_OK(status)) {
5836                         did_rename = True;
5837                         new_name_hash = fsp->name_hash;
5838                 }
5839         }
5840
5841         if (!did_rename) {
5842                 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5843                            "for %s\n", file_id_string_tos(&lck->id),
5844                            smb_fname_str_dbg(smb_fname_dst)));
5845         }
5846
5847         /* Send messages to all smbd's (not ourself) that the name has changed. */
5848         rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5849                               orig_name_hash, new_name_hash,
5850                               smb_fname_dst);
5851
5852 }
5853
5854 /****************************************************************************
5855  We need to check if the source path is a parent directory of the destination
5856  (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5857  refuse the rename with a sharing violation. Under UNIX the above call can
5858  *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5859  probably need to check that the client is a Windows one before disallowing
5860  this as a UNIX client (one with UNIX extensions) can know the source is a
5861  symlink and make this decision intelligently. Found by an excellent bug
5862  report from <AndyLiebman@aol.com>.
5863 ****************************************************************************/
5864
5865 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5866                                      const struct smb_filename *smb_fname_dst)
5867 {
5868         const char *psrc = smb_fname_src->base_name;
5869         const char *pdst = smb_fname_dst->base_name;
5870         size_t slen;
5871
5872         if (psrc[0] == '.' && psrc[1] == '/') {
5873                 psrc += 2;
5874         }
5875         if (pdst[0] == '.' && pdst[1] == '/') {
5876                 pdst += 2;
5877         }
5878         if ((slen = strlen(psrc)) > strlen(pdst)) {
5879                 return False;
5880         }
5881         return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5882 }
5883
5884 /*
5885  * Do the notify calls from a rename
5886  */
5887
5888 static void notify_rename(connection_struct *conn, bool is_dir,
5889                           const struct smb_filename *smb_fname_src,
5890                           const struct smb_filename *smb_fname_dst)
5891 {
5892         char *parent_dir_src = NULL;
5893         char *parent_dir_dst = NULL;
5894         uint32 mask;
5895
5896         mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5897                 : FILE_NOTIFY_CHANGE_FILE_NAME;
5898
5899         if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5900                             &parent_dir_src, NULL) ||
5901             !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5902                             &parent_dir_dst, NULL)) {
5903                 goto out;
5904         }
5905
5906         if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5907                 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5908                              smb_fname_src->base_name);
5909                 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5910                              smb_fname_dst->base_name);
5911         }
5912         else {
5913                 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5914                              smb_fname_src->base_name);
5915                 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5916                              smb_fname_dst->base_name);
5917         }
5918
5919         /* this is a strange one. w2k3 gives an additional event for
5920            CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5921            files, but not directories */
5922         if (!is_dir) {
5923                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5924                              FILE_NOTIFY_CHANGE_ATTRIBUTES
5925                              |FILE_NOTIFY_CHANGE_CREATION,
5926                              smb_fname_dst->base_name);
5927         }
5928  out:
5929         TALLOC_FREE(parent_dir_src);
5930         TALLOC_FREE(parent_dir_dst);
5931 }
5932
5933 /****************************************************************************
5934  Rename an open file - given an fsp.
5935 ****************************************************************************/
5936
5937 NTSTATUS rename_internals_fsp(connection_struct *conn,
5938                         files_struct *fsp,
5939                         const struct smb_filename *smb_fname_dst_in,
5940                         uint32 attrs,
5941                         bool replace_if_exists)
5942 {
5943         TALLOC_CTX *ctx = talloc_tos();
5944         struct smb_filename *smb_fname_dst = NULL;
5945         NTSTATUS status = NT_STATUS_OK;
5946         struct share_mode_lock *lck = NULL;
5947         bool dst_exists, old_is_stream, new_is_stream;
5948
5949         status = check_name(conn, smb_fname_dst_in->base_name);
5950         if (!NT_STATUS_IS_OK(status)) {
5951                 return status;
5952         }
5953
5954         /* Make a copy of the dst smb_fname structs */
5955
5956         status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5957         if (!NT_STATUS_IS_OK(status)) {
5958                 goto out;
5959         }
5960
5961         /*
5962          * Check for special case with case preserving and not
5963          * case sensitive. If the old last component differs from the original
5964          * last component only by case, then we should allow
5965          * the rename (user is trying to change the case of the
5966          * filename).
5967          */
5968         if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5969             strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5970             strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
5971                 char *last_slash;
5972                 char *fname_dst_lcomp_base_mod = NULL;
5973                 struct smb_filename *smb_fname_orig_lcomp = NULL;
5974
5975                 /*
5976                  * Get the last component of the destination name.
5977                  */
5978                 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5979                 if (last_slash) {
5980                         fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5981                 } else {
5982                         fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
5983                 }
5984                 if (!fname_dst_lcomp_base_mod) {
5985                         status = NT_STATUS_NO_MEMORY;
5986                         goto out;
5987                 }
5988
5989                 /*
5990                  * Create an smb_filename struct using the original last
5991                  * component of the destination.
5992                  */
5993                 status = create_synthetic_smb_fname_split(ctx,
5994                     smb_fname_dst->original_lcomp, NULL,
5995                     &smb_fname_orig_lcomp);
5996                 if (!NT_STATUS_IS_OK(status)) {
5997                         TALLOC_FREE(fname_dst_lcomp_base_mod);
5998                         goto out;
5999                 }
6000
6001                 /* If the base names only differ by case, use original. */
6002                 if(!strcsequal(fname_dst_lcomp_base_mod,
6003                                smb_fname_orig_lcomp->base_name)) {
6004                         char *tmp;
6005                         /*
6006                          * Replace the modified last component with the
6007                          * original.
6008                          */
6009                         if (last_slash) {
6010                                 *last_slash = '\0'; /* Truncate at the '/' */
6011                                 tmp = talloc_asprintf(smb_fname_dst,
6012                                         "%s/%s",
6013                                         smb_fname_dst->base_name,
6014                                         smb_fname_orig_lcomp->base_name);
6015                         } else {
6016                                 tmp = talloc_asprintf(smb_fname_dst,
6017                                         "%s",
6018                                         smb_fname_orig_lcomp->base_name);
6019                         }
6020                         if (tmp == NULL) {
6021                                 status = NT_STATUS_NO_MEMORY;
6022                                 TALLOC_FREE(fname_dst_lcomp_base_mod);
6023                                 TALLOC_FREE(smb_fname_orig_lcomp);
6024                                 goto out;
6025                         }
6026                         TALLOC_FREE(smb_fname_dst->base_name);
6027                         smb_fname_dst->base_name = tmp;
6028                 }
6029
6030                 /* If the stream_names only differ by case, use original. */
6031                 if(!strcsequal(smb_fname_dst->stream_name,
6032                                smb_fname_orig_lcomp->stream_name)) {
6033                         char *tmp = NULL;
6034                         /* Use the original stream. */
6035                         tmp = talloc_strdup(smb_fname_dst,
6036                                             smb_fname_orig_lcomp->stream_name);
6037                         if (tmp == NULL) {
6038                                 status = NT_STATUS_NO_MEMORY;
6039                                 TALLOC_FREE(fname_dst_lcomp_base_mod);
6040                                 TALLOC_FREE(smb_fname_orig_lcomp);
6041                                 goto out;
6042                         }
6043                         TALLOC_FREE(smb_fname_dst->stream_name);
6044                         smb_fname_dst->stream_name = tmp;
6045                 }
6046                 TALLOC_FREE(fname_dst_lcomp_base_mod);
6047                 TALLOC_FREE(smb_fname_orig_lcomp);
6048         }
6049
6050         /*
6051          * If the src and dest names are identical - including case,
6052          * don't do the rename, just return success.
6053          */
6054
6055         if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6056             strcsequal(fsp->fsp_name->stream_name,
6057                        smb_fname_dst->stream_name)) {
6058                 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6059                           "- returning success\n",
6060                           smb_fname_str_dbg(smb_fname_dst)));
6061                 status = NT_STATUS_OK;
6062                 goto out;
6063         }
6064
6065         old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6066         new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6067
6068         /* Return the correct error code if both names aren't streams. */
6069         if (!old_is_stream && new_is_stream) {
6070                 status = NT_STATUS_OBJECT_NAME_INVALID;
6071                 goto out;
6072         }
6073
6074         if (old_is_stream && !new_is_stream) {
6075                 status = NT_STATUS_INVALID_PARAMETER;
6076                 goto out;
6077         }
6078
6079         dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6080
6081         if(!replace_if_exists && dst_exists) {
6082                 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6083                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6084                           smb_fname_str_dbg(smb_fname_dst)));
6085                 status = NT_STATUS_OBJECT_NAME_COLLISION;
6086                 goto out;
6087         }
6088
6089         if (dst_exists) {
6090                 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6091                     &smb_fname_dst->st);
6092                 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6093                                                            fileid);
6094                 /* The file can be open when renaming a stream */
6095                 if (dst_fsp && !new_is_stream) {
6096                         DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6097                         status = NT_STATUS_ACCESS_DENIED;
6098                         goto out;
6099                 }
6100         }
6101
6102         /* Ensure we have a valid stat struct for the source. */
6103         status = vfs_stat_fsp(fsp);
6104         if (!NT_STATUS_IS_OK(status)) {
6105                 goto out;
6106         }
6107
6108         status = can_rename(conn, fsp, attrs);
6109
6110         if (!NT_STATUS_IS_OK(status)) {
6111                 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6112                           nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6113                           smb_fname_str_dbg(smb_fname_dst)));
6114                 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6115                         status = NT_STATUS_ACCESS_DENIED;
6116                 goto out;
6117         }
6118
6119         if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6120                 status = NT_STATUS_ACCESS_DENIED;
6121         }
6122
6123         lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6124                                   NULL);
6125
6126         /*
6127          * We have the file open ourselves, so not being able to get the
6128          * corresponding share mode lock is a fatal error.
6129          */
6130
6131         SMB_ASSERT(lck != NULL);
6132
6133         if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6134                 uint32 create_options = fsp->fh->private_options;
6135
6136                 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6137                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6138                           smb_fname_str_dbg(smb_fname_dst)));
6139
6140                 if (!lp_posix_pathnames() &&
6141                     (lp_map_archive(SNUM(conn)) ||
6142                     lp_store_dos_attributes(SNUM(conn)))) {
6143                         /* We must set the archive bit on the newly
6144                            renamed file. */
6145                         if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6146                                 uint32_t old_dosmode = dos_mode(conn,
6147                                                         smb_fname_dst);
6148                                 file_set_dosmode(conn,
6149                                         smb_fname_dst,
6150                                         old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6151                                         NULL,
6152                                         true);
6153                         }
6154                 }
6155
6156                 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6157                               smb_fname_dst);
6158
6159                 rename_open_files(conn, lck, fsp->name_hash, smb_fname_dst);
6160
6161                 /*
6162                  * A rename acts as a new file create w.r.t. allowing an initial delete
6163                  * on close, probably because in Windows there is a new handle to the
6164                  * new file. If initial delete on close was requested but not
6165                  * originally set, we need to set it here. This is probably not 100% correct,
6166                  * but will work for the CIFSFS client which in non-posix mode
6167                  * depends on these semantics. JRA.
6168                  */
6169
6170                 if (create_options & FILE_DELETE_ON_CLOSE) {
6171                         status = can_set_delete_on_close(fsp, 0);
6172
6173                         if (NT_STATUS_IS_OK(status)) {
6174                                 /* Note that here we set the *inital* delete on close flag,
6175                                  * not the regular one. The magic gets handled in close. */
6176                                 fsp->initial_delete_on_close = True;
6177                         }
6178                 }
6179                 TALLOC_FREE(lck);
6180                 status = NT_STATUS_OK;
6181                 goto out;
6182         }
6183
6184         TALLOC_FREE(lck);
6185
6186         if (errno == ENOTDIR || errno == EISDIR) {
6187                 status = NT_STATUS_OBJECT_NAME_COLLISION;
6188         } else {
6189                 status = map_nt_error_from_unix(errno);
6190         }
6191
6192         DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6193                   nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6194                   smb_fname_str_dbg(smb_fname_dst)));
6195
6196  out:
6197         TALLOC_FREE(smb_fname_dst);
6198
6199         return status;
6200 }
6201
6202 /****************************************************************************
6203  The guts of the rename command, split out so it may be called by the NT SMB
6204  code.
6205 ****************************************************************************/
6206
6207 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6208                         connection_struct *conn,
6209                         struct smb_request *req,
6210                         struct smb_filename *smb_fname_src,
6211                         struct smb_filename *smb_fname_dst,
6212                         uint32 attrs,
6213                         bool replace_if_exists,
6214                         bool src_has_wild,
6215                         bool dest_has_wild,
6216                         uint32_t access_mask)
6217 {
6218         char *fname_src_dir = NULL;
6219         char *fname_src_mask = NULL;
6220         int count=0;
6221         NTSTATUS status = NT_STATUS_OK;
6222         struct smb_Dir *dir_hnd = NULL;
6223         const char *dname = NULL;
6224         char *talloced = NULL;
6225         long offset = 0;
6226         int create_options = 0;
6227         bool posix_pathnames = lp_posix_pathnames();
6228
6229         /*
6230          * Split the old name into directory and last component
6231          * strings. Note that unix_convert may have stripped off a
6232          * leading ./ from both name and newname if the rename is
6233          * at the root of the share. We need to make sure either both
6234          * name and newname contain a / character or neither of them do
6235          * as this is checked in resolve_wildcards().
6236          */
6237
6238         /* Split up the directory from the filename/mask. */
6239         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6240                                       &fname_src_dir, &fname_src_mask);
6241         if (!NT_STATUS_IS_OK(status)) {
6242                 status = NT_STATUS_NO_MEMORY;
6243                 goto out;
6244         }
6245
6246         /*
6247          * We should only check the mangled cache
6248          * here if unix_convert failed. This means
6249          * that the path in 'mask' doesn't exist
6250          * on the file system and so we need to look
6251          * for a possible mangle. This patch from
6252          * Tine Smukavec <valentin.smukavec@hermes.si>.
6253          */
6254
6255         if (!VALID_STAT(smb_fname_src->st) &&
6256             mangle_is_mangled(fname_src_mask, conn->params)) {
6257                 char *new_mask = NULL;
6258                 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6259                                             conn->params);
6260                 if (new_mask) {
6261                         TALLOC_FREE(fname_src_mask);
6262                         fname_src_mask = new_mask;
6263                 }
6264         }
6265
6266         if (!src_has_wild) {
6267                 files_struct *fsp;
6268
6269                 /*
6270                  * Only one file needs to be renamed. Append the mask back
6271                  * onto the directory.
6272                  */
6273                 TALLOC_FREE(smb_fname_src->base_name);
6274                 if (ISDOT(fname_src_dir)) {
6275                         /* Ensure we use canonical names on open. */
6276                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6277                                                         "%s",
6278                                                         fname_src_mask);
6279                 } else {
6280                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6281                                                         "%s/%s",
6282                                                         fname_src_dir,
6283                                                         fname_src_mask);
6284                 }
6285                 if (!smb_fname_src->base_name) {
6286                         status = NT_STATUS_NO_MEMORY;
6287                         goto out;
6288                 }
6289
6290                 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6291                           "case_preserve = %d, short case preserve = %d, "
6292                           "directory = %s, newname = %s, "
6293                           "last_component_dest = %s\n",
6294                           conn->case_sensitive, conn->case_preserve,
6295                           conn->short_case_preserve,
6296                           smb_fname_str_dbg(smb_fname_src),
6297                           smb_fname_str_dbg(smb_fname_dst),
6298                           smb_fname_dst->original_lcomp));
6299
6300                 /* The dest name still may have wildcards. */
6301                 if (dest_has_wild) {
6302                         char *fname_dst_mod = NULL;
6303                         if (!resolve_wildcards(smb_fname_dst,
6304                                                smb_fname_src->base_name,
6305                                                smb_fname_dst->base_name,
6306                                                &fname_dst_mod)) {
6307                                 DEBUG(6, ("rename_internals: resolve_wildcards "
6308                                           "%s %s failed\n",
6309                                           smb_fname_src->base_name,
6310                                           smb_fname_dst->base_name));
6311                                 status = NT_STATUS_NO_MEMORY;
6312                                 goto out;
6313                         }
6314                         TALLOC_FREE(smb_fname_dst->base_name);
6315                         smb_fname_dst->base_name = fname_dst_mod;
6316                 }
6317
6318                 ZERO_STRUCT(smb_fname_src->st);
6319                 if (posix_pathnames) {
6320                         SMB_VFS_LSTAT(conn, smb_fname_src);
6321                 } else {
6322                         SMB_VFS_STAT(conn, smb_fname_src);
6323                 }
6324
6325                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6326                         create_options |= FILE_DIRECTORY_FILE;
6327                 }
6328
6329                 status = SMB_VFS_CREATE_FILE(
6330                         conn,                           /* conn */
6331                         req,                            /* req */
6332                         0,                              /* root_dir_fid */
6333                         smb_fname_src,                  /* fname */
6334                         access_mask,                    /* access_mask */
6335                         (FILE_SHARE_READ |              /* share_access */
6336                             FILE_SHARE_WRITE),
6337                         FILE_OPEN,                      /* create_disposition*/
6338                         create_options,                 /* create_options */
6339                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6340                         0,                              /* oplock_request */
6341                         0,                              /* allocation_size */
6342                         0,                              /* private_flags */
6343                         NULL,                           /* sd */
6344                         NULL,                           /* ea_list */
6345                         &fsp,                           /* result */
6346                         NULL);                          /* pinfo */
6347
6348                 if (!NT_STATUS_IS_OK(status)) {
6349                         DEBUG(3, ("Could not open rename source %s: %s\n",
6350                                   smb_fname_str_dbg(smb_fname_src),
6351                                   nt_errstr(status)));
6352                         goto out;
6353                 }
6354
6355                 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6356                                               attrs, replace_if_exists);
6357
6358                 close_file(req, fsp, NORMAL_CLOSE);
6359
6360                 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6361                           nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6362                           smb_fname_str_dbg(smb_fname_dst)));
6363
6364                 goto out;
6365         }
6366
6367         /*
6368          * Wildcards - process each file that matches.
6369          */
6370         if (strequal(fname_src_mask, "????????.???")) {
6371                 TALLOC_FREE(fname_src_mask);
6372                 fname_src_mask = talloc_strdup(ctx, "*");
6373                 if (!fname_src_mask) {
6374                         status = NT_STATUS_NO_MEMORY;
6375                         goto out;
6376                 }
6377         }
6378
6379         status = check_name(conn, fname_src_dir);
6380         if (!NT_STATUS_IS_OK(status)) {
6381                 goto out;
6382         }
6383
6384         dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6385                           attrs);
6386         if (dir_hnd == NULL) {
6387                 status = map_nt_error_from_unix(errno);
6388                 goto out;
6389         }
6390
6391         status = NT_STATUS_NO_SUCH_FILE;
6392         /*
6393          * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6394          * - gentest fix. JRA
6395          */
6396
6397         while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6398                                     &talloced))) {
6399                 files_struct *fsp = NULL;
6400                 char *destname = NULL;
6401                 bool sysdir_entry = False;
6402
6403                 /* Quick check for "." and ".." */
6404                 if (ISDOT(dname) || ISDOTDOT(dname)) {
6405                         if (attrs & aDIR) {
6406                                 sysdir_entry = True;
6407                         } else {
6408                                 TALLOC_FREE(talloced);
6409                                 continue;
6410                         }
6411                 }
6412
6413                 if (!is_visible_file(conn, fname_src_dir, dname,
6414                                      &smb_fname_src->st, false)) {
6415                         TALLOC_FREE(talloced);
6416                         continue;
6417                 }
6418
6419                 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6420                         TALLOC_FREE(talloced);
6421                         continue;
6422                 }
6423
6424                 if (sysdir_entry) {
6425                         status = NT_STATUS_OBJECT_NAME_INVALID;
6426                         break;
6427                 }
6428
6429                 TALLOC_FREE(smb_fname_src->base_name);
6430                 if (ISDOT(fname_src_dir)) {
6431                         /* Ensure we use canonical names on open. */
6432                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6433                                                         "%s",
6434                                                         dname);
6435                 } else {
6436                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6437                                                         "%s/%s",
6438                                                         fname_src_dir,
6439                                                         dname);
6440                 }
6441                 if (!smb_fname_src->base_name) {
6442                         status = NT_STATUS_NO_MEMORY;
6443                         goto out;
6444                 }
6445
6446                 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6447                                        smb_fname_dst->base_name,
6448                                        &destname)) {
6449                         DEBUG(6, ("resolve_wildcards %s %s failed\n",
6450                                   smb_fname_src->base_name, destname));
6451                         TALLOC_FREE(talloced);
6452                         continue;
6453                 }
6454                 if (!destname) {
6455                         status = NT_STATUS_NO_MEMORY;
6456                         goto out;
6457                 }
6458
6459                 TALLOC_FREE(smb_fname_dst->base_name);
6460                 smb_fname_dst->base_name = destname;
6461
6462                 ZERO_STRUCT(smb_fname_src->st);
6463                 if (posix_pathnames) {
6464                         SMB_VFS_LSTAT(conn, smb_fname_src);
6465                 } else {
6466                         SMB_VFS_STAT(conn, smb_fname_src);
6467                 }
6468
6469                 create_options = 0;
6470
6471                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6472                         create_options |= FILE_DIRECTORY_FILE;
6473                 }
6474
6475                 status = SMB_VFS_CREATE_FILE(
6476                         conn,                           /* conn */
6477                         req,                            /* req */
6478                         0,                              /* root_dir_fid */
6479                         smb_fname_src,                  /* fname */
6480                         access_mask,                    /* access_mask */
6481                         (FILE_SHARE_READ |              /* share_access */
6482                             FILE_SHARE_WRITE),
6483                         FILE_OPEN,                      /* create_disposition*/
6484                         create_options,                 /* create_options */
6485                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6486                         0,                              /* oplock_request */
6487                         0,                              /* allocation_size */
6488                         0,                              /* private_flags */
6489                         NULL,                           /* sd */
6490                         NULL,                           /* ea_list */
6491                         &fsp,                           /* result */
6492                         NULL);                          /* pinfo */
6493
6494                 if (!NT_STATUS_IS_OK(status)) {
6495                         DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6496                                  "returned %s rename %s -> %s\n",
6497                                  nt_errstr(status),
6498                                  smb_fname_str_dbg(smb_fname_src),
6499                                  smb_fname_str_dbg(smb_fname_dst)));
6500                         break;
6501                 }
6502
6503                 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6504                                                               dname);
6505                 if (!smb_fname_dst->original_lcomp) {
6506                         status = NT_STATUS_NO_MEMORY;
6507                         goto out;
6508                 }
6509
6510                 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6511                                               attrs, replace_if_exists);
6512
6513                 close_file(req, fsp, NORMAL_CLOSE);
6514
6515                 if (!NT_STATUS_IS_OK(status)) {
6516                         DEBUG(3, ("rename_internals_fsp returned %s for "
6517                                   "rename %s -> %s\n", nt_errstr(status),
6518                                   smb_fname_str_dbg(smb_fname_src),
6519                                   smb_fname_str_dbg(smb_fname_dst)));
6520                         break;
6521                 }
6522
6523                 count++;
6524
6525                 DEBUG(3,("rename_internals: doing rename on %s -> "
6526                          "%s\n", smb_fname_str_dbg(smb_fname_src),
6527                          smb_fname_str_dbg(smb_fname_src)));
6528                 TALLOC_FREE(talloced);
6529         }
6530         TALLOC_FREE(dir_hnd);
6531
6532         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6533                 status = map_nt_error_from_unix(errno);
6534         }
6535
6536  out:
6537         TALLOC_FREE(talloced);
6538         TALLOC_FREE(fname_src_dir);
6539         TALLOC_FREE(fname_src_mask);
6540         return status;
6541 }
6542
6543 /****************************************************************************
6544  Reply to a mv.
6545 ****************************************************************************/
6546
6547 void reply_mv(struct smb_request *req)
6548 {
6549         connection_struct *conn = req->conn;
6550         char *name = NULL;
6551         char *newname = NULL;
6552         const char *p;
6553         uint32 attrs;
6554         NTSTATUS status;
6555         bool src_has_wcard = False;
6556         bool dest_has_wcard = False;
6557         TALLOC_CTX *ctx = talloc_tos();
6558         struct smb_filename *smb_fname_src = NULL;
6559         struct smb_filename *smb_fname_dst = NULL;
6560         bool stream_rename = false;
6561
6562         START_PROFILE(SMBmv);
6563
6564         if (req->wct < 1) {
6565                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6566                 goto out;
6567         }
6568
6569         attrs = SVAL(req->vwv+0, 0);
6570
6571         p = (const char *)req->buf + 1;
6572         p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6573                                        &status, &src_has_wcard);
6574         if (!NT_STATUS_IS_OK(status)) {
6575                 reply_nterror(req, status);
6576                 goto out;
6577         }
6578         p++;
6579         p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6580                                        &status, &dest_has_wcard);
6581         if (!NT_STATUS_IS_OK(status)) {
6582                 reply_nterror(req, status);
6583                 goto out;
6584         }
6585
6586         if (!lp_posix_pathnames()) {
6587                 /* The newname must begin with a ':' if the
6588                    name contains a ':'. */
6589                 if (strchr_m(name, ':')) {
6590                         if (newname[0] != ':') {
6591                                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6592                                 goto out;
6593                         }
6594                         stream_rename = true;
6595                 }
6596         }
6597
6598         status = filename_convert(ctx,
6599                                   conn,
6600                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6601                                   name,
6602                                   UCF_COND_ALLOW_WCARD_LCOMP,
6603                                   &src_has_wcard,
6604                                   &smb_fname_src);
6605
6606         if (!NT_STATUS_IS_OK(status)) {
6607                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6608                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6609                                         ERRSRV, ERRbadpath);
6610                         goto out;
6611                 }
6612                 reply_nterror(req, status);
6613                 goto out;
6614         }
6615
6616         status = filename_convert(ctx,
6617                                   conn,
6618                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6619                                   newname,
6620                                   UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6621                                   &dest_has_wcard,
6622                                   &smb_fname_dst);
6623
6624         if (!NT_STATUS_IS_OK(status)) {
6625                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6626                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6627                                         ERRSRV, ERRbadpath);
6628                         goto out;
6629                 }
6630                 reply_nterror(req, status);
6631                 goto out;
6632         }
6633
6634         if (stream_rename) {
6635                 /* smb_fname_dst->base_name must be the same as
6636                    smb_fname_src->base_name. */
6637                 TALLOC_FREE(smb_fname_dst->base_name);
6638                 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6639                                                 smb_fname_src->base_name);
6640                 if (!smb_fname_dst->base_name) {
6641                         reply_nterror(req, NT_STATUS_NO_MEMORY);
6642                         goto out;
6643                 }
6644         }
6645
6646         DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6647                  smb_fname_str_dbg(smb_fname_dst)));
6648
6649         status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6650                                   attrs, False, src_has_wcard, dest_has_wcard,
6651                                   DELETE_ACCESS);
6652         if (!NT_STATUS_IS_OK(status)) {
6653                 if (open_was_deferred(req->mid)) {
6654                         /* We have re-scheduled this call. */
6655                         goto out;
6656                 }
6657                 reply_nterror(req, status);
6658                 goto out;
6659         }
6660
6661         reply_outbuf(req, 0, 0);
6662  out:
6663         TALLOC_FREE(smb_fname_src);
6664         TALLOC_FREE(smb_fname_dst);
6665         END_PROFILE(SMBmv);
6666         return;
6667 }
6668
6669 /*******************************************************************
6670  Copy a file as part of a reply_copy.
6671 ******************************************************************/
6672
6673 /*
6674  * TODO: check error codes on all callers
6675  */
6676
6677 NTSTATUS copy_file(TALLOC_CTX *ctx,
6678                         connection_struct *conn,
6679                         struct smb_filename *smb_fname_src,
6680                         struct smb_filename *smb_fname_dst,
6681                         int ofun,
6682                         int count,
6683                         bool target_is_directory)
6684 {
6685         struct smb_filename *smb_fname_dst_tmp = NULL;
6686         SMB_OFF_T ret=-1;
6687         files_struct *fsp1,*fsp2;
6688         uint32 dosattrs;
6689         uint32 new_create_disposition;
6690         NTSTATUS status;
6691
6692
6693         status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6694         if (!NT_STATUS_IS_OK(status)) {
6695                 return status;
6696         }
6697
6698         /*
6699          * If the target is a directory, extract the last component from the
6700          * src filename and append it to the dst filename
6701          */
6702         if (target_is_directory) {
6703                 const char *p;
6704
6705                 /* dest/target can't be a stream if it's a directory. */
6706                 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6707
6708                 p = strrchr_m(smb_fname_src->base_name,'/');
6709                 if (p) {
6710                         p++;
6711                 } else {
6712                         p = smb_fname_src->base_name;
6713                 }
6714                 smb_fname_dst_tmp->base_name =
6715                     talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6716                                            p);
6717                 if (!smb_fname_dst_tmp->base_name) {
6718                         status = NT_STATUS_NO_MEMORY;
6719                         goto out;
6720                 }
6721         }
6722
6723         status = vfs_file_exist(conn, smb_fname_src);
6724         if (!NT_STATUS_IS_OK(status)) {
6725                 goto out;
6726         }
6727
6728         if (!target_is_directory && count) {
6729                 new_create_disposition = FILE_OPEN;
6730         } else {
6731                 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
6732                                                  NULL, NULL,
6733                                                  &new_create_disposition,
6734                                                  NULL,
6735                                                  NULL)) {
6736                         status = NT_STATUS_INVALID_PARAMETER;
6737                         goto out;
6738                 }
6739         }
6740
6741         /* Open the src file for reading. */
6742         status = SMB_VFS_CREATE_FILE(
6743                 conn,                                   /* conn */
6744                 NULL,                                   /* req */
6745                 0,                                      /* root_dir_fid */
6746                 smb_fname_src,                          /* fname */
6747                 FILE_GENERIC_READ,                      /* access_mask */
6748                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
6749                 FILE_OPEN,                              /* create_disposition*/
6750                 0,                                      /* create_options */
6751                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
6752                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
6753                 0,                                      /* allocation_size */
6754                 0,                                      /* private_flags */
6755                 NULL,                                   /* sd */
6756                 NULL,                                   /* ea_list */
6757                 &fsp1,                                  /* result */
6758                 NULL);                                  /* psbuf */
6759
6760         if (!NT_STATUS_IS_OK(status)) {
6761                 goto out;
6762         }
6763
6764         dosattrs = dos_mode(conn, smb_fname_src);
6765
6766         if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6767                 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6768         }
6769
6770         /* Open the dst file for writing. */
6771         status = SMB_VFS_CREATE_FILE(
6772                 conn,                                   /* conn */
6773                 NULL,                                   /* req */
6774                 0,                                      /* root_dir_fid */
6775                 smb_fname_dst,                          /* fname */
6776                 FILE_GENERIC_WRITE,                     /* access_mask */
6777                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
6778                 new_create_disposition,                 /* create_disposition*/
6779                 0,                                      /* create_options */
6780                 dosattrs,                               /* file_attributes */
6781                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
6782                 0,                                      /* allocation_size */
6783                 0,                                      /* private_flags */
6784                 NULL,                                   /* sd */
6785                 NULL,                                   /* ea_list */
6786                 &fsp2,                                  /* result */
6787                 NULL);                                  /* psbuf */
6788
6789         if (!NT_STATUS_IS_OK(status)) {
6790                 close_file(NULL, fsp1, ERROR_CLOSE);
6791                 goto out;
6792         }
6793
6794         if (ofun & OPENX_FILE_EXISTS_OPEN) {
6795                 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
6796                 if (ret == -1) {
6797                         DEBUG(0, ("error - vfs lseek returned error %s\n",
6798                                 strerror(errno)));
6799                         status = map_nt_error_from_unix(errno);
6800                         close_file(NULL, fsp1, ERROR_CLOSE);
6801                         close_file(NULL, fsp2, ERROR_CLOSE);
6802                         goto out;
6803                 }
6804         }
6805
6806         /* Do the actual copy. */
6807         if (smb_fname_src->st.st_ex_size) {
6808                 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6809         } else {
6810                 ret = 0;
6811         }
6812
6813         close_file(NULL, fsp1, NORMAL_CLOSE);
6814
6815         /* Ensure the modtime is set correctly on the destination file. */
6816         set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6817
6818         /*
6819          * As we are opening fsp1 read-only we only expect
6820          * an error on close on fsp2 if we are out of space.
6821          * Thus we don't look at the error return from the
6822          * close of fsp1.
6823          */
6824         status = close_file(NULL, fsp2, NORMAL_CLOSE);
6825
6826         if (!NT_STATUS_IS_OK(status)) {
6827                 goto out;
6828         }
6829
6830         if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6831                 status = NT_STATUS_DISK_FULL;
6832                 goto out;
6833         }
6834
6835         status = NT_STATUS_OK;
6836
6837  out:
6838         TALLOC_FREE(smb_fname_dst_tmp);
6839         return status;
6840 }
6841
6842 /****************************************************************************
6843  Reply to a file copy.
6844 ****************************************************************************/
6845
6846 void reply_copy(struct smb_request *req)
6847 {
6848         connection_struct *conn = req->conn;
6849         struct smb_filename *smb_fname_src = NULL;
6850         struct smb_filename *smb_fname_dst = NULL;
6851         char *fname_src = NULL;
6852         char *fname_dst = NULL;
6853         char *fname_src_mask = NULL;
6854         char *fname_src_dir = NULL;
6855         const char *p;
6856         int count=0;
6857         int error = ERRnoaccess;
6858         int tid2;
6859         int ofun;
6860         int flags;
6861         bool target_is_directory=False;
6862         bool source_has_wild = False;
6863         bool dest_has_wild = False;
6864         NTSTATUS status;
6865         TALLOC_CTX *ctx = talloc_tos();
6866
6867         START_PROFILE(SMBcopy);
6868
6869         if (req->wct < 3) {
6870                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6871                 goto out;
6872         }
6873
6874         tid2 = SVAL(req->vwv+0, 0);
6875         ofun = SVAL(req->vwv+1, 0);
6876         flags = SVAL(req->vwv+2, 0);
6877
6878         p = (const char *)req->buf;
6879         p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6880                                        &status, &source_has_wild);
6881         if (!NT_STATUS_IS_OK(status)) {
6882                 reply_nterror(req, status);
6883                 goto out;
6884         }
6885         p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6886                                        &status, &dest_has_wild);
6887         if (!NT_STATUS_IS_OK(status)) {
6888                 reply_nterror(req, status);
6889                 goto out;
6890         }
6891
6892         DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6893
6894         if (tid2 != conn->cnum) {
6895                 /* can't currently handle inter share copies XXXX */
6896                 DEBUG(3,("Rejecting inter-share copy\n"));
6897                 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6898                 goto out;
6899         }
6900
6901         status = filename_convert(ctx, conn,
6902                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6903                                   fname_src,
6904                                   UCF_COND_ALLOW_WCARD_LCOMP,
6905                                   &source_has_wild,
6906                                   &smb_fname_src);
6907         if (!NT_STATUS_IS_OK(status)) {
6908                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6909                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6910                                         ERRSRV, ERRbadpath);
6911                         goto out;
6912                 }
6913                 reply_nterror(req, status);
6914                 goto out;
6915         }
6916
6917         status = filename_convert(ctx, conn,
6918                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6919                                   fname_dst,
6920                                   UCF_COND_ALLOW_WCARD_LCOMP,
6921                                   &dest_has_wild,
6922                                   &smb_fname_dst);
6923         if (!NT_STATUS_IS_OK(status)) {
6924                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6925                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6926                                         ERRSRV, ERRbadpath);
6927                         goto out;
6928                 }
6929                 reply_nterror(req, status);
6930                 goto out;
6931         }
6932
6933         target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6934
6935         if ((flags&1) && target_is_directory) {
6936                 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6937                 goto out;
6938         }
6939
6940         if ((flags&2) && !target_is_directory) {
6941                 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
6942                 goto out;
6943         }
6944
6945         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6946                 /* wants a tree copy! XXXX */
6947                 DEBUG(3,("Rejecting tree copy\n"));
6948                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6949                 goto out;
6950         }
6951
6952         /* Split up the directory from the filename/mask. */
6953         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6954                                       &fname_src_dir, &fname_src_mask);
6955         if (!NT_STATUS_IS_OK(status)) {
6956                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6957                 goto out;
6958         }
6959
6960         /*
6961          * We should only check the mangled cache
6962          * here if unix_convert failed. This means
6963          * that the path in 'mask' doesn't exist
6964          * on the file system and so we need to look
6965          * for a possible mangle. This patch from
6966          * Tine Smukavec <valentin.smukavec@hermes.si>.
6967          */
6968         if (!VALID_STAT(smb_fname_src->st) &&
6969             mangle_is_mangled(fname_src_mask, conn->params)) {
6970                 char *new_mask = NULL;
6971                 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6972                                             &new_mask, conn->params);
6973
6974                 /* Use demangled name if one was successfully found. */
6975                 if (new_mask) {
6976                         TALLOC_FREE(fname_src_mask);
6977                         fname_src_mask = new_mask;
6978                 }
6979         }
6980
6981         if (!source_has_wild) {
6982
6983                 /*
6984                  * Only one file needs to be copied. Append the mask back onto
6985                  * the directory.
6986                  */
6987                 TALLOC_FREE(smb_fname_src->base_name);
6988                 if (ISDOT(fname_src_dir)) {
6989                         /* Ensure we use canonical names on open. */
6990                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6991                                                         "%s",
6992                                                         fname_src_mask);
6993                 } else {
6994                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6995                                                         "%s/%s",
6996                                                         fname_src_dir,
6997                                                         fname_src_mask);
6998                 }
6999                 if (!smb_fname_src->base_name) {
7000                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7001                         goto out;
7002                 }
7003
7004                 if (dest_has_wild) {
7005                         char *fname_dst_mod = NULL;
7006                         if (!resolve_wildcards(smb_fname_dst,
7007                                                smb_fname_src->base_name,
7008                                                smb_fname_dst->base_name,
7009                                                &fname_dst_mod)) {
7010                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7011                                 goto out;
7012                         }
7013                         TALLOC_FREE(smb_fname_dst->base_name);
7014                         smb_fname_dst->base_name = fname_dst_mod;
7015                 }
7016
7017                 status = check_name(conn, smb_fname_src->base_name);
7018                 if (!NT_STATUS_IS_OK(status)) {
7019                         reply_nterror(req, status);
7020                         goto out;
7021                 }
7022
7023                 status = check_name(conn, smb_fname_dst->base_name);
7024                 if (!NT_STATUS_IS_OK(status)) {
7025                         reply_nterror(req, status);
7026                         goto out;
7027                 }
7028
7029                 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7030                                    ofun, count, target_is_directory);
7031
7032                 if(!NT_STATUS_IS_OK(status)) {
7033                         reply_nterror(req, status);
7034                         goto out;
7035                 } else {
7036                         count++;
7037                 }
7038         } else {
7039                 struct smb_Dir *dir_hnd = NULL;
7040                 const char *dname = NULL;
7041                 char *talloced = NULL;
7042                 long offset = 0;
7043
7044                 /*
7045                  * There is a wildcard that requires us to actually read the
7046                  * src dir and copy each file matching the mask to the dst.
7047                  * Right now streams won't be copied, but this could
7048                  * presumably be added with a nested loop for reach dir entry.
7049                  */
7050                 SMB_ASSERT(!smb_fname_src->stream_name);
7051                 SMB_ASSERT(!smb_fname_dst->stream_name);
7052
7053                 smb_fname_src->stream_name = NULL;
7054                 smb_fname_dst->stream_name = NULL;
7055
7056                 if (strequal(fname_src_mask,"????????.???")) {
7057                         TALLOC_FREE(fname_src_mask);
7058                         fname_src_mask = talloc_strdup(ctx, "*");
7059                         if (!fname_src_mask) {
7060                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7061                                 goto out;
7062                         }
7063                 }
7064
7065                 status = check_name(conn, fname_src_dir);
7066                 if (!NT_STATUS_IS_OK(status)) {
7067                         reply_nterror(req, status);
7068                         goto out;
7069                 }
7070
7071                 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7072                 if (dir_hnd == NULL) {
7073                         status = map_nt_error_from_unix(errno);
7074                         reply_nterror(req, status);
7075                         goto out;
7076                 }
7077
7078                 error = ERRbadfile;
7079
7080                 /* Iterate over the src dir copying each entry to the dst. */
7081                 while ((dname = ReadDirName(dir_hnd, &offset,
7082                                             &smb_fname_src->st, &talloced))) {
7083                         char *destname = NULL;
7084
7085                         if (ISDOT(dname) || ISDOTDOT(dname)) {
7086                                 TALLOC_FREE(talloced);
7087                                 continue;
7088                         }
7089
7090                         if (!is_visible_file(conn, fname_src_dir, dname,
7091                                              &smb_fname_src->st, false)) {
7092                                 TALLOC_FREE(talloced);
7093                                 continue;
7094                         }
7095
7096                         if(!mask_match(dname, fname_src_mask,
7097                                        conn->case_sensitive)) {
7098                                 TALLOC_FREE(talloced);
7099                                 continue;
7100                         }
7101
7102                         error = ERRnoaccess;
7103
7104                         /* Get the src smb_fname struct setup. */
7105                         TALLOC_FREE(smb_fname_src->base_name);
7106                         if (ISDOT(fname_src_dir)) {
7107                                 /* Ensure we use canonical names on open. */
7108                                 smb_fname_src->base_name =
7109                                         talloc_asprintf(smb_fname_src, "%s",
7110                                                 dname);
7111                         } else {
7112                                 smb_fname_src->base_name =
7113                                         talloc_asprintf(smb_fname_src, "%s/%s",
7114                                                 fname_src_dir, dname);
7115                         }
7116
7117                         if (!smb_fname_src->base_name) {
7118                                 TALLOC_FREE(dir_hnd);
7119                                 TALLOC_FREE(talloced);
7120                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7121                                 goto out;
7122                         }
7123
7124                         if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7125                                                smb_fname_dst->base_name,
7126                                                &destname)) {
7127                                 TALLOC_FREE(talloced);
7128                                 continue;
7129                         }
7130                         if (!destname) {
7131                                 TALLOC_FREE(dir_hnd);
7132                                 TALLOC_FREE(talloced);
7133                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7134                                 goto out;
7135                         }
7136
7137                         TALLOC_FREE(smb_fname_dst->base_name);
7138                         smb_fname_dst->base_name = destname;
7139
7140                         status = check_name(conn, smb_fname_src->base_name);
7141                         if (!NT_STATUS_IS_OK(status)) {
7142                                 TALLOC_FREE(dir_hnd);
7143                                 TALLOC_FREE(talloced);
7144                                 reply_nterror(req, status);
7145                                 goto out;
7146                         }
7147
7148                         status = check_name(conn, smb_fname_dst->base_name);
7149                         if (!NT_STATUS_IS_OK(status)) {
7150                                 TALLOC_FREE(dir_hnd);
7151                                 TALLOC_FREE(talloced);
7152                                 reply_nterror(req, status);
7153                                 goto out;
7154                         }
7155
7156                         DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7157                                 smb_fname_src->base_name,
7158                                 smb_fname_dst->base_name));
7159
7160                         status = copy_file(ctx, conn, smb_fname_src,
7161                                            smb_fname_dst, ofun, count,
7162                                            target_is_directory);
7163                         if (NT_STATUS_IS_OK(status)) {
7164                                 count++;
7165                         }
7166
7167                         TALLOC_FREE(talloced);
7168                 }
7169                 TALLOC_FREE(dir_hnd);
7170         }
7171
7172         if (count == 0) {
7173                 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7174                 goto out;
7175         }
7176
7177         reply_outbuf(req, 1, 0);
7178         SSVAL(req->outbuf,smb_vwv0,count);
7179  out:
7180         TALLOC_FREE(smb_fname_src);
7181         TALLOC_FREE(smb_fname_dst);
7182         TALLOC_FREE(fname_src);
7183         TALLOC_FREE(fname_dst);
7184         TALLOC_FREE(fname_src_mask);
7185         TALLOC_FREE(fname_src_dir);
7186
7187         END_PROFILE(SMBcopy);
7188         return;
7189 }
7190
7191 #undef DBGC_CLASS
7192 #define DBGC_CLASS DBGC_LOCKING
7193
7194 /****************************************************************************
7195  Get a lock pid, dealing with large count requests.
7196 ****************************************************************************/
7197
7198 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7199                     bool large_file_format)
7200 {
7201         if(!large_file_format)
7202                 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7203         else
7204                 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7205 }
7206
7207 /****************************************************************************
7208  Get a lock count, dealing with large count requests.
7209 ****************************************************************************/
7210
7211 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7212                         bool large_file_format)
7213 {
7214         uint64_t count = 0;
7215
7216         if(!large_file_format) {
7217                 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7218         } else {
7219
7220 #if defined(HAVE_LONGLONG)
7221                 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7222                         ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7223 #else /* HAVE_LONGLONG */
7224
7225                 /*
7226                  * NT4.x seems to be broken in that it sends large file (64 bit)
7227                  * lockingX calls even if the CAP_LARGE_FILES was *not*
7228                  * negotiated. For boxes without large unsigned ints truncate the
7229                  * lock count by dropping the top 32 bits.
7230                  */
7231
7232                 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7233                         DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7234                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7235                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7236                                 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7237                 }
7238
7239                 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7240 #endif /* HAVE_LONGLONG */
7241         }
7242
7243         return count;
7244 }
7245
7246 #if !defined(HAVE_LONGLONG)
7247 /****************************************************************************
7248  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7249 ****************************************************************************/
7250
7251 static uint32 map_lock_offset(uint32 high, uint32 low)
7252 {
7253         unsigned int i;
7254         uint32 mask = 0;
7255         uint32 highcopy = high;
7256
7257         /*
7258          * Try and find out how many significant bits there are in high.
7259          */
7260
7261         for(i = 0; highcopy; i++)
7262                 highcopy >>= 1;
7263
7264         /*
7265          * We use 31 bits not 32 here as POSIX
7266          * lock offsets may not be negative.
7267          */
7268
7269         mask = (~0) << (31 - i);
7270
7271         if(low & mask)
7272                 return 0; /* Fail. */
7273
7274         high <<= (31 - i);
7275
7276         return (high|low);
7277 }
7278 #endif /* !defined(HAVE_LONGLONG) */
7279
7280 /****************************************************************************
7281  Get a lock offset, dealing with large offset requests.
7282 ****************************************************************************/
7283
7284 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7285                          bool large_file_format, bool *err)
7286 {
7287         uint64_t offset = 0;
7288
7289         *err = False;
7290
7291         if(!large_file_format) {
7292                 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7293         } else {
7294
7295 #if defined(HAVE_LONGLONG)
7296                 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7297                                 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7298 #else /* HAVE_LONGLONG */
7299
7300                 /*
7301                  * NT4.x seems to be broken in that it sends large file (64 bit)
7302                  * lockingX calls even if the CAP_LARGE_FILES was *not*
7303                  * negotiated. For boxes without large unsigned ints mangle the
7304                  * lock offset by mapping the top 32 bits onto the lower 32.
7305                  */
7306
7307                 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7308                         uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7309                         uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7310                         uint32 new_low = 0;
7311
7312                         if((new_low = map_lock_offset(high, low)) == 0) {
7313                                 *err = True;
7314                                 return (uint64_t)-1;
7315                         }
7316
7317                         DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7318                                 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7319                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7320                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7321                 }
7322
7323                 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7324 #endif /* HAVE_LONGLONG */
7325         }
7326
7327         return offset;
7328 }
7329
7330 NTSTATUS smbd_do_locking(struct smb_request *req,
7331                          files_struct *fsp,
7332                          uint8_t type,
7333                          int32_t timeout,
7334                          uint16_t num_ulocks,
7335                          struct smbd_lock_element *ulocks,
7336                          uint16_t num_locks,
7337                          struct smbd_lock_element *locks,
7338                          bool *async)
7339 {
7340         connection_struct *conn = req->conn;
7341         int i;
7342         NTSTATUS status = NT_STATUS_OK;
7343
7344         *async = false;
7345
7346         /* Data now points at the beginning of the list
7347            of smb_unlkrng structs */
7348         for(i = 0; i < (int)num_ulocks; i++) {
7349                 struct smbd_lock_element *e = &ulocks[i];
7350
7351                 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7352                           "pid %u, file %s\n",
7353                           (double)e->offset,
7354                           (double)e->count,
7355                           (unsigned int)e->smblctx,
7356                           fsp_str_dbg(fsp)));
7357
7358                 if (e->brltype != UNLOCK_LOCK) {
7359                         /* this can only happen with SMB2 */
7360                         return NT_STATUS_INVALID_PARAMETER;
7361                 }
7362
7363                 status = do_unlock(req->sconn->msg_ctx,
7364                                 fsp,
7365                                 e->smblctx,
7366                                 e->count,
7367                                 e->offset,
7368                                 WINDOWS_LOCK);
7369
7370                 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7371                     nt_errstr(status)));
7372
7373                 if (!NT_STATUS_IS_OK(status)) {
7374                         return status;
7375                 }
7376         }
7377
7378         /* Setup the timeout in seconds. */
7379
7380         if (!lp_blocking_locks(SNUM(conn))) {
7381                 timeout = 0;
7382         }
7383
7384         /* Data now points at the beginning of the list
7385            of smb_lkrng structs */
7386
7387         for(i = 0; i < (int)num_locks; i++) {
7388                 struct smbd_lock_element *e = &locks[i];
7389
7390                 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7391                           "%llu, file %s timeout = %d\n",
7392                           (double)e->offset,
7393                           (double)e->count,
7394                           (unsigned long long)e->smblctx,
7395                           fsp_str_dbg(fsp),
7396                           (int)timeout));
7397
7398                 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7399                         struct blocking_lock_record *blr = NULL;
7400
7401                         if (num_locks > 1) {
7402                                 /*
7403                                  * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7404                                  * if the lock vector contains one entry. When given mutliple cancel
7405                                  * requests in a single PDU we expect the server to return an
7406                                  * error. Windows servers seem to accept the request but only
7407                                  * cancel the first lock.
7408                                  * JRA - Do what Windows does (tm) :-).
7409                                  */
7410
7411 #if 0
7412                                 /* MS-CIFS (2.2.4.32.1) behavior. */
7413                                 return NT_STATUS_DOS(ERRDOS,
7414                                                 ERRcancelviolation);
7415 #else
7416                                 /* Windows behavior. */
7417                                 if (i != 0) {
7418                                         DEBUG(10,("smbd_do_locking: ignoring subsequent "
7419                                                 "cancel request\n"));
7420                                         continue;
7421                                 }
7422 #endif
7423                         }
7424
7425                         if (lp_blocking_locks(SNUM(conn))) {
7426
7427                                 /* Schedule a message to ourselves to
7428                                    remove the blocking lock record and
7429                                    return the right error. */
7430
7431                                 blr = blocking_lock_cancel_smb1(fsp,
7432                                                 e->smblctx,
7433                                                 e->offset,
7434                                                 e->count,
7435                                                 WINDOWS_LOCK,
7436                                                 type,
7437                                                 NT_STATUS_FILE_LOCK_CONFLICT);
7438                                 if (blr == NULL) {
7439                                         return NT_STATUS_DOS(
7440                                                         ERRDOS,
7441                                                         ERRcancelviolation);
7442                                 }
7443                         }
7444                         /* Remove a matching pending lock. */
7445                         status = do_lock_cancel(fsp,
7446                                                 e->smblctx,
7447                                                 e->count,
7448                                                 e->offset,
7449                                                 WINDOWS_LOCK,
7450                                                 blr);
7451                 } else {
7452                         bool blocking_lock = timeout ? true : false;
7453                         bool defer_lock = false;
7454                         struct byte_range_lock *br_lck;
7455                         uint64_t block_smblctx;
7456
7457                         br_lck = do_lock(req->sconn->msg_ctx,
7458                                         fsp,
7459                                         e->smblctx,
7460                                         e->count,
7461                                         e->offset, 
7462                                         e->brltype,
7463                                         WINDOWS_LOCK,
7464                                         blocking_lock,
7465                                         &status,
7466                                         &block_smblctx,
7467                                         NULL);
7468
7469                         if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7470                                 /* Windows internal resolution for blocking locks seems
7471                                    to be about 200ms... Don't wait for less than that. JRA. */
7472                                 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7473                                         timeout = lp_lock_spin_time();
7474                                 }
7475                                 defer_lock = true;
7476                         }
7477
7478                         /* If a lock sent with timeout of zero would fail, and
7479                          * this lock has been requested multiple times,
7480                          * according to brl_lock_failed() we convert this
7481                          * request to a blocking lock with a timeout of between
7482                          * 150 - 300 milliseconds.
7483                          *
7484                          * If lp_lock_spin_time() has been set to 0, we skip
7485                          * this blocking retry and fail immediately.
7486                          *
7487                          * Replacement for do_lock_spin(). JRA. */
7488
7489                         if (!req->sconn->using_smb2 &&
7490                             br_lck && lp_blocking_locks(SNUM(conn)) &&
7491                             lp_lock_spin_time() && !blocking_lock &&
7492                             NT_STATUS_EQUAL((status),
7493                                 NT_STATUS_FILE_LOCK_CONFLICT))
7494                         {
7495                                 defer_lock = true;
7496                                 timeout = lp_lock_spin_time();
7497                         }
7498
7499                         if (br_lck && defer_lock) {
7500                                 /*
7501                                  * A blocking lock was requested. Package up
7502                                  * this smb into a queued request and push it
7503                                  * onto the blocking lock queue.
7504                                  */
7505                                 if(push_blocking_lock_request(br_lck,
7506                                                         req,
7507                                                         fsp,
7508                                                         timeout,
7509                                                         i,
7510                                                         e->smblctx,
7511                                                         e->brltype,
7512                                                         WINDOWS_LOCK,
7513                                                         e->offset,
7514                                                         e->count,
7515                                                         block_smblctx)) {
7516                                         TALLOC_FREE(br_lck);
7517                                         *async = true;
7518                                         return NT_STATUS_OK;
7519                                 }
7520                         }
7521
7522                         TALLOC_FREE(br_lck);
7523                 }
7524
7525                 if (!NT_STATUS_IS_OK(status)) {
7526                         break;
7527                 }
7528         }
7529
7530         /* If any of the above locks failed, then we must unlock
7531            all of the previous locks (X/Open spec). */
7532
7533         if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7534
7535                 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7536                         i = -1; /* we want to skip the for loop */
7537                 }
7538
7539                 /*
7540                  * Ensure we don't do a remove on the lock that just failed,
7541                  * as under POSIX rules, if we have a lock already there, we
7542                  * will delete it (and we shouldn't) .....
7543                  */
7544                 for(i--; i >= 0; i--) {
7545                         struct smbd_lock_element *e = &locks[i];
7546
7547                         do_unlock(req->sconn->msg_ctx,
7548                                 fsp,
7549                                 e->smblctx,
7550                                 e->count,
7551                                 e->offset,
7552                                 WINDOWS_LOCK);
7553                 }
7554                 return status;
7555         }
7556
7557         DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7558                   fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7559
7560         return NT_STATUS_OK;
7561 }
7562
7563 /****************************************************************************
7564  Reply to a lockingX request.
7565 ****************************************************************************/
7566
7567 void reply_lockingX(struct smb_request *req)
7568 {
7569         connection_struct *conn = req->conn;
7570         files_struct *fsp;
7571         unsigned char locktype;
7572         unsigned char oplocklevel;
7573         uint16 num_ulocks;
7574         uint16 num_locks;
7575         int32 lock_timeout;
7576         int i;
7577         const uint8_t *data;
7578         bool large_file_format;
7579         bool err;
7580         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7581         struct smbd_lock_element *ulocks;
7582         struct smbd_lock_element *locks;
7583         bool async = false;
7584
7585         START_PROFILE(SMBlockingX);
7586
7587         if (req->wct < 8) {
7588                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7589                 END_PROFILE(SMBlockingX);
7590                 return;
7591         }
7592
7593         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7594         locktype = CVAL(req->vwv+3, 0);
7595         oplocklevel = CVAL(req->vwv+3, 1);
7596         num_ulocks = SVAL(req->vwv+6, 0);
7597         num_locks = SVAL(req->vwv+7, 0);
7598         lock_timeout = IVAL(req->vwv+4, 0);
7599         large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7600
7601         if (!check_fsp(conn, req, fsp)) {
7602                 END_PROFILE(SMBlockingX);
7603                 return;
7604         }
7605
7606         data = req->buf;
7607
7608         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7609                 /* we don't support these - and CANCEL_LOCK makes w2k
7610                    and XP reboot so I don't really want to be
7611                    compatible! (tridge) */
7612                 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7613                 END_PROFILE(SMBlockingX);
7614                 return;
7615         }
7616
7617         /* Check if this is an oplock break on a file
7618            we have granted an oplock on.
7619         */
7620         if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7621                 /* Client can insist on breaking to none. */
7622                 bool break_to_none = (oplocklevel == 0);
7623                 bool result;
7624
7625                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7626                          "for fnum = %d\n", (unsigned int)oplocklevel,
7627                          fsp->fnum ));
7628
7629                 /*
7630                  * Make sure we have granted an exclusive or batch oplock on
7631                  * this file.
7632                  */
7633
7634                 if (fsp->oplock_type == 0) {
7635
7636                         /* The Samba4 nbench simulator doesn't understand
7637                            the difference between break to level2 and break
7638                            to none from level2 - it sends oplock break
7639                            replies in both cases. Don't keep logging an error
7640                            message here - just ignore it. JRA. */
7641
7642                         DEBUG(5,("reply_lockingX: Error : oplock break from "
7643                                  "client for fnum = %d (oplock=%d) and no "
7644                                  "oplock granted on this file (%s).\n",
7645                                  fsp->fnum, fsp->oplock_type,
7646                                  fsp_str_dbg(fsp)));
7647
7648                         /* if this is a pure oplock break request then don't
7649                          * send a reply */
7650                         if (num_locks == 0 && num_ulocks == 0) {
7651                                 END_PROFILE(SMBlockingX);
7652                                 return;
7653                         } else {
7654                                 END_PROFILE(SMBlockingX);
7655                                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7656                                 return;
7657                         }
7658                 }
7659
7660                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7661                     (break_to_none)) {
7662                         result = remove_oplock(fsp);
7663                 } else {
7664                         result = downgrade_oplock(fsp);
7665                 }
7666
7667                 if (!result) {
7668                         DEBUG(0, ("reply_lockingX: error in removing "
7669                                   "oplock on file %s\n", fsp_str_dbg(fsp)));
7670                         /* Hmmm. Is this panic justified? */
7671                         smb_panic("internal tdb error");
7672                 }
7673
7674                 reply_to_oplock_break_requests(fsp);
7675
7676                 /* if this is a pure oplock break request then don't send a
7677                  * reply */
7678                 if (num_locks == 0 && num_ulocks == 0) {
7679                         /* Sanity check - ensure a pure oplock break is not a
7680                            chained request. */
7681                         if(CVAL(req->vwv+0, 0) != 0xff)
7682                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
7683                                          "break is a chained %d request !\n",
7684                                          (unsigned int)CVAL(req->vwv+0, 0)));
7685                         END_PROFILE(SMBlockingX);
7686                         return;
7687                 }
7688         }
7689
7690         if (req->buflen <
7691             (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7692                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7693                 END_PROFILE(SMBlockingX);
7694                 return;
7695         }
7696
7697         ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7698         if (ulocks == NULL) {
7699                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7700                 END_PROFILE(SMBlockingX);
7701                 return;
7702         }
7703
7704         locks = talloc_array(req, struct smbd_lock_element, num_locks);
7705         if (locks == NULL) {
7706                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7707                 END_PROFILE(SMBlockingX);
7708                 return;
7709         }
7710
7711         /* Data now points at the beginning of the list
7712            of smb_unlkrng structs */
7713         for(i = 0; i < (int)num_ulocks; i++) {
7714                 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7715                 ulocks[i].count = get_lock_count(data, i, large_file_format);
7716                 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7717                 ulocks[i].brltype = UNLOCK_LOCK;
7718
7719                 /*
7720                  * There is no error code marked "stupid client bug".... :-).
7721                  */
7722                 if(err) {
7723                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7724                         END_PROFILE(SMBlockingX);
7725                         return;
7726                 }
7727         }
7728
7729         /* Now do any requested locks */
7730         data += ((large_file_format ? 20 : 10)*num_ulocks);
7731
7732         /* Data now points at the beginning of the list
7733            of smb_lkrng structs */
7734
7735         for(i = 0; i < (int)num_locks; i++) {
7736                 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7737                 locks[i].count = get_lock_count(data, i, large_file_format);
7738                 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7739
7740                 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7741                         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7742                                 locks[i].brltype = PENDING_READ_LOCK;
7743                         } else {
7744                                 locks[i].brltype = READ_LOCK;
7745                         }
7746                 } else {
7747                         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7748                                 locks[i].brltype = PENDING_WRITE_LOCK;
7749                         } else {
7750                                 locks[i].brltype = WRITE_LOCK;
7751                         }
7752                 }
7753
7754                 /*
7755                  * There is no error code marked "stupid client bug".... :-).
7756                  */
7757                 if(err) {
7758                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7759                         END_PROFILE(SMBlockingX);
7760                         return;
7761                 }
7762         }
7763
7764         status = smbd_do_locking(req, fsp,
7765                                  locktype, lock_timeout,
7766                                  num_ulocks, ulocks,
7767                                  num_locks, locks,
7768                                  &async);
7769         if (!NT_STATUS_IS_OK(status)) {
7770                 END_PROFILE(SMBlockingX);
7771                 reply_nterror(req, status);
7772                 return;
7773         }
7774         if (async) {
7775                 END_PROFILE(SMBlockingX);
7776                 return;
7777         }
7778
7779         reply_outbuf(req, 2, 0);
7780
7781         DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7782                   fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7783
7784         END_PROFILE(SMBlockingX);
7785         chain_reply(req);
7786 }
7787
7788 #undef DBGC_CLASS
7789 #define DBGC_CLASS DBGC_ALL
7790
7791 /****************************************************************************
7792  Reply to a SMBreadbmpx (read block multiplex) request.
7793  Always reply with an error, if someone has a platform really needs this,
7794  please contact vl@samba.org
7795 ****************************************************************************/
7796
7797 void reply_readbmpx(struct smb_request *req)
7798 {
7799         START_PROFILE(SMBreadBmpx);
7800         reply_force_doserror(req, ERRSRV, ERRuseSTD);
7801         END_PROFILE(SMBreadBmpx);
7802         return;
7803 }
7804
7805 /****************************************************************************
7806  Reply to a SMBreadbs (read block multiplex secondary) request.
7807  Always reply with an error, if someone has a platform really needs this,
7808  please contact vl@samba.org
7809 ****************************************************************************/
7810
7811 void reply_readbs(struct smb_request *req)
7812 {
7813         START_PROFILE(SMBreadBs);
7814         reply_force_doserror(req, ERRSRV, ERRuseSTD);
7815         END_PROFILE(SMBreadBs);
7816         return;
7817 }
7818
7819 /****************************************************************************
7820  Reply to a SMBsetattrE.
7821 ****************************************************************************/
7822
7823 void reply_setattrE(struct smb_request *req)
7824 {
7825         connection_struct *conn = req->conn;
7826         struct smb_file_time ft;
7827         files_struct *fsp;
7828         NTSTATUS status;
7829
7830         START_PROFILE(SMBsetattrE);
7831         ZERO_STRUCT(ft);
7832
7833         if (req->wct < 7) {
7834                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7835                 goto out;
7836         }
7837
7838         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7839
7840         if(!fsp || (fsp->conn != conn)) {
7841                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7842                 goto out;
7843         }
7844
7845         /*
7846          * Convert the DOS times into unix times.
7847          */
7848
7849         ft.atime = convert_time_t_to_timespec(
7850             srv_make_unix_date2(req->vwv+3));
7851         ft.mtime = convert_time_t_to_timespec(
7852             srv_make_unix_date2(req->vwv+5));
7853         ft.create_time = convert_time_t_to_timespec(
7854             srv_make_unix_date2(req->vwv+1));
7855
7856         reply_outbuf(req, 0, 0);
7857
7858         /* 
7859          * Patch from Ray Frush <frush@engr.colostate.edu>
7860          * Sometimes times are sent as zero - ignore them.
7861          */
7862
7863         /* Ensure we have a valid stat struct for the source. */
7864         status = vfs_stat_fsp(fsp);
7865         if (!NT_STATUS_IS_OK(status)) {
7866                 reply_nterror(req, status);
7867                 goto out;
7868         }
7869
7870         status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7871         if (!NT_STATUS_IS_OK(status)) {
7872                 reply_nterror(req, status);
7873                 goto out;
7874         }
7875
7876         DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7877                " createtime=%u\n",
7878                 fsp->fnum,
7879                 (unsigned int)ft.atime.tv_sec,
7880                 (unsigned int)ft.mtime.tv_sec,
7881                 (unsigned int)ft.create_time.tv_sec
7882                 ));
7883  out:
7884         END_PROFILE(SMBsetattrE);
7885         return;
7886 }
7887
7888
7889 /* Back from the dead for OS/2..... JRA. */
7890
7891 /****************************************************************************
7892  Reply to a SMBwritebmpx (write block multiplex primary) request.
7893  Always reply with an error, if someone has a platform really needs this,
7894  please contact vl@samba.org
7895 ****************************************************************************/
7896
7897 void reply_writebmpx(struct smb_request *req)
7898 {
7899         START_PROFILE(SMBwriteBmpx);
7900         reply_force_doserror(req, ERRSRV, ERRuseSTD);
7901         END_PROFILE(SMBwriteBmpx);
7902         return;
7903 }
7904
7905 /****************************************************************************
7906  Reply to a SMBwritebs (write block multiplex secondary) request.
7907  Always reply with an error, if someone has a platform really needs this,
7908  please contact vl@samba.org
7909 ****************************************************************************/
7910
7911 void reply_writebs(struct smb_request *req)
7912 {
7913         START_PROFILE(SMBwriteBs);
7914         reply_force_doserror(req, ERRSRV, ERRuseSTD);
7915         END_PROFILE(SMBwriteBs);
7916         return;
7917 }
7918
7919 /****************************************************************************
7920  Reply to a SMBgetattrE.
7921 ****************************************************************************/
7922
7923 void reply_getattrE(struct smb_request *req)
7924 {
7925         connection_struct *conn = req->conn;
7926         int mode;
7927         files_struct *fsp;
7928         struct timespec create_ts;
7929
7930         START_PROFILE(SMBgetattrE);
7931
7932         if (req->wct < 1) {
7933                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7934                 END_PROFILE(SMBgetattrE);
7935                 return;
7936         }
7937
7938         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7939
7940         if(!fsp || (fsp->conn != conn)) {
7941                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7942                 END_PROFILE(SMBgetattrE);
7943                 return;
7944         }
7945
7946         /* Do an fstat on this file */
7947         if(fsp_stat(fsp)) {
7948                 reply_nterror(req, map_nt_error_from_unix(errno));
7949                 END_PROFILE(SMBgetattrE);
7950                 return;
7951         }
7952
7953         mode = dos_mode(conn, fsp->fsp_name);
7954
7955         /*
7956          * Convert the times into dos times. Set create
7957          * date to be last modify date as UNIX doesn't save
7958          * this.
7959          */
7960
7961         reply_outbuf(req, 11, 0);
7962
7963         create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7964         srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7965         srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7966                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7967         /* Should we check pending modtime here ? JRA */
7968         srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7969                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7970
7971         if (mode & aDIR) {
7972                 SIVAL(req->outbuf, smb_vwv6, 0);
7973                 SIVAL(req->outbuf, smb_vwv8, 0);
7974         } else {
7975                 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7976                 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
7977                 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7978         }
7979         SSVAL(req->outbuf,smb_vwv10, mode);
7980
7981         DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7982
7983         END_PROFILE(SMBgetattrE);
7984         return;
7985 }