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