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