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