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