672c68330930f5c19f6c0422b0351539bb8a5ad3
[tprouty/samba.git] / source / 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
29 /* look in server.c for some explanation of these variables */
30 extern enum protocol_types Protocol;
31 extern int max_recv;
32 unsigned int smb_echo_count = 0;
33 extern uint32 global_client_caps;
34
35 extern struct current_user current_user;
36 extern BOOL global_encrypted_passwords_negotiated;
37
38 /****************************************************************************
39  Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
40  path or anything including wildcards.
41  We're assuming here that '/' is not the second byte in any multibyte char
42  set (a safe assumption). '\\' *may* be the second byte in a multibyte char
43  set.
44 ****************************************************************************/
45
46 /* Custom version for processing POSIX paths. */
47 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
48
49 static NTSTATUS check_path_syntax_internal(char *path,
50                                            BOOL posix_path,
51                                            BOOL *p_last_component_contains_wcard)
52 {
53         char *d = path;
54         const char *s = path;
55         NTSTATUS ret = NT_STATUS_OK;
56         BOOL start_of_name_component = True;
57
58         *p_last_component_contains_wcard = False;
59
60         while (*s) {
61                 if (IS_PATH_SEP(*s,posix_path)) {
62                         /*
63                          * Safe to assume is not the second part of a mb char
64                          * as this is handled below.
65                          */
66                         /* Eat multiple '/' or '\\' */
67                         while (IS_PATH_SEP(*s,posix_path)) {
68                                 s++;
69                         }
70                         if ((d != path) && (*s != '\0')) {
71                                 /* We only care about non-leading or trailing '/' or '\\' */
72                                 *d++ = '/';
73                         }
74
75                         start_of_name_component = True;
76                         /* New component. */
77                         *p_last_component_contains_wcard = False;
78                         continue;
79                 }
80
81                 if (start_of_name_component) {
82                         if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
83                                 /* Uh oh - "/../" or "\\..\\"  or "/..\0" or "\\..\0" ! */
84
85                                 /*
86                                  * No mb char starts with '.' so we're safe checking the directory separator here.
87                                  */
88
89                                 /* If  we just added a '/' - delete it */
90                                 if ((d > path) && (*(d-1) == '/')) {
91                                         *(d-1) = '\0';
92                                         d--;
93                                 }
94
95                                 /* Are we at the start ? Can't go back further if so. */
96                                 if (d <= path) {
97                                         ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
98                                         break;
99                                 }
100                                 /* Go back one level... */
101                                 /* We know this is safe as '/' cannot be part of a mb sequence. */
102                                 /* NOTE - if this assumption is invalid we are not in good shape... */
103                                 /* Decrement d first as d points to the *next* char to write into. */
104                                 for (d--; d > path; d--) {
105                                         if (*d == '/')
106                                                 break;
107                                 }
108                                 s += 2; /* Else go past the .. */
109                                 /* We're still at the start of a name component, just the previous one. */
110                                 continue;
111
112                         } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
113                                 if (posix_path) {
114                                         /* Eat the '.' */
115                                         s++;
116                                         continue;
117                                 }
118                         }
119
120                 }
121
122                 if (!(*s & 0x80)) {
123                         if (!posix_path) {
124                                 if (*s <= 0x1f) {
125                                         return NT_STATUS_OBJECT_NAME_INVALID;
126                                 }
127                                 switch (*s) {
128                                         case '*':
129                                         case '?':
130                                         case '<':
131                                         case '>':
132                                         case '"':
133                                                 *p_last_component_contains_wcard = True;
134                                                 break;
135                                         default:
136                                                 break;
137                                 }
138                         }
139                         *d++ = *s++;
140                 } else {
141                         size_t siz;
142                         /* Get the size of the next MB character. */
143                         next_codepoint(s,&siz);
144                         switch(siz) {
145                                 case 5:
146                                         *d++ = *s++;
147                                         /*fall through*/
148                                 case 4:
149                                         *d++ = *s++;
150                                         /*fall through*/
151                                 case 3:
152                                         *d++ = *s++;
153                                         /*fall through*/
154                                 case 2:
155                                         *d++ = *s++;
156                                         /*fall through*/
157                                 case 1:
158                                         *d++ = *s++;
159                                         break;
160                                 default:
161                                         DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
162                                         *d = '\0';
163                                         return NT_STATUS_INVALID_PARAMETER;
164                         }
165                 }
166                 start_of_name_component = False;
167         }
168
169         *d = '\0';
170         return ret;
171 }
172
173 /****************************************************************************
174  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
175  No wildcards allowed.
176 ****************************************************************************/
177
178 NTSTATUS check_path_syntax(char *path)
179 {
180         BOOL ignore;
181         return check_path_syntax_internal(path, False, &ignore);
182 }
183
184 /****************************************************************************
185  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
186  Wildcards allowed - p_contains_wcard returns true if the last component contained
187  a wildcard.
188 ****************************************************************************/
189
190 NTSTATUS check_path_syntax_wcard(char *path, BOOL *p_contains_wcard)
191 {
192         return check_path_syntax_internal(path, False, p_contains_wcard);
193 }
194
195 /****************************************************************************
196  Check the path for a POSIX client.
197  We're assuming here that '/' is not the second byte in any multibyte char
198  set (a safe assumption).
199 ****************************************************************************/
200
201 NTSTATUS check_path_syntax_posix(char *path)
202 {
203         BOOL ignore;
204         return check_path_syntax_internal(path, True, &ignore);
205 }
206
207 /****************************************************************************
208  Pull a string and check the path allowing a wilcard - provide for error return.
209 ****************************************************************************/
210
211 size_t srvstr_get_path_wcard(const char *inbuf, uint16 smb_flags2, char *dest,
212                              const char *src, size_t dest_len, size_t src_len,
213                              int flags, NTSTATUS *err, BOOL *contains_wcard)
214 {
215         size_t ret;
216 #ifdef DEVELOPER
217         SMB_ASSERT(dest_len == sizeof(pstring));
218 #endif
219
220         if (src_len == 0) {
221                 ret = srvstr_pull_buf(inbuf, smb_flags2, dest, src,
222                                       dest_len, flags);
223         } else {
224                 ret = srvstr_pull(inbuf, smb_flags2, dest, src,
225                                   dest_len, src_len, flags);
226         }
227
228         *contains_wcard = False;
229
230         if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
231                 /* 
232                  * For a DFS path the function parse_dfs_path()
233                  * will do the path processing, just make a copy.
234                  */
235                 *err = NT_STATUS_OK;
236                 return ret;
237         }
238
239         if (lp_posix_pathnames()) {
240                 *err = check_path_syntax_posix(dest);
241         } else {
242                 *err = check_path_syntax_wcard(dest, contains_wcard);
243         }
244
245         return ret;
246 }
247
248 /****************************************************************************
249  Pull a string and check the path - provide for error return.
250 ****************************************************************************/
251
252 size_t srvstr_get_path(const char *inbuf, uint16 smb_flags2, char *dest,
253                        const char *src, size_t dest_len, size_t src_len,
254                        int flags, NTSTATUS *err)
255 {
256         size_t ret;
257 #ifdef DEVELOPER
258         SMB_ASSERT(dest_len == sizeof(pstring));
259 #endif
260
261         if (src_len == 0) {
262                 ret = srvstr_pull_buf(inbuf, smb_flags2, dest, src,
263                                       dest_len, flags);
264         } else {
265                 ret = srvstr_pull(inbuf, smb_flags2, dest, src,
266                                   dest_len, src_len, flags);
267         }
268
269         if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
270                 /* 
271                  * For a DFS path the function parse_dfs_path()
272                  * will do the path processing, just make a copy.
273                  */
274                 *err = NT_STATUS_OK;
275                 return ret;
276         }
277
278         if (lp_posix_pathnames()) {
279                 *err = check_path_syntax_posix(dest);
280         } else {
281                 *err = check_path_syntax(dest);
282         }
283
284         return ret;
285 }
286
287 /****************************************************************************
288  Check if we have a correct fsp pointing to a file. Basic check for open fsp.
289 ****************************************************************************/
290
291 BOOL check_fsp_open(connection_struct *conn, struct smb_request *req,
292                files_struct *fsp, struct current_user *user)
293 {
294         if (!(fsp) || !(conn)) {
295                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
296                 return False;
297         }
298         if (((conn) != (fsp)->conn) || user->vuid != (fsp)->vuid) {
299                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
300                 return False;
301         }
302         return True;
303 }
304
305 /****************************************************************************
306  Check if we have a correct fsp pointing to a file. Replacement for the
307  CHECK_FSP macro.
308 ****************************************************************************/
309
310 BOOL check_fsp(connection_struct *conn, struct smb_request *req,
311                files_struct *fsp, struct current_user *user)
312 {
313         if (!check_fsp_open(conn, req, fsp, user)) {
314                 return False;
315         }
316         if ((fsp)->is_directory) {
317                 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
318                 return False;
319         }
320         if ((fsp)->fh->fd == -1) {
321                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
322                 return False;
323         }
324         (fsp)->num_smb_operations++;
325         return True;
326 }
327
328 /****************************************************************************
329  Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
330 ****************************************************************************/
331
332 BOOL fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
333                       files_struct *fsp, struct current_user *user)
334 {
335         if ((fsp) && (conn) && ((conn)==(fsp)->conn)
336             && (current_user.vuid==(fsp)->vuid)) {
337                 return True;
338         }
339
340         reply_nterror(req, NT_STATUS_INVALID_HANDLE);
341         return False;
342 }
343
344 /****************************************************************************
345  Reply to a (netbios-level) special message.
346 ****************************************************************************/
347
348 void reply_special(char *inbuf)
349 {
350         int msg_type = CVAL(inbuf,0);
351         int msg_flags = CVAL(inbuf,1);
352         fstring name1,name2;
353         char name_type = 0;
354
355         /*
356          * We only really use 4 bytes of the outbuf, but for the smb_setlen
357          * calculation & friends (send_smb uses that) we need the full smb
358          * header.
359          */
360         char outbuf[smb_size];
361         
362         static BOOL already_got_session = False;
363
364         *name1 = *name2 = 0;
365         
366         memset(outbuf, '\0', sizeof(outbuf));
367
368         smb_setlen(inbuf,outbuf,0);
369         
370         switch (msg_type) {
371         case 0x81: /* session request */
372                 
373                 if (already_got_session) {
374                         exit_server_cleanly("multiple session request not permitted");
375                 }
376                 
377                 SCVAL(outbuf,0,0x82);
378                 SCVAL(outbuf,3,0);
379                 if (name_len(inbuf+4) > 50 || 
380                     name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
381                         DEBUG(0,("Invalid name length in session request\n"));
382                         return;
383                 }
384                 name_extract(inbuf,4,name1);
385                 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
386                 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
387                          name1,name2));      
388
389                 set_local_machine_name(name1, True);
390                 set_remote_machine_name(name2, True);
391
392                 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
393                          get_local_machine_name(), get_remote_machine_name(),
394                          name_type));
395
396                 if (name_type == 'R') {
397                         /* We are being asked for a pathworks session --- 
398                            no thanks! */
399                         SCVAL(outbuf, 0,0x83);
400                         break;
401                 }
402
403                 /* only add the client's machine name to the list
404                    of possibly valid usernames if we are operating
405                    in share mode security */
406                 if (lp_security() == SEC_SHARE) {
407                         add_session_user(get_remote_machine_name());
408                 }
409
410                 reload_services(True);
411                 reopen_logs();
412
413                 already_got_session = True;
414                 break;
415                 
416         case 0x89: /* session keepalive request 
417                       (some old clients produce this?) */
418                 SCVAL(outbuf,0,SMBkeepalive);
419                 SCVAL(outbuf,3,0);
420                 break;
421                 
422         case 0x82: /* positive session response */
423         case 0x83: /* negative session response */
424         case 0x84: /* retarget session response */
425                 DEBUG(0,("Unexpected session response\n"));
426                 break;
427                 
428         case SMBkeepalive: /* session keepalive */
429         default:
430                 return;
431         }
432         
433         DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
434                     msg_type, msg_flags));
435
436         send_smb(smbd_server_fd(), outbuf);
437         return;
438 }
439
440 /****************************************************************************
441  Reply to a tcon.
442  conn POINTER CAN BE NULL HERE !
443 ****************************************************************************/
444
445 void reply_tcon(connection_struct *conn, struct smb_request *req)
446 {
447         const char *service;
448         char *service_buf = NULL;
449         char *password = NULL;
450         char *dev = NULL;
451         int pwlen=0;
452         NTSTATUS nt_status;
453         char *p;
454         DATA_BLOB password_blob;
455         TALLOC_CTX *ctx = talloc_tos();
456
457         START_PROFILE(SMBtcon);
458
459         if (smb_buflen(req->inbuf) < 4) {
460                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
461                 END_PROFILE(SMBtcon);
462                 return;
463         }
464
465         p = smb_buf(req->inbuf)+1;
466         p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2,
467                                     &service_buf, p, STR_TERMINATE) + 1;
468         pwlen = srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2,
469                                        &password, p, STR_TERMINATE) + 1;
470         p += pwlen;
471         p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2,
472                                     &dev, p, STR_TERMINATE) + 1;
473
474         if (service_buf == NULL || password == NULL || dev == NULL) {
475                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
476                 END_PROFILE(SMBtcon);
477                 return;
478         }
479         p = strrchr_m(service_buf,'\\');
480         if (p) {
481                 service = p+1;
482         } else {
483                 service = service_buf;
484         }
485
486         password_blob = data_blob(password, pwlen+1);
487
488         conn = make_connection(service,password_blob,dev,req->vuid,&nt_status);
489
490         data_blob_clear_free(&password_blob);
491
492         if (!conn) {
493                 reply_nterror(req, nt_status);
494                 END_PROFILE(SMBtcon);
495                 return;
496         }
497
498         reply_outbuf(req, 2, 0);
499         SSVAL(req->outbuf,smb_vwv0,max_recv);
500         SSVAL(req->outbuf,smb_vwv1,conn->cnum);
501         SSVAL(req->outbuf,smb_tid,conn->cnum);
502
503         DEBUG(3,("tcon service=%s cnum=%d\n",
504                  service, conn->cnum));
505
506         END_PROFILE(SMBtcon);
507         return;
508 }
509
510 /****************************************************************************
511  Reply to a tcon and X.
512  conn POINTER CAN BE NULL HERE !
513 ****************************************************************************/
514
515 void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
516 {
517         char *service = NULL;
518         DATA_BLOB password;
519         TALLOC_CTX *ctx = talloc_tos();
520         /* what the cleint thinks the device is */
521         char *client_devicetype = NULL;
522         /* what the server tells the client the share represents */
523         const char *server_devicetype;
524         NTSTATUS nt_status;
525         int passlen;
526         char *path = NULL;
527         char *p, *q;
528         uint16 tcon_flags;
529
530         START_PROFILE(SMBtconX);
531
532         if (req->wct < 4) {
533                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
534                 END_PROFILE(SMBtconX);
535                 return;
536         }
537
538         passlen = SVAL(req->inbuf,smb_vwv3);
539         tcon_flags = SVAL(req->inbuf,smb_vwv2);
540
541         /* we might have to close an old one */
542         if ((tcon_flags & 0x1) && conn) {
543                 close_cnum(conn,req->vuid);
544         }
545
546         if ((passlen > MAX_PASS_LEN) || (passlen >= smb_buflen(req->inbuf))) {
547                 reply_doserror(req, ERRDOS, ERRbuftoosmall);
548                 END_PROFILE(SMBtconX);
549                 return;
550         }
551
552         if (global_encrypted_passwords_negotiated) {
553                 password = data_blob(smb_buf(req->inbuf),passlen);
554                 if (lp_security() == SEC_SHARE) {
555                         /*
556                          * Security = share always has a pad byte
557                          * after the password.
558                          */
559                         p = smb_buf(req->inbuf) + passlen + 1;
560                 } else {
561                         p = smb_buf(req->inbuf) + passlen;
562                 }
563         } else {
564                 password = data_blob(smb_buf(req->inbuf),passlen+1);
565                 /* Ensure correct termination */
566                 password.data[passlen]=0;
567                 p = smb_buf(req->inbuf) + passlen + 1;
568         }
569
570         p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2, &path, p,
571                              STR_TERMINATE);
572
573         if (path == NULL) {
574                 data_blob_clear_free(&password);
575                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
576                 END_PROFILE(SMBtconX);
577                 return;
578         }
579
580         /*
581          * the service name can be either: \\server\share
582          * or share directly like on the DELL PowerVault 705
583          */
584         if (*path=='\\') {
585                 q = strchr_m(path+2,'\\');
586                 if (!q) {
587                         data_blob_clear_free(&password);
588                         reply_doserror(req, ERRDOS, ERRnosuchshare);
589                         END_PROFILE(SMBtconX);
590                         return;
591                 }
592                 service = q+1;
593         } else {
594                 service = path;
595         }
596
597         p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
598                                 &client_devicetype, p,
599                                 MIN(6,smb_bufrem(req->inbuf, p)), STR_ASCII);
600
601         if (client_devicetype == NULL) {
602                 data_blob_clear_free(&password);
603                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
604                 END_PROFILE(SMBtconX);
605                 return;
606         }
607
608         DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
609
610         conn = make_connection(service, password, client_devicetype,
611                                req->vuid, &nt_status);
612
613         data_blob_clear_free(&password);
614
615         if (!conn) {
616                 reply_nterror(req, nt_status);
617                 END_PROFILE(SMBtconX);
618                 return;
619         }
620
621         if ( IS_IPC(conn) )
622                 server_devicetype = "IPC";
623         else if ( IS_PRINT(conn) )
624                 server_devicetype = "LPT1:";
625         else
626                 server_devicetype = "A:";
627
628         if (Protocol < PROTOCOL_NT1) {
629                 reply_outbuf(req, 2, 0);
630                 if (message_push_string(&req->outbuf, server_devicetype,
631                                         STR_TERMINATE|STR_ASCII) == -1) {
632                         reply_nterror(req, NT_STATUS_NO_MEMORY);
633                         END_PROFILE(SMBtconX);
634                         return;
635                 }
636         } else {
637                 /* NT sets the fstype of IPC$ to the null string */
638                 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
639
640                 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
641                         /* Return permissions. */
642                         uint32 perm1 = 0;
643                         uint32 perm2 = 0;
644
645                         reply_outbuf(req, 7, 0);
646
647                         if (IS_IPC(conn)) {
648                                 perm1 = FILE_ALL_ACCESS;
649                                 perm2 = FILE_ALL_ACCESS;
650                         } else {
651                                 perm1 = CAN_WRITE(conn) ?
652                                                 SHARE_ALL_ACCESS :
653                                                 SHARE_READ_ONLY;
654                         }
655
656                         SIVAL(req->outbuf, smb_vwv3, perm1);
657                         SIVAL(req->outbuf, smb_vwv5, perm2);
658                 } else {
659                         reply_outbuf(req, 3, 0);
660                 }
661
662                 if ((message_push_string(&req->outbuf, server_devicetype,
663                                          STR_TERMINATE|STR_ASCII) == -1)
664                     || (message_push_string(&req->outbuf, fstype,
665                                             STR_TERMINATE) == -1)) {
666                         reply_nterror(req, NT_STATUS_NO_MEMORY);
667                         END_PROFILE(SMBtconX);
668                         return;
669                 }
670
671                 /* what does setting this bit do? It is set by NT4 and
672                    may affect the ability to autorun mounted cdroms */
673                 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
674                       (lp_csc_policy(SNUM(conn)) << 2));
675
676                 init_dfsroot(conn, req->inbuf, req->outbuf);
677         }
678
679
680         DEBUG(3,("tconX service=%s \n",
681                  service));
682
683         /* set the incoming and outgoing tid to the just created one */
684         SSVAL(req->inbuf,smb_tid,conn->cnum);
685         SSVAL(req->outbuf,smb_tid,conn->cnum);
686
687         END_PROFILE(SMBtconX);
688
689         chain_reply(req);
690         return;
691 }
692
693 /****************************************************************************
694  Reply to an unknown type.
695 ****************************************************************************/
696
697 int reply_unknown(char *inbuf,char *outbuf)
698 {
699         int type;
700         type = CVAL(inbuf,smb_com);
701   
702         DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
703                  smb_fn_name(type), type, type));
704   
705         return(ERROR_DOS(ERRSRV,ERRunknownsmb));
706 }
707
708 void reply_unknown_new(struct smb_request *req, uint8 type)
709 {
710         DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
711                   smb_fn_name(type), type, type));
712         reply_doserror(req, ERRSRV, ERRunknownsmb);
713         return;
714 }
715
716 /****************************************************************************
717  Reply to an ioctl.
718  conn POINTER CAN BE NULL HERE !
719 ****************************************************************************/
720
721 void reply_ioctl(connection_struct *conn, struct smb_request *req)
722 {
723         uint16 device;
724         uint16 function;
725         uint32 ioctl_code;
726         int replysize;
727         char *p;
728
729         START_PROFILE(SMBioctl);
730
731         if (req->wct < 3) {
732                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
733                 END_PROFILE(SMBioctl);
734                 return;
735         }
736
737         device     = SVAL(req->inbuf,smb_vwv1);
738         function   = SVAL(req->inbuf,smb_vwv2);
739         ioctl_code = (device << 16) + function;
740
741         DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
742
743         switch (ioctl_code) {
744             case IOCTL_QUERY_JOB_INFO:
745                     replysize = 32;
746                     break;
747             default:
748                     reply_doserror(req, ERRSRV, ERRnosupport);
749                     END_PROFILE(SMBioctl);
750                     return;
751         }
752
753         reply_outbuf(req, 8, replysize+1);
754         SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
755         SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
756         SSVAL(req->outbuf,smb_vwv6,52);        /* Offset to data */
757         p = smb_buf(req->outbuf);
758         memset(p, '\0', replysize+1); /* valgrind-safe. */
759         p += 1;          /* Allow for alignment */
760
761         switch (ioctl_code) {
762                 case IOCTL_QUERY_JOB_INFO:                  
763                 {
764                         files_struct *fsp = file_fsp(SVAL(req->inbuf,
765                                                           smb_vwv0));
766                         if (!fsp) {
767                                 reply_doserror(req, ERRDOS, ERRbadfid);
768                                 END_PROFILE(SMBioctl);
769                                 return;
770                         }
771                         SSVAL(p,0,fsp->rap_print_jobid);             /* Job number */
772                         srvstr_push((char *)req->outbuf, req->flags2, p+2,
773                                     global_myname(), 15,
774                                     STR_TERMINATE|STR_ASCII);
775                         if (conn) {
776                                 srvstr_push((char *)req->outbuf, req->flags2,
777                                             p+18, lp_servicename(SNUM(conn)),
778                                             13, STR_TERMINATE|STR_ASCII);
779                         } else {
780                                 memset(p+18, 0, 13);
781                         }
782                         break;
783                 }
784         }
785
786         END_PROFILE(SMBioctl);
787         return;
788 }
789
790 /****************************************************************************
791  Strange checkpath NTSTATUS mapping.
792 ****************************************************************************/
793
794 static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
795 {
796         /* Strange DOS error code semantics only for checkpath... */
797         if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
798                 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
799                         /* We need to map to ERRbadpath */
800                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
801                 }
802         }
803         return status;
804 }
805         
806 /****************************************************************************
807  Reply to a checkpath.
808 ****************************************************************************/
809
810 void reply_checkpath(connection_struct *conn, struct smb_request *req)
811 {
812         pstring name_in;
813         char *name = NULL;
814         SMB_STRUCT_STAT sbuf;
815         NTSTATUS status;
816         TALLOC_CTX *ctx = talloc_tos();
817
818         START_PROFILE(SMBcheckpath);
819
820         srvstr_get_path((char *)req->inbuf, req->flags2, name_in,
821                         smb_buf(req->inbuf) + 1, sizeof(name_in), 0,
822                         STR_TERMINATE, &status);
823         if (!NT_STATUS_IS_OK(status)) {
824                 status = map_checkpath_error((char *)req->inbuf, status);
825                 reply_nterror(req, status);
826                 END_PROFILE(SMBcheckpath);
827                 return;
828         }
829
830         status = resolve_dfspath(ctx, conn,
831                         req->flags2 & FLAGS2_DFS_PATHNAMES,
832                         name_in,
833                         &name);
834         if (!NT_STATUS_IS_OK(status)) {
835                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
836                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
837                                         ERRSRV, ERRbadpath);
838                         END_PROFILE(SMBcheckpath);
839                         return;
840                 }
841                 goto path_err;
842         }
843
844         DEBUG(3,("reply_checkpath %s mode=%d\n", name_in, (int)SVAL(req->inbuf,smb_vwv0)));
845
846         status = unix_convert(conn, name, False, &name, NULL, &sbuf);
847         if (!NT_STATUS_IS_OK(status)) {
848                 goto path_err;
849         }
850
851         status = check_name(conn, name);
852         if (!NT_STATUS_IS_OK(status)) {
853                 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
854                 goto path_err;
855         }
856
857         if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
858                 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
859                 status = map_nt_error_from_unix(errno);
860                 goto path_err;
861         }
862
863         if (!S_ISDIR(sbuf.st_mode)) {
864                 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
865                                 ERRDOS, ERRbadpath);
866                 END_PROFILE(SMBcheckpath);
867                 return;
868         }
869
870         reply_outbuf(req, 0, 0);
871
872         END_PROFILE(SMBcheckpath);
873         return;
874
875   path_err:
876
877         END_PROFILE(SMBcheckpath);
878
879         /* We special case this - as when a Windows machine
880                 is parsing a path is steps through the components
881                 one at a time - if a component fails it expects
882                 ERRbadpath, not ERRbadfile.
883         */
884         status = map_checkpath_error((char *)req->inbuf, status);
885         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
886                 /*
887                  * Windows returns different error codes if
888                  * the parent directory is valid but not the
889                  * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
890                  * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
891                  * if the path is invalid.
892                  */
893                 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
894                                 ERRDOS, ERRbadpath);
895                 return;
896         }
897
898         reply_nterror(req, status);
899 }
900
901 /****************************************************************************
902  Reply to a getatr.
903 ****************************************************************************/
904
905 void reply_getatr(connection_struct *conn, struct smb_request *req)
906 {
907         pstring fname_in;
908         char *fname = NULL;
909         SMB_STRUCT_STAT sbuf;
910         int mode=0;
911         SMB_OFF_T size=0;
912         time_t mtime=0;
913         char *p;
914         NTSTATUS status;
915         TALLOC_CTX *ctx = talloc_tos();
916
917         START_PROFILE(SMBgetatr);
918
919         p = smb_buf(req->inbuf) + 1;
920         p += srvstr_get_path((char *)req->inbuf, req->flags2, fname_in, p,
921                              sizeof(fname_in), 0, STR_TERMINATE, &status);
922         if (!NT_STATUS_IS_OK(status)) {
923                 reply_nterror(req, status);
924                 END_PROFILE(SMBgetatr);
925                 return;
926         }
927
928         status = resolve_dfspath(ctx, conn,
929                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
930                                 fname_in,
931                                 &fname);
932         if (!NT_STATUS_IS_OK(status)) {
933                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
934                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
935                                         ERRSRV, ERRbadpath);
936                         END_PROFILE(SMBgetatr);
937                         return;
938                 }
939                 reply_nterror(req, status);
940                 END_PROFILE(SMBgetatr);
941                 return;
942         }
943
944         /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
945                 under WfWg - weird! */
946         if (*fname == '\0') {
947                 mode = aHIDDEN | aDIR;
948                 if (!CAN_WRITE(conn)) {
949                         mode |= aRONLY;
950                 }
951                 size = 0;
952                 mtime = 0;
953         } else {
954                 status = unix_convert(conn, fname, False, &fname, NULL,&sbuf);
955                 if (!NT_STATUS_IS_OK(status)) {
956                         reply_nterror(req, status);
957                         END_PROFILE(SMBgetatr);
958                         return;
959                 }
960                 status = check_name(conn, fname);
961                 if (!NT_STATUS_IS_OK(status)) {
962                         DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
963                         reply_nterror(req, status);
964                         END_PROFILE(SMBgetatr);
965                         return;
966                 }
967                 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
968                         DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
969                         reply_unixerror(req, ERRDOS,ERRbadfile);
970                         END_PROFILE(SMBgetatr);
971                         return;
972                 }
973
974                 mode = dos_mode(conn,fname,&sbuf);
975                 size = sbuf.st_size;
976                 mtime = sbuf.st_mtime;
977                 if (mode & aDIR) {
978                         size = 0;
979                 }
980         }
981
982         reply_outbuf(req, 10, 0);
983
984         SSVAL(req->outbuf,smb_vwv0,mode);
985         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
986                 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
987         } else {
988                 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
989         }
990         SIVAL(req->outbuf,smb_vwv3,(uint32)size);
991
992         if (Protocol >= PROTOCOL_NT1) {
993                 SSVAL(req->outbuf, smb_flg2,
994                       SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
995         }
996   
997         DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
998   
999         END_PROFILE(SMBgetatr);
1000         return;
1001 }
1002
1003 /****************************************************************************
1004  Reply to a setatr.
1005 ****************************************************************************/
1006
1007 void reply_setatr(connection_struct *conn, struct smb_request *req)
1008 {
1009         pstring fname_in;
1010         char *fname = NULL;
1011         int mode;
1012         time_t mtime;
1013         SMB_STRUCT_STAT sbuf;
1014         char *p;
1015         NTSTATUS status;
1016         TALLOC_CTX *ctx = talloc_tos();
1017
1018         START_PROFILE(SMBsetatr);
1019
1020         if (req->wct < 2) {
1021                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1022                 return;
1023         }
1024
1025         p = smb_buf(req->inbuf) + 1;
1026         p += srvstr_get_path((char *)req->inbuf, req->flags2, fname_in, p,
1027                              sizeof(fname_in), 0, STR_TERMINATE, &status);
1028         if (!NT_STATUS_IS_OK(status)) {
1029                 reply_nterror(req, status);
1030                 END_PROFILE(SMBsetatr);
1031                 return;
1032         }
1033
1034         status = resolve_dfspath(ctx, conn,
1035                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
1036                                 fname_in,
1037                                 &fname);
1038         if (!NT_STATUS_IS_OK(status)) {
1039                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1040                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1041                                         ERRSRV, ERRbadpath);
1042                         END_PROFILE(SMBsetatr);
1043                         return;
1044                 }
1045                 reply_nterror(req, status);
1046                 END_PROFILE(SMBsetatr);
1047                 return;
1048         }
1049   
1050         status = unix_convert(conn, fname, False, &fname, NULL, &sbuf);
1051         if (!NT_STATUS_IS_OK(status)) {
1052                 reply_nterror(req, status);
1053                 END_PROFILE(SMBsetatr);
1054                 return;
1055         }
1056
1057         status = check_name(conn, fname);
1058         if (!NT_STATUS_IS_OK(status)) {
1059                 reply_nterror(req, status);
1060                 END_PROFILE(SMBsetatr);
1061                 return;
1062         }
1063
1064         if (fname[0] == '.' && fname[1] == '\0') {
1065                 /*
1066                  * Not sure here is the right place to catch this
1067                  * condition. Might be moved to somewhere else later -- vl
1068                  */
1069                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1070                 END_PROFILE(SMBsetatr);
1071                 return;
1072         }
1073
1074         mode = SVAL(req->inbuf,smb_vwv0);
1075         mtime = srv_make_unix_date3(req->inbuf+smb_vwv1);
1076   
1077         if (mode != FILE_ATTRIBUTE_NORMAL) {
1078                 if (VALID_STAT_OF_DIR(sbuf))
1079                         mode |= aDIR;
1080                 else
1081                         mode &= ~aDIR;
1082
1083                 if (file_set_dosmode(conn,fname,mode,&sbuf,False) != 0) {
1084                         reply_unixerror(req, ERRDOS, ERRnoaccess);
1085                         END_PROFILE(SMBsetatr);
1086                         return;
1087                 }
1088         }
1089
1090         if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) {
1091                 reply_unixerror(req, ERRDOS, ERRnoaccess);
1092                 END_PROFILE(SMBsetatr);
1093                 return;
1094         }
1095
1096         reply_outbuf(req, 0, 0);
1097  
1098         DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1099   
1100         END_PROFILE(SMBsetatr);
1101         return;
1102 }
1103
1104 /****************************************************************************
1105  Reply to a dskattr.
1106 ****************************************************************************/
1107
1108 void reply_dskattr(connection_struct *conn, struct smb_request *req)
1109 {
1110         SMB_BIG_UINT dfree,dsize,bsize;
1111         START_PROFILE(SMBdskattr);
1112
1113         if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1114                 reply_unixerror(req, ERRHRD, ERRgeneral);
1115                 END_PROFILE(SMBdskattr);
1116                 return;
1117         }
1118
1119         reply_outbuf(req, 5, 0);
1120         
1121         if (Protocol <= PROTOCOL_LANMAN2) {
1122                 double total_space, free_space;
1123                 /* we need to scale this to a number that DOS6 can handle. We
1124                    use floating point so we can handle large drives on systems
1125                    that don't have 64 bit integers 
1126
1127                    we end up displaying a maximum of 2G to DOS systems
1128                 */
1129                 total_space = dsize * (double)bsize;
1130                 free_space = dfree * (double)bsize;
1131
1132                 dsize = (total_space+63*512) / (64*512);
1133                 dfree = (free_space+63*512) / (64*512);
1134                 
1135                 if (dsize > 0xFFFF) dsize = 0xFFFF;
1136                 if (dfree > 0xFFFF) dfree = 0xFFFF;
1137
1138                 SSVAL(req->outbuf,smb_vwv0,dsize);
1139                 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1140                 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1141                 SSVAL(req->outbuf,smb_vwv3,dfree);
1142         } else {
1143                 SSVAL(req->outbuf,smb_vwv0,dsize);
1144                 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1145                 SSVAL(req->outbuf,smb_vwv2,512);
1146                 SSVAL(req->outbuf,smb_vwv3,dfree);
1147         }
1148
1149         DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1150
1151         END_PROFILE(SMBdskattr);
1152         return;
1153 }
1154
1155 /****************************************************************************
1156  Reply to a search.
1157  Can be called from SMBsearch, SMBffirst or SMBfunique.
1158 ****************************************************************************/
1159
1160 void reply_search(connection_struct *conn, struct smb_request *req)
1161 {
1162         pstring mask;
1163         char *directory = NULL;
1164         pstring fname;
1165         SMB_OFF_T size;
1166         uint32 mode;
1167         time_t date;
1168         uint32 dirtype;
1169         unsigned int numentries = 0;
1170         unsigned int maxentries = 0;
1171         BOOL finished = False;
1172         char *p;
1173         int status_len;
1174         pstring path_in;
1175         char *path = NULL;
1176         char status[21];
1177         int dptr_num= -1;
1178         BOOL check_descend = False;
1179         BOOL expect_close = False;
1180         NTSTATUS nt_status;
1181         BOOL mask_contains_wcard = False;
1182         BOOL allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1183         TALLOC_CTX *ctx = talloc_tos();
1184
1185         START_PROFILE(SMBsearch);
1186
1187         if (req->wct < 2) {
1188                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1189                 END_PROFILE(SMBsearch);
1190                 return;
1191         }
1192
1193         if (lp_posix_pathnames()) {
1194                 reply_unknown_new(req, CVAL(req->inbuf, smb_com));
1195                 END_PROFILE(SMBsearch);
1196                 return;
1197         }
1198
1199         *mask = *fname = 0;
1200
1201         /* If we were called as SMBffirst then we must expect close. */
1202         if(CVAL(req->inbuf,smb_com) == SMBffirst) {
1203                 expect_close = True;
1204         }
1205
1206         reply_outbuf(req, 1, 3);
1207         maxentries = SVAL(req->inbuf,smb_vwv0);
1208         dirtype = SVAL(req->inbuf,smb_vwv1);
1209         p = smb_buf(req->inbuf) + 1;
1210         p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, path_in, p,
1211                                    sizeof(path_in), 0, STR_TERMINATE, &nt_status,
1212                                    &mask_contains_wcard);
1213         if (!NT_STATUS_IS_OK(nt_status)) {
1214                 reply_nterror(req, nt_status);
1215                 END_PROFILE(SMBsearch);
1216                 return;
1217         }
1218
1219         nt_status = resolve_dfspath_wcard(ctx, conn,
1220                                           req->flags2 & FLAGS2_DFS_PATHNAMES,
1221                                           path_in,
1222                                           &path,
1223                                           &mask_contains_wcard);
1224         if (!NT_STATUS_IS_OK(nt_status)) {
1225                 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1226                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1227                                         ERRSRV, ERRbadpath);
1228                         END_PROFILE(SMBsearch);
1229                         return;
1230                 }
1231                 reply_nterror(req, nt_status);
1232                 END_PROFILE(SMBsearch);
1233                 return;
1234         }
1235
1236         p++;
1237         status_len = SVAL(p, 0);
1238         p += 2;
1239
1240         /* dirtype &= ~aDIR; */
1241
1242         if (status_len == 0) {
1243                 SMB_STRUCT_STAT sbuf;
1244
1245                 nt_status = unix_convert(conn, path, True, &directory, NULL, &sbuf);
1246                 if (!NT_STATUS_IS_OK(nt_status)) {
1247                         reply_nterror(req, nt_status);
1248                         END_PROFILE(SMBsearch);
1249                         return;
1250                 }
1251
1252                 nt_status = check_name(conn, directory);
1253                 if (!NT_STATUS_IS_OK(nt_status)) {
1254                         reply_nterror(req, nt_status);
1255                         END_PROFILE(SMBsearch);
1256                         return;
1257                 }
1258
1259                 p = strrchr_m(directory,'/');
1260                 if (!p) {
1261                         pstrcpy(mask,directory);
1262                         directory = talloc_strdup(talloc_tos(),".");
1263                         if (!directory) {
1264                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
1265                                 END_PROFILE(SMBsearch);
1266                                 return;
1267                         }
1268                 } else {
1269                         *p = 0;
1270                         pstrcpy(mask,p+1);
1271                 }
1272
1273                 if (*directory == '\0') {
1274                         directory = talloc_strdup(talloc_tos(),".");
1275                         if (!directory) {
1276                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
1277                                 END_PROFILE(SMBsearch);
1278                                 return;
1279                         }
1280                 }
1281                 memset((char *)status,'\0',21);
1282                 SCVAL(status,0,(dirtype & 0x1F));
1283
1284                 nt_status = dptr_create(conn,
1285                                         directory,
1286                                         True,
1287                                         expect_close,
1288                                         req->smbpid,
1289                                         mask,
1290                                         mask_contains_wcard,
1291                                         dirtype,
1292                                         &conn->dirptr);
1293                 if (!NT_STATUS_IS_OK(nt_status)) {
1294                         reply_nterror(req, nt_status);
1295                         END_PROFILE(SMBsearch);
1296                         return;
1297                 }
1298                 dptr_num = dptr_dnum(conn->dirptr);
1299         } else {
1300                 int status_dirtype;
1301
1302                 memcpy(status,p,21);
1303                 status_dirtype = CVAL(status,0) & 0x1F;
1304                 if (status_dirtype != (dirtype & 0x1F)) {
1305                         dirtype = status_dirtype;
1306                 }
1307
1308                 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1309                 if (!conn->dirptr) {
1310                         goto SearchEmpty;
1311                 }
1312                 string_set(&conn->dirpath,dptr_path(dptr_num));
1313                 pstrcpy(mask, dptr_wcard(dptr_num));
1314                 /*
1315                  * For a 'continue' search we have no string. So
1316                  * check from the initial saved string.
1317                  */
1318                 mask_contains_wcard = ms_has_wild(mask);
1319                 dirtype = dptr_attr(dptr_num);
1320         }
1321
1322         DEBUG(4,("dptr_num is %d\n",dptr_num));
1323
1324         if ((dirtype&0x1F) == aVOLID) {
1325                 char buf[DIR_STRUCT_SIZE];
1326                 memcpy(buf,status,21);
1327                 make_dir_struct(buf,"???????????",volume_label(SNUM(conn)),
1328                                 0,aVOLID,0,!allow_long_path_components);
1329                 dptr_fill(buf+12,dptr_num);
1330                 if (dptr_zero(buf+12) && (status_len==0)) {
1331                         numentries = 1;
1332                 } else {
1333                         numentries = 0;
1334                 }
1335                 if (message_push_blob(&req->outbuf,
1336                                       data_blob_const(buf, sizeof(buf)))
1337                     == -1) {
1338                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1339                         END_PROFILE(SMBsearch);
1340                         return;
1341                 }
1342         } else {
1343                 unsigned int i;
1344                 maxentries = MIN(
1345                         maxentries,
1346                         ((BUFFER_SIZE -
1347                           ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1348                          /DIR_STRUCT_SIZE));
1349
1350                 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1351                         conn->dirpath,lp_dontdescend(SNUM(conn))));
1352                 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1353                         check_descend = True;
1354                 }
1355
1356                 for (i=numentries;(i<maxentries) && !finished;i++) {
1357                         finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1358                         if (!finished) {
1359                                 char buf[DIR_STRUCT_SIZE];
1360                                 memcpy(buf,status,21);
1361                                 make_dir_struct(buf,mask,fname,size, mode,date,
1362                                                 !allow_long_path_components);
1363                                 if (!dptr_fill(buf+12,dptr_num)) {
1364                                         break;
1365                                 }
1366                                 if (message_push_blob(&req->outbuf,
1367                                                       data_blob_const(buf, sizeof(buf)))
1368                                     == -1) {
1369                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1370                                         END_PROFILE(SMBsearch);
1371                                         return;
1372                                 }
1373                                 numentries++;
1374                         }
1375                 }
1376         }
1377
1378   SearchEmpty:
1379
1380         /* If we were called as SMBffirst with smb_search_id == NULL
1381                 and no entries were found then return error and close dirptr 
1382                 (X/Open spec) */
1383
1384         if (numentries == 0) {
1385                 dptr_close(&dptr_num);
1386         } else if(expect_close && status_len == 0) {
1387                 /* Close the dptr - we know it's gone */
1388                 dptr_close(&dptr_num);
1389         }
1390
1391         /* If we were called as SMBfunique, then we can close the dirptr now ! */
1392         if(dptr_num >= 0 && CVAL(req->inbuf,smb_com) == SMBfunique) {
1393                 dptr_close(&dptr_num);
1394         }
1395
1396         if ((numentries == 0) && !mask_contains_wcard) {
1397                 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1398                 END_PROFILE(SMBsearch);
1399                 return;
1400         }
1401
1402         SSVAL(req->outbuf,smb_vwv0,numentries);
1403         SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1404         SCVAL(smb_buf(req->outbuf),0,5);
1405         SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1406
1407         /* The replies here are never long name. */
1408         SSVAL(req->outbuf, smb_flg2,
1409               SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1410         if (!allow_long_path_components) {
1411                 SSVAL(req->outbuf, smb_flg2,
1412                       SVAL(req->outbuf, smb_flg2)
1413                       & (~FLAGS2_LONG_PATH_COMPONENTS));
1414         }
1415
1416         /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1417         SSVAL(req->outbuf, smb_flg2,
1418               (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1419
1420         if (!directory) {
1421                 directory = dptr_path(dptr_num);
1422         }
1423
1424         DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1425                 smb_fn_name(CVAL(req->inbuf,smb_com)),
1426                 mask,
1427                 directory ? directory : "./",
1428                 dirtype,
1429                 numentries,
1430                 maxentries ));
1431
1432         END_PROFILE(SMBsearch);
1433         return;
1434 }
1435
1436 /****************************************************************************
1437  Reply to a fclose (stop directory search).
1438 ****************************************************************************/
1439
1440 void reply_fclose(connection_struct *conn, struct smb_request *req)
1441 {
1442         int status_len;
1443         pstring path;
1444         char status[21];
1445         int dptr_num= -2;
1446         char *p;
1447         NTSTATUS err;
1448         BOOL path_contains_wcard = False;
1449
1450         START_PROFILE(SMBfclose);
1451
1452         if (lp_posix_pathnames()) {
1453                 reply_unknown_new(req, CVAL(req->inbuf, smb_com));
1454                 END_PROFILE(SMBfclose);
1455                 return;
1456         }
1457
1458         p = smb_buf(req->inbuf) + 1;
1459         p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, path, p,
1460                                    sizeof(path), 0, STR_TERMINATE, &err,
1461                                    &path_contains_wcard);
1462         if (!NT_STATUS_IS_OK(err)) {
1463                 reply_nterror(req, err);
1464                 END_PROFILE(SMBfclose);
1465                 return;
1466         }
1467         p++;
1468         status_len = SVAL(p,0);
1469         p += 2;
1470
1471         if (status_len == 0) {
1472                 reply_doserror(req, ERRSRV, ERRsrverror);
1473                 END_PROFILE(SMBfclose);
1474                 return;
1475         }
1476
1477         memcpy(status,p,21);
1478
1479         if(dptr_fetch(status+12,&dptr_num)) {
1480                 /*  Close the dptr - we know it's gone */
1481                 dptr_close(&dptr_num);
1482         }
1483
1484         reply_outbuf(req, 1, 0);
1485         SSVAL(req->outbuf,smb_vwv0,0);
1486
1487         DEBUG(3,("search close\n"));
1488
1489         END_PROFILE(SMBfclose);
1490         return;
1491 }
1492
1493 /****************************************************************************
1494  Reply to an open.
1495 ****************************************************************************/
1496
1497 void reply_open(connection_struct *conn, struct smb_request *req)
1498 {
1499         pstring fname_in;
1500         char *fname = NULL;
1501         uint32 fattr=0;
1502         SMB_OFF_T size = 0;
1503         time_t mtime=0;
1504         int info;
1505         SMB_STRUCT_STAT sbuf;
1506         files_struct *fsp;
1507         int oplock_request;
1508         int deny_mode;
1509         uint32 dos_attr;
1510         uint32 access_mask;
1511         uint32 share_mode;
1512         uint32 create_disposition;
1513         uint32 create_options = 0;
1514         NTSTATUS status;
1515         TALLOC_CTX *ctx = talloc_tos();
1516
1517         START_PROFILE(SMBopen);
1518
1519         if (req->wct < 2) {
1520                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1521                 END_PROFILE(SMBopen);
1522                 return;
1523         }
1524
1525         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1526         deny_mode = SVAL(req->inbuf,smb_vwv0);
1527         dos_attr = SVAL(req->inbuf,smb_vwv1);
1528
1529         srvstr_get_path((char *)req->inbuf, req->flags2, fname_in,
1530                         smb_buf(req->inbuf)+1, sizeof(fname_in), 0,
1531                         STR_TERMINATE, &status);
1532         if (!NT_STATUS_IS_OK(status)) {
1533                 reply_nterror(req, status);
1534                 END_PROFILE(SMBopen);
1535                 return;
1536         }
1537
1538         status = resolve_dfspath(ctx, conn,
1539                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
1540                                 fname_in,
1541                                 &fname);
1542         if (!NT_STATUS_IS_OK(status)) {
1543                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1544                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1545                                         ERRSRV, ERRbadpath);
1546                         END_PROFILE(SMBopen);
1547                         return;
1548                 }
1549                 reply_nterror(req, status);
1550                 END_PROFILE(SMBopen);
1551                 return;
1552         }
1553
1554         status = unix_convert(conn, fname, False, &fname, NULL, &sbuf);
1555         if (!NT_STATUS_IS_OK(status)) {
1556                 reply_nterror(req, status);
1557                 END_PROFILE(SMBopen);
1558                 return;
1559         }
1560     
1561         status = check_name(conn, fname);
1562         if (!NT_STATUS_IS_OK(status)) {
1563                 reply_nterror(req, status);
1564                 END_PROFILE(SMBopen);
1565                 return;
1566         }
1567
1568         if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
1569                         &access_mask, &share_mode, &create_disposition, &create_options)) {
1570                 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1571                 END_PROFILE(SMBopen);
1572                 return;
1573         }
1574
1575         status = open_file_ntcreate(conn, req, fname, &sbuf,
1576                         access_mask,
1577                         share_mode,
1578                         create_disposition,
1579                         create_options,
1580                         dos_attr,
1581                         oplock_request,
1582                         &info, &fsp);
1583
1584         if (!NT_STATUS_IS_OK(status)) {
1585                 if (open_was_deferred(req->mid)) {
1586                         END_PROFILE(SMBopen);
1587                         /* We have re-scheduled this call. */
1588                         return;
1589                 }
1590                 reply_openerror(req, status);
1591                 END_PROFILE(SMBopen);
1592                 return;
1593         }
1594
1595         size = sbuf.st_size;
1596         fattr = dos_mode(conn,fname,&sbuf);
1597         mtime = sbuf.st_mtime;
1598
1599         if (fattr & aDIR) {
1600                 DEBUG(3,("attempt to open a directory %s\n",fname));
1601                 close_file(fsp,ERROR_CLOSE);
1602                 reply_doserror(req, ERRDOS,ERRnoaccess);
1603                 END_PROFILE(SMBopen);
1604                 return;
1605         }
1606
1607         reply_outbuf(req, 7, 0);
1608         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1609         SSVAL(req->outbuf,smb_vwv1,fattr);
1610         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1611                 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1612         } else {
1613                 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1614         }
1615         SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1616         SSVAL(req->outbuf,smb_vwv6,deny_mode);
1617
1618         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1619                 SCVAL(req->outbuf,smb_flg,
1620                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1621         }
1622     
1623         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1624                 SCVAL(req->outbuf,smb_flg,
1625                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1626         }
1627         END_PROFILE(SMBopen);
1628         return;
1629 }
1630
1631 /****************************************************************************
1632  Reply to an open and X.
1633 ****************************************************************************/
1634
1635 void reply_open_and_X(connection_struct *conn, struct smb_request *req)
1636 {
1637         pstring fname_in;
1638         char *fname = NULL;
1639         uint16 open_flags;
1640         int deny_mode;
1641         uint32 smb_attr;
1642         /* Breakout the oplock request bits so we can set the
1643                 reply bits separately. */
1644         int ex_oplock_request;
1645         int core_oplock_request;
1646         int oplock_request;
1647 #if 0
1648         int smb_sattr = SVAL(req->inbuf,smb_vwv4);
1649         uint32 smb_time = make_unix_date3(req->inbuf+smb_vwv6);
1650 #endif
1651         int smb_ofun;
1652         uint32 fattr=0;
1653         int mtime=0;
1654         SMB_STRUCT_STAT sbuf;
1655         int smb_action = 0;
1656         files_struct *fsp;
1657         NTSTATUS status;
1658         SMB_BIG_UINT allocation_size;
1659         ssize_t retval = -1;
1660         uint32 access_mask;
1661         uint32 share_mode;
1662         uint32 create_disposition;
1663         uint32 create_options = 0;
1664         TALLOC_CTX *ctx = talloc_tos();
1665
1666         START_PROFILE(SMBopenX);
1667
1668         if (req->wct < 15) {
1669                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1670                 END_PROFILE(SMBopenX);
1671                 return;
1672         }
1673
1674         open_flags = SVAL(req->inbuf,smb_vwv2);
1675         deny_mode = SVAL(req->inbuf,smb_vwv3);
1676         smb_attr = SVAL(req->inbuf,smb_vwv5);
1677         ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1678         core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1679         oplock_request = ex_oplock_request | core_oplock_request;
1680         smb_ofun = SVAL(req->inbuf,smb_vwv8);
1681         allocation_size = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv9);
1682
1683         /* If it's an IPC, pass off the pipe handler. */
1684         if (IS_IPC(conn)) {
1685                 if (lp_nt_pipe_support()) {
1686                         reply_open_pipe_and_X(conn, req);
1687                 } else {
1688                         reply_doserror(req, ERRSRV, ERRaccess);
1689                 }
1690                 END_PROFILE(SMBopenX);
1691                 return;
1692         }
1693
1694         /* XXXX we need to handle passed times, sattr and flags */
1695         srvstr_get_path((char *)req->inbuf, req->flags2, fname_in,
1696                         smb_buf(req->inbuf), sizeof(fname_in), 0, STR_TERMINATE,
1697                         &status);
1698         if (!NT_STATUS_IS_OK(status)) {
1699                 reply_nterror(req, status);
1700                 END_PROFILE(SMBopenX);
1701                 return;
1702         }
1703
1704         status = resolve_dfspath(ctx, conn,
1705                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
1706                                 fname_in,
1707                                 &fname);
1708         if (!NT_STATUS_IS_OK(status)) {
1709                 END_PROFILE(SMBopenX);
1710                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1711                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1712                                         ERRSRV, ERRbadpath);
1713                         return;
1714                 }
1715                 reply_nterror(req, status);
1716                 return;
1717         }
1718
1719         status = unix_convert(conn, fname, False, &fname, NULL, &sbuf);
1720         if (!NT_STATUS_IS_OK(status)) {
1721                 reply_nterror(req, status);
1722                 END_PROFILE(SMBopenX);
1723                 return;
1724         }
1725
1726         status = check_name(conn, fname);
1727         if (!NT_STATUS_IS_OK(status)) {
1728                 reply_nterror(req, status);
1729                 END_PROFILE(SMBopenX);
1730                 return;
1731         }
1732
1733         if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
1734                                 &access_mask,
1735                                 &share_mode,
1736                                 &create_disposition,
1737                                 &create_options)) {
1738                 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1739                 END_PROFILE(SMBopenX);
1740                 return;
1741         }
1742
1743         status = open_file_ntcreate(conn, req, fname, &sbuf,
1744                         access_mask,
1745                         share_mode,
1746                         create_disposition,
1747                         create_options,
1748                         smb_attr,
1749                         oplock_request,
1750                         &smb_action, &fsp);
1751
1752         if (!NT_STATUS_IS_OK(status)) {
1753                 END_PROFILE(SMBopenX);
1754                 if (open_was_deferred(req->mid)) {
1755                         /* We have re-scheduled this call. */
1756                         return;
1757                 }
1758                 reply_openerror(req, status);
1759                 return;
1760         }
1761
1762         /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1763            if the file is truncated or created. */
1764         if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1765                 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1766                 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1767                         close_file(fsp,ERROR_CLOSE);
1768                         reply_nterror(req, NT_STATUS_DISK_FULL);
1769                         END_PROFILE(SMBopenX);
1770                         return;
1771                 }
1772                 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1773                 if (retval < 0) {
1774                         close_file(fsp,ERROR_CLOSE);
1775                         reply_nterror(req, NT_STATUS_DISK_FULL);
1776                         END_PROFILE(SMBopenX);
1777                         return;
1778                 }
1779                 sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
1780         }
1781
1782         fattr = dos_mode(conn,fname,&sbuf);
1783         mtime = sbuf.st_mtime;
1784         if (fattr & aDIR) {
1785                 close_file(fsp,ERROR_CLOSE);
1786                 reply_doserror(req, ERRDOS, ERRnoaccess);
1787                 END_PROFILE(SMBopenX);
1788                 return;
1789         }
1790
1791         /* If the caller set the extended oplock request bit
1792                 and we granted one (by whatever means) - set the
1793                 correct bit for extended oplock reply.
1794         */
1795
1796         if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1797                 smb_action |= EXTENDED_OPLOCK_GRANTED;
1798         }
1799
1800         if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1801                 smb_action |= EXTENDED_OPLOCK_GRANTED;
1802         }
1803
1804         /* If the caller set the core oplock request bit
1805                 and we granted one (by whatever means) - set the
1806                 correct bit for core oplock reply.
1807         */
1808
1809         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1810                 reply_outbuf(req, 19, 0);
1811         } else {
1812                 reply_outbuf(req, 15, 0);
1813         }
1814
1815         if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1816                 SCVAL(req->outbuf, smb_flg,
1817                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1818         }
1819
1820         if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1821                 SCVAL(req->outbuf, smb_flg,
1822                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1823         }
1824
1825         SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1826         SSVAL(req->outbuf,smb_vwv3,fattr);
1827         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1828                 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1829         } else {
1830                 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
1831         }
1832         SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_size);
1833         SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1834         SSVAL(req->outbuf,smb_vwv11,smb_action);
1835
1836         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1837                 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1838         }
1839
1840         END_PROFILE(SMBopenX);
1841         chain_reply(req);
1842         return;
1843 }
1844
1845 /****************************************************************************
1846  Reply to a SMBulogoffX.
1847  conn POINTER CAN BE NULL HERE !
1848 ****************************************************************************/
1849
1850 void reply_ulogoffX(connection_struct *conn, struct smb_request *req)
1851 {
1852         user_struct *vuser;
1853
1854         START_PROFILE(SMBulogoffX);
1855
1856         vuser = get_valid_user_struct(req->vuid);
1857
1858         if(vuser == NULL) {
1859                 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
1860                          req->vuid));
1861         }
1862
1863         /* in user level security we are supposed to close any files
1864                 open by this user */
1865         if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
1866                 file_close_user(req->vuid);
1867         }
1868
1869         invalidate_vuid(req->vuid);
1870
1871         reply_outbuf(req, 2, 0);
1872
1873         DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
1874
1875         END_PROFILE(SMBulogoffX);
1876         chain_reply(req);
1877 }
1878
1879 /****************************************************************************
1880  Reply to a mknew or a create.
1881 ****************************************************************************/
1882
1883 void reply_mknew(connection_struct *conn, struct smb_request *req)
1884 {
1885         pstring fname_in;
1886         char *fname = NULL;
1887         int com;
1888         uint32 fattr = 0;
1889         struct timespec ts[2];
1890         files_struct *fsp;
1891         int oplock_request = 0;
1892         SMB_STRUCT_STAT sbuf;
1893         NTSTATUS status;
1894         uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1895         uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1896         uint32 create_disposition;
1897         uint32 create_options = 0;
1898         TALLOC_CTX *ctx = talloc_tos();
1899
1900         START_PROFILE(SMBcreate);
1901
1902         if (req->wct < 3) {
1903                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1904                 END_PROFILE(SMBcreate);
1905                 return;
1906         }
1907
1908         fattr = SVAL(req->inbuf,smb_vwv0);
1909         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1910         com = SVAL(req->inbuf,smb_com);
1911
1912         ts[1] =convert_time_t_to_timespec(
1913                         srv_make_unix_date3(req->inbuf + smb_vwv1));
1914                         /* mtime. */
1915
1916         srvstr_get_path((char *)req->inbuf, req->flags2, fname_in,
1917                         smb_buf(req->inbuf) + 1, sizeof(fname_in), 0,
1918                         STR_TERMINATE, &status);
1919         if (!NT_STATUS_IS_OK(status)) {
1920                 reply_nterror(req, status);
1921                 END_PROFILE(SMBcreate);
1922                 return;
1923         }
1924
1925         status = resolve_dfspath(ctx, conn,
1926                         req->flags2 & FLAGS2_DFS_PATHNAMES,
1927                         fname_in,
1928                         &fname);
1929         if (!NT_STATUS_IS_OK(status)) {
1930                 END_PROFILE(SMBcreate);
1931                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1932                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1933                                         ERRSRV, ERRbadpath);
1934                         return;
1935                 }
1936                 reply_nterror(req, status);
1937                 return;
1938         }
1939
1940         status = unix_convert(conn, fname, False, &fname, NULL, &sbuf);
1941         if (!NT_STATUS_IS_OK(status)) {
1942                 reply_nterror(req, status);
1943                 END_PROFILE(SMBcreate);
1944                 return;
1945         }
1946
1947         status = check_name(conn, fname);
1948         if (!NT_STATUS_IS_OK(status)) {
1949                 reply_nterror(req, status);
1950                 END_PROFILE(SMBcreate);
1951                 return;
1952         }
1953
1954         if (fattr & aVOLID) {
1955                 DEBUG(0,("Attempt to create file (%s) with volid set - "
1956                         "please report this\n", fname));
1957         }
1958
1959         if(com == SMBmknew) {
1960                 /* We should fail if file exists. */
1961                 create_disposition = FILE_CREATE;
1962         } else {
1963                 /* Create if file doesn't exist, truncate if it does. */
1964                 create_disposition = FILE_OVERWRITE_IF;
1965         }
1966
1967         /* Open file using ntcreate. */
1968         status = open_file_ntcreate(conn, req, fname, &sbuf,
1969                                 access_mask,
1970                                 share_mode,
1971                                 create_disposition,
1972                                 create_options,
1973                                 fattr,
1974                                 oplock_request,
1975                                 NULL, &fsp);
1976
1977         if (!NT_STATUS_IS_OK(status)) {
1978                 END_PROFILE(SMBcreate);
1979                 if (open_was_deferred(req->mid)) {
1980                         /* We have re-scheduled this call. */
1981                         return;
1982                 }
1983                 reply_nterror(req, status);
1984                 return;
1985         }
1986
1987         ts[0] = get_atimespec(&sbuf); /* atime. */
1988         file_ntimes(conn, fname, ts);
1989
1990         reply_outbuf(req, 1, 0);
1991         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1992
1993         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1994                 SCVAL(req->outbuf,smb_flg,
1995                                 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1996         }
1997
1998         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1999                 SCVAL(req->outbuf,smb_flg,
2000                                 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2001         }
2002
2003         DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
2004         DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2005                                 fname, fsp->fh->fd, (unsigned int)fattr ) );
2006
2007         END_PROFILE(SMBcreate);
2008         return;
2009 }
2010
2011 /****************************************************************************
2012  Reply to a create temporary file.
2013 ****************************************************************************/
2014
2015 void reply_ctemp(connection_struct *conn, struct smb_request *req)
2016 {
2017         pstring fname_in;
2018         char *fname = NULL;
2019         uint32 fattr;
2020         files_struct *fsp;
2021         int oplock_request;
2022         int tmpfd;
2023         SMB_STRUCT_STAT sbuf;
2024         char *s;
2025         NTSTATUS status;
2026         TALLOC_CTX *ctx = talloc_tos();
2027
2028         START_PROFILE(SMBctemp);
2029
2030         if (req->wct < 3) {
2031                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2032                 END_PROFILE(SMBctemp);
2033                 return;
2034         }
2035
2036         fattr = SVAL(req->inbuf,smb_vwv0);
2037         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2038
2039         srvstr_get_path((char *)req->inbuf, req->flags2, fname_in,
2040                         smb_buf(req->inbuf)+1, sizeof(fname_in), 0, STR_TERMINATE,
2041                         &status);
2042         if (!NT_STATUS_IS_OK(status)) {
2043                 reply_nterror(req, status);
2044                 END_PROFILE(SMBctemp);
2045                 return;
2046         }
2047         if (*fname_in) {
2048                 pstrcat(fname_in,"/TMXXXXXX");
2049         } else {
2050                 pstrcat(fname_in,"TMXXXXXX");
2051         }
2052
2053         status = resolve_dfspath(ctx, conn,
2054                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
2055                                 fname_in,
2056                                 &fname);
2057         if (!NT_STATUS_IS_OK(status)) {
2058                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2059                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2060                                         ERRSRV, ERRbadpath);
2061                         END_PROFILE(SMBctemp);
2062                         return;
2063                 }
2064                 reply_nterror(req, status);
2065                 END_PROFILE(SMBctemp);
2066                 return;
2067         }
2068
2069         status = unix_convert(conn, fname, False, &fname, NULL, &sbuf);
2070         if (!NT_STATUS_IS_OK(status)) {
2071                 reply_nterror(req, status);
2072                 END_PROFILE(SMBctemp);
2073                 return;
2074         }
2075
2076         status = check_name(conn, CONST_DISCARD(char *,fname));
2077         if (!NT_STATUS_IS_OK(status)) {
2078                 reply_nterror(req, status);
2079                 END_PROFILE(SMBctemp);
2080                 return;
2081         }
2082
2083         tmpfd = smb_mkstemp(fname);
2084         if (tmpfd == -1) {
2085                 reply_unixerror(req, ERRDOS, ERRnoaccess);
2086                 END_PROFILE(SMBctemp);
2087                 return;
2088         }
2089
2090         SMB_VFS_STAT(conn,fname,&sbuf);
2091
2092         /* We should fail if file does not exist. */
2093         status = open_file_ntcreate(conn, req, fname, &sbuf,
2094                                 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
2095                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
2096                                 FILE_OPEN,
2097                                 0,
2098                                 fattr,
2099                                 oplock_request,
2100                                 NULL, &fsp);
2101
2102         /* close fd from smb_mkstemp() */
2103         close(tmpfd);
2104
2105         if (!NT_STATUS_IS_OK(status)) {
2106                 if (open_was_deferred(req->mid)) {
2107                         /* We have re-scheduled this call. */
2108                         END_PROFILE(SMBctemp);
2109                         return;
2110                 }
2111                 reply_openerror(req, status);
2112                 END_PROFILE(SMBctemp);
2113                 return;
2114         }
2115
2116         reply_outbuf(req, 1, 0);
2117         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2118
2119         /* the returned filename is relative to the directory */
2120         s = strrchr_m(fname, '/');
2121         if (!s) {
2122                 s = fname;
2123         } else {
2124                 s++;
2125         }
2126
2127 #if 0
2128         /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2129            thing in the byte section. JRA */
2130         SSVALS(p, 0, -1); /* what is this? not in spec */
2131 #endif
2132         if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2133             == -1) {
2134                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2135                 END_PROFILE(SMBctemp);
2136                 return;
2137         }
2138
2139         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2140                 SCVAL(req->outbuf, smb_flg,
2141                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2142         }
2143   
2144         if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2145                 SCVAL(req->outbuf, smb_flg,
2146                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2147         }
2148
2149         DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
2150         DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
2151                         (unsigned int)sbuf.st_mode ) );
2152
2153         END_PROFILE(SMBctemp);
2154         return;
2155 }
2156
2157 /*******************************************************************
2158  Check if a user is allowed to rename a file.
2159 ********************************************************************/
2160
2161 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2162                            uint16 dirtype, SMB_STRUCT_STAT *pst)
2163 {
2164         uint32 fmode;
2165
2166         if (!CAN_WRITE(conn)) {
2167                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2168         }
2169
2170         fmode = dos_mode(conn, fsp->fsp_name, pst);
2171         if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2172                 return NT_STATUS_NO_SUCH_FILE;
2173         }
2174
2175         if (S_ISDIR(pst->st_mode)) {
2176                 return NT_STATUS_OK;
2177         }
2178
2179         if (fsp->access_mask & DELETE_ACCESS) {
2180                 return NT_STATUS_OK;
2181         }
2182
2183         return NT_STATUS_ACCESS_DENIED;
2184 }
2185
2186 /*******************************************************************
2187  * unlink a file with all relevant access checks
2188  *******************************************************************/
2189
2190 static NTSTATUS do_unlink(connection_struct *conn, struct smb_request *req,
2191                           char *fname, uint32 dirtype)
2192 {
2193         SMB_STRUCT_STAT sbuf;
2194         uint32 fattr;
2195         files_struct *fsp;
2196         uint32 dirtype_orig = dirtype;
2197         NTSTATUS status;
2198
2199         DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2200
2201         if (!CAN_WRITE(conn)) {
2202                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2203         }
2204
2205         if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
2206                 return map_nt_error_from_unix(errno);
2207         }
2208
2209         fattr = dos_mode(conn,fname,&sbuf);
2210
2211         if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2212                 dirtype = aDIR|aARCH|aRONLY;
2213         }
2214
2215         dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2216         if (!dirtype) {
2217                 return NT_STATUS_NO_SUCH_FILE;
2218         }
2219
2220         if (!dir_check_ftype(conn, fattr, dirtype)) {
2221                 if (fattr & aDIR) {
2222                         return NT_STATUS_FILE_IS_A_DIRECTORY;
2223                 }
2224                 return NT_STATUS_NO_SUCH_FILE;
2225         }
2226
2227         if (dirtype_orig & 0x8000) {
2228                 /* These will never be set for POSIX. */
2229                 return NT_STATUS_NO_SUCH_FILE;
2230         }
2231
2232 #if 0
2233         if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2234                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2235         }
2236
2237         if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2238                 return NT_STATUS_NO_SUCH_FILE;
2239         }
2240
2241         if (dirtype & 0xFF00) {
2242                 /* These will never be set for POSIX. */
2243                 return NT_STATUS_NO_SUCH_FILE;
2244         }
2245
2246         dirtype &= 0xFF;
2247         if (!dirtype) {
2248                 return NT_STATUS_NO_SUCH_FILE;
2249         }
2250
2251         /* Can't delete a directory. */
2252         if (fattr & aDIR) {
2253                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2254         }
2255 #endif
2256
2257 #if 0 /* JRATEST */
2258         else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2259                 return NT_STATUS_OBJECT_NAME_INVALID;
2260 #endif /* JRATEST */
2261
2262         /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2263
2264           On a Windows share, a file with read-only dosmode can be opened with
2265           DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2266           fails with NT_STATUS_CANNOT_DELETE error.
2267
2268           This semantic causes a problem that a user can not
2269           rename a file with read-only dosmode on a Samba share
2270           from a Windows command prompt (i.e. cmd.exe, but can rename
2271           from Windows Explorer).
2272         */
2273
2274         if (!lp_delete_readonly(SNUM(conn))) {
2275                 if (fattr & aRONLY) {
2276                         return NT_STATUS_CANNOT_DELETE;
2277                 }
2278         }
2279
2280         /* On open checks the open itself will check the share mode, so
2281            don't do it here as we'll get it wrong. */
2282
2283         status = open_file_ntcreate(conn, req, fname, &sbuf,
2284                                     DELETE_ACCESS,
2285                                     FILE_SHARE_NONE,
2286                                     FILE_OPEN,
2287                                     0,
2288                                     FILE_ATTRIBUTE_NORMAL,
2289                                     req != NULL ? 0 : INTERNAL_OPEN_ONLY,
2290                                     NULL, &fsp);
2291
2292         if (!NT_STATUS_IS_OK(status)) {
2293                 DEBUG(10, ("open_file_ntcreate failed: %s\n",
2294                            nt_errstr(status)));
2295                 return status;
2296         }
2297
2298         /* The set is across all open files on this dev/inode pair. */
2299         if (!set_delete_on_close(fsp, True, &current_user.ut)) {
2300                 close_file(fsp, NORMAL_CLOSE);
2301                 return NT_STATUS_ACCESS_DENIED;
2302         }
2303
2304         return close_file(fsp,NORMAL_CLOSE);
2305 }
2306
2307 /****************************************************************************
2308  The guts of the unlink command, split out so it may be called by the NT SMB
2309  code.
2310 ****************************************************************************/
2311
2312 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2313                           uint32 dirtype, const char *name_in, BOOL has_wild)
2314 {
2315         pstring directory;
2316         pstring mask;
2317         char *name = NULL;
2318         char *p;
2319         int count=0;
2320         NTSTATUS status = NT_STATUS_OK;
2321         SMB_STRUCT_STAT sbuf;
2322
2323         *directory = *mask = 0;
2324
2325         status = unix_convert(conn, name_in, has_wild, &name, NULL, &sbuf);
2326         if (!NT_STATUS_IS_OK(status)) {
2327                 return status;
2328         }
2329
2330         p = strrchr_m(name,'/');
2331         if (!p) {
2332                 pstrcpy(directory,".");
2333                 pstrcpy(mask,name);
2334         } else {
2335                 *p = 0;
2336                 pstrcpy(directory,name);
2337                 pstrcpy(mask,p+1);
2338         }
2339
2340         /*
2341          * We should only check the mangled cache
2342          * here if unix_convert failed. This means
2343          * that the path in 'mask' doesn't exist
2344          * on the file system and so we need to look
2345          * for a possible mangle. This patch from
2346          * Tine Smukavec <valentin.smukavec@hermes.si>.
2347          */
2348
2349         if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params)) {
2350                 char *new_mask = NULL;
2351                 mangle_lookup_name_from_8_3(talloc_tos(),
2352                                 mask,
2353                                 &new_mask,
2354                                 conn->params );
2355                 if (new_mask) {
2356                         pstrcpy(mask, new_mask);
2357                 }
2358         }
2359
2360         if (!has_wild) {
2361                 pstrcat(directory,"/");
2362                 pstrcat(directory,mask);
2363                 if (dirtype == 0) {
2364                         dirtype = FILE_ATTRIBUTE_NORMAL;
2365                 }
2366
2367                 status = check_name(conn, directory);
2368                 if (!NT_STATUS_IS_OK(status)) {
2369                         return status;
2370                 }
2371
2372                 status = do_unlink(conn, req, directory, dirtype);
2373                 if (!NT_STATUS_IS_OK(status)) {
2374                         return status;
2375                 }
2376
2377                 count++;
2378         } else {
2379                 struct smb_Dir *dir_hnd = NULL;
2380                 long offset = 0;
2381                 const char *dname;
2382
2383                 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2384                         return NT_STATUS_OBJECT_NAME_INVALID;
2385                 }
2386
2387                 if (strequal(mask,"????????.???")) {
2388                         pstrcpy(mask,"*");
2389                 }
2390
2391                 status = check_name(conn, directory);
2392                 if (!NT_STATUS_IS_OK(status)) {
2393                         return status;
2394                 }
2395
2396                 dir_hnd = OpenDir(conn, directory, mask, dirtype);
2397                 if (dir_hnd == NULL) {
2398                         return map_nt_error_from_unix(errno);
2399                 }
2400                 
2401                 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2402                    the pattern matches against the long name, otherwise the short name 
2403                    We don't implement this yet XXXX
2404                 */
2405                 
2406                 status = NT_STATUS_NO_SUCH_FILE;
2407
2408                 while ((dname = ReadDirName(dir_hnd, &offset))) {
2409                         SMB_STRUCT_STAT st;
2410                         pstring fname;
2411                         pstrcpy(fname,dname);
2412
2413                         if (!is_visible_file(conn, directory, dname, &st, True)) {
2414                                 continue;
2415                         }
2416
2417                         /* Quick check for "." and ".." */
2418                         if (fname[0] == '.') {
2419                                 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
2420                                         continue;
2421                                 }
2422                         }
2423
2424                         if(!mask_match(fname, mask, conn->case_sensitive)) {
2425                                 continue;
2426                         }
2427                                 
2428                         slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2429
2430                         status = check_name(conn, fname);
2431                         if (!NT_STATUS_IS_OK(status)) {
2432                                 CloseDir(dir_hnd);
2433                                 return status;
2434                         }
2435
2436                         status = do_unlink(conn, req, fname, dirtype);
2437                         if (!NT_STATUS_IS_OK(status)) {
2438                                 continue;
2439                         }
2440
2441                         count++;
2442                         DEBUG(3,("unlink_internals: succesful unlink [%s]\n",
2443                                  fname));
2444                 }
2445                 CloseDir(dir_hnd);
2446         }
2447         
2448         if (count == 0 && NT_STATUS_IS_OK(status)) {
2449                 status = map_nt_error_from_unix(errno);
2450         }
2451
2452         return status;
2453 }
2454
2455 /****************************************************************************
2456  Reply to a unlink
2457 ****************************************************************************/
2458
2459 void reply_unlink(connection_struct *conn, struct smb_request *req)
2460 {
2461         pstring name_in;
2462         char *name = NULL;
2463         uint32 dirtype;
2464         NTSTATUS status;
2465         BOOL path_contains_wcard = False;
2466         TALLOC_CTX *ctx = talloc_tos();
2467
2468         START_PROFILE(SMBunlink);
2469
2470         if (req->wct < 1) {
2471                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2472                 END_PROFILE(SMBunlink);
2473                 return;
2474         }
2475
2476         dirtype = SVAL(req->inbuf,smb_vwv0);
2477
2478         srvstr_get_path_wcard((char *)req->inbuf, req->flags2, name_in,
2479                               smb_buf(req->inbuf) + 1, sizeof(name_in), 0,
2480                               STR_TERMINATE, &status, &path_contains_wcard);
2481         if (!NT_STATUS_IS_OK(status)) {
2482                 reply_nterror(req, status);
2483                 END_PROFILE(SMBunlink);
2484                 return;
2485         }
2486
2487         status = resolve_dfspath_wcard(ctx, conn,
2488                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
2489                                        name_in,
2490                                        &name,
2491                                        &path_contains_wcard);
2492         if (!NT_STATUS_IS_OK(status)) {
2493                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2494                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2495                                         ERRSRV, ERRbadpath);
2496                         END_PROFILE(SMBunlink);
2497                         return;
2498                 }
2499                 reply_nterror(req, status);
2500                 END_PROFILE(SMBunlink);
2501                 return;
2502         }
2503
2504         DEBUG(3,("reply_unlink : %s\n",name));
2505
2506         status = unlink_internals(conn, req, dirtype, name,
2507                                   path_contains_wcard);
2508         if (!NT_STATUS_IS_OK(status)) {
2509                 if (open_was_deferred(req->mid)) {
2510                         /* We have re-scheduled this call. */
2511                         END_PROFILE(SMBunlink);
2512                         return;
2513                 }
2514                 reply_nterror(req, status);
2515                 END_PROFILE(SMBunlink);
2516                 return;
2517         }
2518
2519         reply_outbuf(req, 0, 0);
2520         END_PROFILE(SMBunlink);
2521
2522         return;
2523 }
2524
2525 /****************************************************************************
2526  Fail for readbraw.
2527 ****************************************************************************/
2528
2529 static void fail_readraw(void)
2530 {
2531         pstring errstr;
2532         slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2533                 strerror(errno) );
2534         exit_server_cleanly(errstr);
2535 }
2536
2537 /****************************************************************************
2538  Fake (read/write) sendfile. Returns -1 on read or write fail.
2539 ****************************************************************************/
2540
2541 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2542                              size_t nread)
2543 {
2544         size_t bufsize;
2545         size_t tosend = nread;
2546         char *buf;
2547
2548         if (nread == 0) {
2549                 return 0;
2550         }
2551
2552         bufsize = MIN(nread, 65536);
2553
2554         if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2555                 return -1;
2556         }
2557
2558         while (tosend > 0) {
2559                 ssize_t ret;
2560                 size_t cur_read;
2561
2562                 if (tosend > bufsize) {
2563                         cur_read = bufsize;
2564                 } else {
2565                         cur_read = tosend;
2566                 }
2567                 ret = read_file(fsp,buf,startpos,cur_read);
2568                 if (ret == -1) {
2569                         SAFE_FREE(buf);
2570                         return -1;
2571                 }
2572
2573                 /* If we had a short read, fill with zeros. */
2574                 if (ret < cur_read) {
2575                         memset(buf, '\0', cur_read - ret);
2576                 }
2577
2578                 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2579                         SAFE_FREE(buf);
2580                         return -1;
2581                 }
2582                 tosend -= cur_read;
2583                 startpos += cur_read;
2584         }
2585
2586         SAFE_FREE(buf);
2587         return (ssize_t)nread;
2588 }
2589
2590 /****************************************************************************
2591  Return a readbraw error (4 bytes of zero).
2592 ****************************************************************************/
2593
2594 static void reply_readbraw_error(void)
2595 {
2596         char header[4];
2597         SIVAL(header,0,0);
2598         if (write_data(smbd_server_fd(),header,4) != 4) {
2599                 fail_readraw();
2600         }
2601 }
2602
2603 /****************************************************************************
2604  Use sendfile in readbraw.
2605 ****************************************************************************/
2606
2607 void send_file_readbraw(connection_struct *conn,
2608                         files_struct *fsp,
2609                         SMB_OFF_T startpos,
2610                         size_t nread,
2611                         ssize_t mincount)
2612 {
2613         char *outbuf = NULL;
2614         ssize_t ret=0;
2615
2616 #if defined(WITH_SENDFILE)
2617         /*
2618          * We can only use sendfile on a non-chained packet 
2619          * but we can use on a non-oplocked file. tridge proved this
2620          * on a train in Germany :-). JRA.
2621          * reply_readbraw has already checked the length.
2622          */
2623
2624         if ( (chain_size == 0) && (nread > 0) &&
2625             (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2626                 char header[4];
2627                 DATA_BLOB header_blob;
2628
2629                 _smb_setlen(header,nread);
2630                 header_blob = data_blob_const(header, 4);
2631
2632                 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd,
2633                                 &header_blob, startpos, nread) == -1) {
2634                         /* Returning ENOSYS means no data at all was sent.
2635                          * Do this as a normal read. */
2636                         if (errno == ENOSYS) {
2637                                 goto normal_readbraw;
2638                         }
2639
2640                         /*
2641                          * Special hack for broken Linux with no working sendfile. If we
2642                          * return EINTR we sent the header but not the rest of the data.
2643                          * Fake this up by doing read/write calls.
2644                          */
2645                         if (errno == EINTR) {
2646                                 /* Ensure we don't do this again. */
2647                                 set_use_sendfile(SNUM(conn), False);
2648                                 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2649
2650                                 if (fake_sendfile(fsp, startpos, nread) == -1) {
2651                                         DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2652                                                 fsp->fsp_name, strerror(errno) ));
2653                                         exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2654                                 }
2655                                 return;
2656                         }
2657
2658                         DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2659                                 fsp->fsp_name, strerror(errno) ));
2660                         exit_server_cleanly("send_file_readbraw sendfile failed");
2661                 }
2662
2663                 return;
2664         }
2665 #endif
2666
2667 normal_readbraw:
2668
2669         outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2670         if (!outbuf) {
2671                 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2672                         (unsigned)(nread+4)));
2673                 reply_readbraw_error();
2674                 return;
2675         }
2676
2677         if (nread > 0) {
2678                 ret = read_file(fsp,outbuf+4,startpos,nread);
2679 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2680                 if (ret < mincount)
2681                         ret = 0;
2682 #else
2683                 if (ret < nread)
2684                         ret = 0;
2685 #endif
2686         }
2687
2688         _smb_setlen(outbuf,ret);
2689         if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2690                 fail_readraw();
2691
2692         TALLOC_FREE(outbuf);
2693 }
2694
2695 /****************************************************************************
2696  Reply to a readbraw (core+ protocol).
2697 ****************************************************************************/
2698
2699 void reply_readbraw(connection_struct *conn, struct smb_request *req)
2700 {
2701         ssize_t maxcount,mincount;
2702         size_t nread = 0;
2703         SMB_OFF_T startpos;
2704         files_struct *fsp;
2705         SMB_STRUCT_STAT st;
2706         SMB_OFF_T size = 0;
2707
2708         START_PROFILE(SMBreadbraw);
2709
2710         if (srv_is_signing_active()) {
2711                 exit_server_cleanly("reply_readbraw: SMB signing is active - "
2712                         "raw reads/writes are disallowed.");
2713         }
2714
2715         if (req->wct < 8) {
2716                 reply_readbraw_error();
2717                 END_PROFILE(SMBreadbraw);
2718                 return;
2719         }
2720
2721         /*
2722          * Special check if an oplock break has been issued
2723          * and the readraw request croses on the wire, we must
2724          * return a zero length response here.
2725          */
2726
2727         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
2728
2729         /*
2730          * We have to do a check_fsp by hand here, as
2731          * we must always return 4 zero bytes on error,
2732          * not a NTSTATUS.
2733          */
2734
2735         if (!fsp || !conn || conn != fsp->conn ||
2736                         current_user.vuid != fsp->vuid ||
2737                         fsp->is_directory || fsp->fh->fd == -1) {
2738                 /*
2739                  * fsp could be NULL here so use the value from the packet. JRA.
2740                  */
2741                 DEBUG(3,("reply_readbraw: fnum %d not valid "
2742                         "- cache prime?\n",
2743                         (int)SVAL(req->inbuf,smb_vwv0)));
2744                 reply_readbraw_error();
2745                 END_PROFILE(SMBreadbraw);
2746                 return;
2747         }
2748
2749         /* Do a "by hand" version of CHECK_READ. */
2750         if (!(fsp->can_read ||
2751                         ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
2752                                 (fsp->access_mask & FILE_EXECUTE)))) {
2753                 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
2754                                 (int)SVAL(req->inbuf,smb_vwv0)));
2755                 reply_readbraw_error();
2756                 END_PROFILE(SMBreadbraw);
2757                 return;
2758         }
2759
2760         flush_write_cache(fsp, READRAW_FLUSH);
2761
2762         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv1);
2763         if(req->wct == 10) {
2764                 /*
2765                  * This is a large offset (64 bit) read.
2766                  */
2767 #ifdef LARGE_SMB_OFF_T
2768
2769                 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv8)) << 32);
2770
2771 #else /* !LARGE_SMB_OFF_T */
2772
2773                 /*
2774                  * Ensure we haven't been sent a >32 bit offset.
2775                  */
2776
2777                 if(IVAL(req->inbuf,smb_vwv8) != 0) {
2778                         DEBUG(0,("reply_readbraw: large offset "
2779                                 "(%x << 32) used and we don't support "
2780                                 "64 bit offsets.\n",
2781                         (unsigned int)IVAL(req->inbuf,smb_vwv8) ));
2782                         reply_readbraw_error();
2783                         END_PROFILE(SMBreadbraw);
2784                         return;
2785                 }
2786
2787 #endif /* LARGE_SMB_OFF_T */
2788
2789                 if(startpos < 0) {
2790                         DEBUG(0,("reply_readbraw: negative 64 bit "
2791                                 "readraw offset (%.0f) !\n",
2792                                 (double)startpos ));
2793                         reply_readbraw_error();
2794                         END_PROFILE(SMBreadbraw);
2795                         return;
2796                 }      
2797         }
2798
2799         maxcount = (SVAL(req->inbuf,smb_vwv3) & 0xFFFF);
2800         mincount = (SVAL(req->inbuf,smb_vwv4) & 0xFFFF);
2801
2802         /* ensure we don't overrun the packet size */
2803         maxcount = MIN(65535,maxcount);
2804
2805         if (is_locked(fsp,(uint32)req->smbpid,
2806                         (SMB_BIG_UINT)maxcount,
2807                         (SMB_BIG_UINT)startpos,
2808                         READ_LOCK)) {
2809                 reply_readbraw_error();
2810                 END_PROFILE(SMBreadbraw);
2811                 return;
2812         }
2813
2814         if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2815                 size = st.st_size;
2816         }
2817
2818         if (startpos >= size) {
2819                 nread = 0;
2820         } else {
2821                 nread = MIN(maxcount,(size - startpos));
2822         }
2823
2824 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2825         if (nread < mincount)
2826                 nread = 0;
2827 #endif
2828   
2829         DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
2830                 "min=%lu nread=%lu\n",
2831                 fsp->fnum, (double)startpos,
2832                 (unsigned long)maxcount,
2833                 (unsigned long)mincount,
2834                 (unsigned long)nread ) );
2835   
2836         send_file_readbraw(conn, fsp, startpos, nread, mincount);
2837
2838         DEBUG(5,("reply_readbraw finished\n"));
2839         END_PROFILE(SMBreadbraw);
2840 }
2841
2842 #undef DBGC_CLASS
2843 #define DBGC_CLASS DBGC_LOCKING
2844
2845 /****************************************************************************
2846  Reply to a lockread (core+ protocol).
2847 ****************************************************************************/
2848
2849 void reply_lockread(connection_struct *conn, struct smb_request *req)
2850 {
2851         ssize_t nread = -1;
2852         char *data;
2853         SMB_OFF_T startpos;
2854         size_t numtoread;
2855         NTSTATUS status;
2856         files_struct *fsp;
2857         struct byte_range_lock *br_lck = NULL;
2858         char *p = NULL;
2859
2860         START_PROFILE(SMBlockread);
2861
2862         if (req->wct < 5) {
2863                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2864                 END_PROFILE(SMBlockread);
2865                 return;
2866         }
2867
2868         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
2869
2870         if (!check_fsp(conn, req, fsp, &current_user)) {
2871                 END_PROFILE(SMBlockread);
2872                 return;
2873         }
2874
2875         if (!CHECK_READ(fsp,req->inbuf)) {
2876                 reply_doserror(req, ERRDOS, ERRbadaccess);
2877                 END_PROFILE(SMBlockread);
2878                 return;
2879         }
2880
2881         release_level_2_oplocks_on_change(fsp);
2882
2883         numtoread = SVAL(req->inbuf,smb_vwv1);
2884         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
2885
2886         numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
2887
2888         reply_outbuf(req, 5, numtoread + 3);
2889
2890         data = smb_buf(req->outbuf) + 3;
2891         
2892         /*
2893          * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2894          * protocol request that predates the read/write lock concept. 
2895          * Thus instead of asking for a read lock here we need to ask
2896          * for a write lock. JRA.
2897          * Note that the requested lock size is unaffected by max_recv.
2898          */
2899         
2900         br_lck = do_lock(smbd_messaging_context(),
2901                         fsp,
2902                         req->smbpid,
2903                         (SMB_BIG_UINT)numtoread,
2904                         (SMB_BIG_UINT)startpos,
2905                         WRITE_LOCK,
2906                         WINDOWS_LOCK,
2907                         False, /* Non-blocking lock. */
2908                         &status,
2909                         NULL);
2910         TALLOC_FREE(br_lck);
2911
2912         if (NT_STATUS_V(status)) {
2913                 reply_nterror(req, status);
2914                 END_PROFILE(SMBlockread);
2915                 return;
2916         }
2917
2918         /*
2919          * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2920          */
2921
2922         if (numtoread > max_recv) {
2923                 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2924 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2925                         (unsigned int)numtoread, (unsigned int)max_recv ));
2926                 numtoread = MIN(numtoread,max_recv);
2927         }
2928         nread = read_file(fsp,data,startpos,numtoread);
2929
2930         if (nread < 0) {
2931                 reply_unixerror(req, ERRDOS, ERRnoaccess);
2932                 END_PROFILE(SMBlockread);
2933                 return;
2934         }
2935         
2936         set_message(NULL, (char *)req->outbuf, 5, nread+3, False);
2937
2938         SSVAL(req->outbuf,smb_vwv0,nread);
2939         SSVAL(req->outbuf,smb_vwv5,nread+3);
2940         p = smb_buf(req->outbuf);
2941         SCVAL(p,0,0); /* pad byte. */
2942         SSVAL(p,1,nread);
2943         
2944         DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2945                  fsp->fnum, (int)numtoread, (int)nread));
2946
2947         END_PROFILE(SMBlockread);
2948         return;
2949 }
2950
2951 #undef DBGC_CLASS
2952 #define DBGC_CLASS DBGC_ALL
2953
2954 /****************************************************************************
2955  Reply to a read.
2956 ****************************************************************************/
2957
2958 void reply_read(connection_struct *conn, struct smb_request *req)
2959 {
2960         size_t numtoread;
2961         ssize_t nread = 0;
2962         char *data;
2963         SMB_OFF_T startpos;
2964         int outsize = 0;
2965         files_struct *fsp;
2966
2967         START_PROFILE(SMBread);
2968
2969         if (req->wct < 3) {
2970                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2971                 END_PROFILE(SMBread);
2972                 return;
2973         }
2974
2975         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
2976
2977         if (!check_fsp(conn, req, fsp, &current_user)) {
2978                 END_PROFILE(SMBread);
2979                 return;
2980         }
2981
2982         if (!CHECK_READ(fsp,req->inbuf)) {
2983                 reply_doserror(req, ERRDOS, ERRbadaccess);
2984                 END_PROFILE(SMBread);
2985                 return;
2986         }
2987
2988         numtoread = SVAL(req->inbuf,smb_vwv1);
2989         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
2990
2991         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2992
2993         /*
2994          * The requested read size cannot be greater than max_recv. JRA.
2995          */
2996         if (numtoread > max_recv) {
2997                 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2998 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2999                         (unsigned int)numtoread, (unsigned int)max_recv ));
3000                 numtoread = MIN(numtoread,max_recv);
3001         }
3002
3003         reply_outbuf(req, 5, numtoread+3);
3004
3005         data = smb_buf(req->outbuf) + 3;
3006   
3007         if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtoread,
3008                       (SMB_BIG_UINT)startpos, READ_LOCK)) {
3009                 reply_doserror(req, ERRDOS,ERRlock);
3010                 END_PROFILE(SMBread);
3011                 return;
3012         }
3013
3014         if (numtoread > 0)
3015                 nread = read_file(fsp,data,startpos,numtoread);
3016
3017         if (nread < 0) {
3018                 reply_unixerror(req, ERRDOS,ERRnoaccess);
3019                 END_PROFILE(SMBread);
3020                 return;
3021         }
3022
3023         set_message(NULL, (char *)req->outbuf, 5, nread+3, False);
3024
3025         SSVAL(req->outbuf,smb_vwv0,nread);
3026         SSVAL(req->outbuf,smb_vwv5,nread+3);
3027         SCVAL(smb_buf(req->outbuf),0,1);
3028         SSVAL(smb_buf(req->outbuf),1,nread);
3029   
3030         DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3031                 fsp->fnum, (int)numtoread, (int)nread ) );
3032
3033         END_PROFILE(SMBread);
3034         return;
3035 }
3036
3037 /****************************************************************************
3038  Setup readX header.
3039 ****************************************************************************/
3040
3041 static int setup_readX_header(const uint8 *inbuf, uint8 *outbuf,
3042                               size_t smb_maxcnt)
3043 {
3044         int outsize;
3045         char *data;
3046
3047         outsize = set_message((char *)inbuf, (char *)outbuf,12,smb_maxcnt,
3048                               False);
3049         data = smb_buf(outbuf);
3050
3051         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3052         SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3053         SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
3054         SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3055         SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
3056         SCVAL(outbuf,smb_vwv0,0xFF);
3057         /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3058         _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3059         return outsize;
3060 }
3061
3062 /****************************************************************************
3063  Reply to a read and X - possibly using sendfile.
3064 ****************************************************************************/
3065
3066 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3067                             files_struct *fsp, SMB_OFF_T startpos,
3068                             size_t smb_maxcnt)
3069 {
3070         SMB_STRUCT_STAT sbuf;
3071         ssize_t nread = -1;
3072
3073         if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3074                 reply_unixerror(req, ERRDOS, ERRnoaccess);
3075                 return;
3076         }
3077
3078         if (startpos > sbuf.st_size) {
3079                 smb_maxcnt = 0;
3080         } else if (smb_maxcnt > (sbuf.st_size - startpos)) {
3081                 smb_maxcnt = (sbuf.st_size - startpos);
3082         }
3083
3084         if (smb_maxcnt == 0) {
3085                 goto normal_read;
3086         }
3087
3088 #if defined(WITH_SENDFILE)
3089         /*
3090          * We can only use sendfile on a non-chained packet 
3091          * but we can use on a non-oplocked file. tridge proved this
3092          * on a train in Germany :-). JRA.
3093          */
3094
3095         if ((chain_size == 0) && (CVAL(req->inbuf,smb_vwv0) == 0xFF) &&
3096             lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
3097                 uint8 headerbuf[smb_size + 12 * 2];
3098                 DATA_BLOB header;
3099
3100                 /* 
3101                  * Set up the packet header before send. We
3102                  * assume here the sendfile will work (get the
3103                  * correct amount of data).
3104                  */
3105
3106                 header = data_blob_const(headerbuf, sizeof(headerbuf));
3107
3108                 construct_reply_common((char *)req->inbuf, (char *)headerbuf);
3109                 setup_readX_header(req->inbuf, headerbuf, smb_maxcnt);
3110
3111                 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
3112                         /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
3113                         if (errno == ENOSYS) {
3114                                 goto normal_read;
3115                         }
3116
3117                         /*
3118                          * Special hack for broken Linux with no working sendfile. If we
3119                          * return EINTR we sent the header but not the rest of the data.
3120                          * Fake this up by doing read/write calls.
3121                          */
3122
3123                         if (errno == EINTR) {
3124                                 /* Ensure we don't do this again. */
3125                                 set_use_sendfile(SNUM(conn), False);
3126                                 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3127                                 nread = fake_sendfile(fsp, startpos,
3128                                                       smb_maxcnt);
3129                                 if (nread == -1) {
3130                                         DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3131                                                 fsp->fsp_name, strerror(errno) ));
3132                                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
3133                                 }
3134                                 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3135                                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3136                                 /* No outbuf here means successful sendfile. */
3137                                 TALLOC_FREE(req->outbuf);
3138                                 return;
3139                         }
3140
3141                         DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3142                                 fsp->fsp_name, strerror(errno) ));
3143                         exit_server_cleanly("send_file_readX sendfile failed");
3144                 }
3145
3146                 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3147                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3148                 /* No outbuf here means successful sendfile. */
3149                 TALLOC_FREE(req->outbuf);
3150                 return;
3151         }
3152 #endif
3153
3154 normal_read:
3155
3156         if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3157                 uint8 headerbuf[smb_size + 2*12];
3158
3159                 construct_reply_common((char *)req->inbuf, (char *)headerbuf);
3160                 setup_readX_header(req->inbuf, headerbuf, smb_maxcnt);
3161
3162                 /* Send out the header. */
3163                 if (write_data(smbd_server_fd(), (char *)headerbuf,
3164                                sizeof(headerbuf)) != sizeof(headerbuf)) {
3165                         DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3166                                 fsp->fsp_name, strerror(errno) ));
3167                         exit_server_cleanly("send_file_readX sendfile failed");
3168                 }
3169                 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3170                 if (nread == -1) {
3171                         DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3172                                 fsp->fsp_name, strerror(errno) ));
3173                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
3174                 }
3175                 TALLOC_FREE(req->outbuf);
3176                 return;
3177         } else {
3178                 reply_outbuf(req, 12, smb_maxcnt);
3179
3180                 nread = read_file(fsp, smb_buf(req->outbuf), startpos,
3181                                   smb_maxcnt);
3182                 if (nread < 0) {
3183                         reply_unixerror(req, ERRDOS, ERRnoaccess);
3184                         return;
3185                 }
3186
3187                 setup_readX_header(req->inbuf, req->outbuf, nread);
3188
3189                 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3190                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3191
3192                 chain_reply(req);
3193
3194                 return;
3195         }
3196 }
3197
3198 /****************************************************************************
3199  Reply to a read and X.
3200 ****************************************************************************/
3201
3202 void reply_read_and_X(connection_struct *conn, struct smb_request *req)
3203 {
3204         files_struct *fsp;
3205         SMB_OFF_T startpos;
3206         size_t smb_maxcnt;
3207         BOOL big_readX = False;
3208 #if 0
3209         size_t smb_mincnt = SVAL(req->inbuf,smb_vwv6);
3210 #endif
3211
3212         START_PROFILE(SMBreadX);
3213
3214         if ((req->wct != 10) && (req->wct != 12)) {
3215                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3216                 return;
3217         }
3218
3219         fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
3220         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
3221         smb_maxcnt = SVAL(req->inbuf,smb_vwv5);
3222
3223         /* If it's an IPC, pass off the pipe handler. */
3224         if (IS_IPC(conn)) {
3225                 reply_pipe_read_and_X(req);
3226                 END_PROFILE(SMBreadX);
3227                 return;
3228         }
3229
3230         if (!check_fsp(conn, req, fsp, &current_user)) {
3231                 END_PROFILE(SMBreadX);
3232                 return;
3233         }
3234
3235         if (!CHECK_READ(fsp,req->inbuf)) {
3236                 reply_doserror(req, ERRDOS,ERRbadaccess);
3237                 END_PROFILE(SMBreadX);
3238                 return;
3239         }
3240
3241         if (global_client_caps & CAP_LARGE_READX) {
3242                 size_t upper_size = SVAL(req->inbuf,smb_vwv7);
3243                 smb_maxcnt |= (upper_size<<16);
3244                 if (upper_size > 1) {
3245                         /* Can't do this on a chained packet. */
3246                         if ((CVAL(req->inbuf,smb_vwv0) != 0xFF)) {
3247                                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3248                                 END_PROFILE(SMBreadX);
3249                                 return;
3250                         }
3251                         /* We currently don't do this on signed or sealed data. */
3252                         if (srv_is_signing_active() || srv_encryption_on()) {
3253                                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3254                                 END_PROFILE(SMBreadX);
3255                                 return;
3256                         }
3257                         /* Is there room in the reply for this data ? */
3258                         if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2)))  {
3259                                 reply_nterror(req,
3260                                               NT_STATUS_INVALID_PARAMETER);
3261                                 END_PROFILE(SMBreadX);
3262                                 return;
3263                         }
3264                         big_readX = True;
3265                 }
3266         }
3267
3268         if (req->wct == 12) {
3269 #ifdef LARGE_SMB_OFF_T
3270                 /*
3271                  * This is a large offset (64 bit) read.
3272                  */
3273                 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv10)) << 32);
3274
3275 #else /* !LARGE_SMB_OFF_T */
3276
3277                 /*
3278                  * Ensure we haven't been sent a >32 bit offset.
3279                  */
3280
3281                 if(IVAL(req->inbuf,smb_vwv10) != 0) {
3282                         DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3283                                  "used and we don't support 64 bit offsets.\n",
3284                                  (unsigned int)IVAL(req->inbuf,smb_vwv10) ));
3285                         END_PROFILE(SMBreadX);
3286                         reply_doserror(req, ERRDOS, ERRbadaccess);
3287                         return;
3288                 }
3289
3290 #endif /* LARGE_SMB_OFF_T */
3291
3292         }
3293
3294         if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)smb_maxcnt,
3295                       (SMB_BIG_UINT)startpos, READ_LOCK)) {
3296                 END_PROFILE(SMBreadX);
3297                 reply_doserror(req, ERRDOS, ERRlock);
3298                 return;
3299         }
3300
3301         if (!big_readX
3302             && schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3303                 END_PROFILE(SMBreadX);
3304                 return;
3305         }
3306
3307         send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3308
3309         END_PROFILE(SMBreadX);
3310         return;
3311 }
3312
3313 /****************************************************************************
3314  Error replies to writebraw must have smb_wct == 1. Fix this up.
3315 ****************************************************************************/
3316
3317 void error_to_writebrawerr(struct smb_request *req)
3318 {
3319         uint8 *old_outbuf = req->outbuf;
3320
3321         reply_outbuf(req, 1, 0);
3322
3323         memcpy(req->outbuf, old_outbuf, smb_size);
3324         TALLOC_FREE(old_outbuf);
3325 }
3326
3327 /****************************************************************************
3328  Reply to a writebraw (core+ or LANMAN1.0 protocol).
3329 ****************************************************************************/
3330
3331 void reply_writebraw(connection_struct *conn, struct smb_request *req)
3332 {
3333         int outsize = 0;
3334         char *buf = NULL;
3335         ssize_t nwritten=0;
3336         ssize_t total_written=0;
3337         size_t numtowrite=0;
3338         size_t tcount;
3339         SMB_OFF_T startpos;
3340         char *data=NULL;
3341         BOOL write_through;
3342         files_struct *fsp;
3343         NTSTATUS status;
3344
3345         START_PROFILE(SMBwritebraw);
3346
3347         /*
3348          * If we ever reply with an error, it must have the SMB command
3349          * type of SMBwritec, not SMBwriteBraw, as this tells the client
3350          * we're finished.
3351          */
3352         SCVAL(req->inbuf,smb_com,SMBwritec);
3353
3354         if (srv_is_signing_active()) {
3355                 END_PROFILE(SMBwritebraw);
3356                 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3357                                 "raw reads/writes are disallowed.");
3358         }
3359
3360         if (req->wct < 12) {
3361                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3362                 error_to_writebrawerr(req);
3363                 END_PROFILE(SMBwritebraw);
3364                 return;
3365         }
3366
3367         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3368         if (!check_fsp(conn, req, fsp, &current_user)) {
3369                 error_to_writebrawerr(req);
3370                 END_PROFILE(SMBwritebraw);
3371                 return;
3372         }
3373
3374         if (!CHECK_WRITE(fsp)) {
3375                 reply_doserror(req, ERRDOS, ERRbadaccess);
3376                 error_to_writebrawerr(req);
3377                 END_PROFILE(SMBwritebraw);
3378                 return;
3379         }
3380
3381         tcount = IVAL(req->inbuf,smb_vwv1);
3382         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
3383         write_through = BITSETW(req->inbuf+smb_vwv7,0);
3384
3385         /* We have to deal with slightly different formats depending
3386                 on whether we are using the core+ or lanman1.0 protocol */
3387
3388         if(Protocol <= PROTOCOL_COREPLUS) {
3389                 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3390                 data = smb_buf(req->inbuf);
3391         } else {
3392                 numtowrite = SVAL(req->inbuf,smb_vwv10);
3393                 data = smb_base(req->inbuf) + SVAL(req->inbuf, smb_vwv11);
3394         }
3395
3396         /* Ensure we don't write bytes past the end of this packet. */
3397         if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3398                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3399                 error_to_writebrawerr(req);
3400                 END_PROFILE(SMBwritebraw);
3401                 return;
3402         }
3403
3404         if (is_locked(fsp,(uint32)req->smbpid,(SMB_BIG_UINT)tcount,
3405                                 (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3406                 reply_doserror(req, ERRDOS, ERRlock);
3407                 error_to_writebrawerr(req);
3408                 END_PROFILE(SMBwritebraw);
3409                 return;
3410         }
3411
3412         if (numtowrite>0) {
3413                 nwritten = write_file(fsp,data,startpos,numtowrite);
3414         }
3415
3416         DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3417                         "wrote=%d sync=%d\n",
3418                 fsp->fnum, (double)startpos, (int)numtowrite,
3419                 (int)nwritten, (int)write_through));
3420
3421         if (nwritten < (ssize_t)numtowrite)  {
3422                 reply_unixerror(req, ERRHRD, ERRdiskfull);
3423                 error_to_writebrawerr(req);
3424                 END_PROFILE(SMBwritebraw);
3425                 return;
3426         }
3427
3428         total_written = nwritten;
3429
3430         /* Allocate a buffer of 64k + length. */
3431         buf = TALLOC_ARRAY(NULL, char, 65540);
3432         if (!buf) {
3433                 reply_doserror(req, ERRDOS, ERRnomem);
3434                 error_to_writebrawerr(req);
3435                 END_PROFILE(SMBwritebraw);
3436                 return;
3437         }
3438
3439         /* Return a SMBwritebraw message to the redirector to tell
3440          * it to send more bytes */
3441
3442         memcpy(buf, req->inbuf, smb_size);
3443         outsize = set_message(NULL,buf,
3444                         Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3445         SCVAL(buf,smb_com,SMBwritebraw);
3446         SSVALS(buf,smb_vwv0,0xFFFF);
3447         show_msg(buf);
3448         if (!send_smb(smbd_server_fd(),buf)) {
3449                 exit_server_cleanly("reply_writebraw: send_smb "
3450                         "failed.");
3451         }
3452
3453         /* Now read the raw data into the buffer and write it */
3454         if (read_smb_length(smbd_server_fd(),buf,SMB_SECONDARY_WAIT) == -1) {
3455                 exit_server_cleanly("secondary writebraw failed");
3456         }
3457
3458         /*
3459          * Even though this is not an smb message,
3460          * smb_len returns the generic length of a packet.
3461          */
3462
3463         numtowrite = smb_len(buf);
3464
3465         /* Set up outbuf to return the correct size */
3466         reply_outbuf(req, 1, 0);
3467
3468         if (numtowrite != 0) {
3469
3470                 if (numtowrite > 0xFFFF) {
3471                         DEBUG(0,("reply_writebraw: Oversize secondary write "
3472                                 "raw requested (%u). Terminating\n",
3473                                 (unsigned int)numtowrite ));
3474                         exit_server_cleanly("secondary writebraw failed");
3475                 }
3476
3477                 if (tcount > nwritten+numtowrite) {
3478                         DEBUG(3,("reply_writebraw: Client overestimated the "
3479                                 "write %d %d %d\n",
3480                                 (int)tcount,(int)nwritten,(int)numtowrite));
3481                 }
3482
3483                 if (read_data(smbd_server_fd(), buf+4, numtowrite)
3484                                         != numtowrite ) {
3485                         DEBUG(0,("reply_writebraw: Oversize secondary write "
3486                                 "raw read failed (%s). Terminating\n",
3487                                 strerror(errno) ));
3488                         exit_server_cleanly("secondary writebraw failed");
3489                 }
3490
3491                 nwritten = write_file(fsp,buf+4,startpos+nwritten,numtowrite);
3492                 if (nwritten == -1) {
3493                         TALLOC_FREE(buf);
3494                         reply_unixerror(req, ERRHRD, ERRdiskfull);
3495                         error_to_writebrawerr(req);
3496                         END_PROFILE(SMBwritebraw);
3497                         return;
3498                 }
3499
3500                 if (nwritten < (ssize_t)numtowrite) {
3501                         SCVAL(req->outbuf,smb_rcls,ERRHRD);
3502                         SSVAL(req->outbuf,smb_err,ERRdiskfull);
3503                 }
3504
3505                 if (nwritten > 0) {
3506                         total_written += nwritten;
3507                 }
3508         }
3509
3510         TALLOC_FREE(buf);
3511         SSVAL(req->outbuf,smb_vwv0,total_written);
3512
3513         status = sync_file(conn, fsp, write_through);
3514         if (!NT_STATUS_IS_OK(status)) {
3515                 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3516                         fsp->fsp_name, nt_errstr(status) ));
3517                 reply_nterror(req, status);
3518                 error_to_writebrawerr(req);
3519                 END_PROFILE(SMBwritebraw);
3520                 return;
3521         }
3522
3523         DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3524                 "wrote=%d\n",
3525                 fsp->fnum, (double)startpos, (int)numtowrite,
3526                 (int)total_written));
3527
3528         /* We won't return a status if write through is not selected - this
3529          * follows what WfWg does */
3530         END_PROFILE(SMBwritebraw);
3531
3532         if (!write_through && total_written==tcount) {
3533
3534 #if RABBIT_PELLET_FIX
3535                 /*
3536                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3537                  * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3538                  * JRA.
3539                  */
3540                 if (!send_keepalive(smbd_server_fd())) {
3541                         exit_server_cleanly("reply_writebraw: send of "
3542                                 "keepalive failed");
3543                 }
3544 #endif
3545                 TALLOC_FREE(req->outbuf);
3546         }
3547         return;
3548 }
3549
3550 #undef DBGC_CLASS
3551 #define DBGC_CLASS DBGC_LOCKING
3552
3553 /****************************************************************************
3554  Reply to a writeunlock (core+).
3555 ****************************************************************************/
3556
3557 void reply_writeunlock(connection_struct *conn, struct smb_request *req)
3558 {
3559         ssize_t nwritten = -1;
3560         size_t numtowrite;
3561         SMB_OFF_T startpos;
3562         char *data;
3563         NTSTATUS status = NT_STATUS_OK;
3564         files_struct *fsp;
3565
3566         START_PROFILE(SMBwriteunlock);
3567
3568         if (req->wct < 5) {
3569                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3570                 END_PROFILE(SMBwriteunlock);
3571                 return;
3572         }
3573         
3574         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3575
3576         if (!check_fsp(conn, req, fsp, &current_user)) {
3577                 END_PROFILE(SMBwriteunlock);
3578                 return;
3579         }
3580
3581         if (!CHECK_WRITE(fsp)) {
3582                 reply_doserror(req, ERRDOS,ERRbadaccess);
3583                 END_PROFILE(SMBwriteunlock);
3584                 return;
3585         }
3586
3587         numtowrite = SVAL(req->inbuf,smb_vwv1);
3588         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
3589         data = smb_buf(req->inbuf) + 3;
3590   
3591         if (numtowrite
3592             && is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
3593                          (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3594                 reply_doserror(req, ERRDOS, ERRlock);
3595                 END_PROFILE(SMBwriteunlock);
3596                 return;
3597         }
3598
3599         /* The special X/Open SMB protocol handling of
3600            zero length writes is *NOT* done for
3601            this call */
3602         if(numtowrite == 0) {
3603                 nwritten = 0;
3604         } else {
3605                 nwritten = write_file(fsp,data,startpos,numtowrite);
3606         }
3607   
3608         status = sync_file(conn, fsp, False /* write through */);
3609         if (!NT_STATUS_IS_OK(status)) {
3610                 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3611                         fsp->fsp_name, nt_errstr(status) ));
3612                 reply_nterror(req, status);
3613                 END_PROFILE(SMBwriteunlock);
3614                 return;
3615         }
3616
3617         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3618                 reply_unixerror(req, ERRHRD, ERRdiskfull);
3619                 END_PROFILE(SMBwriteunlock);
3620                 return;
3621         }
3622
3623         if (numtowrite) {
3624                 status = do_unlock(smbd_messaging_context(),
3625                                 fsp,
3626                                 req->smbpid,
3627                                 (SMB_BIG_UINT)numtowrite, 
3628                                 (SMB_BIG_UINT)startpos,
3629                                 WINDOWS_LOCK);
3630
3631                 if (NT_STATUS_V(status)) {
3632                         reply_nterror(req, status);
3633                         END_PROFILE(SMBwriteunlock);
3634                         return;
3635                 }
3636         }
3637
3638         reply_outbuf(req, 1, 0);
3639         
3640         SSVAL(req->outbuf,smb_vwv0,nwritten);
3641         
3642         DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3643                  fsp->fnum, (int)numtowrite, (int)nwritten));
3644         
3645         END_PROFILE(SMBwriteunlock);
3646         return;
3647 }
3648
3649 #undef DBGC_CLASS
3650 #define DBGC_CLASS DBGC_ALL
3651
3652 /****************************************************************************
3653  Reply to a write.
3654 ****************************************************************************/
3655
3656 void reply_write(connection_struct *conn, struct smb_request *req)
3657 {
3658         size_t numtowrite;
3659         ssize_t nwritten = -1;
3660         SMB_OFF_T startpos;
3661         char *data;
3662         files_struct *fsp;
3663         NTSTATUS status;
3664
3665         START_PROFILE(SMBwrite);
3666
3667         if (req->wct < 5) {
3668                 END_PROFILE(SMBwrite);
3669                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3670                 return;
3671         }
3672
3673         /* If it's an IPC, pass off the pipe handler. */
3674         if (IS_IPC(conn)) {
3675                 reply_pipe_write(req);
3676                 END_PROFILE(SMBwrite);
3677                 return;
3678         }
3679
3680         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3681
3682         if (!check_fsp(conn, req, fsp, &current_user)) {
3683                 END_PROFILE(SMBwrite);
3684                 return;
3685         }
3686
3687         if (!CHECK_WRITE(fsp)) {
3688                 reply_doserror(req, ERRDOS, ERRbadaccess);
3689                 END_PROFILE(SMBwrite);
3690                 return;
3691         }
3692
3693         numtowrite = SVAL(req->inbuf,smb_vwv1);
3694         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
3695         data = smb_buf(req->inbuf) + 3;
3696   
3697         if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
3698                       (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3699                 reply_doserror(req, ERRDOS, ERRlock);
3700                 END_PROFILE(SMBwrite);
3701                 return;
3702         }
3703
3704         /*
3705          * X/Open SMB protocol says that if smb_vwv1 is
3706          * zero then the file size should be extended or
3707          * truncated to the size given in smb_vwv[2-3].
3708          */
3709
3710         if(numtowrite == 0) {
3711                 /*
3712                  * This is actually an allocate call, and set EOF. JRA.
3713                  */
3714                 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3715                 if (nwritten < 0) {
3716                         reply_nterror(req, NT_STATUS_DISK_FULL);
3717  &