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