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