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