Refactor the crypto code after a very helpful conversation
[nivanova/samba-autobuild/.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(connection_struct *conn, struct smb_request *req)
483 {
484         const char *service;
485         char *service_buf = NULL;
486         char *password = NULL;
487         char *dev = NULL;
488         int pwlen=0;
489         NTSTATUS nt_status;
490         char *p;
491         DATA_BLOB password_blob;
492         TALLOC_CTX *ctx = talloc_tos();
493
494         START_PROFILE(SMBtcon);
495
496         if (smb_buflen(req->inbuf) < 4) {
497                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
498                 END_PROFILE(SMBtcon);
499                 return;
500         }
501
502         p = smb_buf(req->inbuf)+1;
503         p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2,
504                                     &service_buf, p, STR_TERMINATE) + 1;
505         pwlen = srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2,
506                                        &password, p, STR_TERMINATE) + 1;
507         p += pwlen;
508         p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2,
509                                     &dev, p, STR_TERMINATE) + 1;
510
511         if (service_buf == NULL || password == NULL || dev == NULL) {
512                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
513                 END_PROFILE(SMBtcon);
514                 return;
515         }
516         p = strrchr_m(service_buf,'\\');
517         if (p) {
518                 service = p+1;
519         } else {
520                 service = service_buf;
521         }
522
523         password_blob = data_blob(password, pwlen+1);
524
525         conn = make_connection(service,password_blob,dev,req->vuid,&nt_status);
526         req->conn = conn;
527
528         data_blob_clear_free(&password_blob);
529
530         if (!conn) {
531                 reply_nterror(req, nt_status);
532                 END_PROFILE(SMBtcon);
533                 return;
534         }
535
536         reply_outbuf(req, 2, 0);
537         SSVAL(req->outbuf,smb_vwv0,max_recv);
538         SSVAL(req->outbuf,smb_vwv1,conn->cnum);
539         SSVAL(req->outbuf,smb_tid,conn->cnum);
540
541         DEBUG(3,("tcon service=%s cnum=%d\n",
542                  service, conn->cnum));
543
544         END_PROFILE(SMBtcon);
545         return;
546 }
547
548 /****************************************************************************
549  Reply to a tcon and X.
550  conn POINTER CAN BE NULL HERE !
551 ****************************************************************************/
552
553 void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
554 {
555         char *service = NULL;
556         DATA_BLOB password;
557         TALLOC_CTX *ctx = talloc_tos();
558         /* what the cleint thinks the device is */
559         char *client_devicetype = NULL;
560         /* what the server tells the client the share represents */
561         const char *server_devicetype;
562         NTSTATUS nt_status;
563         int passlen;
564         char *path = NULL;
565         char *p, *q;
566         uint16 tcon_flags;
567
568         START_PROFILE(SMBtconX);
569
570         if (req->wct < 4) {
571                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
572                 END_PROFILE(SMBtconX);
573                 return;
574         }
575
576         passlen = SVAL(req->inbuf,smb_vwv3);
577         tcon_flags = SVAL(req->inbuf,smb_vwv2);
578
579         /* we might have to close an old one */
580         if ((tcon_flags & 0x1) && conn) {
581                 close_cnum(conn,req->vuid);
582                 req->conn = NULL;
583         }
584
585         if ((passlen > MAX_PASS_LEN) || (passlen >= smb_buflen(req->inbuf))) {
586                 reply_doserror(req, ERRDOS, ERRbuftoosmall);
587                 END_PROFILE(SMBtconX);
588                 return;
589         }
590
591         if (global_encrypted_passwords_negotiated) {
592                 password = data_blob(smb_buf(req->inbuf),passlen);
593                 if (lp_security() == SEC_SHARE) {
594                         /*
595                          * Security = share always has a pad byte
596                          * after the password.
597                          */
598                         p = smb_buf(req->inbuf) + passlen + 1;
599                 } else {
600                         p = smb_buf(req->inbuf) + passlen;
601                 }
602         } else {
603                 password = data_blob(smb_buf(req->inbuf),passlen+1);
604                 /* Ensure correct termination */
605                 password.data[passlen]=0;
606                 p = smb_buf(req->inbuf) + passlen + 1;
607         }
608
609         p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2, &path, p,
610                              STR_TERMINATE);
611
612         if (path == NULL) {
613                 data_blob_clear_free(&password);
614                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
615                 END_PROFILE(SMBtconX);
616                 return;
617         }
618
619         /*
620          * the service name can be either: \\server\share
621          * or share directly like on the DELL PowerVault 705
622          */
623         if (*path=='\\') {
624                 q = strchr_m(path+2,'\\');
625                 if (!q) {
626                         data_blob_clear_free(&password);
627                         reply_doserror(req, ERRDOS, ERRnosuchshare);
628                         END_PROFILE(SMBtconX);
629                         return;
630                 }
631                 service = q+1;
632         } else {
633                 service = path;
634         }
635
636         p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
637                                 &client_devicetype, p,
638                                 MIN(6,smb_bufrem(req->inbuf, p)), STR_ASCII);
639
640         if (client_devicetype == NULL) {
641                 data_blob_clear_free(&password);
642                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
643                 END_PROFILE(SMBtconX);
644                 return;
645         }
646
647         DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
648
649         conn = make_connection(service, password, client_devicetype,
650                                req->vuid, &nt_status);
651         req->conn =conn;
652
653         data_blob_clear_free(&password);
654
655         if (!conn) {
656                 reply_nterror(req, nt_status);
657                 END_PROFILE(SMBtconX);
658                 return;
659         }
660
661         if ( IS_IPC(conn) )
662                 server_devicetype = "IPC";
663         else if ( IS_PRINT(conn) )
664                 server_devicetype = "LPT1:";
665         else
666                 server_devicetype = "A:";
667
668         if (Protocol < PROTOCOL_NT1) {
669                 reply_outbuf(req, 2, 0);
670                 if (message_push_string(&req->outbuf, server_devicetype,
671                                         STR_TERMINATE|STR_ASCII) == -1) {
672                         reply_nterror(req, NT_STATUS_NO_MEMORY);
673                         END_PROFILE(SMBtconX);
674                         return;
675                 }
676         } else {
677                 /* NT sets the fstype of IPC$ to the null string */
678                 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
679
680                 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
681                         /* Return permissions. */
682                         uint32 perm1 = 0;
683                         uint32 perm2 = 0;
684
685                         reply_outbuf(req, 7, 0);
686
687                         if (IS_IPC(conn)) {
688                                 perm1 = FILE_ALL_ACCESS;
689                                 perm2 = FILE_ALL_ACCESS;
690                         } else {
691                                 perm1 = CAN_WRITE(conn) ?
692                                                 SHARE_ALL_ACCESS :
693                                                 SHARE_READ_ONLY;
694                         }
695
696                         SIVAL(req->outbuf, smb_vwv3, perm1);
697                         SIVAL(req->outbuf, smb_vwv5, perm2);
698                 } else {
699                         reply_outbuf(req, 3, 0);
700                 }
701
702                 if ((message_push_string(&req->outbuf, server_devicetype,
703                                          STR_TERMINATE|STR_ASCII) == -1)
704                     || (message_push_string(&req->outbuf, fstype,
705                                             STR_TERMINATE) == -1)) {
706                         reply_nterror(req, NT_STATUS_NO_MEMORY);
707                         END_PROFILE(SMBtconX);
708                         return;
709                 }
710
711                 /* what does setting this bit do? It is set by NT4 and
712                    may affect the ability to autorun mounted cdroms */
713                 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
714                       (lp_csc_policy(SNUM(conn)) << 2));
715
716                 init_dfsroot(conn, req->inbuf, req->outbuf);
717         }
718
719
720         DEBUG(3,("tconX service=%s \n",
721                  service));
722
723         /* set the incoming and outgoing tid to the just created one */
724         SSVAL(req->inbuf,smb_tid,conn->cnum);
725         SSVAL(req->outbuf,smb_tid,conn->cnum);
726
727         END_PROFILE(SMBtconX);
728
729         chain_reply(req);
730         return;
731 }
732
733 /****************************************************************************
734  Reply to an unknown type.
735 ****************************************************************************/
736
737 int reply_unknown(char *inbuf,char *outbuf)
738 {
739         int type;
740         type = CVAL(inbuf,smb_com);
741   
742         DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
743                  smb_fn_name(type), type, type));
744   
745         return(ERROR_DOS(ERRSRV,ERRunknownsmb));
746 }
747
748 void reply_unknown_new(struct smb_request *req, uint8 type)
749 {
750         DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
751                   smb_fn_name(type), type, type));
752         reply_doserror(req, ERRSRV, ERRunknownsmb);
753         return;
754 }
755
756 /****************************************************************************
757  Reply to an ioctl.
758  conn POINTER CAN BE NULL HERE !
759 ****************************************************************************/
760
761 void reply_ioctl(connection_struct *conn, struct smb_request *req)
762 {
763         uint16 device;
764         uint16 function;
765         uint32 ioctl_code;
766         int replysize;
767         char *p;
768
769         START_PROFILE(SMBioctl);
770
771         if (req->wct < 3) {
772                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
773                 END_PROFILE(SMBioctl);
774                 return;
775         }
776
777         device     = SVAL(req->inbuf,smb_vwv1);
778         function   = SVAL(req->inbuf,smb_vwv2);
779         ioctl_code = (device << 16) + function;
780
781         DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
782
783         switch (ioctl_code) {
784             case IOCTL_QUERY_JOB_INFO:
785                     replysize = 32;
786                     break;
787             default:
788                     reply_doserror(req, ERRSRV, ERRnosupport);
789                     END_PROFILE(SMBioctl);
790                     return;
791         }
792
793         reply_outbuf(req, 8, replysize+1);
794         SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
795         SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
796         SSVAL(req->outbuf,smb_vwv6,52);        /* Offset to data */
797         p = smb_buf(req->outbuf);
798         memset(p, '\0', replysize+1); /* valgrind-safe. */
799         p += 1;          /* Allow for alignment */
800
801         switch (ioctl_code) {
802                 case IOCTL_QUERY_JOB_INFO:                  
803                 {
804                         files_struct *fsp = file_fsp(SVAL(req->inbuf,
805                                                           smb_vwv0));
806                         if (!fsp) {
807                                 reply_doserror(req, ERRDOS, ERRbadfid);
808                                 END_PROFILE(SMBioctl);
809                                 return;
810                         }
811                         SSVAL(p,0,fsp->rap_print_jobid);             /* Job number */
812                         srvstr_push((char *)req->outbuf, req->flags2, p+2,
813                                     global_myname(), 15,
814                                     STR_TERMINATE|STR_ASCII);
815                         if (conn) {
816                                 srvstr_push((char *)req->outbuf, req->flags2,
817                                             p+18, lp_servicename(SNUM(conn)),
818                                             13, STR_TERMINATE|STR_ASCII);
819                         } else {
820                                 memset(p+18, 0, 13);
821                         }
822                         break;
823                 }
824         }
825
826         END_PROFILE(SMBioctl);
827         return;
828 }
829
830 /****************************************************************************
831  Strange checkpath NTSTATUS mapping.
832 ****************************************************************************/
833
834 static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
835 {
836         /* Strange DOS error code semantics only for checkpath... */
837         if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
838                 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
839                         /* We need to map to ERRbadpath */
840                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
841                 }
842         }
843         return status;
844 }
845
846 /****************************************************************************
847  Reply to a checkpath.
848 ****************************************************************************/
849
850 void reply_checkpath(connection_struct *conn, struct smb_request *req)
851 {
852         char *name = NULL;
853         SMB_STRUCT_STAT sbuf;
854         NTSTATUS status;
855         TALLOC_CTX *ctx = talloc_tos();
856
857         START_PROFILE(SMBcheckpath);
858
859         srvstr_get_path(ctx,(char *)req->inbuf, req->flags2, &name,
860                         smb_buf(req->inbuf) + 1, 0,
861                         STR_TERMINATE, &status);
862         if (!NT_STATUS_IS_OK(status)) {
863                 status = map_checkpath_error((char *)req->inbuf, status);
864                 reply_nterror(req, status);
865                 END_PROFILE(SMBcheckpath);
866                 return;
867         }
868
869         status = resolve_dfspath(ctx, conn,
870                         req->flags2 & FLAGS2_DFS_PATHNAMES,
871                         name,
872                         &name);
873         if (!NT_STATUS_IS_OK(status)) {
874                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
875                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
876                                         ERRSRV, ERRbadpath);
877                         END_PROFILE(SMBcheckpath);
878                         return;
879                 }
880                 goto path_err;
881         }
882
883         DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->inbuf,smb_vwv0)));
884
885         status = unix_convert(ctx, conn, name, False, &name, NULL, &sbuf);
886         if (!NT_STATUS_IS_OK(status)) {
887                 goto path_err;
888         }
889
890         status = check_name(conn, name);
891         if (!NT_STATUS_IS_OK(status)) {
892                 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
893                 goto path_err;
894         }
895
896         if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
897                 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
898                 status = map_nt_error_from_unix(errno);
899                 goto path_err;
900         }
901
902         if (!S_ISDIR(sbuf.st_mode)) {
903                 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
904                                 ERRDOS, ERRbadpath);
905                 END_PROFILE(SMBcheckpath);
906                 return;
907         }
908
909         reply_outbuf(req, 0, 0);
910
911         END_PROFILE(SMBcheckpath);
912         return;
913
914   path_err:
915
916         END_PROFILE(SMBcheckpath);
917
918         /* We special case this - as when a Windows machine
919                 is parsing a path is steps through the components
920                 one at a time - if a component fails it expects
921                 ERRbadpath, not ERRbadfile.
922         */
923         status = map_checkpath_error((char *)req->inbuf, status);
924         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
925                 /*
926                  * Windows returns different error codes if
927                  * the parent directory is valid but not the
928                  * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
929                  * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
930                  * if the path is invalid.
931                  */
932                 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
933                                 ERRDOS, ERRbadpath);
934                 return;
935         }
936
937         reply_nterror(req, status);
938 }
939
940 /****************************************************************************
941  Reply to a getatr.
942 ****************************************************************************/
943
944 void reply_getatr(connection_struct *conn, struct smb_request *req)
945 {
946         char *fname = NULL;
947         SMB_STRUCT_STAT sbuf;
948         int mode=0;
949         SMB_OFF_T size=0;
950         time_t mtime=0;
951         char *p;
952         NTSTATUS status;
953         TALLOC_CTX *ctx = talloc_tos();
954
955         START_PROFILE(SMBgetatr);
956
957         p = smb_buf(req->inbuf) + 1;
958         p += srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname, p,
959                              0, STR_TERMINATE, &status);
960         if (!NT_STATUS_IS_OK(status)) {
961                 reply_nterror(req, status);
962                 END_PROFILE(SMBgetatr);
963                 return;
964         }
965
966         status = resolve_dfspath(ctx, conn,
967                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
968                                 fname,
969                                 &fname);
970         if (!NT_STATUS_IS_OK(status)) {
971                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
972                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
973                                         ERRSRV, ERRbadpath);
974                         END_PROFILE(SMBgetatr);
975                         return;
976                 }
977                 reply_nterror(req, status);
978                 END_PROFILE(SMBgetatr);
979                 return;
980         }
981
982         /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
983                 under WfWg - weird! */
984         if (*fname == '\0') {
985                 mode = aHIDDEN | aDIR;
986                 if (!CAN_WRITE(conn)) {
987                         mode |= aRONLY;
988                 }
989                 size = 0;
990                 mtime = 0;
991         } else {
992                 status = unix_convert(ctx, conn, fname, False, &fname, NULL,&sbuf);
993                 if (!NT_STATUS_IS_OK(status)) {
994                         reply_nterror(req, status);
995                         END_PROFILE(SMBgetatr);
996                         return;
997                 }
998                 status = check_name(conn, fname);
999                 if (!NT_STATUS_IS_OK(status)) {
1000                         DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
1001                         reply_nterror(req, status);
1002                         END_PROFILE(SMBgetatr);
1003                         return;
1004                 }
1005                 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
1006                         DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
1007                         reply_unixerror(req, ERRDOS,ERRbadfile);
1008                         END_PROFILE(SMBgetatr);
1009                         return;
1010                 }
1011
1012                 mode = dos_mode(conn,fname,&sbuf);
1013                 size = sbuf.st_size;
1014                 mtime = sbuf.st_mtime;
1015                 if (mode & aDIR) {
1016                         size = 0;
1017                 }
1018         }
1019
1020         reply_outbuf(req, 10, 0);
1021
1022         SSVAL(req->outbuf,smb_vwv0,mode);
1023         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1024                 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1025         } else {
1026                 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1027         }
1028         SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1029
1030         if (Protocol >= PROTOCOL_NT1) {
1031                 SSVAL(req->outbuf, smb_flg2,
1032                       SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1033         }
1034   
1035         DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
1036
1037         END_PROFILE(SMBgetatr);
1038         return;
1039 }
1040
1041 /****************************************************************************
1042  Reply to a setatr.
1043 ****************************************************************************/
1044
1045 void reply_setatr(connection_struct *conn, struct smb_request *req)
1046 {
1047         char *fname = NULL;
1048         int mode;
1049         time_t mtime;
1050         SMB_STRUCT_STAT sbuf;
1051         char *p;
1052         NTSTATUS status;
1053         TALLOC_CTX *ctx = talloc_tos();
1054
1055         START_PROFILE(SMBsetatr);
1056
1057         if (req->wct < 2) {
1058                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1059                 return;
1060         }
1061
1062         p = smb_buf(req->inbuf) + 1;
1063         p += srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname, p,
1064                                 0, STR_TERMINATE, &status);
1065         if (!NT_STATUS_IS_OK(status)) {
1066                 reply_nterror(req, status);
1067                 END_PROFILE(SMBsetatr);
1068                 return;
1069         }
1070
1071         status = resolve_dfspath(ctx, conn,
1072                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
1073                                 fname,
1074                                 &fname);
1075         if (!NT_STATUS_IS_OK(status)) {
1076                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1077                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1078                                         ERRSRV, ERRbadpath);
1079                         END_PROFILE(SMBsetatr);
1080                         return;
1081                 }
1082                 reply_nterror(req, status);
1083                 END_PROFILE(SMBsetatr);
1084                 return;
1085         }
1086
1087         status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
1088         if (!NT_STATUS_IS_OK(status)) {
1089                 reply_nterror(req, status);
1090                 END_PROFILE(SMBsetatr);
1091                 return;
1092         }
1093
1094         status = check_name(conn, fname);
1095         if (!NT_STATUS_IS_OK(status)) {
1096                 reply_nterror(req, status);
1097                 END_PROFILE(SMBsetatr);
1098                 return;
1099         }
1100
1101         if (fname[0] == '.' && fname[1] == '\0') {
1102                 /*
1103                  * Not sure here is the right place to catch this
1104                  * condition. Might be moved to somewhere else later -- vl
1105                  */
1106                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1107                 END_PROFILE(SMBsetatr);
1108                 return;
1109         }
1110
1111         mode = SVAL(req->inbuf,smb_vwv0);
1112         mtime = srv_make_unix_date3(req->inbuf+smb_vwv1);
1113
1114         if (mode != FILE_ATTRIBUTE_NORMAL) {
1115                 if (VALID_STAT_OF_DIR(sbuf))
1116                         mode |= aDIR;
1117                 else
1118                         mode &= ~aDIR;
1119
1120                 if (file_set_dosmode(conn,fname,mode,&sbuf,NULL,false) != 0) {
1121                         reply_unixerror(req, ERRDOS, ERRnoaccess);
1122                         END_PROFILE(SMBsetatr);
1123                         return;
1124                 }
1125         }
1126
1127         if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) {
1128                 reply_unixerror(req, ERRDOS, ERRnoaccess);
1129                 END_PROFILE(SMBsetatr);
1130                 return;
1131         }
1132
1133         reply_outbuf(req, 0, 0);
1134  
1135         DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1136   
1137         END_PROFILE(SMBsetatr);
1138         return;
1139 }
1140
1141 /****************************************************************************
1142  Reply to a dskattr.
1143 ****************************************************************************/
1144
1145 void reply_dskattr(connection_struct *conn, struct smb_request *req)
1146 {
1147         SMB_BIG_UINT dfree,dsize,bsize;
1148         START_PROFILE(SMBdskattr);
1149
1150         if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1151                 reply_unixerror(req, ERRHRD, ERRgeneral);
1152                 END_PROFILE(SMBdskattr);
1153                 return;
1154         }
1155
1156         reply_outbuf(req, 5, 0);
1157         
1158         if (Protocol <= PROTOCOL_LANMAN2) {
1159                 double total_space, free_space;
1160                 /* we need to scale this to a number that DOS6 can handle. We
1161                    use floating point so we can handle large drives on systems
1162                    that don't have 64 bit integers 
1163
1164                    we end up displaying a maximum of 2G to DOS systems
1165                 */
1166                 total_space = dsize * (double)bsize;
1167                 free_space = dfree * (double)bsize;
1168
1169                 dsize = (SMB_BIG_UINT)((total_space+63*512) / (64*512));
1170                 dfree = (SMB_BIG_UINT)((free_space+63*512) / (64*512));
1171                 
1172                 if (dsize > 0xFFFF) dsize = 0xFFFF;
1173                 if (dfree > 0xFFFF) dfree = 0xFFFF;
1174
1175                 SSVAL(req->outbuf,smb_vwv0,dsize);
1176                 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1177                 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1178                 SSVAL(req->outbuf,smb_vwv3,dfree);
1179         } else {
1180                 SSVAL(req->outbuf,smb_vwv0,dsize);
1181                 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1182                 SSVAL(req->outbuf,smb_vwv2,512);
1183                 SSVAL(req->outbuf,smb_vwv3,dfree);
1184         }
1185
1186         DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1187
1188         END_PROFILE(SMBdskattr);
1189         return;
1190 }
1191
1192 /****************************************************************************
1193  Reply to a search.
1194  Can be called from SMBsearch, SMBffirst or SMBfunique.
1195 ****************************************************************************/
1196
1197 void reply_search(connection_struct *conn, struct smb_request *req)
1198 {
1199         char *mask = NULL;
1200         char *directory = NULL;
1201         char *fname = NULL;
1202         SMB_OFF_T size;
1203         uint32 mode;
1204         time_t date;
1205         uint32 dirtype;
1206         unsigned int numentries = 0;
1207         unsigned int maxentries = 0;
1208         bool finished = False;
1209         char *p;
1210         int status_len;
1211         char *path = NULL;
1212         char status[21];
1213         int dptr_num= -1;
1214         bool check_descend = False;
1215         bool expect_close = False;
1216         NTSTATUS nt_status;
1217         bool mask_contains_wcard = False;
1218         bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1219         TALLOC_CTX *ctx = talloc_tos();
1220
1221         START_PROFILE(SMBsearch);
1222
1223         if (req->wct < 2) {
1224                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1225                 END_PROFILE(SMBsearch);
1226                 return;
1227         }
1228
1229         if (lp_posix_pathnames()) {
1230                 reply_unknown_new(req, CVAL(req->inbuf, smb_com));
1231                 END_PROFILE(SMBsearch);
1232                 return;
1233         }
1234
1235         /* If we were called as SMBffirst then we must expect close. */
1236         if(CVAL(req->inbuf,smb_com) == SMBffirst) {
1237                 expect_close = True;
1238         }
1239
1240         reply_outbuf(req, 1, 3);
1241         maxentries = SVAL(req->inbuf,smb_vwv0);
1242         dirtype = SVAL(req->inbuf,smb_vwv1);
1243         p = smb_buf(req->inbuf) + 1;
1244         p += srvstr_get_path_wcard(ctx,
1245                                 (char *)req->inbuf,
1246                                 req->flags2,
1247                                 &path,
1248                                 p,
1249                                 0,
1250                                 STR_TERMINATE,
1251                                 &nt_status,
1252                                 &mask_contains_wcard);
1253         if (!NT_STATUS_IS_OK(nt_status)) {
1254                 reply_nterror(req, nt_status);
1255                 END_PROFILE(SMBsearch);
1256                 return;
1257         }
1258
1259         nt_status = resolve_dfspath_wcard(ctx, conn,
1260                                           req->flags2 & FLAGS2_DFS_PATHNAMES,
1261                                           path,
1262                                           &path,
1263                                           &mask_contains_wcard);
1264         if (!NT_STATUS_IS_OK(nt_status)) {
1265                 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1266                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1267                                         ERRSRV, ERRbadpath);
1268                         END_PROFILE(SMBsearch);
1269                         return;
1270                 }
1271                 reply_nterror(req, nt_status);
1272                 END_PROFILE(SMBsearch);
1273                 return;
1274         }
1275
1276         p++;
1277         status_len = SVAL(p, 0);
1278         p += 2;
1279
1280         /* dirtype &= ~aDIR; */
1281
1282         if (status_len == 0) {
1283                 SMB_STRUCT_STAT sbuf;
1284
1285                 nt_status = unix_convert(ctx, conn, path, True,
1286                                 &directory, NULL, &sbuf);
1287                 if (!NT_STATUS_IS_OK(nt_status)) {
1288                         reply_nterror(req, nt_status);
1289                         END_PROFILE(SMBsearch);
1290                         return;
1291                 }
1292
1293                 nt_status = check_name(conn, directory);
1294                 if (!NT_STATUS_IS_OK(nt_status)) {
1295                         reply_nterror(req, nt_status);
1296                         END_PROFILE(SMBsearch);
1297                         return;
1298                 }
1299
1300                 p = strrchr_m(directory,'/');
1301                 if (!p) {
1302                         mask = directory;
1303                         directory = talloc_strdup(ctx,".");
1304                         if (!directory) {
1305                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
1306                                 END_PROFILE(SMBsearch);
1307                                 return;
1308                         }
1309                 } else {
1310                         *p = 0;
1311                         mask = p+1;
1312                 }
1313
1314                 if (*directory == '\0') {
1315                         directory = talloc_strdup(ctx,".");
1316                         if (!directory) {
1317                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
1318                                 END_PROFILE(SMBsearch);
1319                                 return;
1320                         }
1321                 }
1322                 memset((char *)status,'\0',21);
1323                 SCVAL(status,0,(dirtype & 0x1F));
1324
1325                 nt_status = dptr_create(conn,
1326                                         directory,
1327                                         True,
1328                                         expect_close,
1329                                         req->smbpid,
1330                                         mask,
1331                                         mask_contains_wcard,
1332                                         dirtype,
1333                                         &conn->dirptr);
1334                 if (!NT_STATUS_IS_OK(nt_status)) {
1335                         reply_nterror(req, nt_status);
1336                         END_PROFILE(SMBsearch);
1337                         return;
1338                 }
1339                 dptr_num = dptr_dnum(conn->dirptr);
1340         } else {
1341                 int status_dirtype;
1342
1343                 memcpy(status,p,21);
1344                 status_dirtype = CVAL(status,0) & 0x1F;
1345                 if (status_dirtype != (dirtype & 0x1F)) {
1346                         dirtype = status_dirtype;
1347                 }
1348
1349                 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1350                 if (!conn->dirptr) {
1351                         goto SearchEmpty;
1352                 }
1353                 string_set(&conn->dirpath,dptr_path(dptr_num));
1354                 mask = dptr_wcard(dptr_num);
1355                 if (!mask) {
1356                         goto SearchEmpty;
1357                 }
1358                 /*
1359                  * For a 'continue' search we have no string. So
1360                  * check from the initial saved string.
1361                  */
1362                 mask_contains_wcard = ms_has_wild(mask);
1363                 dirtype = dptr_attr(dptr_num);
1364         }
1365
1366         DEBUG(4,("dptr_num is %d\n",dptr_num));
1367
1368         if ((dirtype&0x1F) == aVOLID) {
1369                 char buf[DIR_STRUCT_SIZE];
1370                 memcpy(buf,status,21);
1371                 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1372                                 0,aVOLID,0,!allow_long_path_components)) {
1373                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1374                         END_PROFILE(SMBsearch);
1375                         return;
1376                 }
1377                 dptr_fill(buf+12,dptr_num);
1378                 if (dptr_zero(buf+12) && (status_len==0)) {
1379                         numentries = 1;
1380                 } else {
1381                         numentries = 0;
1382                 }
1383                 if (message_push_blob(&req->outbuf,
1384                                       data_blob_const(buf, sizeof(buf)))
1385                     == -1) {
1386                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1387                         END_PROFILE(SMBsearch);
1388                         return;
1389                 }
1390         } else {
1391                 unsigned int i;
1392                 maxentries = MIN(
1393                         maxentries,
1394                         ((BUFFER_SIZE -
1395                           ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1396                          /DIR_STRUCT_SIZE));
1397
1398                 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1399                         conn->dirpath,lp_dontdescend(SNUM(conn))));
1400                 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1401                         check_descend = True;
1402                 }
1403
1404                 for (i=numentries;(i<maxentries) && !finished;i++) {
1405                         finished = !get_dir_entry(ctx,conn,mask,dirtype,&fname,
1406                                         &size,&mode,&date,check_descend);
1407                         if (!finished) {
1408                                 char buf[DIR_STRUCT_SIZE];
1409                                 memcpy(buf,status,21);
1410                                 if (!make_dir_struct(ctx,
1411                                                 buf,
1412                                                 mask,
1413                                                 fname,
1414                                                 size,
1415                                                 mode,
1416                                                 date,
1417                                                 !allow_long_path_components)) {
1418                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1419                                         END_PROFILE(SMBsearch);
1420                                         return;
1421                                 }
1422                                 if (!dptr_fill(buf+12,dptr_num)) {
1423                                         break;
1424                                 }
1425                                 if (message_push_blob(&req->outbuf,
1426                                                       data_blob_const(buf, sizeof(buf)))
1427                                     == -1) {
1428                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1429                                         END_PROFILE(SMBsearch);
1430                                         return;
1431                                 }
1432                                 numentries++;
1433                         }
1434                 }
1435         }
1436
1437   SearchEmpty:
1438
1439         /* If we were called as SMBffirst with smb_search_id == NULL
1440                 and no entries were found then return error and close dirptr 
1441                 (X/Open spec) */
1442
1443         if (numentries == 0) {
1444                 dptr_close(&dptr_num);
1445         } else if(expect_close && status_len == 0) {
1446                 /* Close the dptr - we know it's gone */
1447                 dptr_close(&dptr_num);
1448         }
1449
1450         /* If we were called as SMBfunique, then we can close the dirptr now ! */
1451         if(dptr_num >= 0 && CVAL(req->inbuf,smb_com) == SMBfunique) {
1452                 dptr_close(&dptr_num);
1453         }
1454
1455         if ((numentries == 0) && !mask_contains_wcard) {
1456                 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1457                 END_PROFILE(SMBsearch);
1458                 return;
1459         }
1460
1461         SSVAL(req->outbuf,smb_vwv0,numentries);
1462         SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1463         SCVAL(smb_buf(req->outbuf),0,5);
1464         SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1465
1466         /* The replies here are never long name. */
1467         SSVAL(req->outbuf, smb_flg2,
1468               SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1469         if (!allow_long_path_components) {
1470                 SSVAL(req->outbuf, smb_flg2,
1471                       SVAL(req->outbuf, smb_flg2)
1472                       & (~FLAGS2_LONG_PATH_COMPONENTS));
1473         }
1474
1475         /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1476         SSVAL(req->outbuf, smb_flg2,
1477               (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1478
1479         if (!directory) {
1480                 directory = dptr_path(dptr_num);
1481         }
1482
1483         DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1484                 smb_fn_name(CVAL(req->inbuf,smb_com)),
1485                 mask,
1486                 directory ? directory : "./",
1487                 dirtype,
1488                 numentries,
1489                 maxentries ));
1490
1491         END_PROFILE(SMBsearch);
1492         return;
1493 }
1494
1495 /****************************************************************************
1496  Reply to a fclose (stop directory search).
1497 ****************************************************************************/
1498
1499 void reply_fclose(connection_struct *conn, struct smb_request *req)
1500 {
1501         int status_len;
1502         char status[21];
1503         int dptr_num= -2;
1504         char *p;
1505         char *path = NULL;
1506         NTSTATUS err;
1507         bool path_contains_wcard = False;
1508         TALLOC_CTX *ctx = talloc_tos();
1509
1510         START_PROFILE(SMBfclose);
1511
1512         if (lp_posix_pathnames()) {
1513                 reply_unknown_new(req, CVAL(req->inbuf, smb_com));
1514                 END_PROFILE(SMBfclose);
1515                 return;
1516         }
1517
1518         p = smb_buf(req->inbuf) + 1;
1519         p += srvstr_get_path_wcard(ctx,
1520                                 (char *)req->inbuf,
1521                                 req->flags2,
1522                                 &path,
1523                                 p,
1524                                 0,
1525                                 STR_TERMINATE,
1526                                 &err,
1527                                 &path_contains_wcard);
1528         if (!NT_STATUS_IS_OK(err)) {
1529                 reply_nterror(req, err);
1530                 END_PROFILE(SMBfclose);
1531                 return;
1532         }
1533         p++;
1534         status_len = SVAL(p,0);
1535         p += 2;
1536
1537         if (status_len == 0) {
1538                 reply_doserror(req, ERRSRV, ERRsrverror);
1539                 END_PROFILE(SMBfclose);
1540                 return;
1541         }
1542
1543         memcpy(status,p,21);
1544
1545         if(dptr_fetch(status+12,&dptr_num)) {
1546                 /*  Close the dptr - we know it's gone */
1547                 dptr_close(&dptr_num);
1548         }
1549
1550         reply_outbuf(req, 1, 0);
1551         SSVAL(req->outbuf,smb_vwv0,0);
1552
1553         DEBUG(3,("search close\n"));
1554
1555         END_PROFILE(SMBfclose);
1556         return;
1557 }
1558
1559 /****************************************************************************
1560  Reply to an open.
1561 ****************************************************************************/
1562
1563 void reply_open(connection_struct *conn, struct smb_request *req)
1564 {
1565         char *fname = NULL;
1566         uint32 fattr=0;
1567         SMB_OFF_T size = 0;
1568         time_t mtime=0;
1569         int info;
1570         SMB_STRUCT_STAT sbuf;
1571         files_struct *fsp;
1572         int oplock_request;
1573         int deny_mode;
1574         uint32 dos_attr;
1575         uint32 access_mask;
1576         uint32 share_mode;
1577         uint32 create_disposition;
1578         uint32 create_options = 0;
1579         NTSTATUS status;
1580         TALLOC_CTX *ctx = talloc_tos();
1581
1582         START_PROFILE(SMBopen);
1583
1584         if (req->wct < 2) {
1585                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1586                 END_PROFILE(SMBopen);
1587                 return;
1588         }
1589
1590         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1591         deny_mode = SVAL(req->inbuf,smb_vwv0);
1592         dos_attr = SVAL(req->inbuf,smb_vwv1);
1593
1594         srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname,
1595                         smb_buf(req->inbuf)+1, 0,
1596                         STR_TERMINATE, &status);
1597         if (!NT_STATUS_IS_OK(status)) {
1598                 reply_nterror(req, status);
1599                 END_PROFILE(SMBopen);
1600                 return;
1601         }
1602
1603         if (!map_open_params_to_ntcreate(
1604                     fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
1605                     &share_mode, &create_disposition, &create_options)) {
1606                 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1607                 END_PROFILE(SMBopen);
1608                 return;
1609         }
1610
1611         status = create_file(conn,                      /* conn */
1612                              req,                       /* req */
1613                              0,                         /* root_dir_fid */
1614                              fname,                     /* fname */
1615                              access_mask,               /* access_mask */
1616                              share_mode,                /* share_access */
1617                              create_disposition,        /* create_disposition*/
1618                              create_options,            /* create_options */
1619                              dos_attr,                  /* file_attributes */
1620                              oplock_request,            /* oplock_request */
1621                              0,                         /* allocation_size */
1622                              NULL,                      /* sd */
1623                              NULL,                      /* ea_list */
1624                              &fsp,                      /* result */
1625                              &info,                     /* pinfo */
1626                              &sbuf);                    /* psbuf */
1627
1628         if (!NT_STATUS_IS_OK(status)) {
1629                 if (open_was_deferred(req->mid)) {
1630                         /* We have re-scheduled this call. */
1631                         END_PROFILE(SMBopen);
1632                         return;
1633                 }
1634                 reply_openerror(req, status);
1635                 END_PROFILE(SMBopen);
1636                 return;
1637         }
1638
1639         size = sbuf.st_size;
1640         fattr = dos_mode(conn,fname,&sbuf);
1641         mtime = sbuf.st_mtime;
1642
1643         if (fattr & aDIR) {
1644                 DEBUG(3,("attempt to open a directory %s\n",fname));
1645                 close_file(fsp,ERROR_CLOSE);
1646                 reply_doserror(req, ERRDOS,ERRnoaccess);
1647                 END_PROFILE(SMBopen);
1648                 return;
1649         }
1650
1651         reply_outbuf(req, 7, 0);
1652         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1653         SSVAL(req->outbuf,smb_vwv1,fattr);
1654         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1655                 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1656         } else {
1657                 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1658         }
1659         SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1660         SSVAL(req->outbuf,smb_vwv6,deny_mode);
1661
1662         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1663                 SCVAL(req->outbuf,smb_flg,
1664                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1665         }
1666     
1667         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1668                 SCVAL(req->outbuf,smb_flg,
1669                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1670         }
1671         END_PROFILE(SMBopen);
1672         return;
1673 }
1674
1675 /****************************************************************************
1676  Reply to an open and X.
1677 ****************************************************************************/
1678
1679 void reply_open_and_X(connection_struct *conn, struct smb_request *req)
1680 {
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  conn POINTER CAN BE NULL HERE !
1868 ****************************************************************************/
1869
1870 void reply_ulogoffX(connection_struct *conn, struct smb_request *req)
1871 {
1872         user_struct *vuser;
1873
1874         START_PROFILE(SMBulogoffX);
1875
1876         vuser = get_valid_user_struct(req->vuid);
1877
1878         if(vuser == NULL) {
1879                 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
1880                          req->vuid));
1881         }
1882
1883         /* in user level security we are supposed to close any files
1884                 open by this user */
1885         if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
1886                 file_close_user(req->vuid);
1887         }
1888
1889         invalidate_vuid(req->vuid);
1890
1891         reply_outbuf(req, 2, 0);
1892
1893         DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
1894
1895         END_PROFILE(SMBulogoffX);
1896         chain_reply(req);
1897 }
1898
1899 /****************************************************************************
1900  Reply to a mknew or a create.
1901 ****************************************************************************/
1902
1903 void reply_mknew(connection_struct *conn, struct smb_request *req)
1904 {
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(connection_struct *conn, struct smb_request *req)
2013 {
2014         char *fname = NULL;
2015         uint32 fattr;
2016         files_struct *fsp;
2017         int oplock_request;
2018         int tmpfd;
2019         SMB_STRUCT_STAT sbuf;
2020         char *s;
2021         NTSTATUS status;
2022         TALLOC_CTX *ctx = talloc_tos();
2023
2024         START_PROFILE(SMBctemp);
2025
2026         if (req->wct < 3) {
2027                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2028                 END_PROFILE(SMBctemp);
2029                 return;
2030         }
2031
2032         fattr = SVAL(req->inbuf,smb_vwv0);
2033         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2034
2035         srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname,
2036                         smb_buf(req->inbuf)+1, 0, STR_TERMINATE,
2037                         &status);
2038         if (!NT_STATUS_IS_OK(status)) {
2039                 reply_nterror(req, status);
2040                 END_PROFILE(SMBctemp);
2041                 return;
2042         }
2043         if (*fname) {
2044                 fname = talloc_asprintf(ctx,
2045                                 "%s/TMXXXXXX",
2046                                 fname);
2047         } else {
2048                 fname = talloc_strdup(ctx, "TMXXXXXX");
2049         }
2050
2051         if (!fname) {
2052                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2053                 END_PROFILE(SMBctemp);
2054                 return;
2055         }
2056
2057         status = resolve_dfspath(ctx, conn,
2058                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
2059                                 fname,
2060                                 &fname);
2061         if (!NT_STATUS_IS_OK(status)) {
2062                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2063                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2064                                         ERRSRV, ERRbadpath);
2065                         END_PROFILE(SMBctemp);
2066                         return;
2067                 }
2068                 reply_nterror(req, status);
2069                 END_PROFILE(SMBctemp);
2070                 return;
2071         }
2072
2073         status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
2074         if (!NT_STATUS_IS_OK(status)) {
2075                 reply_nterror(req, status);
2076                 END_PROFILE(SMBctemp);
2077                 return;
2078         }
2079
2080         status = check_name(conn, CONST_DISCARD(char *,fname));
2081         if (!NT_STATUS_IS_OK(status)) {
2082                 reply_nterror(req, status);
2083                 END_PROFILE(SMBctemp);
2084                 return;
2085         }
2086
2087         tmpfd = smb_mkstemp(fname);
2088         if (tmpfd == -1) {
2089                 reply_unixerror(req, ERRDOS, ERRnoaccess);
2090                 END_PROFILE(SMBctemp);
2091                 return;
2092         }
2093
2094         SMB_VFS_STAT(conn,fname,&sbuf);
2095
2096         /* We should fail if file does not exist. */
2097         status = open_file_ntcreate(conn, req, fname, &sbuf,
2098                                 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
2099                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
2100                                 FILE_OPEN,
2101                                 0,
2102                                 fattr,
2103                                 oplock_request,
2104                                 NULL, &fsp);
2105
2106         /* close fd from smb_mkstemp() */
2107         close(tmpfd);
2108
2109         if (!NT_STATUS_IS_OK(status)) {
2110                 if (open_was_deferred(req->mid)) {
2111                         /* We have re-scheduled this call. */
2112                         END_PROFILE(SMBctemp);
2113                         return;
2114                 }
2115                 reply_openerror(req, status);
2116                 END_PROFILE(SMBctemp);
2117                 return;
2118         }
2119
2120         reply_outbuf(req, 1, 0);
2121         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2122
2123         /* the returned filename is relative to the directory */
2124         s = strrchr_m(fname, '/');
2125         if (!s) {
2126                 s = fname;
2127         } else {
2128                 s++;
2129         }
2130
2131 #if 0
2132         /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2133            thing in the byte section. JRA */
2134         SSVALS(p, 0, -1); /* what is this? not in spec */
2135 #endif
2136         if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2137             == -1) {
2138                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2139                 END_PROFILE(SMBctemp);
2140                 return;
2141         }
2142
2143         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2144                 SCVAL(req->outbuf, smb_flg,
2145                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2146         }
2147   
2148         if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2149                 SCVAL(req->outbuf, smb_flg,
2150                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2151         }
2152
2153         DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
2154         DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
2155                         (unsigned int)sbuf.st_mode ) );
2156
2157         END_PROFILE(SMBctemp);
2158         return;
2159 }
2160
2161 /*******************************************************************
2162  Check if a user is allowed to rename a file.
2163 ********************************************************************/
2164
2165 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2166                            uint16 dirtype, SMB_STRUCT_STAT *pst)
2167 {
2168         uint32 fmode;
2169
2170         if (!CAN_WRITE(conn)) {
2171                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2172         }
2173
2174         fmode = dos_mode(conn, fsp->fsp_name, pst);
2175         if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2176                 return NT_STATUS_NO_SUCH_FILE;
2177         }
2178
2179         if (S_ISDIR(pst->st_mode)) {
2180                 return NT_STATUS_OK;
2181         }
2182
2183         if (fsp->access_mask & DELETE_ACCESS) {
2184                 return NT_STATUS_OK;
2185         }
2186
2187         return NT_STATUS_ACCESS_DENIED;
2188 }
2189
2190 /*******************************************************************
2191  * unlink a file with all relevant access checks
2192  *******************************************************************/
2193
2194 static NTSTATUS do_unlink(connection_struct *conn,
2195                         struct smb_request *req,
2196                         const char *fname,
2197                         uint32 dirtype)
2198 {
2199         SMB_STRUCT_STAT sbuf;
2200         uint32 fattr;
2201         files_struct *fsp;
2202         uint32 dirtype_orig = dirtype;
2203         NTSTATUS status;
2204
2205         DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2206
2207         if (!CAN_WRITE(conn)) {
2208                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2209         }
2210
2211         if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
2212                 return map_nt_error_from_unix(errno);
2213         }
2214
2215         fattr = dos_mode(conn,fname,&sbuf);
2216
2217         if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2218                 dirtype = aDIR|aARCH|aRONLY;
2219         }
2220
2221         dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2222         if (!dirtype) {
2223                 return NT_STATUS_NO_SUCH_FILE;
2224         }
2225
2226         if (!dir_check_ftype(conn, fattr, dirtype)) {
2227                 if (fattr & aDIR) {
2228                         return NT_STATUS_FILE_IS_A_DIRECTORY;
2229                 }
2230                 return NT_STATUS_NO_SUCH_FILE;
2231         }
2232
2233         if (dirtype_orig & 0x8000) {
2234                 /* These will never be set for POSIX. */
2235                 return NT_STATUS_NO_SUCH_FILE;
2236         }
2237
2238 #if 0
2239         if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2240                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2241         }
2242
2243         if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2244                 return NT_STATUS_NO_SUCH_FILE;
2245         }
2246
2247         if (dirtype & 0xFF00) {
2248                 /* These will never be set for POSIX. */
2249                 return NT_STATUS_NO_SUCH_FILE;
2250         }
2251
2252         dirtype &= 0xFF;
2253         if (!dirtype) {
2254                 return NT_STATUS_NO_SUCH_FILE;
2255         }
2256
2257         /* Can't delete a directory. */
2258         if (fattr & aDIR) {
2259                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2260         }
2261 #endif
2262
2263 #if 0 /* JRATEST */
2264         else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2265                 return NT_STATUS_OBJECT_NAME_INVALID;
2266 #endif /* JRATEST */
2267
2268         /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2269
2270           On a Windows share, a file with read-only dosmode can be opened with
2271           DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2272           fails with NT_STATUS_CANNOT_DELETE error.
2273
2274           This semantic causes a problem that a user can not
2275           rename a file with read-only dosmode on a Samba share
2276           from a Windows command prompt (i.e. cmd.exe, but can rename
2277           from Windows Explorer).
2278         */
2279
2280         if (!lp_delete_readonly(SNUM(conn))) {
2281                 if (fattr & aRONLY) {
2282                         return NT_STATUS_CANNOT_DELETE;
2283                 }
2284         }
2285
2286         /* On open checks the open itself will check the share mode, so
2287            don't do it here as we'll get it wrong. */
2288
2289         status = open_file_ntcreate(conn, req, fname, &sbuf,
2290                                     DELETE_ACCESS,
2291                                     FILE_SHARE_NONE,
2292                                     FILE_OPEN,
2293                                     0,
2294                                     FILE_ATTRIBUTE_NORMAL,
2295                                     req != NULL ? 0 : INTERNAL_OPEN_ONLY,
2296                                     NULL, &fsp);
2297
2298         if (!NT_STATUS_IS_OK(status)) {
2299                 DEBUG(10, ("open_file_ntcreate failed: %s\n",
2300                            nt_errstr(status)));
2301                 return status;
2302         }
2303
2304         /* The set is across all open files on this dev/inode pair. */
2305         if (!set_delete_on_close(fsp, True, &current_user.ut)) {
2306                 close_file(fsp, NORMAL_CLOSE);
2307                 return NT_STATUS_ACCESS_DENIED;
2308         }
2309
2310         return close_file(fsp,NORMAL_CLOSE);
2311 }
2312
2313 /****************************************************************************
2314  The guts of the unlink command, split out so it may be called by the NT SMB
2315  code.
2316 ****************************************************************************/
2317
2318 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2319                           uint32 dirtype, const char *name_in, bool has_wild)
2320 {
2321         const char *directory = NULL;
2322         char *mask = NULL;
2323         char *name = NULL;
2324         char *p = NULL;
2325         int count=0;
2326         NTSTATUS status = NT_STATUS_OK;
2327         SMB_STRUCT_STAT sbuf;
2328         TALLOC_CTX *ctx = talloc_tos();
2329
2330         status = unix_convert(ctx, conn, name_in, has_wild, &name, NULL, &sbuf);
2331         if (!NT_STATUS_IS_OK(status)) {
2332                 return status;
2333         }
2334
2335         p = strrchr_m(name,'/');
2336         if (!p) {
2337                 directory = talloc_strdup(ctx, ".");
2338                 if (!directory) {
2339                         return NT_STATUS_NO_MEMORY;
2340                 }
2341                 mask = name;
2342         } else {
2343                 *p = 0;
2344                 directory = name;
2345                 mask = p+1;
2346         }
2347
2348         /*
2349          * We should only check the mangled cache
2350          * here if unix_convert failed. This means
2351          * that the path in 'mask' doesn't exist
2352          * on the file system and so we need to look
2353          * for a possible mangle. This patch from
2354          * Tine Smukavec <valentin.smukavec@hermes.si>.
2355          */
2356
2357         if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params)) {
2358                 char *new_mask = NULL;
2359                 mangle_lookup_name_from_8_3(ctx,
2360                                 mask,
2361                                 &new_mask,
2362                                 conn->params );
2363                 if (new_mask) {
2364                         mask = new_mask;
2365                 }
2366         }
2367
2368         if (!has_wild) {
2369                 directory = talloc_asprintf(ctx,
2370                                 "%s/%s",
2371                                 directory,
2372                                 mask);
2373                 if (!directory) {
2374                         return NT_STATUS_NO_MEMORY;
2375                 }
2376                 if (dirtype == 0) {
2377                         dirtype = FILE_ATTRIBUTE_NORMAL;
2378                 }
2379
2380                 status = check_name(conn, directory);
2381                 if (!NT_STATUS_IS_OK(status)) {
2382                         return status;
2383                 }
2384
2385                 status = do_unlink(conn, req, directory, dirtype);
2386                 if (!NT_STATUS_IS_OK(status)) {
2387                         return status;
2388                 }
2389
2390                 count++;
2391         } else {
2392                 struct smb_Dir *dir_hnd = NULL;
2393                 long offset = 0;
2394                 const char *dname;
2395
2396                 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2397                         return NT_STATUS_OBJECT_NAME_INVALID;
2398                 }
2399
2400                 if (strequal(mask,"????????.???")) {
2401                         mask[0] = '*';
2402                         mask[1] = '\0';
2403                 }
2404
2405                 status = check_name(conn, directory);
2406                 if (!NT_STATUS_IS_OK(status)) {
2407                         return status;
2408                 }
2409
2410                 dir_hnd = OpenDir(conn, directory, mask, dirtype);
2411                 if (dir_hnd == NULL) {
2412                         return map_nt_error_from_unix(errno);
2413                 }
2414
2415                 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2416                    the pattern matches against the long name, otherwise the short name 
2417                    We don't implement this yet XXXX
2418                 */
2419
2420                 status = NT_STATUS_NO_SUCH_FILE;
2421
2422                 while ((dname = ReadDirName(dir_hnd, &offset))) {
2423                         SMB_STRUCT_STAT st;
2424                         char *fname = NULL;
2425
2426                         if (!is_visible_file(conn, directory, dname, &st, True)) {
2427                                 continue;
2428                         }
2429
2430                         /* Quick check for "." and ".." */
2431                         if (ISDOT(dname) || ISDOTDOT(dname)) {
2432                                 continue;
2433                         }
2434
2435                         if(!mask_match(dname, mask, conn->case_sensitive)) {
2436                                 continue;
2437                         }
2438
2439                         fname = talloc_asprintf(ctx, "%s/%s",
2440                                         directory,
2441                                         dname);
2442                         if (!fname) {
2443                                 return NT_STATUS_NO_MEMORY;
2444                         }
2445
2446                         status = check_name(conn, fname);
2447                         if (!NT_STATUS_IS_OK(status)) {
2448                                 CloseDir(dir_hnd);
2449                                 return status;
2450                         }
2451
2452                         status = do_unlink(conn, req, fname, dirtype);
2453                         if (!NT_STATUS_IS_OK(status)) {
2454                                 TALLOC_FREE(fname);
2455                                 continue;
2456                         }
2457
2458                         count++;
2459                         DEBUG(3,("unlink_internals: succesful unlink [%s]\n",
2460                                  fname));
2461
2462                         TALLOC_FREE(fname);
2463                 }
2464                 CloseDir(dir_hnd);
2465         }
2466
2467         if (count == 0 && NT_STATUS_IS_OK(status)) {
2468                 status = map_nt_error_from_unix(errno);
2469         }
2470
2471         return status;
2472 }
2473
2474 /****************************************************************************
2475  Reply to a unlink
2476 ****************************************************************************/
2477
2478 void reply_unlink(connection_struct *conn, struct smb_request *req)
2479 {
2480         char *name = NULL;
2481         uint32 dirtype;
2482         NTSTATUS status;
2483         bool path_contains_wcard = False;
2484         TALLOC_CTX *ctx = talloc_tos();
2485
2486         START_PROFILE(SMBunlink);
2487
2488         if (req->wct < 1) {
2489                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2490                 END_PROFILE(SMBunlink);
2491                 return;
2492         }
2493
2494         dirtype = SVAL(req->inbuf,smb_vwv0);
2495
2496         srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name,
2497                               smb_buf(req->inbuf) + 1, 0,
2498                               STR_TERMINATE, &status, &path_contains_wcard);
2499         if (!NT_STATUS_IS_OK(status)) {
2500                 reply_nterror(req, status);
2501                 END_PROFILE(SMBunlink);
2502                 return;
2503         }
2504
2505         status = resolve_dfspath_wcard(ctx, conn,
2506                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
2507                                        name,
2508                                        &name,
2509                                        &path_contains_wcard);
2510         if (!NT_STATUS_IS_OK(status)) {
2511                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2512                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2513                                         ERRSRV, ERRbadpath);
2514                         END_PROFILE(SMBunlink);
2515                         return;
2516                 }
2517                 reply_nterror(req, status);
2518                 END_PROFILE(SMBunlink);
2519                 return;
2520         }
2521
2522         DEBUG(3,("reply_unlink : %s\n",name));
2523
2524         status = unlink_internals(conn, req, dirtype, name,
2525                                   path_contains_wcard);
2526         if (!NT_STATUS_IS_OK(status)) {
2527                 if (open_was_deferred(req->mid)) {
2528                         /* We have re-scheduled this call. */
2529                         END_PROFILE(SMBunlink);
2530                         return;
2531                 }
2532                 reply_nterror(req, status);
2533                 END_PROFILE(SMBunlink);
2534                 return;
2535         }
2536
2537         reply_outbuf(req, 0, 0);
2538         END_PROFILE(SMBunlink);
2539
2540         return;
2541 }
2542
2543 /****************************************************************************
2544  Fail for readbraw.
2545 ****************************************************************************/
2546
2547 static void fail_readraw(void)
2548 {
2549         const char *errstr = talloc_asprintf(talloc_tos(),
2550                         "FAIL ! reply_readbraw: socket write fail (%s)",
2551                         strerror(errno));
2552         if (!errstr) {
2553                 errstr = "";
2554         }
2555         exit_server_cleanly(errstr);
2556 }
2557
2558 /****************************************************************************
2559  Fake (read/write) sendfile. Returns -1 on read or write fail.
2560 ****************************************************************************/
2561
2562 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2563                              size_t nread)
2564 {
2565         size_t bufsize;
2566         size_t tosend = nread;
2567         char *buf;
2568
2569         if (nread == 0) {
2570                 return 0;
2571         }
2572
2573         bufsize = MIN(nread, 65536);
2574
2575         if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2576                 return -1;
2577         }
2578
2579         while (tosend > 0) {
2580                 ssize_t ret;
2581                 size_t cur_read;
2582
2583                 if (tosend > bufsize) {
2584                         cur_read = bufsize;
2585                 } else {
2586                         cur_read = tosend;
2587                 }
2588                 ret = read_file(fsp,buf,startpos,cur_read);
2589                 if (ret == -1) {
2590                         SAFE_FREE(buf);
2591                         return -1;
2592                 }
2593
2594                 /* If we had a short read, fill with zeros. */
2595                 if (ret < cur_read) {
2596                         memset(buf, '\0', cur_read - ret);
2597                 }
2598
2599                 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2600                         SAFE_FREE(buf);
2601                         return -1;
2602                 }
2603                 tosend -= cur_read;
2604                 startpos += cur_read;
2605         }
2606
2607         SAFE_FREE(buf);
2608         return (ssize_t)nread;
2609 }
2610
2611 /****************************************************************************
2612  Return a readbraw error (4 bytes of zero).
2613 ****************************************************************************/
2614
2615 static void reply_readbraw_error(void)
2616 {
2617         char header[4];
2618         SIVAL(header,0,0);
2619         if (write_data(smbd_server_fd(),header,4) != 4) {
2620                 fail_readraw();
2621         }
2622 }
2623
2624 /****************************************************************************
2625  Use sendfile in readbraw.
2626 ****************************************************************************/
2627
2628 void send_file_readbraw(connection_struct *conn,
2629                         files_struct *fsp,
2630                         SMB_OFF_T startpos,
2631                         size_t nread,
2632                         ssize_t mincount)
2633 {
2634         char *outbuf = NULL;
2635         ssize_t ret=0;
2636
2637 #if defined(WITH_SENDFILE)
2638         /*
2639          * We can only use sendfile on a non-chained packet 
2640          * but we can use on a non-oplocked file. tridge proved this
2641          * on a train in Germany :-). JRA.
2642          * reply_readbraw has already checked the length.
2643          */
2644
2645         if ( (chain_size == 0) && (nread > 0) &&
2646             (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2647                 char header[4];
2648                 DATA_BLOB header_blob;
2649
2650                 _smb_setlen(header,nread);
2651                 header_blob = data_blob_const(header, 4);
2652
2653                 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd,
2654                                 &header_blob, startpos, nread) == -1) {
2655                         /* Returning ENOSYS means no data at all was sent.
2656                          * Do this as a normal read. */
2657                         if (errno == ENOSYS) {
2658                                 goto normal_readbraw;
2659                         }
2660
2661                         /*
2662                          * Special hack for broken Linux with no working sendfile. If we
2663                          * return EINTR we sent the header but not the rest of the data.
2664                          * Fake this up by doing read/write calls.
2665                          */
2666                         if (errno == EINTR) {
2667                                 /* Ensure we don't do this again. */
2668                                 set_use_sendfile(SNUM(conn), False);
2669                                 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2670
2671                                 if (fake_sendfile(fsp, startpos, nread) == -1) {
2672                                         DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2673                                                 fsp->fsp_name, strerror(errno) ));
2674                                         exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2675                                 }
2676                                 return;
2677                         }
2678
2679                         DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2680                                 fsp->fsp_name, strerror(errno) ));
2681                         exit_server_cleanly("send_file_readbraw sendfile failed");
2682                 }
2683
2684                 return;
2685         }
2686 #endif
2687
2688 normal_readbraw:
2689
2690         outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2691         if (!outbuf) {
2692                 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2693                         (unsigned)(nread+4)));
2694                 reply_readbraw_error();
2695                 return;
2696         }
2697
2698         if (nread > 0) {
2699                 ret = read_file(fsp,outbuf+4,startpos,nread);
2700 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2701                 if (ret < mincount)
2702                         ret = 0;
2703 #else
2704                 if (ret < nread)
2705                         ret = 0;
2706 #endif
2707         }
2708
2709         _smb_setlen(outbuf,ret);
2710         if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2711                 fail_readraw();
2712
2713         TALLOC_FREE(outbuf);
2714 }
2715
2716 /****************************************************************************
2717  Reply to a readbraw (core+ protocol).
2718 ****************************************************************************/
2719
2720 void reply_readbraw(connection_struct *conn, struct smb_request *req)
2721 {
2722         ssize_t maxcount,mincount;
2723         size_t nread = 0;
2724         SMB_OFF_T startpos;
2725         files_struct *fsp;
2726         SMB_STRUCT_STAT st;
2727         SMB_OFF_T size = 0;
2728
2729         START_PROFILE(SMBreadbraw);
2730
2731         if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
2732                 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
2733                         "raw reads/writes are disallowed.");
2734         }
2735
2736         if (req->wct < 8) {
2737                 reply_readbraw_error();
2738                 END_PROFILE(SMBreadbraw);
2739                 return;
2740         }
2741
2742         /*
2743          * Special check if an oplock break has been issued
2744          * and the readraw request croses on the wire, we must
2745          * return a zero length response here.
2746          */
2747
2748         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
2749
2750         /*
2751          * We have to do a check_fsp by hand here, as
2752          * we must always return 4 zero bytes on error,
2753          * not a NTSTATUS.
2754          */
2755
2756         if (!fsp || !conn || conn != fsp->conn ||
2757                         current_user.vuid != fsp->vuid ||
2758                         fsp->is_directory || fsp->fh->fd == -1) {
2759                 /*
2760                  * fsp could be NULL here so use the value from the packet. JRA.
2761                  */
2762                 DEBUG(3,("reply_readbraw: fnum %d not valid "
2763                         "- cache prime?\n",
2764                         (int)SVAL(req->inbuf,smb_vwv0)));
2765                 reply_readbraw_error();
2766                 END_PROFILE(SMBreadbraw);
2767                 return;
2768         }
2769
2770         /* Do a "by hand" version of CHECK_READ. */
2771         if (!(fsp->can_read ||
2772                         ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
2773                                 (fsp->access_mask & FILE_EXECUTE)))) {
2774                 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
2775                                 (int)SVAL(req->inbuf,smb_vwv0)));
2776                 reply_readbraw_error();
2777                 END_PROFILE(SMBreadbraw);
2778                 return;
2779         }
2780
2781         flush_write_cache(fsp, READRAW_FLUSH);
2782
2783         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv1);
2784         if(req->wct == 10) {
2785                 /*
2786                  * This is a large offset (64 bit) read.
2787                  */
2788 #ifdef LARGE_SMB_OFF_T
2789
2790                 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv8)) << 32);
2791
2792 #else /* !LARGE_SMB_OFF_T */
2793
2794                 /*
2795                  * Ensure we haven't been sent a >32 bit offset.
2796                  */
2797
2798                 if(IVAL(req->inbuf,smb_vwv8) != 0) {
2799                         DEBUG(0,("reply_readbraw: large offset "
2800                                 "(%x << 32) used and we don't support "
2801                                 "64 bit offsets.\n",
2802                         (unsigned int)IVAL(req->inbuf,smb_vwv8) ));
2803                         reply_readbraw_error();
2804                         END_PROFILE(SMBreadbraw);
2805                         return;
2806                 }
2807
2808 #endif /* LARGE_SMB_OFF_T */
2809
2810                 if(startpos < 0) {
2811                         DEBUG(0,("reply_readbraw: negative 64 bit "
2812                                 "readraw offset (%.0f) !\n",
2813                                 (double)startpos ));
2814                         reply_readbraw_error();
2815                         END_PROFILE(SMBreadbraw);
2816                         return;
2817                 }      
2818         }
2819
2820         maxcount = (SVAL(req->inbuf,smb_vwv3) & 0xFFFF);
2821         mincount = (SVAL(req->inbuf,smb_vwv4) & 0xFFFF);
2822
2823         /* ensure we don't overrun the packet size */
2824         maxcount = MIN(65535,maxcount);
2825
2826         if (is_locked(fsp,(uint32)req->smbpid,
2827                         (SMB_BIG_UINT)maxcount,
2828                         (SMB_BIG_UINT)startpos,
2829                         READ_LOCK)) {
2830                 reply_readbraw_error();
2831                 END_PROFILE(SMBreadbraw);
2832                 return;
2833         }
2834
2835         if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2836                 size = st.st_size;
2837         }
2838
2839         if (startpos >= size) {
2840                 nread = 0;
2841         } else {
2842                 nread = MIN(maxcount,(size - startpos));
2843         }
2844
2845 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2846         if (nread < mincount)
2847                 nread = 0;
2848 #endif
2849   
2850         DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
2851                 "min=%lu nread=%lu\n",
2852                 fsp->fnum, (double)startpos,
2853                 (unsigned long)maxcount,
2854                 (unsigned long)mincount,
2855                 (unsigned long)nread ) );
2856   
2857         send_file_readbraw(conn, fsp, startpos, nread, mincount);
2858
2859         DEBUG(5,("reply_readbraw finished\n"));
2860         END_PROFILE(SMBreadbraw);
2861 }
2862
2863 #undef DBGC_CLASS
2864 #define DBGC_CLASS DBGC_LOCKING
2865
2866 /****************************************************************************
2867  Reply to a lockread (core+ protocol).
2868 ****************************************************************************/
2869
2870 void reply_lockread(connection_struct *conn, struct smb_request *req)
2871 {
2872         ssize_t nread = -1;
2873         char *data;
2874         SMB_OFF_T startpos;
2875         size_t numtoread;
2876         NTSTATUS status;
2877         files_struct *fsp;
2878         struct byte_range_lock *br_lck = NULL;
2879         char *p = NULL;
2880
2881         START_PROFILE(SMBlockread);
2882
2883         if (req->wct < 5) {
2884                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2885                 END_PROFILE(SMBlockread);
2886                 return;
2887         }
2888
2889         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
2890
2891         if (!check_fsp(conn, req, fsp, &current_user)) {
2892                 END_PROFILE(SMBlockread);
2893                 return;
2894         }
2895
2896         if (!CHECK_READ(fsp,req->inbuf)) {
2897                 reply_doserror(req, ERRDOS, ERRbadaccess);
2898                 END_PROFILE(SMBlockread);
2899                 return;
2900         }
2901
2902         release_level_2_oplocks_on_change(fsp);
2903
2904         numtoread = SVAL(req->inbuf,smb_vwv1);
2905         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
2906
2907         numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
2908
2909         reply_outbuf(req, 5, numtoread + 3);
2910
2911         data = smb_buf(req->outbuf) + 3;
2912         
2913         /*
2914          * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2915          * protocol request that predates the read/write lock concept. 
2916          * Thus instead of asking for a read lock here we need to ask
2917          * for a write lock. JRA.
2918          * Note that the requested lock size is unaffected by max_recv.
2919          */
2920         
2921         br_lck = do_lock(smbd_messaging_context(),
2922                         fsp,
2923                         req->smbpid,
2924                         (SMB_BIG_UINT)numtoread,
2925                         (SMB_BIG_UINT)startpos,
2926                         WRITE_LOCK,
2927                         WINDOWS_LOCK,
2928                         False, /* Non-blocking lock. */
2929                         &status,
2930                         NULL);
2931         TALLOC_FREE(br_lck);
2932
2933         if (NT_STATUS_V(status)) {
2934                 reply_nterror(req, status);
2935                 END_PROFILE(SMBlockread);
2936                 return;
2937         }
2938
2939         /*
2940          * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2941          */
2942
2943         if (numtoread > max_recv) {
2944                 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2945 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2946                         (unsigned int)numtoread, (unsigned int)max_recv ));
2947                 numtoread = MIN(numtoread,max_recv);
2948         }
2949         nread = read_file(fsp,data,startpos,numtoread);
2950
2951         if (nread < 0) {
2952                 reply_unixerror(req, ERRDOS, ERRnoaccess);
2953                 END_PROFILE(SMBlockread);
2954                 return;
2955         }
2956         
2957         srv_set_message((char *)req->outbuf, 5, nread+3, False);
2958
2959         SSVAL(req->outbuf,smb_vwv0,nread);
2960         SSVAL(req->outbuf,smb_vwv5,nread+3);
2961         p = smb_buf(req->outbuf);
2962         SCVAL(p,0,0); /* pad byte. */
2963         SSVAL(p,1,nread);
2964         
2965         DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2966                  fsp->fnum, (int)numtoread, (int)nread));
2967
2968         END_PROFILE(SMBlockread);
2969         return;
2970 }
2971
2972 #undef DBGC_CLASS
2973 #define DBGC_CLASS DBGC_ALL
2974
2975 /****************************************************************************
2976  Reply to a read.
2977 ****************************************************************************/
2978
2979 void reply_read(connection_struct *conn, struct smb_request *req)
2980 {
2981         size_t numtoread;
2982         ssize_t nread = 0;
2983         char *data;
2984         SMB_OFF_T startpos;
2985         int outsize = 0;
2986         files_struct *fsp;
2987
2988         START_PROFILE(SMBread);
2989
2990         if (req->wct < 3) {
2991                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2992                 END_PROFILE(SMBread);
2993                 return;
2994         }
2995
2996         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
2997
2998         if (!check_fsp(conn, req, fsp, &current_user)) {
2999                 END_PROFILE(SMBread);
3000                 return;
3001         }
3002
3003         if (!CHECK_READ(fsp,req->inbuf)) {
3004                 reply_doserror(req, ERRDOS, ERRbadaccess);
3005                 END_PROFILE(SMBread);
3006                 return;
3007         }
3008
3009         numtoread = SVAL(req->inbuf,smb_vwv1);
3010         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
3011
3012         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3013
3014         /*
3015          * The requested read size cannot be greater than max_recv. JRA.
3016          */
3017         if (numtoread > max_recv) {
3018                 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3019 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3020                         (unsigned int)numtoread, (unsigned int)max_recv ));
3021                 numtoread = MIN(numtoread,max_recv);
3022         }
3023
3024         reply_outbuf(req, 5, numtoread+3);
3025
3026         data = smb_buf(req->outbuf) + 3;
3027   
3028         if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtoread,
3029                       (SMB_BIG_UINT)startpos, READ_LOCK)) {
3030                 reply_doserror(req, ERRDOS,ERRlock);
3031                 END_PROFILE(SMBread);
3032                 return;
3033         }
3034
3035         if (numtoread > 0)
3036                 nread = read_file(fsp,data,startpos,numtoread);
3037
3038         if (nread < 0) {
3039                 reply_unixerror(req, ERRDOS,ERRnoaccess);
3040                 END_PROFILE(SMBread);
3041                 return;
3042         }
3043
3044         srv_set_message((char *)req->outbuf, 5, nread+3, False);
3045
3046         SSVAL(req->outbuf,smb_vwv0,nread);
3047         SSVAL(req->outbuf,smb_vwv5,nread+3);
3048         SCVAL(smb_buf(req->outbuf),0,1);
3049         SSVAL(smb_buf(req->outbuf),1,nread);
3050   
3051         DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3052                 fsp->fnum, (int)numtoread, (int)nread ) );
3053
3054         END_PROFILE(SMBread);
3055         return;
3056 }
3057
3058 /****************************************************************************
3059  Setup readX header.
3060 ****************************************************************************/
3061
3062 static int setup_readX_header(char *outbuf, size_t smb_maxcnt)
3063 {
3064         int outsize;
3065         char *data;
3066
3067         outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3068         data = smb_buf(outbuf);
3069
3070         memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3071
3072         SCVAL(outbuf,smb_vwv0,0xFF);
3073         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3074         SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3075         SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
3076         SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3077         SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
3078         /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3079         _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3080         return outsize;
3081 }
3082
3083 /****************************************************************************
3084  Reply to a read and X - possibly using sendfile.
3085 ****************************************************************************/
3086
3087 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3088                             files_struct *fsp, SMB_OFF_T startpos,
3089                             size_t smb_maxcnt)
3090 {
3091         SMB_STRUCT_STAT sbuf;
3092         ssize_t nread = -1;
3093
3094         if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3095                 reply_unixerror(req, ERRDOS, ERRnoaccess);
3096                 return;
3097         }
3098
3099         if (startpos > sbuf.st_size) {
3100                 smb_maxcnt = 0;
3101         } else if (smb_maxcnt > (sbuf.st_size - startpos)) {
3102                 smb_maxcnt = (sbuf.st_size - startpos);
3103         }
3104
3105         if (smb_maxcnt == 0) {
3106                 goto normal_read;
3107         }
3108
3109 #if defined(WITH_SENDFILE)
3110         /*
3111          * We can only use sendfile on a non-chained packet
3112          * but we can use on a non-oplocked file. tridge proved this
3113          * on a train in Germany :-). JRA.
3114          */
3115
3116         if ((chain_size == 0) && (CVAL(req->inbuf,smb_vwv0) == 0xFF) &&
3117             !is_encrypted_packet(req->inbuf) &&
3118             lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
3119                 uint8 headerbuf[smb_size + 12 * 2];
3120                 DATA_BLOB header;
3121
3122                 /*
3123                  * Set up the packet header before send. We
3124                  * assume here the sendfile will work (get the
3125                  * correct amount of data).
3126                  */
3127
3128                 header = data_blob_const(headerbuf, sizeof(headerbuf));
3129
3130                 construct_reply_common((char *)req->inbuf, (char *)headerbuf);
3131                 setup_readX_header((char *)headerbuf, smb_maxcnt);
3132
3133                 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
3134                         /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
3135                         if (errno == ENOSYS) {
3136                                 goto normal_read;
3137                         }
3138
3139                         /*
3140                          * Special hack for broken Linux with no working sendfile. If we
3141                          * return EINTR we sent the header but not the rest of the data.
3142                          * Fake this up by doing read/write calls.
3143                          */
3144
3145                         if (errno == EINTR) {
3146                                 /* Ensure we don't do this again. */
3147                                 set_use_sendfile(SNUM(conn), False);
3148                                 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3149                                 nread = fake_sendfile(fsp, startpos,
3150                                                       smb_maxcnt);
3151                                 if (nread == -1) {
3152                                         DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3153                                                 fsp->fsp_name, strerror(errno) ));
3154                                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
3155                                 }
3156                                 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3157                                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3158                                 /* No outbuf here means successful sendfile. */
3159                                 TALLOC_FREE(req->outbuf);
3160                                 return;
3161                         }
3162
3163                         DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3164                                 fsp->fsp_name, strerror(errno) ));
3165                         exit_server_cleanly("send_file_readX sendfile failed");
3166                 }
3167
3168                 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3169                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3170                 /* No outbuf here means successful sendfile. */
3171                 TALLOC_FREE(req->outbuf);
3172                 return;
3173         }
3174 #endif
3175
3176 normal_read:
3177
3178         if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3179                 uint8 headerbuf[smb_size + 2*12];
3180
3181                 construct_reply_common((char *)req->inbuf, (char *)headerbuf);
3182                 setup_readX_header((char *)headerbuf, smb_maxcnt);
3183
3184                 /* Send out the header. */
3185                 if (write_data(smbd_server_fd(), (char *)headerbuf,
3186                                sizeof(headerbuf)) != sizeof(headerbuf)) {
3187                         DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3188                                 fsp->fsp_name, strerror(errno) ));
3189                         exit_server_cleanly("send_file_readX sendfile failed");
3190                 }
3191                 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3192                 if (nread == -1) {
3193                         DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3194                                 fsp->fsp_name, strerror(errno) ));
3195                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
3196                 }
3197                 TALLOC_FREE(req->outbuf);
3198                 return;
3199         } else {
3200                 reply_outbuf(req, 12, smb_maxcnt);
3201
3202                 nread = read_file(fsp, smb_buf(req->outbuf), startpos,
3203                                   smb_maxcnt);
3204                 if (nread < 0) {
3205                         reply_unixerror(req, ERRDOS, ERRnoaccess);
3206                         return;
3207                 }
3208
3209                 setup_readX_header((char *)req->outbuf, nread);
3210
3211                 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3212                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3213
3214                 chain_reply(req);
3215
3216                 return;
3217         }
3218 }
3219
3220 /****************************************************************************
3221  Reply to a read and X.
3222 ****************************************************************************/
3223
3224 void reply_read_and_X(connection_struct *conn, struct smb_request *req)
3225 {
3226         files_struct *fsp;
3227         SMB_OFF_T startpos;
3228         size_t smb_maxcnt;
3229         bool big_readX = False;
3230 #if 0
3231         size_t smb_mincnt = SVAL(req->inbuf,smb_vwv6);
3232 #endif
3233
3234         START_PROFILE(SMBreadX);
3235
3236         if ((req->wct != 10) && (req->wct != 12)) {
3237                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3238                 return;
3239         }
3240
3241         fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
3242         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
3243         smb_maxcnt = SVAL(req->inbuf,smb_vwv5);
3244
3245         /* If it's an IPC, pass off the pipe handler. */
3246         if (IS_IPC(conn)) {
3247                 reply_pipe_read_and_X(req);
3248                 END_PROFILE(SMBreadX);
3249                 return;
3250         }
3251
3252         if (!check_fsp(conn, req, fsp, &current_user)) {
3253                 END_PROFILE(SMBreadX);
3254                 return;
3255         }
3256
3257         if (!CHECK_READ(fsp,req->inbuf)) {
3258                 reply_doserror(req, ERRDOS,ERRbadaccess);
3259                 END_PROFILE(SMBreadX);
3260                 return;
3261         }
3262
3263         if (global_client_caps & CAP_LARGE_READX) {
3264                 size_t upper_size = SVAL(req->inbuf,smb_vwv7);
3265                 smb_maxcnt |= (upper_size<<16);
3266                 if (upper_size > 1) {
3267                         /* Can't do this on a chained packet. */
3268                         if ((CVAL(req->inbuf,smb_vwv0) != 0xFF)) {
3269                                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3270                                 END_PROFILE(SMBreadX);
3271                                 return;
3272                         }
3273                         /* We currently don't do this on signed or sealed data. */
3274                         if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
3275                                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3276                                 END_PROFILE(SMBreadX);
3277                                 return;
3278                         }
3279                         /* Is there room in the reply for this data ? */
3280                         if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2)))  {
3281                                 reply_nterror(req,
3282                                               NT_STATUS_INVALID_PARAMETER);
3283                                 END_PROFILE(SMBreadX);
3284                                 return;
3285                         }
3286                         big_readX = True;
3287                 }
3288         }
3289
3290         if (req->wct == 12) {
3291 #ifdef LARGE_SMB_OFF_T
3292                 /*
3293                  * This is a large offset (64 bit) read.
3294                  */
3295                 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv10)) << 32);
3296
3297 #else /* !LARGE_SMB_OFF_T */
3298
3299                 /*
3300                  * Ensure we haven't been sent a >32 bit offset.
3301                  */
3302
3303                 if(IVAL(req->inbuf,smb_vwv10) != 0) {
3304                         DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3305                                  "used and we don't support 64 bit offsets.\n",
3306                                  (unsigned int)IVAL(req->inbuf,smb_vwv10) ));
3307                         END_PROFILE(SMBreadX);
3308                         reply_doserror(req, ERRDOS, ERRbadaccess);
3309                         return;
3310                 }
3311
3312 #endif /* LARGE_SMB_OFF_T */
3313
3314         }
3315
3316         if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)smb_maxcnt,
3317                       (SMB_BIG_UINT)startpos, READ_LOCK)) {
3318                 END_PROFILE(SMBreadX);
3319                 reply_doserror(req, ERRDOS, ERRlock);
3320                 return;
3321         }
3322
3323         if (!big_readX
3324             && schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3325                 END_PROFILE(SMBreadX);
3326                 return;
3327         }
3328
3329         send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3330
3331         END_PROFILE(SMBreadX);
3332         return;
3333 }
3334
3335 /****************************************************************************
3336  Error replies to writebraw must have smb_wct == 1. Fix this up.
3337 ****************************************************************************/
3338
3339 void error_to_writebrawerr(struct smb_request *req)
3340 {
3341         uint8 *old_outbuf = req->outbuf;
3342
3343         reply_outbuf(req, 1, 0);
3344
3345         memcpy(req->outbuf, old_outbuf, smb_size);
3346         TALLOC_FREE(old_outbuf);
3347 }
3348
3349 /****************************************************************************
3350  Reply to a writebraw (core+ or LANMAN1.0 protocol).
3351 ****************************************************************************/
3352
3353 void reply_writebraw(connection_struct *conn, struct smb_request *req)
3354 {
3355         int outsize = 0;
3356         char *buf = NULL;
3357         ssize_t nwritten=0;
3358         ssize_t total_written=0;
3359         size_t numtowrite=0;
3360         size_t tcount;
3361         SMB_OFF_T startpos;
3362         char *data=NULL;
3363         bool write_through;
3364         files_struct *fsp;
3365         NTSTATUS status;
3366
3367         START_PROFILE(SMBwritebraw);
3368
3369         /*
3370          * If we ever reply with an error, it must have the SMB command
3371          * type of SMBwritec, not SMBwriteBraw, as this tells the client
3372          * we're finished.
3373          */
3374         SCVAL(req->inbuf,smb_com,SMBwritec);
3375
3376         if (srv_is_signing_active()) {
3377                 END_PROFILE(SMBwritebraw);
3378                 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3379                                 "raw reads/writes are disallowed.");
3380         }
3381
3382         if (req->wct < 12) {
3383                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3384                 error_to_writebrawerr(req);
3385                 END_PROFILE(SMBwritebraw);
3386                 return;
3387         }
3388
3389         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3390         if (!check_fsp(conn, req, fsp, &current_user)) {
3391                 error_to_writebrawerr(req);
3392                 END_PROFILE(SMBwritebraw);
3393                 return;
3394         }
3395
3396         if (!CHECK_WRITE(fsp)) {
3397                 reply_doserror(req, ERRDOS, ERRbadaccess);
3398                 error_to_writebrawerr(req);
3399                 END_PROFILE(SMBwritebraw);
3400                 return;
3401         }
3402
3403         tcount = IVAL(req->inbuf,smb_vwv1);
3404         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
3405         write_through = BITSETW(req->inbuf+smb_vwv7,0);
3406
3407         /* We have to deal with slightly different formats depending
3408                 on whether we are using the core+ or lanman1.0 protocol */
3409
3410         if(Protocol <= PROTOCOL_COREPLUS) {
3411                 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3412                 data = smb_buf(req->inbuf);
3413         } else {
3414                 numtowrite = SVAL(req->inbuf,smb_vwv10);
3415                 data = smb_base(req->inbuf) + SVAL(req->inbuf, smb_vwv11);
3416         }
3417
3418         /* Ensure we don't write bytes past the end of this packet. */
3419         if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3420                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3421                 error_to_writebrawerr(req);
3422                 END_PROFILE(SMBwritebraw);
3423                 return;
3424         }
3425
3426         if (is_locked(fsp,(uint32)req->smbpid,(SMB_BIG_UINT)tcount,
3427                                 (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3428                 reply_doserror(req, ERRDOS, ERRlock);
3429                 error_to_writebrawerr(req);
3430                 END_PROFILE(SMBwritebraw);
3431                 return;
3432         }
3433
3434         if (numtowrite>0) {
3435                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3436         }
3437
3438         DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3439                         "wrote=%d sync=%d\n",
3440                 fsp->fnum, (double)startpos, (int)numtowrite,
3441                 (int)nwritten, (int)write_through));
3442
3443         if (nwritten < (ssize_t)numtowrite)  {
3444                 reply_unixerror(req, ERRHRD, ERRdiskfull);
3445                 error_to_writebrawerr(req);
3446                 END_PROFILE(SMBwritebraw);
3447                 return;
3448         }
3449
3450         total_written = nwritten;
3451
3452         /* Allocate a buffer of 64k + length. */
3453         buf = TALLOC_ARRAY(NULL, char, 65540);
3454         if (!buf) {
3455                 reply_doserror(req, ERRDOS, ERRnomem);
3456                 error_to_writebrawerr(req);
3457                 END_PROFILE(SMBwritebraw);
3458                 return;
3459         }
3460
3461         /* Return a SMBwritebraw message to the redirector to tell
3462          * it to send more bytes */
3463
3464         memcpy(buf, req->inbuf, smb_size);
3465         outsize = srv_set_message(buf,
3466                         Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3467         SCVAL(buf,smb_com,SMBwritebraw);
3468         SSVALS(buf,smb_vwv0,0xFFFF);
3469         show_msg(buf);
3470         if (!srv_send_smb(smbd_server_fd(),
3471                         buf,
3472                         IS_CONN_ENCRYPTED(conn))) {
3473                 exit_server_cleanly("reply_writebraw: srv_send_smb "
3474                         "failed.");
3475         }
3476
3477         /* Now read the raw data into the buffer and write it */
3478         if (read_smb_length(smbd_server_fd(),buf,
3479                         SMB_SECONDARY_WAIT, get_srv_read_error()) == -1) {
3480                 exit_server_cleanly("secondary writebraw failed");
3481         }
3482
3483         /*
3484          * Even though this is not an smb message,
3485          * smb_len returns the generic length of a packet.
3486          */
3487
3488         numtowrite = smb_len(buf);
3489
3490         /* Set up outbuf to return the correct size */
3491         reply_outbuf(req, 1, 0);
3492
3493         if (numtowrite != 0) {
3494
3495                 if (numtowrite > 0xFFFF) {
3496                         DEBUG(0,("reply_writebraw: Oversize secondary write "
3497                                 "raw requested (%u). Terminating\n",
3498                                 (unsigned int)numtowrite ));
3499                         exit_server_cleanly("secondary writebraw failed");
3500                 }
3501
3502                 if (tcount > nwritten+numtowrite) {
3503                         DEBUG(3,("reply_writebraw: Client overestimated the "
3504                                 "write %d %d %d\n",
3505                                 (int)tcount,(int)nwritten,(int)numtowrite));
3506                 }
3507
3508                 if (read_data(smbd_server_fd(), buf+4, numtowrite,get_srv_read_error())
3509                                         != numtowrite ) {
3510                         DEBUG(0,("reply_writebraw: Oversize secondary write "
3511                                 "raw read failed (%s). Terminating\n",
3512                                 strerror(errno) ));
3513                         exit_server_cleanly("secondary writebraw failed");
3514                 }
3515
3516                 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3517                 if (nwritten == -1) {
3518                         TALLOC_FREE(buf);
3519                         reply_unixerror(req, ERRHRD, ERRdiskfull);
3520                         error_to_writebrawerr(req);
3521                         END_PROFILE(SMBwritebraw);
3522                         return;
3523                 }
3524
3525                 if (nwritten < (ssize_t)numtowrite) {
3526                         SCVAL(req->outbuf,smb_rcls,ERRHRD);
3527                         SSVAL(req->outbuf,smb_err,ERRdiskfull);
3528                 }
3529
3530                 if (nwritten > 0) {
3531                         total_written += nwritten;
3532                 }
3533         }
3534
3535         TALLOC_FREE(buf);
3536         SSVAL(req->outbuf,smb_vwv0,total_written);
3537
3538         status = sync_file(conn, fsp, write_through);
3539         if (!NT_STATUS_IS_OK(status)) {
3540                 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3541                         fsp->fsp_name, nt_errstr(status) ));
3542                 reply_nterror(req, status);
3543                 error_to_writebrawerr(req);
3544                 END_PROFILE(SMBwritebraw);
3545                 return;
3546         }
3547
3548         DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3549                 "wrote=%d\n",
3550                 fsp->fnum, (double)startpos, (int)numtowrite,
3551                 (int)total_written));
3552
3553         /* We won't return a status if write through is not selected - this
3554          * follows what WfWg does */
3555         END_PROFILE(SMBwritebraw);
3556
3557         if (!write_through && total_written==tcount) {
3558
3559 #if RABBIT_PELLET_FIX
3560                 /*
3561                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3562                  * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3563                  * JRA.
3564                  */
3565                 if (!send_keepalive(smbd_server_fd())) {
3566                         exit_server_cleanly("reply_writebraw: send of "
3567                                 "keepalive failed");
3568                 }
3569 #endif
3570                 TALLOC_FREE(req->outbuf);
3571         }
3572         return;
3573 }
3574
3575 #undef DBGC_CLASS
3576 #define DBGC_CLASS DBGC_LOCKING
3577
3578 /****************************************************************************
3579  Reply to a writeunlock (core+).
3580 ****************************************************************************/
3581
3582 void reply_writeunlock(connection_struct *conn, struct smb_request *req)
3583 {
3584         ssize_t nwritten = -1;
3585         size_t numtowrite;
3586         SMB_OFF_T startpos;
3587         char *data;
3588         NTSTATUS status = NT_STATUS_OK;
3589         files_struct *fsp;
3590
3591         START_PROFILE(SMBwriteunlock);
3592
3593         if (req->wct < 5) {
3594                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3595                 END_PROFILE(SMBwriteunlock);
3596                 return;
3597         }
3598         
3599         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3600
3601         if (!check_fsp(conn, req, fsp, &current_user)) {
3602                 END_PROFILE(SMBwriteunlock);
3603                 return;
3604         }
3605
3606         if (!CHECK_WRITE(fsp)) {
3607                 reply_doserror(req, ERRDOS,ERRbadaccess);
3608                 END_PROFILE(SMBwriteunlock);
3609                 return;
3610         }
3611
3612         numtowrite = SVAL(req->inbuf,smb_vwv1);
3613         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
3614         data = smb_buf(req->inbuf) + 3;
3615   
3616         if (numtowrite
3617             && is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
3618                          (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3619                 reply_doserror(req, ERRDOS, ERRlock);
3620                 END_PROFILE(SMBwriteunlock);
3621                 return;
3622         }
3623
3624         /* The special X/Open SMB protocol handling of
3625            zero length writes is *NOT* done for
3626            this call */
3627         if(numtowrite == 0) {
3628                 nwritten = 0;
3629         } else {
3630                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3631         }
3632   
3633         status = sync_file(conn, fsp, False /* write through */);
3634         if (!NT_STATUS_IS_OK(status)) {
3635                 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3636                         fsp->fsp_name, nt_errstr(status) ));
3637                 reply_nterror(req, status);
3638                 END_PROFILE(SMBwriteunlock);
3639                 return;
3640         }
3641
3642         if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
3643                 reply_unixerror(req, ERRHRD, ERRdiskfull);
3644                 END_PROFILE(SMBwriteunlock);
3645                 return;
3646         }
3647
3648         if (numtowrite) {
3649                 status = do_unlock(smbd_messaging_context(),
3650                                 fsp,
3651                                 req->smbpid,
3652                                 (SMB_BIG_UINT)numtowrite, 
3653                                 (SMB_BIG_UINT)startpos,
3654                                 WINDOWS_LOCK);
3655
3656                 if (NT_STATUS_V(status)) {
3657                         reply_nterror(req, status);
3658                         END_PROFILE(SMBwriteunlock);
3659                         return;
3660                 }
3661         }
3662
3663         reply_outbuf(req, 1, 0);
3664         
3665         SSVAL(req->outbuf,smb_vwv0,nwritten);
3666         
3667         DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3668                  fsp->fnum, (int)numtowrite, (int)nwritten));
3669         
3670         END_PROFILE(SMBwriteunlock);
3671         return;
3672 }
3673
3674 #undef DBGC_CLASS
3675 #define DBGC_CLASS DBGC_ALL
3676
3677 /****************************************************************************
3678  Reply to a write.
3679 ****************************************************************************/
3680
3681 void reply_write(connection_struct *conn, struct smb_request *req)
3682 {
3683         size_t numtowrite;
3684         ssize_t nwritten = -1;
3685         SMB_OFF_T startpos;
3686         char *data;
3687         files_struct *fsp;
3688         NTSTATUS status;
3689
3690         START_PROFILE(SMBwrite);
3691
3692         if (req->wct < 5) {
3693                 END_PROFILE(SMBwrite);
3694                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3695                 return;
3696         }
3697
3698         /* If it's an IPC, pass off the pipe handler. */
3699         if (IS_IPC(conn)) {
3700                 reply_pipe_write(req);
3701                 END_PROFILE(SMBwrite);
3702                 return;
3703         }
3704
3705         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3706
3707         if (!check_fsp(conn, req, fsp, &current_user)) {
3708                 END_PROFILE(SMBwrite);
3709                 return;
3710         }
3711
3712         if (!CHECK_WRITE(fsp)) {
3713                 reply_doserror(req, ERRDOS, ERRbadaccess);
3714                 END_PROFILE(SMBwrite);
3715                 return;
3716         }
3717
3718         numtowrite = SVAL(req->inbuf,smb_vwv1);
3719         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
3720         data = smb_buf(req->inbuf) + 3;
3721   
3722         if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
3723                       (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3724                 reply_doserror(req, ERRDOS, ERRlock);
3725                 END_PROFILE(SMBwrite);
3726                 return;
3727         }
3728
3729         /*
3730          * X/Open SMB protocol says that if smb_vwv1 is
3731          * zero then the file size should be extended or
3732          * truncated to the size given in smb_vwv[2-3].
3733          */
3734
3735         if(numtowrite == 0) {
3736                 /*
3737                  * This is actually an allocate call, and set EOF. JRA.
3738                  */
3739                 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3740                 if (nwritten < 0) {
3741                         reply_nterror(req, NT_STATUS_DISK_FULL);
3742                         END_PROFILE(SMBwrite);
3743                         return;
3744                 }
3745                 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3746                 if (nwritten < 0) {
3747                         reply_nterror(req, NT_STATUS_DISK_FULL);
3748                         END_PROFILE(SMBwrite);
3749                         return;
3750                 }
3751         } else
3752                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3753   
3754         status = sync_file(conn, fsp, False);
3755         if (!NT_STATUS_IS_OK(status)) {
3756                 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3757                         fsp->fsp_name, nt_errstr(status) ));
3758                 reply_nterror(req, status);
3759                 END_PROFILE(SMBwrite);
3760                 return;
3761         }
3762
3763         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3764                 reply_unixerror(req, ERRHRD, ERRdiskfull);
3765                 END_PROFILE(SMBwrite);
3766                 return;
3767         }
3768
3769         reply_outbuf(req, 1, 0);
3770   
3771         SSVAL(req->outbuf,smb_vwv0,nwritten);
3772
3773         if (nwritten < (ssize_t)numtowrite) {
3774                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3775                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3776         }
3777   
3778         DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3779
3780         END_PROFILE(SMBwrite);
3781         return;
3782 }
3783
3784 /****************************************************************************
3785  Ensure a buffer is a valid writeX for recvfile purposes.
3786 ****************************************************************************/
3787
3788 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
3789                                                 (2*14) + /* word count (including bcc) */ \
3790                                                 1 /* pad byte */)
3791
3792 bool is_valid_writeX_buffer(const uint8_t *inbuf)
3793 {
3794         size_t numtowrite;
3795         connection_struct *conn = NULL;
3796         unsigned int doff = 0;
3797         size_t len = smb_len_large(inbuf);
3798
3799         if (is_encrypted_packet(inbuf)) {
3800                 /* Can't do this on encrypted
3801                  * connections. */
3802                 return false;
3803         }
3804
3805         if (CVAL(inbuf,smb_com) != SMBwriteX) {
3806                 return false;
3807         }
3808
3809         if (CVAL(inbuf,smb_vwv0) != 0xFF ||
3810                         CVAL(inbuf,smb_wct) != 14) {
3811                 DEBUG(10,("is_valid_writeX_buffer: chained or "
3812                         "invalid word length.\n"));
3813                 return false;
3814         }
3815
3816         conn = conn_find(SVAL(inbuf, smb_tid));
3817         if (conn == NULL) {
3818                 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
3819                 return false;
3820         }
3821         if (IS_IPC(conn)) {
3822                 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
3823                 return false;
3824         }
3825         doff = SVAL(inbuf,smb_vwv11);
3826
3827         numtowrite = SVAL(inbuf,smb_vwv10);
3828
3829         if (len > doff && len - doff > 0xFFFF) {
3830                 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
3831         }
3832
3833         if (numtowrite == 0) {
3834                 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
3835                 return false;
3836         }
3837
3838         /* Ensure the sizes match up. */
3839         if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
3840                 /* no pad byte...old smbclient :-( */
3841                 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
3842                         (unsigned int)doff,
3843                         (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
3844                 return false;
3845         }
3846
3847         if (len - doff != numtowrite) {
3848                 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
3849                         "len = %u, doff = %u, numtowrite = %u\n",
3850                         (unsigned int)len,
3851                         (unsigned int)doff,
3852                         (unsigned int)numtowrite ));
3853                 return false;
3854         }
3855
3856         DEBUG(10,("is_valid_writeX_buffer: true "
3857                 "len = %u, doff = %u, numtowrite = %u\n",
3858                 (unsigned int)len,
3859                 (unsigned int)doff,
3860                 (unsigned int)numtowrite ));
3861
3862         return true;
3863 }
3864
3865 /****************************************************************************
3866  Reply to a write and X.
3867 ****************************************************************************/
3868
3869 void reply_write_and_X(connection_struct *conn, struct smb_request *req)
3870 {
3871         files_struct *fsp;
3872         SMB_OFF_T startpos;
3873         size_t numtowrite;
3874         bool write_through;
3875         ssize_t nwritten;
3876         unsigned int smb_doff;
3877         unsigned int smblen;
3878         char *data;
3879         NTSTATUS status;
3880
3881         START_PROFILE(SMBwriteX);
3882
3883         if ((req->wct != 12) && (req->wct != 14)) {
3884                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3885                 END_PROFILE(SMBwriteX);
3886                 return;
3887         }
3888
3889         numtowrite = SVAL(req->inbuf,smb_vwv10);
3890         smb_doff = SVAL(req->inbuf,smb_vwv11);
3891         smblen = smb_len(req->inbuf);
3892
3893         if (req->unread_bytes > 0xFFFF ||
3894                         (smblen > smb_doff &&
3895                                 smblen - smb_doff > 0xFFFF)) {
3896                 numtowrite |= (((size_t)SVAL(req->inbuf,smb_vwv9))<<16);
3897         }
3898
3899         if (req->unread_bytes) {
3900                 /* Can't do a recvfile write on IPC$ */
3901                 if (IS_IPC(conn)) {
3902                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3903                         END_PROFILE(SMBwriteX);
3904                         return;
3905                 }
3906                 if (numtowrite != req->unread_bytes) {
3907                         reply_doserror(req, ERRDOS, ERRbadmem);
3908                         END_PROFILE(SMBwriteX);
3909                         return;
3910                 }
3911         } else {
3912                 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
3913                                 smb_doff + numtowrite > smblen) {
3914                         reply_doserror(req, ERRDOS, ERRbadmem);
3915                         END_PROFILE(SMBwriteX);
3916                         return;
3917                 }
3918         }
3919
3920         /* If it's an IPC, pass off the pipe handler. */
3921         if (IS_IPC(conn)) {
3922                 if (req->unread_bytes) {
3923                         reply_doserror(req, ERRDOS, ERRbadmem);
3924                         END_PROFILE(SMBwriteX);
3925                         return;
3926                 }
3927                 reply_pipe_write_and_X(req);
3928                 END_PROFILE(SMBwriteX);
3929                 return;
3930         }
3931
3932         fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
3933         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
3934         write_through = BITSETW(req->inbuf+smb_vwv7,0);
3935
3936         if (!check_fsp(conn, req, fsp, &current_user)) {
3937                 END_PROFILE(SMBwriteX);
3938                 return;
3939         }
3940
3941         if (!CHECK_WRITE(fsp)) {
3942                 reply_doserror(req, ERRDOS, ERRbadaccess);
3943                 END_PROFILE(SMBwriteX);
3944                 return;
3945         }
3946
3947         data = smb_base(req->inbuf) + smb_doff;
3948
3949         if(req->wct == 14) {
3950 #ifdef LARGE_SMB_OFF_T
3951                 /*
3952                  * This is a large offset (64 bit) write.
3953                  */
3954                 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv12)) << 32);
3955
3956 #else /* !LARGE_SMB_OFF_T */
3957
3958                 /*
3959                  * Ensure we haven't been sent a >32 bit offset.
3960                  */
3961
3962                 if(IVAL(req->inbuf,smb_vwv12) != 0) {
3963                         DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
3964                                  "used and we don't support 64 bit offsets.\n",
3965                                  (unsigned int)IVAL(req->inbuf,smb_vwv12) ));
3966                         reply_doserror(req, ERRDOS, ERRbadaccess);
3967                         END_PROFILE(SMBwriteX);
3968                         return;
3969                 }
3970
3971 #endif /* LARGE_SMB_OFF_T */
3972         }
3973
3974         if (is_locked(fsp,(uint32)req->smbpid,
3975                       (SMB_BIG_UINT)numtowrite,
3976                       (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3977                 reply_doserror(req, ERRDOS, ERRlock);
3978                 END_PROFILE(SMBwriteX);
3979                 return;
3980         }
3981
3982         /* X/Open SMB protocol says that, unlike SMBwrite
3983         if the length is zero then NO truncation is
3984         done, just a write of zero. To truncate a file,
3985         use SMBwrite. */
3986
3987         if(numtowrite == 0) {
3988                 nwritten = 0;
3989         } else {
3990
3991                 if (req->unread_bytes == 0 &&
3992                                 schedule_aio_write_and_X(conn, req, fsp, data,
3993                                                         startpos, numtowrite)) {
3994                         END_PROFILE(SMBwriteX);
3995                         return;
3996                 }
3997
3998                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3999         }
4000
4001         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4002                 reply_unixerror(req, ERRHRD, ERRdiskfull);
4003                 END_PROFILE(SMBwriteX);
4004                 return;
4005         }
4006
4007         reply_outbuf(req, 6, 0);
4008         SSVAL(req->outbuf,smb_vwv2,nwritten);
4009         SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4010
4011         if (nwritten < (ssize_t)numtowrite) {
4012                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4013                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4014         }
4015
4016         DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4017                 fsp->fnum, (int)numtowrite, (int)nwritten));
4018
4019         status = sync_file(conn, fsp, write_through);
4020         if (!NT_STATUS_IS_OK(status)) {
4021                 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4022                         fsp->fsp_name, nt_errstr(status) ));
4023                 reply_nterror(req, status);
4024                 END_PROFILE(SMBwriteX);
4025                 return;
4026         }
4027
4028         END_PROFILE(SMBwriteX);
4029         chain_reply(req);
4030         return;
4031 }
4032
4033 /****************************************************************************
4034  Reply to a lseek.
4035 ****************************************************************************/
4036
4037 void reply_lseek(connection_struct *conn, struct smb_request *req)
4038 {
4039         SMB_OFF_T startpos;
4040         SMB_OFF_T res= -1;
4041         int mode,umode;
4042         files_struct *fsp;
4043
4044         START_PROFILE(SMBlseek);
4045
4046         if (req->wct < 4) {
4047                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4048                 END_PROFILE(SMBlseek);
4049                 return;
4050         }
4051
4052         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4053
4054         if (!check_fsp(conn, req, fsp, &current_user)) {
4055                 return;
4056         }
4057
4058         flush_write_cache(fsp, SEEK_FLUSH);
4059
4060         mode = SVAL(req->inbuf,smb_vwv1) & 3;
4061         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4062         startpos = (SMB_OFF_T)IVALS(req->inbuf,smb_vwv2);
4063
4064         switch (mode) {
4065                 case 0:
4066                         umode = SEEK_SET;
4067                         res = startpos;
4068                         break;
4069                 case 1:
4070                         umode = SEEK_CUR;
4071                         res = fsp->fh->pos + startpos;
4072                         break;
4073                 case 2:
4074                         umode = SEEK_END;
4075                         break;
4076                 default:
4077                         umode = SEEK_SET;
4078                         res = startpos;
4079                         break;
4080         }
4081
4082         if (umode == SEEK_END) {
4083                 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
4084                         if(errno == EINVAL) {
4085                                 SMB_OFF_T current_pos = startpos;
4086                                 SMB_STRUCT_STAT sbuf;
4087
4088                                 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
4089                                         reply_unixerror(req, ERRDOS,
4090                                                         ERRnoaccess);
4091                                         END_PROFILE(SMBlseek);
4092                                         return;
4093                                 }
4094
4095                                 current_pos += sbuf.st_size;
4096                                 if(current_pos < 0)
4097                                         res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
4098                         }
4099                 }
4100
4101                 if(res == -1) {
4102                         reply_unixerror(req, ERRDOS, ERRnoaccess);
4103                         END_PROFILE(SMBlseek);
4104                         return;
4105                 }
4106         }
4107
4108         fsp->fh->pos = res;
4109
4110         reply_outbuf(req, 2, 0);
4111         SIVAL(req->outbuf,smb_vwv0,res);
4112   
4113         DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4114                 fsp->fnum, (double)startpos, (double)res, mode));
4115
4116         END_PROFILE(SMBlseek);
4117         return;
4118 }
4119
4120 /****************************************************************************
4121  Reply to a flush.
4122 ****************************************************************************/
4123
4124 void reply_flush(connection_struct *conn, struct smb_request *req)
4125 {
4126         uint16 fnum;
4127         files_struct *fsp;
4128
4129         START_PROFILE(SMBflush);
4130
4131         if (req->wct < 1) {
4132                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4133                 return;
4134         }
4135
4136         fnum = SVAL(req->inbuf,smb_vwv0);
4137         fsp = file_fsp(fnum);
4138
4139         if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp, &current_user)) {
4140                 return;
4141         }
4142         
4143         if (!fsp) {
4144                 file_sync_all(conn);
4145         } else {
4146                 NTSTATUS status = sync_file(conn, fsp, True);
4147                 if (!NT_STATUS_IS_OK(status)) {
4148                         DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4149                                 fsp->fsp_name, nt_errstr(status) ));
4150                         reply_nterror(req, status);
4151                         END_PROFILE(SMBflush);
4152                         return;
4153                 }
4154         }
4155         
4156         reply_outbuf(req, 0, 0);
4157
4158         DEBUG(3,("flush\n"));
4159         END_PROFILE(SMBflush);
4160         return;
4161 }
4162
4163 /****************************************************************************
4164  Reply to a exit.
4165  conn POINTER CAN BE NULL HERE !
4166 ****************************************************************************/
4167
4168 void reply_exit(connection_struct *conn, struct smb_request *req)
4169 {
4170         START_PROFILE(SMBexit);
4171
4172         file_close_pid(req->smbpid, req->vuid);
4173
4174         reply_outbuf(req, 0, 0);
4175
4176         DEBUG(3,("exit\n"));
4177
4178         END_PROFILE(SMBexit);
4179         return;
4180 }
4181
4182 /****************************************************************************
4183  Reply to a close - has to deal with closing a directory opened by NT SMB's.
4184 ****************************************************************************/
4185
4186 void reply_close(connection_struct *conn, struct smb_request *req)
4187 {
4188         NTSTATUS status = NT_STATUS_OK;
4189         files_struct *fsp = NULL;
4190         START_PROFILE(SMBclose);
4191
4192         if (req->wct < 3) {
4193                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4194                 END_PROFILE(SMBclose);
4195                 return;
4196         }
4197
4198         /* If it's an IPC, pass off to the pipe handler. */
4199         if (IS_IPC(conn)) {
4200                 reply_pipe_close(conn, req);
4201                 END_PROFILE(SMBclose);
4202                 return;
4203         }
4204
4205         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4206
4207         /*
4208          * We can only use CHECK_FSP if we know it's not a directory.
4209          */
4210
4211         if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
4212                 reply_doserror(req, ERRDOS, ERRbadfid);
4213                 END_PROFILE(SMBclose);
4214                 return;
4215         }
4216
4217         if(fsp->is_directory) {
4218                 /*
4219                  * Special case - close NT SMB directory handle.
4220                  */
4221                 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4222                 status = close_file(fsp,NORMAL_CLOSE);
4223         } else {
4224                 /*
4225                  * Close ordinary file.
4226                  */
4227
4228                 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4229                          fsp->fh->fd, fsp->fnum,
4230                          conn->num_files_open));
4231  
4232                 /*
4233                  * Take care of any time sent in the close.
4234                  */
4235
4236                 fsp_set_pending_modtime(fsp, convert_time_t_to_timespec(
4237                                                 srv_make_unix_date3(
4238                                                         req->inbuf+smb_vwv1)));
4239
4240                 /*
4241                  * close_file() returns the unix errno if an error
4242                  * was detected on close - normally this is due to
4243                  * a disk full error. If not then it was probably an I/O error.
4244                  */
4245  
4246                 status = close_file(fsp,NORMAL_CLOSE);
4247         }  
4248
4249         if (!NT_STATUS_IS_OK(status)) {
4250                 reply_nterror(req, status);
4251                 END_PROFILE(SMBclose);
4252                 return;
4253         }
4254
4255         reply_outbuf(req, 0, 0);
4256         END_PROFILE(SMBclose);
4257         return;
4258 }
4259
4260 /****************************************************************************
4261  Reply to a writeclose (Core+ protocol).
4262 ****************************************************************************/
4263
4264 void reply_writeclose(connection_struct *conn, struct smb_request *req)
4265 {
4266         size_t numtowrite;
4267         ssize_t nwritten = -1;
4268         NTSTATUS close_status = NT_STATUS_OK;
4269         SMB_OFF_T startpos;
4270         char *data;
4271         struct timespec mtime;
4272         files_struct *fsp;
4273
4274         START_PROFILE(SMBwriteclose);
4275
4276         if (req->wct < 6) {
4277                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4278                 END_PROFILE(SMBwriteclose);
4279                 return;
4280         }
4281
4282         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4283
4284         if (!check_fsp(conn, req, fsp, &current_user)) {
4285                 END_PROFILE(SMBwriteclose);
4286                 return;
4287         }
4288         if (!CHECK_WRITE(fsp)) {
4289                 reply_doserror(req, ERRDOS,ERRbadaccess);
4290                 END_PROFILE(SMBwriteclose);
4291                 return;
4292         }
4293
4294         numtowrite = SVAL(req->inbuf,smb_vwv1);
4295         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
4296         mtime = convert_time_t_to_timespec(srv_make_unix_date3(
4297                                                    req->inbuf+smb_vwv4));
4298         data = smb_buf(req->inbuf) + 1;
4299   
4300         if (numtowrite
4301             && is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
4302                          (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
4303                 reply_doserror(req, ERRDOS,ERRlock);
4304                 END_PROFILE(SMBwriteclose);
4305                 return;
4306         }
4307   
4308         nwritten = write_file(req,fsp,data,startpos,numtowrite);
4309
4310         set_filetime(conn, fsp->fsp_name, mtime);
4311   
4312         /*
4313          * More insanity. W2K only closes the file if writelen > 0.
4314          * JRA.
4315          */
4316
4317         if (numtowrite) {
4318                 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4319                         fsp->fsp_name ));
4320                 close_status = close_file(fsp,NORMAL_CLOSE);
4321         }
4322
4323         DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4324                  fsp->fnum, (int)numtowrite, (int)nwritten,
4325                  conn->num_files_open));
4326   
4327         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4328                 reply_doserror(req, ERRHRD, ERRdiskfull);
4329                 END_PROFILE(SMBwriteclose);
4330                 return;
4331         }
4332  
4333         if(!NT_STATUS_IS_OK(close_status)) {
4334                 reply_nterror(req, close_status);
4335                 END_PROFILE(SMBwriteclose);
4336                 return;
4337         }
4338
4339         reply_outbuf(req, 1, 0);
4340   
4341         SSVAL(req->outbuf,smb_vwv0,nwritten);
4342         END_PROFILE(SMBwriteclose);
4343         return;
4344 }
4345
4346 #undef DBGC_CLASS
4347 #define DBGC_CLASS DBGC_LOCKING
4348
4349 /****************************************************************************
4350  Reply to a lock.
4351 ****************************************************************************/
4352
4353 void reply_lock(connection_struct *conn, struct smb_request *req)
4354 {
4355         SMB_BIG_UINT count,offset;
4356         NTSTATUS status;
4357         files_struct *fsp;
4358         struct byte_range_lock *br_lck = NULL;
4359
4360         START_PROFILE(SMBlock);
4361
4362         if (req->wct < 5) {
4363                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4364                 END_PROFILE(SMBlock);
4365                 return;
4366         }
4367
4368         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4369
4370         if (!check_fsp(conn, req, fsp, &current_user)) {
4371                 END_PROFILE(SMBlock);
4372                 return;
4373         }
4374
4375         release_level_2_oplocks_on_change(fsp);
4376
4377         count = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv1);
4378         offset = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv3);
4379
4380         DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4381                  fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4382
4383         br_lck = do_lock(smbd_messaging_context(),
4384                         fsp,
4385                         req->smbpid,
4386                         count,
4387                         offset,
4388                         WRITE_LOCK,
4389                         WINDOWS_LOCK,
4390                         False, /* Non-blocking lock. */
4391                         &status,
4392                         NULL);
4393
4394         TALLOC_FREE(br_lck);
4395
4396         if (NT_STATUS_V(status)) {
4397                 reply_nterror(req, status);
4398                 END_PROFILE(SMBlock);
4399                 return;
4400         }
4401
4402         reply_outbuf(req, 0, 0);
4403
4404         END_PROFILE(SMBlock);
4405         return;
4406 }
4407
4408 /****************************************************************************
4409  Reply to a unlock.
4410 ****************************************************************************/
4411
4412 void reply_unlock(connection_struct *conn, struct smb_request *req)
4413 {
4414         SMB_BIG_UINT count,offset;
4415         NTSTATUS status;
4416         files_struct *fsp;
4417
4418         START_PROFILE(SMBunlock);
4419
4420         if (req->wct < 5) {
4421                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4422                 END_PROFILE(SMBunlock);
4423                 return;
4424         }
4425
4426         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4427
4428         if (!check_fsp(conn, req, fsp, &current_user)) {
4429                 END_PROFILE(SMBunlock);
4430                 return;
4431         }
4432         
4433         count = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv1);
4434         offset = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv3);
4435         
4436         status = do_unlock(smbd_messaging_context(),
4437                         fsp,
4438                         req->smbpid,
4439                         count,
4440                         offset,
4441                         WINDOWS_LOCK);
4442
4443         if (NT_STATUS_V(status)) {
4444                 reply_nterror(req, status);
4445                 END_PROFILE(SMBunlock);
4446                 return;
4447         }
4448
4449         DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4450                     fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4451
4452         reply_outbuf(req, 0, 0);
4453
4454         END_PROFILE(SMBunlock);
4455         return;
4456 }
4457
4458 #undef DBGC_CLASS
4459 #define DBGC_CLASS DBGC_ALL
4460
4461 /****************************************************************************
4462  Reply to a tdis.
4463  conn POINTER CAN BE NULL HERE !
4464 ****************************************************************************/
4465
4466 void reply_tdis(connection_struct *conn, struct smb_request *req)
4467 {
4468         START_PROFILE(SMBtdis);
4469
4470         if (!conn) {
4471                 DEBUG(4,("Invalid connection in tdis\n"));
4472                 reply_doserror(req, ERRSRV, ERRinvnid);
4473                 END_PROFILE(SMBtdis);
4474                 return;
4475         }
4476
4477         conn->used = False;
4478
4479         close_cnum(conn,req->vuid);
4480         req->conn = NULL;
4481
4482         reply_outbuf(req, 0, 0);
4483         END_PROFILE(SMBtdis);
4484         return;
4485 }
4486
4487 /****************************************************************************
4488  Reply to a echo.
4489  conn POINTER CAN BE NULL HERE !
4490 ****************************************************************************/
4491
4492 void reply_echo(connection_struct *conn, struct smb_request *req)
4493 {
4494         int smb_reverb;
4495         int seq_num;
4496         unsigned int data_len = smb_buflen(req->inbuf);
4497
4498         START_PROFILE(SMBecho);
4499
4500         if (req->wct < 1) {
4501                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4502                 END_PROFILE(SMBecho);
4503                 return;
4504         }
4505
4506         if (data_len > BUFFER_SIZE) {
4507                 DEBUG(0,("reply_echo: data_len too large.\n"));
4508                 reply_nterror(req, NT_STATUS_INSUFFICIENT_RESOURCES);
4509                 END_PROFILE(SMBecho);
4510                 return;
4511         }
4512
4513         smb_reverb = SVAL(req->inbuf,smb_vwv0);
4514
4515         reply_outbuf(req, 1, data_len);
4516
4517         /* copy any incoming data back out */
4518         if (data_len > 0) {
4519                 memcpy(smb_buf(req->outbuf),smb_buf(req->inbuf),data_len);
4520         }
4521
4522         if (smb_reverb > 100) {
4523                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4524                 smb_reverb = 100;
4525         }
4526
4527         for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
4528                 SSVAL(req->outbuf,smb_vwv0,seq_num);
4529
4530                 show_msg((char *)req->outbuf);
4531                 if (!srv_send_smb(smbd_server_fd(),
4532                                 (char *)req->outbuf,
4533                                 IS_CONN_ENCRYPTED(conn)||req->encrypted))
4534                         exit_server_cleanly("reply_echo: srv_send_smb failed.");
4535         }
4536
4537         DEBUG(3,("echo %d times\n", smb_reverb));
4538
4539         TALLOC_FREE(req->outbuf);
4540
4541         smb_echo_count++;
4542
4543         END_PROFILE(SMBecho);
4544         return;
4545 }
4546
4547 /****************************************************************************
4548  Reply to a printopen.
4549 ****************************************************************************/
4550
4551 void reply_printopen(connection_struct *conn, struct smb_request *req)
4552 {
4553         files_struct *fsp;
4554         NTSTATUS status;
4555         
4556         START_PROFILE(SMBsplopen);
4557
4558         if (req->wct < 2) {
4559                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4560                 END_PROFILE(SMBsplopen);
4561                 return;
4562         }
4563
4564         if (!CAN_PRINT(conn)) {
4565                 reply_doserror(req, ERRDOS, ERRnoaccess);
4566                 END_PROFILE(SMBsplopen);
4567                 return;
4568         }
4569
4570         /* Open for exclusive use, write only. */
4571         status = print_fsp_open(conn, NULL, &fsp);
4572
4573         if (!NT_STATUS_IS_OK(status)) {
4574                 reply_nterror(req, status);
4575                 END_PROFILE(SMBsplopen);
4576                 return;
4577         }
4578
4579         reply_outbuf(req, 1, 0);
4580         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4581   
4582         DEBUG(3,("openprint fd=%d fnum=%d\n",
4583                  fsp->fh->fd, fsp->fnum));
4584
4585         END_PROFILE(SMBsplopen);
4586         return;
4587 }
4588
4589 /****************************************************************************
4590  Reply to a printclose.
4591 ****************************************************************************/
4592
4593 void reply_printclose(connection_struct *conn, struct smb_request *req)
4594 {
4595         files_struct *fsp;
4596         NTSTATUS status;
4597
4598         START_PROFILE(SMBsplclose);
4599
4600         if (req->wct < 3) {
4601                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4602                 END_PROFILE(SMBsplclose);
4603                 return;
4604         }
4605
4606         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4607
4608         if (!check_fsp(conn, req, fsp, &current_user)) {
4609                 END_PROFILE(SMBsplclose);
4610                 return;
4611         }
4612
4613         if (!CAN_PRINT(conn)) {
4614                 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
4615                 END_PROFILE(SMBsplclose);
4616                 return;
4617         }
4618   
4619         DEBUG(3,("printclose fd=%d fnum=%d\n",
4620                  fsp->fh->fd,fsp->fnum));
4621   
4622         status = close_file(fsp,NORMAL_CLOSE);
4623
4624         if(!NT_STATUS_IS_OK(status)) {
4625                 reply_nterror(req, status);
4626                 END_PROFILE(SMBsplclose);
4627                 return;
4628         }
4629
4630         END_PROFILE(SMBsplclose);
4631         return;
4632 }
4633
4634 /****************************************************************************
4635  Reply to a printqueue.
4636 ****************************************************************************/
4637
4638 void reply_printqueue(connection_struct *conn, struct smb_request *req)
4639 {
4640         int max_count;
4641         int start_index;
4642
4643         START_PROFILE(SMBsplretq);
4644
4645         if (req->wct < 2) {
4646                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4647                 END_PROFILE(SMBsplretq);
4648                 return;
4649         }
4650
4651         max_count = SVAL(req->inbuf,smb_vwv0);
4652         start_index = SVAL(req->inbuf,smb_vwv1);
4653
4654         /* we used to allow the client to get the cnum wrong, but that
4655            is really quite gross and only worked when there was only
4656            one printer - I think we should now only accept it if they
4657            get it right (tridge) */
4658         if (!CAN_PRINT(conn)) {
4659                 reply_doserror(req, ERRDOS, ERRnoaccess);
4660                 END_PROFILE(SMBsplretq);
4661                 return;
4662         }
4663
4664         reply_outbuf(req, 2, 3);
4665         SSVAL(req->outbuf,smb_vwv0,0);
4666         SSVAL(req->outbuf,smb_vwv1,0);
4667         SCVAL(smb_buf(req->outbuf),0,1);
4668         SSVAL(smb_buf(req->outbuf),1,0);
4669   
4670         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
4671                  start_index, max_count));
4672
4673         {
4674                 print_queue_struct *queue = NULL;
4675                 print_status_struct status;
4676                 int count = print_queue_status(SNUM(conn), &queue, &status);
4677                 int num_to_get = ABS(max_count);
4678                 int first = (max_count>0?start_index:start_index+max_count+1);
4679                 int i;
4680
4681                 if (first >= count)
4682                         num_to_get = 0;
4683                 else
4684                         num_to_get = MIN(num_to_get,count-first);
4685     
4686
4687                 for (i=first;i<first+num_to_get;i++) {
4688                         char blob[28];
4689                         char *p = blob;
4690
4691                         srv_put_dos_date2(p,0,queue[i].time);
4692                         SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
4693                         SSVAL(p,5, queue[i].job);
4694                         SIVAL(p,7,queue[i].size);
4695                         SCVAL(p,11,0);
4696                         srvstr_push(blob, req->flags2, p+12,
4697                                     queue[i].fs_user, 16, STR_ASCII);
4698
4699                         if (message_push_blob(
4700                                     &req->outbuf,
4701                                     data_blob_const(
4702                                             blob, sizeof(blob))) == -1) {
4703                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4704                                 END_PROFILE(SMBsplretq);
4705                                 return;
4706                         }
4707                 }
4708
4709                 if (count > 0) {
4710                         SSVAL(req->outbuf,smb_vwv0,count);
4711                         SSVAL(req->outbuf,smb_vwv1,
4712                               (max_count>0?first+count:first-1));
4713                         SCVAL(smb_buf(req->outbuf),0,1);
4714                         SSVAL(smb_buf(req->outbuf),1,28*count);
4715                 }
4716
4717                 SAFE_FREE(queue);
4718           
4719                 DEBUG(3,("%d entries returned in queue\n",count));
4720         }
4721   
4722         END_PROFILE(SMBsplretq);
4723         return;
4724 }
4725
4726 /****************************************************************************
4727  Reply to a printwrite.
4728 ****************************************************************************/
4729
4730 void reply_printwrite(connection_struct *conn, struct smb_request *req)
4731 {
4732         int numtowrite;
4733         char *data;
4734         files_struct *fsp;
4735
4736         START_PROFILE(SMBsplwr);
4737
4738         if (req->wct < 1) {
4739                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4740                 END_PROFILE(SMBsplwr);
4741                 return;
4742         }
4743   
4744         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4745
4746         if (!check_fsp(conn, req, fsp, &current_user)) {
4747                 END_PROFILE(SMBsplwr);
4748                 return;
4749         }
4750
4751         if (!CAN_PRINT(conn)) {
4752                 reply_doserror(req, ERRDOS, ERRnoaccess);
4753                 END_PROFILE(SMBsplwr);
4754                 return;
4755         }
4756
4757         if (!CHECK_WRITE(fsp)) {
4758                 reply_doserror(req, ERRDOS, ERRbadaccess);
4759                 END_PROFILE(SMBsplwr);
4760                 return;
4761         }
4762
4763         numtowrite = SVAL(smb_buf(req->inbuf),1);
4764
4765         if (smb_buflen(req->inbuf) < numtowrite + 3) {
4766                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4767                 END_PROFILE(SMBsplwr);
4768                 return;
4769         }
4770
4771         data = smb_buf(req->inbuf) + 3;
4772
4773         if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
4774                 reply_unixerror(req, ERRHRD, ERRdiskfull);
4775                 END_PROFILE(SMBsplwr);
4776                 return;
4777         }
4778
4779         DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
4780
4781         END_PROFILE(SMBsplwr);
4782         return;
4783 }
4784
4785 /****************************************************************************
4786  Reply to a mkdir.
4787 ****************************************************************************/
4788
4789 void reply_mkdir(connection_struct *conn, struct smb_request *req)
4790 {
4791         char *directory = NULL;
4792         NTSTATUS status;
4793         SMB_STRUCT_STAT sbuf;
4794         TALLOC_CTX *ctx = talloc_tos();
4795
4796         START_PROFILE(SMBmkdir);
4797
4798         srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &directory,
4799                         smb_buf(req->inbuf) + 1, 0,
4800                         STR_TERMINATE, &status);
4801         if (!NT_STATUS_IS_OK(status)) {
4802                 reply_nterror(req, status);
4803                 END_PROFILE(SMBmkdir);
4804                 return;
4805         }
4806
4807         status = resolve_dfspath(ctx, conn,
4808                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
4809                                  directory,
4810                                  &directory);
4811         if (!NT_STATUS_IS_OK(status)) {
4812                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4813                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
4814                                         ERRSRV, ERRbadpath);
4815                         END_PROFILE(SMBmkdir);
4816                         return;
4817                 }
4818                 reply_nterror(req, status);
4819                 END_PROFILE(SMBmkdir);
4820                 return;
4821         }
4822
4823         status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
4824         if (!NT_STATUS_IS_OK(status)) {
4825                 reply_nterror(req, status);
4826                 END_PROFILE(SMBmkdir);
4827                 return;
4828         }
4829
4830         status = check_name(conn, directory);
4831         if (!NT_STATUS_IS_OK(status)) {
4832                 reply_nterror(req, status);
4833                 END_PROFILE(SMBmkdir);
4834                 return;
4835         }
4836
4837         status = create_directory(conn, req, directory);
4838
4839         DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
4840
4841         if (!NT_STATUS_IS_OK(status)) {
4842
4843                 if (!use_nt_status()
4844                     && NT_STATUS_EQUAL(status,
4845                                        NT_STATUS_OBJECT_NAME_COLLISION)) {
4846                         /*
4847                          * Yes, in the DOS error code case we get a
4848                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
4849                          * samba4 torture test.
4850                          */
4851                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
4852                 }
4853
4854                 reply_nterror(req, status);
4855                 END_PROFILE(SMBmkdir);
4856                 return;
4857         }
4858
4859         reply_outbuf(req, 0, 0);
4860
4861         DEBUG( 3, ( "mkdir %s\n", directory ) );
4862
4863         END_PROFILE(SMBmkdir);
4864         return;
4865 }
4866
4867 /****************************************************************************
4868  Static function used by reply_rmdir to delete an entire directory
4869  tree recursively. Return True on ok, False on fail.
4870 ****************************************************************************/
4871
4872 static bool recursive_rmdir(TALLOC_CTX *ctx,
4873                         connection_struct *conn,
4874                         char *directory)
4875 {
4876         const char *dname = NULL;
4877         bool ret = True;
4878         long offset = 0;
4879         struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
4880
4881         if(dir_hnd == NULL)
4882                 return False;
4883
4884         while((dname = ReadDirName(dir_hnd, &offset))) {
4885                 char *fullname = NULL;
4886                 SMB_STRUCT_STAT st;
4887
4888                 if (ISDOT(dname) || ISDOTDOT(dname)) {
4889                         continue;
4890                 }
4891
4892                 if (!is_visible_file(conn, directory, dname, &st, False)) {
4893                         continue;
4894                 }
4895
4896                 /* Construct the full name. */
4897                 fullname = talloc_asprintf(ctx,
4898                                 "%s/%s",
4899                                 directory,
4900                                 dname);
4901                 if (!fullname) {
4902                         errno = ENOMEM;
4903                         ret = False;
4904                         break;
4905                 }
4906
4907                 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
4908                         ret = False;
4909                         break;
4910                 }
4911
4912                 if(st.st_mode & S_IFDIR) {
4913                         if(!recursive_rmdir(ctx, conn, fullname)) {
4914                                 ret = False;
4915                                 break;
4916                         }
4917                         if(SMB_VFS_RMDIR(conn,fullname) != 0) {
4918                                 ret = False;
4919                                 break;
4920                         }
4921                 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
4922                         ret = False;
4923                         break;
4924                 }
4925                 TALLOC_FREE(fullname);
4926         }
4927         CloseDir(dir_hnd);
4928         return ret;
4929 }
4930
4931 /****************************************************************************
4932  The internals of the rmdir code - called elsewhere.
4933 ****************************************************************************/
4934
4935 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
4936                         connection_struct *conn,
4937                         const char *directory)
4938 {
4939         int ret;
4940         SMB_STRUCT_STAT st;
4941
4942         /* Might be a symlink. */
4943         if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
4944                 return map_nt_error_from_unix(errno);
4945         }
4946
4947         if (S_ISLNK(st.st_mode)) {
4948                 /* Is what it points to a directory ? */
4949                 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
4950                         return map_nt_error_from_unix(errno);
4951                 }
4952                 if (!(S_ISDIR(st.st_mode))) {
4953                         return NT_STATUS_NOT_A_DIRECTORY;
4954                 }
4955                 ret = SMB_VFS_UNLINK(conn,directory);
4956         } else {
4957                 ret = SMB_VFS_RMDIR(conn,directory);
4958         }
4959         if (ret == 0) {
4960                 notify_fname(conn, NOTIFY_ACTION_REMOVED,
4961                              FILE_NOTIFY_CHANGE_DIR_NAME,
4962                              directory);
4963                 return NT_STATUS_OK;
4964         }
4965
4966         if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
4967                 /*
4968                  * Check to see if the only thing in this directory are
4969                  * vetoed files/directories. If so then delete them and
4970                  * retry. If we fail to delete any of them (and we *don't*
4971                  * do a recursive delete) then fail the rmdir.
4972                  */
4973                 const char *dname;
4974                 long dirpos = 0;
4975                 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
4976
4977                 if(dir_hnd == NULL) {
4978                         errno = ENOTEMPTY;
4979                         goto err;
4980                 }
4981
4982                 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4983                         if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4984                                 continue;
4985                         if (!is_visible_file(conn, directory, dname, &st, False))
4986                                 continue;
4987                         if(!IS_VETO_PATH(conn, dname)) {
4988                                 CloseDir(dir_hnd);
4989                                 errno = ENOTEMPTY;
4990                                 goto err;
4991                         }
4992                 }
4993
4994                 /* We only have veto files/directories. Recursive delete. */
4995
4996                 RewindDir(dir_hnd,&dirpos);
4997                 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4998                         char *fullname = NULL;
4999
5000                         if (ISDOT(dname) || ISDOTDOT(dname)) {
5001                                 continue;
5002                         }
5003                         if (!is_visible_file(conn, directory, dname, &st, False)) {
5004                                 continue;
5005                         }
5006
5007                         fullname = talloc_asprintf(ctx,
5008                                         "%s/%s",
5009                                         directory,
5010                                         dname);
5011
5012                         if(!fullname) {
5013                                 errno = ENOMEM;
5014                                 break;
5015                         }
5016
5017                         if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5018                                 break;
5019                         }
5020                         if(st.st_mode & S_IFDIR) {
5021                                 if(lp_recursive_veto_delete(SNUM(conn))) {
5022                                         if(!recursive_rmdir(ctx, conn, fullname))
5023                                                 break;
5024                                 }
5025                                 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5026                                         break;
5027                                 }
5028                         } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5029                                 break;
5030                         }
5031                         TALLOC_FREE(fullname);
5032                 }
5033                 CloseDir(dir_hnd);
5034                 /* Retry the rmdir */
5035                 ret = SMB_VFS_RMDIR(conn,directory);
5036         }
5037
5038   err:
5039
5040         if (ret != 0) {
5041                 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5042                          "%s\n", directory,strerror(errno)));
5043                 return map_nt_error_from_unix(errno);
5044         }
5045
5046         notify_fname(conn, NOTIFY_ACTION_REMOVED,
5047                      FILE_NOTIFY_CHANGE_DIR_NAME,
5048                      directory);
5049
5050         return NT_STATUS_OK;
5051 }
5052
5053 /****************************************************************************
5054  Reply to a rmdir.
5055 ****************************************************************************/
5056
5057 void reply_rmdir(connection_struct *conn, struct smb_request *req)
5058 {
5059         char *directory = NULL;
5060         SMB_STRUCT_STAT sbuf;
5061         NTSTATUS status;
5062         TALLOC_CTX *ctx = talloc_tos();
5063
5064         START_PROFILE(SMBrmdir);
5065
5066         srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &directory,
5067                         smb_buf(req->inbuf) + 1, 0,
5068                         STR_TERMINATE, &status);
5069         if (!NT_STATUS_IS_OK(status)) {
5070                 reply_nterror(req, status);
5071                 END_PROFILE(SMBrmdir);
5072                 return;
5073         }
5074
5075         status = resolve_dfspath(ctx, conn,
5076                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
5077                                  directory,
5078                                  &directory);
5079         if (!NT_STATUS_IS_OK(status)) {
5080                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5081                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5082                                         ERRSRV, ERRbadpath);
5083                         END_PROFILE(SMBrmdir);
5084                         return;
5085                 }
5086                 reply_nterror(req, status);
5087                 END_PROFILE(SMBrmdir);
5088                 return;
5089         }
5090
5091         status = unix_convert(ctx, conn, directory, False, &directory,
5092                         NULL, &sbuf);
5093         if (!NT_STATUS_IS_OK(status)) {
5094                 reply_nterror(req, status);
5095                 END_PROFILE(SMBrmdir);
5096                 return;
5097         }
5098
5099         status = check_name(conn, directory);
5100         if (!NT_STATUS_IS_OK(status)) {
5101                 reply_nterror(req, status);
5102                 END_PROFILE(SMBrmdir);
5103                 return;
5104         }
5105
5106         dptr_closepath(directory, req->smbpid);
5107         status = rmdir_internals(ctx, conn, directory);
5108         if (!NT_STATUS_IS_OK(status)) {
5109                 reply_nterror(req, status);
5110                 END_PROFILE(SMBrmdir);
5111                 return;
5112         }
5113
5114         reply_outbuf(req, 0, 0);
5115
5116         DEBUG( 3, ( "rmdir %s\n", directory ) );
5117
5118         END_PROFILE(SMBrmdir);
5119         return;
5120 }
5121
5122 /*******************************************************************
5123  Resolve wildcards in a filename rename.
5124 ********************************************************************/
5125
5126 static bool resolve_wildcards(TALLOC_CTX *ctx,
5127                                 const char *name1,
5128                                 const char *name2,
5129                                 char **pp_newname)
5130 {
5131         char *name2_copy = NULL;
5132         char *root1 = NULL;
5133         char *root2 = NULL;
5134         char *ext1 = NULL;
5135         char *ext2 = NULL;
5136         char *p,*p2, *pname1, *pname2;
5137         
5138         name2_copy = talloc_strdup(ctx, name2);
5139         if (!name2_copy) {
5140                 return False;
5141         }
5142
5143         pname1 = strrchr_m(name1,'/');
5144         pname2 = strrchr_m(name2_copy,'/');
5145
5146         if (!pname1 || !pname2) {
5147                 return False;
5148         }
5149   
5150         /* Truncate the copy of name2 at the last '/' */
5151         *pname2 = '\0';
5152
5153         /* Now go past the '/' */
5154         pname1++;
5155         pname2++;
5156
5157         root1 = talloc_strdup(ctx, pname1);
5158         root2 = talloc_strdup(ctx, pname2);
5159
5160         if (!root1 || !root2) {
5161                 return False;
5162         }
5163
5164         p = strrchr_m(root1,'.');
5165         if (p) {
5166                 *p = 0;
5167                 ext1 = talloc_strdup(ctx, p+1);
5168         } else {
5169                 ext1 = talloc_strdup(ctx, "");
5170         }
5171         p = strrchr_m(root2,'.');
5172         if (p) {
5173                 *p = 0;
5174                 ext2 = talloc_strdup(ctx, p+1);
5175         } else {
5176                 ext2 = talloc_strdup(ctx, "");
5177         }
5178
5179         if (!ext1 || !ext2) {
5180                 return False;
5181         }
5182
5183         p = root1;
5184         p2 = root2;
5185         while (*p2) {
5186                 if (*p2 == '?') {
5187                         /* Hmmm. Should this be mb-aware ? */
5188                         *p2 = *p;
5189                         p2++;
5190                 } else if (*p2 == '*') {
5191                         *p2 = '\0';
5192                         root2 = talloc_asprintf(ctx, "%s%s",
5193                                                 root2,
5194                                                 p);
5195                         if (!root2) {
5196                                 return False;
5197                         }
5198                         break;
5199                 } else {
5200                         p2++;
5201                 }
5202                 if (*p) {
5203                         p++;
5204                 }
5205         }
5206
5207         p = ext1;
5208         p2 = ext2;
5209         while (*p2) {
5210                 if (*p2 == '?') {
5211                         /* Hmmm. Should this be mb-aware ? */
5212                         *p2 = *p;
5213                         p2++;
5214                 } else if (*p2 == '*') {
5215                         *p2 = '\0';
5216                         ext2 = talloc_asprintf(ctx, "%s%s",
5217                                                 ext2,
5218                                                 p);
5219                         if (!ext2) {
5220                                 return False;
5221                         }
5222                         break;
5223                 } else {
5224                         p2++;
5225                 }
5226                 if (*p) {
5227                         p++;
5228                 }
5229         }
5230
5231         if (*ext2) {
5232                 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5233                                 name2_copy,
5234                                 root2,
5235                                 ext2);
5236         } else {
5237                 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5238                                 name2_copy,
5239                                 root2);
5240         }
5241
5242         if (!*pp_newname) {
5243                 return False;
5244         }
5245
5246         return True;
5247 }
5248
5249 /****************************************************************************
5250  Ensure open files have their names updated. Updated to notify other smbd's
5251  asynchronously.
5252 ****************************************************************************/
5253
5254 static void rename_open_files(connection_struct *conn,
5255                               struct share_mode_lock *lck,
5256                               const char *newname)
5257 {
5258         files_struct *fsp;
5259         bool did_rename = False;
5260
5261         for(fsp = file_find_di_first(lck->id); fsp;
5262             fsp = file_find_di_next(fsp)) {
5263                 /* fsp_name is a relative path under the fsp. To change this for other
5264                    sharepaths we need to manipulate relative paths. */
5265                 /* TODO - create the absolute path and manipulate the newname
5266                    relative to the sharepath. */
5267                 if (fsp->conn != conn) {
5268                         continue;
5269                 }
5270                 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5271                           fsp->fnum, file_id_string_tos(&fsp->file_id),
5272                         fsp->fsp_name, newname ));
5273                 string_set(&fsp->fsp_name, newname);
5274                 did_rename = True;
5275         }
5276
5277         if (!did_rename) {
5278                 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5279                           file_id_string_tos(&lck->id), newname ));
5280         }
5281
5282         /* Send messages to all smbd's (not ourself) that the name has changed. */
5283         rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5284                               newname);
5285 }
5286
5287 /****************************************************************************
5288  We need to check if the source path is a parent directory of the destination
5289  (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5290  refuse the rename with a sharing violation. Under UNIX the above call can
5291  *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5292  probably need to check that the client is a Windows one before disallowing
5293  this as a UNIX client (one with UNIX extensions) can know the source is a
5294  symlink and make this decision intelligently. Found by an excellent bug
5295  report from <AndyLiebman@aol.com>.
5296 ****************************************************************************/
5297
5298 static bool rename_path_prefix_equal(const char *src, const char *dest)
5299 {
5300         const char *psrc = src;
5301         const char *pdst = dest;
5302         size_t slen;
5303
5304         if (psrc[0] == '.' && psrc[1] == '/') {
5305                 psrc += 2;
5306         }
5307         if (pdst[0] == '.' && pdst[1] == '/') {
5308                 pdst += 2;
5309         }
5310         if ((slen = strlen(psrc)) > strlen(pdst)) {
5311                 return False;
5312         }
5313         return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5314 }
5315
5316 /*
5317  * Do the notify calls from a rename
5318  */
5319
5320 static void notify_rename(connection_struct *conn, bool is_dir,
5321                           const char *oldpath, const char *newpath)
5322 {
5323         char *olddir, *newdir;
5324         const char *oldname, *newname;
5325         uint32 mask;
5326
5327         mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5328                 : FILE_NOTIFY_CHANGE_FILE_NAME;
5329
5330         if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
5331             || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
5332                 TALLOC_FREE(olddir);
5333                 return;
5334         }
5335
5336         if (strcmp(olddir, newdir) == 0) {
5337                 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
5338                 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
5339         }
5340         else {
5341                 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
5342                 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
5343         }
5344         TALLOC_FREE(olddir);
5345         TALLOC_FREE(newdir);
5346
5347         /* this is a strange one. w2k3 gives an additional event for
5348            CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5349            files, but not directories */
5350         if (!is_dir) {
5351                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5352                              FILE_NOTIFY_CHANGE_ATTRIBUTES
5353                              |FILE_NOTIFY_CHANGE_CREATION,
5354                              newpath);
5355         }
5356 }
5357
5358 /****************************************************************************
5359  Rename an open file - given an fsp.
5360 ****************************************************************************/
5361
5362 NTSTATUS rename_internals_fsp(connection_struct *conn,
5363                         files_struct *fsp,
5364                         char *newname,
5365                         const char *newname_last_component,
5366                         uint32 attrs,
5367                         bool replace_if_exists)
5368 {
5369         TALLOC_CTX *ctx = talloc_tos();
5370         SMB_STRUCT_STAT sbuf, sbuf1;
5371         NTSTATUS status = NT_STATUS_OK;
5372         struct share_mode_lock *lck = NULL;
5373         bool dst_exists;
5374
5375         ZERO_STRUCT(sbuf);
5376
5377         status = check_name(conn, newname);
5378         if (!NT_STATUS_IS_OK(status)) {
5379                 return status;
5380         }
5381
5382         /* Ensure newname contains a '/' */
5383         if(strrchr_m(newname,'/') == 0) {
5384                 newname = talloc_asprintf(ctx,
5385                                         "./%s",
5386                                         newname);
5387                 if (!newname) {
5388                         return NT_STATUS_NO_MEMORY;
5389                 }
5390         }
5391
5392         /*
5393          * Check for special case with case preserving and not
5394          * case sensitive. If the old last component differs from the original
5395          * last component only by case, then we should allow
5396          * the rename (user is trying to change the case of the
5397          * filename).
5398          */
5399
5400         if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5401                         strequal(newname, fsp->fsp_name)) {
5402                 char *p;
5403                 char *newname_modified_last_component = NULL;
5404
5405                 /*
5406                  * Get the last component of the modified name.
5407                  * Note that we guarantee that newname contains a '/'
5408                  * character above.
5409                  */
5410                 p = strrchr_m(newname,'/');
5411                 newname_modified_last_component = talloc_strdup(ctx,
5412                                                 p+1);
5413                 if (!newname_modified_last_component) {
5414                         return NT_STATUS_NO_MEMORY;
5415                 }
5416
5417                 if(strcsequal(newname_modified_last_component,
5418                               newname_last_component) == False) {
5419                         /*
5420                          * Replace the modified last component with
5421                          * the original.
5422                          */
5423                         *p = '\0'; /* Truncate at the '/' */
5424                         newname = talloc_asprintf(ctx,
5425                                         "%s/%s",
5426                                         newname,
5427                                         newname_last_component);
5428                 }
5429         }
5430
5431         /*
5432          * If the src and dest names are identical - including case,
5433          * don't do the rename, just return success.
5434          */
5435
5436         if (strcsequal(fsp->fsp_name, newname)) {
5437                 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5438                         newname));
5439                 return NT_STATUS_OK;
5440         }
5441
5442         /*
5443          * Have vfs_object_exist also fill sbuf1
5444          */
5445         dst_exists = vfs_object_exist(conn, newname, &sbuf1);
5446
5447         if(!replace_if_exists && dst_exists) {
5448                 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5449                         fsp->fsp_name,newname));
5450                 return NT_STATUS_OBJECT_NAME_COLLISION;
5451         }
5452
5453         if (dst_exists) {
5454                 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5455                 files_struct *dst_fsp = file_find_di_first(fileid);
5456                 if (dst_fsp) {
5457                         DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5458                         return NT_STATUS_ACCESS_DENIED;
5459                 }
5460         }
5461
5462         /* Ensure we have a valid stat struct for the source. */
5463         if (fsp->fh->fd != -1) {
5464                 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) == -1) {
5465                         return map_nt_error_from_unix(errno);
5466                 }
5467         } else {
5468                 if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
5469                         return map_nt_error_from_unix(errno);
5470                 }
5471         }
5472
5473         status = can_rename(conn, fsp, attrs, &sbuf);
5474
5475         if (!NT_STATUS_IS_OK(status)) {
5476                 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5477                         nt_errstr(status), fsp->fsp_name,newname));
5478                 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5479                         status = NT_STATUS_ACCESS_DENIED;
5480                 return status;
5481         }
5482
5483         if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5484                 return NT_STATUS_ACCESS_DENIED;
5485         }
5486
5487         lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
5488
5489         /*
5490          * We have the file open ourselves, so not being able to get the
5491          * corresponding share mode lock is a fatal error.
5492          */
5493
5494         SMB_ASSERT(lck != NULL);
5495
5496         if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5497                 uint32 create_options = fsp->fh->private_options;
5498
5499                 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5500                         fsp->fsp_name,newname));
5501
5502                 rename_open_files(conn, lck, newname);
5503
5504                 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5505
5506                 /*
5507                  * A rename acts as a new file create w.r.t. allowing an initial delete
5508                  * on close, probably because in Windows there is a new handle to the
5509                  * new file. If initial delete on close was requested but not
5510                  * originally set, we need to set it here. This is probably not 100% correct,
5511                  * but will work for the CIFSFS client which in non-posix mode
5512                  * depends on these semantics. JRA.
5513                  */
5514
5515                 set_allow_initial_delete_on_close(lck, fsp, True);
5516
5517                 if (create_options & FILE_DELETE_ON_CLOSE) {
5518                         status = can_set_delete_on_close(fsp, True, 0);
5519
5520                         if (NT_STATUS_IS_OK(status)) {
5521                                 /* Note that here we set the *inital* delete on close flag,
5522                                  * not the regular one. The magic gets handled in close. */
5523                                 fsp->initial_delete_on_close = True;
5524                         }
5525                 }
5526                 TALLOC_FREE(lck);
5527                 return NT_STATUS_OK;
5528         }
5529
5530         TALLOC_FREE(lck);
5531
5532         if (errno == ENOTDIR || errno == EISDIR) {
5533                 status = NT_STATUS_OBJECT_NAME_COLLISION;
5534         } else {
5535                 status = map_nt_error_from_unix(errno);
5536         }
5537
5538         DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5539                 nt_errstr(status), fsp->fsp_name,newname));
5540
5541         return status;
5542 }
5543
5544 /****************************************************************************
5545  The guts of the rename command, split out so it may be called by the NT SMB
5546  code.
5547 ****************************************************************************/
5548
5549 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5550                         connection_struct *conn,
5551                         struct smb_request *req,
5552                         const char *name_in,
5553                         const char *newname_in,
5554                         uint32 attrs,
5555                         bool replace_if_exists,
5556                         bool src_has_wild,
5557                         bool dest_has_wild)
5558 {
5559         char *directory = NULL;
5560         char *mask = NULL;
5561         char *last_component_src = NULL;
5562         char *last_component_dest = NULL;
5563         char *name = NULL;
5564         char *newname = NULL;
5565         char *p;
5566         int count=0;
5567         NTSTATUS status = NT_STATUS_OK;
5568         SMB_STRUCT_STAT sbuf1, sbuf2;
5569         struct smb_Dir *dir_hnd = NULL;
5570         const char *dname;
5571         long offset = 0;
5572
5573         ZERO_STRUCT(sbuf1);
5574         ZERO_STRUCT(sbuf2);
5575
5576         status = unix_convert(ctx, conn, name_in, src_has_wild, &name,
5577                         &last_component_src, &sbuf1);
5578         if (!NT_STATUS_IS_OK(status)) {
5579                 return status;
5580         }
5581
5582         status = unix_convert(ctx, conn, newname_in, dest_has_wild, &newname,
5583                         &last_component_dest, &sbuf2);
5584         if (!NT_STATUS_IS_OK(status)) {
5585                 return status;
5586         }
5587
5588         /*
5589          * Split the old name into directory and last component
5590          * strings. Note that unix_convert may have stripped off a
5591          * leading ./ from both name and newname if the rename is
5592          * at the root of the share. We need to make sure either both
5593          * name and newname contain a / character or neither of them do
5594          * as this is checked in resolve_wildcards().
5595          */
5596
5597         p = strrchr_m(name,'/');
5598         if (!p) {
5599                 directory = talloc_strdup(ctx, ".");
5600                 if (!directory) {
5601                         return NT_STATUS_NO_MEMORY;
5602                 }
5603                 mask = name;
5604         } else {
5605                 *p = 0;
5606                 directory = talloc_strdup(ctx, name);
5607                 if (!directory) {
5608                         return NT_STATUS_NO_MEMORY;
5609                 }
5610                 mask = p+1;
5611                 *p = '/'; /* Replace needed for exceptional test below. */
5612         }
5613
5614         /*
5615          * We should only check the mangled cache
5616          * here if unix_convert failed. This means
5617          * that the path in 'mask' doesn't exist
5618          * on the file system and so we need to look
5619          * for a possible mangle. This patch from
5620          * Tine Smukavec <valentin.smukavec@hermes.si>.
5621          */
5622
5623         if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5624                 char *new_mask = NULL;
5625                 mangle_lookup_name_from_8_3(ctx,
5626                                         mask,
5627                                         &new_mask,
5628                                         conn->params );
5629                 if (new_mask) {
5630                         mask = new_mask;
5631                 }
5632         }
5633
5634         if (!src_has_wild) {
5635                 files_struct *fsp;
5636
5637                 /*
5638                  * No wildcards - just process the one file.
5639                  */
5640                 bool is_short_name = mangle_is_8_3(name, True, conn->params);
5641
5642                 /* Add a terminating '/' to the directory name. */
5643                 directory = talloc_asprintf_append(directory,
5644                                 "/%s",
5645                                 mask);
5646                 if (!directory) {
5647                         return NT_STATUS_NO_MEMORY;
5648                 }
5649
5650                 /* Ensure newname contains a '/' also */
5651                 if(strrchr_m(newname,'/') == 0) {
5652                         newname = talloc_asprintf(ctx,
5653                                                 "./%s",
5654                                                 newname);
5655                         if (!newname) {
5656                                 return NT_STATUS_NO_MEMORY;
5657                         }
5658                 }
5659
5660                 DEBUG(3, ("rename_internals: case_sensitive = %d, "
5661                           "case_preserve = %d, short case preserve = %d, "
5662                           "directory = %s, newname = %s, "
5663                           "last_component_dest = %s, is_8_3 = %d\n",
5664                           conn->case_sensitive, conn->case_preserve,
5665                           conn->short_case_preserve, directory,
5666                           newname, last_component_dest, is_short_name));
5667
5668                 /* The dest name still may have wildcards. */
5669                 if (dest_has_wild) {
5670                         char *mod_newname = NULL;
5671                         if (!resolve_wildcards(ctx,
5672                                         directory,newname,&mod_newname)) {
5673                                 DEBUG(6, ("rename_internals: resolve_wildcards "
5674                                         "%s %s failed\n",
5675                                         directory,
5676                                         newname));
5677                                 return NT_STATUS_NO_MEMORY;
5678                         }
5679                         newname = mod_newname;
5680                 }
5681
5682                 ZERO_STRUCT(sbuf1);
5683                 SMB_VFS_STAT(conn, directory, &sbuf1);
5684
5685                 status = S_ISDIR(sbuf1.st_mode) ?
5686                         open_directory(conn, req, directory, &sbuf1,
5687                                        DELETE_ACCESS,
5688                                        FILE_SHARE_READ|FILE_SHARE_WRITE,
5689                                        FILE_OPEN, 0, 0, NULL,
5690                                        &fsp)
5691                         : open_file_ntcreate(conn, req, directory, &sbuf1,
5692                                              DELETE_ACCESS,
5693                                              FILE_SHARE_READ|FILE_SHARE_WRITE,
5694                                              FILE_OPEN, 0, 0, 0, NULL,
5695                                              &fsp);
5696
5697                 if (!NT_STATUS_IS_OK(status)) {
5698                         DEBUG(3, ("Could not open rename source %s: %s\n",
5699                                   directory, nt_errstr(status)));
5700                         return status;
5701                 }
5702
5703                 status = rename_internals_fsp(conn, fsp, newname,
5704                                               last_component_dest,
5705                                               attrs, replace_if_exists);
5706
5707                 close_file(fsp, NORMAL_CLOSE);
5708
5709                 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
5710                           nt_errstr(status), directory,newname));
5711
5712                 return status;
5713         }
5714
5715         /*
5716          * Wildcards - process each file that matches.
5717          */
5718         if (strequal(mask,"????????.???")) {
5719                 mask[0] = '*';
5720                 mask[1] = '\0';
5721         }
5722
5723         status = check_name(conn, directory);
5724         if (!NT_STATUS_IS_OK(status)) {
5725                 return status;
5726         }
5727
5728         dir_hnd = OpenDir(conn, directory, mask, attrs);
5729         if (dir_hnd == NULL) {
5730                 return map_nt_error_from_unix(errno);
5731         }
5732
5733         status = NT_STATUS_NO_SUCH_FILE;
5734         /*
5735          * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
5736          * - gentest fix. JRA
5737          */
5738
5739         while ((dname = ReadDirName(dir_hnd, &offset))) {
5740                 files_struct *fsp = NULL;
5741                 char *fname = NULL;
5742                 char *destname = NULL;
5743                 bool sysdir_entry = False;
5744
5745                 /* Quick check for "." and ".." */
5746                 if (ISDOT(dname) || ISDOTDOT(dname)) {
5747                         if (attrs & aDIR) {
5748                                 sysdir_entry = True;
5749                         } else {
5750                                 continue;
5751                         }
5752                 }
5753
5754                 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5755                         continue;
5756                 }
5757
5758                 if(!mask_match(dname, mask, conn->case_sensitive)) {
5759                         continue;
5760                 }
5761
5762                 if (sysdir_entry) {
5763                         status = NT_STATUS_OBJECT_NAME_INVALID;
5764                         break;
5765                 }
5766
5767                 fname = talloc_asprintf(ctx,
5768                                 "%s/%s",
5769                                 directory,
5770                                 dname);
5771                 if (!fname) {
5772                         return NT_STATUS_NO_MEMORY;
5773                 }
5774
5775                 if (!resolve_wildcards(ctx,
5776                                 fname,newname,&destname)) {
5777                         DEBUG(6, ("resolve_wildcards %s %s failed\n",
5778                                   fname, destname));
5779                         TALLOC_FREE(fname);
5780                         continue;
5781                 }
5782                 if (!destname) {
5783                         return NT_STATUS_NO_MEMORY;
5784                 }
5785
5786                 ZERO_STRUCT(sbuf1);
5787                 SMB_VFS_STAT(conn, fname, &sbuf1);
5788
5789                 status = S_ISDIR(sbuf1.st_mode) ?
5790                         open_directory(conn, req, fname, &sbuf1,
5791                                        DELETE_ACCESS,
5792                                        FILE_SHARE_READ|FILE_SHARE_WRITE,
5793                                        FILE_OPEN, 0, 0, NULL,
5794                                        &fsp)
5795                         : open_file_ntcreate(conn, req, fname, &sbuf1,
5796                                              DELETE_ACCESS,
5797                                              FILE_SHARE_READ|FILE_SHARE_WRITE,
5798                                              FILE_OPEN, 0, 0, 0, NULL,
5799                                              &fsp);
5800
5801                 if (!NT_STATUS_IS_OK(status)) {
5802                         DEBUG(3,("rename_internals: open_file_ntcreate "
5803                                  "returned %s rename %s -> %s\n",
5804                                  nt_errstr(status), directory, newname));
5805                         break;
5806                 }
5807
5808                 status = rename_internals_fsp(conn, fsp, destname, dname,
5809                                               attrs, replace_if_exists);
5810
5811                 close_file(fsp, NORMAL_CLOSE);
5812
5813                 if (!NT_STATUS_IS_OK(status)) {
5814                         DEBUG(3, ("rename_internals_fsp returned %s for "
5815                                   "rename %s -> %s\n", nt_errstr(status),
5816                                   directory, newname));
5817                         break;
5818                 }
5819
5820                 count++;
5821
5822                 DEBUG(3,("rename_internals: doing rename on %s -> "
5823                          "%s\n",fname,destname));
5824
5825                 TALLOC_FREE(fname);
5826                 TALLOC_FREE(destname);
5827         }
5828         CloseDir(dir_hnd);
5829
5830         if (count == 0 && NT_STATUS_IS_OK(status)) {
5831                 status = map_nt_error_from_unix(errno);
5832         }
5833
5834         return status;
5835 }
5836
5837 /****************************************************************************
5838  Reply to a mv.
5839 ****************************************************************************/
5840
5841 void reply_mv(connection_struct *conn, struct smb_request *req)
5842 {
5843         char *name = NULL;
5844         char *newname = NULL;
5845         char *p;
5846         uint32 attrs;
5847         NTSTATUS status;
5848         bool src_has_wcard = False;
5849         bool dest_has_wcard = False;
5850         TALLOC_CTX *ctx = talloc_tos();
5851
5852         START_PROFILE(SMBmv);
5853
5854         if (req->wct < 1) {
5855                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5856                 END_PROFILE(SMBmv);
5857                 return;
5858         }
5859
5860         attrs = SVAL(req->inbuf,smb_vwv0);
5861
5862         p = smb_buf(req->inbuf) + 1;
5863         p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name, p,
5864                                    0, STR_TERMINATE, &status,
5865                                    &src_has_wcard);
5866         if (!NT_STATUS_IS_OK(status)) {
5867                 reply_nterror(req, status);
5868                 END_PROFILE(SMBmv);
5869                 return;
5870         }
5871         p++;
5872         p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &newname, p,
5873                                    0, STR_TERMINATE, &status,
5874                                    &dest_has_wcard);
5875         if (!NT_STATUS_IS_OK(status)) {
5876                 reply_nterror(req, status);
5877                 END_PROFILE(SMBmv);
5878                 return;
5879         }
5880
5881         status = resolve_dfspath_wcard(ctx, conn,
5882                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
5883                                        name,
5884                                        &name,
5885                                        &src_has_wcard);
5886         if (!NT_STATUS_IS_OK(status)) {
5887                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5888                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5889                                         ERRSRV, ERRbadpath);
5890                         END_PROFILE(SMBmv);
5891                         return;
5892                 }
5893                 reply_nterror(req, status);
5894                 END_PROFILE(SMBmv);
5895                 return;
5896         }
5897
5898         status = resolve_dfspath_wcard(ctx, conn,
5899                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
5900                                        newname,
5901                                        &newname,
5902                                        &dest_has_wcard);
5903         if (!NT_STATUS_IS_OK(status)) {
5904                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5905                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5906                                         ERRSRV, ERRbadpath);
5907                         END_PROFILE(SMBmv);
5908                         return;
5909                 }
5910                 reply_nterror(req, status);
5911                 END_PROFILE(SMBmv);
5912                 return;
5913         }
5914
5915         DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
5916
5917         status = rename_internals(ctx, conn, req, name, newname, attrs, False,
5918                                   src_has_wcard, dest_has_wcard);
5919         if (!NT_STATUS_IS_OK(status)) {
5920                 if (open_was_deferred(req->mid)) {
5921                         /* We have re-scheduled this call. */
5922                         END_PROFILE(SMBmv);
5923                         return;
5924                 }
5925                 reply_nterror(req, status);
5926                 END_PROFILE(SMBmv);
5927                 return;
5928         }
5929
5930         reply_outbuf(req, 0, 0);
5931
5932         END_PROFILE(SMBmv);
5933         return;
5934 }
5935
5936 /*******************************************************************
5937  Copy a file as part of a reply_copy.
5938 ******************************************************************/
5939
5940 /*
5941  * TODO: check error codes on all callers
5942  */
5943
5944 NTSTATUS copy_file(TALLOC_CTX *ctx,
5945                         connection_struct *conn,
5946                         const char *src,
5947                         const char *dest1,
5948                         int ofun,
5949                         int count,
5950                         bool target_is_directory)
5951 {
5952         SMB_STRUCT_STAT src_sbuf, sbuf2;
5953         SMB_OFF_T ret=-1;
5954         files_struct *fsp1,*fsp2;
5955         char *dest = NULL;
5956         uint32 dosattrs;
5957         uint32 new_create_disposition;
5958         NTSTATUS status;
5959
5960         dest = talloc_strdup(ctx, dest1);
5961         if (!dest) {
5962                 return NT_STATUS_NO_MEMORY;
5963         }
5964         if (target_is_directory) {
5965                 const char *p = strrchr_m(src,'/');
5966                 if (p) {
5967                         p++;
5968                 } else {
5969                         p = src;
5970                 }
5971                 dest = talloc_asprintf_append(dest,
5972                                 "/%s",
5973                                 p);
5974                 if (!dest) {
5975                         return NT_STATUS_NO_MEMORY;
5976                 }
5977         }
5978
5979         if (!vfs_file_exist(conn,src,&src_sbuf)) {
5980                 TALLOC_FREE(dest);
5981                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5982         }
5983
5984         if (!target_is_directory && count) {
5985                 new_create_disposition = FILE_OPEN;
5986         } else {
5987                 if (!map_open_params_to_ntcreate(dest1,0,ofun,
5988                                 NULL, NULL, &new_create_disposition, NULL)) {
5989                         TALLOC_FREE(dest);
5990                         return NT_STATUS_INVALID_PARAMETER;
5991                 }
5992         }
5993
5994         status = open_file_ntcreate(conn, NULL, src, &src_sbuf,
5995                         FILE_GENERIC_READ,
5996                         FILE_SHARE_READ|FILE_SHARE_WRITE,
5997                         FILE_OPEN,
5998                         0,
5999                         FILE_ATTRIBUTE_NORMAL,
6000                         INTERNAL_OPEN_ONLY,
6001                         NULL, &fsp1);
6002
6003         if (!NT_STATUS_IS_OK(status)) {
6004                 TALLOC_FREE(dest);
6005                 return status;
6006         }
6007
6008         dosattrs = dos_mode(conn, src, &src_sbuf);
6009         if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
6010                 ZERO_STRUCTP(&sbuf2);
6011         }
6012
6013         status = open_file_ntcreate(conn, NULL, dest, &sbuf2,
6014                         FILE_GENERIC_WRITE,
6015                         FILE_SHARE_READ|FILE_SHARE_WRITE,
6016                         new_create_disposition,
6017                         0,
6018                         dosattrs,
6019                         INTERNAL_OPEN_ONLY,
6020                         NULL, &fsp2);
6021
6022         TALLOC_FREE(dest);
6023
6024         if (!NT_STATUS_IS_OK(status)) {
6025                 close_file(fsp1,ERROR_CLOSE);
6026                 return status;
6027         }
6028
6029         if ((ofun&3) == 1) {
6030                 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
6031                         DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6032                         /*
6033                          * Stop the copy from occurring.
6034                          */
6035                         ret = -1;
6036                         src_sbuf.st_size = 0;
6037                 }
6038         }
6039
6040         if (src_sbuf.st_size) {
6041                 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
6042         }
6043
6044         close_file(fsp1,NORMAL_CLOSE);
6045
6046         /* Ensure the modtime is set correctly on the destination file. */
6047         fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
6048
6049         /*
6050          * As we are opening fsp1 read-only we only expect
6051          * an error on close on fsp2 if we are out of space.
6052          * Thus we don't look at the error return from the
6053          * close of fsp1.
6054          */
6055         status = close_file(fsp2,NORMAL_CLOSE);
6056
6057         if (!NT_STATUS_IS_OK(status)) {
6058                 return status;
6059         }
6060
6061         if (ret != (SMB_OFF_T)src_sbuf.st_size) {
6062                 return NT_STATUS_DISK_FULL;
6063         }
6064
6065         return NT_STATUS_OK;
6066 }
6067
6068 /****************************************************************************
6069  Reply to a file copy.
6070 ****************************************************************************/
6071
6072 void reply_copy(connection_struct *conn, struct smb_request *req)
6073 {
6074         char *name = NULL;
6075         char *newname = NULL;
6076         char *directory = NULL;
6077         char *mask = NULL;
6078         char *p;
6079         int count=0;
6080         int error = ERRnoaccess;
6081         int err = 0;
6082         int tid2;
6083         int ofun;
6084         int flags;
6085         bool target_is_directory=False;
6086         bool source_has_wild = False;
6087         bool dest_has_wild = False;
6088         SMB_STRUCT_STAT sbuf1, sbuf2;
6089         NTSTATUS status;
6090         TALLOC_CTX *ctx = talloc_tos();
6091
6092         START_PROFILE(SMBcopy);
6093
6094         if (req->wct < 3) {
6095                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6096                 END_PROFILE(SMBcopy);
6097                 return;
6098         }
6099
6100         tid2 = SVAL(req->inbuf,smb_vwv0);
6101         ofun = SVAL(req->inbuf,smb_vwv1);
6102         flags = SVAL(req->inbuf,smb_vwv2);
6103
6104         p = smb_buf(req->inbuf);
6105         p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name, p,
6106                                    0, STR_TERMINATE, &status,
6107                                    &source_has_wild);
6108         if (!NT_STATUS_IS_OK(status)) {
6109                 reply_nterror(req, status);
6110                 END_PROFILE(SMBcopy);
6111                 return;
6112         }
6113         p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &newname, p,
6114                                    0, STR_TERMINATE, &status,
6115                                    &dest_has_wild);
6116         if (!NT_STATUS_IS_OK(status)) {
6117                 reply_nterror(req, status);
6118                 END_PROFILE(SMBcopy);
6119                 return;
6120         }
6121
6122         DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
6123
6124         if (tid2 != conn->cnum) {
6125                 /* can't currently handle inter share copies XXXX */
6126                 DEBUG(3,("Rejecting inter-share copy\n"));
6127                 reply_doserror(req, ERRSRV, ERRinvdevice);
6128                 END_PROFILE(SMBcopy);
6129                 return;
6130         }
6131
6132         status = resolve_dfspath_wcard(ctx, conn,
6133                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
6134                                        name,
6135                                        &name,
6136                                        &source_has_wild);
6137         if (!NT_STATUS_IS_OK(status)) {
6138                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6139                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6140                                         ERRSRV, ERRbadpath);
6141                         END_PROFILE(SMBcopy);
6142                         return;
6143                 }
6144                 reply_nterror(req, status);
6145                 END_PROFILE(SMBcopy);
6146                 return;
6147         }
6148
6149         status = resolve_dfspath_wcard(ctx, conn,
6150                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
6151                                        newname,
6152                                        &newname,
6153                                        &dest_has_wild);
6154         if (!NT_STATUS_IS_OK(status)) {
6155                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6156                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6157                                         ERRSRV, ERRbadpath);
6158                         END_PROFILE(SMBcopy);
6159                         return;
6160                 }
6161                 reply_nterror(req, status);
6162                 END_PROFILE(SMBcopy);
6163                 return;
6164         }
6165
6166         status = unix_convert(ctx, conn, name, source_has_wild,
6167                         &name, NULL, &sbuf1);
6168         if (!NT_STATUS_IS_OK(status)) {
6169                 reply_nterror(req, status);
6170                 END_PROFILE(SMBcopy);
6171                 return;
6172         }
6173
6174         status = unix_convert(ctx, conn, newname, dest_has_wild,
6175                         &newname, NULL, &sbuf2);
6176         if (!NT_STATUS_IS_OK(status)) {
6177                 reply_nterror(req, status);
6178                 END_PROFILE(SMBcopy);
6179                 return;
6180         }
6181
6182         target_is_directory = VALID_STAT_OF_DIR(sbuf2);
6183
6184         if ((flags&1) && target_is_directory) {
6185                 reply_doserror(req, ERRDOS, ERRbadfile);
6186                 END_PROFILE(SMBcopy);
6187                 return;
6188         }
6189
6190         if ((flags&2) && !target_is_directory) {
6191                 reply_doserror(req, ERRDOS, ERRbadpath);
6192                 END_PROFILE(SMBcopy);
6193                 return;
6194         }
6195
6196         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
6197                 /* wants a tree copy! XXXX */
6198                 DEBUG(3,("Rejecting tree copy\n"));
6199                 reply_doserror(req, ERRSRV, ERRerror);
6200                 END_PROFILE(SMBcopy);
6201                 return;
6202         }
6203
6204         p = strrchr_m(name,'/');
6205         if (!p) {
6206                 directory = talloc_strdup(ctx, "./");
6207                 if (!directory) {
6208                         reply_nterror(req, NT_STATUS_NO_MEMORY);
6209                         END_PROFILE(SMBcopy);
6210                         return;
6211                 }
6212                 mask = name;
6213         } else {
6214                 *p = 0;
6215                 directory = talloc_strdup(ctx, name);
6216                 if (!directory) {
6217                         reply_nterror(req, NT_STATUS_NO_MEMORY);
6218                         END_PROFILE(SMBcopy);
6219                         return;
6220                 }
6221                 mask = p+1;
6222         }
6223
6224         /*
6225          * We should only check the mangled cache
6226          * here if unix_convert failed. This means
6227          * that the path in 'mask' doesn't exist
6228          * on the file system and so we need to look
6229          * for a possible mangle. This patch from
6230          * Tine Smukavec <valentin.smukavec@hermes.si>.
6231          */
6232
6233         if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
6234                 char *new_mask = NULL;
6235                 mangle_lookup_name_from_8_3(ctx,
6236                                         mask,
6237                                         &new_mask,
6238                                         conn->params );
6239                 if (new_mask) {
6240                         mask = new_mask;
6241                 }
6242         }
6243
6244         if (!source_has_wild) {
6245                 directory = talloc_asprintf_append(directory,
6246                                 "/%s",
6247                                 mask);
6248                 if (dest_has_wild) {
6249                         char *mod_newname = NULL;
6250                         if (!resolve_wildcards(ctx,
6251                                         directory,newname,&mod_newname)) {
6252                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6253                                 END_PROFILE(SMBcopy);
6254                                 return;
6255                         }
6256                         newname = mod_newname;
6257                 }
6258
6259                 status = check_name(conn, directory);
6260                 if (!NT_STATUS_IS_OK(status)) {
6261                         reply_nterror(req, status);
6262                         END_PROFILE(SMBcopy);
6263                         return;
6264                 }
6265
6266                 status = check_name(conn, newname);
6267                 if (!NT_STATUS_IS_OK(status)) {
6268                         reply_nterror(req, status);
6269                         END_PROFILE(SMBcopy);
6270                         return;
6271                 }
6272
6273                 status = copy_file(ctx,conn,directory,newname,ofun,
6274                                 count,target_is_directory);
6275
6276                 if(!NT_STATUS_IS_OK(status)) {
6277                         reply_nterror(req, status);
6278                         END_PROFILE(SMBcopy);
6279                         return;
6280                 } else {
6281                         count++;
6282                 }
6283         } else {
6284                 struct smb_Dir *dir_hnd = NULL;
6285                 const char *dname = NULL;
6286                 long offset = 0;
6287
6288                 if (strequal(mask,"????????.???")) {
6289                         mask[0] = '*';
6290                         mask[1] = '\0';
6291                 }
6292
6293                 status = check_name(conn, directory);
6294                 if (!NT_STATUS_IS_OK(status)) {
6295                         reply_nterror(req, status);
6296                         END_PROFILE(SMBcopy);
6297                         return;
6298                 }
6299
6300                 dir_hnd = OpenDir(conn, directory, mask, 0);
6301                 if (dir_hnd == NULL) {
6302                         status = map_nt_error_from_unix(errno);
6303                         reply_nterror(req, status);
6304                         END_PROFILE(SMBcopy);
6305                         return;
6306                 }
6307
6308                 error = ERRbadfile;
6309
6310                 while ((dname = ReadDirName(dir_hnd, &offset))) {
6311                         char *destname = NULL;
6312                         char *fname = NULL;
6313
6314                         if (ISDOT(dname) || ISDOTDOT(dname)) {
6315                                 continue;
6316                         }
6317
6318                         if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
6319                                 continue;
6320                         }
6321
6322                         if(!mask_match(dname, mask, conn->case_sensitive)) {
6323                                 continue;
6324                         }
6325
6326                         error = ERRnoaccess;
6327                         fname = talloc_asprintf(ctx,
6328                                         "%s/%s",
6329                                         directory,
6330                                         dname);
6331                         if (!fname) {
6332                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6333                                 END_PROFILE(SMBcopy);
6334                                 return;
6335                         }
6336
6337                         if (!resolve_wildcards(ctx,
6338                                         fname,newname,&destname)) {
6339                                 continue;
6340                         }
6341                         if (!destname) {
6342                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6343                                 END_PROFILE(SMBcopy);
6344                                 return;
6345                         }
6346
6347                         status = check_name(conn, fname);
6348                         if (!NT_STATUS_IS_OK(status)) {
6349                                 reply_nterror(req, status);
6350                                 END_PROFILE(SMBcopy);
6351                                 return;
6352                         }
6353
6354                         status = check_name(conn, destname);
6355                         if (!NT_STATUS_IS_OK(status)) {
6356                                 reply_nterror(req, status);
6357                                 END_PROFILE(SMBcopy);
6358                                 return;
6359                         }
6360
6361                         DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
6362
6363                         status = copy_file(ctx,conn,fname,destname,ofun,
6364                                         count,target_is_directory);
6365                         if (NT_STATUS_IS_OK(status)) {
6366                                 count++;
6367                         }
6368                         TALLOC_FREE(fname);
6369                         TALLOC_FREE(destname);
6370                 }
6371                 CloseDir(dir_hnd);
6372         }
6373
6374         if (count == 0) {
6375                 if(err) {
6376                         /* Error on close... */
6377                         errno = err;
6378                         reply_unixerror(req, ERRHRD, ERRgeneral);
6379                         END_PROFILE(SMBcopy);
6380                         return;
6381                 }
6382
6383                 reply_doserror(req, ERRDOS, error);
6384                 END_PROFILE(SMBcopy);
6385                 return;
6386         }
6387
6388         reply_outbuf(req, 1, 0);
6389         SSVAL(req->outbuf,smb_vwv0,count);
6390
6391         END_PROFILE(SMBcopy);
6392         return;
6393 }
6394
6395 #undef DBGC_CLASS
6396 #define DBGC_CLASS DBGC_LOCKING
6397
6398 /****************************************************************************
6399  Get a lock pid, dealing with large count requests.
6400 ****************************************************************************/
6401
6402 uint32 get_lock_pid( char *data, int data_offset, bool large_file_format)
6403 {
6404         if(!large_file_format)
6405                 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
6406         else
6407                 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6408 }
6409
6410 /****************************************************************************
6411  Get a lock count, dealing with large count requests.
6412 ****************************************************************************/
6413
6414 SMB_BIG_UINT get_lock_count( char *data, int data_offset, bool large_file_format)
6415 {
6416         SMB_BIG_UINT count = 0;
6417
6418         if(!large_file_format) {
6419                 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6420         } else {
6421
6422 #if defined(HAVE_LONGLONG)
6423                 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6424                         ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6425 #else /* HAVE_LONGLONG */
6426
6427                 /*
6428                  * NT4.x seems to be broken in that it sends large file (64 bit)
6429                  * lockingX calls even if the CAP_LARGE_FILES was *not*
6430                  * negotiated. For boxes without large unsigned ints truncate the
6431                  * lock count by dropping the top 32 bits.
6432                  */
6433
6434                 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6435                         DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6436                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6437                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6438                                 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6439                 }
6440
6441                 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6442 #endif /* HAVE_LONGLONG */
6443         }
6444
6445         return count;
6446 }
6447
6448 #if !defined(HAVE_LONGLONG)
6449 /****************************************************************************
6450  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6451 ****************************************************************************/
6452
6453 static uint32 map_lock_offset(uint32 high, uint32 low)
6454 {
6455         unsigned int i;
6456         uint32 mask = 0;
6457         uint32 highcopy = high;
6458  
6459         /*
6460          * Try and find out how many significant bits there are in high.
6461          */
6462  
6463         for(i = 0; highcopy; i++)
6464                 highcopy >>= 1;
6465  
6466         /*
6467          * We use 31 bits not 32 here as POSIX
6468          * lock offsets may not be negative.
6469          */
6470  
6471         mask = (~0) << (31 - i);
6472  
6473         if(low & mask)
6474                 return 0; /* Fail. */
6475  
6476         high <<= (31 - i);
6477  
6478         return (high|low);
6479 }
6480 #endif /* !defined(HAVE_LONGLONG) */
6481
6482 /****************************************************************************
6483  Get a lock offset, dealing with large offset requests.
6484 ****************************************************************************/
6485
6486 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, bool large_file_format, bool *err)
6487 {
6488         SMB_BIG_UINT offset = 0;
6489
6490         *err = False;
6491
6492         if(!large_file_format) {
6493                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
6494         } else {
6495
6496 #if defined(HAVE_LONGLONG)
6497                 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
6498                                 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
6499 #else /* HAVE_LONGLONG */
6500
6501                 /*
6502                  * NT4.x seems to be broken in that it sends large file (64 bit)
6503                  * lockingX calls even if the CAP_LARGE_FILES was *not*
6504                  * negotiated. For boxes without large unsigned ints mangle the
6505                  * lock offset by mapping the top 32 bits onto the lower 32.
6506                  */
6507       
6508                 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
6509                         uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6510                         uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
6511                         uint32 new_low = 0;
6512
6513                         if((new_low = map_lock_offset(high, low)) == 0) {
6514                                 *err = True;
6515                                 return (SMB_BIG_UINT)-1;
6516                         }
6517
6518                         DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
6519                                 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
6520                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
6521                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
6522                 }
6523
6524                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6525 #endif /* HAVE_LONGLONG */
6526         }
6527
6528         return offset;
6529 }
6530
6531 /****************************************************************************
6532  Reply to a lockingX request.
6533 ****************************************************************************/
6534
6535 void reply_lockingX(connection_struct *conn, struct smb_request *req)
6536 {
6537         files_struct *fsp;
6538         unsigned char locktype;
6539         unsigned char oplocklevel;
6540         uint16 num_ulocks;
6541         uint16 num_locks;
6542         SMB_BIG_UINT count = 0, offset = 0;
6543         uint32 lock_pid;
6544         int32 lock_timeout;
6545         int i;
6546         char *data;
6547         bool large_file_format;
6548         bool err;
6549         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
6550
6551         START_PROFILE(SMBlockingX);
6552
6553         if (req->wct < 8) {
6554                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6555                 END_PROFILE(SMBlockingX);
6556                 return;
6557         }
6558         
6559         fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
6560         locktype = CVAL(req->inbuf,smb_vwv3);
6561         oplocklevel = CVAL(req->inbuf,smb_vwv3+1);
6562         num_ulocks = SVAL(req->inbuf,smb_vwv6);
6563         num_locks = SVAL(req->inbuf,smb_vwv7);
6564         lock_timeout = IVAL(req->inbuf,smb_vwv4);
6565         large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
6566
6567         if (!check_fsp(conn, req, fsp, &current_user)) {
6568                 END_PROFILE(SMBlockingX);
6569                 return;
6570         }
6571         
6572         data = smb_buf(req->inbuf);
6573
6574         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
6575                 /* we don't support these - and CANCEL_LOCK makes w2k
6576                    and XP reboot so I don't really want to be
6577                    compatible! (tridge) */
6578                 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
6579                 END_PROFILE(SMBlockingX);
6580                 return;
6581         }
6582         
6583         /* Check if this is an oplock break on a file
6584            we have granted an oplock on.
6585         */
6586         if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
6587                 /* Client can insist on breaking to none. */
6588                 bool break_to_none = (oplocklevel == 0);
6589                 bool result;
6590
6591                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6592                          "for fnum = %d\n", (unsigned int)oplocklevel,
6593                          fsp->fnum ));
6594
6595                 /*
6596                  * Make sure we have granted an exclusive or batch oplock on
6597                  * this file.
6598                  */
6599                 
6600                 if (fsp->oplock_type == 0) {
6601
6602                         /* The Samba4 nbench simulator doesn't understand
6603                            the difference between break to level2 and break
6604                            to none from level2 - it sends oplock break
6605                            replies in both cases. Don't keep logging an error
6606                            message here - just ignore it. JRA. */
6607
6608                         DEBUG(5,("reply_lockingX: Error : oplock break from "
6609                                  "client for fnum = %d (oplock=%d) and no "
6610                                  "oplock granted on this file (%s).\n",
6611                                  fsp->fnum, fsp->oplock_type, fsp->fsp_name));
6612
6613                         /* if this is a pure oplock break request then don't
6614                          * send a reply */
6615                         if (num_locks == 0 && num_ulocks == 0) {
6616                                 END_PROFILE(SMBlockingX);
6617                                 return;
6618                         } else {
6619                                 END_PROFILE(SMBlockingX);
6620                                 reply_doserror(req, ERRDOS, ERRlock);
6621                                 return;
6622                         }
6623                 }
6624
6625                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
6626                     (break_to_none)) {
6627                         result = remove_oplock(fsp);
6628                 } else {
6629                         result = downgrade_oplock(fsp);
6630                 }
6631                 
6632                 if (!result) {
6633                         DEBUG(0, ("reply_lockingX: error in removing "
6634                                   "oplock on file %s\n", fsp->fsp_name));
6635                         /* Hmmm. Is this panic justified? */
6636                         smb_panic("internal tdb error");
6637                 }
6638
6639                 reply_to_oplock_break_requests(fsp);
6640
6641                 /* if this is a pure oplock break request then don't send a
6642                  * reply */
6643                 if (num_locks == 0 && num_ulocks == 0) {
6644                         /* Sanity check - ensure a pure oplock break is not a
6645                            chained request. */
6646                         if(CVAL(req->inbuf,smb_vwv0) != 0xff)
6647                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
6648                                          "break is a chained %d request !\n",
6649                                          (unsigned int)CVAL(req->inbuf,
6650                                                             smb_vwv0) ));
6651                         END_PROFILE(SMBlockingX);
6652                         return;
6653                 }
6654         }
6655
6656         /*
6657          * We do this check *after* we have checked this is not a oplock break
6658          * response message. JRA.
6659          */
6660         
6661         release_level_2_oplocks_on_change(fsp);
6662
6663         if (smb_buflen(req->inbuf) <
6664             (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
6665                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6666                 END_PROFILE(SMBlockingX);
6667                 return;
6668         }
6669         
6670         /* Data now points at the beginning of the list
6671            of smb_unlkrng structs */
6672         for(i = 0; i < (int)num_ulocks; i++) {
6673                 lock_pid = get_lock_pid( data, i, large_file_format);
6674                 count = get_lock_count( data, i, large_file_format);
6675                 offset = get_lock_offset( data, i, large_file_format, &err);
6676                 
6677                 /*
6678                  * There is no error code marked "stupid client bug".... :-).
6679                  */
6680                 if(err) {
6681                         END_PROFILE(SMBlockingX);
6682                         reply_doserror(req, ERRDOS, ERRnoaccess);
6683                         return;
6684                 }
6685
6686                 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
6687                           "pid %u, file %s\n", (double)offset, (double)count,
6688                           (unsigned int)lock_pid, fsp->fsp_name ));
6689                 
6690                 status = do_unlock(smbd_messaging_context(),
6691                                 fsp,
6692                                 lock_pid,
6693                                 count,
6694                                 offset,
6695                                 WINDOWS_LOCK);
6696
6697                 if (NT_STATUS_V(status)) {
6698                         END_PROFILE(SMBlockingX);
6699                         reply_nterror(req, status);
6700                         return;
6701                 }
6702         }
6703
6704         /* Setup the timeout in seconds. */
6705
6706         if (!lp_blocking_locks(SNUM(conn))) {
6707                 lock_timeout = 0;
6708         }
6709         
6710         /* Now do any requested locks */
6711         data += ((large_file_format ? 20 : 10)*num_ulocks);
6712         
6713         /* Data now points at the beginning of the list
6714            of smb_lkrng structs */
6715         
6716         for(i = 0; i < (int)num_locks; i++) {
6717                 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
6718                                 READ_LOCK:WRITE_LOCK);
6719                 lock_pid = get_lock_pid( data, i, large_file_format);
6720                 count = get_lock_count( data, i, large_file_format);
6721                 offset = get_lock_offset( data, i, large_file_format, &err);
6722                 
6723                 /*
6724                  * There is no error code marked "stupid client bug".... :-).
6725                  */
6726                 if(err) {
6727                         END_PROFILE(SMBlockingX);
6728                         reply_doserror(req, ERRDOS, ERRnoaccess);
6729                         return;
6730                 }
6731                 
6732                 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
6733                           "%u, file %s timeout = %d\n", (double)offset,
6734                           (double)count, (unsigned int)lock_pid,
6735                           fsp->fsp_name, (int)lock_timeout ));
6736                 
6737                 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
6738                         if (lp_blocking_locks(SNUM(conn))) {
6739
6740                                 /* Schedule a message to ourselves to
6741                                    remove the blocking lock record and
6742                                    return the right error. */
6743
6744                                 if (!blocking_lock_cancel(fsp,
6745                                                 lock_pid,
6746                                                 offset,
6747                                                 count,
6748                                                 WINDOWS_LOCK,
6749                                                 locktype,
6750                                                 NT_STATUS_FILE_LOCK_CONFLICT)) {
6751                                         END_PROFILE(SMBlockingX);
6752                                         reply_nterror(
6753                                                 req,
6754                                                 NT_STATUS_DOS(
6755                                                         ERRDOS,
6756                                                         ERRcancelviolation));
6757                                         return;
6758                                 }
6759                         }
6760                         /* Remove a matching pending lock. */
6761                         status = do_lock_cancel(fsp,
6762                                                 lock_pid,
6763                                                 count,
6764                                                 offset,
6765                                                 WINDOWS_LOCK);
6766                 } else {
6767                         bool blocking_lock = lock_timeout ? True : False;
6768                         bool defer_lock = False;
6769                         struct byte_range_lock *br_lck;
6770                         uint32 block_smbpid;
6771
6772                         br_lck = do_lock(smbd_messaging_context(),
6773                                         fsp,
6774                                         lock_pid,
6775                                         count,
6776                                         offset, 
6777                                         lock_type,
6778                                         WINDOWS_LOCK,
6779                                         blocking_lock,
6780                                         &status,
6781                                         &block_smbpid);
6782
6783                         if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6784                                 /* Windows internal resolution for blocking locks seems
6785                                    to be about 200ms... Don't wait for less than that. JRA. */
6786                                 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
6787                                         lock_timeout = lp_lock_spin_time();
6788                                 }
6789                                 defer_lock = True;
6790                         }
6791
6792                         /* This heuristic seems to match W2K3 very well. If a
6793                            lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
6794                            it pretends we asked for a timeout of between 150 - 300 milliseconds as
6795                            far as I can tell. Replacement for do_lock_spin(). JRA. */
6796
6797                         if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
6798                                         NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
6799                                 defer_lock = True;
6800                                 lock_timeout = lp_lock_spin_time();
6801                         }
6802
6803                         if (br_lck && defer_lock) {
6804                                 /*
6805                                  * A blocking lock was requested. Package up
6806                                  * this smb into a queued request and push it
6807                                  * onto the blocking lock queue.
6808                                  */
6809                                 if(push_blocking_lock_request(br_lck,
6810                                                         req,
6811                                                         fsp,
6812                                                         lock_timeout,
6813                                                         i,
6814                                                         lock_pid,
6815                                                         lock_type,
6816                                                         WINDOWS_LOCK,
6817                                                         offset,
6818                                                         count,
6819                                                         block_smbpid)) {
6820                                         TALLOC_FREE(br_lck);
6821                                         END_PROFILE(SMBlockingX);
6822                                         return;
6823                                 }
6824                         }
6825
6826                         TALLOC_FREE(br_lck);
6827                 }
6828
6829                 if (NT_STATUS_V(status)) {
6830                         END_PROFILE(SMBlockingX);
6831                         reply_nterror(req, status);
6832                         return;
6833                 }
6834         }
6835         
6836         /* If any of the above locks failed, then we must unlock
6837            all of the previous locks (X/Open spec). */
6838
6839         if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
6840                         (i != num_locks) &&
6841                         (num_locks != 0)) {
6842                 /*
6843                  * Ensure we don't do a remove on the lock that just failed,
6844                  * as under POSIX rules, if we have a lock already there, we
6845                  * will delete it (and we shouldn't) .....
6846                  */
6847                 for(i--; i >= 0; i--) {
6848                         lock_pid = get_lock_pid( data, i, large_file_format);
6849                         count = get_lock_count( data, i, large_file_format);
6850                         offset = get_lock_offset( data, i, large_file_format,
6851                                                   &err);
6852                         
6853                         /*
6854                          * There is no error code marked "stupid client
6855                          * bug".... :-).
6856                          */
6857                         if(err) {
6858                                 END_PROFILE(SMBlockingX);
6859                                 reply_doserror(req, ERRDOS, ERRnoaccess);
6860                                 return;
6861                         }
6862                         
6863                         do_unlock(smbd_messaging_context(),
6864                                 fsp,
6865                                 lock_pid,
6866                                 count,
6867                                 offset,
6868                                 WINDOWS_LOCK);
6869                 }
6870                 END_PROFILE(SMBlockingX);
6871                 reply_nterror(req, status);
6872                 return;
6873         }
6874
6875         reply_outbuf(req, 2, 0);
6876         
6877         DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
6878                   fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
6879         
6880         END_PROFILE(SMBlockingX);
6881         chain_reply(req);
6882 }
6883
6884 #undef DBGC_CLASS
6885 #define DBGC_CLASS DBGC_ALL
6886
6887 /****************************************************************************
6888  Reply to a SMBreadbmpx (read block multiplex) request.
6889  Always reply with an error, if someone has a platform really needs this,
6890  please contact vl@samba.org
6891 ****************************************************************************/
6892
6893 void reply_readbmpx(connection_struct *conn, struct smb_request *req)
6894 {
6895         START_PROFILE(SMBreadBmpx);
6896         reply_doserror(req, ERRSRV, ERRuseSTD);
6897         END_PROFILE(SMBreadBmpx);
6898         return;
6899 }
6900
6901 /****************************************************************************
6902  Reply to a SMBreadbs (read block multiplex secondary) request.
6903  Always reply with an error, if someone has a platform really needs this,
6904  please contact vl@samba.org
6905 ****************************************************************************/
6906
6907 void reply_readbs(connection_struct *conn, struct smb_request *req)
6908 {
6909         START_PROFILE(SMBreadBs);
6910         reply_doserror(req, ERRSRV, ERRuseSTD);
6911         END_PROFILE(SMBreadBs);
6912         return;
6913 }
6914
6915 /****************************************************************************
6916  Reply to a SMBsetattrE.
6917 ****************************************************************************/
6918
6919 void reply_setattrE(connection_struct *conn, struct smb_request *req)
6920 {
6921         struct timespec ts[2];
6922         files_struct *fsp;
6923
6924         START_PROFILE(SMBsetattrE);
6925
6926         if (req->wct < 7) {
6927                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6928                 END_PROFILE(SMBsetattrE);
6929                 return;
6930         }
6931
6932         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
6933
6934         if(!fsp || (fsp->conn != conn)) {
6935                 reply_doserror(req, ERRDOS, ERRbadfid);
6936                 END_PROFILE(SMBsetattrE);
6937                 return;
6938         }
6939
6940
6941         /*
6942          * Convert the DOS times into unix times. Ignore create
6943          * time as UNIX can't set this.
6944          */
6945
6946         ts[0] = convert_time_t_to_timespec(
6947                 srv_make_unix_date2(req->inbuf+smb_vwv3)); /* atime. */
6948         ts[1] = convert_time_t_to_timespec(
6949                 srv_make_unix_date2(req->inbuf+smb_vwv5)); /* mtime. */
6950   
6951         reply_outbuf(req, 0, 0);
6952
6953         /* 
6954          * Patch from Ray Frush <frush@engr.colostate.edu>
6955          * Sometimes times are sent as zero - ignore them.
6956          */
6957
6958         if (null_timespec(ts[0]) && null_timespec(ts[1])) {
6959                 /* Ignore request */
6960                 if( DEBUGLVL( 3 ) ) {
6961                         dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
6962                         dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
6963                 }
6964                 END_PROFILE(SMBsetattrE);
6965                 return;
6966         } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
6967                 /* set modify time = to access time if modify time was unset */
6968                 ts[1] = ts[0];
6969         }
6970
6971         /* Set the date on this file */
6972         /* Should we set pending modtime here ? JRA */
6973         if(file_ntimes(conn, fsp->fsp_name, ts)) {
6974                 reply_doserror(req, ERRDOS, ERRnoaccess);
6975                 END_PROFILE(SMBsetattrE);
6976                 return;
6977         }
6978   
6979         DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
6980                 fsp->fnum,
6981                 (unsigned int)ts[0].tv_sec,
6982                 (unsigned int)ts[1].tv_sec));
6983
6984         END_PROFILE(SMBsetattrE);
6985         return;
6986 }
6987
6988
6989 /* Back from the dead for OS/2..... JRA. */
6990
6991 /****************************************************************************
6992  Reply to a SMBwritebmpx (write block multiplex primary) request.
6993  Always reply with an error, if someone has a platform really needs this,
6994  please contact vl@samba.org
6995 ****************************************************************************/
6996
6997 void reply_writebmpx(connection_struct *conn, struct smb_request *req)
6998 {
6999         START_PROFILE(SMBwriteBmpx);
7000         reply_doserror(req, ERRSRV, ERRuseSTD);
7001         END_PROFILE(SMBwriteBmpx);
7002         return;
7003 }
7004
7005 /****************************************************************************
7006  Reply to a SMBwritebs (write block multiplex secondary) request.
7007  Always reply with an error, if someone has a platform really needs this,
7008  please contact vl@samba.org
7009 ****************************************************************************/
7010
7011 void reply_writebs(connection_struct *conn, struct smb_request *req)
7012 {
7013         START_PROFILE(SMBwriteBs);
7014         reply_doserror(req, ERRSRV, ERRuseSTD);
7015         END_PROFILE(SMBwriteBs);
7016         return;
7017 }
7018
7019 /****************************************************************************
7020  Reply to a SMBgetattrE.
7021 ****************************************************************************/
7022
7023 void reply_getattrE(connection_struct *conn, struct smb_request *req)
7024 {
7025         SMB_STRUCT_STAT sbuf;
7026         int mode;
7027         files_struct *fsp;
7028
7029         START_PROFILE(SMBgetattrE);
7030
7031         if (req->wct < 1) {
7032                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7033                 END_PROFILE(SMBgetattrE);
7034                 return;
7035         }
7036
7037         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
7038
7039         if(!fsp || (fsp->conn != conn)) {
7040                 reply_doserror(req, ERRDOS, ERRbadfid);
7041                 END_PROFILE(SMBgetattrE);
7042                 return;
7043         }
7044
7045         /* Do an fstat on this file */
7046         if(fsp_stat(fsp, &sbuf)) {
7047                 reply_unixerror(req, ERRDOS, ERRnoaccess);
7048                 END_PROFILE(SMBgetattrE);
7049                 return;
7050         }
7051   
7052         mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7053   
7054         /*
7055          * Convert the times into dos times. Set create
7056          * date to be last modify date as UNIX doesn't save
7057          * this.
7058          */
7059
7060         reply_outbuf(req, 11, 0);
7061
7062         srv_put_dos_date2((char *)req->outbuf, smb_vwv0,
7063                           get_create_time(&sbuf,
7064                                           lp_fake_dir_create_times(SNUM(conn))));
7065         srv_put_dos_date2((char *)req->outbuf, smb_vwv2, sbuf.st_atime);
7066         /* Should we check pending modtime here ? JRA */
7067         srv_put_dos_date2((char *)req->outbuf, smb_vwv4, sbuf.st_mtime);
7068
7069         if (mode & aDIR) {
7070                 SIVAL(req->outbuf, smb_vwv6, 0);
7071                 SIVAL(req->outbuf, smb_vwv8, 0);
7072         } else {
7073                 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
7074                 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_size);
7075                 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7076         }
7077         SSVAL(req->outbuf,smb_vwv10, mode);
7078   
7079         DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7080   
7081         END_PROFILE(SMBgetattrE);
7082         return;
7083 }