s3: Remove "req_wct_ofs()"
[obnox/samba/samba-obnox.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         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
864         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
865
866         DEBUG(3,("tconX service=%s \n",
867                  service));
868
869         /* set the incoming and outgoing tid to the just created one */
870         SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
871         SSVAL(req->outbuf,smb_tid,conn->cnum);
872
873         END_PROFILE(SMBtconX);
874
875         req->tid = conn->cnum;
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         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2039         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
2040
2041         if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2042                 SCVAL(req->outbuf, smb_flg,
2043                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2044         }
2045
2046         if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2047                 SCVAL(req->outbuf, smb_flg,
2048                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2049         }
2050
2051         SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2052         SSVAL(req->outbuf,smb_vwv3,fattr);
2053         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2054                 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2055         } else {
2056                 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2057         }
2058         SIVAL(req->outbuf,smb_vwv6,(uint32)fsp->fsp_name->st.st_ex_size);
2059         SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2060         SSVAL(req->outbuf,smb_vwv11,smb_action);
2061
2062         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2063                 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2064         }
2065
2066  out:
2067         TALLOC_FREE(smb_fname);
2068         END_PROFILE(SMBopenX);
2069         return;
2070 }
2071
2072 /****************************************************************************
2073  Reply to a SMBulogoffX.
2074 ****************************************************************************/
2075
2076 void reply_ulogoffX(struct smb_request *req)
2077 {
2078         struct smbd_server_connection *sconn = req->sconn;
2079         user_struct *vuser;
2080
2081         START_PROFILE(SMBulogoffX);
2082
2083         vuser = get_valid_user_struct(sconn, req->vuid);
2084
2085         if(vuser == NULL) {
2086                 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2087                          req->vuid));
2088         }
2089
2090         /* in user level security we are supposed to close any files
2091                 open by this user */
2092         if (vuser != NULL) {
2093                 file_close_user(sconn, req->vuid);
2094         }
2095
2096         invalidate_vuid(sconn, req->vuid);
2097
2098         reply_outbuf(req, 2, 0);
2099         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2100         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
2101
2102         DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2103
2104         END_PROFILE(SMBulogoffX);
2105         req->vuid = UID_FIELD_INVALID;
2106 }
2107
2108 /****************************************************************************
2109  Reply to a mknew or a create.
2110 ****************************************************************************/
2111
2112 void reply_mknew(struct smb_request *req)
2113 {
2114         connection_struct *conn = req->conn;
2115         struct smb_filename *smb_fname = NULL;
2116         char *fname = NULL;
2117         uint32 fattr = 0;
2118         struct smb_file_time ft;
2119         files_struct *fsp;
2120         int oplock_request = 0;
2121         NTSTATUS status;
2122         uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2123         uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2124         uint32 create_disposition;
2125         uint32 create_options = 0;
2126         TALLOC_CTX *ctx = talloc_tos();
2127
2128         START_PROFILE(SMBcreate);
2129         ZERO_STRUCT(ft);
2130
2131         if (req->wct < 3) {
2132                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2133                 goto out;
2134         }
2135
2136         fattr = SVAL(req->vwv+0, 0);
2137         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2138
2139         /* mtime. */
2140         ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2141
2142         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2143                             STR_TERMINATE, &status);
2144         if (!NT_STATUS_IS_OK(status)) {
2145                 reply_nterror(req, status);
2146                 goto out;
2147         }
2148
2149         status = filename_convert(ctx,
2150                                 conn,
2151                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
2152                                 fname,
2153                                 0,
2154                                 NULL,
2155                                 &smb_fname);
2156         if (!NT_STATUS_IS_OK(status)) {
2157                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2158                         reply_botherror(req,
2159                                         NT_STATUS_PATH_NOT_COVERED,
2160                                         ERRSRV, ERRbadpath);
2161                         goto out;
2162                 }
2163                 reply_nterror(req, status);
2164                 goto out;
2165         }
2166
2167         if (fattr & FILE_ATTRIBUTE_VOLUME) {
2168                 DEBUG(0,("Attempt to create file (%s) with volid set - "
2169                          "please report this\n",
2170                          smb_fname_str_dbg(smb_fname)));
2171         }
2172
2173         if(req->cmd == SMBmknew) {
2174                 /* We should fail if file exists. */
2175                 create_disposition = FILE_CREATE;
2176         } else {
2177                 /* Create if file doesn't exist, truncate if it does. */
2178                 create_disposition = FILE_OVERWRITE_IF;
2179         }
2180
2181         status = SMB_VFS_CREATE_FILE(
2182                 conn,                                   /* conn */
2183                 req,                                    /* req */
2184                 0,                                      /* root_dir_fid */
2185                 smb_fname,                              /* fname */
2186                 access_mask,                            /* access_mask */
2187                 share_mode,                             /* share_access */
2188                 create_disposition,                     /* create_disposition*/
2189                 create_options,                         /* create_options */
2190                 fattr,                                  /* file_attributes */
2191                 oplock_request,                         /* oplock_request */
2192                 0,                                      /* allocation_size */
2193                 0,                                      /* private_flags */
2194                 NULL,                                   /* sd */
2195                 NULL,                                   /* ea_list */
2196                 &fsp,                                   /* result */
2197                 NULL);                                  /* pinfo */
2198
2199         if (!NT_STATUS_IS_OK(status)) {
2200                 if (open_was_deferred(req->sconn, req->mid)) {
2201                         /* We have re-scheduled this call. */
2202                         goto out;
2203                 }
2204                 reply_openerror(req, status);
2205                 goto out;
2206         }
2207
2208         ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2209         status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2210         if (!NT_STATUS_IS_OK(status)) {
2211                 END_PROFILE(SMBcreate);
2212                 goto out;
2213         }
2214
2215         reply_outbuf(req, 1, 0);
2216         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2217
2218         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2219                 SCVAL(req->outbuf,smb_flg,
2220                                 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2221         }
2222
2223         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2224                 SCVAL(req->outbuf,smb_flg,
2225                                 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2226         }
2227
2228         DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2229         DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2230                   smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2231                   (unsigned int)fattr));
2232
2233  out:
2234         TALLOC_FREE(smb_fname);
2235         END_PROFILE(SMBcreate);
2236         return;
2237 }
2238
2239 /****************************************************************************
2240  Reply to a create temporary file.
2241 ****************************************************************************/
2242
2243 void reply_ctemp(struct smb_request *req)
2244 {
2245         connection_struct *conn = req->conn;
2246         struct smb_filename *smb_fname = NULL;
2247         char *fname = NULL;
2248         uint32 fattr;
2249         files_struct *fsp;
2250         int oplock_request;
2251         int tmpfd;
2252         char *s;
2253         NTSTATUS status;
2254         TALLOC_CTX *ctx = talloc_tos();
2255
2256         START_PROFILE(SMBctemp);
2257
2258         if (req->wct < 3) {
2259                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2260                 goto out;
2261         }
2262
2263         fattr = SVAL(req->vwv+0, 0);
2264         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2265
2266         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2267                             STR_TERMINATE, &status);
2268         if (!NT_STATUS_IS_OK(status)) {
2269                 reply_nterror(req, status);
2270                 goto out;
2271         }
2272         if (*fname) {
2273                 fname = talloc_asprintf(ctx,
2274                                 "%s/TMXXXXXX",
2275                                 fname);
2276         } else {
2277                 fname = talloc_strdup(ctx, "TMXXXXXX");
2278         }
2279
2280         if (!fname) {
2281                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2282                 goto out;
2283         }
2284
2285         status = filename_convert(ctx, conn,
2286                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
2287                                 fname,
2288                                 0,
2289                                 NULL,
2290                                 &smb_fname);
2291         if (!NT_STATUS_IS_OK(status)) {
2292                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2293                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2294                                         ERRSRV, ERRbadpath);
2295                         goto out;
2296                 }
2297                 reply_nterror(req, status);
2298                 goto out;
2299         }
2300
2301         tmpfd = mkstemp(smb_fname->base_name);
2302         if (tmpfd == -1) {
2303                 reply_nterror(req, map_nt_error_from_unix(errno));
2304                 goto out;
2305         }
2306
2307         SMB_VFS_STAT(conn, smb_fname);
2308
2309         /* We should fail if file does not exist. */
2310         status = SMB_VFS_CREATE_FILE(
2311                 conn,                                   /* conn */
2312                 req,                                    /* req */
2313                 0,                                      /* root_dir_fid */
2314                 smb_fname,                              /* fname */
2315                 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2316                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
2317                 FILE_OPEN,                              /* create_disposition*/
2318                 0,                                      /* create_options */
2319                 fattr,                                  /* file_attributes */
2320                 oplock_request,                         /* oplock_request */
2321                 0,                                      /* allocation_size */
2322                 0,                                      /* private_flags */
2323                 NULL,                                   /* sd */
2324                 NULL,                                   /* ea_list */
2325                 &fsp,                                   /* result */
2326                 NULL);                                  /* pinfo */
2327
2328         /* close fd from mkstemp() */
2329         close(tmpfd);
2330
2331         if (!NT_STATUS_IS_OK(status)) {
2332                 if (open_was_deferred(req->sconn, req->mid)) {
2333                         /* We have re-scheduled this call. */
2334                         goto out;
2335                 }
2336                 reply_openerror(req, status);
2337                 goto out;
2338         }
2339
2340         reply_outbuf(req, 1, 0);
2341         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2342
2343         /* the returned filename is relative to the directory */
2344         s = strrchr_m(fsp->fsp_name->base_name, '/');
2345         if (!s) {
2346                 s = fsp->fsp_name->base_name;
2347         } else {
2348                 s++;
2349         }
2350
2351 #if 0
2352         /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2353            thing in the byte section. JRA */
2354         SSVALS(p, 0, -1); /* what is this? not in spec */
2355 #endif
2356         if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2357             == -1) {
2358                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2359                 goto out;
2360         }
2361
2362         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2363                 SCVAL(req->outbuf, smb_flg,
2364                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2365         }
2366
2367         if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2368                 SCVAL(req->outbuf, smb_flg,
2369                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2370         }
2371
2372         DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2373         DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2374                     fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2375  out:
2376         TALLOC_FREE(smb_fname);
2377         END_PROFILE(SMBctemp);
2378         return;
2379 }
2380
2381 /*******************************************************************
2382  Check if a user is allowed to rename a file.
2383 ********************************************************************/
2384
2385 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2386                         uint16 dirtype)
2387 {
2388         if (!CAN_WRITE(conn)) {
2389                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2390         }
2391
2392         if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2393                         (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2394                 /* Only bother to read the DOS attribute if we might deny the
2395                    rename on the grounds of attribute missmatch. */
2396                 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2397                 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2398                         return NT_STATUS_NO_SUCH_FILE;
2399                 }
2400         }
2401
2402         if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2403                 if (fsp->posix_open) {
2404                         return NT_STATUS_OK;
2405                 }
2406
2407                 /* If no pathnames are open below this
2408                    directory, allow the rename. */
2409
2410                 if (file_find_subpath(fsp)) {
2411                         return NT_STATUS_ACCESS_DENIED;
2412                 }
2413                 return NT_STATUS_OK;
2414         }
2415
2416         if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2417                 return NT_STATUS_OK;
2418         }
2419
2420         return NT_STATUS_ACCESS_DENIED;
2421 }
2422
2423 /*******************************************************************
2424  * unlink a file with all relevant access checks
2425  *******************************************************************/
2426
2427 static NTSTATUS do_unlink(connection_struct *conn,
2428                         struct smb_request *req,
2429                         struct smb_filename *smb_fname,
2430                         uint32 dirtype)
2431 {
2432         uint32 fattr;
2433         files_struct *fsp;
2434         uint32 dirtype_orig = dirtype;
2435         NTSTATUS status;
2436         int ret;
2437         bool posix_paths = lp_posix_pathnames();
2438
2439         DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2440                   smb_fname_str_dbg(smb_fname),
2441                   dirtype));
2442
2443         if (!CAN_WRITE(conn)) {
2444                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2445         }
2446
2447         if (posix_paths) {
2448                 ret = SMB_VFS_LSTAT(conn, smb_fname);
2449         } else {
2450                 ret = SMB_VFS_STAT(conn, smb_fname);
2451         }
2452         if (ret != 0) {
2453                 return map_nt_error_from_unix(errno);
2454         }
2455
2456         fattr = dos_mode(conn, smb_fname);
2457
2458         if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2459                 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2460         }
2461
2462         dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2463         if (!dirtype) {
2464                 return NT_STATUS_NO_SUCH_FILE;
2465         }
2466
2467         if (!dir_check_ftype(conn, fattr, dirtype)) {
2468                 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2469                         return NT_STATUS_FILE_IS_A_DIRECTORY;
2470                 }
2471                 return NT_STATUS_NO_SUCH_FILE;
2472         }
2473
2474         if (dirtype_orig & 0x8000) {
2475                 /* These will never be set for POSIX. */
2476                 return NT_STATUS_NO_SUCH_FILE;
2477         }
2478
2479 #if 0
2480         if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2481                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2482         }
2483
2484         if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2485                 return NT_STATUS_NO_SUCH_FILE;
2486         }
2487
2488         if (dirtype & 0xFF00) {
2489                 /* These will never be set for POSIX. */
2490                 return NT_STATUS_NO_SUCH_FILE;
2491         }
2492
2493         dirtype &= 0xFF;
2494         if (!dirtype) {
2495                 return NT_STATUS_NO_SUCH_FILE;
2496         }
2497
2498         /* Can't delete a directory. */
2499         if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2500                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2501         }
2502 #endif
2503
2504 #if 0 /* JRATEST */
2505         else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2506                 return NT_STATUS_OBJECT_NAME_INVALID;
2507 #endif /* JRATEST */
2508
2509         /* On open checks the open itself will check the share mode, so
2510            don't do it here as we'll get it wrong. */
2511
2512         status = SMB_VFS_CREATE_FILE
2513                 (conn,                  /* conn */
2514                  req,                   /* req */
2515                  0,                     /* root_dir_fid */
2516                  smb_fname,             /* fname */
2517                  DELETE_ACCESS,         /* access_mask */
2518                  FILE_SHARE_NONE,       /* share_access */
2519                  FILE_OPEN,             /* create_disposition*/
2520                  FILE_NON_DIRECTORY_FILE, /* create_options */
2521                                         /* file_attributes */
2522                  posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2523                                 FILE_ATTRIBUTE_NORMAL,
2524                  0,                     /* oplock_request */
2525                  0,                     /* allocation_size */
2526                  0,                     /* private_flags */
2527                  NULL,                  /* sd */
2528                  NULL,                  /* ea_list */
2529                  &fsp,                  /* result */
2530                  NULL);                 /* pinfo */
2531
2532         if (!NT_STATUS_IS_OK(status)) {
2533                 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2534                            nt_errstr(status)));
2535                 return status;
2536         }
2537
2538         status = can_set_delete_on_close(fsp, fattr);
2539         if (!NT_STATUS_IS_OK(status)) {
2540                 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2541                         "(%s)\n",
2542                         smb_fname_str_dbg(smb_fname),
2543                         nt_errstr(status)));
2544                 close_file(req, fsp, NORMAL_CLOSE);
2545                 return status;
2546         }
2547
2548         /* The set is across all open files on this dev/inode pair. */
2549         if (!set_delete_on_close(fsp, True, conn->session_info->unix_token)) {
2550                 close_file(req, fsp, NORMAL_CLOSE);
2551                 return NT_STATUS_ACCESS_DENIED;
2552         }
2553
2554         return close_file(req, fsp, NORMAL_CLOSE);
2555 }
2556
2557 /****************************************************************************
2558  The guts of the unlink command, split out so it may be called by the NT SMB
2559  code.
2560 ****************************************************************************/
2561
2562 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2563                           uint32 dirtype, struct smb_filename *smb_fname,
2564                           bool has_wild)
2565 {
2566         char *fname_dir = NULL;
2567         char *fname_mask = NULL;
2568         int count=0;
2569         NTSTATUS status = NT_STATUS_OK;
2570         TALLOC_CTX *ctx = talloc_tos();
2571
2572         /* Split up the directory from the filename/mask. */
2573         status = split_fname_dir_mask(ctx, smb_fname->base_name,
2574                                       &fname_dir, &fname_mask);
2575         if (!NT_STATUS_IS_OK(status)) {
2576                 goto out;
2577         }
2578
2579         /*
2580          * We should only check the mangled cache
2581          * here if unix_convert failed. This means
2582          * that the path in 'mask' doesn't exist
2583          * on the file system and so we need to look
2584          * for a possible mangle. This patch from
2585          * Tine Smukavec <valentin.smukavec@hermes.si>.
2586          */
2587
2588         if (!VALID_STAT(smb_fname->st) &&
2589             mangle_is_mangled(fname_mask, conn->params)) {
2590                 char *new_mask = NULL;
2591                 mangle_lookup_name_from_8_3(ctx, fname_mask,
2592                                             &new_mask, conn->params);
2593                 if (new_mask) {
2594                         TALLOC_FREE(fname_mask);
2595                         fname_mask = new_mask;
2596                 }
2597         }
2598
2599         if (!has_wild) {
2600
2601                 /*
2602                  * Only one file needs to be unlinked. Append the mask back
2603                  * onto the directory.
2604                  */
2605                 TALLOC_FREE(smb_fname->base_name);
2606                 if (ISDOT(fname_dir)) {
2607                         /* Ensure we use canonical names on open. */
2608                         smb_fname->base_name = talloc_asprintf(smb_fname,
2609                                                         "%s",
2610                                                         fname_mask);
2611                 } else {
2612                         smb_fname->base_name = talloc_asprintf(smb_fname,
2613                                                         "%s/%s",
2614                                                         fname_dir,
2615                                                         fname_mask);
2616                 }
2617                 if (!smb_fname->base_name) {
2618                         status = NT_STATUS_NO_MEMORY;
2619                         goto out;
2620                 }
2621                 if (dirtype == 0) {
2622                         dirtype = FILE_ATTRIBUTE_NORMAL;
2623                 }
2624
2625                 status = check_name(conn, smb_fname->base_name);
2626                 if (!NT_STATUS_IS_OK(status)) {
2627                         goto out;
2628                 }
2629
2630                 status = do_unlink(conn, req, smb_fname, dirtype);
2631                 if (!NT_STATUS_IS_OK(status)) {
2632                         goto out;
2633                 }
2634
2635                 count++;
2636         } else {
2637                 struct smb_Dir *dir_hnd = NULL;
2638                 long offset = 0;
2639                 const char *dname = NULL;
2640                 char *talloced = NULL;
2641
2642                 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
2643                         status = NT_STATUS_OBJECT_NAME_INVALID;
2644                         goto out;
2645                 }
2646
2647                 if (strequal(fname_mask,"????????.???")) {
2648                         TALLOC_FREE(fname_mask);
2649                         fname_mask = talloc_strdup(ctx, "*");
2650                         if (!fname_mask) {
2651                                 status = NT_STATUS_NO_MEMORY;
2652                                 goto out;
2653                         }
2654                 }
2655
2656                 status = check_name(conn, fname_dir);
2657                 if (!NT_STATUS_IS_OK(status)) {
2658                         goto out;
2659                 }
2660
2661                 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2662                                   dirtype);
2663                 if (dir_hnd == NULL) {
2664                         status = map_nt_error_from_unix(errno);
2665                         goto out;
2666                 }
2667
2668                 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2669                    the pattern matches against the long name, otherwise the short name 
2670                    We don't implement this yet XXXX
2671                 */
2672
2673                 status = NT_STATUS_NO_SUCH_FILE;
2674
2675                 while ((dname = ReadDirName(dir_hnd, &offset,
2676                                             &smb_fname->st, &talloced))) {
2677                         TALLOC_CTX *frame = talloc_stackframe();
2678
2679                         if (!is_visible_file(conn, fname_dir, dname,
2680                                              &smb_fname->st, true)) {
2681                                 TALLOC_FREE(frame);
2682                                 TALLOC_FREE(talloced);
2683                                 continue;
2684                         }
2685
2686                         /* Quick check for "." and ".." */
2687                         if (ISDOT(dname) || ISDOTDOT(dname)) {
2688                                 TALLOC_FREE(frame);
2689                                 TALLOC_FREE(talloced);
2690                                 continue;
2691                         }
2692
2693                         if(!mask_match(dname, fname_mask,
2694                                        conn->case_sensitive)) {
2695                                 TALLOC_FREE(frame);
2696                                 TALLOC_FREE(talloced);
2697                                 continue;
2698                         }
2699
2700                         TALLOC_FREE(smb_fname->base_name);
2701                         if (ISDOT(fname_dir)) {
2702                                 /* Ensure we use canonical names on open. */
2703                                 smb_fname->base_name =
2704                                         talloc_asprintf(smb_fname, "%s",
2705                                                 dname);
2706                         } else {
2707                                 smb_fname->base_name =
2708                                         talloc_asprintf(smb_fname, "%s/%s",
2709                                                 fname_dir, dname);
2710                         }
2711
2712                         if (!smb_fname->base_name) {
2713                                 TALLOC_FREE(dir_hnd);
2714                                 status = NT_STATUS_NO_MEMORY;
2715                                 TALLOC_FREE(frame);
2716                                 TALLOC_FREE(talloced);
2717                                 goto out;
2718                         }
2719
2720                         status = check_name(conn, smb_fname->base_name);
2721                         if (!NT_STATUS_IS_OK(status)) {
2722                                 TALLOC_FREE(dir_hnd);
2723                                 TALLOC_FREE(frame);
2724                                 TALLOC_FREE(talloced);
2725                                 goto out;
2726                         }
2727
2728                         status = do_unlink(conn, req, smb_fname, dirtype);
2729                         if (!NT_STATUS_IS_OK(status)) {
2730                                 TALLOC_FREE(frame);
2731                                 TALLOC_FREE(talloced);
2732                                 continue;
2733                         }
2734
2735                         count++;
2736                         DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2737                                  smb_fname->base_name));
2738
2739                         TALLOC_FREE(frame);
2740                         TALLOC_FREE(talloced);
2741                 }
2742                 TALLOC_FREE(dir_hnd);
2743         }
2744
2745         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2746                 status = map_nt_error_from_unix(errno);
2747         }
2748
2749  out:
2750         TALLOC_FREE(fname_dir);
2751         TALLOC_FREE(fname_mask);
2752         return status;
2753 }
2754
2755 /****************************************************************************
2756  Reply to a unlink
2757 ****************************************************************************/
2758
2759 void reply_unlink(struct smb_request *req)
2760 {
2761         connection_struct *conn = req->conn;
2762         char *name = NULL;
2763         struct smb_filename *smb_fname = NULL;
2764         uint32 dirtype;
2765         NTSTATUS status;
2766         bool path_contains_wcard = False;
2767         TALLOC_CTX *ctx = talloc_tos();
2768
2769         START_PROFILE(SMBunlink);
2770
2771         if (req->wct < 1) {
2772                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2773                 goto out;
2774         }
2775
2776         dirtype = SVAL(req->vwv+0, 0);
2777
2778         srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2779                                   STR_TERMINATE, &status,
2780                                   &path_contains_wcard);
2781         if (!NT_STATUS_IS_OK(status)) {
2782                 reply_nterror(req, status);
2783                 goto out;
2784         }
2785
2786         status = filename_convert(ctx, conn,
2787                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
2788                                   name,
2789                                   UCF_COND_ALLOW_WCARD_LCOMP,
2790                                   &path_contains_wcard,
2791                                   &smb_fname);
2792         if (!NT_STATUS_IS_OK(status)) {
2793                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2794                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2795                                         ERRSRV, ERRbadpath);
2796                         goto out;
2797                 }
2798                 reply_nterror(req, status);
2799                 goto out;
2800         }
2801
2802         DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2803
2804         status = unlink_internals(conn, req, dirtype, smb_fname,
2805                                   path_contains_wcard);
2806         if (!NT_STATUS_IS_OK(status)) {
2807                 if (open_was_deferred(req->sconn, req->mid)) {
2808                         /* We have re-scheduled this call. */
2809                         goto out;
2810                 }
2811                 reply_nterror(req, status);
2812                 goto out;
2813         }
2814
2815         reply_outbuf(req, 0, 0);
2816  out:
2817         TALLOC_FREE(smb_fname);
2818         END_PROFILE(SMBunlink);
2819         return;
2820 }
2821
2822 /****************************************************************************
2823  Fail for readbraw.
2824 ****************************************************************************/
2825
2826 static void fail_readraw(void)
2827 {
2828         const char *errstr = talloc_asprintf(talloc_tos(),
2829                         "FAIL ! reply_readbraw: socket write fail (%s)",
2830                         strerror(errno));
2831         if (!errstr) {
2832                 errstr = "";
2833         }
2834         exit_server_cleanly(errstr);
2835 }
2836
2837 /****************************************************************************
2838  Fake (read/write) sendfile. Returns -1 on read or write fail.
2839 ****************************************************************************/
2840
2841 ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread)
2842 {
2843         size_t bufsize;
2844         size_t tosend = nread;
2845         char *buf;
2846
2847         if (nread == 0) {
2848                 return 0;
2849         }
2850
2851         bufsize = MIN(nread, 65536);
2852
2853         if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2854                 return -1;
2855         }
2856
2857         while (tosend > 0) {
2858                 ssize_t ret;
2859                 size_t cur_read;
2860
2861                 if (tosend > bufsize) {
2862                         cur_read = bufsize;
2863                 } else {
2864                         cur_read = tosend;
2865                 }
2866                 ret = read_file(fsp,buf,startpos,cur_read);
2867                 if (ret == -1) {
2868                         SAFE_FREE(buf);
2869                         return -1;
2870                 }
2871
2872                 /* If we had a short read, fill with zeros. */
2873                 if (ret < cur_read) {
2874                         memset(buf + ret, '\0', cur_read - ret);
2875                 }
2876
2877                 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
2878                     != cur_read) {
2879                         char addr[INET6_ADDRSTRLEN];
2880                         /*
2881                          * Try and give an error message saying what
2882                          * client failed.
2883                          */
2884                         DEBUG(0, ("write_data failed for client %s. "
2885                                   "Error %s\n",
2886                                   get_peer_addr(fsp->conn->sconn->sock, addr,
2887                                                 sizeof(addr)),
2888                                   strerror(errno)));
2889                         SAFE_FREE(buf);
2890                         return -1;
2891                 }
2892                 tosend -= cur_read;
2893                 startpos += cur_read;
2894         }
2895
2896         SAFE_FREE(buf);
2897         return (ssize_t)nread;
2898 }
2899
2900 /****************************************************************************
2901  Deal with the case of sendfile reading less bytes from the file than
2902  requested. Fill with zeros (all we can do).
2903 ****************************************************************************/
2904
2905 void sendfile_short_send(files_struct *fsp,
2906                                 ssize_t nread,
2907                                 size_t headersize,
2908                                 size_t smb_maxcnt)
2909 {
2910 #define SHORT_SEND_BUFSIZE 1024
2911         if (nread < headersize) {
2912                 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2913                         "header for file %s (%s). Terminating\n",
2914                         fsp_str_dbg(fsp), strerror(errno)));
2915                 exit_server_cleanly("sendfile_short_send failed");
2916         }
2917
2918         nread -= headersize;
2919
2920         if (nread < smb_maxcnt) {
2921                 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2922                 if (!buf) {
2923                         exit_server_cleanly("sendfile_short_send: "
2924                                 "malloc failed");
2925                 }
2926
2927                 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2928                         "with zeros !\n", fsp_str_dbg(fsp)));
2929
2930                 while (nread < smb_maxcnt) {
2931                         /*
2932                          * We asked for the real file size and told sendfile
2933                          * to not go beyond the end of the file. But it can
2934                          * happen that in between our fstat call and the
2935                          * sendfile call the file was truncated. This is very
2936                          * bad because we have already announced the larger
2937                          * number of bytes to the client.
2938                          *
2939                          * The best we can do now is to send 0-bytes, just as
2940                          * a read from a hole in a sparse file would do.
2941                          *
2942                          * This should happen rarely enough that I don't care
2943                          * about efficiency here :-)
2944                          */
2945                         size_t to_write;
2946
2947                         to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2948                         if (write_data(fsp->conn->sconn->sock, buf, to_write)
2949                             != to_write) {
2950                                 char addr[INET6_ADDRSTRLEN];
2951                                 /*
2952                                  * Try and give an error message saying what
2953                                  * client failed.
2954                                  */
2955                                 DEBUG(0, ("write_data failed for client %s. "
2956                                           "Error %s\n",
2957                                           get_peer_addr(
2958                                                   fsp->conn->sconn->sock, addr,
2959                                                   sizeof(addr)),
2960                                           strerror(errno)));
2961                                 exit_server_cleanly("sendfile_short_send: "
2962                                                     "write_data failed");
2963                         }
2964                         nread += to_write;
2965                 }
2966                 SAFE_FREE(buf);
2967         }
2968 }
2969
2970 /****************************************************************************
2971  Return a readbraw error (4 bytes of zero).
2972 ****************************************************************************/
2973
2974 static void reply_readbraw_error(struct smbd_server_connection *sconn)
2975 {
2976         char header[4];
2977
2978         SIVAL(header,0,0);
2979
2980         smbd_lock_socket(sconn);
2981         if (write_data(sconn->sock,header,4) != 4) {
2982                 char addr[INET6_ADDRSTRLEN];
2983                 /*
2984                  * Try and give an error message saying what
2985                  * client failed.
2986                  */
2987                 DEBUG(0, ("write_data failed for client %s. "
2988                           "Error %s\n",
2989                           get_peer_addr(sconn->sock, addr, sizeof(addr)),
2990                           strerror(errno)));
2991
2992                 fail_readraw();
2993         }
2994         smbd_unlock_socket(sconn);
2995 }
2996
2997 /****************************************************************************
2998  Use sendfile in readbraw.
2999 ****************************************************************************/
3000
3001 static void send_file_readbraw(connection_struct *conn,
3002                                struct smb_request *req,
3003                                files_struct *fsp,
3004                                SMB_OFF_T startpos,
3005                                size_t nread,
3006                                ssize_t mincount)
3007 {
3008         struct smbd_server_connection *sconn = req->sconn;
3009         char *outbuf = NULL;
3010         ssize_t ret=0;
3011
3012         /*
3013          * We can only use sendfile on a non-chained packet 
3014          * but we can use on a non-oplocked file. tridge proved this
3015          * on a train in Germany :-). JRA.
3016          * reply_readbraw has already checked the length.
3017          */
3018
3019         if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3020             (fsp->wcp == NULL) &&
3021             lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3022                 ssize_t sendfile_read = -1;
3023                 char header[4];
3024                 DATA_BLOB header_blob;
3025
3026                 _smb_setlen(header,nread);
3027                 header_blob = data_blob_const(header, 4);
3028
3029                 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
3030                                                  &header_blob, startpos,
3031                                                  nread);
3032                 if (sendfile_read == -1) {
3033                         /* Returning ENOSYS means no data at all was sent.
3034                          * Do this as a normal read. */
3035                         if (errno == ENOSYS) {
3036                                 goto normal_readbraw;
3037                         }
3038
3039                         /*
3040                          * Special hack for broken Linux with no working sendfile. If we
3041                          * return EINTR we sent the header but not the rest of the data.
3042                          * Fake this up by doing read/write calls.
3043                          */
3044                         if (errno == EINTR) {
3045                                 /* Ensure we don't do this again. */
3046                                 set_use_sendfile(SNUM(conn), False);
3047                                 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3048
3049                                 if (fake_sendfile(fsp, startpos, nread) == -1) {
3050                                         DEBUG(0,("send_file_readbraw: "
3051                                                  "fake_sendfile failed for "
3052                                                  "file %s (%s).\n",
3053                                                  fsp_str_dbg(fsp),
3054                                                  strerror(errno)));
3055                                         exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3056                                 }
3057                                 return;
3058                         }
3059
3060                         DEBUG(0,("send_file_readbraw: sendfile failed for "
3061                                  "file %s (%s). Terminating\n",
3062                                  fsp_str_dbg(fsp), strerror(errno)));
3063                         exit_server_cleanly("send_file_readbraw sendfile failed");
3064                 } else if (sendfile_read == 0) {
3065                         /*
3066                          * Some sendfile implementations return 0 to indicate
3067                          * that there was a short read, but nothing was
3068                          * actually written to the socket.  In this case,
3069                          * fallback to the normal read path so the header gets
3070                          * the correct byte count.
3071                          */
3072                         DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3073                                   "bytes falling back to the normal read: "
3074                                   "%s\n", fsp_str_dbg(fsp)));
3075                         goto normal_readbraw;
3076                 }
3077
3078                 /* Deal with possible short send. */
3079                 if (sendfile_read != 4+nread) {
3080                         sendfile_short_send(fsp, sendfile_read, 4, nread);
3081                 }
3082                 return;
3083         }
3084
3085 normal_readbraw:
3086
3087         outbuf = talloc_array(NULL, char, nread+4);
3088         if (!outbuf) {
3089                 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3090                         (unsigned)(nread+4)));
3091                 reply_readbraw_error(sconn);
3092                 return;
3093         }
3094
3095         if (nread > 0) {
3096                 ret = read_file(fsp,outbuf+4,startpos,nread);
3097 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3098                 if (ret < mincount)
3099                         ret = 0;
3100 #else
3101                 if (ret < nread)
3102                         ret = 0;
3103 #endif
3104         }
3105
3106         _smb_setlen(outbuf,ret);
3107         if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
3108                 char addr[INET6_ADDRSTRLEN];
3109                 /*
3110                  * Try and give an error message saying what
3111                  * client failed.
3112                  */
3113                 DEBUG(0, ("write_data failed for client %s. "
3114                           "Error %s\n",
3115                           get_peer_addr(fsp->conn->sconn->sock, addr,
3116                                         sizeof(addr)),
3117                           strerror(errno)));
3118
3119                 fail_readraw();
3120         }
3121
3122         TALLOC_FREE(outbuf);
3123 }
3124
3125 /****************************************************************************
3126  Reply to a readbraw (core+ protocol).
3127 ****************************************************************************/
3128
3129 void reply_readbraw(struct smb_request *req)
3130 {
3131         connection_struct *conn = req->conn;
3132         struct smbd_server_connection *sconn = req->sconn;
3133         ssize_t maxcount,mincount;
3134         size_t nread = 0;
3135         SMB_OFF_T startpos;
3136         files_struct *fsp;
3137         struct lock_struct lock;
3138         SMB_OFF_T size = 0;
3139
3140         START_PROFILE(SMBreadbraw);
3141
3142         if (srv_is_signing_active(sconn) ||
3143             is_encrypted_packet(sconn, req->inbuf)) {
3144                 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3145                         "raw reads/writes are disallowed.");
3146         }
3147
3148         if (req->wct < 8) {
3149                 reply_readbraw_error(sconn);
3150                 END_PROFILE(SMBreadbraw);
3151                 return;
3152         }
3153
3154         if (sconn->smb1.echo_handler.trusted_fde) {
3155                 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3156                          "'async smb echo handler = yes'\n"));
3157                 reply_readbraw_error(sconn);
3158                 END_PROFILE(SMBreadbraw);
3159                 return;
3160         }
3161
3162         /*
3163          * Special check if an oplock break has been issued
3164          * and the readraw request croses on the wire, we must
3165          * return a zero length response here.
3166          */
3167
3168         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3169
3170         /*
3171          * We have to do a check_fsp by hand here, as
3172          * we must always return 4 zero bytes on error,
3173          * not a NTSTATUS.
3174          */
3175
3176         if (!fsp || !conn || conn != fsp->conn ||
3177                         req->vuid != fsp->vuid ||
3178                         fsp->is_directory || fsp->fh->fd == -1) {
3179                 /*
3180                  * fsp could be NULL here so use the value from the packet. JRA.
3181                  */
3182                 DEBUG(3,("reply_readbraw: fnum %d not valid "
3183                         "- cache prime?\n",
3184                         (int)SVAL(req->vwv+0, 0)));
3185                 reply_readbraw_error(sconn);
3186                 END_PROFILE(SMBreadbraw);
3187                 return;
3188         }
3189
3190         /* Do a "by hand" version of CHECK_READ. */
3191         if (!(fsp->can_read ||
3192                         ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3193                                 (fsp->access_mask & FILE_EXECUTE)))) {
3194                 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3195                                 (int)SVAL(req->vwv+0, 0)));
3196                 reply_readbraw_error(sconn);
3197                 END_PROFILE(SMBreadbraw);
3198                 return;
3199         }
3200
3201         flush_write_cache(fsp, READRAW_FLUSH);
3202
3203         startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3204         if(req->wct == 10) {
3205                 /*
3206                  * This is a large offset (64 bit) read.
3207                  */
3208 #ifdef LARGE_SMB_OFF_T
3209
3210                 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3211
3212 #else /* !LARGE_SMB_OFF_T */
3213
3214                 /*
3215                  * Ensure we haven't been sent a >32 bit offset.
3216                  */
3217
3218                 if(IVAL(req->vwv+8, 0) != 0) {
3219                         DEBUG(0,("reply_readbraw: large offset "
3220                                 "(%x << 32) used and we don't support "
3221                                 "64 bit offsets.\n",
3222                         (unsigned int)IVAL(req->vwv+8, 0) ));
3223                         reply_readbraw_error(sconn);
3224                         END_PROFILE(SMBreadbraw);
3225                         return;
3226                 }
3227
3228 #endif /* LARGE_SMB_OFF_T */
3229
3230                 if(startpos < 0) {
3231                         DEBUG(0,("reply_readbraw: negative 64 bit "
3232                                 "readraw offset (%.0f) !\n",
3233                                 (double)startpos ));
3234                         reply_readbraw_error(sconn);
3235                         END_PROFILE(SMBreadbraw);
3236                         return;
3237                 }
3238         }
3239
3240         maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3241         mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3242
3243         /* ensure we don't overrun the packet size */
3244         maxcount = MIN(65535,maxcount);
3245
3246         init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3247             (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3248             &lock);
3249
3250         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3251                 reply_readbraw_error(sconn);
3252                 END_PROFILE(SMBreadbraw);
3253                 return;
3254         }
3255
3256         if (fsp_stat(fsp) == 0) {
3257                 size = fsp->fsp_name->st.st_ex_size;
3258         }
3259
3260         if (startpos >= size) {
3261                 nread = 0;
3262         } else {
3263                 nread = MIN(maxcount,(size - startpos));
3264         }
3265
3266 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3267         if (nread < mincount)
3268                 nread = 0;
3269 #endif
3270
3271         DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3272                 "min=%lu nread=%lu\n",
3273                 fsp->fnum, (double)startpos,
3274                 (unsigned long)maxcount,
3275                 (unsigned long)mincount,
3276                 (unsigned long)nread ) );
3277
3278         send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3279
3280         DEBUG(5,("reply_readbraw finished\n"));
3281
3282         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3283
3284         END_PROFILE(SMBreadbraw);
3285         return;
3286 }
3287
3288 #undef DBGC_CLASS
3289 #define DBGC_CLASS DBGC_LOCKING
3290
3291 /****************************************************************************
3292  Reply to a lockread (core+ protocol).
3293 ****************************************************************************/
3294
3295 void reply_lockread(struct smb_request *req)
3296 {
3297         connection_struct *conn = req->conn;
3298         ssize_t nread = -1;
3299         char *data;
3300         SMB_OFF_T startpos;
3301         size_t numtoread;
3302         NTSTATUS status;
3303         files_struct *fsp;
3304         struct byte_range_lock *br_lck = NULL;
3305         char *p = NULL;
3306         struct smbd_server_connection *sconn = req->sconn;
3307
3308         START_PROFILE(SMBlockread);
3309
3310         if (req->wct < 5) {
3311                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3312                 END_PROFILE(SMBlockread);
3313                 return;
3314         }
3315
3316         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3317
3318         if (!check_fsp(conn, req, fsp)) {
3319                 END_PROFILE(SMBlockread);
3320                 return;
3321         }
3322
3323         if (!CHECK_READ(fsp,req)) {
3324                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3325                 END_PROFILE(SMBlockread);
3326                 return;
3327         }
3328
3329         numtoread = SVAL(req->vwv+1, 0);
3330         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3331
3332         numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3333
3334         reply_outbuf(req, 5, numtoread + 3);
3335
3336         data = smb_buf(req->outbuf) + 3;
3337
3338         /*
3339          * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3340          * protocol request that predates the read/write lock concept. 
3341          * Thus instead of asking for a read lock here we need to ask
3342          * for a write lock. JRA.
3343          * Note that the requested lock size is unaffected by max_recv.
3344          */
3345
3346         br_lck = do_lock(req->sconn->msg_ctx,
3347                         fsp,
3348                         (uint64_t)req->smbpid,
3349                         (uint64_t)numtoread,
3350                         (uint64_t)startpos,
3351                         WRITE_LOCK,
3352                         WINDOWS_LOCK,
3353                         False, /* Non-blocking lock. */
3354                         &status,
3355                         NULL,
3356                         NULL);
3357         TALLOC_FREE(br_lck);
3358
3359         if (NT_STATUS_V(status)) {
3360                 reply_nterror(req, status);
3361                 END_PROFILE(SMBlockread);
3362                 return;
3363         }
3364
3365         /*
3366          * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3367          */
3368
3369         if (numtoread > sconn->smb1.negprot.max_recv) {
3370                 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3371 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3372                         (unsigned int)numtoread,
3373                         (unsigned int)sconn->smb1.negprot.max_recv));
3374                 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3375         }
3376         nread = read_file(fsp,data,startpos,numtoread);
3377
3378         if (nread < 0) {
3379                 reply_nterror(req, map_nt_error_from_unix(errno));
3380                 END_PROFILE(SMBlockread);
3381                 return;
3382         }
3383
3384         srv_set_message((char *)req->outbuf, 5, nread+3, False);
3385
3386         SSVAL(req->outbuf,smb_vwv0,nread);
3387         SSVAL(req->outbuf,smb_vwv5,nread+3);
3388         p = smb_buf(req->outbuf);
3389         SCVAL(p,0,0); /* pad byte. */
3390         SSVAL(p,1,nread);
3391
3392         DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3393                  fsp->fnum, (int)numtoread, (int)nread));
3394
3395         END_PROFILE(SMBlockread);
3396         return;
3397 }
3398
3399 #undef DBGC_CLASS
3400 #define DBGC_CLASS DBGC_ALL
3401
3402 /****************************************************************************
3403  Reply to a read.
3404 ****************************************************************************/
3405
3406 void reply_read(struct smb_request *req)
3407 {
3408         connection_struct *conn = req->conn;
3409         size_t numtoread;
3410         ssize_t nread = 0;
3411         char *data;
3412         SMB_OFF_T startpos;
3413         int outsize = 0;
3414         files_struct *fsp;
3415         struct lock_struct lock;
3416         struct smbd_server_connection *sconn = req->sconn;
3417
3418         START_PROFILE(SMBread);
3419
3420         if (req->wct < 3) {
3421                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3422                 END_PROFILE(SMBread);
3423                 return;
3424         }
3425
3426         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3427
3428         if (!check_fsp(conn, req, fsp)) {
3429                 END_PROFILE(SMBread);
3430                 return;
3431         }
3432
3433         if (!CHECK_READ(fsp,req)) {
3434                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3435                 END_PROFILE(SMBread);
3436                 return;
3437         }
3438
3439         numtoread = SVAL(req->vwv+1, 0);
3440         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3441
3442         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3443
3444         /*
3445          * The requested read size cannot be greater than max_recv. JRA.
3446          */
3447         if (numtoread > sconn->smb1.negprot.max_recv) {
3448                 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3449 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3450                         (unsigned int)numtoread,
3451                         (unsigned int)sconn->smb1.negprot.max_recv));
3452                 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3453         }
3454
3455         reply_outbuf(req, 5, numtoread+3);
3456
3457         data = smb_buf(req->outbuf) + 3;
3458
3459         init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3460             (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3461             &lock);
3462
3463         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3464                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3465                 END_PROFILE(SMBread);
3466                 return;
3467         }
3468
3469         if (numtoread > 0)
3470                 nread = read_file(fsp,data,startpos,numtoread);
3471
3472         if (nread < 0) {
3473                 reply_nterror(req, map_nt_error_from_unix(errno));
3474                 goto strict_unlock;
3475         }
3476
3477         srv_set_message((char *)req->outbuf, 5, nread+3, False);
3478
3479         SSVAL(req->outbuf,smb_vwv0,nread);
3480         SSVAL(req->outbuf,smb_vwv5,nread+3);
3481         SCVAL(smb_buf(req->outbuf),0,1);
3482         SSVAL(smb_buf(req->outbuf),1,nread);
3483
3484         DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3485                 fsp->fnum, (int)numtoread, (int)nread ) );
3486
3487 strict_unlock:
3488         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3489
3490         END_PROFILE(SMBread);
3491         return;
3492 }
3493
3494 /****************************************************************************
3495  Setup readX header.
3496 ****************************************************************************/
3497
3498 static int setup_readX_header(struct smb_request *req, char *outbuf,
3499                               size_t smb_maxcnt)
3500 {
3501         int outsize;
3502
3503         outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3504
3505         memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3506
3507         SCVAL(outbuf,smb_vwv0,0xFF);
3508         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3509         SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3510         SSVAL(outbuf,smb_vwv6,
3511               (smb_wct - 4)     /* offset from smb header to wct */
3512               + 1               /* the wct field */
3513               + 12 * sizeof(uint16_t) /* vwv */
3514               + 2);             /* the buflen field */
3515         SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3516         SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3517         /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3518         _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3519         return outsize;
3520 }
3521
3522 /****************************************************************************
3523  Reply to a read and X - possibly using sendfile.
3524 ****************************************************************************/
3525
3526 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3527                             files_struct *fsp, SMB_OFF_T startpos,
3528                             size_t smb_maxcnt)
3529 {
3530         ssize_t nread = -1;
3531         struct lock_struct lock;
3532         int saved_errno = 0;
3533
3534         if(fsp_stat(fsp) == -1) {
3535                 reply_nterror(req, map_nt_error_from_unix(errno));
3536                 return;
3537         }
3538
3539         init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3540             (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3541             &lock);
3542
3543         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3544                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3545                 return;
3546         }
3547
3548         if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3549                         (startpos > fsp->fsp_name->st.st_ex_size)
3550                         || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3551                 /*
3552                  * We already know that we would do a short read, so don't
3553                  * try the sendfile() path.
3554                  */
3555                 goto nosendfile_read;
3556         }
3557
3558         /*
3559          * We can only use sendfile on a non-chained packet
3560          * but we can use on a non-oplocked file. tridge proved this
3561          * on a train in Germany :-). JRA.
3562          */
3563
3564         if (!req_is_in_chain(req) &&
3565             !is_encrypted_packet(req->sconn, req->inbuf) &&
3566             (fsp->base_fsp == NULL) &&
3567             (fsp->wcp == NULL) &&
3568             lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3569                 uint8 headerbuf[smb_size + 12 * 2];
3570                 DATA_BLOB header;
3571
3572                 /*
3573                  * Set up the packet header before send. We
3574                  * assume here the sendfile will work (get the
3575                  * correct amount of data).
3576                  */
3577
3578                 header = data_blob_const(headerbuf, sizeof(headerbuf));
3579
3580                 construct_reply_common_req(req, (char *)headerbuf);
3581                 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3582
3583                 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3584                                          startpos, smb_maxcnt);
3585                 if (nread == -1) {
3586                         /* Returning ENOSYS means no data at all was sent.
3587                            Do this as a normal read. */
3588                         if (errno == ENOSYS) {
3589                                 goto normal_read;
3590                         }
3591
3592                         /*
3593                          * Special hack for broken Linux with no working sendfile. If we
3594                          * return EINTR we sent the header but not the rest of the data.
3595                          * Fake this up by doing read/write calls.
3596                          */
3597
3598                         if (errno == EINTR) {
3599                                 /* Ensure we don't do this again. */
3600                                 set_use_sendfile(SNUM(conn), False);
3601                                 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3602                                 nread = fake_sendfile(fsp, startpos,
3603                                                       smb_maxcnt);
3604                                 if (nread == -1) {
3605                                         DEBUG(0,("send_file_readX: "
3606                                                  "fake_sendfile failed for "
3607                                                  "file %s (%s).\n",
3608                                                  fsp_str_dbg(fsp),
3609                                                  strerror(errno)));
3610                                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
3611                                 }
3612                                 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3613                                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3614                                 /* No outbuf here means successful sendfile. */
3615                                 goto strict_unlock;
3616                         }
3617
3618                         DEBUG(0,("send_file_readX: sendfile failed for file "
3619                                  "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3620                                  strerror(errno)));
3621                         exit_server_cleanly("send_file_readX sendfile failed");
3622                 } else if (nread == 0) {
3623                         /*
3624                          * Some sendfile implementations return 0 to indicate
3625                          * that there was a short read, but nothing was
3626                          * actually written to the socket.  In this case,
3627                          * fallback to the normal read path so the header gets
3628                          * the correct byte count.
3629                          */
3630                         DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3631                                   "falling back to the normal read: %s\n",
3632                                   fsp_str_dbg(fsp)));
3633                         goto normal_read;
3634                 }
3635
3636                 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3637                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3638
3639                 /* Deal with possible short send. */
3640                 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3641                         sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3642                 }
3643                 /* No outbuf here means successful sendfile. */
3644                 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3645                 SMB_PERFCOUNT_END(&req->pcd);
3646                 goto strict_unlock;
3647         }
3648
3649 normal_read:
3650
3651         if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3652                 uint8 headerbuf[smb_size + 2*12];
3653
3654                 construct_reply_common_req(req, (char *)headerbuf);
3655                 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3656
3657                 /* Send out the header. */
3658                 if (write_data(req->sconn->sock, (char *)headerbuf,
3659                                sizeof(headerbuf)) != sizeof(headerbuf)) {
3660
3661                         char addr[INET6_ADDRSTRLEN];
3662                         /*
3663                          * Try and give an error message saying what
3664                          * client failed.
3665                          */
3666                         DEBUG(0, ("write_data failed for client %s. "
3667                                   "Error %s\n",
3668                                   get_peer_addr(req->sconn->sock, addr,
3669                                                 sizeof(addr)),
3670                                   strerror(errno)));
3671
3672                         DEBUG(0,("send_file_readX: write_data failed for file "
3673                                  "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3674                                  strerror(errno)));
3675                         exit_server_cleanly("send_file_readX sendfile failed");
3676                 }
3677                 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3678                 if (nread == -1) {
3679                         DEBUG(0,("send_file_readX: fake_sendfile failed for "
3680                                  "file %s (%s).\n", fsp_str_dbg(fsp),
3681                                  strerror(errno)));
3682                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
3683                 }
3684                 goto strict_unlock;
3685         }
3686
3687 nosendfile_read:
3688
3689         reply_outbuf(req, 12, smb_maxcnt);
3690         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
3691         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
3692
3693         nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3694         saved_errno = errno;
3695
3696         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3697
3698         if (nread < 0) {
3699                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3700                 return;
3701         }
3702
3703         setup_readX_header(req, (char *)req->outbuf, nread);
3704
3705         DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3706                     fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3707         return;
3708
3709  strict_unlock:
3710         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3711         TALLOC_FREE(req->outbuf);
3712         return;
3713 }
3714
3715 /****************************************************************************
3716  Reply to a read and X.
3717 ****************************************************************************/
3718
3719 void reply_read_and_X(struct smb_request *req)
3720 {
3721         struct smbd_server_connection *sconn = req->sconn;
3722         connection_struct *conn = req->conn;
3723         files_struct *fsp;
3724         SMB_OFF_T startpos;
3725         size_t smb_maxcnt;
3726         bool big_readX = False;
3727 #if 0
3728         size_t smb_mincnt = SVAL(req->vwv+6, 0);
3729 #endif
3730
3731         START_PROFILE(SMBreadX);
3732
3733         if ((req->wct != 10) && (req->wct != 12)) {
3734                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3735                 return;
3736         }
3737
3738         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3739         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3740         smb_maxcnt = SVAL(req->vwv+5, 0);
3741
3742         /* If it's an IPC, pass off the pipe handler. */
3743         if (IS_IPC(conn)) {
3744                 reply_pipe_read_and_X(req);
3745                 END_PROFILE(SMBreadX);
3746                 return;
3747         }
3748
3749         if (!check_fsp(conn, req, fsp)) {
3750                 END_PROFILE(SMBreadX);
3751                 return;
3752         }
3753
3754         if (!CHECK_READ(fsp,req)) {
3755                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3756                 END_PROFILE(SMBreadX);
3757                 return;
3758         }
3759
3760         if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_LARGE_READ_CAP) ||
3761             (get_remote_arch() == RA_SAMBA)) {
3762                 /*
3763                  * This is Samba only behavior (up to Samba 3.6)!
3764                  *
3765                  * Windows 2008 R2 ignores the upper_size,
3766                  * so we do unless unix extentions are active
3767                  * or "smbclient" is talking to us.
3768                  */
3769                 size_t upper_size = SVAL(req->vwv+7, 0);
3770                 smb_maxcnt |= (upper_size<<16);
3771                 if (upper_size > 1) {
3772                         /* Can't do this on a chained packet. */
3773                         if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3774                                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3775                                 END_PROFILE(SMBreadX);
3776                                 return;
3777                         }
3778                         /* We currently don't do this on signed or sealed data. */
3779                         if (srv_is_signing_active(req->sconn) ||
3780                             is_encrypted_packet(req->sconn, req->inbuf)) {
3781                                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3782                                 END_PROFILE(SMBreadX);
3783                                 return;
3784                         }
3785                         /* Is there room in the reply for this data ? */
3786                         if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2)))  {
3787                                 reply_nterror(req,
3788                                               NT_STATUS_INVALID_PARAMETER);
3789                                 END_PROFILE(SMBreadX);
3790                                 return;
3791                         }
3792                         big_readX = True;
3793                 }
3794         }
3795
3796         if (req->wct == 12) {
3797 #ifdef LARGE_SMB_OFF_T
3798                 /*
3799                  * This is a large offset (64 bit) read.
3800                  */
3801                 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3802
3803 #else /* !LARGE_SMB_OFF_T */
3804
3805                 /*
3806                  * Ensure we haven't been sent a >32 bit offset.
3807                  */
3808
3809                 if(IVAL(req->vwv+10, 0) != 0) {
3810                         DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3811                                  "used and we don't support 64 bit offsets.\n",
3812                                  (unsigned int)IVAL(req->vwv+10, 0) ));
3813                         END_PROFILE(SMBreadX);
3814                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3815                         return;
3816                 }
3817
3818 #endif /* LARGE_SMB_OFF_T */
3819
3820         }
3821
3822         if (!big_readX) {
3823                 NTSTATUS status = schedule_aio_read_and_X(conn,
3824                                         req,
3825                                         fsp,
3826                                         startpos,
3827                                         smb_maxcnt);
3828                 if (NT_STATUS_IS_OK(status)) {
3829                         /* Read scheduled - we're done. */
3830                         goto out;
3831                 }
3832                 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3833                         /* Real error - report to client. */
3834                         END_PROFILE(SMBreadX);
3835                         reply_nterror(req, status);
3836                         return;
3837                 }
3838                 /* NT_STATUS_RETRY - fall back to sync read. */
3839         }
3840
3841         smbd_lock_socket(req->sconn);
3842         send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3843         smbd_unlock_socket(req->sconn);
3844
3845  out:
3846         END_PROFILE(SMBreadX);
3847         return;
3848 }
3849
3850 /****************************************************************************
3851  Error replies to writebraw must have smb_wct == 1. Fix this up.
3852 ****************************************************************************/
3853
3854 void error_to_writebrawerr(struct smb_request *req)
3855 {
3856         uint8 *old_outbuf = req->outbuf;
3857
3858         reply_outbuf(req, 1, 0);
3859
3860         memcpy(req->outbuf, old_outbuf, smb_size);
3861         TALLOC_FREE(old_outbuf);
3862 }
3863
3864 /****************************************************************************
3865  Read 4 bytes of a smb packet and return the smb length of the packet.
3866  Store the result in the buffer. This version of the function will
3867  never return a session keepalive (length of zero).
3868  Timeout is in milliseconds.
3869 ****************************************************************************/
3870
3871 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3872                                 size_t *len)
3873 {
3874         uint8_t msgtype = NBSSkeepalive;
3875
3876         while (msgtype == NBSSkeepalive) {
3877                 NTSTATUS status;
3878
3879                 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3880                                                           len);
3881                 if (!NT_STATUS_IS_OK(status)) {
3882                         char addr[INET6_ADDRSTRLEN];
3883                         /* Try and give an error message
3884                          * saying what client failed. */
3885                         DEBUG(0, ("read_fd_with_timeout failed for "
3886                                   "client %s read error = %s.\n",
3887                                   get_peer_addr(fd,addr,sizeof(addr)),
3888                                   nt_errstr(status)));
3889                         return status;
3890                 }
3891
3892                 msgtype = CVAL(inbuf, 0);
3893         }
3894
3895         DEBUG(10,("read_smb_length: got smb length of %lu\n",
3896                   (unsigned long)len));
3897
3898         return NT_STATUS_OK;
3899 }
3900
3901 /****************************************************************************
3902  Reply to a writebraw (core+ or LANMAN1.0 protocol).
3903 ****************************************************************************/
3904
3905 void reply_writebraw(struct smb_request *req)
3906 {
3907         connection_struct *conn = req->conn;
3908         char *buf = NULL;
3909         ssize_t nwritten=0;
3910         ssize_t total_written=0;
3911         size_t numtowrite=0;
3912         size_t tcount;
3913         SMB_OFF_T startpos;
3914         const char *data=NULL;
3915         bool write_through;
3916         files_struct *fsp;
3917         struct lock_struct lock;
3918         NTSTATUS status;
3919
3920         START_PROFILE(SMBwritebraw);
3921
3922         /*
3923          * If we ever reply with an error, it must have the SMB command
3924          * type of SMBwritec, not SMBwriteBraw, as this tells the client
3925          * we're finished.
3926          */
3927         SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
3928
3929         if (srv_is_signing_active(req->sconn)) {
3930                 END_PROFILE(SMBwritebraw);
3931                 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3932                                 "raw reads/writes are disallowed.");
3933         }
3934
3935         if (req->wct < 12) {
3936                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3937                 error_to_writebrawerr(req);
3938                 END_PROFILE(SMBwritebraw);
3939                 return;
3940         }
3941
3942         if (req->sconn->smb1.echo_handler.trusted_fde) {
3943                 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3944                          "'async smb echo handler = yes'\n"));
3945                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3946                 error_to_writebrawerr(req);
3947                 END_PROFILE(SMBwritebraw);
3948                 return;
3949         }
3950
3951         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3952         if (!check_fsp(conn, req, fsp)) {
3953                 error_to_writebrawerr(req);
3954                 END_PROFILE(SMBwritebraw);
3955                 return;
3956         }
3957
3958         if (!CHECK_WRITE(fsp)) {
3959                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3960                 error_to_writebrawerr(req);
3961                 END_PROFILE(SMBwritebraw);
3962                 return;
3963         }
3964
3965         tcount = IVAL(req->vwv+1, 0);
3966         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3967         write_through = BITSETW(req->vwv+7,0);
3968
3969         /* We have to deal with slightly different formats depending
3970                 on whether we are using the core+ or lanman1.0 protocol */
3971
3972         if(get_Protocol() <= PROTOCOL_COREPLUS) {
3973                 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
3974                 data = smb_buf_const(req->inbuf);
3975         } else {
3976                 numtowrite = SVAL(req->vwv+10, 0);
3977                 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3978         }
3979
3980         /* Ensure we don't write bytes past the end of this packet. */
3981         if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3982                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3983                 error_to_writebrawerr(req);
3984                 END_PROFILE(SMBwritebraw);
3985                 return;
3986         }
3987
3988         if (!fsp->print_file) {
3989                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3990                     (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3991                     &lock);
3992
3993                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3994                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3995                         error_to_writebrawerr(req);
3996                         END_PROFILE(SMBwritebraw);
3997                         return;
3998                 }
3999         }
4000
4001         if (numtowrite>0) {
4002                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4003         }
4004
4005         DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
4006                         "wrote=%d sync=%d\n",
4007                 fsp->fnum, (double)startpos, (int)numtowrite,
4008                 (int)nwritten, (int)write_through));
4009
4010         if (nwritten < (ssize_t)numtowrite)  {
4011                 reply_nterror(req, NT_STATUS_DISK_FULL);
4012                 error_to_writebrawerr(req);
4013                 goto strict_unlock;
4014         }
4015
4016         total_written = nwritten;
4017
4018         /* Allocate a buffer of 64k + length. */
4019         buf = talloc_array(NULL, char, 65540);
4020         if (!buf) {
4021                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4022                 error_to_writebrawerr(req);
4023                 goto strict_unlock;
4024         }
4025
4026         /* Return a SMBwritebraw message to the redirector to tell
4027          * it to send more bytes */
4028
4029         memcpy(buf, req->inbuf, smb_size);
4030         srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4031         SCVAL(buf,smb_com,SMBwritebraw);
4032         SSVALS(buf,smb_vwv0,0xFFFF);
4033         show_msg(buf);
4034         if (!srv_send_smb(req->sconn,
4035                           buf,
4036                           false, 0, /* no signing */
4037                           IS_CONN_ENCRYPTED(conn),
4038                           &req->pcd)) {
4039                 exit_server_cleanly("reply_writebraw: srv_send_smb "
4040                         "failed.");
4041         }
4042
4043         /* Now read the raw data into the buffer and write it */
4044         status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
4045                                  &numtowrite);
4046         if (!NT_STATUS_IS_OK(status)) {
4047                 exit_server_cleanly("secondary writebraw failed");
4048         }
4049
4050         /* Set up outbuf to return the correct size */
4051         reply_outbuf(req, 1, 0);
4052
4053         if (numtowrite != 0) {
4054
4055                 if (numtowrite > 0xFFFF) {
4056                         DEBUG(0,("reply_writebraw: Oversize secondary write "
4057                                 "raw requested (%u). Terminating\n",
4058                                 (unsigned int)numtowrite ));
4059                         exit_server_cleanly("secondary writebraw failed");
4060                 }
4061
4062                 if (tcount > nwritten+numtowrite) {
4063                         DEBUG(3,("reply_writebraw: Client overestimated the "
4064                                 "write %d %d %d\n",
4065                                 (int)tcount,(int)nwritten,(int)numtowrite));
4066                 }
4067
4068                 status = read_data(req->sconn->sock, buf+4, numtowrite);
4069
4070                 if (!NT_STATUS_IS_OK(status)) {
4071                         char addr[INET6_ADDRSTRLEN];
4072                         /* Try and give an error message
4073                          * saying what client failed. */
4074                         DEBUG(0, ("reply_writebraw: Oversize secondary write "
4075                                   "raw read failed (%s) for client %s. "
4076                                   "Terminating\n", nt_errstr(status),
4077                                   get_peer_addr(req->sconn->sock, addr,
4078                                                 sizeof(addr))));
4079                         exit_server_cleanly("secondary writebraw failed");
4080                 }
4081
4082                 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4083                 if (nwritten == -1) {
4084                         TALLOC_FREE(buf);
4085                         reply_nterror(req, map_nt_error_from_unix(errno));
4086                         error_to_writebrawerr(req);
4087                         goto strict_unlock;
4088                 }
4089
4090                 if (nwritten < (ssize_t)numtowrite) {
4091                         SCVAL(req->outbuf,smb_rcls,ERRHRD);
4092                         SSVAL(req->outbuf,smb_err,ERRdiskfull);
4093                 }
4094
4095                 if (nwritten > 0) {
4096                         total_written += nwritten;
4097                 }
4098         }
4099
4100         TALLOC_FREE(buf);
4101         SSVAL(req->outbuf,smb_vwv0,total_written);
4102
4103         status = sync_file(conn, fsp, write_through);
4104         if (!NT_STATUS_IS_OK(status)) {
4105                 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4106                          fsp_str_dbg(fsp), nt_errstr(status)));
4107                 reply_nterror(req, status);
4108                 error_to_writebrawerr(req);
4109                 goto strict_unlock;
4110         }
4111
4112         DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4113                 "wrote=%d\n",
4114                 fsp->fnum, (double)startpos, (int)numtowrite,
4115                 (int)total_written));
4116
4117         if (!fsp->print_file) {
4118                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4119         }
4120
4121         /* We won't return a status if write through is not selected - this
4122          * follows what WfWg does */
4123         END_PROFILE(SMBwritebraw);
4124
4125         if (!write_through && total_written==tcount) {
4126
4127 #if RABBIT_PELLET_FIX
4128                 /*
4129                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4130                  * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4131                  * JRA.
4132                  */
4133                 if (!send_keepalive(req->sconn->sock)) {
4134                         exit_server_cleanly("reply_writebraw: send of "
4135                                 "keepalive failed");
4136                 }
4137 #endif
4138                 TALLOC_FREE(req->outbuf);
4139         }
4140         return;
4141
4142 strict_unlock:
4143         if (!fsp->print_file) {
4144                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4145         }
4146
4147         END_PROFILE(SMBwritebraw);
4148         return;
4149 }
4150
4151 #undef DBGC_CLASS
4152 #define DBGC_CLASS DBGC_LOCKING
4153
4154 /****************************************************************************
4155  Reply to a writeunlock (core+).
4156 ****************************************************************************/
4157
4158 void reply_writeunlock(struct smb_request *req)
4159 {
4160         connection_struct *conn = req->conn;
4161         ssize_t nwritten = -1;
4162         size_t numtowrite;
4163         SMB_OFF_T startpos;
4164         const char *data;
4165         NTSTATUS status = NT_STATUS_OK;
4166         files_struct *fsp;
4167         struct lock_struct lock;
4168         int saved_errno = 0;
4169
4170         START_PROFILE(SMBwriteunlock);
4171
4172         if (req->wct < 5) {
4173                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4174                 END_PROFILE(SMBwriteunlock);
4175                 return;
4176         }
4177
4178         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4179
4180         if (!check_fsp(conn, req, fsp)) {
4181                 END_PROFILE(SMBwriteunlock);
4182                 return;
4183         }
4184
4185         if (!CHECK_WRITE(fsp)) {
4186                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4187                 END_PROFILE(SMBwriteunlock);
4188                 return;
4189         }
4190
4191         numtowrite = SVAL(req->vwv+1, 0);
4192         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4193         data = (const char *)req->buf + 3;
4194
4195         if (!fsp->print_file && numtowrite > 0) {
4196                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4197                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4198                     &lock);
4199
4200                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4201                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4202                         END_PROFILE(SMBwriteunlock);
4203                         return;
4204                 }
4205         }
4206
4207         /* The special X/Open SMB protocol handling of
4208            zero length writes is *NOT* done for
4209            this call */
4210         if(numtowrite == 0) {
4211                 nwritten = 0;
4212         } else {
4213                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4214                 saved_errno = errno;
4215         }
4216
4217         status = sync_file(conn, fsp, False /* write through */);
4218         if (!NT_STATUS_IS_OK(status)) {
4219                 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4220                          fsp_str_dbg(fsp), nt_errstr(status)));
4221                 reply_nterror(req, status);
4222                 goto strict_unlock;
4223         }
4224
4225         if(nwritten < 0) {
4226                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4227                 goto strict_unlock;
4228         }
4229
4230         if((nwritten < numtowrite) && (numtowrite != 0)) {
4231                 reply_nterror(req, NT_STATUS_DISK_FULL);
4232                 goto strict_unlock;
4233         }
4234
4235         if (numtowrite && !fsp->print_file) {
4236                 status = do_unlock(req->sconn->msg_ctx,
4237                                 fsp,
4238                                 (uint64_t)req->smbpid,
4239                                 (uint64_t)numtowrite, 
4240                                 (uint64_t)startpos,
4241                                 WINDOWS_LOCK);
4242
4243                 if (NT_STATUS_V(status)) {
4244                         reply_nterror(req, status);
4245                         goto strict_unlock;
4246                 }
4247         }
4248
4249         reply_outbuf(req, 1, 0);
4250
4251         SSVAL(req->outbuf,smb_vwv0,nwritten);
4252
4253         DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4254                  fsp->fnum, (int)numtowrite, (int)nwritten));
4255
4256 strict_unlock:
4257         if (numtowrite && !fsp->print_file) {
4258                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4259         }
4260
4261         END_PROFILE(SMBwriteunlock);
4262         return;
4263 }
4264
4265 #undef DBGC_CLASS
4266 #define DBGC_CLASS DBGC_ALL
4267
4268 /****************************************************************************
4269  Reply to a write.
4270 ****************************************************************************/
4271
4272 void reply_write(struct smb_request *req)
4273 {
4274         connection_struct *conn = req->conn;
4275         size_t numtowrite;
4276         ssize_t nwritten = -1;
4277         SMB_OFF_T startpos;
4278         const char *data;
4279         files_struct *fsp;
4280         struct lock_struct lock;
4281         NTSTATUS status;
4282         int saved_errno = 0;
4283
4284         START_PROFILE(SMBwrite);
4285
4286         if (req->wct < 5) {
4287                 END_PROFILE(SMBwrite);
4288                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4289                 return;
4290         }
4291
4292         /* If it's an IPC, pass off the pipe handler. */
4293         if (IS_IPC(conn)) {
4294                 reply_pipe_write(req);
4295                 END_PROFILE(SMBwrite);
4296                 return;
4297         }
4298
4299         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4300
4301         if (!check_fsp(conn, req, fsp)) {
4302                 END_PROFILE(SMBwrite);
4303                 return;
4304         }
4305
4306         if (!CHECK_WRITE(fsp)) {
4307                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4308                 END_PROFILE(SMBwrite);
4309                 return;
4310         }
4311
4312         numtowrite = SVAL(req->vwv+1, 0);
4313         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4314         data = (const char *)req->buf + 3;
4315
4316         if (!fsp->print_file) {
4317                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4318                         (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4319                         &lock);
4320
4321                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4322                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4323                         END_PROFILE(SMBwrite);
4324                         return;
4325                 }
4326         }
4327
4328         /*
4329          * X/Open SMB protocol says that if smb_vwv1 is
4330          * zero then the file size should be extended or
4331          * truncated to the size given in smb_vwv[2-3].
4332          */
4333
4334         if(numtowrite == 0) {
4335                 /*
4336                  * This is actually an allocate call, and set EOF. JRA.
4337                  */
4338                 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4339                 if (nwritten < 0) {
4340                         reply_nterror(req, NT_STATUS_DISK_FULL);
4341                         goto strict_unlock;
4342                 }
4343                 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4344                 if (nwritten < 0) {
4345                         reply_nterror(req, NT_STATUS_DISK_FULL);
4346                         goto strict_unlock;
4347                 }
4348                 trigger_write_time_update_immediate(fsp);
4349         } else {
4350                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4351         }
4352
4353         status = sync_file(conn, fsp, False);
4354         if (!NT_STATUS_IS_OK(status)) {
4355                 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4356                          fsp_str_dbg(fsp), nt_errstr(status)));
4357                 reply_nterror(req, status);
4358                 goto strict_unlock;
4359         }
4360
4361         if(nwritten < 0) {
4362                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4363                 goto strict_unlock;
4364         }
4365
4366         if((nwritten == 0) && (numtowrite != 0)) {
4367                 reply_nterror(req, NT_STATUS_DISK_FULL);
4368                 goto strict_unlock;
4369         }
4370
4371         reply_outbuf(req, 1, 0);
4372
4373         SSVAL(req->outbuf,smb_vwv0,nwritten);
4374
4375         if (nwritten < (ssize_t)numtowrite) {
4376                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4377                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4378         }
4379
4380         DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4381
4382 strict_unlock:
4383         if (!fsp->print_file) {
4384                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4385         }
4386
4387         END_PROFILE(SMBwrite);
4388         return;
4389 }
4390
4391 /****************************************************************************
4392  Ensure a buffer is a valid writeX for recvfile purposes.
4393 ****************************************************************************/
4394
4395 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4396                                                 (2*14) + /* word count (including bcc) */ \
4397                                                 1 /* pad byte */)
4398
4399 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4400                             const uint8_t *inbuf)
4401 {
4402         size_t numtowrite;
4403         connection_struct *conn = NULL;
4404         unsigned int doff = 0;
4405         size_t len = smb_len_large(inbuf);
4406
4407         if (is_encrypted_packet(sconn, inbuf)) {
4408                 /* Can't do this on encrypted
4409                  * connections. */
4410                 return false;
4411         }
4412
4413         if (CVAL(inbuf,smb_com) != SMBwriteX) {
4414                 return false;
4415         }
4416
4417         if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4418                         CVAL(inbuf,smb_wct) != 14) {
4419                 DEBUG(10,("is_valid_writeX_buffer: chained or "
4420                         "invalid word length.\n"));
4421                 return false;
4422         }
4423
4424         conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4425         if (conn == NULL) {
4426                 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4427                 return false;
4428         }
4429         if (IS_IPC(conn)) {
4430                 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4431                 return false;
4432         }
4433         if (IS_PRINT(conn)) {
4434                 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4435                 return false;
4436         }
4437         doff = SVAL(inbuf,smb_vwv11);
4438
4439         numtowrite = SVAL(inbuf,smb_vwv10);
4440
4441         if (len > doff && len - doff > 0xFFFF) {
4442                 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4443         }
4444
4445         if (numtowrite == 0) {
4446                 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4447                 return false;
4448         }
4449
4450         /* Ensure the sizes match up. */
4451         if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4452                 /* no pad byte...old smbclient :-( */
4453                 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4454                         (unsigned int)doff,
4455                         (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4456                 return false;
4457         }
4458
4459         if (len - doff != numtowrite) {
4460                 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4461                         "len = %u, doff = %u, numtowrite = %u\n",
4462                         (unsigned int)len,
4463                         (unsigned int)doff,
4464                         (unsigned int)numtowrite ));
4465                 return false;
4466         }
4467
4468         DEBUG(10,("is_valid_writeX_buffer: true "
4469                 "len = %u, doff = %u, numtowrite = %u\n",
4470                 (unsigned int)len,
4471                 (unsigned int)doff,
4472                 (unsigned int)numtowrite ));
4473
4474         return true;
4475 }
4476
4477 /****************************************************************************
4478  Reply to a write and X.
4479 ****************************************************************************/
4480
4481 void reply_write_and_X(struct smb_request *req)
4482 {
4483         connection_struct *conn = req->conn;
4484         files_struct *fsp;
4485         struct lock_struct lock;
4486         SMB_OFF_T startpos;
4487         size_t numtowrite;
4488         bool write_through;
4489         ssize_t nwritten;
4490         unsigned int smb_doff;
4491         unsigned int smblen;
4492         const char *data;
4493         NTSTATUS status;
4494         int saved_errno = 0;
4495
4496         START_PROFILE(SMBwriteX);
4497
4498         if ((req->wct != 12) && (req->wct != 14)) {
4499                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4500                 goto out;
4501         }
4502
4503         numtowrite = SVAL(req->vwv+10, 0);
4504         smb_doff = SVAL(req->vwv+11, 0);
4505         smblen = smb_len(req->inbuf);
4506
4507         if (req->unread_bytes > 0xFFFF ||
4508                         (smblen > smb_doff &&
4509                                 smblen - smb_doff > 0xFFFF)) {
4510                 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4511         }
4512
4513         if (req->unread_bytes) {
4514                 /* Can't do a recvfile write on IPC$ */
4515                 if (IS_IPC(conn)) {
4516                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4517                         goto out;
4518                 }
4519                 if (numtowrite != req->unread_bytes) {
4520                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4521                         goto out;
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                         goto out;
4528                 }
4529         }
4530
4531         /* If it's an IPC, pass off the pipe handler. */
4532         if (IS_IPC(conn)) {
4533                 if (req->unread_bytes) {
4534                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4535                         goto out;
4536                 }
4537                 reply_pipe_write_and_X(req);
4538                 goto out;
4539         }
4540
4541         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4542         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4543         write_through = BITSETW(req->vwv+7,0);
4544
4545         if (!check_fsp(conn, req, fsp)) {
4546                 goto out;
4547         }
4548
4549         if (!CHECK_WRITE(fsp)) {
4550                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4551                 goto out;
4552         }
4553
4554         data = smb_base(req->inbuf) + smb_doff;
4555
4556         if(req->wct == 14) {
4557 #ifdef LARGE_SMB_OFF_T
4558                 /*
4559                  * This is a large offset (64 bit) write.
4560                  */
4561                 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4562
4563 #else /* !LARGE_SMB_OFF_T */
4564
4565                 /*
4566                  * Ensure we haven't been sent a >32 bit offset.
4567                  */
4568
4569                 if(IVAL(req->vwv+12, 0) != 0) {
4570                         DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4571                                  "used and we don't support 64 bit offsets.\n",
4572                                  (unsigned int)IVAL(req->vwv+12, 0) ));
4573                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4574                         goto out;
4575                 }
4576
4577 #endif /* LARGE_SMB_OFF_T */
4578         }
4579
4580         /* X/Open SMB protocol says that, unlike SMBwrite
4581         if the length is zero then NO truncation is
4582         done, just a write of zero. To truncate a file,
4583         use SMBwrite. */
4584
4585         if(numtowrite == 0) {
4586                 nwritten = 0;
4587         } else {
4588                 if (req->unread_bytes == 0) {
4589                         status = schedule_aio_write_and_X(conn,
4590                                                 req,
4591                                                 fsp,
4592                                                 data,
4593                                                 startpos,
4594                                                 numtowrite);
4595
4596                         if (NT_STATUS_IS_OK(status)) {
4597                                 /* write scheduled - we're done. */
4598                                 goto out;
4599                         }
4600                         if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4601                                 /* Real error - report to client. */
4602                                 reply_nterror(req, status);
4603                                 goto out;
4604                         }
4605                         /* NT_STATUS_RETRY - fall through to sync write. */
4606                 }
4607
4608                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4609                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4610                     &lock);
4611
4612                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4613                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4614                         goto out;
4615                 }
4616
4617                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4618                 saved_errno = errno;
4619
4620                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4621         }
4622
4623         if(nwritten < 0) {
4624                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4625                 goto out;
4626         }
4627
4628         if((nwritten == 0) && (numtowrite != 0)) {
4629                 reply_nterror(req, NT_STATUS_DISK_FULL);
4630                 goto out;
4631         }
4632
4633         reply_outbuf(req, 6, 0);
4634         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4635         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
4636         SSVAL(req->outbuf,smb_vwv2,nwritten);
4637         SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4638
4639         DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4640                 fsp->fnum, (int)numtowrite, (int)nwritten));
4641
4642         status = sync_file(conn, fsp, write_through);
4643         if (!NT_STATUS_IS_OK(status)) {
4644                 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4645                          fsp_str_dbg(fsp), nt_errstr(status)));
4646                 reply_nterror(req, status);
4647                 goto out;
4648         }
4649
4650         END_PROFILE(SMBwriteX);
4651         return;
4652
4653 out:
4654         if (req->unread_bytes) {
4655                 /* writeX failed. drain socket. */
4656                 if (drain_socket(req->sconn->sock, req->unread_bytes) !=
4657                                 req->unread_bytes) {
4658                         smb_panic("failed to drain pending bytes");
4659                 }
4660                 req->unread_bytes = 0;
4661         }
4662
4663         END_PROFILE(SMBwriteX);
4664         return;
4665 }
4666
4667 /****************************************************************************
4668  Reply to a lseek.
4669 ****************************************************************************/
4670
4671 void reply_lseek(struct smb_request *req)
4672 {
4673         connection_struct *conn = req->conn;
4674         SMB_OFF_T startpos;
4675         SMB_OFF_T res= -1;
4676         int mode,umode;
4677         files_struct *fsp;
4678
4679         START_PROFILE(SMBlseek);
4680
4681         if (req->wct < 4) {
4682                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4683                 END_PROFILE(SMBlseek);
4684                 return;
4685         }
4686
4687         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4688
4689         if (!check_fsp(conn, req, fsp)) {
4690                 return;
4691         }
4692
4693         flush_write_cache(fsp, SEEK_FLUSH);
4694
4695         mode = SVAL(req->vwv+1, 0) & 3;
4696         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4697         startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4698
4699         switch (mode) {
4700                 case 0:
4701                         umode = SEEK_SET;
4702                         res = startpos;
4703                         break;
4704                 case 1:
4705                         umode = SEEK_CUR;
4706                         res = fsp->fh->pos + startpos;
4707                         break;
4708                 case 2:
4709                         umode = SEEK_END;
4710                         break;
4711                 default:
4712                         umode = SEEK_SET;
4713                         res = startpos;
4714                         break;
4715         }
4716
4717         if (umode == SEEK_END) {
4718                 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4719                         if(errno == EINVAL) {
4720                                 SMB_OFF_T current_pos = startpos;
4721
4722                                 if(fsp_stat(fsp) == -1) {
4723                                         reply_nterror(req,
4724                                                 map_nt_error_from_unix(errno));
4725                                         END_PROFILE(SMBlseek);
4726                                         return;
4727                                 }
4728
4729                                 current_pos += fsp->fsp_name->st.st_ex_size;
4730                                 if(current_pos < 0)
4731                                         res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4732                         }
4733                 }
4734
4735                 if(res == -1) {
4736                         reply_nterror(req, map_nt_error_from_unix(errno));
4737                         END_PROFILE(SMBlseek);
4738                         return;
4739                 }
4740         }
4741
4742         fsp->fh->pos = res;
4743
4744         reply_outbuf(req, 2, 0);
4745         SIVAL(req->outbuf,smb_vwv0,res);
4746
4747         DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4748                 fsp->fnum, (double)startpos, (double)res, mode));
4749
4750         END_PROFILE(SMBlseek);
4751         return;
4752 }
4753
4754 /****************************************************************************
4755  Reply to a flush.
4756 ****************************************************************************/
4757
4758 void reply_flush(struct smb_request *req)
4759 {
4760         connection_struct *conn = req->conn;
4761         uint16 fnum;
4762         files_struct *fsp;
4763
4764         START_PROFILE(SMBflush);
4765
4766         if (req->wct < 1) {
4767                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4768                 return;
4769         }
4770
4771         fnum = SVAL(req->vwv+0, 0);
4772         fsp = file_fsp(req, fnum);
4773
4774         if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4775                 return;
4776         }
4777
4778         if (!fsp) {
4779                 file_sync_all(conn);
4780         } else {
4781                 NTSTATUS status = sync_file(conn, fsp, True);
4782                 if (!NT_STATUS_IS_OK(status)) {
4783                         DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4784                                 fsp_str_dbg(fsp), nt_errstr(status)));
4785                         reply_nterror(req, status);
4786                         END_PROFILE(SMBflush);
4787                         return;
4788                 }
4789         }
4790
4791         reply_outbuf(req, 0, 0);
4792
4793         DEBUG(3,("flush\n"));
4794         END_PROFILE(SMBflush);
4795         return;
4796 }
4797
4798 /****************************************************************************
4799  Reply to a exit.
4800  conn POINTER CAN BE NULL HERE !
4801 ****************************************************************************/
4802
4803 void reply_exit(struct smb_request *req)
4804 {
4805         START_PROFILE(SMBexit);
4806
4807         file_close_pid(req->sconn, req->smbpid, req->vuid);
4808
4809         reply_outbuf(req, 0, 0);
4810
4811         DEBUG(3,("exit\n"));
4812
4813         END_PROFILE(SMBexit);
4814         return;
4815 }
4816
4817 /****************************************************************************
4818  Reply to a close - has to deal with closing a directory opened by NT SMB's.
4819 ****************************************************************************/
4820
4821 void reply_close(struct smb_request *req)
4822 {
4823         connection_struct *conn = req->conn;
4824         NTSTATUS status = NT_STATUS_OK;
4825         files_struct *fsp = NULL;
4826         START_PROFILE(SMBclose);
4827
4828         if (req->wct < 3) {
4829                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4830                 END_PROFILE(SMBclose);
4831                 return;
4832         }
4833
4834         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4835
4836         /*
4837          * We can only use check_fsp if we know it's not a directory.
4838          */
4839
4840         if (!check_fsp_open(conn, req, fsp)) {
4841                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4842                 END_PROFILE(SMBclose);
4843                 return;
4844         }
4845
4846         if(fsp->is_directory) {
4847                 /*
4848                  * Special case - close NT SMB directory handle.
4849                  */
4850                 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4851                 status = close_file(req, fsp, NORMAL_CLOSE);
4852         } else {
4853                 time_t t;
4854                 /*
4855                  * Close ordinary file.
4856                  */
4857
4858                 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4859                          fsp->fh->fd, fsp->fnum,
4860                          conn->num_files_open));
4861
4862                 /*
4863                  * Take care of any time sent in the close.
4864                  */
4865
4866                 t = srv_make_unix_date3(req->vwv+1);
4867                 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4868
4869                 /*
4870                  * close_file() returns the unix errno if an error
4871                  * was detected on close - normally this is due to
4872                  * a disk full error. If not then it was probably an I/O error.
4873                  */
4874
4875                 status = close_file(req, fsp, NORMAL_CLOSE);
4876         }  
4877
4878         if (!NT_STATUS_IS_OK(status)) {
4879                 reply_nterror(req, status);
4880                 END_PROFILE(SMBclose);
4881                 return;
4882         }
4883
4884         reply_outbuf(req, 0, 0);
4885         END_PROFILE(SMBclose);
4886         return;
4887 }
4888
4889 /****************************************************************************
4890  Reply to a writeclose (Core+ protocol).
4891 ****************************************************************************/
4892
4893 void reply_writeclose(struct smb_request *req)
4894 {
4895         connection_struct *conn = req->conn;
4896         size_t numtowrite;
4897         ssize_t nwritten = -1;
4898         NTSTATUS close_status = NT_STATUS_OK;
4899         SMB_OFF_T startpos;
4900         const char *data;
4901         struct timespec mtime;
4902         files_struct *fsp;
4903         struct lock_struct lock;
4904
4905         START_PROFILE(SMBwriteclose);
4906
4907         if (req->wct < 6) {
4908                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4909                 END_PROFILE(SMBwriteclose);
4910                 return;
4911         }
4912
4913         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4914
4915         if (!check_fsp(conn, req, fsp)) {
4916                 END_PROFILE(SMBwriteclose);
4917                 return;
4918         }
4919         if (!CHECK_WRITE(fsp)) {
4920                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4921                 END_PROFILE(SMBwriteclose);
4922                 return;
4923         }
4924
4925         numtowrite = SVAL(req->vwv+1, 0);
4926         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4927         mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4928         data = (const char *)req->buf + 1;
4929
4930         if (!fsp->print_file) {
4931                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4932                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4933                     &lock);
4934
4935                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4936                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4937                         END_PROFILE(SMBwriteclose);
4938                         return;
4939                 }
4940         }
4941
4942         nwritten = write_file(req,fsp,data,startpos,numtowrite);
4943
4944         set_close_write_time(fsp, mtime);
4945
4946         /*
4947          * More insanity. W2K only closes the file if writelen > 0.
4948          * JRA.
4949          */
4950
4951         if (numtowrite) {
4952                 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4953                          "file %s\n", fsp_str_dbg(fsp)));
4954                 close_status = close_file(req, fsp, NORMAL_CLOSE);
4955         }
4956
4957         DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4958                  fsp->fnum, (int)numtowrite, (int)nwritten,
4959                  conn->num_files_open));
4960
4961         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4962                 reply_nterror(req, NT_STATUS_DISK_FULL);
4963                 goto strict_unlock;
4964         }
4965
4966         if(!NT_STATUS_IS_OK(close_status)) {
4967                 reply_nterror(req, close_status);
4968                 goto strict_unlock;
4969         }
4970
4971         reply_outbuf(req, 1, 0);
4972
4973         SSVAL(req->outbuf,smb_vwv0,nwritten);
4974
4975 strict_unlock:
4976         if (numtowrite && !fsp->print_file) {
4977                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4978         }
4979
4980         END_PROFILE(SMBwriteclose);
4981         return;
4982 }
4983
4984 #undef DBGC_CLASS
4985 #define DBGC_CLASS DBGC_LOCKING
4986
4987 /****************************************************************************
4988  Reply to a lock.
4989 ****************************************************************************/
4990
4991 void reply_lock(struct smb_request *req)
4992 {
4993         connection_struct *conn = req->conn;
4994         uint64_t count,offset;
4995         NTSTATUS status;
4996         files_struct *fsp;
4997         struct byte_range_lock *br_lck = NULL;
4998
4999         START_PROFILE(SMBlock);
5000
5001         if (req->wct < 5) {
5002                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5003                 END_PROFILE(SMBlock);
5004                 return;
5005         }
5006
5007         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5008
5009         if (!check_fsp(conn, req, fsp)) {
5010                 END_PROFILE(SMBlock);
5011                 return;
5012         }
5013
5014         count = (uint64_t)IVAL(req->vwv+1, 0);
5015         offset = (uint64_t)IVAL(req->vwv+3, 0);
5016
5017         DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5018                  fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
5019
5020         br_lck = do_lock(req->sconn->msg_ctx,
5021                         fsp,
5022                         (uint64_t)req->smbpid,
5023                         count,
5024                         offset,
5025                         WRITE_LOCK,
5026                         WINDOWS_LOCK,
5027                         False, /* Non-blocking lock. */
5028                         &status,
5029                         NULL,
5030                         NULL);
5031
5032         TALLOC_FREE(br_lck);
5033
5034         if (NT_STATUS_V(status)) {
5035                 reply_nterror(req, status);
5036                 END_PROFILE(SMBlock);
5037                 return;
5038         }
5039
5040         reply_outbuf(req, 0, 0);
5041
5042         END_PROFILE(SMBlock);
5043         return;
5044 }
5045
5046 /****************************************************************************
5047  Reply to a unlock.
5048 ****************************************************************************/
5049
5050 void reply_unlock(struct smb_request *req)
5051 {
5052         connection_struct *conn = req->conn;
5053         uint64_t count,offset;
5054         NTSTATUS status;
5055         files_struct *fsp;
5056
5057         START_PROFILE(SMBunlock);
5058
5059         if (req->wct < 5) {
5060                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5061                 END_PROFILE(SMBunlock);
5062                 return;
5063         }
5064
5065         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5066
5067         if (!check_fsp(conn, req, fsp)) {
5068                 END_PROFILE(SMBunlock);
5069                 return;
5070         }
5071
5072         count = (uint64_t)IVAL(req->vwv+1, 0);
5073         offset = (uint64_t)IVAL(req->vwv+3, 0);
5074
5075         status = do_unlock(req->sconn->msg_ctx,
5076                         fsp,
5077                         (uint64_t)req->smbpid,
5078                         count,
5079                         offset,
5080                         WINDOWS_LOCK);
5081
5082         if (NT_STATUS_V(status)) {
5083                 reply_nterror(req, status);
5084                 END_PROFILE(SMBunlock);
5085                 return;
5086         }
5087
5088         DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5089                     fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
5090
5091         reply_outbuf(req, 0, 0);
5092
5093         END_PROFILE(SMBunlock);
5094         return;
5095 }
5096
5097 #undef DBGC_CLASS
5098 #define DBGC_CLASS DBGC_ALL
5099
5100 /****************************************************************************
5101  Reply to a tdis.
5102  conn POINTER CAN BE NULL HERE !
5103 ****************************************************************************/
5104
5105 void reply_tdis(struct smb_request *req)
5106 {
5107         connection_struct *conn = req->conn;
5108         START_PROFILE(SMBtdis);
5109
5110         if (!conn) {
5111                 DEBUG(4,("Invalid connection in tdis\n"));
5112                 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
5113                 END_PROFILE(SMBtdis);
5114                 return;
5115         }
5116
5117         conn->used = False;
5118
5119         close_cnum(conn,req->vuid);
5120         req->conn = NULL;
5121
5122         reply_outbuf(req, 0, 0);
5123         END_PROFILE(SMBtdis);
5124         return;
5125 }
5126
5127 /****************************************************************************
5128  Reply to a echo.
5129  conn POINTER CAN BE NULL HERE !
5130 ****************************************************************************/
5131
5132 void reply_echo(struct smb_request *req)
5133 {
5134         connection_struct *conn = req->conn;
5135         struct smb_perfcount_data local_pcd;
5136         struct smb_perfcount_data *cur_pcd;
5137         int smb_reverb;
5138         int seq_num;
5139
5140         START_PROFILE(SMBecho);
5141
5142         smb_init_perfcount_data(&local_pcd);
5143
5144         if (req->wct < 1) {
5145                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5146                 END_PROFILE(SMBecho);
5147                 return;
5148         }
5149
5150         smb_reverb = SVAL(req->vwv+0, 0);
5151
5152         reply_outbuf(req, 1, req->buflen);
5153
5154         /* copy any incoming data back out */
5155         if (req->buflen > 0) {
5156                 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5157         }
5158
5159         if (smb_reverb > 100) {
5160                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5161                 smb_reverb = 100;
5162         }
5163
5164         for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5165
5166                 /* this makes sure we catch the request pcd */
5167                 if (seq_num == smb_reverb) {
5168                         cur_pcd = &req->pcd;
5169                 } else {
5170                         SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5171                         cur_pcd = &local_pcd;
5172                 }
5173
5174                 SSVAL(req->outbuf,smb_vwv0,seq_num);
5175
5176                 show_msg((char *)req->outbuf);
5177                 if (!srv_send_smb(req->sconn,
5178                                 (char *)req->outbuf,
5179                                 true, req->seqnum+1,
5180                                 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5181                                 cur_pcd))
5182                         exit_server_cleanly("reply_echo: srv_send_smb failed.");
5183         }
5184
5185         DEBUG(3,("echo %d times\n", smb_reverb));
5186
5187         TALLOC_FREE(req->outbuf);
5188
5189         END_PROFILE(SMBecho);
5190         return;
5191 }
5192
5193 /****************************************************************************
5194  Reply to a printopen.
5195 ****************************************************************************/
5196
5197 void reply_printopen(struct smb_request *req)
5198 {
5199         connection_struct *conn = req->conn;
5200         files_struct *fsp;
5201         NTSTATUS status;
5202
5203         START_PROFILE(SMBsplopen);
5204
5205         if (req->wct < 2) {
5206                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5207                 END_PROFILE(SMBsplopen);
5208                 return;
5209         }
5210
5211         if (!CAN_PRINT(conn)) {
5212                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5213                 END_PROFILE(SMBsplopen);
5214                 return;
5215         }
5216
5217         status = file_new(req, conn, &fsp);
5218         if(!NT_STATUS_IS_OK(status)) {
5219                 reply_nterror(req, status);
5220                 END_PROFILE(SMBsplopen);
5221                 return;
5222         }
5223
5224         /* Open for exclusive use, write only. */
5225         status = print_spool_open(fsp, NULL, req->vuid);
5226
5227         if (!NT_STATUS_IS_OK(status)) {
5228                 file_free(req, fsp);
5229                 reply_nterror(req, status);
5230                 END_PROFILE(SMBsplopen);
5231                 return;
5232         }
5233
5234         reply_outbuf(req, 1, 0);
5235         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5236
5237         DEBUG(3,("openprint fd=%d fnum=%d\n",
5238                  fsp->fh->fd, fsp->fnum));
5239
5240         END_PROFILE(SMBsplopen);
5241         return;
5242 }
5243
5244 /****************************************************************************
5245  Reply to a printclose.
5246 ****************************************************************************/
5247
5248 void reply_printclose(struct smb_request *req)
5249 {
5250         connection_struct *conn = req->conn;
5251         files_struct *fsp;
5252         NTSTATUS status;
5253
5254         START_PROFILE(SMBsplclose);
5255
5256         if (req->wct < 1) {
5257                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5258                 END_PROFILE(SMBsplclose);
5259                 return;
5260         }
5261
5262         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5263
5264         if (!check_fsp(conn, req, fsp)) {
5265                 END_PROFILE(SMBsplclose);
5266                 return;
5267         }
5268
5269         if (!CAN_PRINT(conn)) {
5270                 reply_force_doserror(req, ERRSRV, ERRerror);
5271                 END_PROFILE(SMBsplclose);
5272                 return;
5273         }
5274
5275         DEBUG(3,("printclose fd=%d fnum=%d\n",
5276                  fsp->fh->fd,fsp->fnum));
5277
5278         status = close_file(req, fsp, NORMAL_CLOSE);
5279
5280         if(!NT_STATUS_IS_OK(status)) {
5281                 reply_nterror(req, status);
5282                 END_PROFILE(SMBsplclose);
5283                 return;
5284         }
5285
5286         reply_outbuf(req, 0, 0);
5287
5288         END_PROFILE(SMBsplclose);
5289         return;
5290 }
5291
5292 /****************************************************************************
5293  Reply to a printqueue.
5294 ****************************************************************************/
5295
5296 void reply_printqueue(struct smb_request *req)
5297 {
5298         connection_struct *conn = req->conn;
5299         int max_count;
5300         int start_index;
5301
5302         START_PROFILE(SMBsplretq);
5303
5304         if (req->wct < 2) {
5305                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5306                 END_PROFILE(SMBsplretq);
5307                 return;
5308         }
5309
5310         max_count = SVAL(req->vwv+0, 0);
5311         start_index = SVAL(req->vwv+1, 0);
5312
5313         /* we used to allow the client to get the cnum wrong, but that
5314            is really quite gross and only worked when there was only
5315            one printer - I think we should now only accept it if they
5316            get it right (tridge) */
5317         if (!CAN_PRINT(conn)) {
5318                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5319                 END_PROFILE(SMBsplretq);
5320                 return;
5321         }
5322
5323         reply_outbuf(req, 2, 3);
5324         SSVAL(req->outbuf,smb_vwv0,0);
5325         SSVAL(req->outbuf,smb_vwv1,0);
5326         SCVAL(smb_buf(req->outbuf),0,1);
5327         SSVAL(smb_buf(req->outbuf),1,0);
5328
5329         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5330                  start_index, max_count));
5331
5332         {
5333                 TALLOC_CTX *mem_ctx = talloc_tos();
5334                 NTSTATUS status;
5335                 WERROR werr;
5336                 const char *sharename = lp_servicename(SNUM(conn));
5337                 struct rpc_pipe_client *cli = NULL;
5338                 struct dcerpc_binding_handle *b = NULL;
5339                 struct policy_handle handle;
5340                 struct spoolss_DevmodeContainer devmode_ctr;
5341                 union spoolss_JobInfo *info;
5342                 uint32_t count;
5343                 uint32_t num_to_get;
5344                 uint32_t first;
5345                 uint32_t i;
5346
5347                 ZERO_STRUCT(handle);
5348
5349                 status = rpc_pipe_open_interface(conn,
5350                                                  &ndr_table_spoolss.syntax_id,
5351                                                  conn->session_info,
5352                                                  conn->sconn->remote_address,
5353                                                  conn->sconn->msg_ctx,
5354                                                  &cli);
5355                 if (!NT_STATUS_IS_OK(status)) {
5356                         DEBUG(0, ("reply_printqueue: "
5357                                   "could not connect to spoolss: %s\n",
5358                                   nt_errstr(status)));
5359                         reply_nterror(req, status);
5360                         goto out;
5361                 }
5362                 b = cli->binding_handle;
5363
5364                 ZERO_STRUCT(devmode_ctr);
5365
5366                 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5367                                                 sharename,
5368                                                 NULL, devmode_ctr,
5369                                                 SEC_FLAG_MAXIMUM_ALLOWED,
5370                                                 &handle,
5371                                                 &werr);
5372                 if (!NT_STATUS_IS_OK(status)) {
5373                         reply_nterror(req, status);
5374                         goto out;
5375                 }
5376                 if (!W_ERROR_IS_OK(werr)) {
5377                         reply_nterror(req, werror_to_ntstatus(werr));
5378                         goto out;
5379                 }
5380
5381                 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5382                                                &handle,
5383                                                0, /* firstjob */
5384                                                0xff, /* numjobs */
5385                                                2, /* level */
5386                                                0, /* offered */
5387                                                &count,
5388                                                &info);
5389                 if (!W_ERROR_IS_OK(werr)) {
5390                         reply_nterror(req, werror_to_ntstatus(werr));
5391                         goto out;
5392                 }
5393
5394                 if (max_count > 0) {
5395                         first = start_index;
5396                 } else {
5397                         first = start_index + max_count + 1;
5398                 }
5399
5400                 if (first >= count) {
5401                         num_to_get = first;
5402                 } else {
5403                         num_to_get = first + MIN(ABS(max_count), count - first);
5404                 }
5405
5406                 for (i = first; i < num_to_get; i++) {
5407                         char blob[28];
5408                         char *p = blob;
5409                         time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5410                         int qstatus;
5411                         uint16_t qrapjobid = pjobid_to_rap(sharename,
5412                                                         info[i].info2.job_id);
5413
5414                         if (info[i].info2.status == JOB_STATUS_PRINTING) {
5415                                 qstatus = 2;
5416                         } else {
5417                                 qstatus = 3;
5418                         }
5419
5420                         srv_put_dos_date2(p, 0, qtime);
5421                         SCVAL(p, 4, qstatus);
5422                         SSVAL(p, 5, qrapjobid);
5423                         SIVAL(p, 7, info[i].info2.size);
5424                         SCVAL(p, 11, 0);
5425                         srvstr_push(blob, req->flags2, p+12,
5426                                     info[i].info2.notify_name, 16, STR_ASCII);
5427
5428                         if (message_push_blob(
5429                                     &req->outbuf,
5430                                     data_blob_const(
5431                                             blob, sizeof(blob))) == -1) {
5432                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
5433                                 goto out;
5434                         }
5435                 }
5436
5437                 if (count > 0) {
5438                         SSVAL(req->outbuf,smb_vwv0,count);
5439                         SSVAL(req->outbuf,smb_vwv1,
5440                               (max_count>0?first+count:first-1));
5441                         SCVAL(smb_buf(req->outbuf),0,1);
5442                         SSVAL(smb_buf(req->outbuf),1,28*count);
5443                 }
5444
5445
5446                 DEBUG(3, ("%u entries returned in queue\n",
5447                           (unsigned)count));
5448
5449 out:
5450                 if (b && is_valid_policy_hnd(&handle)) {
5451                         dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5452                 }
5453
5454         }
5455
5456         END_PROFILE(SMBsplretq);
5457         return;
5458 }
5459
5460 /****************************************************************************
5461  Reply to a printwrite.
5462 ****************************************************************************/
5463
5464 void reply_printwrite(struct smb_request *req)
5465 {
5466         connection_struct *conn = req->conn;
5467         int numtowrite;
5468         const char *data;
5469         files_struct *fsp;
5470
5471         START_PROFILE(SMBsplwr);
5472
5473         if (req->wct < 1) {
5474                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5475                 END_PROFILE(SMBsplwr);
5476                 return;
5477         }
5478
5479         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5480
5481         if (!check_fsp(conn, req, fsp)) {
5482                 END_PROFILE(SMBsplwr);
5483                 return;
5484         }
5485
5486         if (!fsp->print_file) {
5487                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5488                 END_PROFILE(SMBsplwr);
5489                 return;
5490         }
5491
5492         if (!CHECK_WRITE(fsp)) {
5493                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5494                 END_PROFILE(SMBsplwr);
5495                 return;
5496         }
5497
5498         numtowrite = SVAL(req->buf, 1);
5499
5500         if (req->buflen < numtowrite + 3) {
5501                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5502                 END_PROFILE(SMBsplwr);
5503                 return;
5504         }
5505
5506         data = (const char *)req->buf + 3;
5507
5508         if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5509                 reply_nterror(req, map_nt_error_from_unix(errno));
5510                 END_PROFILE(SMBsplwr);
5511                 return;
5512         }
5513
5514         DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5515
5516         END_PROFILE(SMBsplwr);
5517         return;
5518 }
5519
5520 /****************************************************************************
5521  Reply to a mkdir.
5522 ****************************************************************************/
5523
5524 void reply_mkdir(struct smb_request *req)
5525 {
5526         connection_struct *conn = req->conn;
5527         struct smb_filename *smb_dname = NULL;
5528         char *directory = NULL;
5529         NTSTATUS status;
5530         TALLOC_CTX *ctx = talloc_tos();
5531
5532         START_PROFILE(SMBmkdir);
5533
5534         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5535                             STR_TERMINATE, &status);
5536         if (!NT_STATUS_IS_OK(status)) {
5537                 reply_nterror(req, status);
5538                 goto out;
5539         }
5540
5541         status = filename_convert(ctx, conn,
5542                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
5543                                  directory,
5544                                  0,
5545                                  NULL,
5546                                  &smb_dname);
5547         if (!NT_STATUS_IS_OK(status)) {
5548                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5549                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5550                                         ERRSRV, ERRbadpath);
5551                         goto out;
5552                 }
5553                 reply_nterror(req, status);
5554                 goto out;
5555         }
5556
5557         status = create_directory(conn, req, smb_dname);
5558
5559         DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5560
5561         if (!NT_STATUS_IS_OK(status)) {
5562
5563                 if (!use_nt_status()
5564                     && NT_STATUS_EQUAL(status,
5565                                        NT_STATUS_OBJECT_NAME_COLLISION)) {
5566                         /*
5567                          * Yes, in the DOS error code case we get a
5568                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5569                          * samba4 torture test.
5570                          */
5571                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5572                 }
5573
5574                 reply_nterror(req, status);
5575                 goto out;
5576         }
5577
5578         reply_outbuf(req, 0, 0);
5579
5580         DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5581  out:
5582         TALLOC_FREE(smb_dname);
5583         END_PROFILE(SMBmkdir);
5584         return;
5585 }
5586
5587 /****************************************************************************
5588  Reply to a rmdir.
5589 ****************************************************************************/
5590
5591 void reply_rmdir(struct smb_request *req)
5592 {
5593         connection_struct *conn = req->conn;
5594         struct smb_filename *smb_dname = NULL;
5595         char *directory = NULL;
5596         NTSTATUS status;
5597         TALLOC_CTX *ctx = talloc_tos();
5598         files_struct *fsp = NULL;
5599         int info = 0;
5600         struct smbd_server_connection *sconn = req->sconn;
5601
5602         START_PROFILE(SMBrmdir);
5603
5604         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5605                             STR_TERMINATE, &status);
5606         if (!NT_STATUS_IS_OK(status)) {
5607                 reply_nterror(req, status);
5608                 goto out;
5609         }
5610
5611         status = filename_convert(ctx, conn,
5612                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
5613                                  directory,
5614                                  0,
5615                                  NULL,
5616                                  &smb_dname);
5617         if (!NT_STATUS_IS_OK(status)) {
5618                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5619                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5620                                         ERRSRV, ERRbadpath);
5621                         goto out;
5622                 }
5623                 reply_nterror(req, status);
5624                 goto out;
5625         }
5626
5627         if (is_ntfs_stream_smb_fname(smb_dname)) {
5628                 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5629                 goto out;
5630         }
5631
5632         status = SMB_VFS_CREATE_FILE(
5633                 conn,                                   /* conn */
5634                 req,                                    /* req */
5635                 0,                                      /* root_dir_fid */
5636                 smb_dname,                              /* fname */
5637                 DELETE_ACCESS,                          /* access_mask */
5638                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
5639                         FILE_SHARE_DELETE),
5640                 FILE_OPEN,                              /* create_disposition*/
5641                 FILE_DIRECTORY_FILE,                    /* create_options */
5642                 FILE_ATTRIBUTE_DIRECTORY,               /* file_attributes */
5643                 0,                                      /* oplock_request */
5644                 0,                                      /* allocation_size */
5645                 0,                                      /* private_flags */
5646                 NULL,                                   /* sd */
5647                 NULL,                                   /* ea_list */
5648                 &fsp,                                   /* result */
5649                 &info);                                 /* pinfo */
5650
5651         if (!NT_STATUS_IS_OK(status)) {
5652                 if (open_was_deferred(req->sconn, req->mid)) {
5653                         /* We have re-scheduled this call. */
5654                         goto out;
5655                 }
5656                 reply_nterror(req, status);
5657                 goto out;
5658         }
5659
5660         status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5661         if (!NT_STATUS_IS_OK(status)) {
5662                 close_file(req, fsp, ERROR_CLOSE);
5663                 reply_nterror(req, status);
5664                 goto out;
5665         }
5666
5667         if (!set_delete_on_close(fsp, true, conn->session_info->unix_token)) {
5668                 close_file(req, fsp, ERROR_CLOSE);
5669                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5670                 goto out;
5671         }
5672
5673         status = close_file(req, fsp, NORMAL_CLOSE);
5674         if (!NT_STATUS_IS_OK(status)) {
5675                 reply_nterror(req, status);
5676         } else {
5677                 reply_outbuf(req, 0, 0);
5678         }
5679
5680         dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5681
5682         DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5683  out:
5684         TALLOC_FREE(smb_dname);
5685         END_PROFILE(SMBrmdir);
5686         return;
5687 }
5688
5689 /*******************************************************************
5690  Resolve wildcards in a filename rename.
5691 ********************************************************************/
5692
5693 static bool resolve_wildcards(TALLOC_CTX *ctx,
5694                                 const char *name1,
5695                                 const char *name2,
5696                                 char **pp_newname)
5697 {
5698         char *name2_copy = NULL;
5699         char *root1 = NULL;
5700         char *root2 = NULL;
5701         char *ext1 = NULL;
5702         char *ext2 = NULL;
5703         char *p,*p2, *pname1, *pname2;
5704
5705         name2_copy = talloc_strdup(ctx, name2);
5706         if (!name2_copy) {
5707                 return False;
5708         }
5709
5710         pname1 = strrchr_m(name1,'/');
5711         pname2 = strrchr_m(name2_copy,'/');
5712
5713         if (!pname1 || !pname2) {
5714                 return False;
5715         }
5716
5717         /* Truncate the copy of name2 at the last '/' */
5718         *pname2 = '\0';
5719
5720         /* Now go past the '/' */
5721         pname1++;
5722         pname2++;
5723
5724         root1 = talloc_strdup(ctx, pname1);
5725         root2 = talloc_strdup(ctx, pname2);
5726
5727         if (!root1 || !root2) {
5728                 return False;
5729         }
5730
5731         p = strrchr_m(root1,'.');
5732         if (p) {
5733                 *p = 0;
5734                 ext1 = talloc_strdup(ctx, p+1);
5735         } else {
5736                 ext1 = talloc_strdup(ctx, "");
5737         }
5738         p = strrchr_m(root2,'.');
5739         if (p) {
5740                 *p = 0;
5741                 ext2 = talloc_strdup(ctx, p+1);
5742         } else {
5743                 ext2 = talloc_strdup(ctx, "");
5744         }
5745
5746         if (!ext1 || !ext2) {
5747                 return False;
5748         }
5749
5750         p = root1;
5751         p2 = root2;
5752         while (*p2) {
5753                 if (*p2 == '?') {
5754                         /* Hmmm. Should this be mb-aware ? */
5755                         *p2 = *p;
5756                         p2++;
5757                 } else if (*p2 == '*') {
5758                         *p2 = '\0';
5759                         root2 = talloc_asprintf(ctx, "%s%s",
5760                                                 root2,
5761                                                 p);
5762                         if (!root2) {
5763                                 return False;
5764                         }
5765                         break;
5766                 } else {
5767                         p2++;
5768                 }
5769                 if (*p) {
5770                         p++;
5771                 }
5772         }
5773
5774         p = ext1;
5775         p2 = ext2;
5776         while (*p2) {
5777                 if (*p2 == '?') {
5778                         /* Hmmm. Should this be mb-aware ? */
5779                         *p2 = *p;
5780                         p2++;
5781                 } else if (*p2 == '*') {
5782                         *p2 = '\0';
5783                         ext2 = talloc_asprintf(ctx, "%s%s",
5784                                                 ext2,
5785                                                 p);
5786                         if (!ext2) {
5787                                 return False;
5788                         }
5789                         break;
5790                 } else {
5791                         p2++;
5792                 }
5793                 if (*p) {
5794                         p++;
5795                 }
5796         }
5797
5798         if (*ext2) {
5799                 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5800                                 name2_copy,
5801                                 root2,
5802                                 ext2);
5803         } else {
5804                 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5805                                 name2_copy,
5806                                 root2);
5807         }
5808
5809         if (!*pp_newname) {
5810                 return False;
5811         }
5812
5813         return True;
5814 }
5815
5816 /****************************************************************************
5817  Ensure open files have their names updated. Updated to notify other smbd's
5818  asynchronously.
5819 ****************************************************************************/
5820
5821 static void rename_open_files(connection_struct *conn,
5822                               struct share_mode_lock *lck,
5823                               uint32_t orig_name_hash,
5824                               const struct smb_filename *smb_fname_dst)
5825 {
5826         files_struct *fsp;
5827         bool did_rename = False;
5828         NTSTATUS status;
5829         uint32_t new_name_hash = 0;
5830
5831         for(fsp = file_find_di_first(conn->sconn, lck->data->id); fsp;
5832             fsp = file_find_di_next(fsp)) {
5833                 /* fsp_name is a relative path under the fsp. To change this for other
5834                    sharepaths we need to manipulate relative paths. */
5835                 /* TODO - create the absolute path and manipulate the newname
5836                    relative to the sharepath. */
5837                 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5838                         continue;
5839                 }
5840                 if (fsp->name_hash != orig_name_hash) {
5841                         continue;
5842                 }
5843                 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5844                            "(file_id %s) from %s -> %s\n", fsp->fnum,
5845                            file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5846                            smb_fname_str_dbg(smb_fname_dst)));
5847
5848                 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5849                 if (NT_STATUS_IS_OK(status)) {
5850                         did_rename = True;
5851                         new_name_hash = fsp->name_hash;
5852                 }
5853         }
5854
5855         if (!did_rename) {
5856                 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5857                            "for %s\n", file_id_string_tos(&lck->data->id),
5858                            smb_fname_str_dbg(smb_fname_dst)));
5859         }
5860
5861         /* Send messages to all smbd's (not ourself) that the name has changed. */
5862         rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5863                               orig_name_hash, new_name_hash,
5864                               smb_fname_dst);
5865
5866 }
5867
5868 /****************************************************************************
5869  We need to check if the source path is a parent directory of the destination
5870  (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5871  refuse the rename with a sharing violation. Under UNIX the above call can
5872  *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5873  probably need to check that the client is a Windows one before disallowing
5874  this as a UNIX client (one with UNIX extensions) can know the source is a
5875  symlink and make this decision intelligently. Found by an excellent bug
5876  report from <AndyLiebman@aol.com>.
5877 ****************************************************************************/
5878
5879 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5880                                      const struct smb_filename *smb_fname_dst)
5881 {
5882         const char *psrc = smb_fname_src->base_name;
5883         const char *pdst = smb_fname_dst->base_name;
5884         size_t slen;
5885
5886         if (psrc[0] == '.' && psrc[1] == '/') {
5887                 psrc += 2;
5888         }
5889         if (pdst[0] == '.' && pdst[1] == '/') {
5890                 pdst += 2;
5891         }
5892         if ((slen = strlen(psrc)) > strlen(pdst)) {
5893                 return False;
5894         }
5895         return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5896 }
5897
5898 /*
5899  * Do the notify calls from a rename
5900  */
5901
5902 static void notify_rename(connection_struct *conn, bool is_dir,
5903                           const struct smb_filename *smb_fname_src,
5904                           const struct smb_filename *smb_fname_dst)
5905 {
5906         char *parent_dir_src = NULL;
5907         char *parent_dir_dst = NULL;
5908         uint32 mask;
5909
5910         mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5911                 : FILE_NOTIFY_CHANGE_FILE_NAME;
5912
5913         if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5914                             &parent_dir_src, NULL) ||
5915             !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5916                             &parent_dir_dst, NULL)) {
5917                 goto out;
5918         }
5919
5920         if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5921                 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5922                              smb_fname_src->base_name);
5923                 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5924                              smb_fname_dst->base_name);
5925         }
5926         else {
5927                 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5928                              smb_fname_src->base_name);
5929                 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5930                              smb_fname_dst->base_name);
5931         }
5932
5933         /* this is a strange one. w2k3 gives an additional event for
5934            CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5935            files, but not directories */
5936         if (!is_dir) {
5937                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5938                              FILE_NOTIFY_CHANGE_ATTRIBUTES
5939                              |FILE_NOTIFY_CHANGE_CREATION,
5940                              smb_fname_dst->base_name);
5941         }
5942  out:
5943         TALLOC_FREE(parent_dir_src);
5944         TALLOC_FREE(parent_dir_dst);
5945 }
5946
5947 /****************************************************************************
5948  Returns an error if the parent directory for a filename is open in an
5949  incompatible way.
5950 ****************************************************************************/
5951
5952 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
5953                                         const struct smb_filename *smb_fname_dst_in)
5954 {
5955         char *parent_dir = NULL;
5956         struct smb_filename smb_fname_parent;
5957         struct file_id id;
5958         files_struct *fsp = NULL;
5959         int ret;
5960
5961         if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
5962                         &parent_dir, NULL)) {
5963                 return NT_STATUS_NO_MEMORY;
5964         }
5965         ZERO_STRUCT(smb_fname_parent);
5966         smb_fname_parent.base_name = parent_dir;
5967
5968         ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
5969         if (ret == -1) {
5970                 return map_nt_error_from_unix(errno);
5971         }
5972
5973         /*
5974          * We're only checking on this smbd here, mostly good
5975          * enough.. and will pass tests.
5976          */
5977
5978         id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
5979         for (fsp = file_find_di_first(conn->sconn, id); fsp;
5980                         fsp = file_find_di_next(fsp)) {
5981                 if (fsp->access_mask & DELETE_ACCESS) {
5982                         return NT_STATUS_SHARING_VIOLATION;
5983                 }
5984         }
5985         return NT_STATUS_OK;
5986 }
5987
5988 /****************************************************************************
5989  Rename an open file - given an fsp.
5990 ****************************************************************************/
5991
5992 NTSTATUS rename_internals_fsp(connection_struct *conn,
5993                         files_struct *fsp,
5994                         const struct smb_filename *smb_fname_dst_in,
5995                         uint32 attrs,
5996                         bool replace_if_exists)
5997 {
5998         TALLOC_CTX *ctx = talloc_tos();
5999         struct smb_filename *smb_fname_dst = NULL;
6000         NTSTATUS status = NT_STATUS_OK;
6001         struct share_mode_lock *lck = NULL;
6002         bool dst_exists, old_is_stream, new_is_stream;
6003
6004         status = check_name(conn, smb_fname_dst_in->base_name);
6005         if (!NT_STATUS_IS_OK(status)) {
6006                 return status;
6007         }
6008
6009         status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6010         if (!NT_STATUS_IS_OK(status)) {
6011                 return status;
6012         }
6013
6014         /* Make a copy of the dst smb_fname structs */
6015
6016         status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
6017         if (!NT_STATUS_IS_OK(status)) {
6018                 goto out;
6019         }
6020
6021         /*
6022          * Check for special case with case preserving and not
6023          * case sensitive. If the old last component differs from the original
6024          * last component only by case, then we should allow
6025          * the rename (user is trying to change the case of the
6026          * filename).
6027          */
6028         if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
6029             strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6030             strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6031                 char *last_slash;
6032                 char *fname_dst_lcomp_base_mod = NULL;
6033                 struct smb_filename *smb_fname_orig_lcomp = NULL;
6034
6035                 /*
6036                  * Get the last component of the destination name.
6037                  */
6038                 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
6039                 if (last_slash) {
6040                         fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
6041                 } else {
6042                         fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
6043                 }
6044                 if (!fname_dst_lcomp_base_mod) {
6045                         status = NT_STATUS_NO_MEMORY;
6046                         goto out;
6047                 }
6048
6049                 /*
6050                  * Create an smb_filename struct using the original last
6051                  * component of the destination.
6052                  */
6053                 status = create_synthetic_smb_fname_split(ctx,
6054                     smb_fname_dst->original_lcomp, NULL,
6055                     &smb_fname_orig_lcomp);
6056                 if (!NT_STATUS_IS_OK(status)) {
6057                         TALLOC_FREE(fname_dst_lcomp_base_mod);
6058                         goto out;
6059                 }
6060
6061                 /* If the base names only differ by case, use original. */
6062                 if(!strcsequal(fname_dst_lcomp_base_mod,
6063                                smb_fname_orig_lcomp->base_name)) {
6064                         char *tmp;
6065                         /*
6066                          * Replace the modified last component with the
6067                          * original.
6068                          */
6069                         if (last_slash) {
6070                                 *last_slash = '\0'; /* Truncate at the '/' */
6071                                 tmp = talloc_asprintf(smb_fname_dst,
6072                                         "%s/%s",
6073                                         smb_fname_dst->base_name,
6074                                         smb_fname_orig_lcomp->base_name);
6075                         } else {
6076                                 tmp = talloc_asprintf(smb_fname_dst,
6077                                         "%s",
6078                                         smb_fname_orig_lcomp->base_name);
6079                         }
6080                         if (tmp == NULL) {
6081                                 status = NT_STATUS_NO_MEMORY;
6082                                 TALLOC_FREE(fname_dst_lcomp_base_mod);
6083                                 TALLOC_FREE(smb_fname_orig_lcomp);
6084                                 goto out;
6085                         }
6086                         TALLOC_FREE(smb_fname_dst->base_name);
6087                         smb_fname_dst->base_name = tmp;
6088                 }
6089
6090                 /* If the stream_names only differ by case, use original. */
6091                 if(!strcsequal(smb_fname_dst->stream_name,
6092                                smb_fname_orig_lcomp->stream_name)) {
6093                         char *tmp = NULL;
6094                         /* Use the original stream. */
6095                         tmp = talloc_strdup(smb_fname_dst,
6096                                             smb_fname_orig_lcomp->stream_name);
6097                         if (tmp == NULL) {
6098                                 status = NT_STATUS_NO_MEMORY;
6099                                 TALLOC_FREE(fname_dst_lcomp_base_mod);
6100                                 TALLOC_FREE(smb_fname_orig_lcomp);
6101                                 goto out;
6102                         }
6103                         TALLOC_FREE(smb_fname_dst->stream_name);
6104                         smb_fname_dst->stream_name = tmp;
6105                 }
6106                 TALLOC_FREE(fname_dst_lcomp_base_mod);
6107                 TALLOC_FREE(smb_fname_orig_lcomp);
6108         }
6109
6110         /*
6111          * If the src and dest names are identical - including case,
6112          * don't do the rename, just return success.
6113          */
6114
6115         if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6116             strcsequal(fsp->fsp_name->stream_name,
6117                        smb_fname_dst->stream_name)) {
6118                 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6119                           "- returning success\n",
6120                           smb_fname_str_dbg(smb_fname_dst)));
6121                 status = NT_STATUS_OK;
6122                 goto out;
6123         }
6124
6125         old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6126         new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6127
6128         /* Return the correct error code if both names aren't streams. */
6129         if (!old_is_stream && new_is_stream) {
6130                 status = NT_STATUS_OBJECT_NAME_INVALID;
6131                 goto out;
6132         }
6133
6134         if (old_is_stream && !new_is_stream) {
6135                 status = NT_STATUS_INVALID_PARAMETER;
6136                 goto out;
6137         }
6138
6139         dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6140
6141         if(!replace_if_exists && dst_exists) {
6142                 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6143                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6144                           smb_fname_str_dbg(smb_fname_dst)));
6145                 status = NT_STATUS_OBJECT_NAME_COLLISION;
6146                 goto out;
6147         }
6148
6149         if (dst_exists) {
6150                 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6151                     &smb_fname_dst->st);
6152                 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6153                                                            fileid);
6154                 /* The file can be open when renaming a stream */
6155                 if (dst_fsp && !new_is_stream) {
6156                         DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6157                         status = NT_STATUS_ACCESS_DENIED;
6158                         goto out;
6159                 }
6160         }
6161
6162         /* Ensure we have a valid stat struct for the source. */
6163         status = vfs_stat_fsp(fsp);
6164         if (!NT_STATUS_IS_OK(status)) {
6165                 goto out;
6166         }
6167
6168         status = can_rename(conn, fsp, attrs);
6169
6170         if (!NT_STATUS_IS_OK(status)) {
6171                 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6172                           nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6173                           smb_fname_str_dbg(smb_fname_dst)));
6174                 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6175                         status = NT_STATUS_ACCESS_DENIED;
6176                 goto out;
6177         }
6178
6179         if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6180                 status = NT_STATUS_ACCESS_DENIED;
6181         }
6182
6183         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6184
6185         /*
6186          * We have the file open ourselves, so not being able to get the
6187          * corresponding share mode lock is a fatal error.
6188          */
6189
6190         SMB_ASSERT(lck != NULL);
6191
6192         if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6193                 uint32 create_options = fsp->fh->private_options;
6194
6195                 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6196                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6197                           smb_fname_str_dbg(smb_fname_dst)));
6198
6199                 if (!lp_posix_pathnames() &&
6200                     (lp_map_archive(SNUM(conn)) ||
6201                     lp_store_dos_attributes(SNUM(conn)))) {
6202                         /* We must set the archive bit on the newly
6203                            renamed file. */
6204                         if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6205                                 uint32_t old_dosmode = dos_mode(conn,
6206                                                         smb_fname_dst);
6207                                 file_set_dosmode(conn,
6208                                         smb_fname_dst,
6209                                         old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6210                                         NULL,
6211                                         true);
6212                         }
6213                 }
6214
6215                 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6216                               smb_fname_dst);
6217
6218                 rename_open_files(conn, lck, fsp->name_hash, smb_fname_dst);
6219
6220                 /*
6221                  * A rename acts as a new file create w.r.t. allowing an initial delete
6222                  * on close, probably because in Windows there is a new handle to the
6223                  * new file. If initial delete on close was requested but not
6224                  * originally set, we need to set it here. This is probably not 100% correct,
6225                  * but will work for the CIFSFS client which in non-posix mode
6226                  * depends on these semantics. JRA.
6227                  */
6228
6229                 if (create_options & FILE_DELETE_ON_CLOSE) {
6230                         status = can_set_delete_on_close(fsp, 0);
6231
6232                         if (NT_STATUS_IS_OK(status)) {
6233                                 /* Note that here we set the *inital* delete on close flag,
6234                                  * not the regular one. The magic gets handled in close. */
6235                                 fsp->initial_delete_on_close = True;
6236                         }
6237                 }
6238                 TALLOC_FREE(lck);
6239                 status = NT_STATUS_OK;
6240                 goto out;
6241         }
6242
6243         TALLOC_FREE(lck);
6244
6245         if (errno == ENOTDIR || errno == EISDIR) {
6246                 status = NT_STATUS_OBJECT_NAME_COLLISION;
6247         } else {
6248                 status = map_nt_error_from_unix(errno);
6249         }
6250
6251         DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6252                   nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6253                   smb_fname_str_dbg(smb_fname_dst)));
6254
6255  out:
6256         TALLOC_FREE(smb_fname_dst);
6257
6258         return status;
6259 }
6260
6261 /****************************************************************************
6262  The guts of the rename command, split out so it may be called by the NT SMB
6263  code.
6264 ****************************************************************************/
6265
6266 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6267                         connection_struct *conn,
6268                         struct smb_request *req,
6269                         struct smb_filename *smb_fname_src,
6270                         struct smb_filename *smb_fname_dst,
6271                         uint32 attrs,
6272                         bool replace_if_exists,
6273                         bool src_has_wild,
6274                         bool dest_has_wild,
6275                         uint32_t access_mask)
6276 {
6277         char *fname_src_dir = NULL;
6278         char *fname_src_mask = NULL;
6279         int count=0;
6280         NTSTATUS status = NT_STATUS_OK;
6281         struct smb_Dir *dir_hnd = NULL;
6282         const char *dname = NULL;
6283         char *talloced = NULL;
6284         long offset = 0;
6285         int create_options = 0;
6286         bool posix_pathnames = lp_posix_pathnames();
6287
6288         /*
6289          * Split the old name into directory and last component
6290          * strings. Note that unix_convert may have stripped off a
6291          * leading ./ from both name and newname if the rename is
6292          * at the root of the share. We need to make sure either both
6293          * name and newname contain a / character or neither of them do
6294          * as this is checked in resolve_wildcards().
6295          */
6296
6297         /* Split up the directory from the filename/mask. */
6298         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6299                                       &fname_src_dir, &fname_src_mask);
6300         if (!NT_STATUS_IS_OK(status)) {
6301                 status = NT_STATUS_NO_MEMORY;
6302                 goto out;
6303         }
6304
6305         /*
6306          * We should only check the mangled cache
6307          * here if unix_convert failed. This means
6308          * that the path in 'mask' doesn't exist
6309          * on the file system and so we need to look
6310          * for a possible mangle. This patch from
6311          * Tine Smukavec <valentin.smukavec@hermes.si>.
6312          */
6313
6314         if (!VALID_STAT(smb_fname_src->st) &&
6315             mangle_is_mangled(fname_src_mask, conn->params)) {
6316                 char *new_mask = NULL;
6317                 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6318                                             conn->params);
6319                 if (new_mask) {
6320                         TALLOC_FREE(fname_src_mask);
6321                         fname_src_mask = new_mask;
6322                 }
6323         }
6324
6325         if (!src_has_wild) {
6326                 files_struct *fsp;
6327
6328                 /*
6329                  * Only one file needs to be renamed. Append the mask back
6330                  * onto the directory.
6331                  */
6332                 TALLOC_FREE(smb_fname_src->base_name);
6333                 if (ISDOT(fname_src_dir)) {
6334                         /* Ensure we use canonical names on open. */
6335                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6336                                                         "%s",
6337                                                         fname_src_mask);
6338                 } else {
6339                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6340                                                         "%s/%s",
6341                                                         fname_src_dir,
6342                                                         fname_src_mask);
6343                 }
6344                 if (!smb_fname_src->base_name) {
6345                         status = NT_STATUS_NO_MEMORY;
6346                         goto out;
6347                 }
6348
6349                 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6350                           "case_preserve = %d, short case preserve = %d, "
6351                           "directory = %s, newname = %s, "
6352                           "last_component_dest = %s\n",
6353                           conn->case_sensitive, conn->case_preserve,
6354                           conn->short_case_preserve,
6355                           smb_fname_str_dbg(smb_fname_src),
6356                           smb_fname_str_dbg(smb_fname_dst),
6357                           smb_fname_dst->original_lcomp));
6358
6359                 /* The dest name still may have wildcards. */
6360                 if (dest_has_wild) {
6361                         char *fname_dst_mod = NULL;
6362                         if (!resolve_wildcards(smb_fname_dst,
6363                                                smb_fname_src->base_name,
6364                                                smb_fname_dst->base_name,
6365                                                &fname_dst_mod)) {
6366                                 DEBUG(6, ("rename_internals: resolve_wildcards "
6367                                           "%s %s failed\n",
6368                                           smb_fname_src->base_name,
6369                                           smb_fname_dst->base_name));
6370                                 status = NT_STATUS_NO_MEMORY;
6371                                 goto out;
6372                         }
6373                         TALLOC_FREE(smb_fname_dst->base_name);
6374                         smb_fname_dst->base_name = fname_dst_mod;
6375                 }
6376
6377                 ZERO_STRUCT(smb_fname_src->st);
6378                 if (posix_pathnames) {
6379                         SMB_VFS_LSTAT(conn, smb_fname_src);
6380                 } else {
6381                         SMB_VFS_STAT(conn, smb_fname_src);
6382                 }
6383
6384                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6385                         create_options |= FILE_DIRECTORY_FILE;
6386                 }
6387
6388                 status = SMB_VFS_CREATE_FILE(
6389                         conn,                           /* conn */
6390                         req,                            /* req */
6391                         0,                              /* root_dir_fid */
6392                         smb_fname_src,                  /* fname */
6393                         access_mask,                    /* access_mask */
6394                         (FILE_SHARE_READ |              /* share_access */
6395                             FILE_SHARE_WRITE),
6396                         FILE_OPEN,                      /* create_disposition*/
6397                         create_options,                 /* create_options */
6398                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6399                         0,                              /* oplock_request */
6400                         0,                              /* allocation_size */
6401                         0,                              /* private_flags */
6402                         NULL,                           /* sd */
6403                         NULL,                           /* ea_list */
6404                         &fsp,                           /* result */
6405                         NULL);                          /* pinfo */
6406
6407                 if (!NT_STATUS_IS_OK(status)) {
6408                         DEBUG(3, ("Could not open rename source %s: %s\n",
6409                                   smb_fname_str_dbg(smb_fname_src),
6410                                   nt_errstr(status)));
6411                         goto out;
6412                 }
6413
6414                 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6415                                               attrs, replace_if_exists);
6416
6417                 close_file(req, fsp, NORMAL_CLOSE);
6418
6419                 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6420                           nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6421                           smb_fname_str_dbg(smb_fname_dst)));
6422
6423                 goto out;
6424         }
6425
6426         /*
6427          * Wildcards - process each file that matches.
6428          */
6429         if (strequal(fname_src_mask, "????????.???")) {
6430                 TALLOC_FREE(fname_src_mask);
6431                 fname_src_mask = talloc_strdup(ctx, "*");
6432                 if (!fname_src_mask) {
6433                         status = NT_STATUS_NO_MEMORY;
6434                         goto out;
6435                 }
6436         }
6437
6438         status = check_name(conn, fname_src_dir);
6439         if (!NT_STATUS_IS_OK(status)) {
6440                 goto out;
6441         }
6442
6443         dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6444                           attrs);
6445         if (dir_hnd == NULL) {
6446                 status = map_nt_error_from_unix(errno);
6447                 goto out;
6448         }
6449
6450         status = NT_STATUS_NO_SUCH_FILE;
6451         /*
6452          * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6453          * - gentest fix. JRA
6454          */
6455
6456         while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6457                                     &talloced))) {
6458                 files_struct *fsp = NULL;
6459                 char *destname = NULL;
6460                 bool sysdir_entry = False;
6461
6462                 /* Quick check for "." and ".." */
6463                 if (ISDOT(dname) || ISDOTDOT(dname)) {
6464                         if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6465                                 sysdir_entry = True;
6466                         } else {
6467                                 TALLOC_FREE(talloced);
6468                                 continue;
6469                         }
6470                 }
6471
6472                 if (!is_visible_file(conn, fname_src_dir, dname,
6473                                      &smb_fname_src->st, false)) {
6474                         TALLOC_FREE(talloced);
6475                         continue;
6476                 }
6477
6478                 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6479                         TALLOC_FREE(talloced);
6480                         continue;
6481                 }
6482
6483                 if (sysdir_entry) {
6484                         status = NT_STATUS_OBJECT_NAME_INVALID;
6485                         break;
6486                 }
6487
6488                 TALLOC_FREE(smb_fname_src->base_name);
6489                 if (ISDOT(fname_src_dir)) {
6490                         /* Ensure we use canonical names on open. */
6491                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6492                                                         "%s",
6493                                                         dname);
6494                 } else {
6495                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6496                                                         "%s/%s",
6497                                                         fname_src_dir,
6498                                                         dname);
6499                 }
6500                 if (!smb_fname_src->base_name) {
6501                         status = NT_STATUS_NO_MEMORY;
6502                         goto out;
6503                 }
6504
6505                 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6506                                        smb_fname_dst->base_name,
6507                                        &destname)) {
6508                         DEBUG(6, ("resolve_wildcards %s %s failed\n",
6509                                   smb_fname_src->base_name, destname));
6510                         TALLOC_FREE(talloced);
6511                         continue;
6512                 }
6513                 if (!destname) {
6514                         status = NT_STATUS_NO_MEMORY;
6515                         goto out;
6516                 }
6517
6518                 TALLOC_FREE(smb_fname_dst->base_name);
6519                 smb_fname_dst->base_name = destname;
6520
6521                 ZERO_STRUCT(smb_fname_src->st);
6522                 if (posix_pathnames) {
6523                         SMB_VFS_LSTAT(conn, smb_fname_src);
6524                 } else {
6525                         SMB_VFS_STAT(conn, smb_fname_src);
6526                 }
6527
6528                 create_options = 0;
6529
6530                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6531                         create_options |= FILE_DIRECTORY_FILE;
6532                 }
6533
6534                 status = SMB_VFS_CREATE_FILE(
6535                         conn,                           /* conn */
6536                         req,                            /* req */
6537                         0,                              /* root_dir_fid */
6538                         smb_fname_src,                  /* fname */
6539                         access_mask,                    /* access_mask */
6540                         (FILE_SHARE_READ |              /* share_access */
6541                             FILE_SHARE_WRITE),
6542                         FILE_OPEN,                      /* create_disposition*/
6543                         create_options,                 /* create_options */
6544                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6545                         0,                              /* oplock_request */
6546                         0,                              /* allocation_size */
6547                         0,                              /* private_flags */
6548                         NULL,                           /* sd */
6549                         NULL,                           /* ea_list */
6550                         &fsp,                           /* result */
6551                         NULL);                          /* pinfo */
6552
6553                 if (!NT_STATUS_IS_OK(status)) {
6554                         DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6555                                  "returned %s rename %s -> %s\n",
6556                                  nt_errstr(status),
6557                                  smb_fname_str_dbg(smb_fname_src),
6558                                  smb_fname_str_dbg(smb_fname_dst)));
6559                         break;
6560                 }
6561
6562                 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6563                                                               dname);
6564                 if (!smb_fname_dst->original_lcomp) {
6565                         status = NT_STATUS_NO_MEMORY;
6566                         goto out;
6567                 }
6568
6569                 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6570                                               attrs, replace_if_exists);
6571
6572                 close_file(req, fsp, NORMAL_CLOSE);
6573
6574                 if (!NT_STATUS_IS_OK(status)) {
6575                         DEBUG(3, ("rename_internals_fsp returned %s for "
6576                                   "rename %s -> %s\n", nt_errstr(status),
6577                                   smb_fname_str_dbg(smb_fname_src),
6578                                   smb_fname_str_dbg(smb_fname_dst)));
6579                         break;
6580                 }
6581
6582                 count++;
6583
6584                 DEBUG(3,("rename_internals: doing rename on %s -> "
6585                          "%s\n", smb_fname_str_dbg(smb_fname_src),
6586                          smb_fname_str_dbg(smb_fname_src)));
6587                 TALLOC_FREE(talloced);
6588         }
6589         TALLOC_FREE(dir_hnd);
6590
6591         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6592                 status = map_nt_error_from_unix(errno);
6593         }
6594
6595  out:
6596         TALLOC_FREE(talloced);
6597         TALLOC_FREE(fname_src_dir);
6598         TALLOC_FREE(fname_src_mask);
6599         return status;
6600 }
6601
6602 /****************************************************************************
6603  Reply to a mv.
6604 ****************************************************************************/
6605
6606 void reply_mv(struct smb_request *req)
6607 {
6608         connection_struct *conn = req->conn;
6609         char *name = NULL;
6610         char *newname = NULL;
6611         const char *p;
6612         uint32 attrs;
6613         NTSTATUS status;
6614         bool src_has_wcard = False;
6615         bool dest_has_wcard = False;
6616         TALLOC_CTX *ctx = talloc_tos();
6617         struct smb_filename *smb_fname_src = NULL;
6618         struct smb_filename *smb_fname_dst = NULL;
6619         uint32_t src_ucf_flags = lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP : UCF_COND_ALLOW_WCARD_LCOMP;
6620         uint32_t dst_ucf_flags = UCF_SAVE_LCOMP | (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP);
6621         bool stream_rename = false;
6622
6623         START_PROFILE(SMBmv);
6624
6625         if (req->wct < 1) {
6626                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6627                 goto out;
6628         }
6629
6630         attrs = SVAL(req->vwv+0, 0);
6631
6632         p = (const char *)req->buf + 1;
6633         p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6634                                        &status, &src_has_wcard);
6635         if (!NT_STATUS_IS_OK(status)) {
6636                 reply_nterror(req, status);
6637                 goto out;
6638         }
6639         p++;
6640         p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6641                                        &status, &dest_has_wcard);
6642         if (!NT_STATUS_IS_OK(status)) {
6643                 reply_nterror(req, status);
6644                 goto out;
6645         }
6646
6647         if (!lp_posix_pathnames()) {
6648                 /* The newname must begin with a ':' if the
6649                    name contains a ':'. */
6650                 if (strchr_m(name, ':')) {
6651                         if (newname[0] != ':') {
6652                                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6653                                 goto out;
6654                         }
6655                         stream_rename = true;
6656                 }
6657         }
6658
6659         status = filename_convert(ctx,
6660                                   conn,
6661                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6662                                   name,
6663                                   src_ucf_flags,
6664                                   &src_has_wcard,
6665                                   &smb_fname_src);
6666
6667         if (!NT_STATUS_IS_OK(status)) {
6668                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6669                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6670                                         ERRSRV, ERRbadpath);
6671                         goto out;
6672                 }
6673                 reply_nterror(req, status);
6674                 goto out;
6675         }
6676
6677         status = filename_convert(ctx,
6678                                   conn,
6679                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6680                                   newname,
6681                                   dst_ucf_flags,
6682                                   &dest_has_wcard,
6683                                   &smb_fname_dst);
6684
6685         if (!NT_STATUS_IS_OK(status)) {
6686                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6687                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6688                                         ERRSRV, ERRbadpath);
6689                         goto out;
6690                 }
6691                 reply_nterror(req, status);
6692                 goto out;
6693         }
6694
6695         if (stream_rename) {
6696                 /* smb_fname_dst->base_name must be the same as
6697                    smb_fname_src->base_name. */
6698                 TALLOC_FREE(smb_fname_dst->base_name);
6699                 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6700                                                 smb_fname_src->base_name);
6701                 if (!smb_fname_dst->base_name) {
6702                         reply_nterror(req, NT_STATUS_NO_MEMORY);
6703                         goto out;
6704                 }
6705         }
6706
6707         DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6708                  smb_fname_str_dbg(smb_fname_dst)));
6709
6710         status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6711                                   attrs, False, src_has_wcard, dest_has_wcard,
6712                                   DELETE_ACCESS);
6713         if (!NT_STATUS_IS_OK(status)) {
6714                 if (open_was_deferred(req->sconn, req->mid)) {
6715                         /* We have re-scheduled this call. */
6716                         goto out;
6717                 }
6718                 reply_nterror(req, status);
6719                 goto out;
6720         }
6721
6722         reply_outbuf(req, 0, 0);
6723  out:
6724         TALLOC_FREE(smb_fname_src);
6725         TALLOC_FREE(smb_fname_dst);
6726         END_PROFILE(SMBmv);
6727         return;
6728 }
6729
6730 /*******************************************************************
6731  Copy a file as part of a reply_copy.
6732 ******************************************************************/
6733
6734 /*
6735  * TODO: check error codes on all callers
6736  */
6737
6738 NTSTATUS copy_file(TALLOC_CTX *ctx,
6739                         connection_struct *conn,
6740                         struct smb_filename *smb_fname_src,
6741                         struct smb_filename *smb_fname_dst,
6742                         int ofun,
6743                         int count,
6744                         bool target_is_directory)
6745 {
6746         struct smb_filename *smb_fname_dst_tmp = NULL;
6747         SMB_OFF_T ret=-1;
6748         files_struct *fsp1,*fsp2;
6749         uint32 dosattrs;
6750         uint32 new_create_disposition;
6751         NTSTATUS status;
6752
6753
6754         status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6755         if (!NT_STATUS_IS_OK(status)) {
6756                 return status;
6757         }
6758
6759         /*
6760          * If the target is a directory, extract the last component from the
6761          * src filename and append it to the dst filename
6762          */
6763         if (target_is_directory) {
6764                 const char *p;
6765
6766                 /* dest/target can't be a stream if it's a directory. */
6767                 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6768
6769                 p = strrchr_m(smb_fname_src->base_name,'/');
6770                 if (p) {
6771                         p++;
6772                 } else {
6773                         p = smb_fname_src->base_name;
6774                 }
6775                 smb_fname_dst_tmp->base_name =
6776                     talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6777                                            p);
6778                 if (!smb_fname_dst_tmp->base_name) {
6779                         status = NT_STATUS_NO_MEMORY;
6780                         goto out;
6781                 }
6782         }
6783
6784         status = vfs_file_exist(conn, smb_fname_src);
6785         if (!NT_STATUS_IS_OK(status)) {
6786                 goto out;
6787         }
6788
6789         if (!target_is_directory && count) {
6790                 new_create_disposition = FILE_OPEN;
6791         } else {
6792                 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
6793                                                  0, ofun,
6794                                                  NULL, NULL,
6795                                                  &new_create_disposition,
6796                                                  NULL,
6797                                                  NULL)) {
6798                         status = NT_STATUS_INVALID_PARAMETER;
6799                         goto out;
6800                 }
6801         }
6802
6803         /* Open the src file for reading. */
6804         status = SMB_VFS_CREATE_FILE(
6805                 conn,                                   /* conn */
6806                 NULL,                                   /* req */
6807                 0,                                      /* root_dir_fid */
6808                 smb_fname_src,                          /* fname */
6809                 FILE_GENERIC_READ,                      /* access_mask */
6810                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
6811                 FILE_OPEN,                              /* create_disposition*/
6812                 0,                                      /* create_options */
6813                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
6814                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
6815                 0,                                      /* allocation_size */
6816                 0,                                      /* private_flags */
6817                 NULL,                                   /* sd */
6818                 NULL,                                   /* ea_list */
6819                 &fsp1,                                  /* result */
6820                 NULL);                                  /* psbuf */
6821
6822         if (!NT_STATUS_IS_OK(status)) {
6823                 goto out;
6824         }
6825
6826         dosattrs = dos_mode(conn, smb_fname_src);
6827
6828         if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6829                 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6830         }
6831
6832         /* Open the dst file for writing. */
6833         status = SMB_VFS_CREATE_FILE(
6834                 conn,                                   /* conn */
6835                 NULL,                                   /* req */
6836                 0,                                      /* root_dir_fid */
6837                 smb_fname_dst,                          /* fname */
6838                 FILE_GENERIC_WRITE,                     /* access_mask */
6839                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
6840                 new_create_disposition,                 /* create_disposition*/
6841                 0,                                      /* create_options */
6842                 dosattrs,                               /* file_attributes */
6843                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
6844                 0,                                      /* allocation_size */
6845                 0,                                      /* private_flags */
6846                 NULL,                                   /* sd */
6847                 NULL,                                   /* ea_list */
6848                 &fsp2,                                  /* result */
6849                 NULL);                                  /* psbuf */
6850
6851         if (!NT_STATUS_IS_OK(status)) {
6852                 close_file(NULL, fsp1, ERROR_CLOSE);
6853                 goto out;
6854         }
6855
6856         if (ofun & OPENX_FILE_EXISTS_OPEN) {
6857                 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
6858                 if (ret == -1) {
6859                         DEBUG(0, ("error - vfs lseek returned error %s\n",
6860                                 strerror(errno)));
6861                         status = map_nt_error_from_unix(errno);
6862                         close_file(NULL, fsp1, ERROR_CLOSE);
6863                         close_file(NULL, fsp2, ERROR_CLOSE);
6864                         goto out;
6865                 }
6866         }
6867
6868         /* Do the actual copy. */
6869         if (smb_fname_src->st.st_ex_size) {
6870                 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6871         } else {
6872                 ret = 0;
6873         }
6874
6875         close_file(NULL, fsp1, NORMAL_CLOSE);
6876
6877         /* Ensure the modtime is set correctly on the destination file. */
6878         set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6879
6880         /*
6881          * As we are opening fsp1 read-only we only expect
6882          * an error on close on fsp2 if we are out of space.
6883          * Thus we don't look at the error return from the
6884          * close of fsp1.
6885          */
6886         status = close_file(NULL, fsp2, NORMAL_CLOSE);
6887
6888         if (!NT_STATUS_IS_OK(status)) {
6889                 goto out;
6890         }
6891
6892         if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6893                 status = NT_STATUS_DISK_FULL;
6894                 goto out;
6895         }
6896
6897         status = NT_STATUS_OK;
6898
6899  out:
6900         TALLOC_FREE(smb_fname_dst_tmp);
6901         return status;
6902 }
6903
6904 /****************************************************************************
6905  Reply to a file copy.
6906 ****************************************************************************/
6907
6908 void reply_copy(struct smb_request *req)
6909 {
6910         connection_struct *conn = req->conn;
6911         struct smb_filename *smb_fname_src = NULL;
6912         struct smb_filename *smb_fname_dst = NULL;
6913         char *fname_src = NULL;
6914         char *fname_dst = NULL;
6915         char *fname_src_mask = NULL;
6916         char *fname_src_dir = NULL;
6917         const char *p;
6918         int count=0;
6919         int error = ERRnoaccess;
6920         int tid2;
6921         int ofun;
6922         int flags;
6923         bool target_is_directory=False;
6924         bool source_has_wild = False;
6925         bool dest_has_wild = False;
6926         NTSTATUS status;
6927         TALLOC_CTX *ctx = talloc_tos();
6928
6929         START_PROFILE(SMBcopy);
6930
6931         if (req->wct < 3) {
6932                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6933                 goto out;
6934         }
6935
6936         tid2 = SVAL(req->vwv+0, 0);
6937         ofun = SVAL(req->vwv+1, 0);
6938         flags = SVAL(req->vwv+2, 0);
6939
6940         p = (const char *)req->buf;
6941         p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6942                                        &status, &source_has_wild);
6943         if (!NT_STATUS_IS_OK(status)) {
6944                 reply_nterror(req, status);
6945                 goto out;
6946         }
6947         p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6948                                        &status, &dest_has_wild);
6949         if (!NT_STATUS_IS_OK(status)) {
6950                 reply_nterror(req, status);
6951                 goto out;
6952         }
6953
6954         DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6955
6956         if (tid2 != conn->cnum) {
6957                 /* can't currently handle inter share copies XXXX */
6958                 DEBUG(3,("Rejecting inter-share copy\n"));
6959                 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6960                 goto out;
6961         }
6962
6963         status = filename_convert(ctx, conn,
6964                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6965                                   fname_src,
6966                                   UCF_COND_ALLOW_WCARD_LCOMP,
6967                                   &source_has_wild,
6968                                   &smb_fname_src);
6969         if (!NT_STATUS_IS_OK(status)) {
6970                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6971                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6972                                         ERRSRV, ERRbadpath);
6973                         goto out;
6974                 }
6975                 reply_nterror(req, status);
6976                 goto out;
6977         }
6978
6979         status = filename_convert(ctx, conn,
6980                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6981                                   fname_dst,
6982                                   UCF_COND_ALLOW_WCARD_LCOMP,
6983                                   &dest_has_wild,
6984                                   &smb_fname_dst);
6985         if (!NT_STATUS_IS_OK(status)) {
6986                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6987                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6988                                         ERRSRV, ERRbadpath);
6989                         goto out;
6990                 }
6991                 reply_nterror(req, status);
6992                 goto out;
6993         }
6994
6995         target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6996
6997         if ((flags&1) && target_is_directory) {
6998                 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6999                 goto out;
7000         }
7001
7002         if ((flags&2) && !target_is_directory) {
7003                 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7004                 goto out;
7005         }
7006
7007         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7008                 /* wants a tree copy! XXXX */
7009                 DEBUG(3,("Rejecting tree copy\n"));
7010                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7011                 goto out;
7012         }
7013
7014         /* Split up the directory from the filename/mask. */
7015         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7016                                       &fname_src_dir, &fname_src_mask);
7017         if (!NT_STATUS_IS_OK(status)) {
7018                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7019                 goto out;
7020         }
7021
7022         /*
7023          * We should only check the mangled cache
7024          * here if unix_convert failed. This means
7025          * that the path in 'mask' doesn't exist
7026          * on the file system and so we need to look
7027          * for a possible mangle. This patch from
7028          * Tine Smukavec <valentin.smukavec@hermes.si>.
7029          */
7030         if (!VALID_STAT(smb_fname_src->st) &&
7031             mangle_is_mangled(fname_src_mask, conn->params)) {
7032                 char *new_mask = NULL;
7033                 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7034                                             &new_mask, conn->params);
7035
7036                 /* Use demangled name if one was successfully found. */
7037                 if (new_mask) {
7038                         TALLOC_FREE(fname_src_mask);
7039                         fname_src_mask = new_mask;
7040                 }
7041         }
7042
7043         if (!source_has_wild) {
7044
7045                 /*
7046                  * Only one file needs to be copied. Append the mask back onto
7047                  * the directory.
7048                  */
7049                 TALLOC_FREE(smb_fname_src->base_name);
7050                 if (ISDOT(fname_src_dir)) {
7051                         /* Ensure we use canonical names on open. */
7052                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7053                                                         "%s",
7054                                                         fname_src_mask);
7055                 } else {
7056                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7057                                                         "%s/%s",
7058                                                         fname_src_dir,
7059                                                         fname_src_mask);
7060                 }
7061                 if (!smb_fname_src->base_name) {
7062                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7063                         goto out;
7064                 }
7065
7066                 if (dest_has_wild) {
7067                         char *fname_dst_mod = NULL;
7068                         if (!resolve_wildcards(smb_fname_dst,
7069                                                smb_fname_src->base_name,
7070                                                smb_fname_dst->base_name,
7071                                                &fname_dst_mod)) {
7072                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7073                                 goto out;
7074                         }
7075                         TALLOC_FREE(smb_fname_dst->base_name);
7076                         smb_fname_dst->base_name = fname_dst_mod;
7077                 }
7078
7079                 status = check_name(conn, smb_fname_src->base_name);
7080                 if (!NT_STATUS_IS_OK(status)) {
7081                         reply_nterror(req, status);
7082                         goto out;
7083                 }
7084
7085                 status = check_name(conn, smb_fname_dst->base_name);
7086                 if (!NT_STATUS_IS_OK(status)) {
7087                         reply_nterror(req, status);
7088                         goto out;
7089                 }
7090
7091                 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7092                                    ofun, count, target_is_directory);
7093
7094                 if(!NT_STATUS_IS_OK(status)) {
7095                         reply_nterror(req, status);
7096                         goto out;
7097                 } else {
7098                         count++;
7099                 }
7100         } else {
7101                 struct smb_Dir *dir_hnd = NULL;
7102                 const char *dname = NULL;
7103                 char *talloced = NULL;
7104                 long offset = 0;
7105
7106                 /*
7107                  * There is a wildcard that requires us to actually read the
7108                  * src dir and copy each file matching the mask to the dst.
7109                  * Right now streams won't be copied, but this could
7110                  * presumably be added with a nested loop for reach dir entry.
7111                  */
7112                 SMB_ASSERT(!smb_fname_src->stream_name);
7113                 SMB_ASSERT(!smb_fname_dst->stream_name);
7114
7115                 smb_fname_src->stream_name = NULL;
7116                 smb_fname_dst->stream_name = NULL;
7117
7118                 if (strequal(fname_src_mask,"????????.???")) {
7119                         TALLOC_FREE(fname_src_mask);
7120                         fname_src_mask = talloc_strdup(ctx, "*");
7121                         if (!fname_src_mask) {
7122                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7123                                 goto out;
7124                         }
7125                 }
7126
7127                 status = check_name(conn, fname_src_dir);
7128                 if (!NT_STATUS_IS_OK(status)) {
7129                         reply_nterror(req, status);
7130                         goto out;
7131                 }
7132
7133                 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7134                 if (dir_hnd == NULL) {
7135                         status = map_nt_error_from_unix(errno);
7136                         reply_nterror(req, status);
7137                         goto out;
7138                 }
7139
7140                 error = ERRbadfile;
7141
7142                 /* Iterate over the src dir copying each entry to the dst. */
7143                 while ((dname = ReadDirName(dir_hnd, &offset,
7144                                             &smb_fname_src->st, &talloced))) {
7145                         char *destname = NULL;
7146
7147                         if (ISDOT(dname) || ISDOTDOT(dname)) {
7148                                 TALLOC_FREE(talloced);
7149                                 continue;
7150                         }
7151
7152                         if (!is_visible_file(conn, fname_src_dir, dname,
7153                                              &smb_fname_src->st, false)) {
7154                                 TALLOC_FREE(talloced);
7155                                 continue;
7156                         }
7157
7158                         if(!mask_match(dname, fname_src_mask,
7159                                        conn->case_sensitive)) {
7160                                 TALLOC_FREE(talloced);
7161                                 continue;
7162                         }
7163
7164                         error = ERRnoaccess;
7165
7166                         /* Get the src smb_fname struct setup. */
7167                         TALLOC_FREE(smb_fname_src->base_name);
7168                         if (ISDOT(fname_src_dir)) {
7169                                 /* Ensure we use canonical names on open. */
7170                                 smb_fname_src->base_name =
7171                                         talloc_asprintf(smb_fname_src, "%s",
7172                                                 dname);
7173                         } else {
7174                                 smb_fname_src->base_name =
7175                                         talloc_asprintf(smb_fname_src, "%s/%s",
7176                                                 fname_src_dir, dname);
7177                         }
7178
7179                         if (!smb_fname_src->base_name) {
7180                                 TALLOC_FREE(dir_hnd);
7181                                 TALLOC_FREE(talloced);
7182                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7183                                 goto out;
7184                         }
7185
7186                         if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7187                                                smb_fname_dst->base_name,
7188                                                &destname)) {
7189                                 TALLOC_FREE(talloced);
7190                                 continue;
7191                         }
7192                         if (!destname) {
7193                                 TALLOC_FREE(dir_hnd);
7194                                 TALLOC_FREE(talloced);
7195                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7196                                 goto out;
7197                         }
7198
7199                         TALLOC_FREE(smb_fname_dst->base_name);
7200                         smb_fname_dst->base_name = destname;
7201
7202                         status = check_name(conn, smb_fname_src->base_name);
7203                         if (!NT_STATUS_IS_OK(status)) {
7204                                 TALLOC_FREE(dir_hnd);
7205                                 TALLOC_FREE(talloced);
7206                                 reply_nterror(req, status);
7207                                 goto out;
7208                         }
7209
7210                         status = check_name(conn, smb_fname_dst->base_name);
7211                         if (!NT_STATUS_IS_OK(status)) {
7212                                 TALLOC_FREE(dir_hnd);
7213                                 TALLOC_FREE(talloced);
7214                                 reply_nterror(req, status);
7215                                 goto out;
7216                         }
7217
7218                         DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7219                                 smb_fname_src->base_name,
7220                                 smb_fname_dst->base_name));
7221
7222                         status = copy_file(ctx, conn, smb_fname_src,
7223                                            smb_fname_dst, ofun, count,
7224                                            target_is_directory);
7225                         if (NT_STATUS_IS_OK(status)) {
7226                                 count++;
7227                         }
7228
7229                         TALLOC_FREE(talloced);
7230                 }
7231                 TALLOC_FREE(dir_hnd);
7232         }
7233
7234         if (count == 0) {
7235                 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7236                 goto out;
7237         }
7238
7239         reply_outbuf(req, 1, 0);
7240         SSVAL(req->outbuf,smb_vwv0,count);
7241  out:
7242         TALLOC_FREE(smb_fname_src);
7243         TALLOC_FREE(smb_fname_dst);
7244         TALLOC_FREE(fname_src);
7245         TALLOC_FREE(fname_dst);
7246         TALLOC_FREE(fname_src_mask);
7247         TALLOC_FREE(fname_src_dir);
7248
7249         END_PROFILE(SMBcopy);
7250         return;
7251 }
7252
7253 #undef DBGC_CLASS
7254 #define DBGC_CLASS DBGC_LOCKING
7255
7256 /****************************************************************************
7257  Get a lock pid, dealing with large count requests.
7258 ****************************************************************************/
7259
7260 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7261                     bool large_file_format)
7262 {
7263         if(!large_file_format)
7264                 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7265         else
7266                 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7267 }
7268
7269 /****************************************************************************
7270  Get a lock count, dealing with large count requests.
7271 ****************************************************************************/
7272
7273 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7274                         bool large_file_format)
7275 {
7276         uint64_t count = 0;
7277
7278         if(!large_file_format) {
7279                 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7280         } else {
7281
7282 #if defined(HAVE_LONGLONG)
7283                 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7284                         ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7285 #else /* HAVE_LONGLONG */
7286
7287                 /*
7288                  * NT4.x seems to be broken in that it sends large file (64 bit)
7289                  * lockingX calls even if the CAP_LARGE_FILES was *not*
7290                  * negotiated. For boxes without large unsigned ints truncate the
7291                  * lock count by dropping the top 32 bits.
7292                  */
7293
7294                 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7295                         DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7296                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7297                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7298                                 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7299                 }
7300
7301                 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7302 #endif /* HAVE_LONGLONG */
7303         }
7304
7305         return count;
7306 }
7307
7308 #if !defined(HAVE_LONGLONG)
7309 /****************************************************************************
7310  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7311 ****************************************************************************/
7312
7313 static uint32 map_lock_offset(uint32 high, uint32 low)
7314 {
7315         unsigned int i;
7316         uint32 mask = 0;
7317         uint32 highcopy = high;
7318
7319         /*
7320          * Try and find out how many significant bits there are in high.
7321          */
7322
7323         for(i = 0; highcopy; i++)
7324                 highcopy >>= 1;
7325
7326         /*
7327          * We use 31 bits not 32 here as POSIX
7328          * lock offsets may not be negative.
7329          */
7330
7331         mask = (~0) << (31 - i);
7332
7333         if(low & mask)
7334                 return 0; /* Fail. */
7335
7336         high <<= (31 - i);
7337
7338         return (high|low);
7339 }
7340 #endif /* !defined(HAVE_LONGLONG) */
7341
7342 /****************************************************************************
7343  Get a lock offset, dealing with large offset requests.
7344 ****************************************************************************/
7345
7346 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7347                          bool large_file_format, bool *err)
7348 {
7349         uint64_t offset = 0;
7350
7351         *err = False;
7352
7353         if(!large_file_format) {
7354                 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7355         } else {
7356
7357 #if defined(HAVE_LONGLONG)
7358                 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7359                                 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7360 #else /* HAVE_LONGLONG */
7361
7362                 /*
7363                  * NT4.x seems to be broken in that it sends large file (64 bit)
7364                  * lockingX calls even if the CAP_LARGE_FILES was *not*
7365                  * negotiated. For boxes without large unsigned ints mangle the
7366                  * lock offset by mapping the top 32 bits onto the lower 32.
7367                  */
7368
7369                 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7370                         uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7371                         uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7372                         uint32 new_low = 0;
7373
7374                         if((new_low = map_lock_offset(high, low)) == 0) {
7375                                 *err = True;
7376                                 return (uint64_t)-1;
7377                         }
7378
7379                         DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7380                                 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7381                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7382                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7383                 }
7384
7385                 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7386 #endif /* HAVE_LONGLONG */
7387         }
7388
7389         return offset;
7390 }
7391
7392 NTSTATUS smbd_do_locking(struct smb_request *req,
7393                          files_struct *fsp,
7394                          uint8_t type,
7395                          int32_t timeout,
7396                          uint16_t num_ulocks,
7397                          struct smbd_lock_element *ulocks,
7398                          uint16_t num_locks,
7399                          struct smbd_lock_element *locks,
7400                          bool *async)
7401 {
7402         connection_struct *conn = req->conn;
7403         int i;
7404         NTSTATUS status = NT_STATUS_OK;
7405
7406         *async = false;
7407
7408         /* Data now points at the beginning of the list
7409            of smb_unlkrng structs */
7410         for(i = 0; i < (int)num_ulocks; i++) {
7411                 struct smbd_lock_element *e = &ulocks[i];
7412
7413                 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7414                           "pid %u, file %s\n",
7415                           (double)e->offset,
7416                           (double)e->count,
7417                           (unsigned int)e->smblctx,
7418                           fsp_str_dbg(fsp)));
7419
7420                 if (e->brltype != UNLOCK_LOCK) {
7421                         /* this can only happen with SMB2 */
7422                         return NT_STATUS_INVALID_PARAMETER;
7423                 }
7424
7425                 status = do_unlock(req->sconn->msg_ctx,
7426                                 fsp,
7427                                 e->smblctx,
7428                                 e->count,
7429                                 e->offset,
7430                                 WINDOWS_LOCK);
7431
7432                 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7433                     nt_errstr(status)));
7434
7435                 if (!NT_STATUS_IS_OK(status)) {
7436                         return status;
7437                 }
7438         }
7439
7440         /* Setup the timeout in seconds. */
7441
7442         if (!lp_blocking_locks(SNUM(conn))) {
7443                 timeout = 0;
7444         }
7445
7446         /* Data now points at the beginning of the list
7447            of smb_lkrng structs */
7448
7449         for(i = 0; i < (int)num_locks; i++) {
7450                 struct smbd_lock_element *e = &locks[i];
7451
7452                 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7453                           "%llu, file %s timeout = %d\n",
7454                           (double)e->offset,
7455                           (double)e->count,
7456                           (unsigned long long)e->smblctx,
7457                           fsp_str_dbg(fsp),
7458                           (int)timeout));
7459
7460                 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7461                         struct blocking_lock_record *blr = NULL;
7462
7463                         if (num_locks > 1) {
7464                                 /*
7465                                  * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7466                                  * if the lock vector contains one entry. When given mutliple cancel
7467                                  * requests in a single PDU we expect the server to return an
7468                                  * error. Windows servers seem to accept the request but only
7469                                  * cancel the first lock.
7470                                  * JRA - Do what Windows does (tm) :-).
7471                                  */
7472
7473 #if 0
7474                                 /* MS-CIFS (2.2.4.32.1) behavior. */
7475                                 return NT_STATUS_DOS(ERRDOS,
7476                                                 ERRcancelviolation);
7477 #else
7478                                 /* Windows behavior. */
7479                                 if (i != 0) {
7480                                         DEBUG(10,("smbd_do_locking: ignoring subsequent "
7481                                                 "cancel request\n"));
7482                                         continue;
7483                                 }
7484 #endif
7485                         }
7486
7487                         if (lp_blocking_locks(SNUM(conn))) {
7488
7489                                 /* Schedule a message to ourselves to
7490                                    remove the blocking lock record and
7491                                    return the right error. */
7492
7493                                 blr = blocking_lock_cancel_smb1(fsp,
7494                                                 e->smblctx,
7495                                                 e->offset,
7496                                                 e->count,
7497                                                 WINDOWS_LOCK,
7498                                                 type,
7499                                                 NT_STATUS_FILE_LOCK_CONFLICT);
7500                                 if (blr == NULL) {
7501                                         return NT_STATUS_DOS(
7502                                                         ERRDOS,
7503                                                         ERRcancelviolation);
7504                                 }
7505                         }
7506                         /* Remove a matching pending lock. */
7507                         status = do_lock_cancel(fsp,
7508                                                 e->smblctx,
7509                                                 e->count,
7510                                                 e->offset,
7511                                                 WINDOWS_LOCK,
7512                                                 blr);
7513                 } else {
7514                         bool blocking_lock = timeout ? true : false;
7515                         bool defer_lock = false;
7516                         struct byte_range_lock *br_lck;
7517                         uint64_t block_smblctx;
7518
7519                         br_lck = do_lock(req->sconn->msg_ctx,
7520                                         fsp,
7521                                         e->smblctx,
7522                                         e->count,
7523                                         e->offset, 
7524                                         e->brltype,
7525                                         WINDOWS_LOCK,
7526                                         blocking_lock,
7527                                         &status,
7528                                         &block_smblctx,
7529                                         NULL);
7530
7531                         if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7532                                 /* Windows internal resolution for blocking locks seems
7533                                    to be about 200ms... Don't wait for less than that. JRA. */
7534                                 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7535                                         timeout = lp_lock_spin_time();
7536                                 }
7537                                 defer_lock = true;
7538                         }
7539
7540                         /* If a lock sent with timeout of zero would fail, and
7541                          * this lock has been requested multiple times,
7542                          * according to brl_lock_failed() we convert this
7543                          * request to a blocking lock with a timeout of between
7544                          * 150 - 300 milliseconds.
7545                          *
7546                          * If lp_lock_spin_time() has been set to 0, we skip
7547                          * this blocking retry and fail immediately.
7548                          *
7549                          * Replacement for do_lock_spin(). JRA. */
7550
7551                         if (!req->sconn->using_smb2 &&
7552                             br_lck && lp_blocking_locks(SNUM(conn)) &&
7553                             lp_lock_spin_time() && !blocking_lock &&
7554                             NT_STATUS_EQUAL((status),
7555                                 NT_STATUS_FILE_LOCK_CONFLICT))
7556                         {
7557                                 defer_lock = true;
7558                                 timeout = lp_lock_spin_time();
7559                         }
7560
7561                         if (br_lck && defer_lock) {
7562                                 /*
7563                                  * A blocking lock was requested. Package up
7564                                  * this smb into a queued request and push it
7565                                  * onto the blocking lock queue.
7566                                  */
7567                                 if(push_blocking_lock_request(br_lck,
7568                                                         req,
7569                                                         fsp,
7570                                                         timeout,
7571                                                         i,
7572                                                         e->smblctx,
7573                                                         e->brltype,
7574                                                         WINDOWS_LOCK,
7575                                                         e->offset,
7576                                                         e->count,
7577                                                         block_smblctx)) {
7578                                         TALLOC_FREE(br_lck);
7579                                         *async = true;
7580                                         return NT_STATUS_OK;
7581                                 }
7582                         }
7583
7584                         TALLOC_FREE(br_lck);
7585                 }
7586
7587                 if (!NT_STATUS_IS_OK(status)) {
7588                         break;
7589                 }
7590         }
7591
7592         /* If any of the above locks failed, then we must unlock
7593            all of the previous locks (X/Open spec). */
7594
7595         if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7596
7597                 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7598                         i = -1; /* we want to skip the for loop */
7599                 }
7600
7601                 /*
7602                  * Ensure we don't do a remove on the lock that just failed,
7603                  * as under POSIX rules, if we have a lock already there, we
7604                  * will delete it (and we shouldn't) .....
7605                  */
7606                 for(i--; i >= 0; i--) {
7607                         struct smbd_lock_element *e = &locks[i];
7608
7609                         do_unlock(req->sconn->msg_ctx,
7610                                 fsp,
7611                                 e->smblctx,
7612                                 e->count,
7613                                 e->offset,
7614                                 WINDOWS_LOCK);
7615                 }
7616                 return status;
7617         }
7618
7619         DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7620                   fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7621
7622         return NT_STATUS_OK;
7623 }
7624
7625 /****************************************************************************
7626  Reply to a lockingX request.
7627 ****************************************************************************/
7628
7629 void reply_lockingX(struct smb_request *req)
7630 {
7631         connection_struct *conn = req->conn;
7632         files_struct *fsp;
7633         unsigned char locktype;
7634         unsigned char oplocklevel;
7635         uint16 num_ulocks;
7636         uint16 num_locks;
7637         int32 lock_timeout;
7638         int i;
7639         const uint8_t *data;
7640         bool large_file_format;
7641         bool err;
7642         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7643         struct smbd_lock_element *ulocks;
7644         struct smbd_lock_element *locks;
7645         bool async = false;
7646
7647         START_PROFILE(SMBlockingX);
7648
7649         if (req->wct < 8) {
7650                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7651                 END_PROFILE(SMBlockingX);
7652                 return;
7653         }
7654
7655         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7656         locktype = CVAL(req->vwv+3, 0);
7657         oplocklevel = CVAL(req->vwv+3, 1);
7658         num_ulocks = SVAL(req->vwv+6, 0);
7659         num_locks = SVAL(req->vwv+7, 0);
7660         lock_timeout = IVAL(req->vwv+4, 0);
7661         large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7662
7663         if (!check_fsp(conn, req, fsp)) {
7664                 END_PROFILE(SMBlockingX);
7665                 return;
7666         }
7667
7668         data = req->buf;
7669
7670         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7671                 /* we don't support these - and CANCEL_LOCK makes w2k
7672                    and XP reboot so I don't really want to be
7673                    compatible! (tridge) */
7674                 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7675                 END_PROFILE(SMBlockingX);
7676                 return;
7677         }
7678
7679         /* Check if this is an oplock break on a file
7680            we have granted an oplock on.
7681         */
7682         if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7683                 /* Client can insist on breaking to none. */
7684                 bool break_to_none = (oplocklevel == 0);
7685                 bool result;
7686
7687                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7688                          "for fnum = %d\n", (unsigned int)oplocklevel,
7689                          fsp->fnum ));
7690
7691                 /*
7692                  * Make sure we have granted an exclusive or batch oplock on
7693                  * this file.
7694                  */
7695
7696                 if (fsp->oplock_type == 0) {
7697
7698                         /* The Samba4 nbench simulator doesn't understand
7699                            the difference between break to level2 and break
7700                            to none from level2 - it sends oplock break
7701                            replies in both cases. Don't keep logging an error
7702                            message here - just ignore it. JRA. */
7703
7704                         DEBUG(5,("reply_lockingX: Error : oplock break from "
7705                                  "client for fnum = %d (oplock=%d) and no "
7706                                  "oplock granted on this file (%s).\n",
7707                                  fsp->fnum, fsp->oplock_type,
7708                                  fsp_str_dbg(fsp)));
7709
7710                         /* if this is a pure oplock break request then don't
7711                          * send a reply */
7712                         if (num_locks == 0 && num_ulocks == 0) {
7713                                 END_PROFILE(SMBlockingX);
7714                                 return;
7715                         } else {
7716                                 END_PROFILE(SMBlockingX);
7717                                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7718                                 return;
7719                         }
7720                 }
7721
7722                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7723                     (break_to_none)) {
7724                         result = remove_oplock(fsp);
7725                 } else {
7726                         result = downgrade_oplock(fsp);
7727                 }
7728
7729                 if (!result) {
7730                         DEBUG(0, ("reply_lockingX: error in removing "
7731                                   "oplock on file %s\n", fsp_str_dbg(fsp)));
7732                         /* Hmmm. Is this panic justified? */
7733                         smb_panic("internal tdb error");
7734                 }
7735
7736                 reply_to_oplock_break_requests(fsp);
7737
7738                 /* if this is a pure oplock break request then don't send a
7739                  * reply */
7740                 if (num_locks == 0 && num_ulocks == 0) {
7741                         /* Sanity check - ensure a pure oplock break is not a
7742                            chained request. */
7743                         if(CVAL(req->vwv+0, 0) != 0xff)
7744                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
7745                                          "break is a chained %d request !\n",
7746                                          (unsigned int)CVAL(req->vwv+0, 0)));
7747                         END_PROFILE(SMBlockingX);
7748                         return;
7749                 }
7750         }
7751
7752         if (req->buflen <
7753             (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7754                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7755                 END_PROFILE(SMBlockingX);
7756                 return;
7757         }
7758
7759         ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7760         if (ulocks == NULL) {
7761                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7762                 END_PROFILE(SMBlockingX);
7763                 return;
7764         }
7765
7766         locks = talloc_array(req, struct smbd_lock_element, num_locks);
7767         if (locks == NULL) {
7768                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7769                 END_PROFILE(SMBlockingX);
7770                 return;
7771         }
7772
7773         /* Data now points at the beginning of the list
7774            of smb_unlkrng structs */
7775         for(i = 0; i < (int)num_ulocks; i++) {
7776                 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7777                 ulocks[i].count = get_lock_count(data, i, large_file_format);
7778                 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7779                 ulocks[i].brltype = UNLOCK_LOCK;
7780
7781                 /*
7782                  * There is no error code marked "stupid client bug".... :-).
7783                  */
7784                 if(err) {
7785                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7786                         END_PROFILE(SMBlockingX);
7787                         return;
7788                 }
7789         }
7790
7791         /* Now do any requested locks */
7792         data += ((large_file_format ? 20 : 10)*num_ulocks);
7793
7794         /* Data now points at the beginning of the list
7795            of smb_lkrng structs */
7796
7797         for(i = 0; i < (int)num_locks; i++) {
7798                 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7799                 locks[i].count = get_lock_count(data, i, large_file_format);
7800                 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7801
7802                 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7803                         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7804                                 locks[i].brltype = PENDING_READ_LOCK;
7805                         } else {
7806                                 locks[i].brltype = READ_LOCK;
7807                         }
7808                 } else {
7809                         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7810                                 locks[i].brltype = PENDING_WRITE_LOCK;
7811                         } else {
7812                                 locks[i].brltype = WRITE_LOCK;
7813                         }
7814                 }
7815
7816                 /*
7817                  * There is no error code marked "stupid client bug".... :-).
7818                  */
7819                 if(err) {
7820                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7821                         END_PROFILE(SMBlockingX);
7822                         return;
7823                 }
7824         }
7825
7826         status = smbd_do_locking(req, fsp,
7827                                  locktype, lock_timeout,
7828                                  num_ulocks, ulocks,
7829                                  num_locks, locks,
7830                                  &async);
7831         if (!NT_STATUS_IS_OK(status)) {
7832                 END_PROFILE(SMBlockingX);
7833                 reply_nterror(req, status);
7834                 return;
7835         }
7836         if (async) {
7837                 END_PROFILE(SMBlockingX);
7838                 return;
7839         }
7840
7841         reply_outbuf(req, 2, 0);
7842         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
7843         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
7844
7845         DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7846                   fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7847
7848         END_PROFILE(SMBlockingX);
7849 }
7850
7851 #undef DBGC_CLASS
7852 #define DBGC_CLASS DBGC_ALL
7853
7854 /****************************************************************************
7855  Reply to a SMBreadbmpx (read block multiplex) request.
7856  Always reply with an error, if someone has a platform really needs this,
7857  please contact vl@samba.org
7858 ****************************************************************************/
7859
7860 void reply_readbmpx(struct smb_request *req)
7861 {
7862         START_PROFILE(SMBreadBmpx);
7863         reply_force_doserror(req, ERRSRV, ERRuseSTD);
7864         END_PROFILE(SMBreadBmpx);
7865         return;
7866 }
7867
7868 /****************************************************************************
7869  Reply to a SMBreadbs (read block multiplex secondary) request.
7870  Always reply with an error, if someone has a platform really needs this,
7871  please contact vl@samba.org
7872 ****************************************************************************/
7873
7874 void reply_readbs(struct smb_request *req)
7875 {
7876         START_PROFILE(SMBreadBs);
7877         reply_force_doserror(req, ERRSRV, ERRuseSTD);
7878         END_PROFILE(SMBreadBs);
7879         return;
7880 }
7881
7882 /****************************************************************************
7883  Reply to a SMBsetattrE.
7884 ****************************************************************************/
7885
7886 void reply_setattrE(struct smb_request *req)
7887 {
7888         connection_struct *conn = req->conn;
7889         struct smb_file_time ft;
7890         files_struct *fsp;
7891         NTSTATUS status;
7892
7893         START_PROFILE(SMBsetattrE);
7894         ZERO_STRUCT(ft);
7895
7896         if (req->wct < 7) {
7897                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7898                 goto out;
7899         }
7900
7901         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7902
7903         if(!fsp || (fsp->conn != conn)) {
7904                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7905                 goto out;
7906         }
7907
7908         /*
7909          * Convert the DOS times into unix times.
7910          */
7911
7912         ft.atime = convert_time_t_to_timespec(
7913             srv_make_unix_date2(req->vwv+3));
7914         ft.mtime = convert_time_t_to_timespec(
7915             srv_make_unix_date2(req->vwv+5));
7916         ft.create_time = convert_time_t_to_timespec(
7917             srv_make_unix_date2(req->vwv+1));
7918
7919         reply_outbuf(req, 0, 0);
7920
7921         /* 
7922          * Patch from Ray Frush <frush@engr.colostate.edu>
7923          * Sometimes times are sent as zero - ignore them.
7924          */
7925
7926         /* Ensure we have a valid stat struct for the source. */
7927         status = vfs_stat_fsp(fsp);
7928         if (!NT_STATUS_IS_OK(status)) {
7929                 reply_nterror(req, status);
7930                 goto out;
7931         }
7932
7933         if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
7934                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7935                 goto out;
7936         }
7937
7938         status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7939         if (!NT_STATUS_IS_OK(status)) {
7940                 reply_nterror(req, status);
7941                 goto out;
7942         }
7943
7944         DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7945                " createtime=%u\n",
7946                 fsp->fnum,
7947                 (unsigned int)ft.atime.tv_sec,
7948                 (unsigned int)ft.mtime.tv_sec,
7949                 (unsigned int)ft.create_time.tv_sec
7950                 ));
7951  out:
7952         END_PROFILE(SMBsetattrE);
7953         return;
7954 }
7955
7956
7957 /* Back from the dead for OS/2..... JRA. */
7958
7959 /****************************************************************************
7960  Reply to a SMBwritebmpx (write block multiplex primary) request.
7961  Always reply with an error, if someone has a platform really needs this,
7962  please contact vl@samba.org
7963 ****************************************************************************/
7964
7965 void reply_writebmpx(struct smb_request *req)
7966 {
7967         START_PROFILE(SMBwriteBmpx);
7968         reply_force_doserror(req, ERRSRV, ERRuseSTD);
7969         END_PROFILE(SMBwriteBmpx);
7970         return;
7971 }
7972
7973 /****************************************************************************
7974  Reply to a SMBwritebs (write block multiplex secondary) request.
7975  Always reply with an error, if someone has a platform really needs this,
7976  please contact vl@samba.org
7977 ****************************************************************************/
7978
7979 void reply_writebs(struct smb_request *req)
7980 {
7981         START_PROFILE(SMBwriteBs);
7982         reply_force_doserror(req, ERRSRV, ERRuseSTD);
7983         END_PROFILE(SMBwriteBs);
7984         return;
7985 }
7986
7987 /****************************************************************************
7988  Reply to a SMBgetattrE.
7989 ****************************************************************************/
7990
7991 void reply_getattrE(struct smb_request *req)
7992 {
7993         connection_struct *conn = req->conn;
7994         int mode;
7995         files_struct *fsp;
7996         struct timespec create_ts;
7997
7998         START_PROFILE(SMBgetattrE);
7999
8000         if (req->wct < 1) {
8001                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8002                 END_PROFILE(SMBgetattrE);
8003                 return;
8004         }
8005
8006         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8007
8008         if(!fsp || (fsp->conn != conn)) {
8009                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8010                 END_PROFILE(SMBgetattrE);
8011                 return;
8012         }
8013
8014         /* Do an fstat on this file */
8015         if(fsp_stat(fsp)) {
8016                 reply_nterror(req, map_nt_error_from_unix(errno));
8017                 END_PROFILE(SMBgetattrE);
8018                 return;
8019         }
8020
8021         mode = dos_mode(conn, fsp->fsp_name);
8022
8023         /*
8024          * Convert the times into dos times. Set create
8025          * date to be last modify date as UNIX doesn't save
8026          * this.
8027          */
8028
8029         reply_outbuf(req, 11, 0);
8030
8031         create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8032         srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8033         srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8034                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8035         /* Should we check pending modtime here ? JRA */
8036         srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8037                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8038
8039         if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8040                 SIVAL(req->outbuf, smb_vwv6, 0);
8041                 SIVAL(req->outbuf, smb_vwv8, 0);
8042         } else {
8043                 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8044                 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
8045                 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8046         }
8047         SSVAL(req->outbuf,smb_vwv10, mode);
8048
8049         DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
8050
8051         END_PROFILE(SMBgetattrE);
8052         return;
8053 }