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