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