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