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