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