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