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