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