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