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