r25111: Move to talloced pathnames on most code paths.
[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         pstring mask;
1197         char *directory = NULL;
1198         pstring fname;
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         *mask = *fname = 0;
1233
1234         /* If we were called as SMBffirst then we must expect close. */
1235         if(CVAL(req->inbuf,smb_com) == SMBffirst) {
1236                 expect_close = True;
1237         }
1238
1239         reply_outbuf(req, 1, 3);
1240         maxentries = SVAL(req->inbuf,smb_vwv0);
1241         dirtype = SVAL(req->inbuf,smb_vwv1);
1242         p = smb_buf(req->inbuf) + 1;
1243         p += srvstr_get_path_wcard(ctx,
1244                                 (char *)req->inbuf,
1245                                 req->flags2,
1246                                 &path,
1247                                 p,
1248                                 0,
1249                                 STR_TERMINATE,
1250                                 &nt_status,
1251                                 &mask_contains_wcard);
1252         if (!NT_STATUS_IS_OK(nt_status)) {
1253                 reply_nterror(req, nt_status);
1254                 END_PROFILE(SMBsearch);
1255                 return;
1256         }
1257
1258         nt_status = resolve_dfspath_wcard(ctx, conn,
1259                                           req->flags2 & FLAGS2_DFS_PATHNAMES,
1260                                           path,
1261                                           &path,
1262                                           &mask_contains_wcard);
1263         if (!NT_STATUS_IS_OK(nt_status)) {
1264                 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1265                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1266                                         ERRSRV, ERRbadpath);
1267                         END_PROFILE(SMBsearch);
1268                         return;
1269                 }
1270                 reply_nterror(req, nt_status);
1271                 END_PROFILE(SMBsearch);
1272                 return;
1273         }
1274
1275         p++;
1276         status_len = SVAL(p, 0);
1277         p += 2;
1278
1279         /* dirtype &= ~aDIR; */
1280
1281         if (status_len == 0) {
1282                 SMB_STRUCT_STAT sbuf;
1283
1284                 nt_status = unix_convert(conn, path, True, &directory, NULL, &sbuf);
1285                 if (!NT_STATUS_IS_OK(nt_status)) {
1286                         reply_nterror(req, nt_status);
1287                         END_PROFILE(SMBsearch);
1288                         return;
1289                 }
1290
1291                 nt_status = check_name(conn, directory);
1292                 if (!NT_STATUS_IS_OK(nt_status)) {
1293                         reply_nterror(req, nt_status);
1294                         END_PROFILE(SMBsearch);
1295                         return;
1296                 }
1297
1298                 p = strrchr_m(directory,'/');
1299                 if (!p) {
1300                         pstrcpy(mask,directory);
1301                         directory = talloc_strdup(talloc_tos(),".");
1302                         if (!directory) {
1303                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
1304                                 END_PROFILE(SMBsearch);
1305                                 return;
1306                         }
1307                 } else {
1308                         *p = 0;
1309                         pstrcpy(mask,p+1);
1310                 }
1311
1312                 if (*directory == '\0') {
1313                         directory = talloc_strdup(talloc_tos(),".");
1314                         if (!directory) {
1315                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
1316                                 END_PROFILE(SMBsearch);
1317                                 return;
1318                         }
1319                 }
1320                 memset((char *)status,'\0',21);
1321                 SCVAL(status,0,(dirtype & 0x1F));
1322
1323                 nt_status = dptr_create(conn,
1324                                         directory,
1325                                         True,
1326                                         expect_close,
1327                                         req->smbpid,
1328                                         mask,
1329                                         mask_contains_wcard,
1330                                         dirtype,
1331                                         &conn->dirptr);
1332                 if (!NT_STATUS_IS_OK(nt_status)) {
1333                         reply_nterror(req, nt_status);
1334                         END_PROFILE(SMBsearch);
1335                         return;
1336                 }
1337                 dptr_num = dptr_dnum(conn->dirptr);
1338         } else {
1339                 int status_dirtype;
1340
1341                 memcpy(status,p,21);
1342                 status_dirtype = CVAL(status,0) & 0x1F;
1343                 if (status_dirtype != (dirtype & 0x1F)) {
1344                         dirtype = status_dirtype;
1345                 }
1346
1347                 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1348                 if (!conn->dirptr) {
1349                         goto SearchEmpty;
1350                 }
1351                 string_set(&conn->dirpath,dptr_path(dptr_num));
1352                 pstrcpy(mask, dptr_wcard(dptr_num));
1353                 /*
1354                  * For a 'continue' search we have no string. So
1355                  * check from the initial saved string.
1356                  */
1357                 mask_contains_wcard = ms_has_wild(mask);
1358                 dirtype = dptr_attr(dptr_num);
1359         }
1360
1361         DEBUG(4,("dptr_num is %d\n",dptr_num));
1362
1363         if ((dirtype&0x1F) == aVOLID) {
1364                 char buf[DIR_STRUCT_SIZE];
1365                 memcpy(buf,status,21);
1366                 make_dir_struct(buf,"???????????",volume_label(SNUM(conn)),
1367                                 0,aVOLID,0,!allow_long_path_components);
1368                 dptr_fill(buf+12,dptr_num);
1369                 if (dptr_zero(buf+12) && (status_len==0)) {
1370                         numentries = 1;
1371                 } else {
1372                         numentries = 0;
1373                 }
1374                 if (message_push_blob(&req->outbuf,
1375                                       data_blob_const(buf, sizeof(buf)))
1376                     == -1) {
1377                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1378                         END_PROFILE(SMBsearch);
1379                         return;
1380                 }
1381         } else {
1382                 unsigned int i;
1383                 maxentries = MIN(
1384                         maxentries,
1385                         ((BUFFER_SIZE -
1386                           ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1387                          /DIR_STRUCT_SIZE));
1388
1389                 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1390                         conn->dirpath,lp_dontdescend(SNUM(conn))));
1391                 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1392                         check_descend = True;
1393                 }
1394
1395                 for (i=numentries;(i<maxentries) && !finished;i++) {
1396                         finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1397                         if (!finished) {
1398                                 char buf[DIR_STRUCT_SIZE];
1399                                 memcpy(buf,status,21);
1400                                 make_dir_struct(buf,mask,fname,size, mode,date,
1401                                                 !allow_long_path_components);
1402                                 if (!dptr_fill(buf+12,dptr_num)) {
1403                                         break;
1404                                 }
1405                                 if (message_push_blob(&req->outbuf,
1406                                                       data_blob_const(buf, sizeof(buf)))
1407                                     == -1) {
1408                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1409                                         END_PROFILE(SMBsearch);
1410                                         return;
1411                                 }
1412                                 numentries++;
1413                         }
1414                 }
1415         }
1416
1417   SearchEmpty:
1418
1419         /* If we were called as SMBffirst with smb_search_id == NULL
1420                 and no entries were found then return error and close dirptr 
1421                 (X/Open spec) */
1422
1423         if (numentries == 0) {
1424                 dptr_close(&dptr_num);
1425         } else if(expect_close && status_len == 0) {
1426                 /* Close the dptr - we know it's gone */
1427                 dptr_close(&dptr_num);
1428         }
1429
1430         /* If we were called as SMBfunique, then we can close the dirptr now ! */
1431         if(dptr_num >= 0 && CVAL(req->inbuf,smb_com) == SMBfunique) {
1432                 dptr_close(&dptr_num);
1433         }
1434
1435         if ((numentries == 0) && !mask_contains_wcard) {
1436                 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1437                 END_PROFILE(SMBsearch);
1438                 return;
1439         }
1440
1441         SSVAL(req->outbuf,smb_vwv0,numentries);
1442         SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1443         SCVAL(smb_buf(req->outbuf),0,5);
1444         SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1445
1446         /* The replies here are never long name. */
1447         SSVAL(req->outbuf, smb_flg2,
1448               SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1449         if (!allow_long_path_components) {
1450                 SSVAL(req->outbuf, smb_flg2,
1451                       SVAL(req->outbuf, smb_flg2)
1452                       & (~FLAGS2_LONG_PATH_COMPONENTS));
1453         }
1454
1455         /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1456         SSVAL(req->outbuf, smb_flg2,
1457               (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1458
1459         if (!directory) {
1460                 directory = dptr_path(dptr_num);
1461         }
1462
1463         DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1464                 smb_fn_name(CVAL(req->inbuf,smb_com)),
1465                 mask,
1466                 directory ? directory : "./",
1467                 dirtype,
1468                 numentries,
1469                 maxentries ));
1470
1471         END_PROFILE(SMBsearch);
1472         return;
1473 }
1474
1475 /****************************************************************************
1476  Reply to a fclose (stop directory search).
1477 ****************************************************************************/
1478
1479 void reply_fclose(connection_struct *conn, struct smb_request *req)
1480 {
1481         int status_len;
1482         char status[21];
1483         int dptr_num= -2;
1484         char *p;
1485         char *path = NULL;
1486         NTSTATUS err;
1487         BOOL path_contains_wcard = False;
1488         TALLOC_CTX *ctx = talloc_tos();
1489
1490         START_PROFILE(SMBfclose);
1491
1492         if (lp_posix_pathnames()) {
1493                 reply_unknown_new(req, CVAL(req->inbuf, smb_com));
1494                 END_PROFILE(SMBfclose);
1495                 return;
1496         }
1497
1498         p = smb_buf(req->inbuf) + 1;
1499         p += srvstr_get_path_wcard(ctx,
1500                                 (char *)req->inbuf,
1501                                 req->flags2,
1502                                 &path,
1503                                 p,
1504                                 0,
1505                                 STR_TERMINATE,
1506                                 &err,
1507                                 &path_contains_wcard);
1508         if (!NT_STATUS_IS_OK(err)) {
1509                 reply_nterror(req, err);
1510                 END_PROFILE(SMBfclose);
1511                 return;
1512         }
1513         p++;
1514         status_len = SVAL(p,0);
1515         p += 2;
1516
1517         if (status_len == 0) {
1518                 reply_doserror(req, ERRSRV, ERRsrverror);
1519                 END_PROFILE(SMBfclose);
1520                 return;
1521         }
1522
1523         memcpy(status,p,21);
1524
1525         if(dptr_fetch(status+12,&dptr_num)) {
1526                 /*  Close the dptr - we know it's gone */
1527                 dptr_close(&dptr_num);
1528         }
1529
1530         reply_outbuf(req, 1, 0);
1531         SSVAL(req->outbuf,smb_vwv0,0);
1532
1533         DEBUG(3,("search close\n"));
1534
1535         END_PROFILE(SMBfclose);
1536         return;
1537 }
1538
1539 /****************************************************************************
1540  Reply to an open.
1541 ****************************************************************************/
1542
1543 void reply_open(connection_struct *conn, struct smb_request *req)
1544 {
1545         char *fname = NULL;
1546         uint32 fattr=0;
1547         SMB_OFF_T size = 0;
1548         time_t mtime=0;
1549         int info;
1550         SMB_STRUCT_STAT sbuf;
1551         files_struct *fsp;
1552         int oplock_request;
1553         int deny_mode;
1554         uint32 dos_attr;
1555         uint32 access_mask;
1556         uint32 share_mode;
1557         uint32 create_disposition;
1558         uint32 create_options = 0;
1559         NTSTATUS status;
1560         TALLOC_CTX *ctx = talloc_tos();
1561
1562         START_PROFILE(SMBopen);
1563
1564         if (req->wct < 2) {
1565                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1566                 END_PROFILE(SMBopen);
1567                 return;
1568         }
1569
1570         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1571         deny_mode = SVAL(req->inbuf,smb_vwv0);
1572         dos_attr = SVAL(req->inbuf,smb_vwv1);
1573
1574         srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname,
1575                         smb_buf(req->inbuf)+1, 0,
1576                         STR_TERMINATE, &status);
1577         if (!NT_STATUS_IS_OK(status)) {
1578                 reply_nterror(req, status);
1579                 END_PROFILE(SMBopen);
1580                 return;
1581         }
1582
1583         status = resolve_dfspath(ctx, conn,
1584                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
1585                                 fname,
1586                                 &fname);
1587         if (!NT_STATUS_IS_OK(status)) {
1588                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1589                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1590                                         ERRSRV, ERRbadpath);
1591                         END_PROFILE(SMBopen);
1592                         return;
1593                 }
1594                 reply_nterror(req, status);
1595                 END_PROFILE(SMBopen);
1596                 return;
1597         }
1598
1599         status = unix_convert(conn, fname, False, &fname, NULL, &sbuf);
1600         if (!NT_STATUS_IS_OK(status)) {
1601                 reply_nterror(req, status);
1602                 END_PROFILE(SMBopen);
1603                 return;
1604         }
1605     
1606         status = check_name(conn, fname);
1607         if (!NT_STATUS_IS_OK(status)) {
1608                 reply_nterror(req, status);
1609                 END_PROFILE(SMBopen);
1610                 return;
1611         }
1612
1613         if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
1614                         &access_mask, &share_mode, &create_disposition, &create_options)) {
1615                 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1616                 END_PROFILE(SMBopen);
1617                 return;
1618         }
1619
1620         status = open_file_ntcreate(conn, req, fname, &sbuf,
1621                         access_mask,
1622                         share_mode,
1623                         create_disposition,
1624                         create_options,
1625                         dos_attr,
1626                         oplock_request,
1627                         &info, &fsp);
1628
1629         if (!NT_STATUS_IS_OK(status)) {
1630                 if (open_was_deferred(req->mid)) {
1631                         END_PROFILE(SMBopen);
1632                         /* We have re-scheduled this call. */
1633                         return;
1634                 }
1635                 reply_openerror(req, status);
1636                 END_PROFILE(SMBopen);
1637                 return;
1638         }
1639
1640         size = sbuf.st_size;
1641         fattr = dos_mode(conn,fname,&sbuf);
1642         mtime = sbuf.st_mtime;
1643
1644         if (fattr & aDIR) {
1645                 DEBUG(3,("attempt to open a directory %s\n",fname));
1646                 close_file(fsp,ERROR_CLOSE);
1647                 reply_doserror(req, ERRDOS,ERRnoaccess);
1648                 END_PROFILE(SMBopen);
1649                 return;
1650         }
1651
1652         reply_outbuf(req, 7, 0);
1653         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1654         SSVAL(req->outbuf,smb_vwv1,fattr);
1655         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1656                 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1657         } else {
1658                 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1659         }
1660         SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1661         SSVAL(req->outbuf,smb_vwv6,deny_mode);
1662
1663         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1664                 SCVAL(req->outbuf,smb_flg,
1665                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1666         }
1667     
1668         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1669                 SCVAL(req->outbuf,smb_flg,
1670                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1671         }
1672         END_PROFILE(SMBopen);
1673         return;
1674 }
1675
1676 /****************************************************************************
1677  Reply to an open and X.
1678 ****************************************************************************/
1679
1680 void reply_open_and_X(connection_struct *conn, struct smb_request *req)
1681 {
1682         char *fname = NULL;
1683         uint16 open_flags;
1684         int deny_mode;
1685         uint32 smb_attr;
1686         /* Breakout the oplock request bits so we can set the
1687                 reply bits separately. */
1688         int ex_oplock_request;
1689         int core_oplock_request;
1690         int oplock_request;
1691 #if 0
1692         int smb_sattr = SVAL(req->inbuf,smb_vwv4);
1693         uint32 smb_time = make_unix_date3(req->inbuf+smb_vwv6);
1694 #endif
1695         int smb_ofun;
1696         uint32 fattr=0;
1697         int mtime=0;
1698         SMB_STRUCT_STAT sbuf;
1699         int smb_action = 0;
1700         files_struct *fsp;
1701         NTSTATUS status;
1702         SMB_BIG_UINT allocation_size;
1703         ssize_t retval = -1;
1704         uint32 access_mask;
1705         uint32 share_mode;
1706         uint32 create_disposition;
1707         uint32 create_options = 0;
1708         TALLOC_CTX *ctx = talloc_tos();
1709
1710         START_PROFILE(SMBopenX);
1711
1712         if (req->wct < 15) {
1713                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1714                 END_PROFILE(SMBopenX);
1715                 return;
1716         }
1717
1718         open_flags = SVAL(req->inbuf,smb_vwv2);
1719         deny_mode = SVAL(req->inbuf,smb_vwv3);
1720         smb_attr = SVAL(req->inbuf,smb_vwv5);
1721         ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1722         core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1723         oplock_request = ex_oplock_request | core_oplock_request;
1724         smb_ofun = SVAL(req->inbuf,smb_vwv8);
1725         allocation_size = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv9);
1726
1727         /* If it's an IPC, pass off the pipe handler. */
1728         if (IS_IPC(conn)) {
1729                 if (lp_nt_pipe_support()) {
1730                         reply_open_pipe_and_X(conn, req);
1731                 } else {
1732                         reply_doserror(req, ERRSRV, ERRaccess);
1733                 }
1734                 END_PROFILE(SMBopenX);
1735                 return;
1736         }
1737
1738         /* XXXX we need to handle passed times, sattr and flags */
1739         srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname,
1740                         smb_buf(req->inbuf), 0, STR_TERMINATE,
1741                         &status);
1742         if (!NT_STATUS_IS_OK(status)) {
1743                 reply_nterror(req, status);
1744                 END_PROFILE(SMBopenX);
1745                 return;
1746         }
1747
1748         status = resolve_dfspath(ctx, conn,
1749                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
1750                                 fname,
1751                                 &fname);
1752         if (!NT_STATUS_IS_OK(status)) {
1753                 END_PROFILE(SMBopenX);
1754                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1755                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1756                                         ERRSRV, ERRbadpath);
1757                         return;
1758                 }
1759                 reply_nterror(req, status);
1760                 return;
1761         }
1762
1763         status = unix_convert(conn, fname, False, &fname, NULL, &sbuf);
1764         if (!NT_STATUS_IS_OK(status)) {
1765                 reply_nterror(req, status);
1766                 END_PROFILE(SMBopenX);
1767                 return;
1768         }
1769
1770         status = check_name(conn, fname);
1771         if (!NT_STATUS_IS_OK(status)) {
1772                 reply_nterror(req, status);
1773                 END_PROFILE(SMBopenX);
1774                 return;
1775         }
1776
1777         if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
1778                                 &access_mask,
1779                                 &share_mode,
1780                                 &create_disposition,
1781                                 &create_options)) {
1782                 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1783                 END_PROFILE(SMBopenX);
1784                 return;
1785         }
1786
1787         status = open_file_ntcreate(conn, req, fname, &sbuf,
1788                         access_mask,
1789                         share_mode,
1790                         create_disposition,
1791                         create_options,
1792                         smb_attr,
1793                         oplock_request,
1794                         &smb_action, &fsp);
1795
1796         if (!NT_STATUS_IS_OK(status)) {
1797                 END_PROFILE(SMBopenX);
1798                 if (open_was_deferred(req->mid)) {
1799                         /* We have re-scheduled this call. */
1800                         return;
1801                 }
1802                 reply_openerror(req, status);
1803                 return;
1804         }
1805
1806         /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1807            if the file is truncated or created. */
1808         if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1809                 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1810                 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1811                         close_file(fsp,ERROR_CLOSE);
1812                         reply_nterror(req, NT_STATUS_DISK_FULL);
1813                         END_PROFILE(SMBopenX);
1814                         return;
1815                 }
1816                 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1817                 if (retval < 0) {
1818                         close_file(fsp,ERROR_CLOSE);
1819                         reply_nterror(req, NT_STATUS_DISK_FULL);
1820                         END_PROFILE(SMBopenX);
1821                         return;
1822                 }
1823                 sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
1824         }
1825
1826         fattr = dos_mode(conn,fname,&sbuf);
1827         mtime = sbuf.st_mtime;
1828         if (fattr & aDIR) {
1829                 close_file(fsp,ERROR_CLOSE);
1830                 reply_doserror(req, ERRDOS, ERRnoaccess);
1831                 END_PROFILE(SMBopenX);
1832                 return;
1833         }
1834
1835         /* If the caller set the extended oplock request bit
1836                 and we granted one (by whatever means) - set the
1837                 correct bit for extended oplock reply.
1838         */
1839
1840         if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1841                 smb_action |= EXTENDED_OPLOCK_GRANTED;
1842         }
1843
1844         if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1845                 smb_action |= EXTENDED_OPLOCK_GRANTED;
1846         }
1847
1848         /* If the caller set the core oplock request bit
1849                 and we granted one (by whatever means) - set the
1850                 correct bit for core oplock reply.
1851         */
1852
1853         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1854                 reply_outbuf(req, 19, 0);
1855         } else {
1856                 reply_outbuf(req, 15, 0);
1857         }
1858
1859         if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1860                 SCVAL(req->outbuf, smb_flg,
1861                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1862         }
1863
1864         if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1865                 SCVAL(req->outbuf, smb_flg,
1866                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1867         }
1868
1869         SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1870         SSVAL(req->outbuf,smb_vwv3,fattr);
1871         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1872                 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1873         } else {
1874                 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
1875         }
1876         SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_size);
1877         SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1878         SSVAL(req->outbuf,smb_vwv11,smb_action);
1879
1880         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1881                 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1882         }
1883
1884         END_PROFILE(SMBopenX);
1885         chain_reply(req);
1886         return;
1887 }
1888
1889 /****************************************************************************
1890  Reply to a SMBulogoffX.
1891  conn POINTER CAN BE NULL HERE !
1892 ****************************************************************************/
1893
1894 void reply_ulogoffX(connection_struct *conn, struct smb_request *req)
1895 {
1896         user_struct *vuser;
1897
1898         START_PROFILE(SMBulogoffX);
1899
1900         vuser = get_valid_user_struct(req->vuid);
1901
1902         if(vuser == NULL) {
1903                 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
1904                          req->vuid));
1905         }
1906
1907         /* in user level security we are supposed to close any files
1908                 open by this user */
1909         if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
1910                 file_close_user(req->vuid);
1911         }
1912
1913         invalidate_vuid(req->vuid);
1914
1915         reply_outbuf(req, 2, 0);
1916
1917         DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
1918
1919         END_PROFILE(SMBulogoffX);
1920         chain_reply(req);
1921 }
1922
1923 /****************************************************************************
1924  Reply to a mknew or a create.
1925 ****************************************************************************/
1926
1927 void reply_mknew(connection_struct *conn, struct smb_request *req)
1928 {
1929         char *fname = NULL;
1930         int com;
1931         uint32 fattr = 0;
1932         struct timespec ts[2];
1933         files_struct *fsp;
1934         int oplock_request = 0;
1935         SMB_STRUCT_STAT sbuf;
1936         NTSTATUS status;
1937         uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1938         uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1939         uint32 create_disposition;
1940         uint32 create_options = 0;
1941         TALLOC_CTX *ctx = talloc_tos();
1942
1943         START_PROFILE(SMBcreate);
1944
1945         if (req->wct < 3) {
1946                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1947                 END_PROFILE(SMBcreate);
1948                 return;
1949         }
1950
1951         fattr = SVAL(req->inbuf,smb_vwv0);
1952         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1953         com = SVAL(req->inbuf,smb_com);
1954
1955         ts[1] =convert_time_t_to_timespec(
1956                         srv_make_unix_date3(req->inbuf + smb_vwv1));
1957                         /* mtime. */
1958
1959         srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname,
1960                         smb_buf(req->inbuf) + 1, 0,
1961                         STR_TERMINATE, &status);
1962         if (!NT_STATUS_IS_OK(status)) {
1963                 reply_nterror(req, status);
1964                 END_PROFILE(SMBcreate);
1965                 return;
1966         }
1967
1968         status = resolve_dfspath(ctx, conn,
1969                         req->flags2 & FLAGS2_DFS_PATHNAMES,
1970                         fname,
1971                         &fname);
1972         if (!NT_STATUS_IS_OK(status)) {
1973                 END_PROFILE(SMBcreate);
1974                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1975                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1976                                         ERRSRV, ERRbadpath);
1977                         return;
1978                 }
1979                 reply_nterror(req, status);
1980                 return;
1981         }
1982
1983         status = unix_convert(conn, fname, False, &fname, NULL, &sbuf);
1984         if (!NT_STATUS_IS_OK(status)) {
1985                 reply_nterror(req, status);
1986                 END_PROFILE(SMBcreate);
1987                 return;
1988         }
1989
1990         status = check_name(conn, fname);
1991         if (!NT_STATUS_IS_OK(status)) {
1992                 reply_nterror(req, status);
1993                 END_PROFILE(SMBcreate);
1994                 return;
1995         }
1996
1997         if (fattr & aVOLID) {
1998                 DEBUG(0,("Attempt to create file (%s) with volid set - "
1999                         "please report this\n", fname));
2000         }
2001
2002         if(com == SMBmknew) {
2003                 /* We should fail if file exists. */
2004                 create_disposition = FILE_CREATE;
2005         } else {
2006                 /* Create if file doesn't exist, truncate if it does. */
2007                 create_disposition = FILE_OVERWRITE_IF;
2008         }
2009
2010         /* Open file using ntcreate. */
2011         status = open_file_ntcreate(conn, req, fname, &sbuf,
2012                                 access_mask,
2013                                 share_mode,
2014                                 create_disposition,
2015                                 create_options,
2016                                 fattr,
2017                                 oplock_request,
2018                                 NULL, &fsp);
2019
2020         if (!NT_STATUS_IS_OK(status)) {
2021                 END_PROFILE(SMBcreate);
2022                 if (open_was_deferred(req->mid)) {
2023                         /* We have re-scheduled this call. */
2024                         return;
2025                 }
2026                 reply_nterror(req, status);
2027                 return;
2028         }
2029
2030         ts[0] = get_atimespec(&sbuf); /* atime. */
2031         file_ntimes(conn, fname, ts);
2032
2033         reply_outbuf(req, 1, 0);
2034         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2035
2036         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2037                 SCVAL(req->outbuf,smb_flg,
2038                                 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2039         }
2040
2041         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2042                 SCVAL(req->outbuf,smb_flg,
2043                                 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2044         }
2045
2046         DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
2047         DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2048                                 fname, fsp->fh->fd, (unsigned int)fattr ) );
2049
2050         END_PROFILE(SMBcreate);
2051         return;
2052 }
2053
2054 /****************************************************************************
2055  Reply to a create temporary file.
2056 ****************************************************************************/
2057
2058 void reply_ctemp(connection_struct *conn, struct smb_request *req)
2059 {
2060         char *fname = NULL;
2061         uint32 fattr;
2062         files_struct *fsp;
2063         int oplock_request;
2064         int tmpfd;
2065         SMB_STRUCT_STAT sbuf;
2066         char *s;
2067         NTSTATUS status;
2068         TALLOC_CTX *ctx = talloc_tos();
2069
2070         START_PROFILE(SMBctemp);
2071
2072         if (req->wct < 3) {
2073                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2074                 END_PROFILE(SMBctemp);
2075                 return;
2076         }
2077
2078         fattr = SVAL(req->inbuf,smb_vwv0);
2079         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2080
2081         srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname,
2082                         smb_buf(req->inbuf)+1, 0, STR_TERMINATE,
2083                         &status);
2084         if (!NT_STATUS_IS_OK(status)) {
2085                 reply_nterror(req, status);
2086                 END_PROFILE(SMBctemp);
2087                 return;
2088         }
2089         if (*fname) {
2090                 fname = talloc_asprintf(ctx,
2091                                 "%s/TMXXXXXX",
2092                                 fname);
2093         } else {
2094                 fname = talloc_strdup(ctx, "TMXXXXXX");
2095         }
2096
2097         if (!fname) {
2098                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2099                 END_PROFILE(SMBctemp);
2100                 return;
2101         }
2102
2103         status = resolve_dfspath(ctx, conn,
2104                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
2105                                 fname,
2106                                 &fname);
2107         if (!NT_STATUS_IS_OK(status)) {
2108                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2109                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2110                                         ERRSRV, ERRbadpath);
2111                         END_PROFILE(SMBctemp);
2112                         return;
2113                 }
2114                 reply_nterror(req, status);
2115                 END_PROFILE(SMBctemp);
2116                 return;
2117         }
2118
2119         status = unix_convert(conn, fname, False, &fname, NULL, &sbuf);
2120         if (!NT_STATUS_IS_OK(status)) {
2121                 reply_nterror(req, status);
2122                 END_PROFILE(SMBctemp);
2123                 return;
2124         }
2125
2126         status = check_name(conn, CONST_DISCARD(char *,fname));
2127         if (!NT_STATUS_IS_OK(status)) {
2128                 reply_nterror(req, status);
2129                 END_PROFILE(SMBctemp);
2130                 return;
2131         }
2132
2133         tmpfd = smb_mkstemp(fname);
2134         if (tmpfd == -1) {
2135                 reply_unixerror(req, ERRDOS, ERRnoaccess);
2136                 END_PROFILE(SMBctemp);
2137                 return;
2138         }
2139
2140         SMB_VFS_STAT(conn,fname,&sbuf);
2141
2142         /* We should fail if file does not exist. */
2143         status = open_file_ntcreate(conn, req, fname, &sbuf,
2144                                 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
2145                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
2146                                 FILE_OPEN,
2147                                 0,
2148                                 fattr,
2149                                 oplock_request,
2150                                 NULL, &fsp);
2151
2152         /* close fd from smb_mkstemp() */
2153         close(tmpfd);
2154
2155         if (!NT_STATUS_IS_OK(status)) {
2156                 if (open_was_deferred(req->mid)) {
2157                         /* We have re-scheduled this call. */
2158                         END_PROFILE(SMBctemp);
2159                         return;
2160                 }
2161                 reply_openerror(req, status);
2162                 END_PROFILE(SMBctemp);
2163                 return;
2164         }
2165
2166         reply_outbuf(req, 1, 0);
2167         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2168
2169         /* the returned filename is relative to the directory */
2170         s = strrchr_m(fname, '/');
2171         if (!s) {
2172                 s = fname;
2173         } else {
2174                 s++;
2175         }
2176
2177 #if 0
2178         /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2179            thing in the byte section. JRA */
2180         SSVALS(p, 0, -1); /* what is this? not in spec */
2181 #endif
2182         if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2183             == -1) {
2184                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2185                 END_PROFILE(SMBctemp);
2186                 return;
2187         }
2188
2189         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2190                 SCVAL(req->outbuf, smb_flg,
2191                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2192         }
2193   
2194         if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2195                 SCVAL(req->outbuf, smb_flg,
2196                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2197         }
2198
2199         DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
2200         DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
2201                         (unsigned int)sbuf.st_mode ) );
2202
2203         END_PROFILE(SMBctemp);
2204         return;
2205 }
2206
2207 /*******************************************************************
2208  Check if a user is allowed to rename a file.
2209 ********************************************************************/
2210
2211 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2212                            uint16 dirtype, SMB_STRUCT_STAT *pst)
2213 {
2214         uint32 fmode;
2215
2216         if (!CAN_WRITE(conn)) {
2217                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2218         }
2219
2220         fmode = dos_mode(conn, fsp->fsp_name, pst);
2221         if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2222                 return NT_STATUS_NO_SUCH_FILE;
2223         }
2224
2225         if (S_ISDIR(pst->st_mode)) {
2226                 return NT_STATUS_OK;
2227         }
2228
2229         if (fsp->access_mask & DELETE_ACCESS) {
2230                 return NT_STATUS_OK;
2231         }
2232
2233         return NT_STATUS_ACCESS_DENIED;
2234 }
2235
2236 /*******************************************************************
2237  * unlink a file with all relevant access checks
2238  *******************************************************************/
2239
2240 static NTSTATUS do_unlink(connection_struct *conn, struct smb_request *req,
2241                           char *fname, uint32 dirtype)
2242 {
2243         SMB_STRUCT_STAT sbuf;
2244         uint32 fattr;
2245         files_struct *fsp;
2246         uint32 dirtype_orig = dirtype;
2247         NTSTATUS status;
2248
2249         DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2250
2251         if (!CAN_WRITE(conn)) {
2252                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2253         }
2254
2255         if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
2256                 return map_nt_error_from_unix(errno);
2257         }
2258
2259         fattr = dos_mode(conn,fname,&sbuf);
2260
2261         if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2262                 dirtype = aDIR|aARCH|aRONLY;
2263         }
2264
2265         dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2266         if (!dirtype) {
2267                 return NT_STATUS_NO_SUCH_FILE;
2268         }
2269
2270         if (!dir_check_ftype(conn, fattr, dirtype)) {
2271                 if (fattr & aDIR) {
2272                         return NT_STATUS_FILE_IS_A_DIRECTORY;
2273                 }
2274                 return NT_STATUS_NO_SUCH_FILE;
2275         }
2276
2277         if (dirtype_orig & 0x8000) {
2278                 /* These will never be set for POSIX. */
2279                 return NT_STATUS_NO_SUCH_FILE;
2280         }
2281
2282 #if 0
2283         if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2284                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2285         }
2286
2287         if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2288                 return NT_STATUS_NO_SUCH_FILE;
2289         }
2290
2291         if (dirtype & 0xFF00) {
2292                 /* These will never be set for POSIX. */
2293                 return NT_STATUS_NO_SUCH_FILE;
2294         }
2295
2296         dirtype &= 0xFF;
2297         if (!dirtype) {
2298                 return NT_STATUS_NO_SUCH_FILE;
2299         }
2300
2301         /* Can't delete a directory. */
2302         if (fattr & aDIR) {
2303                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2304         }
2305 #endif
2306
2307 #if 0 /* JRATEST */
2308         else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2309                 return NT_STATUS_OBJECT_NAME_INVALID;
2310 #endif /* JRATEST */
2311
2312         /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2313
2314           On a Windows share, a file with read-only dosmode can be opened with
2315           DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2316           fails with NT_STATUS_CANNOT_DELETE error.
2317
2318           This semantic causes a problem that a user can not
2319           rename a file with read-only dosmode on a Samba share
2320           from a Windows command prompt (i.e. cmd.exe, but can rename
2321           from Windows Explorer).
2322         */
2323
2324         if (!lp_delete_readonly(SNUM(conn))) {
2325                 if (fattr & aRONLY) {
2326                         return NT_STATUS_CANNOT_DELETE;
2327                 }
2328         }
2329
2330         /* On open checks the open itself will check the share mode, so
2331            don't do it here as we'll get it wrong. */
2332
2333         status = open_file_ntcreate(conn, req, fname, &sbuf,
2334                                     DELETE_ACCESS,
2335                                     FILE_SHARE_NONE,
2336                                     FILE_OPEN,
2337                                     0,
2338                                     FILE_ATTRIBUTE_NORMAL,
2339                                     req != NULL ? 0 : INTERNAL_OPEN_ONLY,
2340                                     NULL, &fsp);
2341
2342         if (!NT_STATUS_IS_OK(status)) {
2343                 DEBUG(10, ("open_file_ntcreate failed: %s\n",
2344                            nt_errstr(status)));
2345                 return status;
2346         }
2347
2348         /* The set is across all open files on this dev/inode pair. */
2349         if (!set_delete_on_close(fsp, True, &current_user.ut)) {
2350                 close_file(fsp, NORMAL_CLOSE);
2351                 return NT_STATUS_ACCESS_DENIED;
2352         }
2353
2354         return close_file(fsp,NORMAL_CLOSE);
2355 }
2356
2357 /****************************************************************************
2358  The guts of the unlink command, split out so it may be called by the NT SMB
2359  code.
2360 ****************************************************************************/
2361
2362 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2363                           uint32 dirtype, const char *name_in, BOOL has_wild)
2364 {
2365         pstring directory;
2366         pstring mask;
2367         char *name = NULL;
2368         char *p;
2369         int count=0;
2370         NTSTATUS status = NT_STATUS_OK;
2371         SMB_STRUCT_STAT sbuf;
2372
2373         *directory = *mask = 0;
2374
2375         status = unix_convert(conn, name_in, has_wild, &name, NULL, &sbuf);
2376         if (!NT_STATUS_IS_OK(status)) {
2377                 return status;
2378         }
2379
2380         p = strrchr_m(name,'/');
2381         if (!p) {
2382                 pstrcpy(directory,".");
2383                 pstrcpy(mask,name);
2384         } else {
2385                 *p = 0;
2386                 pstrcpy(directory,name);
2387                 pstrcpy(mask,p+1);
2388         }
2389
2390         /*
2391          * We should only check the mangled cache
2392          * here if unix_convert failed. This means
2393          * that the path in 'mask' doesn't exist
2394          * on the file system and so we need to look
2395          * for a possible mangle. This patch from
2396          * Tine Smukavec <valentin.smukavec@hermes.si>.
2397          */
2398
2399         if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params)) {
2400                 char *new_mask = NULL;
2401                 mangle_lookup_name_from_8_3(talloc_tos(),
2402                                 mask,
2403                                 &new_mask,
2404                                 conn->params );
2405                 if (new_mask) {
2406                         pstrcpy(mask, new_mask);
2407                 }
2408         }
2409
2410         if (!has_wild) {
2411                 pstrcat(directory,"/");
2412                 pstrcat(directory,mask);
2413                 if (dirtype == 0) {
2414                         dirtype = FILE_ATTRIBUTE_NORMAL;
2415                 }
2416
2417                 status = check_name(conn, directory);
2418                 if (!NT_STATUS_IS_OK(status)) {
2419                         return status;
2420                 }
2421
2422                 status = do_unlink(conn, req, directory, dirtype);
2423                 if (!NT_STATUS_IS_OK(status)) {
2424                         return status;
2425                 }
2426
2427                 count++;
2428         } else {
2429                 struct smb_Dir *dir_hnd = NULL;
2430                 long offset = 0;
2431                 const char *dname;
2432
2433                 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2434                         return NT_STATUS_OBJECT_NAME_INVALID;
2435                 }
2436
2437                 if (strequal(mask,"????????.???")) {
2438                         pstrcpy(mask,"*");
2439                 }
2440
2441                 status = check_name(conn, directory);
2442                 if (!NT_STATUS_IS_OK(status)) {
2443                         return status;
2444                 }
2445
2446                 dir_hnd = OpenDir(conn, directory, mask, dirtype);
2447                 if (dir_hnd == NULL) {
2448                         return map_nt_error_from_unix(errno);
2449                 }
2450                 
2451                 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2452                    the pattern matches against the long name, otherwise the short name 
2453                    We don't implement this yet XXXX
2454                 */
2455                 
2456                 status = NT_STATUS_NO_SUCH_FILE;
2457
2458                 while ((dname = ReadDirName(dir_hnd, &offset))) {
2459                         SMB_STRUCT_STAT st;
2460                         pstring fname;
2461                         pstrcpy(fname,dname);
2462
2463                         if (!is_visible_file(conn, directory, dname, &st, True)) {
2464                                 continue;
2465                         }
2466
2467                         /* Quick check for "." and ".." */
2468                         if (fname[0] == '.') {
2469                                 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
2470                                         continue;
2471                                 }
2472                         }
2473
2474                         if(!mask_match(fname, mask, conn->case_sensitive)) {
2475                                 continue;
2476                         }
2477                                 
2478                         slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2479
2480                         status = check_name(conn, fname);
2481                         if (!NT_STATUS_IS_OK(status)) {
2482                                 CloseDir(dir_hnd);
2483                                 return status;
2484                         }
2485
2486                         status = do_unlink(conn, req, fname, dirtype);
2487                         if (!NT_STATUS_IS_OK(status)) {
2488                                 continue;
2489                         }
2490
2491                         count++;
2492                         DEBUG(3,("unlink_internals: succesful unlink [%s]\n",
2493                                  fname));
2494                 }
2495                 CloseDir(dir_hnd);
2496         }
2497         
2498         if (count == 0 && NT_STATUS_IS_OK(status)) {
2499                 status = map_nt_error_from_unix(errno);
2500         }
2501
2502         return status;
2503 }
2504
2505 /****************************************************************************
2506  Reply to a unlink
2507 ****************************************************************************/
2508
2509 void reply_unlink(connection_struct *conn, struct smb_request *req)
2510 {
2511         char *name = NULL;
2512         uint32 dirtype;
2513         NTSTATUS status;
2514         BOOL path_contains_wcard = False;
2515         TALLOC_CTX *ctx = talloc_tos();
2516
2517         START_PROFILE(SMBunlink);
2518
2519         if (req->wct < 1) {
2520                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2521                 END_PROFILE(SMBunlink);
2522                 return;
2523         }
2524
2525         dirtype = SVAL(req->inbuf,smb_vwv0);
2526
2527         srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name,
2528                               smb_buf(req->inbuf) + 1, 0,
2529                               STR_TERMINATE, &status, &path_contains_wcard);
2530         if (!NT_STATUS_IS_OK(status)) {
2531                 reply_nterror(req, status);
2532                 END_PROFILE(SMBunlink);
2533                 return;
2534         }
2535
2536         status = resolve_dfspath_wcard(ctx, conn,
2537                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
2538                                        name,
2539                                        &name,
2540                                        &path_contains_wcard);
2541         if (!NT_STATUS_IS_OK(status)) {
2542                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2543                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2544                                         ERRSRV, ERRbadpath);
2545                         END_PROFILE(SMBunlink);
2546                         return;
2547                 }
2548                 reply_nterror(req, status);
2549                 END_PROFILE(SMBunlink);
2550                 return;
2551         }
2552
2553         DEBUG(3,("reply_unlink : %s\n",name));
2554
2555         status = unlink_internals(conn, req, dirtype, name,
2556                                   path_contains_wcard);
2557         if (!NT_STATUS_IS_OK(status)) {
2558                 if (open_was_deferred(req->mid)) {
2559                         /* We have re-scheduled this call. */
2560                         END_PROFILE(SMBunlink);
2561                         return;
2562                 }
2563                 reply_nterror(req, status);
2564                 END_PROFILE(SMBunlink);
2565                 return;
2566         }
2567
2568         reply_outbuf(req, 0, 0);
2569         END_PROFILE(SMBunlink);
2570
2571         return;
2572 }
2573
2574 /****************************************************************************
2575  Fail for readbraw.
2576 ****************************************************************************/
2577
2578 static void fail_readraw(void)
2579 {
2580         pstring errstr;
2581         slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2582                 strerror(errno) );
2583         exit_server_cleanly(errstr);
2584 }
2585
2586 /****************************************************************************
2587  Fake (read/write) sendfile. Returns -1 on read or write fail.
2588 ****************************************************************************/
2589
2590 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2591                              size_t nread)
2592 {
2593         size_t bufsize;
2594         size_t tosend = nread;
2595         char *buf;
2596
2597         if (nread == 0) {
2598                 return 0;
2599         }
2600
2601         bufsize = MIN(nread, 65536);
2602
2603         if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2604                 return -1;
2605         }
2606
2607         while (tosend > 0) {
2608                 ssize_t ret;
2609                 size_t cur_read;
2610
2611                 if (tosend > bufsize) {
2612                         cur_read = bufsize;
2613                 } else {
2614                         cur_read = tosend;
2615                 }
2616                 ret = read_file(fsp,buf,startpos,cur_read);
2617                 if (ret == -1) {
2618                         SAFE_FREE(buf);
2619                         return -1;
2620                 }
2621
2622                 /* If we had a short read, fill with zeros. */
2623                 if (ret < cur_read) {
2624                         memset(buf, '\0', cur_read - ret);
2625                 }
2626
2627                 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2628                         SAFE_FREE(buf);
2629                         return -1;
2630                 }
2631                 tosend -= cur_read;
2632                 startpos += cur_read;
2633         }
2634
2635         SAFE_FREE(buf);
2636         return (ssize_t)nread;
2637 }
2638
2639 /****************************************************************************
2640  Return a readbraw error (4 bytes of zero).
2641 ****************************************************************************/
2642
2643 static void reply_readbraw_error(void)
2644 {
2645         char header[4];
2646         SIVAL(header,0,0);
2647         if (write_data(smbd_server_fd(),header,4) != 4) {
2648                 fail_readraw();
2649         }
2650 }
2651
2652 /****************************************************************************
2653  Use sendfile in readbraw.
2654 ****************************************************************************/
2655
2656 void send_file_readbraw(connection_struct *conn,
2657                         files_struct *fsp,
2658                         SMB_OFF_T startpos,
2659                         size_t nread,
2660                         ssize_t mincount)
2661 {
2662         char *outbuf = NULL;
2663         ssize_t ret=0;
2664
2665 #if defined(WITH_SENDFILE)
2666         /*
2667          * We can only use sendfile on a non-chained packet 
2668          * but we can use on a non-oplocked file. tridge proved this
2669          * on a train in Germany :-). JRA.
2670          * reply_readbraw has already checked the length.
2671          */
2672
2673         if ( (chain_size == 0) && (nread > 0) &&
2674             (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2675                 char header[4];
2676                 DATA_BLOB header_blob;
2677
2678                 _smb_setlen(header,nread);
2679                 header_blob = data_blob_const(header, 4);
2680
2681                 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd,
2682                                 &header_blob, startpos, nread) == -1) {
2683                         /* Returning ENOSYS means no data at all was sent.
2684                          * Do this as a normal read. */
2685                         if (errno == ENOSYS) {
2686                                 goto normal_readbraw;
2687                         }
2688
2689                         /*
2690                          * Special hack for broken Linux with no working sendfile. If we
2691                          * return EINTR we sent the header but not the rest of the data.
2692                          * Fake this up by doing read/write calls.
2693                          */
2694                         if (errno == EINTR) {
2695                                 /* Ensure we don't do this again. */
2696                                 set_use_sendfile(SNUM(conn), False);
2697                                 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2698
2699                                 if (fake_sendfile(fsp, startpos, nread) == -1) {
2700                                         DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2701                                                 fsp->fsp_name, strerror(errno) ));
2702                                         exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2703                                 }
2704                                 return;
2705                         }
2706
2707                         DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2708                                 fsp->fsp_name, strerror(errno) ));
2709                         exit_server_cleanly("send_file_readbraw sendfile failed");
2710                 }
2711
2712                 return;
2713         }
2714 #endif
2715
2716 normal_readbraw:
2717
2718         outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2719         if (!outbuf) {
2720                 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2721                         (unsigned)(nread+4)));
2722                 reply_readbraw_error();
2723                 return;
2724         }
2725
2726         if (nread > 0) {
2727                 ret = read_file(fsp,outbuf+4,startpos,nread);
2728 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2729                 if (ret < mincount)
2730                         ret = 0;
2731 #else
2732                 if (ret < nread)
2733                         ret = 0;
2734 #endif
2735         }
2736
2737         _smb_setlen(outbuf,ret);
2738         if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2739                 fail_readraw();
2740
2741         TALLOC_FREE(outbuf);
2742 }
2743
2744 /****************************************************************************
2745  Reply to a readbraw (core+ protocol).
2746 ****************************************************************************/
2747
2748 void reply_readbraw(connection_struct *conn, struct smb_request *req)
2749 {
2750         ssize_t maxcount,mincount;
2751         size_t nread = 0;
2752         SMB_OFF_T startpos;
2753         files_struct *fsp;
2754         SMB_STRUCT_STAT st;
2755         SMB_OFF_T size = 0;
2756
2757         START_PROFILE(SMBreadbraw);
2758
2759         if (srv_is_signing_active()) {
2760                 exit_server_cleanly("reply_readbraw: SMB signing is active - "
2761                         "raw reads/writes are disallowed.");
2762         }
2763
2764         if (req->wct < 8) {
2765                 reply_readbraw_error();
2766                 END_PROFILE(SMBreadbraw);
2767                 return;
2768         }
2769
2770         /*
2771          * Special check if an oplock break has been issued
2772          * and the readraw request croses on the wire, we must
2773          * return a zero length response here.
2774          */
2775
2776         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
2777
2778         /*
2779          * We have to do a check_fsp by hand here, as
2780          * we must always return 4 zero bytes on error,
2781          * not a NTSTATUS.
2782          */
2783
2784         if (!fsp || !conn || conn != fsp->conn ||
2785                         current_user.vuid != fsp->vuid ||
2786                         fsp->is_directory || fsp->fh->fd == -1) {
2787                 /*
2788                  * fsp could be NULL here so use the value from the packet. JRA.
2789                  */
2790                 DEBUG(3,("reply_readbraw: fnum %d not valid "
2791                         "- cache prime?\n",
2792                         (int)SVAL(req->inbuf,smb_vwv0)));
2793                 reply_readbraw_error();
2794                 END_PROFILE(SMBreadbraw);
2795                 return;
2796         }
2797
2798         /* Do a "by hand" version of CHECK_READ. */
2799         if (!(fsp->can_read ||
2800                         ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
2801                                 (fsp->access_mask & FILE_EXECUTE)))) {
2802                 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
2803                                 (int)SVAL(req->inbuf,smb_vwv0)));
2804                 reply_readbraw_error();
2805                 END_PROFILE(SMBreadbraw);
2806                 return;
2807         }
2808
2809         flush_write_cache(fsp, READRAW_FLUSH);
2810
2811         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv1);
2812         if(req->wct == 10) {
2813                 /*
2814                  * This is a large offset (64 bit) read.
2815                  */
2816 #ifdef LARGE_SMB_OFF_T
2817
2818                 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv8)) << 32);
2819
2820 #else /* !LARGE_SMB_OFF_T */
2821
2822                 /*
2823                  * Ensure we haven't been sent a >32 bit offset.
2824                  */
2825
2826                 if(IVAL(req->inbuf,smb_vwv8) != 0) {
2827                         DEBUG(0,("reply_readbraw: large offset "
2828                                 "(%x << 32) used and we don't support "
2829                                 "64 bit offsets.\n",
2830                         (unsigned int)IVAL(req->inbuf,smb_vwv8) ));
2831                         reply_readbraw_error();
2832                         END_PROFILE(SMBreadbraw);
2833                         return;
2834                 }
2835
2836 #endif /* LARGE_SMB_OFF_T */
2837
2838                 if(startpos < 0) {
2839                         DEBUG(0,("reply_readbraw: negative 64 bit "
2840                                 "readraw offset (%.0f) !\n",
2841                                 (double)startpos ));
2842                         reply_readbraw_error();
2843                         END_PROFILE(SMBreadbraw);
2844                         return;
2845                 }      
2846         }
2847
2848         maxcount = (SVAL(req->inbuf,smb_vwv3) & 0xFFFF);
2849         mincount = (SVAL(req->inbuf,smb_vwv4) & 0xFFFF);
2850
2851         /* ensure we don't overrun the packet size */
2852         maxcount = MIN(65535,maxcount);
2853
2854         if (is_locked(fsp,(uint32)req->smbpid,
2855                         (SMB_BIG_UINT)maxcount,
2856                         (SMB_BIG_UINT)startpos,
2857                         READ_LOCK)) {
2858                 reply_readbraw_error();
2859                 END_PROFILE(SMBreadbraw);
2860                 return;
2861         }
2862
2863         if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2864                 size = st.st_size;
2865         }
2866
2867         if (startpos >= size) {
2868                 nread = 0;
2869         } else {
2870                 nread = MIN(maxcount,(size - startpos));
2871         }
2872
2873 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2874         if (nread < mincount)
2875                 nread = 0;
2876 #endif
2877   
2878         DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
2879                 "min=%lu nread=%lu\n",
2880                 fsp->fnum, (double)startpos,
2881                 (unsigned long)maxcount,
2882                 (unsigned long)mincount,
2883                 (unsigned long)nread ) );
2884   
2885         send_file_readbraw(conn, fsp, startpos, nread, mincount);
2886
2887         DEBUG(5,("reply_readbraw finished\n"));
2888         END_PROFILE(SMBreadbraw);
2889 }
2890
2891 #undef DBGC_CLASS
2892 #define DBGC_CLASS DBGC_LOCKING
2893
2894 /****************************************************************************
2895  Reply to a lockread (core+ protocol).
2896 ****************************************************************************/
2897
2898 void reply_lockread(connection_struct *conn, struct smb_request *req)
2899 {
2900         ssize_t nread = -1;
2901         char *data;
2902         SMB_OFF_T startpos;
2903         size_t numtoread;
2904         NTSTATUS status;
2905         files_struct *fsp;
2906         struct byte_range_lock *br_lck = NULL;
2907         char *p = NULL;
2908
2909         START_PROFILE(SMBlockread);
2910
2911         if (req->wct < 5) {
2912                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2913                 END_PROFILE(SMBlockread);
2914                 return;
2915         }
2916
2917         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
2918
2919         if (!check_fsp(conn, req, fsp, &current_user)) {
2920                 END_PROFILE(SMBlockread);
2921                 return;
2922         }
2923
2924         if (!CHECK_READ(fsp,req->inbuf)) {
2925                 reply_doserror(req, ERRDOS, ERRbadaccess);
2926                 END_PROFILE(SMBlockread);
2927                 return;
2928         }
2929
2930         release_level_2_oplocks_on_change(fsp);
2931
2932         numtoread = SVAL(req->inbuf,smb_vwv1);
2933         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
2934
2935         numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
2936
2937         reply_outbuf(req, 5, numtoread + 3);
2938
2939         data = smb_buf(req->outbuf) + 3;
2940         
2941         /*
2942          * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2943          * protocol request that predates the read/write lock concept. 
2944          * Thus instead of asking for a read lock here we need to ask
2945          * for a write lock. JRA.
2946          * Note that the requested lock size is unaffected by max_recv.
2947          */
2948         
2949         br_lck = do_lock(smbd_messaging_context(),
2950                         fsp,
2951                         req->smbpid,
2952                         (SMB_BIG_UINT)numtoread,
2953                         (SMB_BIG_UINT)startpos,
2954                         WRITE_LOCK,
2955                         WINDOWS_LOCK,
2956                         False, /* Non-blocking lock. */
2957                         &status,
2958                         NULL);
2959         TALLOC_FREE(br_lck);
2960
2961         if (NT_STATUS_V(status)) {
2962                 reply_nterror(req, status);
2963                 END_PROFILE(SMBlockread);
2964                 return;
2965         }
2966
2967         /*
2968          * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2969          */
2970
2971         if (numtoread > max_recv) {
2972                 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2973 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2974                         (unsigned int)numtoread, (unsigned int)max_recv ));
2975                 numtoread = MIN(numtoread,max_recv);
2976         }
2977         nread = read_file(fsp,data,startpos,numtoread);
2978
2979         if (nread < 0) {
2980                 reply_unixerror(req, ERRDOS, ERRnoaccess);
2981                 END_PROFILE(SMBlockread);
2982                 return;
2983         }
2984         
2985         set_message(NULL, (char *)req->outbuf, 5, nread+3, False);
2986
2987         SSVAL(req->outbuf,smb_vwv0,nread);
2988         SSVAL(req->outbuf,smb_vwv5,nread+3);
2989         p = smb_buf(req->outbuf);
2990         SCVAL(p,0,0); /* pad byte. */
2991         SSVAL(p,1,nread);
2992         
2993         DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2994                  fsp->fnum, (int)numtoread, (int)nread));
2995
2996         END_PROFILE(SMBlockread);
2997         return;
2998 }
2999
3000 #undef DBGC_CLASS
3001 #define DBGC_CLASS DBGC_ALL
3002
3003 /****************************************************************************
3004  Reply to a read.
3005 ****************************************************************************/
3006
3007 void reply_read(connection_struct *conn, struct smb_request *req)
3008 {
3009         size_t numtoread;
3010         ssize_t nread = 0;
3011         char *data;
3012         SMB_OFF_T startpos;
3013         int outsize = 0;
3014         files_struct *fsp;
3015
3016         START_PROFILE(SMBread);
3017
3018         if (req->wct < 3) {
3019                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3020                 END_PROFILE(SMBread);
3021                 return;
3022         }
3023
3024         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3025
3026         if (!check_fsp(conn, req, fsp, &current_user)) {
3027                 END_PROFILE(SMBread);
3028                 return;
3029         }
3030
3031         if (!CHECK_READ(fsp,req->inbuf)) {
3032                 reply_doserror(req, ERRDOS, ERRbadaccess);
3033                 END_PROFILE(SMBread);
3034                 return;
3035         }
3036
3037         numtoread = SVAL(req->inbuf,smb_vwv1);
3038         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
3039
3040         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3041
3042         /*
3043          * The requested read size cannot be greater than max_recv. JRA.
3044          */
3045         if (numtoread > max_recv) {
3046                 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3047 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3048                         (unsigned int)numtoread, (unsigned int)max_recv ));
3049                 numtoread = MIN(numtoread,max_recv);
3050         }
3051
3052         reply_outbuf(req, 5, numtoread+3);
3053
3054         data = smb_buf(req->outbuf) + 3;
3055   
3056         if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtoread,
3057                       (SMB_BIG_UINT)startpos, READ_LOCK)) {
3058                 reply_doserror(req, ERRDOS,ERRlock);
3059                 END_PROFILE(SMBread);
3060                 return;
3061         }
3062
3063         if (numtoread > 0)
3064                 nread = read_file(fsp,data,startpos,numtoread);
3065
3066         if (nread < 0) {
3067                 reply_unixerror(req, ERRDOS,ERRnoaccess);
3068                 END_PROFILE(SMBread);
3069                 return;
3070         }
3071
3072         set_message(NULL, (char *)req->outbuf, 5, nread+3, False);
3073
3074         SSVAL(req->outbuf,smb_vwv0,nread);
3075         SSVAL(req->outbuf,smb_vwv5,nread+3);
3076         SCVAL(smb_buf(req->outbuf),0,1);
3077         SSVAL(smb_buf(req->outbuf),1,nread);
3078   
3079         DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3080                 fsp->fnum, (int)numtoread, (int)nread ) );
3081
3082         END_PROFILE(SMBread);
3083         return;
3084 }
3085
3086 /****************************************************************************
3087  Setup readX header.
3088 ****************************************************************************/
3089
3090 static int setup_readX_header(const uint8 *inbuf, uint8 *outbuf,
3091                               size_t smb_maxcnt)
3092 {
3093         int outsize;
3094         char *data;
3095
3096         outsize = set_message((char *)inbuf, (char *)outbuf,12,smb_maxcnt,
3097                               False);
3098         data = smb_buf(outbuf);
3099
3100         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3101         SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3102         SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
3103         SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3104         SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
3105         SCVAL(outbuf,smb_vwv0,0xFF);
3106         /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3107         _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3108         return outsize;
3109 }
3110
3111 /****************************************************************************
3112  Reply to a read and X - possibly using sendfile.
3113 ****************************************************************************/
3114
3115 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3116                             files_struct *fsp, SMB_OFF_T startpos,
3117                             size_t smb_maxcnt)
3118 {
3119         SMB_STRUCT_STAT sbuf;
3120         ssize_t nread = -1;
3121
3122         if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3123                 reply_unixerror(req, ERRDOS, ERRnoaccess);
3124                 return;
3125         }
3126
3127         if (startpos > sbuf.st_size) {
3128                 smb_maxcnt = 0;
3129         } else if (smb_maxcnt > (sbuf.st_size - startpos)) {
3130                 smb_maxcnt = (sbuf.st_size - startpos);
3131         }
3132
3133         if (smb_maxcnt == 0) {
3134                 goto normal_read;
3135         }
3136
3137 #if defined(WITH_SENDFILE)
3138         /*
3139          * We can only use sendfile on a non-chained packet 
3140          * but we can use on a non-oplocked file. tridge proved this
3141          * on a train in Germany :-). JRA.
3142          */
3143
3144         if ((chain_size == 0) && (CVAL(req->inbuf,smb_vwv0) == 0xFF) &&
3145             lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
3146                 uint8 headerbuf[smb_size + 12 * 2];
3147                 DATA_BLOB header;
3148
3149                 /* 
3150                  * Set up the packet header before send. We
3151                  * assume here the sendfile will work (get the
3152                  * correct amount of data).
3153                  */
3154
3155                 header = data_blob_const(headerbuf, sizeof(headerbuf));
3156
3157                 construct_reply_common((char *)req->inbuf, (char *)headerbuf);
3158                 setup_readX_header(req->inbuf, headerbuf, smb_maxcnt);
3159
3160                 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
3161                         /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
3162                         if (errno == ENOSYS) {
3163                                 goto normal_read;
3164                         }
3165
3166                         /*
3167                          * Special hack for broken Linux with no working sendfile. If we
3168                          * return EINTR we sent the header but not the rest of the data.
3169                          * Fake this up by doing read/write calls.
3170                          */
3171
3172                         if (errno == EINTR) {
3173                                 /* Ensure we don't do this again. */
3174                                 set_use_sendfile(SNUM(conn), False);
3175                                 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3176                                 nread = fake_sendfile(fsp, startpos,
3177                                                       smb_maxcnt);
3178                                 if (nread == -1) {
3179                                         DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3180                                                 fsp->fsp_name, strerror(errno) ));
3181                                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
3182                                 }
3183                                 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3184                                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3185                                 /* No outbuf here means successful sendfile. */
3186                                 TALLOC_FREE(req->outbuf);
3187                                 return;
3188                         }
3189
3190                         DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3191                                 fsp->fsp_name, strerror(errno) ));
3192                         exit_server_cleanly("send_file_readX sendfile failed");
3193                 }
3194