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