s3:smbd: move tcon specific globals to struct smbd_server_connection
[kai/samba.git] / source3 / smbd / reply.c
1 /*
2    Unix SMB/CIFS implementation.
3    Main SMB reply routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Andrew Bartlett      2001
6    Copyright (C) Jeremy Allison 1992-2007.
7    Copyright (C) Volker Lendecke 2007
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22 /*
23    This file handles most of the reply_ calls that the server
24    makes to handle specific protocols
25 */
26
27 #include "includes.h"
28 #include "smbd/globals.h"
29
30 extern enum protocol_types Protocol;
31
32 /****************************************************************************
33  Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
34  path or anything including wildcards.
35  We're assuming here that '/' is not the second byte in any multibyte char
36  set (a safe assumption). '\\' *may* be the second byte in a multibyte char
37  set.
38 ****************************************************************************/
39
40 /* Custom version for processing POSIX paths. */
41 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
42
43 static NTSTATUS check_path_syntax_internal(char *path,
44                                            bool posix_path,
45                                            bool *p_last_component_contains_wcard)
46 {
47         char *d = path;
48         const char *s = path;
49         NTSTATUS ret = NT_STATUS_OK;
50         bool start_of_name_component = True;
51         bool stream_started = false;
52
53         *p_last_component_contains_wcard = False;
54
55         while (*s) {
56                 if (stream_started) {
57                         switch (*s) {
58                         case '/':
59                         case '\\':
60                                 return NT_STATUS_OBJECT_NAME_INVALID;
61                         case ':':
62                                 if (s[1] == '\0') {
63                                         return NT_STATUS_OBJECT_NAME_INVALID;
64                                 }
65                                 if (strchr_m(&s[1], ':')) {
66                                         return NT_STATUS_OBJECT_NAME_INVALID;
67                                 }
68                                 if (StrCaseCmp(s, ":$DATA") != 0) {
69                                         return NT_STATUS_INVALID_PARAMETER;
70                                 }
71                                 break;
72                         }
73                 }
74
75                 if (!posix_path && !stream_started && *s == ':') {
76                         if (*p_last_component_contains_wcard) {
77                                 return NT_STATUS_OBJECT_NAME_INVALID;
78                         }
79                         /* Stream names allow more characters than file names.
80                            We're overloading posix_path here to allow a wider
81                            range of characters. If stream_started is true this
82                            is still a Windows path even if posix_path is true.
83                            JRA.
84                         */
85                         stream_started = true;
86                         start_of_name_component = false;
87                         posix_path = true;
88
89                         if (s[1] == '\0') {
90                                 return NT_STATUS_OBJECT_NAME_INVALID;
91                         }
92                 }
93
94                 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
95                         /*
96                          * Safe to assume is not the second part of a mb char
97                          * as this is handled below.
98                          */
99                         /* Eat multiple '/' or '\\' */
100                         while (IS_PATH_SEP(*s,posix_path)) {
101                                 s++;
102                         }
103                         if ((d != path) && (*s != '\0')) {
104                                 /* We only care about non-leading or trailing '/' or '\\' */
105                                 *d++ = '/';
106                         }
107
108                         start_of_name_component = True;
109                         /* New component. */
110                         *p_last_component_contains_wcard = False;
111                         continue;
112                 }
113
114                 if (start_of_name_component) {
115                         if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
116                                 /* Uh oh - "/../" or "\\..\\"  or "/..\0" or "\\..\0" ! */
117
118                                 /*
119                                  * No mb char starts with '.' so we're safe checking the directory separator here.
120                                  */
121
122                                 /* If  we just added a '/' - delete it */
123                                 if ((d > path) && (*(d-1) == '/')) {
124                                         *(d-1) = '\0';
125                                         d--;
126                                 }
127
128                                 /* Are we at the start ? Can't go back further if so. */
129                                 if (d <= path) {
130                                         ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
131                                         break;
132                                 }
133                                 /* Go back one level... */
134                                 /* We know this is safe as '/' cannot be part of a mb sequence. */
135                                 /* NOTE - if this assumption is invalid we are not in good shape... */
136                                 /* Decrement d first as d points to the *next* char to write into. */
137                                 for (d--; d > path; d--) {
138                                         if (*d == '/')
139                                                 break;
140                                 }
141                                 s += 2; /* Else go past the .. */
142                                 /* We're still at the start of a name component, just the previous one. */
143                                 continue;
144
145                         } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
146                                 if (posix_path) {
147                                         /* Eat the '.' */
148                                         s++;
149                                         continue;
150                                 }
151                         }
152
153                 }
154
155                 if (!(*s & 0x80)) {
156                         if (!posix_path) {
157                                 if (*s <= 0x1f || *s == '|') {
158                                         return NT_STATUS_OBJECT_NAME_INVALID;
159                                 }
160                                 switch (*s) {
161                                         case '*':
162                                         case '?':
163                                         case '<':
164                                         case '>':
165                                         case '"':
166                                                 *p_last_component_contains_wcard = True;
167                                                 break;
168                                         default:
169                                                 break;
170                                 }
171                         }
172                         *d++ = *s++;
173                 } else {
174                         size_t siz;
175                         /* Get the size of the next MB character. */
176                         next_codepoint(s,&siz);
177                         switch(siz) {
178                                 case 5:
179                                         *d++ = *s++;
180                                         /*fall through*/
181                                 case 4:
182                                         *d++ = *s++;
183                                         /*fall through*/
184                                 case 3:
185                                         *d++ = *s++;
186                                         /*fall through*/
187                                 case 2:
188                                         *d++ = *s++;
189                                         /*fall through*/
190                                 case 1:
191                                         *d++ = *s++;
192                                         break;
193                                 default:
194                                         DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
195                                         *d = '\0';
196                                         return NT_STATUS_INVALID_PARAMETER;
197                         }
198                 }
199                 start_of_name_component = False;
200         }
201
202         *d = '\0';
203
204         return ret;
205 }
206
207 /****************************************************************************
208  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
209  No wildcards allowed.
210 ****************************************************************************/
211
212 NTSTATUS check_path_syntax(char *path)
213 {
214         bool ignore;
215         return check_path_syntax_internal(path, False, &ignore);
216 }
217
218 /****************************************************************************
219  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
220  Wildcards allowed - p_contains_wcard returns true if the last component contained
221  a wildcard.
222 ****************************************************************************/
223
224 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
225 {
226         return check_path_syntax_internal(path, False, p_contains_wcard);
227 }
228
229 /****************************************************************************
230  Check the path for a POSIX client.
231  We're assuming here that '/' is not the second byte in any multibyte char
232  set (a safe assumption).
233 ****************************************************************************/
234
235 NTSTATUS check_path_syntax_posix(char *path)
236 {
237         bool ignore;
238         return check_path_syntax_internal(path, True, &ignore);
239 }
240
241 /****************************************************************************
242  Pull a string and check the path allowing a wilcard - provide for error return.
243 ****************************************************************************/
244
245 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
246                         const char *base_ptr,
247                         uint16 smb_flags2,
248                         char **pp_dest,
249                         const char *src,
250                         size_t src_len,
251                         int flags,
252                         NTSTATUS *err,
253                         bool *contains_wcard)
254 {
255         size_t ret;
256
257         *pp_dest = NULL;
258
259         ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
260                                  src_len, flags);
261
262         if (!*pp_dest) {
263                 *err = NT_STATUS_INVALID_PARAMETER;
264                 return ret;
265         }
266
267         *contains_wcard = False;
268
269         if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
270                 /*
271                  * For a DFS path the function parse_dfs_path()
272                  * will do the path processing, just make a copy.
273                  */
274                 *err = NT_STATUS_OK;
275                 return ret;
276         }
277
278         if (lp_posix_pathnames()) {
279                 *err = check_path_syntax_posix(*pp_dest);
280         } else {
281                 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
282         }
283
284         return ret;
285 }
286
287 /****************************************************************************
288  Pull a string and check the path - provide for error return.
289 ****************************************************************************/
290
291 size_t srvstr_get_path(TALLOC_CTX *ctx,
292                         const char *base_ptr,
293                         uint16 smb_flags2,
294                         char **pp_dest,
295                         const char *src,
296                         size_t src_len,
297                         int flags,
298                         NTSTATUS *err)
299 {
300         bool ignore;
301         return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
302                                      src_len, flags, err, &ignore);
303 }
304
305 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
306                                  char **pp_dest, const char *src, int flags,
307                                  NTSTATUS *err, bool *contains_wcard)
308 {
309         return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
310                                      pp_dest, src, smbreq_bufrem(req, src),
311                                      flags, err, contains_wcard);
312 }
313
314 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
315                            char **pp_dest, const char *src, int flags,
316                            NTSTATUS *err)
317 {
318         bool ignore;
319         return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
320                                          flags, err, &ignore);
321 }
322
323 /****************************************************************************
324  Check if we have a correct fsp pointing to a file. Basic check for open fsp.
325 ****************************************************************************/
326
327 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
328                     files_struct *fsp)
329 {
330         if (!(fsp) || !(conn)) {
331                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
332                 return False;
333         }
334         if (((conn) != (fsp)->conn) || req->vuid != (fsp)->vuid) {
335                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
336                 return False;
337         }
338         return True;
339 }
340
341 /****************************************************************************
342  Check if we have a correct fsp pointing to a file.
343 ****************************************************************************/
344
345 bool check_fsp(connection_struct *conn, struct smb_request *req,
346                files_struct *fsp)
347 {
348         if (!check_fsp_open(conn, req, fsp)) {
349                 return False;
350         }
351         if ((fsp)->is_directory) {
352                 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
353                 return False;
354         }
355         if ((fsp)->fh->fd == -1) {
356                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
357                 return False;
358         }
359         (fsp)->num_smb_operations++;
360         return True;
361 }
362
363 /****************************************************************************
364  Check if we have a correct fsp pointing to a quota fake file. Replacement for
365  the CHECK_NTQUOTA_HANDLE_OK macro.
366 ****************************************************************************/
367
368 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
369                               files_struct *fsp)
370 {
371         if (!check_fsp_open(conn, req, fsp)) {
372                 return false;
373         }
374
375         if (fsp->is_directory) {
376                 return false;
377         }
378
379         if (fsp->fake_file_handle == NULL) {
380                 return false;
381         }
382
383         if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
384                 return false;
385         }
386
387         if (fsp->fake_file_handle->private_data == NULL) {
388                 return false;
389         }
390
391         return true;
392 }
393
394 /****************************************************************************
395  Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
396 ****************************************************************************/
397
398 bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
399                       files_struct *fsp)
400 {
401         if ((fsp) && (conn) && ((conn)==(fsp)->conn)
402             && (req->vuid == (fsp)->vuid)) {
403                 return True;
404         }
405
406         reply_nterror(req, NT_STATUS_INVALID_HANDLE);
407         return False;
408 }
409
410 static bool netbios_session_retarget(const char *name, int name_type)
411 {
412         char *trim_name;
413         char *trim_name_type;
414         const char *retarget_parm;
415         char *retarget;
416         char *p;
417         int retarget_type = 0x20;
418         int retarget_port = 139;
419         struct sockaddr_storage retarget_addr;
420         struct sockaddr_in *in_addr;
421         bool ret = false;
422         uint8_t outbuf[10];
423
424         if (get_socket_port(smbd_server_fd()) != 139) {
425                 return false;
426         }
427
428         trim_name = talloc_strdup(talloc_tos(), name);
429         if (trim_name == NULL) {
430                 goto fail;
431         }
432         trim_char(trim_name, ' ', ' ');
433
434         trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
435                                          name_type);
436         if (trim_name_type == NULL) {
437                 goto fail;
438         }
439
440         retarget_parm = lp_parm_const_string(-1, "netbios retarget",
441                                              trim_name_type, NULL);
442         if (retarget_parm == NULL) {
443                 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
444                                                      trim_name, NULL);
445         }
446         if (retarget_parm == NULL) {
447                 goto fail;
448         }
449
450         retarget = talloc_strdup(trim_name, retarget_parm);
451         if (retarget == NULL) {
452                 goto fail;
453         }
454
455         DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
456
457         p = strchr(retarget, ':');
458         if (p != NULL) {
459                 *p++ = '\0';
460                 retarget_port = atoi(p);
461         }
462
463         p = strchr_m(retarget, '#');
464         if (p != NULL) {
465                 *p++ = '\0';
466                 sscanf(p, "%x", &retarget_type);
467         }
468
469         ret = resolve_name(retarget, &retarget_addr, retarget_type);
470         if (!ret) {
471                 DEBUG(10, ("could not resolve %s\n", retarget));
472                 goto fail;
473         }
474
475         if (retarget_addr.ss_family != AF_INET) {
476                 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
477                 goto fail;
478         }
479
480         in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
481
482         _smb_setlen(outbuf, 6);
483         SCVAL(outbuf, 0, 0x84);
484         *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
485         *(uint16_t *)(outbuf+8) = htons(retarget_port);
486
487         if (!srv_send_smb(smbd_server_fd(), (char *)outbuf, false, 0, false,
488                           NULL)) {
489                 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
490                                     "failed.");
491         }
492
493         ret = true;
494  fail:
495         TALLOC_FREE(trim_name);
496         return ret;
497 }
498
499 /****************************************************************************
500  Reply to a (netbios-level) special message.
501 ****************************************************************************/
502
503 void reply_special(char *inbuf)
504 {
505         int msg_type = CVAL(inbuf,0);
506         int msg_flags = CVAL(inbuf,1);
507         fstring name1,name2;
508         char name_type1, name_type2;
509         struct smbd_server_connection *sconn = smbd_server_conn;
510
511         /*
512          * We only really use 4 bytes of the outbuf, but for the smb_setlen
513          * calculation & friends (srv_send_smb uses that) we need the full smb
514          * header.
515          */
516         char outbuf[smb_size];
517
518         *name1 = *name2 = 0;
519
520         memset(outbuf, '\0', sizeof(outbuf));
521
522         smb_setlen(outbuf,0);
523
524         switch (msg_type) {
525         case 0x81: /* session request */
526
527                 if (sconn->nbt.got_session) {
528                         exit_server_cleanly("multiple session request not permitted");
529                 }
530
531                 SCVAL(outbuf,0,0x82);
532                 SCVAL(outbuf,3,0);
533                 if (name_len(inbuf+4) > 50 || 
534                     name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
535                         DEBUG(0,("Invalid name length in session request\n"));
536                         return;
537                 }
538                 name_type1 = name_extract(inbuf,4,name1);
539                 name_type2 = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
540                 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
541                          name1, name_type1, name2, name_type2));
542
543                 if (netbios_session_retarget(name1, name_type1)) {
544                         exit_server_cleanly("retargeted client");
545                 }
546
547                 set_local_machine_name(name1, True);
548                 set_remote_machine_name(name2, True);
549
550                 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
551                          get_local_machine_name(), get_remote_machine_name(),
552                          name_type2));
553
554                 if (name_type2 == 'R') {
555                         /* We are being asked for a pathworks session --- 
556                            no thanks! */
557                         SCVAL(outbuf, 0,0x83);
558                         break;
559                 }
560
561                 /* only add the client's machine name to the list
562                    of possibly valid usernames if we are operating
563                    in share mode security */
564                 if (lp_security() == SEC_SHARE) {
565                         add_session_user(sconn, get_remote_machine_name());
566                 }
567
568                 reload_services(True);
569                 reopen_logs();
570
571                 sconn->nbt.got_session = true;
572                 break;
573
574         case 0x89: /* session keepalive request 
575                       (some old clients produce this?) */
576                 SCVAL(outbuf,0,SMBkeepalive);
577                 SCVAL(outbuf,3,0);
578                 break;
579
580         case 0x82: /* positive session response */
581         case 0x83: /* negative session response */
582         case 0x84: /* retarget session response */
583                 DEBUG(0,("Unexpected session response\n"));
584                 break;
585
586         case SMBkeepalive: /* session keepalive */
587         default:
588                 return;
589         }
590
591         DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
592                     msg_type, msg_flags));
593
594         srv_send_smb(smbd_server_fd(), outbuf, false, 0, false, NULL);
595         return;
596 }
597
598 /****************************************************************************
599  Reply to a tcon.
600  conn POINTER CAN BE NULL HERE !
601 ****************************************************************************/
602
603 void reply_tcon(struct smb_request *req)
604 {
605         connection_struct *conn = req->conn;
606         const char *service;
607         char *service_buf = NULL;
608         char *password = NULL;
609         char *dev = NULL;
610         int pwlen=0;
611         NTSTATUS nt_status;
612         const char *p;
613         DATA_BLOB password_blob;
614         TALLOC_CTX *ctx = talloc_tos();
615         struct smbd_server_connection *sconn = smbd_server_conn;
616
617         START_PROFILE(SMBtcon);
618
619         if (req->buflen < 4) {
620                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
621                 END_PROFILE(SMBtcon);
622                 return;
623         }
624
625         p = (const char *)req->buf + 1;
626         p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
627         p += 1;
628         pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
629         p += pwlen+1;
630         p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
631         p += 1;
632
633         if (service_buf == NULL || password == NULL || dev == NULL) {
634                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
635                 END_PROFILE(SMBtcon);
636                 return;
637         }
638         p = strrchr_m(service_buf,'\\');
639         if (p) {
640                 service = p+1;
641         } else {
642                 service = service_buf;
643         }
644
645         password_blob = data_blob(password, pwlen+1);
646
647         conn = make_connection(sconn,service,password_blob,dev,
648                                req->vuid,&nt_status);
649         req->conn = conn;
650
651         data_blob_clear_free(&password_blob);
652
653         if (!conn) {
654                 reply_nterror(req, nt_status);
655                 END_PROFILE(SMBtcon);
656                 return;
657         }
658
659         reply_outbuf(req, 2, 0);
660         SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
661         SSVAL(req->outbuf,smb_vwv1,conn->cnum);
662         SSVAL(req->outbuf,smb_tid,conn->cnum);
663
664         DEBUG(3,("tcon service=%s cnum=%d\n",
665                  service, conn->cnum));
666
667         END_PROFILE(SMBtcon);
668         return;
669 }
670
671 /****************************************************************************
672  Reply to a tcon and X.
673  conn POINTER CAN BE NULL HERE !
674 ****************************************************************************/
675
676 void reply_tcon_and_X(struct smb_request *req)
677 {
678         connection_struct *conn = req->conn;
679         const char *service = NULL;
680         DATA_BLOB password;
681         TALLOC_CTX *ctx = talloc_tos();
682         /* what the cleint thinks the device is */
683         char *client_devicetype = NULL;
684         /* what the server tells the client the share represents */
685         const char *server_devicetype;
686         NTSTATUS nt_status;
687         int passlen;
688         char *path = NULL;
689         const char *p, *q;
690         uint16 tcon_flags;
691         struct smbd_server_connection *sconn = smbd_server_conn;
692
693         START_PROFILE(SMBtconX);
694
695         if (req->wct < 4) {
696                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
697                 END_PROFILE(SMBtconX);
698                 return;
699         }
700
701         passlen = SVAL(req->vwv+3, 0);
702         tcon_flags = SVAL(req->vwv+2, 0);
703
704         /* we might have to close an old one */
705         if ((tcon_flags & 0x1) && conn) {
706                 close_cnum(sconn, conn,req->vuid);
707                 req->conn = NULL;
708                 conn = NULL;
709         }
710
711         if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
712                 reply_doserror(req, ERRDOS, ERRbuftoosmall);
713                 END_PROFILE(SMBtconX);
714                 return;
715         }
716
717         if (sconn->smb1.negprot.encrypted_passwords) {
718                 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
719                 if (lp_security() == SEC_SHARE) {
720                         /*
721                          * Security = share always has a pad byte
722                          * after the password.
723                          */
724                         p = (const char *)req->buf + passlen + 1;
725                 } else {
726                         p = (const char *)req->buf + passlen;
727                 }
728         } else {
729                 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
730                 /* Ensure correct termination */
731                 password.data[passlen]=0;
732                 p = (const char *)req->buf + passlen + 1;
733         }
734
735         p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
736
737         if (path == NULL) {
738                 data_blob_clear_free(&password);
739                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
740                 END_PROFILE(SMBtconX);
741                 return;
742         }
743
744         /*
745          * the service name can be either: \\server\share
746          * or share directly like on the DELL PowerVault 705
747          */
748         if (*path=='\\') {
749                 q = strchr_m(path+2,'\\');
750                 if (!q) {
751                         data_blob_clear_free(&password);
752                         reply_doserror(req, ERRDOS, ERRnosuchshare);
753                         END_PROFILE(SMBtconX);
754                         return;
755                 }
756                 service = q+1;
757         } else {
758                 service = path;
759         }
760
761         p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
762                                 &client_devicetype, p,
763                                 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
764
765         if (client_devicetype == NULL) {
766                 data_blob_clear_free(&password);
767                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
768                 END_PROFILE(SMBtconX);
769                 return;
770         }
771
772         DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
773
774         conn = make_connection(sconn, service, password, client_devicetype,
775                                req->vuid, &nt_status);
776         req->conn =conn;
777
778         data_blob_clear_free(&password);
779
780         if (!conn) {
781                 reply_nterror(req, nt_status);
782                 END_PROFILE(SMBtconX);
783                 return;
784         }
785
786         if ( IS_IPC(conn) )
787                 server_devicetype = "IPC";
788         else if ( IS_PRINT(conn) )
789                 server_devicetype = "LPT1:";
790         else
791                 server_devicetype = "A:";
792
793         if (Protocol < PROTOCOL_NT1) {
794                 reply_outbuf(req, 2, 0);
795                 if (message_push_string(&req->outbuf, server_devicetype,
796                                         STR_TERMINATE|STR_ASCII) == -1) {
797                         reply_nterror(req, NT_STATUS_NO_MEMORY);
798                         END_PROFILE(SMBtconX);
799                         return;
800                 }
801         } else {
802                 /* NT sets the fstype of IPC$ to the null string */
803                 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
804
805                 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
806                         /* Return permissions. */
807                         uint32 perm1 = 0;
808                         uint32 perm2 = 0;
809
810                         reply_outbuf(req, 7, 0);
811
812                         if (IS_IPC(conn)) {
813                                 perm1 = FILE_ALL_ACCESS;
814                                 perm2 = FILE_ALL_ACCESS;
815                         } else {
816                                 perm1 = CAN_WRITE(conn) ?
817                                                 SHARE_ALL_ACCESS :
818                                                 SHARE_READ_ONLY;
819                         }
820
821                         SIVAL(req->outbuf, smb_vwv3, perm1);
822                         SIVAL(req->outbuf, smb_vwv5, perm2);
823                 } else {
824                         reply_outbuf(req, 3, 0);
825                 }
826
827                 if ((message_push_string(&req->outbuf, server_devicetype,
828                                          STR_TERMINATE|STR_ASCII) == -1)
829                     || (message_push_string(&req->outbuf, fstype,
830                                             STR_TERMINATE) == -1)) {
831                         reply_nterror(req, NT_STATUS_NO_MEMORY);
832                         END_PROFILE(SMBtconX);
833                         return;
834                 }
835
836                 /* what does setting this bit do? It is set by NT4 and
837                    may affect the ability to autorun mounted cdroms */
838                 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
839                       (lp_csc_policy(SNUM(conn)) << 2));
840
841                 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
842                         DEBUG(2,("Serving %s as a Dfs root\n",
843                                  lp_servicename(SNUM(conn)) ));
844                         SSVAL(req->outbuf, smb_vwv2,
845                               SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
846                 }
847         }
848
849
850         DEBUG(3,("tconX service=%s \n",
851                  service));
852
853         /* set the incoming and outgoing tid to the just created one */
854         SSVAL(req->inbuf,smb_tid,conn->cnum);
855         SSVAL(req->outbuf,smb_tid,conn->cnum);
856
857         END_PROFILE(SMBtconX);
858
859         chain_reply(req);
860         return;
861 }
862
863 /****************************************************************************
864  Reply to an unknown type.
865 ****************************************************************************/
866
867 void reply_unknown_new(struct smb_request *req, uint8 type)
868 {
869         DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
870                   smb_fn_name(type), type, type));
871         reply_doserror(req, ERRSRV, ERRunknownsmb);
872         return;
873 }
874
875 /****************************************************************************
876  Reply to an ioctl.
877  conn POINTER CAN BE NULL HERE !
878 ****************************************************************************/
879
880 void reply_ioctl(struct smb_request *req)
881 {
882         connection_struct *conn = req->conn;
883         uint16 device;
884         uint16 function;
885         uint32 ioctl_code;
886         int replysize;
887         char *p;
888
889         START_PROFILE(SMBioctl);
890
891         if (req->wct < 3) {
892                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
893                 END_PROFILE(SMBioctl);
894                 return;
895         }
896
897         device     = SVAL(req->vwv+1, 0);
898         function   = SVAL(req->vwv+2, 0);
899         ioctl_code = (device << 16) + function;
900
901         DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
902
903         switch (ioctl_code) {
904             case IOCTL_QUERY_JOB_INFO:
905                     replysize = 32;
906                     break;
907             default:
908                     reply_doserror(req, ERRSRV, ERRnosupport);
909                     END_PROFILE(SMBioctl);
910                     return;
911         }
912
913         reply_outbuf(req, 8, replysize+1);
914         SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
915         SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
916         SSVAL(req->outbuf,smb_vwv6,52);        /* Offset to data */
917         p = smb_buf(req->outbuf);
918         memset(p, '\0', replysize+1); /* valgrind-safe. */
919         p += 1;          /* Allow for alignment */
920
921         switch (ioctl_code) {
922                 case IOCTL_QUERY_JOB_INFO:                  
923                 {
924                         files_struct *fsp = file_fsp(
925                                 req, SVAL(req->vwv+0, 0));
926                         if (!fsp) {
927                                 reply_doserror(req, ERRDOS, ERRbadfid);
928                                 END_PROFILE(SMBioctl);
929                                 return;
930                         }
931                         SSVAL(p,0,fsp->rap_print_jobid);             /* Job number */
932                         srvstr_push((char *)req->outbuf, req->flags2, p+2,
933                                     global_myname(), 15,
934                                     STR_TERMINATE|STR_ASCII);
935                         if (conn) {
936                                 srvstr_push((char *)req->outbuf, req->flags2,
937                                             p+18, lp_servicename(SNUM(conn)),
938                                             13, STR_TERMINATE|STR_ASCII);
939                         } else {
940                                 memset(p+18, 0, 13);
941                         }
942                         break;
943                 }
944         }
945
946         END_PROFILE(SMBioctl);
947         return;
948 }
949
950 /****************************************************************************
951  Strange checkpath NTSTATUS mapping.
952 ****************************************************************************/
953
954 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
955 {
956         /* Strange DOS error code semantics only for checkpath... */
957         if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
958                 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
959                         /* We need to map to ERRbadpath */
960                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
961                 }
962         }
963         return status;
964 }
965
966 /****************************************************************************
967  Reply to a checkpath.
968 ****************************************************************************/
969
970 void reply_checkpath(struct smb_request *req)
971 {
972         connection_struct *conn = req->conn;
973         struct smb_filename *smb_fname = NULL;
974         char *name = NULL;
975         NTSTATUS status;
976         TALLOC_CTX *ctx = talloc_tos();
977
978         START_PROFILE(SMBcheckpath);
979
980         srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
981                             STR_TERMINATE, &status);
982
983         if (!NT_STATUS_IS_OK(status)) {
984                 status = map_checkpath_error(req->flags2, status);
985                 reply_nterror(req, status);
986                 END_PROFILE(SMBcheckpath);
987                 return;
988         }
989
990         status = resolve_dfspath(ctx, conn,
991                         req->flags2 & FLAGS2_DFS_PATHNAMES,
992                         name,
993                         &name);
994         if (!NT_STATUS_IS_OK(status)) {
995                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
996                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
997                                         ERRSRV, ERRbadpath);
998                         END_PROFILE(SMBcheckpath);
999                         return;
1000                 }
1001                 goto path_err;
1002         }
1003
1004         DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1005
1006         status = unix_convert(ctx, conn, name, &smb_fname, 0);
1007         if (!NT_STATUS_IS_OK(status)) {
1008                 goto path_err;
1009         }
1010
1011         status = get_full_smb_filename(ctx, smb_fname, &name);
1012         if (!NT_STATUS_IS_OK(status)) {
1013                 goto path_err;
1014         }
1015
1016         status = check_name(conn, name);
1017         if (!NT_STATUS_IS_OK(status)) {
1018                 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
1019                 goto path_err;
1020         }
1021
1022         if (!VALID_STAT(smb_fname->st) &&
1023             (SMB_VFS_STAT(conn, name, &smb_fname->st) != 0)) {
1024                 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
1025                 status = map_nt_error_from_unix(errno);
1026                 goto path_err;
1027         }
1028
1029         if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1030                 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1031                                 ERRDOS, ERRbadpath);
1032                 goto out;
1033         }
1034
1035         reply_outbuf(req, 0, 0);
1036  out:
1037         TALLOC_FREE(smb_fname);
1038         END_PROFILE(SMBcheckpath);
1039         return;
1040
1041  path_err:
1042
1043         TALLOC_FREE(smb_fname);
1044
1045         END_PROFILE(SMBcheckpath);
1046
1047         /* We special case this - as when a Windows machine
1048                 is parsing a path is steps through the components
1049                 one at a time - if a component fails it expects
1050                 ERRbadpath, not ERRbadfile.
1051         */
1052         status = map_checkpath_error(req->flags2, status);
1053         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1054                 /*
1055                  * Windows returns different error codes if
1056                  * the parent directory is valid but not the
1057                  * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1058                  * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1059                  * if the path is invalid.
1060                  */
1061                 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1062                                 ERRDOS, ERRbadpath);
1063                 return;
1064         }
1065
1066         reply_nterror(req, status);
1067 }
1068
1069 /****************************************************************************
1070  Reply to a getatr.
1071 ****************************************************************************/
1072
1073 void reply_getatr(struct smb_request *req)
1074 {
1075         connection_struct *conn = req->conn;
1076         struct smb_filename *smb_fname = NULL;
1077         char *fname = NULL;
1078         int mode=0;
1079         SMB_OFF_T size=0;
1080         time_t mtime=0;
1081         const char *p;
1082         NTSTATUS status;
1083         TALLOC_CTX *ctx = talloc_tos();
1084
1085         START_PROFILE(SMBgetatr);
1086
1087         p = (const char *)req->buf + 1;
1088         p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1089         if (!NT_STATUS_IS_OK(status)) {
1090                 reply_nterror(req, status);
1091                 goto out;
1092         }
1093
1094         status = resolve_dfspath(ctx, conn,
1095                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
1096                                 fname,
1097                                 &fname);
1098         if (!NT_STATUS_IS_OK(status)) {
1099                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1100                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1101                                         ERRSRV, ERRbadpath);
1102                         goto out;
1103                 }
1104                 reply_nterror(req, status);
1105                 goto out;
1106         }
1107
1108         /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1109                 under WfWg - weird! */
1110         if (*fname == '\0') {
1111                 mode = aHIDDEN | aDIR;
1112                 if (!CAN_WRITE(conn)) {
1113                         mode |= aRONLY;
1114                 }
1115                 size = 0;
1116                 mtime = 0;
1117         } else {
1118                 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
1119                 if (!NT_STATUS_IS_OK(status)) {
1120                         reply_nterror(req, status);
1121                         goto out;
1122                 }
1123                 status = get_full_smb_filename(ctx, smb_fname, &fname);
1124                 if (!NT_STATUS_IS_OK(status)) {
1125                         reply_nterror(req, status);
1126                         goto out;
1127                 }
1128                 status = check_name(conn, fname);
1129                 if (!NT_STATUS_IS_OK(status)) {
1130                         DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
1131                         reply_nterror(req, status);
1132                         goto out;
1133                 }
1134                 if (!VALID_STAT(smb_fname->st) &&
1135                     (SMB_VFS_STAT(conn, fname, &smb_fname->st) != 0)) {
1136                         DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
1137                         reply_unixerror(req, ERRDOS,ERRbadfile);
1138                         goto out;
1139                 }
1140
1141                 mode = dos_mode(conn, fname, &smb_fname->st);
1142                 size = smb_fname->st.st_ex_size;
1143                 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1144                 if (mode & aDIR) {
1145                         size = 0;
1146                 }
1147         }
1148
1149         reply_outbuf(req, 10, 0);
1150
1151         SSVAL(req->outbuf,smb_vwv0,mode);
1152         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1153                 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1154         } else {
1155                 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1156         }
1157         SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1158
1159         if (Protocol >= PROTOCOL_NT1) {
1160                 SSVAL(req->outbuf, smb_flg2,
1161                       SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1162         }
1163
1164         DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
1165
1166  out:
1167         TALLOC_FREE(smb_fname);
1168         END_PROFILE(SMBgetatr);
1169         return;
1170 }
1171
1172 /****************************************************************************
1173  Reply to a setatr.
1174 ****************************************************************************/
1175
1176 void reply_setatr(struct smb_request *req)
1177 {
1178         struct smb_file_time ft;
1179         connection_struct *conn = req->conn;
1180         struct smb_filename *smb_fname = NULL;
1181         char *fname = NULL;
1182         int mode;
1183         time_t mtime;
1184         const char *p;
1185         NTSTATUS status;
1186         TALLOC_CTX *ctx = talloc_tos();
1187
1188         START_PROFILE(SMBsetatr);
1189
1190         ZERO_STRUCT(ft);
1191
1192         if (req->wct < 2) {
1193                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1194                 goto out;
1195         }
1196
1197         p = (const char *)req->buf + 1;
1198         p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1199         if (!NT_STATUS_IS_OK(status)) {
1200                 reply_nterror(req, status);
1201                 goto out;
1202         }
1203
1204         status = resolve_dfspath(ctx, conn,
1205                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
1206                                 fname,
1207                                 &fname);
1208         if (!NT_STATUS_IS_OK(status)) {
1209                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1210                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1211                                         ERRSRV, ERRbadpath);
1212                         goto out;
1213                 }
1214                 reply_nterror(req, status);
1215                 goto out;
1216         }
1217
1218         status = unix_convert(ctx, conn, fname, &smb_fname, 0);
1219         if (!NT_STATUS_IS_OK(status)) {
1220                 reply_nterror(req, status);
1221                 goto out;
1222         }
1223
1224         status = get_full_smb_filename(ctx, smb_fname, &fname);
1225         if (!NT_STATUS_IS_OK(status)) {
1226                 reply_nterror(req, status);
1227                 goto out;
1228         }
1229
1230         status = check_name(conn, fname);
1231         if (!NT_STATUS_IS_OK(status)) {
1232                 reply_nterror(req, status);
1233                 goto out;
1234         }
1235
1236         if (fname[0] == '.' && fname[1] == '\0') {
1237                 /*
1238                  * Not sure here is the right place to catch this
1239                  * condition. Might be moved to somewhere else later -- vl
1240                  */
1241                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1242                 goto out;
1243         }
1244
1245         mode = SVAL(req->vwv+0, 0);
1246         mtime = srv_make_unix_date3(req->vwv+1);
1247
1248         ft.mtime = convert_time_t_to_timespec(mtime);
1249         status = smb_set_file_time(conn, NULL, fname,
1250                                    &smb_fname->st, &ft, true);
1251         if (!NT_STATUS_IS_OK(status)) {
1252                 reply_unixerror(req, ERRDOS, ERRnoaccess);
1253                 goto out;
1254         }
1255
1256         if (mode != FILE_ATTRIBUTE_NORMAL) {
1257                 if (VALID_STAT_OF_DIR(smb_fname->st))
1258                         mode |= aDIR;
1259                 else
1260                         mode &= ~aDIR;
1261
1262                 if (file_set_dosmode(conn, fname, mode, &smb_fname->st, NULL,
1263                                      false) != 0) {
1264                         reply_unixerror(req, ERRDOS, ERRnoaccess);
1265                         goto out;
1266                 }
1267         }
1268
1269         reply_outbuf(req, 0, 0);
1270
1271         DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1272  out:
1273         TALLOC_FREE(smb_fname);
1274         END_PROFILE(SMBsetatr);
1275         return;
1276 }
1277
1278 /****************************************************************************
1279  Reply to a dskattr.
1280 ****************************************************************************/
1281
1282 void reply_dskattr(struct smb_request *req)
1283 {
1284         connection_struct *conn = req->conn;
1285         uint64_t dfree,dsize,bsize;
1286         START_PROFILE(SMBdskattr);
1287
1288         if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1289                 reply_unixerror(req, ERRHRD, ERRgeneral);
1290                 END_PROFILE(SMBdskattr);
1291                 return;
1292         }
1293
1294         reply_outbuf(req, 5, 0);
1295
1296         if (Protocol <= PROTOCOL_LANMAN2) {
1297                 double total_space, free_space;
1298                 /* we need to scale this to a number that DOS6 can handle. We
1299                    use floating point so we can handle large drives on systems
1300                    that don't have 64 bit integers 
1301
1302                    we end up displaying a maximum of 2G to DOS systems
1303                 */
1304                 total_space = dsize * (double)bsize;
1305                 free_space = dfree * (double)bsize;
1306
1307                 dsize = (uint64_t)((total_space+63*512) / (64*512));
1308                 dfree = (uint64_t)((free_space+63*512) / (64*512));
1309
1310                 if (dsize > 0xFFFF) dsize = 0xFFFF;
1311                 if (dfree > 0xFFFF) dfree = 0xFFFF;
1312
1313                 SSVAL(req->outbuf,smb_vwv0,dsize);
1314                 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1315                 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1316                 SSVAL(req->outbuf,smb_vwv3,dfree);
1317         } else {
1318                 SSVAL(req->outbuf,smb_vwv0,dsize);
1319                 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1320                 SSVAL(req->outbuf,smb_vwv2,512);
1321                 SSVAL(req->outbuf,smb_vwv3,dfree);
1322         }
1323
1324         DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1325
1326         END_PROFILE(SMBdskattr);
1327         return;
1328 }
1329
1330 /****************************************************************************
1331  Reply to a search.
1332  Can be called from SMBsearch, SMBffirst or SMBfunique.
1333 ****************************************************************************/
1334
1335 void reply_search(struct smb_request *req)
1336 {
1337         connection_struct *conn = req->conn;
1338         const char *mask = NULL;
1339         char *directory = NULL;
1340         char *fname = NULL;
1341         SMB_OFF_T size;
1342         uint32 mode;
1343         struct timespec date;
1344         uint32 dirtype;
1345         unsigned int numentries = 0;
1346         unsigned int maxentries = 0;
1347         bool finished = False;
1348         const char *p;
1349         int status_len;
1350         char *path = NULL;
1351         char status[21];
1352         int dptr_num= -1;
1353         bool check_descend = False;
1354         bool expect_close = False;
1355         NTSTATUS nt_status;
1356         bool mask_contains_wcard = False;
1357         bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1358         TALLOC_CTX *ctx = talloc_tos();
1359         bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1360
1361         START_PROFILE(SMBsearch);
1362
1363         if (req->wct < 2) {
1364                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1365                 END_PROFILE(SMBsearch);
1366                 return;
1367         }
1368
1369         if (lp_posix_pathnames()) {
1370                 reply_unknown_new(req, req->cmd);
1371                 END_PROFILE(SMBsearch);
1372                 return;
1373         }
1374
1375         /* If we were called as SMBffirst then we must expect close. */
1376         if(req->cmd == SMBffirst) {
1377                 expect_close = True;
1378         }
1379
1380         reply_outbuf(req, 1, 3);
1381         maxentries = SVAL(req->vwv+0, 0);
1382         dirtype = SVAL(req->vwv+1, 0);
1383         p = (const char *)req->buf + 1;
1384         p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1385                                        &nt_status, &mask_contains_wcard);
1386         if (!NT_STATUS_IS_OK(nt_status)) {
1387                 reply_nterror(req, nt_status);
1388                 END_PROFILE(SMBsearch);
1389                 return;
1390         }
1391
1392         nt_status = resolve_dfspath_wcard(ctx, conn,
1393                                           req->flags2 & FLAGS2_DFS_PATHNAMES,
1394                                           path,
1395                                           &path,
1396                                           &mask_contains_wcard);
1397         if (!NT_STATUS_IS_OK(nt_status)) {
1398                 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1399                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1400                                         ERRSRV, ERRbadpath);
1401                         END_PROFILE(SMBsearch);
1402                         return;
1403                 }
1404                 reply_nterror(req, nt_status);
1405                 END_PROFILE(SMBsearch);
1406                 return;
1407         }
1408
1409         p++;
1410         status_len = SVAL(p, 0);
1411         p += 2;
1412
1413         /* dirtype &= ~aDIR; */
1414
1415         if (status_len == 0) {
1416                 struct smb_filename *smb_fname = NULL;
1417
1418                 nt_status = unix_convert(ctx, conn, path, &smb_fname,
1419                                          UCF_ALLOW_WCARD_LCOMP);
1420                 if (!NT_STATUS_IS_OK(nt_status)) {
1421                         reply_nterror(req, nt_status);
1422                         END_PROFILE(SMBsearch);
1423                         return;
1424                 }
1425
1426                 nt_status = get_full_smb_filename(ctx, smb_fname, &directory);
1427                 TALLOC_FREE(smb_fname);
1428                 if (!NT_STATUS_IS_OK(nt_status)) {
1429                         reply_nterror(req, nt_status);
1430                         END_PROFILE(SMBsearch);
1431                         return;
1432                 }
1433
1434                 nt_status = check_name(conn, directory);
1435                 if (!NT_STATUS_IS_OK(nt_status)) {
1436                         reply_nterror(req, nt_status);
1437                         END_PROFILE(SMBsearch);
1438                         return;
1439                 }
1440
1441                 p = strrchr_m(directory,'/');
1442                 if ((p != NULL) && (*directory != '/')) {
1443                         mask = p + 1;
1444                         directory = talloc_strndup(ctx, directory,
1445                                                    PTR_DIFF(p, directory));
1446                 } else {
1447                         mask = directory;
1448                         directory = talloc_strdup(ctx,".");
1449                 }
1450
1451                 if (!directory) {
1452                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1453                         END_PROFILE(SMBsearch);
1454                         return;
1455                 }
1456
1457                 memset((char *)status,'\0',21);
1458                 SCVAL(status,0,(dirtype & 0x1F));
1459
1460                 nt_status = dptr_create(conn,
1461                                         directory,
1462                                         True,
1463                                         expect_close,
1464                                         req->smbpid,
1465                                         mask,
1466                                         mask_contains_wcard,
1467                                         dirtype,
1468                                         &conn->dirptr);
1469                 if (!NT_STATUS_IS_OK(nt_status)) {
1470                         reply_nterror(req, nt_status);
1471                         END_PROFILE(SMBsearch);
1472                         return;
1473                 }
1474                 dptr_num = dptr_dnum(conn->dirptr);
1475         } else {
1476                 int status_dirtype;
1477
1478                 memcpy(status,p,21);
1479                 status_dirtype = CVAL(status,0) & 0x1F;
1480                 if (status_dirtype != (dirtype & 0x1F)) {
1481                         dirtype = status_dirtype;
1482                 }
1483
1484                 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1485                 if (!conn->dirptr) {
1486                         goto SearchEmpty;
1487                 }
1488                 string_set(&conn->dirpath,dptr_path(dptr_num));
1489                 mask = dptr_wcard(dptr_num);
1490                 if (!mask) {
1491                         goto SearchEmpty;
1492                 }
1493                 /*
1494                  * For a 'continue' search we have no string. So
1495                  * check from the initial saved string.
1496                  */
1497                 mask_contains_wcard = ms_has_wild(mask);
1498                 dirtype = dptr_attr(dptr_num);
1499         }
1500
1501         DEBUG(4,("dptr_num is %d\n",dptr_num));
1502
1503         /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1504         dptr_init_search_op(conn->dirptr);
1505
1506         if ((dirtype&0x1F) == aVOLID) {
1507                 char buf[DIR_STRUCT_SIZE];
1508                 memcpy(buf,status,21);
1509                 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1510                                 0,aVOLID,0,!allow_long_path_components)) {
1511                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1512                         END_PROFILE(SMBsearch);
1513                         return;
1514                 }
1515                 dptr_fill(buf+12,dptr_num);
1516                 if (dptr_zero(buf+12) && (status_len==0)) {
1517                         numentries = 1;
1518                 } else {
1519                         numentries = 0;
1520                 }
1521                 if (message_push_blob(&req->outbuf,
1522                                       data_blob_const(buf, sizeof(buf)))
1523                     == -1) {
1524                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1525                         END_PROFILE(SMBsearch);
1526                         return;
1527                 }
1528         } else {
1529                 unsigned int i;
1530                 maxentries = MIN(
1531                         maxentries,
1532                         ((BUFFER_SIZE -
1533                           ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1534                          /DIR_STRUCT_SIZE));
1535
1536                 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1537                         conn->dirpath,lp_dontdescend(SNUM(conn))));
1538                 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1539                         check_descend = True;
1540                 }
1541
1542                 for (i=numentries;(i<maxentries) && !finished;i++) {
1543                         finished = !get_dir_entry(ctx,
1544                                                   conn,
1545                                                   mask,
1546                                                   dirtype,
1547                                                   &fname,
1548                                                   &size,
1549                                                   &mode,
1550                                                   &date,
1551                                                   check_descend,
1552                                                   ask_sharemode);
1553                         if (!finished) {
1554                                 char buf[DIR_STRUCT_SIZE];
1555                                 memcpy(buf,status,21);
1556                                 if (!make_dir_struct(ctx,
1557                                                 buf,
1558                                                 mask,
1559                                                 fname,
1560                                                 size,
1561                                                 mode,
1562                                                 convert_timespec_to_time_t(date),
1563                                                 !allow_long_path_components)) {
1564                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1565                                         END_PROFILE(SMBsearch);
1566                                         return;
1567                                 }
1568                                 if (!dptr_fill(buf+12,dptr_num)) {
1569                                         break;
1570                                 }
1571                                 if (message_push_blob(&req->outbuf,
1572                                                       data_blob_const(buf, sizeof(buf)))
1573                                     == -1) {
1574                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1575                                         END_PROFILE(SMBsearch);
1576                                         return;
1577                                 }
1578                                 numentries++;
1579                         }
1580                 }
1581         }
1582
1583   SearchEmpty:
1584
1585         /* If we were called as SMBffirst with smb_search_id == NULL
1586                 and no entries were found then return error and close dirptr 
1587                 (X/Open spec) */
1588
1589         if (numentries == 0) {
1590                 dptr_close(&dptr_num);
1591         } else if(expect_close && status_len == 0) {
1592                 /* Close the dptr - we know it's gone */
1593                 dptr_close(&dptr_num);
1594         }
1595
1596         /* If we were called as SMBfunique, then we can close the dirptr now ! */
1597         if(dptr_num >= 0 && req->cmd == SMBfunique) {
1598                 dptr_close(&dptr_num);
1599         }
1600
1601         if ((numentries == 0) && !mask_contains_wcard) {
1602                 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1603                 END_PROFILE(SMBsearch);
1604                 return;
1605         }
1606
1607         SSVAL(req->outbuf,smb_vwv0,numentries);
1608         SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1609         SCVAL(smb_buf(req->outbuf),0,5);
1610         SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1611
1612         /* The replies here are never long name. */
1613         SSVAL(req->outbuf, smb_flg2,
1614               SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1615         if (!allow_long_path_components) {
1616                 SSVAL(req->outbuf, smb_flg2,
1617                       SVAL(req->outbuf, smb_flg2)
1618                       & (~FLAGS2_LONG_PATH_COMPONENTS));
1619         }
1620
1621         /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1622         SSVAL(req->outbuf, smb_flg2,
1623               (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1624
1625         if (!directory) {
1626                 directory = dptr_path(dptr_num);
1627         }
1628
1629         DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1630                 smb_fn_name(req->cmd),
1631                 mask,
1632                 directory ? directory : "./",
1633                 dirtype,
1634                 numentries,
1635                 maxentries ));
1636
1637         END_PROFILE(SMBsearch);
1638         return;
1639 }
1640
1641 /****************************************************************************
1642  Reply to a fclose (stop directory search).
1643 ****************************************************************************/
1644
1645 void reply_fclose(struct smb_request *req)
1646 {
1647         int status_len;
1648         char status[21];
1649         int dptr_num= -2;
1650         const char *p;
1651         char *path = NULL;
1652         NTSTATUS err;
1653         bool path_contains_wcard = False;
1654         TALLOC_CTX *ctx = talloc_tos();
1655
1656         START_PROFILE(SMBfclose);
1657
1658         if (lp_posix_pathnames()) {
1659                 reply_unknown_new(req, req->cmd);
1660                 END_PROFILE(SMBfclose);
1661                 return;
1662         }
1663
1664         p = (const char *)req->buf + 1;
1665         p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1666                                        &err, &path_contains_wcard);
1667         if (!NT_STATUS_IS_OK(err)) {
1668                 reply_nterror(req, err);
1669                 END_PROFILE(SMBfclose);
1670                 return;
1671         }
1672         p++;
1673         status_len = SVAL(p,0);
1674         p += 2;
1675
1676         if (status_len == 0) {
1677                 reply_doserror(req, ERRSRV, ERRsrverror);
1678                 END_PROFILE(SMBfclose);
1679                 return;
1680         }
1681
1682         memcpy(status,p,21);
1683
1684         if(dptr_fetch(status+12,&dptr_num)) {
1685                 /*  Close the dptr - we know it's gone */
1686                 dptr_close(&dptr_num);
1687         }
1688
1689         reply_outbuf(req, 1, 0);
1690         SSVAL(req->outbuf,smb_vwv0,0);
1691
1692         DEBUG(3,("search close\n"));
1693
1694         END_PROFILE(SMBfclose);
1695         return;
1696 }
1697
1698 /****************************************************************************
1699  Reply to an open.
1700 ****************************************************************************/
1701
1702 void reply_open(struct smb_request *req)
1703 {
1704         connection_struct *conn = req->conn;
1705         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         struct smbd_server_connection *sconn = smbd_server_conn;
4144
4145         if (is_encrypted_packet(inbuf)) {
4146                 /* Can't do this on encrypted
4147                  * connections. */
4148                 return false;
4149         }
4150
4151         if (CVAL(inbuf,smb_com) != SMBwriteX) {
4152                 return false;
4153         }
4154
4155         if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4156                         CVAL(inbuf,smb_wct) != 14) {
4157                 DEBUG(10,("is_valid_writeX_buffer: chained or "
4158                         "invalid word length.\n"));
4159                 return false;
4160         }
4161
4162         conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4163         if (conn == NULL) {
4164                 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4165                 return false;
4166         }
4167         if (IS_IPC(conn)) {
4168                 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4169                 return false;
4170         }
4171         if (IS_PRINT(conn)) {
4172                 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4173                 return false;
4174         }
4175         doff = SVAL(inbuf,smb_vwv11);
4176
4177         numtowrite = SVAL(inbuf,smb_vwv10);
4178
4179         if (len > doff && len - doff > 0xFFFF) {
4180                 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4181         }
4182
4183         if (numtowrite == 0) {
4184                 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4185                 return false;
4186         }
4187
4188         /* Ensure the sizes match up. */
4189         if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4190                 /* no pad byte...old smbclient :-( */
4191                 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4192                         (unsigned int)doff,
4193                         (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4194                 return false;
4195         }
4196
4197         if (len - doff != numtowrite) {
4198                 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4199                         "len = %u, doff = %u, numtowrite = %u\n",
4200                         (unsigned int)len,
4201                         (unsigned int)doff,
4202                         (unsigned int)numtowrite ));
4203                 return false;
4204         }
4205
4206         DEBUG(10,("is_valid_writeX_buffer: true "
4207                 "len = %u, doff = %u, numtowrite = %u\n",
4208                 (unsigned int)len,
4209                 (unsigned int)doff,
4210                 (unsigned int)numtowrite ));
4211
4212         return true;
4213 }
4214
4215 /****************************************************************************
4216  Reply to a write and X.
4217 ****************************************************************************/
4218
4219 void reply_write_and_X(struct smb_request *req)
4220 {
4221         connection_struct *conn = req->conn;
4222         files_struct *fsp;
4223         struct lock_struct lock;
4224         SMB_OFF_T startpos;
4225         size_t numtowrite;
4226         bool write_through;
4227         ssize_t nwritten;
4228         unsigned int smb_doff;
4229         unsigned int smblen;
4230         char *data;
4231         NTSTATUS status;
4232
4233         START_PROFILE(SMBwriteX);
4234
4235         if ((req->wct != 12) && (req->wct != 14)) {
4236                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4237                 END_PROFILE(SMBwriteX);
4238                 return;
4239         }
4240
4241         numtowrite = SVAL(req->vwv+10, 0);
4242         smb_doff = SVAL(req->vwv+11, 0);
4243         smblen = smb_len(req->inbuf);
4244
4245         if (req->unread_bytes > 0xFFFF ||
4246                         (smblen > smb_doff &&
4247                                 smblen - smb_doff > 0xFFFF)) {
4248                 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4249         }
4250
4251         if (req->unread_bytes) {
4252                 /* Can't do a recvfile write on IPC$ */
4253                 if (IS_IPC(conn)) {
4254                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4255                         END_PROFILE(SMBwriteX);
4256                         return;
4257                 }
4258                 if (numtowrite != req->unread_bytes) {
4259                         reply_doserror(req, ERRDOS, ERRbadmem);
4260                         END_PROFILE(SMBwriteX);
4261                         return;
4262                 }
4263         } else {
4264                 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4265                                 smb_doff + numtowrite > smblen) {
4266                         reply_doserror(req, ERRDOS, ERRbadmem);
4267                         END_PROFILE(SMBwriteX);
4268                         return;
4269                 }
4270         }
4271
4272         /* If it's an IPC, pass off the pipe handler. */
4273         if (IS_IPC(conn)) {
4274                 if (req->unread_bytes) {
4275                         reply_doserror(req, ERRDOS, ERRbadmem);
4276                         END_PROFILE(SMBwriteX);
4277                         return;
4278                 }
4279                 reply_pipe_write_and_X(req);
4280                 END_PROFILE(SMBwriteX);
4281                 return;
4282         }
4283
4284         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4285         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4286         write_through = BITSETW(req->vwv+7,0);
4287
4288         if (!check_fsp(conn, req, fsp)) {
4289                 END_PROFILE(SMBwriteX);
4290                 return;
4291         }
4292
4293         if (!CHECK_WRITE(fsp)) {
4294                 reply_doserror(req, ERRDOS, ERRbadaccess);
4295                 END_PROFILE(SMBwriteX);
4296                 return;
4297         }
4298
4299         data = smb_base(req->inbuf) + smb_doff;
4300
4301         if(req->wct == 14) {
4302 #ifdef LARGE_SMB_OFF_T
4303                 /*
4304                  * This is a large offset (64 bit) write.
4305                  */
4306                 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4307
4308 #else /* !LARGE_SMB_OFF_T */
4309
4310                 /*
4311                  * Ensure we haven't been sent a >32 bit offset.
4312                  */
4313
4314                 if(IVAL(req->vwv+12, 0) != 0) {
4315                         DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4316                                  "used and we don't support 64 bit offsets.\n",
4317                                  (unsigned int)IVAL(req->vwv+12, 0) ));
4318                         reply_doserror(req, ERRDOS, ERRbadaccess);
4319                         END_PROFILE(SMBwriteX);
4320                         return;
4321                 }
4322
4323 #endif /* LARGE_SMB_OFF_T */
4324         }
4325
4326         init_strict_lock_struct(fsp, (uint32)req->smbpid,
4327             (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4328             &lock);
4329
4330         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4331                 reply_doserror(req, ERRDOS, ERRlock);
4332                 END_PROFILE(SMBwriteX);
4333                 return;
4334         }
4335
4336         /* X/Open SMB protocol says that, unlike SMBwrite
4337         if the length is zero then NO truncation is
4338         done, just a write of zero. To truncate a file,
4339         use SMBwrite. */
4340
4341         if(numtowrite == 0) {
4342                 nwritten = 0;
4343         } else {
4344
4345                 if ((req->unread_bytes == 0) &&
4346                     schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4347                                              numtowrite)) {
4348                         goto strict_unlock;
4349                 }
4350
4351                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4352         }
4353
4354         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4355                 reply_unixerror(req, ERRHRD, ERRdiskfull);
4356                 goto strict_unlock;
4357         }
4358
4359         reply_outbuf(req, 6, 0);
4360         SSVAL(req->outbuf,smb_vwv2,nwritten);
4361         SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4362
4363         if (nwritten < (ssize_t)numtowrite) {
4364                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4365                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4366         }
4367
4368         DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4369                 fsp->fnum, (int)numtowrite, (int)nwritten));
4370
4371         status = sync_file(conn, fsp, write_through);
4372         if (!NT_STATUS_IS_OK(status)) {
4373                 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4374                         fsp->fsp_name, nt_errstr(status) ));
4375                 reply_nterror(req, status);
4376                 goto strict_unlock;
4377         }
4378
4379         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4380
4381         END_PROFILE(SMBwriteX);
4382         chain_reply(req);
4383         return;
4384
4385 strict_unlock:
4386         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4387
4388         END_PROFILE(SMBwriteX);
4389         return;
4390 }
4391
4392 /****************************************************************************
4393  Reply to a lseek.
4394 ****************************************************************************/
4395
4396 void reply_lseek(struct smb_request *req)
4397 {
4398         connection_struct *conn = req->conn;
4399         SMB_OFF_T startpos;
4400         SMB_OFF_T res= -1;
4401         int mode,umode;
4402         files_struct *fsp;
4403
4404         START_PROFILE(SMBlseek);
4405
4406         if (req->wct < 4) {
4407                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4408                 END_PROFILE(SMBlseek);
4409                 return;
4410         }
4411
4412         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4413
4414         if (!check_fsp(conn, req, fsp)) {
4415                 return;
4416         }
4417
4418         flush_write_cache(fsp, SEEK_FLUSH);
4419
4420         mode = SVAL(req->vwv+1, 0) & 3;
4421         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4422         startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4423
4424         switch (mode) {
4425                 case 0:
4426                         umode = SEEK_SET;
4427                         res = startpos;
4428                         break;
4429                 case 1:
4430                         umode = SEEK_CUR;
4431                         res = fsp->fh->pos + startpos;
4432                         break;
4433                 case 2:
4434                         umode = SEEK_END;
4435                         break;
4436                 default:
4437                         umode = SEEK_SET;
4438                         res = startpos;
4439                         break;
4440         }
4441
4442         if (umode == SEEK_END) {
4443                 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4444                         if(errno == EINVAL) {
4445                                 SMB_OFF_T current_pos = startpos;
4446                                 SMB_STRUCT_STAT sbuf;
4447
4448                                 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4449                                         reply_unixerror(req, ERRDOS,
4450                                                         ERRnoaccess);
4451                                         END_PROFILE(SMBlseek);
4452                                         return;
4453                                 }
4454
4455                                 current_pos += sbuf.st_ex_size;
4456                                 if(current_pos < 0)
4457                                         res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4458                         }
4459                 }
4460
4461                 if(res == -1) {
4462                         reply_unixerror(req, ERRDOS, ERRnoaccess);
4463                         END_PROFILE(SMBlseek);
4464                         return;
4465                 }
4466         }
4467
4468         fsp->fh->pos = res;
4469
4470         reply_outbuf(req, 2, 0);
4471         SIVAL(req->outbuf,smb_vwv0,res);
4472
4473         DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4474                 fsp->fnum, (double)startpos, (double)res, mode));
4475
4476         END_PROFILE(SMBlseek);
4477         return;
4478 }
4479
4480 /****************************************************************************
4481  Reply to a flush.
4482 ****************************************************************************/
4483
4484 void reply_flush(struct smb_request *req)
4485 {
4486         connection_struct *conn = req->conn;
4487         uint16 fnum;
4488         files_struct *fsp;
4489
4490         START_PROFILE(SMBflush);
4491
4492         if (req->wct < 1) {
4493                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4494                 return;
4495         }
4496
4497         fnum = SVAL(req->vwv+0, 0);
4498         fsp = file_fsp(req, fnum);
4499
4500         if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4501                 return;
4502         }
4503
4504         if (!fsp) {
4505                 file_sync_all(conn);
4506         } else {
4507                 NTSTATUS status = sync_file(conn, fsp, True);
4508                 if (!NT_STATUS_IS_OK(status)) {
4509                         DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4510                                 fsp->fsp_name, nt_errstr(status) ));
4511                         reply_nterror(req, status);
4512                         END_PROFILE(SMBflush);
4513                         return;
4514                 }
4515         }
4516
4517         reply_outbuf(req, 0, 0);
4518
4519         DEBUG(3,("flush\n"));
4520         END_PROFILE(SMBflush);
4521         return;
4522 }
4523
4524 /****************************************************************************
4525  Reply to a exit.
4526  conn POINTER CAN BE NULL HERE !
4527 ****************************************************************************/
4528
4529 void reply_exit(struct smb_request *req)
4530 {
4531         START_PROFILE(SMBexit);
4532
4533         file_close_pid(req->smbpid, req->vuid);
4534
4535         reply_outbuf(req, 0, 0);
4536
4537         DEBUG(3,("exit\n"));
4538
4539         END_PROFILE(SMBexit);
4540         return;
4541 }
4542
4543 /****************************************************************************
4544  Reply to a close - has to deal with closing a directory opened by NT SMB's.
4545 ****************************************************************************/
4546
4547 void reply_close(struct smb_request *req)
4548 {
4549         connection_struct *conn = req->conn;
4550         NTSTATUS status = NT_STATUS_OK;
4551         files_struct *fsp = NULL;
4552         START_PROFILE(SMBclose);
4553
4554         if (req->wct < 3) {
4555                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4556                 END_PROFILE(SMBclose);
4557                 return;
4558         }
4559
4560         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4561
4562         /*
4563          * We can only use check_fsp if we know it's not a directory.
4564          */
4565
4566         if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4567                 reply_doserror(req, ERRDOS, ERRbadfid);
4568                 END_PROFILE(SMBclose);
4569                 return;
4570         }
4571
4572         if(fsp->is_directory) {
4573                 /*
4574                  * Special case - close NT SMB directory handle.
4575                  */
4576                 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4577                 status = close_file(req, fsp, NORMAL_CLOSE);
4578         } else {
4579                 time_t t;
4580                 /*
4581                  * Close ordinary file.
4582                  */
4583
4584                 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4585                          fsp->fh->fd, fsp->fnum,
4586                          conn->num_files_open));
4587
4588                 /*
4589                  * Take care of any time sent in the close.
4590                  */
4591
4592                 t = srv_make_unix_date3(req->vwv+1);
4593                 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4594
4595                 /*
4596                  * close_file() returns the unix errno if an error
4597                  * was detected on close - normally this is due to
4598                  * a disk full error. If not then it was probably an I/O error.
4599                  */
4600
4601                 status = close_file(req, fsp, NORMAL_CLOSE);
4602         }  
4603
4604         if (!NT_STATUS_IS_OK(status)) {
4605                 reply_nterror(req, status);
4606                 END_PROFILE(SMBclose);
4607                 return;
4608         }
4609
4610         reply_outbuf(req, 0, 0);
4611         END_PROFILE(SMBclose);
4612         return;
4613 }
4614
4615 /****************************************************************************
4616  Reply to a writeclose (Core+ protocol).
4617 ****************************************************************************/
4618
4619 void reply_writeclose(struct smb_request *req)
4620 {
4621         connection_struct *conn = req->conn;
4622         size_t numtowrite;
4623         ssize_t nwritten = -1;
4624         NTSTATUS close_status = NT_STATUS_OK;
4625         SMB_OFF_T startpos;
4626         const char *data;
4627         struct timespec mtime;
4628         files_struct *fsp;
4629         struct lock_struct lock;
4630
4631         START_PROFILE(SMBwriteclose);
4632
4633         if (req->wct < 6) {
4634                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4635                 END_PROFILE(SMBwriteclose);
4636                 return;
4637         }
4638
4639         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4640
4641         if (!check_fsp(conn, req, fsp)) {
4642                 END_PROFILE(SMBwriteclose);
4643                 return;
4644         }
4645         if (!CHECK_WRITE(fsp)) {
4646                 reply_doserror(req, ERRDOS,ERRbadaccess);
4647                 END_PROFILE(SMBwriteclose);
4648                 return;
4649         }
4650
4651         numtowrite = SVAL(req->vwv+1, 0);
4652         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4653         mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4654         data = (const char *)req->buf + 1;
4655
4656         if (numtowrite) {
4657                 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4658                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4659                     &lock);
4660
4661                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4662                         reply_doserror(req, ERRDOS,ERRlock);
4663                         END_PROFILE(SMBwriteclose);
4664                         return;
4665                 }
4666         }
4667
4668         nwritten = write_file(req,fsp,data,startpos,numtowrite);
4669
4670         set_close_write_time(fsp, mtime);
4671
4672         /*
4673          * More insanity. W2K only closes the file if writelen > 0.
4674          * JRA.
4675          */
4676
4677         if (numtowrite) {
4678                 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4679                         fsp->fsp_name ));
4680                 close_status = close_file(req, fsp, NORMAL_CLOSE);
4681         }
4682
4683         DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4684                  fsp->fnum, (int)numtowrite, (int)nwritten,
4685                  conn->num_files_open));
4686
4687         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4688                 reply_doserror(req, ERRHRD, ERRdiskfull);
4689                 goto strict_unlock;
4690         }
4691
4692         if(!NT_STATUS_IS_OK(close_status)) {
4693                 reply_nterror(req, close_status);
4694                 goto strict_unlock;
4695         }
4696
4697         reply_outbuf(req, 1, 0);
4698
4699         SSVAL(req->outbuf,smb_vwv0,nwritten);
4700
4701 strict_unlock:
4702         if (numtowrite) {
4703                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4704         }
4705
4706         END_PROFILE(SMBwriteclose);
4707         return;
4708 }
4709
4710 #undef DBGC_CLASS
4711 #define DBGC_CLASS DBGC_LOCKING
4712
4713 /****************************************************************************
4714  Reply to a lock.
4715 ****************************************************************************/
4716
4717 void reply_lock(struct smb_request *req)
4718 {
4719         connection_struct *conn = req->conn;
4720         uint64_t count,offset;
4721         NTSTATUS status;
4722         files_struct *fsp;
4723         struct byte_range_lock *br_lck = NULL;
4724
4725         START_PROFILE(SMBlock);
4726
4727         if (req->wct < 5) {
4728                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4729                 END_PROFILE(SMBlock);
4730                 return;
4731         }
4732
4733         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4734
4735         if (!check_fsp(conn, req, fsp)) {
4736                 END_PROFILE(SMBlock);
4737                 return;
4738         }
4739
4740         count = (uint64_t)IVAL(req->vwv+1, 0);
4741         offset = (uint64_t)IVAL(req->vwv+3, 0);
4742
4743         DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4744                  fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4745
4746         br_lck = do_lock(smbd_messaging_context(),
4747                         fsp,
4748                         req->smbpid,
4749                         count,
4750                         offset,
4751                         WRITE_LOCK,
4752                         WINDOWS_LOCK,
4753                         False, /* Non-blocking lock. */
4754                         &status,
4755                         NULL,
4756                         NULL);
4757
4758         TALLOC_FREE(br_lck);
4759
4760         if (NT_STATUS_V(status)) {
4761                 reply_nterror(req, status);
4762                 END_PROFILE(SMBlock);
4763                 return;
4764         }
4765
4766         reply_outbuf(req, 0, 0);
4767
4768         END_PROFILE(SMBlock);
4769         return;
4770 }
4771
4772 /****************************************************************************
4773  Reply to a unlock.
4774 ****************************************************************************/
4775
4776 void reply_unlock(struct smb_request *req)
4777 {
4778         connection_struct *conn = req->conn;
4779         uint64_t count,offset;
4780         NTSTATUS status;
4781         files_struct *fsp;
4782
4783         START_PROFILE(SMBunlock);
4784
4785         if (req->wct < 5) {
4786                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4787                 END_PROFILE(SMBunlock);
4788                 return;
4789         }
4790
4791         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4792
4793         if (!check_fsp(conn, req, fsp)) {
4794                 END_PROFILE(SMBunlock);
4795                 return;
4796         }
4797
4798         count = (uint64_t)IVAL(req->vwv+1, 0);
4799         offset = (uint64_t)IVAL(req->vwv+3, 0);
4800
4801         status = do_unlock(smbd_messaging_context(),
4802                         fsp,
4803                         req->smbpid,
4804                         count,
4805                         offset,
4806                         WINDOWS_LOCK);
4807
4808         if (NT_STATUS_V(status)) {
4809                 reply_nterror(req, status);
4810                 END_PROFILE(SMBunlock);
4811                 return;
4812         }
4813
4814         DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4815                     fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4816
4817         reply_outbuf(req, 0, 0);
4818
4819         END_PROFILE(SMBunlock);
4820         return;
4821 }
4822
4823 #undef DBGC_CLASS
4824 #define DBGC_CLASS DBGC_ALL
4825
4826 /****************************************************************************
4827  Reply to a tdis.
4828  conn POINTER CAN BE NULL HERE !
4829 ****************************************************************************/
4830
4831 void reply_tdis(struct smb_request *req)
4832 {
4833         struct smbd_server_connection *sconn = smbd_server_conn;
4834         connection_struct *conn = req->conn;
4835         START_PROFILE(SMBtdis);
4836
4837         if (!conn) {
4838                 DEBUG(4,("Invalid connection in tdis\n"));
4839                 reply_doserror(req, ERRSRV, ERRinvnid);
4840                 END_PROFILE(SMBtdis);
4841                 return;
4842         }
4843
4844         conn->used = False;
4845
4846         close_cnum(sconn, conn,req->vuid);
4847         req->conn = NULL;
4848
4849         reply_outbuf(req, 0, 0);
4850         END_PROFILE(SMBtdis);
4851         return;
4852 }
4853
4854 /****************************************************************************
4855  Reply to a echo.
4856  conn POINTER CAN BE NULL HERE !
4857 ****************************************************************************/
4858
4859 void reply_echo(struct smb_request *req)
4860 {
4861         connection_struct *conn = req->conn;
4862         struct smb_perfcount_data local_pcd;
4863         struct smb_perfcount_data *cur_pcd;
4864         int smb_reverb;
4865         int seq_num;
4866
4867         START_PROFILE(SMBecho);
4868
4869         smb_init_perfcount_data(&local_pcd);
4870
4871         if (req->wct < 1) {
4872                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4873                 END_PROFILE(SMBecho);
4874                 return;
4875         }
4876
4877         smb_reverb = SVAL(req->vwv+0, 0);
4878
4879         reply_outbuf(req, 1, req->buflen);
4880
4881         /* copy any incoming data back out */
4882         if (req->buflen > 0) {
4883                 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4884         }
4885
4886         if (smb_reverb > 100) {
4887                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4888                 smb_reverb = 100;
4889         }
4890
4891         for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
4892
4893                 /* this makes sure we catch the request pcd */
4894                 if (seq_num == smb_reverb) {
4895                         cur_pcd = &req->pcd;
4896                 } else {
4897                         SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
4898                         cur_pcd = &local_pcd;
4899                 }
4900
4901                 SSVAL(req->outbuf,smb_vwv0,seq_num);
4902
4903                 show_msg((char *)req->outbuf);
4904                 if (!srv_send_smb(smbd_server_fd(),
4905                                 (char *)req->outbuf,
4906                                 true, req->seqnum+1,
4907                                 IS_CONN_ENCRYPTED(conn)||req->encrypted,
4908                                 cur_pcd))
4909                         exit_server_cleanly("reply_echo: srv_send_smb failed.");
4910         }
4911
4912         DEBUG(3,("echo %d times\n", smb_reverb));
4913
4914         TALLOC_FREE(req->outbuf);
4915
4916         END_PROFILE(SMBecho);
4917         return;
4918 }
4919
4920 /****************************************************************************
4921  Reply to a printopen.
4922 ****************************************************************************/
4923
4924 void reply_printopen(struct smb_request *req)
4925 {
4926         connection_struct *conn = req->conn;
4927         files_struct *fsp;
4928         SMB_STRUCT_STAT sbuf;
4929         NTSTATUS status;
4930
4931         START_PROFILE(SMBsplopen);
4932
4933         if (req->wct < 2) {
4934                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4935                 END_PROFILE(SMBsplopen);
4936                 return;
4937         }
4938
4939         if (!CAN_PRINT(conn)) {
4940                 reply_doserror(req, ERRDOS, ERRnoaccess);
4941                 END_PROFILE(SMBsplopen);
4942                 return;
4943         }
4944
4945         status = file_new(req, conn, &fsp);
4946         if(!NT_STATUS_IS_OK(status)) {
4947                 reply_nterror(req, status);
4948                 END_PROFILE(SMBsplopen);
4949                 return;
4950         }
4951
4952         /* Open for exclusive use, write only. */
4953         status = print_fsp_open(req, conn, NULL, req->vuid, fsp, &sbuf);
4954
4955         if (!NT_STATUS_IS_OK(status)) {
4956                 reply_nterror(req, status);
4957                 END_PROFILE(SMBsplopen);
4958                 return;
4959         }
4960
4961         reply_outbuf(req, 1, 0);
4962         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4963
4964         DEBUG(3,("openprint fd=%d fnum=%d\n",
4965                  fsp->fh->fd, fsp->fnum));
4966
4967         END_PROFILE(SMBsplopen);
4968         return;
4969 }
4970
4971 /****************************************************************************
4972  Reply to a printclose.
4973 ****************************************************************************/
4974
4975 void reply_printclose(struct smb_request *req)
4976 {
4977         connection_struct *conn = req->conn;
4978         files_struct *fsp;
4979         NTSTATUS status;
4980
4981         START_PROFILE(SMBsplclose);
4982
4983         if (req->wct < 1) {
4984                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4985                 END_PROFILE(SMBsplclose);
4986                 return;
4987         }
4988
4989         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4990
4991         if (!check_fsp(conn, req, fsp)) {
4992                 END_PROFILE(SMBsplclose);
4993                 return;
4994         }
4995
4996         if (!CAN_PRINT(conn)) {
4997                 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
4998                 END_PROFILE(SMBsplclose);
4999                 return;
5000         }
5001
5002         DEBUG(3,("printclose fd=%d fnum=%d\n",
5003                  fsp->fh->fd,fsp->fnum));
5004
5005         status = close_file(req, fsp, NORMAL_CLOSE);
5006
5007         if(!NT_STATUS_IS_OK(status)) {
5008                 reply_nterror(req, status);
5009                 END_PROFILE(SMBsplclose);
5010                 return;
5011         }
5012
5013         reply_outbuf(req, 0, 0);
5014
5015         END_PROFILE(SMBsplclose);
5016         return;
5017 }
5018
5019 /****************************************************************************
5020  Reply to a printqueue.
5021 ****************************************************************************/
5022
5023 void reply_printqueue(struct smb_request *req)
5024 {
5025         connection_struct *conn = req->conn;
5026         int max_count;
5027         int start_index;
5028
5029         START_PROFILE(SMBsplretq);
5030
5031         if (req->wct < 2) {
5032                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5033                 END_PROFILE(SMBsplretq);
5034                 return;
5035         }
5036
5037         max_count = SVAL(req->vwv+0, 0);
5038         start_index = SVAL(req->vwv+1, 0);
5039
5040         /* we used to allow the client to get the cnum wrong, but that
5041            is really quite gross and only worked when there was only
5042            one printer - I think we should now only accept it if they
5043            get it right (tridge) */
5044         if (!CAN_PRINT(conn)) {
5045                 reply_doserror(req, ERRDOS, ERRnoaccess);
5046                 END_PROFILE(SMBsplretq);
5047                 return;
5048         }
5049
5050         reply_outbuf(req, 2, 3);
5051         SSVAL(req->outbuf,smb_vwv0,0);
5052         SSVAL(req->outbuf,smb_vwv1,0);
5053         SCVAL(smb_buf(req->outbuf),0,1);
5054         SSVAL(smb_buf(req->outbuf),1,0);
5055
5056         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5057                  start_index, max_count));
5058
5059         {
5060                 print_queue_struct *queue = NULL;
5061                 print_status_struct status;
5062                 int count = print_queue_status(SNUM(conn), &queue, &status);
5063                 int num_to_get = ABS(max_count);
5064                 int first = (max_count>0?start_index:start_index+max_count+1);
5065                 int i;
5066
5067                 if (first >= count)
5068                         num_to_get = 0;
5069                 else
5070                         num_to_get = MIN(num_to_get,count-first);
5071
5072
5073                 for (i=first;i<first+num_to_get;i++) {
5074                         char blob[28];
5075                         char *p = blob;
5076
5077                         srv_put_dos_date2(p,0,queue[i].time);
5078                         SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
5079                         SSVAL(p,5, queue[i].job);
5080                         SIVAL(p,7,queue[i].size);
5081                         SCVAL(p,11,0);
5082                         srvstr_push(blob, req->flags2, p+12,
5083                                     queue[i].fs_user, 16, STR_ASCII);
5084
5085                         if (message_push_blob(
5086                                     &req->outbuf,
5087                                     data_blob_const(
5088                                             blob, sizeof(blob))) == -1) {
5089                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
5090                                 END_PROFILE(SMBsplretq);
5091                                 return;
5092                         }
5093                 }
5094
5095                 if (count > 0) {
5096                         SSVAL(req->outbuf,smb_vwv0,count);
5097                         SSVAL(req->outbuf,smb_vwv1,
5098                               (max_count>0?first+count:first-1));
5099                         SCVAL(smb_buf(req->outbuf),0,1);
5100                         SSVAL(smb_buf(req->outbuf),1,28*count);
5101                 }
5102
5103                 SAFE_FREE(queue);
5104
5105                 DEBUG(3,("%d entries returned in queue\n",count));
5106         }
5107
5108         END_PROFILE(SMBsplretq);
5109         return;
5110 }
5111
5112 /****************************************************************************
5113  Reply to a printwrite.
5114 ****************************************************************************/
5115
5116 void reply_printwrite(struct smb_request *req)
5117 {
5118         connection_struct *conn = req->conn;
5119         int numtowrite;
5120         const char *data;
5121         files_struct *fsp;
5122
5123         START_PROFILE(SMBsplwr);
5124
5125         if (req->wct < 1) {
5126                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5127                 END_PROFILE(SMBsplwr);
5128                 return;
5129         }
5130
5131         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5132
5133         if (!check_fsp(conn, req, fsp)) {
5134                 END_PROFILE(SMBsplwr);
5135                 return;
5136         }
5137
5138         if (!CAN_PRINT(conn)) {
5139                 reply_doserror(req, ERRDOS, ERRnoaccess);
5140                 END_PROFILE(SMBsplwr);
5141                 return;
5142         }
5143
5144         if (!CHECK_WRITE(fsp)) {
5145                 reply_doserror(req, ERRDOS, ERRbadaccess);
5146                 END_PROFILE(SMBsplwr);
5147                 return;
5148         }
5149
5150         numtowrite = SVAL(req->buf, 1);
5151
5152         if (req->buflen < numtowrite + 3) {
5153                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5154                 END_PROFILE(SMBsplwr);
5155                 return;
5156         }
5157
5158         data = (const char *)req->buf + 3;
5159
5160         if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
5161                 reply_unixerror(req, ERRHRD, ERRdiskfull);
5162                 END_PROFILE(SMBsplwr);
5163                 return;
5164         }
5165
5166         DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5167
5168         END_PROFILE(SMBsplwr);
5169         return;
5170 }
5171
5172 /****************************************************************************
5173  Reply to a mkdir.
5174 ****************************************************************************/
5175
5176 void reply_mkdir(struct smb_request *req)
5177 {
5178         connection_struct *conn = req->conn;
5179         struct smb_filename *smb_dname = NULL;
5180         char *directory = NULL;
5181         NTSTATUS status;
5182         TALLOC_CTX *ctx = talloc_tos();
5183
5184         START_PROFILE(SMBmkdir);
5185
5186         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5187                             STR_TERMINATE, &status);
5188         if (!NT_STATUS_IS_OK(status)) {
5189                 reply_nterror(req, status);
5190                 goto out;
5191         }
5192
5193         status = resolve_dfspath(ctx, conn,
5194                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
5195                                  directory,
5196                                  &directory);
5197         if (!NT_STATUS_IS_OK(status)) {
5198                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5199                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5200                                         ERRSRV, ERRbadpath);
5201                         goto out;
5202                 }
5203                 reply_nterror(req, status);
5204                 goto out;
5205         }
5206
5207         status = unix_convert(ctx, conn, directory, &smb_dname, 0);
5208         if (!NT_STATUS_IS_OK(status)) {
5209                 reply_nterror(req, status);
5210                 goto out;
5211         }
5212
5213         status = get_full_smb_filename(ctx, smb_dname, &directory);
5214         if (!NT_STATUS_IS_OK(status)) {
5215                 reply_nterror(req, status);
5216                 goto out;
5217         }
5218
5219         status = check_name(conn, directory);
5220         if (!NT_STATUS_IS_OK(status)) {
5221                 reply_nterror(req, status);
5222                 goto out;
5223         }
5224
5225         status = create_directory(conn, req, directory);
5226
5227         DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5228
5229         if (!NT_STATUS_IS_OK(status)) {
5230
5231                 if (!use_nt_status()
5232                     && NT_STATUS_EQUAL(status,
5233                                        NT_STATUS_OBJECT_NAME_COLLISION)) {
5234                         /*
5235                          * Yes, in the DOS error code case we get a
5236                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5237                          * samba4 torture test.
5238                          */
5239                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5240                 }
5241
5242                 reply_nterror(req, status);
5243                 goto out;
5244         }
5245
5246         reply_outbuf(req, 0, 0);
5247
5248         DEBUG( 3, ( "mkdir %s\n", directory ) );
5249  out:
5250         TALLOC_FREE(smb_dname);
5251         END_PROFILE(SMBmkdir);
5252         return;
5253 }
5254
5255 /****************************************************************************
5256  Static function used by reply_rmdir to delete an entire directory
5257  tree recursively. Return True on ok, False on fail.
5258 ****************************************************************************/
5259
5260 static bool recursive_rmdir(TALLOC_CTX *ctx,
5261                         connection_struct *conn,
5262                         char *directory)
5263 {
5264         const char *dname = NULL;
5265         bool ret = True;
5266         long offset = 0;
5267         SMB_STRUCT_STAT st;
5268         struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, directory,
5269                                           NULL, 0);
5270
5271         if(dir_hnd == NULL)
5272                 return False;
5273
5274         while((dname = ReadDirName(dir_hnd, &offset, &st))) {
5275                 char *fullname = NULL;
5276
5277                 if (ISDOT(dname) || ISDOTDOT(dname)) {
5278                         continue;
5279                 }
5280
5281                 if (!is_visible_file(conn, directory, dname, &st, False)) {
5282                         continue;
5283                 }
5284
5285                 /* Construct the full name. */
5286                 fullname = talloc_asprintf(ctx,
5287                                 "%s/%s",
5288                                 directory,
5289                                 dname);
5290                 if (!fullname) {
5291                         errno = ENOMEM;
5292                         ret = False;
5293                         break;
5294                 }
5295
5296                 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5297                         ret = False;
5298                         break;
5299                 }
5300
5301                 if(st.st_ex_mode & S_IFDIR) {
5302                         if(!recursive_rmdir(ctx, conn, fullname)) {
5303                                 ret = False;
5304                                 break;
5305                         }
5306                         if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5307                                 ret = False;
5308                                 break;
5309                         }
5310                 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5311                         ret = False;
5312                         break;
5313                 }
5314                 TALLOC_FREE(fullname);
5315         }
5316         TALLOC_FREE(dir_hnd);
5317         return ret;
5318 }
5319
5320 /****************************************************************************
5321  The internals of the rmdir code - called elsewhere.
5322 ****************************************************************************/
5323
5324 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
5325                         connection_struct *conn,
5326                         const char *directory)
5327 {
5328         int ret;
5329         SMB_STRUCT_STAT st;
5330
5331         /* Might be a symlink. */
5332         if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
5333                 return map_nt_error_from_unix(errno);
5334         }
5335
5336         if (S_ISLNK(st.st_ex_mode)) {
5337                 /* Is what it points to a directory ? */
5338                 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
5339                         return map_nt_error_from_unix(errno);
5340                 }
5341                 if (!(S_ISDIR(st.st_ex_mode))) {
5342                         return NT_STATUS_NOT_A_DIRECTORY;
5343                 }
5344                 ret = SMB_VFS_UNLINK(conn,directory);
5345         } else {
5346                 ret = SMB_VFS_RMDIR(conn,directory);
5347         }
5348         if (ret == 0) {
5349                 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5350                              FILE_NOTIFY_CHANGE_DIR_NAME,
5351                              directory);
5352                 return NT_STATUS_OK;
5353         }
5354
5355         if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5356                 /*
5357                  * Check to see if the only thing in this directory are
5358                  * vetoed files/directories. If so then delete them and
5359                  * retry. If we fail to delete any of them (and we *don't*
5360                  * do a recursive delete) then fail the rmdir.
5361                  */
5362                 const char *dname;
5363                 long dirpos = 0;
5364                 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5365                                                   directory, NULL, 0);
5366
5367                 if(dir_hnd == NULL) {
5368                         errno = ENOTEMPTY;
5369                         goto err;
5370                 }
5371
5372                 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5373                         if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5374                                 continue;
5375                         if (!is_visible_file(conn, directory, dname, &st, False))
5376                                 continue;
5377                         if(!IS_VETO_PATH(conn, dname)) {
5378                                 TALLOC_FREE(dir_hnd);
5379                                 errno = ENOTEMPTY;
5380                                 goto err;
5381                         }
5382                 }
5383
5384                 /* We only have veto files/directories.
5385                  * Are we allowed to delete them ? */
5386
5387                 if(!lp_recursive_veto_delete(SNUM(conn))) {
5388                         TALLOC_FREE(dir_hnd);
5389                         errno = ENOTEMPTY;
5390                         goto err;
5391                 }
5392
5393                 /* Do a recursive delete. */
5394                 RewindDir(dir_hnd,&dirpos);
5395                 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5396                         char *fullname = NULL;
5397
5398                         if (ISDOT(dname) || ISDOTDOT(dname)) {
5399                                 continue;
5400                         }
5401                         if (!is_visible_file(conn, directory, dname, &st, False)) {
5402                                 continue;
5403                         }
5404
5405                         fullname = talloc_asprintf(ctx,
5406                                         "%s/%s",
5407                                         directory,
5408                                         dname);
5409
5410                         if(!fullname) {
5411                                 errno = ENOMEM;
5412                                 break;
5413                         }
5414
5415                         if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5416                                 break;
5417                         }
5418                         if(st.st_ex_mode & S_IFDIR) {
5419                                 if(!recursive_rmdir(ctx, conn, fullname)) {
5420                                         break;
5421                                 }
5422                                 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5423                                         break;
5424                                 }
5425                         } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5426                                 break;
5427                         }
5428                         TALLOC_FREE(fullname);
5429                 }
5430                 TALLOC_FREE(dir_hnd);
5431                 /* Retry the rmdir */
5432                 ret = SMB_VFS_RMDIR(conn,directory);
5433         }
5434
5435   err:
5436
5437         if (ret != 0) {
5438                 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5439                          "%s\n", directory,strerror(errno)));
5440                 return map_nt_error_from_unix(errno);
5441         }
5442
5443         notify_fname(conn, NOTIFY_ACTION_REMOVED,
5444                      FILE_NOTIFY_CHANGE_DIR_NAME,
5445                      directory);
5446
5447         return NT_STATUS_OK;
5448 }
5449
5450 /****************************************************************************
5451  Reply to a rmdir.
5452 ****************************************************************************/
5453
5454 void reply_rmdir(struct smb_request *req)
5455 {
5456         connection_struct *conn = req->conn;
5457         struct smb_filename *smb_dname = NULL;
5458         char *directory = NULL;
5459         NTSTATUS status;
5460         TALLOC_CTX *ctx = talloc_tos();
5461
5462         START_PROFILE(SMBrmdir);
5463
5464         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5465                             STR_TERMINATE, &status);
5466         if (!NT_STATUS_IS_OK(status)) {
5467                 reply_nterror(req, status);
5468                 goto out;
5469         }
5470
5471         status = resolve_dfspath(ctx, conn,
5472                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
5473                                  directory,
5474                                  &directory);
5475         if (!NT_STATUS_IS_OK(status)) {
5476                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5477                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5478                                         ERRSRV, ERRbadpath);
5479                         goto out;
5480                 }
5481                 reply_nterror(req, status);
5482                 goto out;
5483         }
5484
5485         status = unix_convert(ctx, conn, directory, &smb_dname, 0);
5486         if (!NT_STATUS_IS_OK(status)) {
5487                 reply_nterror(req, status);
5488                 goto out;
5489         }
5490
5491         status = get_full_smb_filename(ctx, smb_dname, &directory);
5492         if (!NT_STATUS_IS_OK(status)) {
5493                 reply_nterror(req, status);
5494                 goto out;
5495         }
5496
5497         status = check_name(conn, directory);
5498         if (!NT_STATUS_IS_OK(status)) {
5499                 reply_nterror(req, status);
5500                 goto out;
5501         }
5502
5503         dptr_closepath(directory, req->smbpid);
5504         status = rmdir_internals(ctx, conn, directory);
5505         if (!NT_STATUS_IS_OK(status)) {
5506                 reply_nterror(req, status);
5507                 goto out;
5508         }
5509
5510         reply_outbuf(req, 0, 0);
5511
5512         DEBUG( 3, ( "rmdir %s\n", directory ) );
5513  out:
5514         TALLOC_FREE(smb_dname);
5515         END_PROFILE(SMBrmdir);
5516         return;
5517 }
5518
5519 /*******************************************************************
5520  Resolve wildcards in a filename rename.
5521 ********************************************************************/
5522
5523 static bool resolve_wildcards(TALLOC_CTX *ctx,
5524                                 const char *name1,
5525                                 const char *name2,
5526                                 char **pp_newname)
5527 {
5528         char *name2_copy = NULL;
5529         char *root1 = NULL;
5530         char *root2 = NULL;
5531         char *ext1 = NULL;
5532         char *ext2 = NULL;
5533         char *p,*p2, *pname1, *pname2;
5534
5535         name2_copy = talloc_strdup(ctx, name2);
5536         if (!name2_copy) {
5537                 return False;
5538         }
5539
5540         pname1 = strrchr_m(name1,'/');
5541         pname2 = strrchr_m(name2_copy,'/');
5542
5543         if (!pname1 || !pname2) {
5544                 return False;
5545         }
5546
5547         /* Truncate the copy of name2 at the last '/' */
5548         *pname2 = '\0';
5549
5550         /* Now go past the '/' */
5551         pname1++;
5552         pname2++;
5553
5554         root1 = talloc_strdup(ctx, pname1);
5555         root2 = talloc_strdup(ctx, pname2);
5556
5557         if (!root1 || !root2) {
5558                 return False;
5559         }
5560
5561         p = strrchr_m(root1,'.');
5562         if (p) {
5563                 *p = 0;
5564                 ext1 = talloc_strdup(ctx, p+1);
5565         } else {
5566                 ext1 = talloc_strdup(ctx, "");
5567         }
5568         p = strrchr_m(root2,'.');
5569         if (p) {
5570                 *p = 0;
5571                 ext2 = talloc_strdup(ctx, p+1);
5572         } else {
5573                 ext2 = talloc_strdup(ctx, "");
5574         }
5575
5576         if (!ext1 || !ext2) {
5577                 return False;
5578         }
5579
5580         p = root1;
5581         p2 = root2;
5582         while (*p2) {
5583                 if (*p2 == '?') {
5584                         /* Hmmm. Should this be mb-aware ? */
5585                         *p2 = *p;
5586                         p2++;
5587                 } else if (*p2 == '*') {
5588                         *p2 = '\0';
5589                         root2 = talloc_asprintf(ctx, "%s%s",
5590                                                 root2,
5591                                                 p);
5592                         if (!root2) {
5593                                 return False;
5594                         }
5595                         break;
5596                 } else {
5597                         p2++;
5598                 }
5599                 if (*p) {
5600                         p++;
5601                 }
5602         }
5603
5604         p = ext1;
5605         p2 = ext2;
5606         while (*p2) {
5607                 if (*p2 == '?') {
5608                         /* Hmmm. Should this be mb-aware ? */
5609                         *p2 = *p;
5610                         p2++;
5611                 } else if (*p2 == '*') {
5612                         *p2 = '\0';
5613                         ext2 = talloc_asprintf(ctx, "%s%s",
5614                                                 ext2,
5615                                                 p);
5616                         if (!ext2) {
5617                                 return False;
5618                         }
5619                         break;
5620                 } else {
5621                         p2++;
5622                 }
5623                 if (*p) {
5624                         p++;
5625                 }
5626         }
5627
5628         if (*ext2) {
5629                 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5630                                 name2_copy,
5631                                 root2,
5632                                 ext2);
5633         } else {
5634                 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5635                                 name2_copy,
5636                                 root2);
5637         }
5638
5639         if (!*pp_newname) {
5640                 return False;
5641         }
5642
5643         return True;
5644 }
5645
5646 /****************************************************************************
5647  Ensure open files have their names updated. Updated to notify other smbd's
5648  asynchronously.
5649 ****************************************************************************/
5650
5651 static void rename_open_files(connection_struct *conn,
5652                               struct share_mode_lock *lck,
5653                               const char *newname)
5654 {
5655         files_struct *fsp;
5656         bool did_rename = False;
5657
5658         for(fsp = file_find_di_first(lck->id); fsp;
5659             fsp = file_find_di_next(fsp)) {
5660                 /* fsp_name is a relative path under the fsp. To change this for other
5661                    sharepaths we need to manipulate relative paths. */
5662                 /* TODO - create the absolute path and manipulate the newname
5663                    relative to the sharepath. */
5664                 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5665                         continue;
5666                 }
5667                 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5668                           fsp->fnum, file_id_string_tos(&fsp->file_id),
5669                         fsp->fsp_name, newname ));
5670                 string_set(&fsp->fsp_name, newname);
5671                 did_rename = True;
5672         }
5673
5674         if (!did_rename) {
5675                 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5676                           file_id_string_tos(&lck->id), newname ));
5677         }
5678
5679         /* Send messages to all smbd's (not ourself) that the name has changed. */
5680         rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5681                               newname);
5682 }
5683
5684 /****************************************************************************
5685  We need to check if the source path is a parent directory of the destination
5686  (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5687  refuse the rename with a sharing violation. Under UNIX the above call can
5688  *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5689  probably need to check that the client is a Windows one before disallowing
5690  this as a UNIX client (one with UNIX extensions) can know the source is a
5691  symlink and make this decision intelligently. Found by an excellent bug
5692  report from <AndyLiebman@aol.com>.
5693 ****************************************************************************/
5694
5695 static bool rename_path_prefix_equal(const char *src, const char *dest)
5696 {
5697         const char *psrc = src;
5698         const char *pdst = dest;
5699         size_t slen;
5700
5701         if (psrc[0] == '.' && psrc[1] == '/') {
5702                 psrc += 2;
5703         }
5704         if (pdst[0] == '.' && pdst[1] == '/') {
5705                 pdst += 2;
5706         }
5707         if ((slen = strlen(psrc)) > strlen(pdst)) {
5708                 return False;
5709         }
5710         return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5711 }
5712
5713 /*
5714  * Do the notify calls from a rename
5715  */
5716
5717 static void notify_rename(connection_struct *conn, bool is_dir,
5718                           const char *oldpath, const char *newpath)
5719 {
5720         char *olddir, *newdir;
5721         const char *oldname, *newname;
5722         uint32 mask;
5723
5724         mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5725                 : FILE_NOTIFY_CHANGE_FILE_NAME;
5726
5727         if (!parent_dirname(talloc_tos(), oldpath, &olddir, &oldname)
5728             || !parent_dirname(talloc_tos(), newpath, &newdir, &newname)) {
5729                 TALLOC_FREE(olddir);
5730                 return;
5731         }
5732
5733         if (strcmp(olddir, newdir) == 0) {
5734                 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
5735                 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
5736         }
5737         else {
5738                 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
5739                 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
5740         }
5741         TALLOC_FREE(olddir);
5742         TALLOC_FREE(newdir);
5743
5744         /* this is a strange one. w2k3 gives an additional event for
5745            CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5746            files, but not directories */
5747         if (!is_dir) {
5748                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5749                              FILE_NOTIFY_CHANGE_ATTRIBUTES
5750                              |FILE_NOTIFY_CHANGE_CREATION,
5751                              newpath);
5752         }
5753 }
5754
5755 /****************************************************************************
5756  Rename an open file - given an fsp.
5757 ****************************************************************************/
5758
5759 NTSTATUS rename_internals_fsp(connection_struct *conn,
5760                         files_struct *fsp,
5761                         char *newname,
5762                         const char *newname_last_component,
5763                         uint32 attrs,
5764                         bool replace_if_exists)
5765 {
5766         TALLOC_CTX *ctx = talloc_tos();
5767         SMB_STRUCT_STAT sbuf, sbuf1;
5768         NTSTATUS status = NT_STATUS_OK;
5769         struct share_mode_lock *lck = NULL;
5770         bool dst_exists, old_is_stream, new_is_stream;
5771
5772         ZERO_STRUCT(sbuf);
5773
5774         status = check_name(conn, newname);
5775         if (!NT_STATUS_IS_OK(status)) {
5776                 return status;
5777         }
5778
5779         /* Ensure newname contains a '/' */
5780         if(strrchr_m(newname,'/') == 0) {
5781                 newname = talloc_asprintf(ctx,
5782                                         "./%s",
5783                                         newname);
5784                 if (!newname) {
5785                         return NT_STATUS_NO_MEMORY;
5786                 }
5787         }
5788
5789         /*
5790          * Check for special case with case preserving and not
5791          * case sensitive. If the old last component differs from the original
5792          * last component only by case, then we should allow
5793          * the rename (user is trying to change the case of the
5794          * filename).
5795          */
5796
5797         if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5798                         strequal(newname, fsp->fsp_name)) {
5799                 char *p;
5800                 char *newname_modified_last_component = NULL;
5801
5802                 /*
5803                  * Get the last component of the modified name.
5804                  * Note that we guarantee that newname contains a '/'
5805                  * character above.
5806                  */
5807                 p = strrchr_m(newname,'/');
5808                 newname_modified_last_component = talloc_strdup(ctx,
5809                                                 p+1);
5810                 if (!newname_modified_last_component) {
5811                         return NT_STATUS_NO_MEMORY;
5812                 }
5813
5814                 if(strcsequal(newname_modified_last_component,
5815                               newname_last_component) == False) {
5816                         /*
5817                          * Replace the modified last component with
5818                          * the original.
5819                          */
5820                         *p = '\0'; /* Truncate at the '/' */
5821                         newname = talloc_asprintf(ctx,
5822                                         "%s/%s",
5823                                         newname,
5824                                         newname_last_component);
5825                 }
5826         }
5827
5828         /*
5829          * If the src and dest names are identical - including case,
5830          * don't do the rename, just return success.
5831          */
5832
5833         if (strcsequal(fsp->fsp_name, newname)) {
5834                 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5835                         newname));
5836                 return NT_STATUS_OK;
5837         }
5838
5839         old_is_stream = is_ntfs_stream_name(fsp->fsp_name);
5840         new_is_stream = is_ntfs_stream_name(newname);
5841
5842         /* Return the correct error code if both names aren't streams. */
5843         if (!old_is_stream && new_is_stream) {
5844                 return NT_STATUS_OBJECT_NAME_INVALID;
5845         }
5846
5847         if (old_is_stream && !new_is_stream) {
5848                 return NT_STATUS_INVALID_PARAMETER;
5849         }
5850
5851         /*
5852          * Have vfs_object_exist also fill sbuf1
5853          */
5854         dst_exists = vfs_object_exist(conn, newname, &sbuf1);
5855
5856         if(!replace_if_exists && dst_exists) {
5857                 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5858                         fsp->fsp_name,newname));
5859                 return NT_STATUS_OBJECT_NAME_COLLISION;
5860         }
5861
5862         if (dst_exists) {
5863                 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5864                 files_struct *dst_fsp = file_find_di_first(fileid);
5865                 /* The file can be open when renaming a stream */
5866                 if (dst_fsp && !new_is_stream) {
5867                         DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5868                         return NT_STATUS_ACCESS_DENIED;
5869                 }
5870         }
5871
5872         /* Ensure we have a valid stat struct for the source. */
5873         if (fsp->fh->fd != -1) {
5874                 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
5875                         return map_nt_error_from_unix(errno);
5876                 }
5877         } else {
5878                 int ret = -1;
5879                 if (fsp->posix_open) {
5880                         ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf);
5881                 } else {
5882                         ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf);
5883                 }
5884                 if (ret == -1) {
5885                         return map_nt_error_from_unix(errno);
5886                 }
5887         }
5888
5889         status = can_rename(conn, fsp, attrs, &sbuf);
5890
5891         if (!NT_STATUS_IS_OK(status)) {
5892                 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5893                         nt_errstr(status), fsp->fsp_name,newname));
5894                 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5895                         status = NT_STATUS_ACCESS_DENIED;
5896                 return status;
5897         }
5898
5899         if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5900                 return NT_STATUS_ACCESS_DENIED;
5901         }
5902
5903         lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5904                                   NULL);
5905
5906         /*
5907          * We have the file open ourselves, so not being able to get the
5908          * corresponding share mode lock is a fatal error.
5909          */
5910
5911         SMB_ASSERT(lck != NULL);
5912
5913         if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5914                 uint32 create_options = fsp->fh->private_options;
5915
5916                 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5917                         fsp->fsp_name,newname));
5918
5919                 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5920
5921                 rename_open_files(conn, lck, newname);
5922
5923                 /*
5924                  * A rename acts as a new file create w.r.t. allowing an initial delete
5925                  * on close, probably because in Windows there is a new handle to the
5926                  * new file. If initial delete on close was requested but not
5927                  * originally set, we need to set it here. This is probably not 100% correct,
5928                  * but will work for the CIFSFS client which in non-posix mode
5929                  * depends on these semantics. JRA.
5930                  */
5931
5932                 if (create_options & FILE_DELETE_ON_CLOSE) {
5933                         status = can_set_delete_on_close(fsp, True, 0);
5934
5935                         if (NT_STATUS_IS_OK(status)) {
5936                                 /* Note that here we set the *inital* delete on close flag,
5937                                  * not the regular one. The magic gets handled in close. */
5938                                 fsp->initial_delete_on_close = True;
5939                         }
5940                 }
5941                 TALLOC_FREE(lck);
5942                 return NT_STATUS_OK;
5943         }
5944
5945         TALLOC_FREE(lck);
5946
5947         if (errno == ENOTDIR || errno == EISDIR) {
5948                 status = NT_STATUS_OBJECT_NAME_COLLISION;
5949         } else {
5950                 status = map_nt_error_from_unix(errno);
5951         }
5952
5953         DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5954                 nt_errstr(status), fsp->fsp_name,newname));
5955
5956         return status;
5957 }
5958
5959 /****************************************************************************
5960  The guts of the rename command, split out so it may be called by the NT SMB
5961  code.
5962 ****************************************************************************/
5963
5964 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5965                         connection_struct *conn,
5966                         struct smb_request *req,
5967                         const char *name_in,
5968                         const char *newname_in,
5969                         uint32 attrs,
5970                         bool replace_if_exists,
5971                         bool src_has_wild,
5972                         bool dest_has_wild,
5973                         uint32_t access_mask)
5974 {
5975         struct smb_filename *smb_fname = NULL;
5976         struct smb_filename *smb_fname_new = NULL;
5977         char *directory = NULL;
5978         char *mask = NULL;
5979         char *name = NULL;
5980         char *newname = NULL;
5981         char *p;
5982         int count=0;
5983         NTSTATUS status = NT_STATUS_OK;
5984         struct smb_Dir *dir_hnd = NULL;
5985         const char *dname;
5986         long offset = 0;
5987         int create_options = 0;
5988         bool posix_pathnames = lp_posix_pathnames();
5989
5990         status = unix_convert(ctx, conn, name_in, &smb_fname,
5991                               src_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
5992         if (!NT_STATUS_IS_OK(status)) {
5993                 goto out;
5994         }
5995
5996         status = get_full_smb_filename(ctx, smb_fname, &name);
5997         if (!NT_STATUS_IS_OK(status)) {
5998                 goto out;
5999         }
6000
6001         status = unix_convert(ctx, conn, newname_in, &smb_fname_new,
6002                               (UCF_SAVE_LCOMP |
6003                                (dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0)));
6004         if (!NT_STATUS_IS_OK(status)) {
6005                 goto out;
6006         }
6007
6008         status = get_full_smb_filename(ctx, smb_fname_new, &newname);
6009         if (!NT_STATUS_IS_OK(status)) {
6010                 goto out;
6011         }
6012
6013         /*
6014          * Split the old name into directory and last component
6015          * strings. Note that unix_convert may have stripped off a
6016          * leading ./ from both name and newname if the rename is
6017          * at the root of the share. We need to make sure either both
6018          * name and newname contain a / character or neither of them do
6019          * as this is checked in resolve_wildcards().
6020          */
6021
6022         p = strrchr_m(name,'/');
6023         if (!p) {
6024                 directory = talloc_strdup(ctx, ".");
6025                 if (!directory) {
6026                         status = NT_STATUS_NO_MEMORY;
6027                         goto out;
6028                 }
6029                 mask = name;
6030         } else {
6031                 *p = 0;
6032                 directory = talloc_strdup(ctx, name);
6033                 if (!directory) {
6034                         status = NT_STATUS_NO_MEMORY;
6035                         goto out;
6036                 }
6037                 mask = p+1;
6038                 *p = '/'; /* Replace needed for exceptional test below. */
6039         }
6040
6041         /*
6042          * We should only check the mangled cache
6043          * here if unix_convert failed. This means
6044          * that the path in 'mask' doesn't exist
6045          * on the file system and so we need to look
6046          * for a possible mangle. This patch from
6047          * Tine Smukavec <valentin.smukavec@hermes.si>.
6048          */
6049
6050         if (!VALID_STAT(smb_fname->st) && mangle_is_mangled(mask, conn->params)) {
6051                 char *new_mask = NULL;
6052                 mangle_lookup_name_from_8_3(ctx,
6053                                         mask,
6054                                         &new_mask,
6055                                         conn->params );
6056                 if (new_mask) {
6057                         mask = new_mask;
6058                 }
6059         }
6060
6061         if (!src_has_wild) {
6062                 files_struct *fsp;
6063
6064                 /*
6065                  * No wildcards - just process the one file.
6066                  */
6067                 /* Add a terminating '/' to the directory name. */
6068                 directory = talloc_asprintf_append(directory,
6069                                 "/%s",
6070                                 mask);
6071                 if (!directory) {
6072                         status = NT_STATUS_NO_MEMORY;
6073                         goto out;
6074                 }
6075
6076                 /* Ensure newname contains a '/' also */
6077                 if(strrchr_m(newname,'/') == 0) {
6078                         newname = talloc_asprintf(ctx,
6079                                                 "./%s",
6080                                                 newname);
6081                         if (!newname) {
6082                                 status = NT_STATUS_NO_MEMORY;
6083                                 goto out;
6084                         }
6085                 }
6086
6087                 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6088                           "case_preserve = %d, short case preserve = %d, "
6089                           "directory = %s, newname = %s, "
6090                           "last_component_dest = %s\n",
6091                           conn->case_sensitive, conn->case_preserve,
6092                           conn->short_case_preserve, directory,
6093                           newname, smb_fname_new->original_lcomp));
6094
6095                 /* The dest name still may have wildcards. */
6096                 if (dest_has_wild) {
6097                         char *mod_newname = NULL;
6098                         if (!resolve_wildcards(ctx,
6099                                         directory,newname,&mod_newname)) {
6100                                 DEBUG(6, ("rename_internals: resolve_wildcards "
6101                                         "%s %s failed\n",
6102                                         directory,
6103                                         newname));
6104                                 status = NT_STATUS_NO_MEMORY;
6105                                 goto out;
6106                         }
6107                         newname = mod_newname;
6108                 }
6109
6110                 ZERO_STRUCT(smb_fname->st);
6111                 if (posix_pathnames) {
6112                         SMB_VFS_LSTAT(conn, directory, &smb_fname->st);
6113                 } else {
6114                         SMB_VFS_STAT(conn, directory, &smb_fname->st);
6115                 }
6116
6117                 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6118                         create_options |= FILE_DIRECTORY_FILE;
6119                 }
6120
6121                 status = SMB_VFS_CREATE_FILE(
6122                         conn,                           /* conn */
6123                         req,                            /* req */
6124                         0,                              /* root_dir_fid */
6125                         directory,                      /* fname */
6126                         0,                              /* create_file_flags */
6127                         access_mask,                    /* access_mask */
6128                         (FILE_SHARE_READ |              /* share_access */
6129                             FILE_SHARE_WRITE),
6130                         FILE_OPEN,                      /* create_disposition*/
6131                         create_options,                 /* create_options */
6132                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6133                         0,                              /* oplock_request */
6134                         0,                              /* allocation_size */
6135                         NULL,                           /* sd */
6136                         NULL,                           /* ea_list */
6137                         &fsp,                           /* result */
6138                         NULL,                           /* pinfo */
6139                         &smb_fname->st);                /* psbuf */
6140
6141                 if (!NT_STATUS_IS_OK(status)) {
6142                         DEBUG(3, ("Could not open rename source %s: %s\n",
6143                                   directory, nt_errstr(status)));
6144                         goto out;
6145                 }
6146
6147                 status = rename_internals_fsp(conn, fsp, newname,
6148                                               smb_fname_new->original_lcomp,
6149                                               attrs, replace_if_exists);
6150
6151                 close_file(req, fsp, NORMAL_CLOSE);
6152
6153                 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6154                           nt_errstr(status), directory,newname));
6155
6156                 goto out;
6157         }
6158
6159         /*
6160          * Wildcards - process each file that matches.
6161          */
6162         if (strequal(mask,"????????.???")) {
6163                 mask[0] = '*';
6164                 mask[1] = '\0';
6165         }
6166
6167         status = check_name(conn, directory);
6168         if (!NT_STATUS_IS_OK(status)) {
6169                 goto out;
6170         }
6171
6172         dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, attrs);
6173         if (dir_hnd == NULL) {
6174                 status = map_nt_error_from_unix(errno);
6175                 goto out;
6176         }
6177
6178         status = NT_STATUS_NO_SUCH_FILE;
6179         /*
6180          * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6181          * - gentest fix. JRA
6182          */
6183
6184         while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname->st))) {
6185                 files_struct *fsp = NULL;
6186                 char *fname = NULL;
6187                 char *destname = NULL;
6188                 bool sysdir_entry = False;
6189
6190                 /* Quick check for "." and ".." */
6191                 if (ISDOT(dname) || ISDOTDOT(dname)) {
6192                         if (attrs & aDIR) {
6193                                 sysdir_entry = True;
6194                         } else {
6195                                 continue;
6196                         }
6197                 }
6198
6199                 if (!is_visible_file(conn, directory, dname, &smb_fname->st,
6200                                      False)) {
6201                         continue;
6202                 }
6203
6204                 if(!mask_match(dname, mask, conn->case_sensitive)) {
6205                         continue;
6206                 }
6207
6208                 if (sysdir_entry) {
6209                         status = NT_STATUS_OBJECT_NAME_INVALID;
6210                         break;
6211                 }
6212
6213                 fname = talloc_asprintf(ctx,
6214                                 "%s/%s",
6215                                 directory,
6216                                 dname);
6217                 if (!fname) {
6218                         status = NT_STATUS_NO_MEMORY;
6219                         goto out;
6220                 }
6221
6222                 if (!resolve_wildcards(ctx,
6223                                 fname,newname,&destname)) {
6224                         DEBUG(6, ("resolve_wildcards %s %s failed\n",
6225                                   fname, destname));
6226                         TALLOC_FREE(fname);
6227                         continue;
6228                 }
6229                 if (!destname) {
6230                         status = NT_STATUS_NO_MEMORY;
6231                         goto out;
6232                 }
6233
6234                 ZERO_STRUCT(smb_fname->st);
6235                 if (posix_pathnames) {
6236                         SMB_VFS_LSTAT(conn, fname, &smb_fname->st);
6237                 } else {
6238                         SMB_VFS_STAT(conn, fname, &smb_fname->st);
6239                 }
6240
6241                 create_options = 0;
6242
6243                 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6244                         create_options |= FILE_DIRECTORY_FILE;
6245                 }
6246
6247                 status = SMB_VFS_CREATE_FILE(
6248                         conn,                           /* conn */
6249                         req,                            /* req */
6250                         0,                              /* root_dir_fid */
6251                         fname,                          /* fname */
6252                         0,                              /* create_file_flags */
6253                         access_mask,                    /* access_mask */
6254                         (FILE_SHARE_READ |              /* share_access */
6255                             FILE_SHARE_WRITE),
6256                         FILE_OPEN,                      /* create_disposition*/
6257                         create_options,                 /* create_options */
6258                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6259                         0,                              /* oplock_request */
6260                         0,                              /* allocation_size */
6261                         NULL,                           /* sd */
6262                         NULL,                           /* ea_list */
6263                         &fsp,                           /* result */
6264                         NULL,                           /* pinfo */
6265                         &smb_fname->st);                /* psbuf */
6266
6267                 if (!NT_STATUS_IS_OK(status)) {
6268                         DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6269                                  "returned %s rename %s -> %s\n",
6270                                  nt_errstr(status), directory, newname));
6271                         break;
6272                 }
6273
6274                 status = rename_internals_fsp(conn, fsp, destname, dname,
6275                                               attrs, replace_if_exists);
6276
6277                 close_file(req, fsp, NORMAL_CLOSE);
6278
6279                 if (!NT_STATUS_IS_OK(status)) {
6280                         DEBUG(3, ("rename_internals_fsp returned %s for "
6281                                   "rename %s -> %s\n", nt_errstr(status),
6282                                   directory, newname));
6283                         break;
6284                 }
6285
6286                 count++;
6287
6288                 DEBUG(3,("rename_internals: doing rename on %s -> "
6289                          "%s\n",fname,destname));
6290
6291                 TALLOC_FREE(fname);
6292                 TALLOC_FREE(destname);
6293         }
6294         TALLOC_FREE(dir_hnd);
6295
6296         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6297                 status = map_nt_error_from_unix(errno);
6298         }
6299
6300  out:
6301         TALLOC_FREE(smb_fname);
6302         TALLOC_FREE(smb_fname_new);
6303         return status;
6304 }
6305
6306 /****************************************************************************
6307  Reply to a mv.
6308 ****************************************************************************/
6309
6310 void reply_mv(struct smb_request *req)
6311 {
6312         connection_struct *conn = req->conn;
6313         char *name = NULL;
6314         char *newname = NULL;
6315         const char *p;
6316         uint32 attrs;
6317         NTSTATUS status;
6318         bool src_has_wcard = False;
6319         bool dest_has_wcard = False;
6320         TALLOC_CTX *ctx = talloc_tos();
6321
6322         START_PROFILE(SMBmv);
6323
6324         if (req->wct < 1) {
6325                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6326                 END_PROFILE(SMBmv);
6327                 return;
6328         }
6329
6330         attrs = SVAL(req->vwv+0, 0);
6331
6332         p = (const char *)req->buf + 1;
6333         p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6334                                        &status, &src_has_wcard);
6335         if (!NT_STATUS_IS_OK(status)) {
6336                 reply_nterror(req, status);
6337                 END_PROFILE(SMBmv);
6338                 return;
6339         }
6340         p++;
6341         p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6342                                        &status, &dest_has_wcard);
6343         if (!NT_STATUS_IS_OK(status)) {
6344                 reply_nterror(req, status);
6345                 END_PROFILE(SMBmv);
6346                 return;
6347         }
6348
6349         status = resolve_dfspath_wcard(ctx, conn,
6350                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
6351                                        name,
6352                                        &name,
6353                                        &src_has_wcard);
6354         if (!NT_STATUS_IS_OK(status)) {
6355                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6356                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6357                                         ERRSRV, ERRbadpath);
6358                         END_PROFILE(SMBmv);
6359                         return;
6360                 }
6361                 reply_nterror(req, status);
6362                 END_PROFILE(SMBmv);
6363                 return;
6364         }
6365
6366         status = resolve_dfspath_wcard(ctx, conn,
6367                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
6368                                        newname,
6369                                        &newname,
6370                                        &dest_has_wcard);
6371         if (!NT_STATUS_IS_OK(status)) {
6372                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6373                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6374                                         ERRSRV, ERRbadpath);
6375                         END_PROFILE(SMBmv);
6376                         return;
6377                 }
6378                 reply_nterror(req, status);
6379                 END_PROFILE(SMBmv);
6380                 return;
6381         }
6382
6383         DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
6384
6385         status = rename_internals(ctx, conn, req, name, newname, attrs, False,
6386                                   src_has_wcard, dest_has_wcard, DELETE_ACCESS);
6387         if (!NT_STATUS_IS_OK(status)) {
6388                 if (open_was_deferred(req->mid)) {
6389                         /* We have re-scheduled this call. */
6390                         END_PROFILE(SMBmv);
6391                         return;
6392                 }
6393                 reply_nterror(req, status);
6394                 END_PROFILE(SMBmv);
6395                 return;
6396         }
6397
6398         reply_outbuf(req, 0, 0);
6399
6400         END_PROFILE(SMBmv);
6401         return;
6402 }
6403
6404 /*******************************************************************
6405  Copy a file as part of a reply_copy.
6406 ******************************************************************/
6407
6408 /*
6409  * TODO: check error codes on all callers
6410  */
6411
6412 NTSTATUS copy_file(TALLOC_CTX *ctx,
6413                         connection_struct *conn,
6414                         const char *src,
6415                         const char *dest1,
6416                         int ofun,
6417                         int count,
6418                         bool target_is_directory)
6419 {
6420         SMB_STRUCT_STAT src_sbuf, sbuf2;
6421         SMB_OFF_T ret=-1;
6422         files_struct *fsp1,*fsp2;
6423         char *dest = NULL;
6424         uint32 dosattrs;
6425         uint32 new_create_disposition;
6426         NTSTATUS status;
6427
6428         dest = talloc_strdup(ctx, dest1);
6429         if (!dest) {
6430                 return NT_STATUS_NO_MEMORY;
6431         }
6432         if (target_is_directory) {
6433                 const char *p = strrchr_m(src,'/');
6434                 if (p) {
6435                         p++;
6436                 } else {
6437                         p = src;
6438                 }
6439                 dest = talloc_asprintf_append(dest,
6440                                 "/%s",
6441                                 p);
6442                 if (!dest) {
6443                         return NT_STATUS_NO_MEMORY;
6444                 }
6445         }
6446
6447         if (!vfs_file_exist(conn,src,&src_sbuf)) {
6448                 TALLOC_FREE(dest);
6449                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6450         }
6451
6452         if (!target_is_directory && count) {
6453                 new_create_disposition = FILE_OPEN;
6454         } else {
6455                 if (!map_open_params_to_ntcreate(dest1,0,ofun,
6456                                 NULL, NULL, &new_create_disposition, NULL)) {
6457                         TALLOC_FREE(dest);
6458                         return NT_STATUS_INVALID_PARAMETER;
6459                 }
6460         }
6461
6462         status = SMB_VFS_CREATE_FILE(
6463                 conn,                                   /* conn */
6464                 NULL,                                   /* req */
6465                 0,                                      /* root_dir_fid */
6466                 src,                                    /* fname */
6467                 0,                                      /* create_file_flags */
6468                 FILE_GENERIC_READ,                      /* access_mask */
6469                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
6470                 FILE_OPEN,                              /* create_disposition*/
6471                 0,                                      /* create_options */
6472                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
6473                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
6474                 0,                                      /* allocation_size */
6475                 NULL,                                   /* sd */
6476                 NULL,                                   /* ea_list */
6477                 &fsp1,                                  /* result */
6478                 NULL,                                   /* pinfo */
6479                 &src_sbuf);                             /* psbuf */
6480
6481         if (!NT_STATUS_IS_OK(status)) {
6482                 TALLOC_FREE(dest);
6483                 return status;
6484         }
6485
6486         dosattrs = dos_mode(conn, src, &src_sbuf);
6487         if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
6488                 ZERO_STRUCTP(&sbuf2);
6489         }
6490
6491         status = SMB_VFS_CREATE_FILE(
6492                 conn,                                   /* conn */
6493                 NULL,                                   /* req */
6494                 0,                                      /* root_dir_fid */
6495                 dest,                                   /* fname */
6496                 0,                                      /* create_file_flags */
6497                 FILE_GENERIC_WRITE,                     /* access_mask */
6498                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
6499                 new_create_disposition,                 /* create_disposition*/
6500                 0,                                      /* create_options */
6501                 dosattrs,                               /* file_attributes */
6502                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
6503                 0,                                      /* allocation_size */
6504                 NULL,                                   /* sd */
6505                 NULL,                                   /* ea_list */
6506                 &fsp2,                                  /* result */
6507                 NULL,                                   /* pinfo */
6508                 &sbuf2);                                /* psbuf */
6509
6510         TALLOC_FREE(dest);
6511
6512         if (!NT_STATUS_IS_OK(status)) {
6513                 close_file(NULL, fsp1, ERROR_CLOSE);
6514                 return status;
6515         }
6516
6517         if ((ofun&3) == 1) {
6518                 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6519                         DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6520                         /*
6521                          * Stop the copy from occurring.
6522                          */
6523                         ret = -1;
6524                         src_sbuf.st_ex_size = 0;
6525                 }
6526         }
6527
6528         if (src_sbuf.st_ex_size) {
6529                 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_ex_size);
6530         }
6531
6532         close_file(NULL, fsp1, NORMAL_CLOSE);
6533
6534         /* Ensure the modtime is set correctly on the destination file. */
6535         set_close_write_time(fsp2, src_sbuf.st_ex_mtime);
6536
6537         /*
6538          * As we are opening fsp1 read-only we only expect
6539          * an error on close on fsp2 if we are out of space.
6540          * Thus we don't look at the error return from the
6541          * close of fsp1.
6542          */
6543         status = close_file(NULL, fsp2, NORMAL_CLOSE);
6544
6545         if (!NT_STATUS_IS_OK(status)) {
6546                 return status;
6547         }
6548
6549         if (ret != (SMB_OFF_T)src_sbuf.st_ex_size) {
6550                 return NT_STATUS_DISK_FULL;
6551         }
6552
6553         return NT_STATUS_OK;
6554 }
6555
6556 /****************************************************************************
6557  Reply to a file copy.
6558 ****************************************************************************/
6559
6560 void reply_copy(struct smb_request *req)
6561 {
6562         connection_struct *conn = req->conn;
6563         struct smb_filename *smb_fname = NULL;
6564         struct smb_filename *smb_fname_new = NULL;
6565         char *name = NULL;
6566         char *newname = NULL;
6567         char *directory = NULL;
6568         const char *mask = NULL;
6569         const char mask_star[] = "*";
6570         const char *p;
6571         int count=0;
6572         int error = ERRnoaccess;
6573         int err = 0;
6574         int tid2;
6575         int ofun;
6576         int flags;
6577         bool target_is_directory=False;
6578         bool source_has_wild = False;
6579         bool dest_has_wild = False;
6580         NTSTATUS status;
6581         TALLOC_CTX *ctx = talloc_tos();
6582
6583         START_PROFILE(SMBcopy);
6584
6585         if (req->wct < 3) {
6586                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6587                 goto out;
6588         }
6589
6590         tid2 = SVAL(req->vwv+0, 0);
6591         ofun = SVAL(req->vwv+1, 0);
6592         flags = SVAL(req->vwv+2, 0);
6593
6594         p = (const char *)req->buf;
6595         p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6596                                        &status, &source_has_wild);
6597         if (!NT_STATUS_IS_OK(status)) {
6598                 reply_nterror(req, status);
6599                 goto out;
6600         }
6601         p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6602                                        &status, &dest_has_wild);
6603         if (!NT_STATUS_IS_OK(status)) {
6604                 reply_nterror(req, status);
6605                 goto out;
6606         }
6607
6608         DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
6609
6610         if (tid2 != conn->cnum) {
6611                 /* can't currently handle inter share copies XXXX */
6612                 DEBUG(3,("Rejecting inter-share copy\n"));
6613                 reply_doserror(req, ERRSRV, ERRinvdevice);
6614                 goto out;
6615         }
6616
6617         status = resolve_dfspath_wcard(ctx, conn,
6618                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
6619                                        name,
6620                                        &name,
6621                                        &source_has_wild);
6622         if (!NT_STATUS_IS_OK(status)) {
6623                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6624                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6625                                         ERRSRV, ERRbadpath);
6626                         goto out;
6627                 }
6628                 reply_nterror(req, status);
6629                 goto out;
6630         }
6631
6632         status = resolve_dfspath_wcard(ctx, conn,
6633                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
6634                                        newname,
6635                                        &newname,
6636                                        &dest_has_wild);
6637         if (!NT_STATUS_IS_OK(status)) {
6638                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6639                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6640                                         ERRSRV, ERRbadpath);
6641                         goto out;
6642                 }
6643                 reply_nterror(req, status);
6644                 goto out;
6645         }
6646
6647         status = unix_convert(ctx, conn, name, &smb_fname,
6648                               source_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
6649         if (!NT_STATUS_IS_OK(status)) {
6650                 reply_nterror(req, status);
6651                 goto out;
6652         }
6653
6654         status = get_full_smb_filename(ctx, smb_fname, &name);
6655         if (!NT_STATUS_IS_OK(status)) {
6656                 reply_nterror(req, status);
6657                 goto out;
6658         }
6659
6660         status = unix_convert(ctx, conn, newname, &smb_fname_new,
6661                               dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
6662         if (!NT_STATUS_IS_OK(status)) {
6663                 reply_nterror(req, status);
6664                 goto out;
6665         }
6666
6667         status = get_full_smb_filename(ctx, smb_fname_new, &newname);
6668         if (!NT_STATUS_IS_OK(status)) {
6669                 reply_nterror(req, status);
6670                 goto out;
6671         }
6672
6673         target_is_directory = VALID_STAT_OF_DIR(smb_fname_new->st);
6674
6675         if ((flags&1) && target_is_directory) {
6676                 reply_doserror(req, ERRDOS, ERRbadfile);
6677                 goto out;
6678         }
6679
6680         if ((flags&2) && !target_is_directory) {
6681                 reply_doserror(req, ERRDOS, ERRbadpath);
6682                 goto out;
6683         }
6684
6685         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname->st)) {
6686                 /* wants a tree copy! XXXX */
6687                 DEBUG(3,("Rejecting tree copy\n"));
6688                 reply_doserror(req, ERRSRV, ERRerror);
6689                 goto out;
6690         }
6691
6692         p = strrchr_m(name,'/');
6693         if (p != NULL) {
6694                 directory = talloc_strndup(ctx, name, PTR_DIFF(p, name));
6695                 mask = p+1;
6696         } else {
6697                 directory = talloc_strdup(ctx, "./");
6698                 mask = name;
6699         }
6700
6701         if (!directory) {
6702                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6703                 goto out;
6704         }
6705
6706         /*
6707          * We should only check the mangled cache
6708          * here if unix_convert failed. This means
6709          * that the path in 'mask' doesn't exist
6710          * on the file system and so we need to look
6711          * for a possible mangle. This patch from
6712          * Tine Smukavec <valentin.smukavec@hermes.si>.
6713          */
6714
6715         if (!VALID_STAT(smb_fname->st) &&
6716             mangle_is_mangled(mask, conn->params)) {
6717                 char *new_mask = NULL;
6718                 mangle_lookup_name_from_8_3(ctx,
6719                                         mask,
6720                                         &new_mask,
6721                                         conn->params );
6722                 if (new_mask) {
6723                         mask = new_mask;
6724                 }
6725         }
6726
6727         if (!source_has_wild) {
6728                 directory = talloc_asprintf_append(directory,
6729                                 "/%s",
6730                                 mask);
6731                 if (dest_has_wild) {
6732                         char *mod_newname = NULL;
6733                         if (!resolve_wildcards(ctx,
6734                                         directory,newname,&mod_newname)) {
6735                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6736                                 goto out;
6737                         }
6738                         newname = mod_newname;
6739                 }
6740
6741                 status = check_name(conn, directory);
6742                 if (!NT_STATUS_IS_OK(status)) {
6743                         reply_nterror(req, status);
6744                         goto out;
6745                 }
6746
6747                 status = check_name(conn, newname);
6748                 if (!NT_STATUS_IS_OK(status)) {
6749                         reply_nterror(req, status);
6750                         goto out;
6751                 }
6752
6753                 status = copy_file(ctx,conn,directory,newname,ofun,
6754                                 count,target_is_directory);
6755
6756                 if(!NT_STATUS_IS_OK(status)) {
6757                         reply_nterror(req, status);
6758                         goto out;
6759                 } else {
6760                         count++;
6761                 }
6762         } else {
6763                 struct smb_Dir *dir_hnd = NULL;
6764                 const char *dname = NULL;
6765                 long offset = 0;
6766
6767                 if (strequal(mask,"????????.???")) {
6768                         mask = mask_star;
6769                 }
6770
6771                 status = check_name(conn, directory);
6772                 if (!NT_STATUS_IS_OK(status)) {
6773                         reply_nterror(req, status);
6774                         goto out;
6775                 }
6776
6777                 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, 0);
6778                 if (dir_hnd == NULL) {
6779                         status = map_nt_error_from_unix(errno);
6780                         reply_nterror(req, status);
6781                         goto out;
6782                 }
6783
6784                 error = ERRbadfile;
6785
6786                 while ((dname = ReadDirName(dir_hnd, &offset,
6787                                             &smb_fname->st))) {
6788                         char *destname = NULL;
6789                         char *fname = NULL;
6790
6791                         if (ISDOT(dname) || ISDOTDOT(dname)) {
6792                                 continue;
6793                         }
6794
6795                         if (!is_visible_file(conn, directory, dname,
6796                                              &smb_fname->st, False)) {
6797                                 continue;
6798                         }
6799
6800                         if(!mask_match(dname, mask, conn->case_sensitive)) {
6801                                 continue;
6802                         }
6803
6804                         error = ERRnoaccess;
6805                         fname = talloc_asprintf(ctx,
6806                                         "%s/%s",
6807                                         directory,
6808                                         dname);
6809                         if (!fname) {
6810                                 TALLOC_FREE(dir_hnd);
6811                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6812                                 goto out;
6813                         }
6814
6815                         if (!resolve_wildcards(ctx,
6816                                         fname,newname,&destname)) {
6817                                 continue;
6818                         }
6819                         if (!destname) {
6820                                 TALLOC_FREE(dir_hnd);
6821                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6822                                 goto out;
6823                         }
6824
6825                         status = check_name(conn, fname);
6826                         if (!NT_STATUS_IS_OK(status)) {
6827                                 TALLOC_FREE(dir_hnd);
6828                                 reply_nterror(req, status);
6829                                 goto out;
6830                         }
6831
6832                         status = check_name(conn, destname);
6833                         if (!NT_STATUS_IS_OK(status)) {
6834                                 TALLOC_FREE(dir_hnd);
6835                                 reply_nterror(req, status);
6836                                 goto out;
6837                         }
6838
6839                         DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
6840
6841                         status = copy_file(ctx,conn,fname,destname,ofun,
6842                                         count,target_is_directory);
6843                         if (NT_STATUS_IS_OK(status)) {
6844                                 count++;
6845                         }
6846                         TALLOC_FREE(fname);
6847                         TALLOC_FREE(destname);
6848                 }
6849                 TALLOC_FREE(dir_hnd);
6850         }
6851
6852         if (count == 0) {
6853                 if(err) {
6854                         /* Error on close... */
6855                         errno = err;
6856                         reply_unixerror(req, ERRHRD, ERRgeneral);
6857                         goto out;
6858                 }
6859
6860                 reply_doserror(req, ERRDOS, error);
6861                 goto out;
6862         }
6863
6864         reply_outbuf(req, 1, 0);
6865         SSVAL(req->outbuf,smb_vwv0,count);
6866  out:
6867         TALLOC_FREE(smb_fname);
6868         TALLOC_FREE(smb_fname_new);
6869         END_PROFILE(SMBcopy);
6870         return;
6871 }
6872
6873 #undef DBGC_CLASS
6874 #define DBGC_CLASS DBGC_LOCKING
6875
6876 /****************************************************************************
6877  Get a lock pid, dealing with large count requests.
6878 ****************************************************************************/
6879
6880 uint32 get_lock_pid(const uint8_t *data, int data_offset,
6881                     bool large_file_format)
6882 {
6883         if(!large_file_format)
6884                 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
6885         else
6886                 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6887 }
6888
6889 /****************************************************************************
6890  Get a lock count, dealing with large count requests.
6891 ****************************************************************************/
6892
6893 uint64_t get_lock_count(const uint8_t *data, int data_offset,
6894                         bool large_file_format)
6895 {
6896         uint64_t count = 0;
6897
6898         if(!large_file_format) {
6899                 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6900         } else {
6901
6902 #if defined(HAVE_LONGLONG)
6903                 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6904                         ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6905 #else /* HAVE_LONGLONG */
6906
6907                 /*
6908                  * NT4.x seems to be broken in that it sends large file (64 bit)
6909                  * lockingX calls even if the CAP_LARGE_FILES was *not*
6910                  * negotiated. For boxes without large unsigned ints truncate the
6911                  * lock count by dropping the top 32 bits.
6912                  */
6913
6914                 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6915                         DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6916                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6917                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6918                                 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6919                 }
6920
6921                 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6922 #endif /* HAVE_LONGLONG */
6923         }
6924
6925         return count;
6926 }
6927
6928 #if !defined(HAVE_LONGLONG)
6929 /****************************************************************************
6930  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6931 ****************************************************************************/
6932
6933 static uint32 map_lock_offset(uint32 high, uint32 low)
6934 {
6935         unsigned int i;
6936         uint32 mask = 0;
6937         uint32 highcopy = high;
6938
6939         /*
6940          * Try and find out how many significant bits there are in high.
6941          */
6942
6943         for(i = 0; highcopy; i++)
6944                 highcopy >>= 1;
6945
6946         /*
6947          * We use 31 bits not 32 here as POSIX
6948          * lock offsets may not be negative.
6949          */
6950
6951         mask = (~0) << (31 - i);
6952
6953         if(low & mask)
6954                 return 0; /* Fail. */
6955
6956         high <<= (31 - i);
6957
6958         return (high|low);
6959 }
6960 #endif /* !defined(HAVE_LONGLONG) */
6961
6962 /****************************************************************************
6963  Get a lock offset, dealing with large offset requests.
6964 ****************************************************************************/
6965
6966 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
6967                          bool large_file_format, bool *err)
6968 {
6969         uint64_t offset = 0;
6970
6971         *err = False;
6972
6973         if(!large_file_format) {
6974                 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
6975         } else {
6976
6977 #if defined(HAVE_LONGLONG)
6978                 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
6979                                 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
6980 #else /* HAVE_LONGLONG */
6981
6982                 /*
6983                  * NT4.x seems to be broken in that it sends large file (64 bit)
6984                  * lockingX calls even if the CAP_LARGE_FILES was *not*
6985                  * negotiated. For boxes without large unsigned ints mangle the
6986                  * lock offset by mapping the top 32 bits onto the lower 32.
6987                  */
6988
6989                 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
6990                         uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6991                         uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
6992                         uint32 new_low = 0;
6993
6994                         if((new_low = map_lock_offset(high, low)) == 0) {
6995                                 *err = True;
6996                                 return (uint64_t)-1;
6997                         }
6998
6999                         DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7000                                 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7001                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7002                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7003                 }
7004
7005                 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7006 #endif /* HAVE_LONGLONG */
7007         }
7008
7009         return offset;
7010 }
7011
7012 /****************************************************************************
7013  Reply to a lockingX request.
7014 ****************************************************************************/
7015
7016 void reply_lockingX(struct smb_request *req)
7017 {
7018         connection_struct *conn = req->conn;
7019         files_struct *fsp;
7020         unsigned char locktype;
7021         unsigned char oplocklevel;
7022         uint16 num_ulocks;
7023         uint16 num_locks;
7024         uint64_t count = 0, offset = 0;
7025         uint32 lock_pid;
7026         int32 lock_timeout;
7027         int i;
7028         const uint8_t *data;
7029         bool large_file_format;
7030         bool err;
7031         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7032
7033         START_PROFILE(SMBlockingX);
7034
7035         if (req->wct < 8) {
7036                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7037                 END_PROFILE(SMBlockingX);
7038                 return;
7039         }
7040
7041         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7042         locktype = CVAL(req->vwv+3, 0);
7043         oplocklevel = CVAL(req->vwv+3, 1);
7044         num_ulocks = SVAL(req->vwv+6, 0);
7045         num_locks = SVAL(req->vwv+7, 0);
7046         lock_timeout = IVAL(req->vwv+4, 0);
7047         large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7048
7049         if (!check_fsp(conn, req, fsp)) {
7050                 END_PROFILE(SMBlockingX);
7051                 return;
7052         }
7053
7054         data = req->buf;
7055
7056         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7057                 /* we don't support these - and CANCEL_LOCK makes w2k
7058                    and XP reboot so I don't really want to be
7059                    compatible! (tridge) */
7060                 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
7061                 END_PROFILE(SMBlockingX);
7062                 return;
7063         }
7064
7065         /* Check if this is an oplock break on a file
7066            we have granted an oplock on.
7067         */
7068         if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7069                 /* Client can insist on breaking to none. */
7070                 bool break_to_none = (oplocklevel == 0);
7071                 bool result;
7072
7073                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7074                          "for fnum = %d\n", (unsigned int)oplocklevel,
7075                          fsp->fnum ));
7076
7077                 /*
7078                  * Make sure we have granted an exclusive or batch oplock on
7079                  * this file.
7080                  */
7081
7082                 if (fsp->oplock_type == 0) {
7083
7084                         /* The Samba4 nbench simulator doesn't understand
7085                            the difference between break to level2 and break
7086                            to none from level2 - it sends oplock break
7087                            replies in both cases. Don't keep logging an error
7088                            message here - just ignore it. JRA. */
7089
7090                         DEBUG(5,("reply_lockingX: Error : oplock break from "
7091                                  "client for fnum = %d (oplock=%d) and no "
7092                                  "oplock granted on this file (%s).\n",
7093                                  fsp->fnum, fsp->oplock_type, fsp->fsp_name));
7094
7095                         /* if this is a pure oplock break request then don't
7096                          * send a reply */
7097                         if (num_locks == 0 && num_ulocks == 0) {
7098                                 END_PROFILE(SMBlockingX);
7099                                 return;
7100                         } else {
7101                                 END_PROFILE(SMBlockingX);
7102                                 reply_doserror(req, ERRDOS, ERRlock);
7103                                 return;
7104                         }
7105                 }
7106
7107                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7108                     (break_to_none)) {
7109                         result = remove_oplock(fsp);
7110                 } else {
7111                         result = downgrade_oplock(fsp);
7112                 }
7113
7114                 if (!result) {
7115                         DEBUG(0, ("reply_lockingX: error in removing "
7116                                   "oplock on file %s\n", fsp->fsp_name));
7117                         /* Hmmm. Is this panic justified? */
7118                         smb_panic("internal tdb error");
7119                 }
7120
7121                 reply_to_oplock_break_requests(fsp);
7122
7123                 /* if this is a pure oplock break request then don't send a
7124                  * reply */
7125                 if (num_locks == 0 && num_ulocks == 0) {
7126                         /* Sanity check - ensure a pure oplock break is not a
7127                            chained request. */
7128                         if(CVAL(req->vwv+0, 0) != 0xff)
7129                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
7130                                          "break is a chained %d request !\n",
7131                                          (unsigned int)CVAL(req->vwv+0, 0)));
7132                         END_PROFILE(SMBlockingX);
7133                         return;
7134                 }
7135         }
7136
7137         if (req->buflen <
7138             (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7139                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7140                 END_PROFILE(SMBlockingX);
7141                 return;
7142         }
7143
7144         /* Data now points at the beginning of the list
7145            of smb_unlkrng structs */
7146         for(i = 0; i < (int)num_ulocks; i++) {
7147                 lock_pid = get_lock_pid( data, i, large_file_format);
7148                 count = get_lock_count( data, i, large_file_format);
7149                 offset = get_lock_offset( data, i, large_file_format, &err);
7150
7151                 /*
7152                  * There is no error code marked "stupid client bug".... :-).
7153                  */
7154                 if(err) {
7155                         END_PROFILE(SMBlockingX);
7156                         reply_doserror(req, ERRDOS, ERRnoaccess);
7157                         return;
7158                 }
7159
7160                 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
7161                           "pid %u, file %s\n", (double)offset, (double)count,
7162                           (unsigned int)lock_pid, fsp->fsp_name ));
7163
7164                 status = do_unlock(smbd_messaging_context(),
7165                                 fsp,
7166                                 lock_pid,
7167                                 count,
7168                                 offset,
7169                                 WINDOWS_LOCK);
7170
7171                 DEBUG(10, ("reply_lockingX: unlock returned %s\n",
7172                     nt_errstr(status)));
7173
7174                 if (NT_STATUS_V(status)) {
7175                         END_PROFILE(SMBlockingX);
7176                         reply_nterror(req, status);
7177                         return;
7178                 }
7179         }
7180
7181         /* Setup the timeout in seconds. */
7182
7183         if (!lp_blocking_locks(SNUM(conn))) {
7184                 lock_timeout = 0;
7185         }
7186
7187         /* Now do any requested locks */
7188         data += ((large_file_format ? 20 : 10)*num_ulocks);
7189
7190         /* Data now points at the beginning of the list
7191            of smb_lkrng structs */
7192
7193         for(i = 0; i < (int)num_locks; i++) {
7194                 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
7195                                 READ_LOCK:WRITE_LOCK);
7196                 lock_pid = get_lock_pid( data, i, large_file_format);
7197                 count = get_lock_count( data, i, large_file_format);
7198                 offset = get_lock_offset( data, i, large_file_format, &err);
7199
7200                 /*
7201                  * There is no error code marked "stupid client bug".... :-).
7202                  */
7203                 if(err) {
7204                         END_PROFILE(SMBlockingX);
7205                         reply_doserror(req, ERRDOS, ERRnoaccess);
7206                         return;
7207                 }
7208
7209                 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
7210                           "%u, file %s timeout = %d\n", (double)offset,
7211                           (double)count, (unsigned int)lock_pid,
7212                           fsp->fsp_name, (int)lock_timeout ));
7213
7214                 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7215                         struct blocking_lock_record *blr = NULL;
7216
7217                         if (lp_blocking_locks(SNUM(conn))) {
7218
7219                                 /* Schedule a message to ourselves to
7220                                    remove the blocking lock record and
7221                                    return the right error. */
7222
7223                                 blr = blocking_lock_cancel(fsp,
7224                                                 lock_pid,
7225                                                 offset,
7226                                                 count,
7227                                                 WINDOWS_LOCK,
7228                                                 locktype,
7229                                                 NT_STATUS_FILE_LOCK_CONFLICT);
7230                                 if (blr == NULL) {
7231                                         END_PROFILE(SMBlockingX);
7232                                         reply_nterror(
7233                                                 req,
7234                                                 NT_STATUS_DOS(
7235                                                         ERRDOS,
7236                                                         ERRcancelviolation));
7237                                         return;
7238                                 }
7239                         }
7240                         /* Remove a matching pending lock. */
7241                         status = do_lock_cancel(fsp,
7242                                                 lock_pid,
7243                                                 count,
7244                                                 offset,
7245                                                 WINDOWS_LOCK,
7246                                                 blr);
7247                 } else {
7248                         bool blocking_lock = lock_timeout ? True : False;
7249                         bool defer_lock = False;
7250                         struct byte_range_lock *br_lck;
7251                         uint32 block_smbpid;
7252
7253                         br_lck = do_lock(smbd_messaging_context(),
7254                                         fsp,
7255                                         lock_pid,
7256                                         count,
7257                                         offset, 
7258                                         lock_type,
7259                                         WINDOWS_LOCK,
7260                                         blocking_lock,
7261                                         &status,
7262                                         &block_smbpid,
7263                                         NULL);
7264
7265                         if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7266                                 /* Windows internal resolution for blocking locks seems
7267                                    to be about 200ms... Don't wait for less than that. JRA. */
7268                                 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
7269                                         lock_timeout = lp_lock_spin_time();
7270                                 }
7271                                 defer_lock = True;
7272                         }
7273
7274                         /* This heuristic seems to match W2K3 very well. If a
7275                            lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7276                            it pretends we asked for a timeout of between 150 - 300 milliseconds as
7277                            far as I can tell. Replacement for do_lock_spin(). JRA. */
7278
7279                         if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
7280                                         NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
7281                                 defer_lock = True;
7282                                 lock_timeout = lp_lock_spin_time();
7283                         }
7284
7285                         if (br_lck && defer_lock) {
7286                                 /*
7287                                  * A blocking lock was requested. Package up
7288                                  * this smb into a queued request and push it
7289                                  * onto the blocking lock queue.
7290                                  */
7291                                 if(push_blocking_lock_request(br_lck,
7292                                                         req,
7293                                                         fsp,
7294                                                         lock_timeout,
7295                                                         i,
7296                                                         lock_pid,
7297                                                         lock_type,
7298                                                         WINDOWS_LOCK,
7299                                                         offset,
7300                                                         count,
7301                                                         block_smbpid)) {
7302                                         TALLOC_FREE(br_lck);
7303                                         END_PROFILE(SMBlockingX);
7304                                         return;
7305                                 }
7306                         }
7307
7308                         TALLOC_FREE(br_lck);
7309                 }
7310
7311                 if (NT_STATUS_V(status)) {
7312                         END_PROFILE(SMBlockingX);
7313                         reply_nterror(req, status);
7314                         return;
7315                 }
7316         }
7317
7318         /* If any of the above locks failed, then we must unlock
7319            all of the previous locks (X/Open spec). */
7320
7321         if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
7322                         (i != num_locks) &&
7323                         (num_locks != 0)) {
7324                 /*
7325                  * Ensure we don't do a remove on the lock that just failed,
7326                  * as under POSIX rules, if we have a lock already there, we
7327                  * will delete it (and we shouldn't) .....
7328                  */
7329                 for(i--; i >= 0; i--) {
7330                         lock_pid = get_lock_pid( data, i, large_file_format);
7331                         count = get_lock_count( data, i, large_file_format);
7332                         offset = get_lock_offset( data, i, large_file_format,
7333                                                   &err);
7334
7335                         /*
7336                          * There is no error code marked "stupid client
7337                          * bug".... :-).
7338                          */
7339                         if(err) {
7340                                 END_PROFILE(SMBlockingX);
7341                                 reply_doserror(req, ERRDOS, ERRnoaccess);
7342                                 return;
7343                         }
7344
7345                         do_unlock(smbd_messaging_context(),
7346                                 fsp,
7347                                 lock_pid,
7348                                 count,
7349                                 offset,
7350                                 WINDOWS_LOCK);
7351                 }
7352                 END_PROFILE(SMBlockingX);
7353                 reply_nterror(req, status);
7354                 return;
7355         }
7356
7357         reply_outbuf(req, 2, 0);
7358
7359         DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7360                   fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7361
7362         END_PROFILE(SMBlockingX);
7363         chain_reply(req);
7364 }
7365
7366 #undef DBGC_CLASS
7367 #define DBGC_CLASS DBGC_ALL
7368
7369 /****************************************************************************
7370  Reply to a SMBreadbmpx (read block multiplex) request.
7371  Always reply with an error, if someone has a platform really needs this,
7372  please contact vl@samba.org
7373 ****************************************************************************/
7374
7375 void reply_readbmpx(struct smb_request *req)
7376 {
7377         START_PROFILE(SMBreadBmpx);
7378         reply_doserror(req, ERRSRV, ERRuseSTD);
7379         END_PROFILE(SMBreadBmpx);
7380         return;
7381 }
7382
7383 /****************************************************************************
7384  Reply to a SMBreadbs (read block multiplex secondary) request.
7385  Always reply with an error, if someone has a platform really needs this,
7386  please contact vl@samba.org
7387 ****************************************************************************/
7388
7389 void reply_readbs(struct smb_request *req)
7390 {
7391         START_PROFILE(SMBreadBs);
7392         reply_doserror(req, ERRSRV, ERRuseSTD);
7393         END_PROFILE(SMBreadBs);
7394         return;
7395 }
7396
7397 /****************************************************************************
7398  Reply to a SMBsetattrE.
7399 ****************************************************************************/
7400
7401 void reply_setattrE(struct smb_request *req)
7402 {
7403         connection_struct *conn = req->conn;
7404         struct smb_file_time ft;
7405         files_struct *fsp;
7406         SMB_STRUCT_STAT sbuf;
7407         NTSTATUS status;
7408
7409         START_PROFILE(SMBsetattrE);
7410         ZERO_STRUCT(ft);
7411
7412         if (req->wct < 7) {
7413                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7414                 END_PROFILE(SMBsetattrE);
7415                 return;
7416         }
7417
7418         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7419
7420         if(!fsp || (fsp->conn != conn)) {
7421                 reply_doserror(req, ERRDOS, ERRbadfid);
7422                 END_PROFILE(SMBsetattrE);
7423                 return;
7424         }
7425
7426
7427         /*
7428          * Convert the DOS times into unix times.
7429          */
7430
7431         ft.atime = convert_time_t_to_timespec(
7432             srv_make_unix_date2(req->vwv+3));
7433         ft.mtime = convert_time_t_to_timespec(
7434             srv_make_unix_date2(req->vwv+5));
7435         ft.create_time = convert_time_t_to_timespec(
7436             srv_make_unix_date2(req->vwv+1));
7437
7438         reply_outbuf(req, 0, 0);
7439
7440         /* 
7441          * Patch from Ray Frush <frush@engr.colostate.edu>
7442          * Sometimes times are sent as zero - ignore them.
7443          */
7444
7445         /* Ensure we have a valid stat struct for the source. */
7446         if (fsp->fh->fd != -1) {
7447                 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
7448                         status = map_nt_error_from_unix(errno);
7449                         reply_nterror(req, status);
7450                         END_PROFILE(SMBsetattrE);
7451                         return;
7452                 }
7453         } else {
7454                 int ret = -1;
7455
7456                 if (fsp->posix_open) {
7457                         ret = SMB_VFS_LSTAT(conn, fsp->fsp_name, &sbuf);
7458                 } else {
7459                         ret = SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf);
7460                 }
7461                 if (ret == -1) {
7462                         status = map_nt_error_from_unix(errno);
7463                         reply_nterror(req, status);
7464                         END_PROFILE(SMBsetattrE);
7465                         return;
7466                 }
7467         }
7468
7469         status = smb_set_file_time(conn, fsp, fsp->fsp_name,
7470                                    &sbuf, &ft, true);
7471         if (!NT_STATUS_IS_OK(status)) {
7472                 reply_doserror(req, ERRDOS, ERRnoaccess);
7473                 END_PROFILE(SMBsetattrE);
7474                 return;
7475         }
7476
7477         DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7478                " createtime=%u\n",
7479                 fsp->fnum,
7480                 (unsigned int)ft.atime.tv_sec,
7481                 (unsigned int)ft.mtime.tv_sec,
7482                 (unsigned int)ft.create_time.tv_sec
7483                 ));
7484
7485         END_PROFILE(SMBsetattrE);
7486         return;
7487 }
7488
7489
7490 /* Back from the dead for OS/2..... JRA. */
7491
7492 /****************************************************************************
7493  Reply to a SMBwritebmpx (write block multiplex primary) request.
7494  Always reply with an error, if someone has a platform really needs this,
7495  please contact vl@samba.org
7496 ****************************************************************************/
7497
7498 void reply_writebmpx(struct smb_request *req)
7499 {
7500         START_PROFILE(SMBwriteBmpx);
7501         reply_doserror(req, ERRSRV, ERRuseSTD);
7502         END_PROFILE(SMBwriteBmpx);
7503         return;
7504 }
7505
7506 /****************************************************************************
7507  Reply to a SMBwritebs (write block multiplex secondary) request.
7508  Always reply with an error, if someone has a platform really needs this,
7509  please contact vl@samba.org
7510 ****************************************************************************/
7511
7512 void reply_writebs(struct smb_request *req)
7513 {
7514         START_PROFILE(SMBwriteBs);
7515         reply_doserror(req, ERRSRV, ERRuseSTD);
7516         END_PROFILE(SMBwriteBs);
7517         return;
7518 }
7519
7520 /****************************************************************************
7521  Reply to a SMBgetattrE.
7522 ****************************************************************************/
7523
7524 void reply_getattrE(struct smb_request *req)
7525 {
7526         connection_struct *conn = req->conn;
7527         SMB_STRUCT_STAT sbuf;
7528         int mode;
7529         files_struct *fsp;
7530         struct timespec create_ts;
7531
7532         START_PROFILE(SMBgetattrE);
7533
7534         if (req->wct < 1) {
7535                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7536                 END_PROFILE(SMBgetattrE);
7537                 return;
7538         }
7539
7540         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7541
7542         if(!fsp || (fsp->conn != conn)) {
7543                 reply_doserror(req, ERRDOS, ERRbadfid);
7544                 END_PROFILE(SMBgetattrE);
7545                 return;
7546         }
7547
7548         /* Do an fstat on this file */
7549         if(fsp_stat(fsp, &sbuf)) {
7550                 reply_unixerror(req, ERRDOS, ERRnoaccess);
7551                 END_PROFILE(SMBgetattrE);
7552                 return;
7553         }
7554
7555         mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7556
7557         /*
7558          * Convert the times into dos times. Set create
7559          * date to be last modify date as UNIX doesn't save
7560          * this.
7561          */
7562
7563         reply_outbuf(req, 11, 0);
7564
7565         create_ts = sbuf.st_ex_btime;
7566         srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7567         srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7568                           convert_timespec_to_time_t(sbuf.st_ex_atime));
7569         /* Should we check pending modtime here ? JRA */
7570         srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7571                           convert_timespec_to_time_t(sbuf.st_ex_mtime));
7572
7573         if (mode & aDIR) {
7574                 SIVAL(req->outbuf, smb_vwv6, 0);
7575                 SIVAL(req->outbuf, smb_vwv8, 0);
7576         } else {
7577                 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &sbuf);
7578                 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_ex_size);
7579                 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7580         }
7581         SSVAL(req->outbuf,smb_vwv10, mode);
7582
7583         DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7584
7585         END_PROFILE(SMBgetattrE);
7586         return;
7587 }