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