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