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