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