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