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