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