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