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