r21093: Remove the hash and dnotify backends. Disabling FAM for this checkin, I'm
[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,
1017                                         directory,
1018                                         True,
1019                                         expect_close,
1020                                         SVAL(inbuf,smb_pid),
1021                                         mask,
1022                                         mask_contains_wcard,
1023                                         dirtype,
1024                                         &conn->dirptr);
1025                 if (!NT_STATUS_IS_OK(nt_status)) {
1026                         return ERROR_NT(nt_status);
1027                 }
1028                 dptr_num = dptr_dnum(conn->dirptr);
1029         } else {
1030                 dirtype = dptr_attr(dptr_num);
1031         }
1032
1033         DEBUG(4,("dptr_num is %d\n",dptr_num));
1034
1035         if ((dirtype&0x1F) == aVOLID) {   
1036                 memcpy(p,status,21);
1037                 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
1038                                 0,aVOLID,0,!allow_long_path_components);
1039                 dptr_fill(p+12,dptr_num);
1040                 if (dptr_zero(p+12) && (status_len==0)) {
1041                         numentries = 1;
1042                 } else {
1043                         numentries = 0;
1044                 }
1045                 p += DIR_STRUCT_SIZE;
1046         } else {
1047                 unsigned int i;
1048                 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
1049
1050                 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1051                         conn->dirpath,lp_dontdescend(SNUM(conn))));
1052                 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1053                         check_descend = True;
1054                 }
1055
1056                 for (i=numentries;(i<maxentries) && !finished;i++) {
1057                         finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1058                         if (!finished) {
1059                                 memcpy(p,status,21);
1060                                 make_dir_struct(p,mask,fname,size, mode,date,
1061                                                 !allow_long_path_components);
1062                                 if (!dptr_fill(p+12,dptr_num)) {
1063                                         break;
1064                                 }
1065                                 numentries++;
1066                                 p += DIR_STRUCT_SIZE;
1067                         }
1068                 }
1069         }
1070
1071   SearchEmpty:
1072
1073         /* If we were called as SMBffirst with smb_search_id == NULL
1074                 and no entries were found then return error and close dirptr 
1075                 (X/Open spec) */
1076
1077         if (numentries == 0) {
1078                 dptr_close(&dptr_num);
1079         } else if(expect_close && status_len == 0) {
1080                 /* Close the dptr - we know it's gone */
1081                 dptr_close(&dptr_num);
1082         }
1083
1084         /* If we were called as SMBfunique, then we can close the dirptr now ! */
1085         if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1086                 dptr_close(&dptr_num);
1087         }
1088
1089         if ((numentries == 0) && !mask_contains_wcard) {
1090                 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1091         }
1092
1093         SSVAL(outbuf,smb_vwv0,numentries);
1094         SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1095         SCVAL(smb_buf(outbuf),0,5);
1096         SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1097
1098         /* The replies here are never long name. */
1099         SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1100         if (!allow_long_path_components) {
1101                 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
1102         }
1103
1104         /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1105         SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1106           
1107         outsize += DIR_STRUCT_SIZE*numentries;
1108         smb_setlen(outbuf,outsize - 4);
1109   
1110         if ((! *directory) && dptr_path(dptr_num))
1111                 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1112
1113         DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1114                 smb_fn_name(CVAL(inbuf,smb_com)), 
1115                 mask, directory, dirtype, numentries, maxentries ) );
1116
1117         END_PROFILE(SMBsearch);
1118         return(outsize);
1119 }
1120
1121 /****************************************************************************
1122  Reply to a fclose (stop directory search).
1123 ****************************************************************************/
1124
1125 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1126 {
1127         int outsize = 0;
1128         int status_len;
1129         pstring path;
1130         char status[21];
1131         int dptr_num= -2;
1132         char *p;
1133         NTSTATUS err;
1134         BOOL path_contains_wcard = False;
1135
1136         START_PROFILE(SMBfclose);
1137
1138         if (lp_posix_pathnames()) {
1139                 END_PROFILE(SMBfclose);
1140                 return reply_unknown(inbuf, outbuf);
1141         }
1142
1143         outsize = set_message(outbuf,1,0,True);
1144         p = smb_buf(inbuf) + 1;
1145         p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, &path_contains_wcard);
1146         if (!NT_STATUS_IS_OK(err)) {
1147                 END_PROFILE(SMBfclose);
1148                 return ERROR_NT(err);
1149         }
1150         p++;
1151         status_len = SVAL(p,0);
1152         p += 2;
1153
1154         if (status_len == 0) {
1155                 END_PROFILE(SMBfclose);
1156                 return ERROR_DOS(ERRSRV,ERRsrverror);
1157         }
1158
1159         memcpy(status,p,21);
1160
1161         if(dptr_fetch(status+12,&dptr_num)) {
1162                 /*  Close the dptr - we know it's gone */
1163                 dptr_close(&dptr_num);
1164         }
1165
1166         SSVAL(outbuf,smb_vwv0,0);
1167
1168         DEBUG(3,("search close\n"));
1169
1170         END_PROFILE(SMBfclose);
1171         return(outsize);
1172 }
1173
1174 /****************************************************************************
1175  Reply to an open.
1176 ****************************************************************************/
1177
1178 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1179 {
1180         pstring fname;
1181         int outsize = 0;
1182         uint32 fattr=0;
1183         SMB_OFF_T size = 0;
1184         time_t mtime=0;
1185         int info;
1186         SMB_STRUCT_STAT sbuf;
1187         files_struct *fsp;
1188         int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1189         int deny_mode;
1190         uint32 dos_attr = SVAL(inbuf,smb_vwv1);
1191         uint32 access_mask;
1192         uint32 share_mode;
1193         uint32 create_disposition;
1194         uint32 create_options = 0;
1195         NTSTATUS status;
1196         START_PROFILE(SMBopen);
1197  
1198         deny_mode = SVAL(inbuf,smb_vwv0);
1199
1200         srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1201         if (!NT_STATUS_IS_OK(status)) {
1202                 END_PROFILE(SMBopen);
1203                 return ERROR_NT(status);
1204         }
1205
1206         RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1207
1208         status = unix_convert(conn, fname, False, NULL, &sbuf);
1209         if (!NT_STATUS_IS_OK(status)) {
1210                 END_PROFILE(SMBopen);
1211                 return ERROR_NT(status);
1212         }
1213     
1214         if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
1215                         &access_mask, &share_mode, &create_disposition, &create_options)) {
1216                 END_PROFILE(SMBopen);
1217                 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1218         }
1219
1220         status = open_file_ntcreate(conn,fname,&sbuf,
1221                         access_mask,
1222                         share_mode,
1223                         create_disposition,
1224                         create_options,
1225                         dos_attr,
1226                         oplock_request,
1227                         &info, &fsp);
1228
1229         if (!NT_STATUS_IS_OK(status)) {
1230                 END_PROFILE(SMBopen);
1231                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1232                         /* We have re-scheduled this call. */
1233                         return -1;
1234                 }
1235                 return ERROR_NT(status);
1236         }
1237
1238         size = sbuf.st_size;
1239         fattr = dos_mode(conn,fname,&sbuf);
1240         mtime = sbuf.st_mtime;
1241
1242         if (fattr & aDIR) {
1243                 DEBUG(3,("attempt to open a directory %s\n",fname));
1244                 close_file(fsp,ERROR_CLOSE);
1245                 END_PROFILE(SMBopen);
1246                 return ERROR_DOS(ERRDOS,ERRnoaccess);
1247         }
1248   
1249         outsize = set_message(outbuf,7,0,True);
1250         SSVAL(outbuf,smb_vwv0,fsp->fnum);
1251         SSVAL(outbuf,smb_vwv1,fattr);
1252         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1253                 srv_put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1254         } else {
1255                 srv_put_dos_date3(outbuf,smb_vwv2,mtime);
1256         }
1257         SIVAL(outbuf,smb_vwv4,(uint32)size);
1258         SSVAL(outbuf,smb_vwv6,deny_mode);
1259
1260         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1261                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1262         }
1263     
1264         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1265                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1266         }
1267         END_PROFILE(SMBopen);
1268         return(outsize);
1269 }
1270
1271 /****************************************************************************
1272  Reply to an open and X.
1273 ****************************************************************************/
1274
1275 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1276 {
1277         pstring fname;
1278         uint16 open_flags = SVAL(inbuf,smb_vwv2);
1279         int deny_mode = SVAL(inbuf,smb_vwv3);
1280         uint32 smb_attr = SVAL(inbuf,smb_vwv5);
1281         /* Breakout the oplock request bits so we can set the
1282                 reply bits separately. */
1283         int ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1284         int core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1285         int oplock_request = ex_oplock_request | core_oplock_request;
1286 #if 0
1287         int smb_sattr = SVAL(inbuf,smb_vwv4); 
1288         uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1289 #endif
1290         int smb_ofun = SVAL(inbuf,smb_vwv8);
1291         uint32 fattr=0;
1292         int mtime=0;
1293         SMB_STRUCT_STAT sbuf;
1294         int smb_action = 0;
1295         files_struct *fsp;
1296         NTSTATUS status;
1297         SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
1298         ssize_t retval = -1;
1299         uint32 access_mask;
1300         uint32 share_mode;
1301         uint32 create_disposition;
1302         uint32 create_options = 0;
1303
1304         START_PROFILE(SMBopenX);
1305
1306         /* If it's an IPC, pass off the pipe handler. */
1307         if (IS_IPC(conn)) {
1308                 if (lp_nt_pipe_support()) {
1309                         END_PROFILE(SMBopenX);
1310                         return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1311                 } else {
1312                         END_PROFILE(SMBopenX);
1313                         return ERROR_DOS(ERRSRV,ERRaccess);
1314                 }
1315         }
1316
1317         /* XXXX we need to handle passed times, sattr and flags */
1318         srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
1319         if (!NT_STATUS_IS_OK(status)) {
1320                 END_PROFILE(SMBopenX);
1321                 return ERROR_NT(status);
1322         }
1323
1324         RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1325
1326         status = unix_convert(conn, fname, False, NULL, &sbuf);
1327         if (!NT_STATUS_IS_OK(status)) {
1328                 END_PROFILE(SMBopenX);
1329                 return ERROR_NT(status);
1330         }
1331
1332         if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
1333                                 &access_mask,
1334                                 &share_mode,
1335                                 &create_disposition,
1336                                 &create_options)) {
1337                 END_PROFILE(SMBopenX);
1338                 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1339         }
1340
1341         status = open_file_ntcreate(conn,fname,&sbuf,
1342                         access_mask,
1343                         share_mode,
1344                         create_disposition,
1345                         create_options,
1346                         smb_attr,
1347                         oplock_request,
1348                         &smb_action, &fsp);
1349       
1350         if (!NT_STATUS_IS_OK(status)) {
1351                 END_PROFILE(SMBopenX);
1352                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1353                         /* We have re-scheduled this call. */
1354                         return -1;
1355                 }
1356                 return ERROR_NT(status);
1357         }
1358
1359         /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1360            if the file is truncated or created. */
1361         if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1362                 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1363                 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1364                         close_file(fsp,ERROR_CLOSE);
1365                         END_PROFILE(SMBopenX);
1366                         return ERROR_NT(NT_STATUS_DISK_FULL);
1367                 }
1368                 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1369                 if (retval < 0) {
1370                         close_file(fsp,ERROR_CLOSE);
1371                         END_PROFILE(SMBopenX);
1372                         return ERROR_NT(NT_STATUS_DISK_FULL);
1373                 }
1374                 sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
1375         }
1376
1377         fattr = dos_mode(conn,fname,&sbuf);
1378         mtime = sbuf.st_mtime;
1379         if (fattr & aDIR) {
1380                 close_file(fsp,ERROR_CLOSE);
1381                 END_PROFILE(SMBopenX);
1382                 return ERROR_DOS(ERRDOS,ERRnoaccess);
1383         }
1384
1385         /* If the caller set the extended oplock request bit
1386                 and we granted one (by whatever means) - set the
1387                 correct bit for extended oplock reply.
1388         */
1389
1390         if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1391                 smb_action |= EXTENDED_OPLOCK_GRANTED;
1392         }
1393
1394         if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1395                 smb_action |= EXTENDED_OPLOCK_GRANTED;
1396         }
1397
1398         /* If the caller set the core oplock request bit
1399                 and we granted one (by whatever means) - set the
1400                 correct bit for core oplock reply.
1401         */
1402
1403         if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1404                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1405         }
1406
1407         if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1408                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1409         }
1410
1411         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1412                 set_message(outbuf,19,0,True);
1413         } else {
1414                 set_message(outbuf,15,0,True);
1415         }
1416         SSVAL(outbuf,smb_vwv2,fsp->fnum);
1417         SSVAL(outbuf,smb_vwv3,fattr);
1418         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1419                 srv_put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1420         } else {
1421                 srv_put_dos_date3(outbuf,smb_vwv4,mtime);
1422         }
1423         SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
1424         SSVAL(outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1425         SSVAL(outbuf,smb_vwv11,smb_action);
1426
1427         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1428                 SIVAL(outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1429         }
1430
1431         END_PROFILE(SMBopenX);
1432         return chain_reply(inbuf,outbuf,length,bufsize);
1433 }
1434
1435 /****************************************************************************
1436  Reply to a SMBulogoffX.
1437  conn POINTER CAN BE NULL HERE !
1438 ****************************************************************************/
1439
1440 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1441 {
1442         uint16 vuid = SVAL(inbuf,smb_uid);
1443         user_struct *vuser = get_valid_user_struct(vuid);
1444         START_PROFILE(SMBulogoffX);
1445
1446         if(vuser == 0)
1447                 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1448
1449         /* in user level security we are supposed to close any files
1450                 open by this user */
1451         if ((vuser != 0) && (lp_security() != SEC_SHARE))
1452                 file_close_user(vuid);
1453
1454         invalidate_vuid(vuid);
1455
1456         set_message(outbuf,2,0,True);
1457
1458         DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1459
1460         END_PROFILE(SMBulogoffX);
1461         return chain_reply(inbuf,outbuf,length,bufsize);
1462 }
1463
1464 /****************************************************************************
1465  Reply to a mknew or a create.
1466 ****************************************************************************/
1467
1468 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1469 {
1470         pstring fname;
1471         int com;
1472         int outsize = 0;
1473         uint32 fattr = SVAL(inbuf,smb_vwv0);
1474         struct utimbuf times;
1475         files_struct *fsp;
1476         int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1477         SMB_STRUCT_STAT sbuf;
1478         NTSTATUS status;
1479         uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1480         uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1481         uint32 create_disposition;
1482         uint32 create_options = 0;
1483
1484         START_PROFILE(SMBcreate);
1485  
1486         com = SVAL(inbuf,smb_com);
1487
1488         times.modtime = srv_make_unix_date3(inbuf + smb_vwv1);
1489
1490         srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
1491         if (!NT_STATUS_IS_OK(status)) {
1492                 END_PROFILE(SMBcreate);
1493                 return ERROR_NT(status);
1494         }
1495
1496         RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1497
1498         status = unix_convert(conn, fname, False, NULL, &sbuf);
1499         if (!NT_STATUS_IS_OK(status)) {
1500                 END_PROFILE(SMBcreate);
1501                 return ERROR_NT(status);
1502         }
1503
1504         if (fattr & aVOLID) {
1505                 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1506         }
1507
1508         if(com == SMBmknew) {
1509                 /* We should fail if file exists. */
1510                 create_disposition = FILE_CREATE;
1511         } else {
1512                 /* Create if file doesn't exist, truncate if it does. */
1513                 create_disposition = FILE_OVERWRITE_IF;
1514         }
1515
1516         /* Open file using ntcreate. */
1517         status = open_file_ntcreate(conn,fname,&sbuf,
1518                                 access_mask,
1519                                 share_mode,
1520                                 create_disposition,
1521                                 create_options,
1522                                 fattr,
1523                                 oplock_request,
1524                                 NULL, &fsp);
1525   
1526         if (!NT_STATUS_IS_OK(status)) {
1527                 END_PROFILE(SMBcreate);
1528                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1529                         /* We have re-scheduled this call. */
1530                         return -1;
1531                 }
1532                 return ERROR_NT(status);
1533         }
1534  
1535         times.actime = sbuf.st_atime;
1536         file_utime(conn, fname, &times);
1537
1538         outsize = set_message(outbuf,1,0,True);
1539         SSVAL(outbuf,smb_vwv0,fsp->fnum);
1540
1541         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1542                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1543         }
1544  
1545         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1546                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1547         }
1548  
1549         DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
1550         DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) );
1551
1552         END_PROFILE(SMBcreate);
1553         return(outsize);
1554 }
1555
1556 /****************************************************************************
1557  Reply to a create temporary file.
1558 ****************************************************************************/
1559
1560 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1561 {
1562         pstring fname;
1563         int outsize = 0;
1564         uint32 fattr = SVAL(inbuf,smb_vwv0);
1565         files_struct *fsp;
1566         int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1567         int tmpfd;
1568         SMB_STRUCT_STAT sbuf;
1569         char *p, *s;
1570         NTSTATUS status;
1571         unsigned int namelen;
1572
1573         START_PROFILE(SMBctemp);
1574
1575         srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1576         if (!NT_STATUS_IS_OK(status)) {
1577                 END_PROFILE(SMBctemp);
1578                 return ERROR_NT(status);
1579         }
1580         if (*fname) {
1581                 pstrcat(fname,"/TMXXXXXX");
1582         } else {
1583                 pstrcat(fname,"TMXXXXXX");
1584         }
1585
1586         RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1587
1588         status = unix_convert(conn, fname, False, NULL, &sbuf);
1589         if (!NT_STATUS_IS_OK(status)) {
1590                 END_PROFILE(SMBctemp);
1591                 return ERROR_NT(status);
1592         }
1593   
1594         tmpfd = smb_mkstemp(fname);
1595         if (tmpfd == -1) {
1596                 END_PROFILE(SMBctemp);
1597                 return(UNIXERROR(ERRDOS,ERRnoaccess));
1598         }
1599
1600         SMB_VFS_STAT(conn,fname,&sbuf);
1601
1602         /* We should fail if file does not exist. */
1603         status = open_file_ntcreate(conn,fname,&sbuf,
1604                                 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
1605                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
1606                                 FILE_OPEN,
1607                                 0,
1608                                 fattr,
1609                                 oplock_request,
1610                                 NULL, &fsp);
1611
1612         /* close fd from smb_mkstemp() */
1613         close(tmpfd);
1614
1615         if (!NT_STATUS_IS_OK(status)) {
1616                 END_PROFILE(SMBctemp);
1617                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1618                         /* We have re-scheduled this call. */
1619                         return -1;
1620                 }
1621                 return ERROR_NT(status);
1622         }
1623
1624         outsize = set_message(outbuf,1,0,True);
1625         SSVAL(outbuf,smb_vwv0,fsp->fnum);
1626
1627         /* the returned filename is relative to the directory */
1628         s = strrchr_m(fname, '/');
1629         if (!s) {
1630                 s = fname;
1631         } else {
1632                 s++;
1633         }
1634
1635         p = smb_buf(outbuf);
1636 #if 0
1637         /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1638            thing in the byte section. JRA */
1639         SSVALS(p, 0, -1); /* what is this? not in spec */
1640 #endif
1641         namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1642         p += namelen;
1643         outsize = set_message_end(outbuf, p);
1644
1645         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1646                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1647         }
1648   
1649         if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1650                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1651         }
1652
1653         DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
1654         DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
1655                         (unsigned int)sbuf.st_mode ) );
1656
1657         END_PROFILE(SMBctemp);
1658         return(outsize);
1659 }
1660
1661 /*******************************************************************
1662  Check if a user is allowed to rename a file.
1663 ********************************************************************/
1664
1665 static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
1666 {
1667         files_struct *fsp;
1668         uint32 fmode;
1669         NTSTATUS status;
1670
1671         if (!CAN_WRITE(conn)) {
1672                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1673         }
1674
1675         fmode = dos_mode(conn,fname,pst);
1676         if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1677                 return NT_STATUS_NO_SUCH_FILE;
1678         }
1679
1680         if (S_ISDIR(pst->st_mode)) {
1681                 return NT_STATUS_OK;
1682         }
1683
1684         status = open_file_ntcreate(conn, fname, pst,
1685                                 DELETE_ACCESS,
1686                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
1687                                 FILE_OPEN,
1688                                 0,
1689                                 FILE_ATTRIBUTE_NORMAL,
1690                                 0,
1691                                 NULL, &fsp);
1692
1693         if (!NT_STATUS_IS_OK(status)) {
1694                 return status;
1695         }
1696         close_file(fsp,NORMAL_CLOSE);
1697         return NT_STATUS_OK;
1698 }
1699
1700 /*******************************************************************
1701  Check if a user is allowed to delete a file.
1702 ********************************************************************/
1703
1704 static NTSTATUS can_delete(connection_struct *conn, char *fname,
1705                            uint32 dirtype, BOOL can_defer)
1706 {
1707         SMB_STRUCT_STAT sbuf;
1708         uint32 fattr;
1709         files_struct *fsp;
1710         uint32 dirtype_orig = dirtype;
1711         NTSTATUS status;
1712
1713         DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype ));
1714
1715         if (!CAN_WRITE(conn)) {
1716                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1717         }
1718
1719         if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1720                 return map_nt_error_from_unix(errno);
1721         }
1722
1723         fattr = dos_mode(conn,fname,&sbuf);
1724
1725         if (dirtype & FILE_ATTRIBUTE_NORMAL) {
1726                 dirtype = aDIR|aARCH|aRONLY;
1727         }
1728
1729         dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
1730         if (!dirtype) {
1731                 return NT_STATUS_NO_SUCH_FILE;
1732         }
1733
1734         if (!dir_check_ftype(conn, fattr, dirtype)) {
1735                 if (fattr & aDIR) {
1736                         return NT_STATUS_FILE_IS_A_DIRECTORY;
1737                 }
1738                 return NT_STATUS_NO_SUCH_FILE;
1739         }
1740
1741         if (dirtype_orig & 0x8000) {
1742                 /* These will never be set for POSIX. */
1743                 return NT_STATUS_NO_SUCH_FILE;
1744         }
1745
1746 #if 0
1747         if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
1748                 return NT_STATUS_FILE_IS_A_DIRECTORY;
1749         }
1750
1751         if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
1752                 return NT_STATUS_NO_SUCH_FILE;
1753         }
1754
1755         if (dirtype & 0xFF00) {
1756                 /* These will never be set for POSIX. */
1757                 return NT_STATUS_NO_SUCH_FILE;
1758         }
1759
1760         dirtype &= 0xFF;
1761         if (!dirtype) {
1762                 return NT_STATUS_NO_SUCH_FILE;
1763         }
1764
1765         /* Can't delete a directory. */
1766         if (fattr & aDIR) {
1767                 return NT_STATUS_FILE_IS_A_DIRECTORY;
1768         }
1769 #endif
1770
1771 #if 0 /* JRATEST */
1772         else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1773                 return NT_STATUS_OBJECT_NAME_INVALID;
1774 #endif /* JRATEST */
1775
1776         /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
1777
1778           On a Windows share, a file with read-only dosmode can be opened with
1779           DELETE_ACCESS. But on a Samba share (delete readonly = no), it
1780           fails with NT_STATUS_CANNOT_DELETE error.
1781
1782           This semantic causes a problem that a user can not
1783           rename a file with read-only dosmode on a Samba share
1784           from a Windows command prompt (i.e. cmd.exe, but can rename
1785           from Windows Explorer).
1786         */
1787
1788         if (!lp_delete_readonly(SNUM(conn))) {
1789                 if (fattr & aRONLY) {
1790                         return NT_STATUS_CANNOT_DELETE;
1791                 }
1792         }
1793
1794         /* On open checks the open itself will check the share mode, so
1795            don't do it here as we'll get it wrong. */
1796
1797         status = open_file_ntcreate(conn, fname, &sbuf,
1798                                     DELETE_ACCESS,
1799                                     FILE_SHARE_NONE,
1800                                     FILE_OPEN,
1801                                     0,
1802                                     FILE_ATTRIBUTE_NORMAL,
1803                                     can_defer ? 0 : INTERNAL_OPEN_ONLY,
1804                                     NULL, &fsp);
1805
1806         if (NT_STATUS_IS_OK(status)) {
1807                 close_file(fsp,NORMAL_CLOSE);
1808         }
1809         return status;
1810 }
1811
1812 /****************************************************************************
1813  The guts of the unlink command, split out so it may be called by the NT SMB
1814  code.
1815 ****************************************************************************/
1816
1817 NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
1818                           char *name, BOOL has_wild, BOOL can_defer)
1819 {
1820         pstring directory;
1821         pstring mask;
1822         char *p;
1823         int count=0;
1824         NTSTATUS status = NT_STATUS_OK;
1825         SMB_STRUCT_STAT sbuf;
1826         
1827         *directory = *mask = 0;
1828         
1829         status = unix_convert(conn, name, has_wild, NULL, &sbuf);
1830         if (!NT_STATUS_IS_OK(status)) {
1831                 return status;
1832         }
1833         
1834         p = strrchr_m(name,'/');
1835         if (!p) {
1836                 pstrcpy(directory,".");
1837                 pstrcpy(mask,name);
1838         } else {
1839                 *p = 0;
1840                 pstrcpy(directory,name);
1841                 pstrcpy(mask,p+1);
1842         }
1843         
1844         /*
1845          * We should only check the mangled cache
1846          * here if unix_convert failed. This means
1847          * that the path in 'mask' doesn't exist
1848          * on the file system and so we need to look
1849          * for a possible mangle. This patch from
1850          * Tine Smukavec <valentin.smukavec@hermes.si>.
1851          */
1852         
1853         if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params))
1854                 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
1855         
1856         if (!has_wild) {
1857                 pstrcat(directory,"/");
1858                 pstrcat(directory,mask);
1859                 if (dirtype == 0) {
1860                         dirtype = FILE_ATTRIBUTE_NORMAL;
1861                 }
1862                 status = can_delete(conn,directory,dirtype,can_defer);
1863                 if (!NT_STATUS_IS_OK(status)) {
1864                         return status;
1865                 }
1866
1867                 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1868                         count++;
1869                         notify_fname(conn, NOTIFY_ACTION_REMOVED,
1870                                      FILE_NOTIFY_CHANGE_FILE_NAME,
1871                                      directory);
1872                 }
1873         } else {
1874                 struct smb_Dir *dir_hnd = NULL;
1875                 long offset = 0;
1876                 const char *dname;
1877                 
1878                 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
1879                         return NT_STATUS_OBJECT_NAME_INVALID;
1880                 }
1881
1882                 if (strequal(mask,"????????.???")) {
1883                         pstrcpy(mask,"*");
1884                 }
1885
1886                 status = check_name(conn, directory);
1887                 if (!NT_STATUS_IS_OK(status)) {
1888                         return status;
1889                 }
1890
1891                 dir_hnd = OpenDir(conn, directory, mask, dirtype);
1892                 if (dir_hnd == NULL) {
1893                         return map_nt_error_from_unix(errno);
1894                 }
1895                 
1896                 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1897                    the pattern matches against the long name, otherwise the short name 
1898                    We don't implement this yet XXXX
1899                 */
1900                 
1901                 status = NT_STATUS_NO_SUCH_FILE;
1902
1903                 while ((dname = ReadDirName(dir_hnd, &offset))) {
1904                         SMB_STRUCT_STAT st;
1905                         pstring fname;
1906                         pstrcpy(fname,dname);
1907
1908                         if (!is_visible_file(conn, directory, dname, &st, True)) {
1909                                 continue;
1910                         }
1911
1912                         /* Quick check for "." and ".." */
1913                         if (fname[0] == '.') {
1914                                 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1915                                         continue;
1916                                 }
1917                         }
1918
1919                         if(!mask_match(fname, mask, conn->case_sensitive)) {
1920                                 continue;
1921                         }
1922                                 
1923                         slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1924                         status = can_delete(conn, fname, dirtype, can_defer);
1925                         if (!NT_STATUS_IS_OK(status)) {
1926                                 continue;
1927                         }
1928                         if (SMB_VFS_UNLINK(conn,fname) == 0) {
1929                                 count++;
1930                                 DEBUG(3,("unlink_internals: succesful unlink "
1931                                          "[%s]\n",fname));
1932                                 notify_fname(conn, NOTIFY_ACTION_REMOVED,
1933                                              FILE_NOTIFY_CHANGE_FILE_NAME,
1934                                              fname);
1935                         }
1936                                 
1937                 }
1938                 CloseDir(dir_hnd);
1939         }
1940         
1941         if (count == 0 && NT_STATUS_IS_OK(status)) {
1942                 status = map_nt_error_from_unix(errno);
1943         }
1944
1945         return status;
1946 }
1947
1948 /****************************************************************************
1949  Reply to a unlink
1950 ****************************************************************************/
1951
1952 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, 
1953                  int dum_buffsize)
1954 {
1955         int outsize = 0;
1956         pstring name;
1957         uint32 dirtype;
1958         NTSTATUS status;
1959         BOOL path_contains_wcard = False;
1960
1961         START_PROFILE(SMBunlink);
1962
1963         dirtype = SVAL(inbuf,smb_vwv0);
1964         
1965         srvstr_get_path_wcard(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard);
1966         if (!NT_STATUS_IS_OK(status)) {
1967                 END_PROFILE(SMBunlink);
1968                 return ERROR_NT(status);
1969         }
1970         
1971         RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
1972         
1973         DEBUG(3,("reply_unlink : %s\n",name));
1974         
1975         status = unlink_internals(conn, dirtype, name, path_contains_wcard,
1976                                   True);
1977         if (!NT_STATUS_IS_OK(status)) {
1978                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1979                         /* We have re-scheduled this call. */
1980                         return -1;
1981                 }
1982                 return ERROR_NT(status);
1983         }
1984
1985         outsize = set_message(outbuf,0,0,False);
1986   
1987         END_PROFILE(SMBunlink);
1988         return outsize;
1989 }
1990
1991 /****************************************************************************
1992  Fail for readbraw.
1993 ****************************************************************************/
1994
1995 static void fail_readraw(void)
1996 {
1997         pstring errstr;
1998         slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1999                 strerror(errno) );
2000         exit_server_cleanly(errstr);
2001 }
2002
2003 #if defined(WITH_SENDFILE)
2004 /****************************************************************************
2005  Fake (read/write) sendfile. Returns -1 on read or write fail.
2006 ****************************************************************************/
2007
2008 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
2009 {
2010         ssize_t ret=0;
2011
2012         /* Paranioa check... */
2013         if (nread > bufsize) {
2014                 fail_readraw();
2015         }
2016
2017         if (nread > 0) {
2018                 ret = read_file(fsp,buf,startpos,nread);
2019                 if (ret == -1) {
2020                         return -1;
2021                 }
2022         }
2023
2024         /* If we had a short read, fill with zeros. */
2025         if (ret < nread) {
2026                 memset(buf, '\0', nread - ret);
2027         }
2028
2029         if (write_data(smbd_server_fd(),buf,nread) != nread) {
2030                 return -1;
2031         }       
2032
2033         return (ssize_t)nread;
2034 }
2035 #endif
2036
2037 /****************************************************************************
2038  Use sendfile in readbraw.
2039 ****************************************************************************/
2040
2041 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
2042                 ssize_t mincount, char *outbuf, int out_buffsize)
2043 {
2044         ssize_t ret=0;
2045
2046 #if defined(WITH_SENDFILE)
2047         /*
2048          * We can only use sendfile on a non-chained packet 
2049          * but we can use on a non-oplocked file. tridge proved this
2050          * on a train in Germany :-). JRA.
2051          * reply_readbraw has already checked the length.
2052          */
2053
2054         if ( (chain_size == 0) && (nread > 0) &&
2055             (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2056                 DATA_BLOB header;
2057
2058                 _smb_setlen(outbuf,nread);
2059                 header.data = (uint8 *)outbuf;
2060                 header.length = 4;
2061                 header.free = NULL;
2062
2063                 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) {
2064                         /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2065                         if (errno == ENOSYS) {
2066                                 goto normal_readbraw;
2067                         }
2068
2069                         /*
2070                          * Special hack for broken Linux with no working sendfile. If we
2071                          * return EINTR we sent the header but not the rest of the data.
2072                          * Fake this up by doing read/write calls.
2073                          */
2074                         if (errno == EINTR) {
2075                                 /* Ensure we don't do this again. */
2076                                 set_use_sendfile(SNUM(conn), False);
2077                                 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2078
2079                                 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
2080                                         DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2081                                                 fsp->fsp_name, strerror(errno) ));
2082                                         exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2083                                 }
2084                                 return;
2085                         }
2086
2087                         DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2088                                 fsp->fsp_name, strerror(errno) ));
2089                         exit_server_cleanly("send_file_readbraw sendfile failed");
2090                 }
2091
2092         }
2093
2094   normal_readbraw:
2095
2096 #endif
2097
2098         if (nread > 0) {
2099                 ret = read_file(fsp,outbuf+4,startpos,nread);
2100 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2101                 if (ret < mincount)
2102                         ret = 0;
2103 #else
2104                 if (ret < nread)
2105                         ret = 0;
2106 #endif
2107         }
2108
2109         _smb_setlen(outbuf,ret);
2110         if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2111                 fail_readraw();
2112 }
2113
2114 /****************************************************************************
2115  Reply to a readbraw (core+ protocol).
2116 ****************************************************************************/
2117
2118 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2119 {
2120         ssize_t maxcount,mincount;
2121         size_t nread = 0;
2122         SMB_OFF_T startpos;
2123         char *header = outbuf;
2124         files_struct *fsp;
2125         START_PROFILE(SMBreadbraw);
2126
2127         if (srv_is_signing_active()) {
2128                 exit_server_cleanly("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2129         }
2130
2131         /*
2132          * Special check if an oplock break has been issued
2133          * and the readraw request croses on the wire, we must
2134          * return a zero length response here.
2135          */
2136
2137         fsp = file_fsp(inbuf,smb_vwv0);
2138
2139         if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2140                 /*
2141                  * fsp could be NULL here so use the value from the packet. JRA.
2142                  */
2143                 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2144                 _smb_setlen(header,0);
2145                 if (write_data(smbd_server_fd(),header,4) != 4)
2146                         fail_readraw();
2147                 END_PROFILE(SMBreadbraw);
2148                 return(-1);
2149         }
2150
2151         CHECK_FSP(fsp,conn);
2152
2153         flush_write_cache(fsp, READRAW_FLUSH);
2154
2155         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2156         if(CVAL(inbuf,smb_wct) == 10) {
2157                 /*
2158                  * This is a large offset (64 bit) read.
2159                  */
2160 #ifdef LARGE_SMB_OFF_T
2161
2162                 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2163
2164 #else /* !LARGE_SMB_OFF_T */
2165
2166                 /*
2167                  * Ensure we haven't been sent a >32 bit offset.
2168                  */
2169
2170                 if(IVAL(inbuf,smb_vwv8) != 0) {
2171                         DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2172 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2173                         _smb_setlen(header,0);
2174                         if (write_data(smbd_server_fd(),header,4) != 4)
2175                                 fail_readraw();
2176                         END_PROFILE(SMBreadbraw);
2177                         return(-1);
2178                 }
2179
2180 #endif /* LARGE_SMB_OFF_T */
2181
2182                 if(startpos < 0) {
2183                         DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2184                         _smb_setlen(header,0);
2185                         if (write_data(smbd_server_fd(),header,4) != 4)
2186                                 fail_readraw();
2187                         END_PROFILE(SMBreadbraw);
2188                         return(-1);
2189                 }      
2190         }
2191         maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2192         mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2193
2194         /* ensure we don't overrun the packet size */
2195         maxcount = MIN(65535,maxcount);
2196
2197         if (!is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2198                 SMB_STRUCT_STAT st;
2199                 SMB_OFF_T size = 0;
2200   
2201                 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2202                         size = st.st_size;
2203                 }
2204
2205                 if (startpos >= size) {
2206                         nread = 0;
2207                 } else {
2208                         nread = MIN(maxcount,(size - startpos));          
2209                 }
2210         }
2211
2212 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2213         if (nread < mincount)
2214                 nread = 0;
2215 #endif
2216   
2217         DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos,
2218                                 (unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) );
2219   
2220         send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2221
2222         DEBUG(5,("readbraw finished\n"));
2223         END_PROFILE(SMBreadbraw);
2224         return -1;
2225 }
2226
2227 #undef DBGC_CLASS
2228 #define DBGC_CLASS DBGC_LOCKING
2229
2230 /****************************************************************************
2231  Reply to a lockread (core+ protocol).
2232 ****************************************************************************/
2233
2234 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2235 {
2236         ssize_t nread = -1;
2237         char *data;
2238         int outsize = 0;
2239         SMB_OFF_T startpos;
2240         size_t numtoread;
2241         NTSTATUS status;
2242         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2243         struct byte_range_lock *br_lck = NULL;
2244         START_PROFILE(SMBlockread);
2245
2246         CHECK_FSP(fsp,conn);
2247         if (!CHECK_READ(fsp,inbuf)) {
2248                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2249         }
2250
2251         release_level_2_oplocks_on_change(fsp);
2252
2253         numtoread = SVAL(inbuf,smb_vwv1);
2254         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2255   
2256         outsize = set_message(outbuf,5,3,True);
2257         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2258         data = smb_buf(outbuf) + 3;
2259         
2260         /*
2261          * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2262          * protocol request that predates the read/write lock concept. 
2263          * Thus instead of asking for a read lock here we need to ask
2264          * for a write lock. JRA.
2265          * Note that the requested lock size is unaffected by max_recv.
2266          */
2267         
2268         br_lck = do_lock(fsp,
2269                         (uint32)SVAL(inbuf,smb_pid), 
2270                         (SMB_BIG_UINT)numtoread,
2271                         (SMB_BIG_UINT)startpos,
2272                         WRITE_LOCK,
2273                         WINDOWS_LOCK,
2274                         False, /* Non-blocking lock. */
2275                         &status);
2276         TALLOC_FREE(br_lck);
2277
2278         if (NT_STATUS_V(status)) {
2279                 END_PROFILE(SMBlockread);
2280                 return ERROR_NT(status);
2281         }
2282
2283         /*
2284          * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2285          */
2286
2287         if (numtoread > max_recv) {
2288                 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2289 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2290                         (unsigned int)numtoread, (unsigned int)max_recv ));
2291                 numtoread = MIN(numtoread,max_recv);
2292         }
2293         nread = read_file(fsp,data,startpos,numtoread);
2294
2295         if (nread < 0) {
2296                 END_PROFILE(SMBlockread);
2297                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2298         }
2299         
2300         outsize += nread;
2301         SSVAL(outbuf,smb_vwv0,nread);
2302         SSVAL(outbuf,smb_vwv5,nread+3);
2303         SSVAL(smb_buf(outbuf),1,nread);
2304         
2305         DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2306                  fsp->fnum, (int)numtoread, (int)nread));
2307
2308         END_PROFILE(SMBlockread);
2309         return(outsize);
2310 }
2311
2312 #undef DBGC_CLASS
2313 #define DBGC_CLASS DBGC_ALL
2314
2315 /****************************************************************************
2316  Reply to a read.
2317 ****************************************************************************/
2318
2319 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2320 {
2321         size_t numtoread;
2322         ssize_t nread = 0;
2323         char *data;
2324         SMB_OFF_T startpos;
2325         int outsize = 0;
2326         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2327         START_PROFILE(SMBread);
2328
2329         CHECK_FSP(fsp,conn);
2330         if (!CHECK_READ(fsp,inbuf)) {
2331                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2332         }
2333
2334         numtoread = SVAL(inbuf,smb_vwv1);
2335         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2336
2337         outsize = set_message(outbuf,5,3,True);
2338         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2339         /*
2340          * The requested read size cannot be greater than max_recv. JRA.
2341          */
2342         if (numtoread > max_recv) {
2343                 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2344 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2345                         (unsigned int)numtoread, (unsigned int)max_recv ));
2346                 numtoread = MIN(numtoread,max_recv);
2347         }
2348
2349         data = smb_buf(outbuf) + 3;
2350   
2351         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2352                 END_PROFILE(SMBread);
2353                 return ERROR_DOS(ERRDOS,ERRlock);
2354         }
2355
2356         if (numtoread > 0)
2357                 nread = read_file(fsp,data,startpos,numtoread);
2358
2359         if (nread < 0) {
2360                 END_PROFILE(SMBread);
2361                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2362         }
2363   
2364         outsize += nread;
2365         SSVAL(outbuf,smb_vwv0,nread);
2366         SSVAL(outbuf,smb_vwv5,nread+3);
2367         SCVAL(smb_buf(outbuf),0,1);
2368         SSVAL(smb_buf(outbuf),1,nread);
2369   
2370         DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2371                 fsp->fnum, (int)numtoread, (int)nread ) );
2372
2373         END_PROFILE(SMBread);
2374         return(outsize);
2375 }
2376
2377 /****************************************************************************
2378  Reply to a read and X - possibly using sendfile.
2379 ****************************************************************************/
2380
2381 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2382                 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2383 {
2384         int outsize = 0;
2385         ssize_t nread = -1;
2386         char *data = smb_buf(outbuf);
2387
2388 #if defined(WITH_SENDFILE)
2389         /*
2390          * We can only use sendfile on a non-chained packet 
2391          * but we can use on a non-oplocked file. tridge proved this
2392          * on a train in Germany :-). JRA.
2393          */
2394
2395         if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
2396             lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
2397                 SMB_STRUCT_STAT sbuf;
2398                 DATA_BLOB header;
2399
2400                 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1)
2401                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2402
2403                 if (startpos > sbuf.st_size)
2404                         goto normal_read;
2405
2406                 if (smb_maxcnt > (sbuf.st_size - startpos))
2407                         smb_maxcnt = (sbuf.st_size - startpos);
2408
2409                 if (smb_maxcnt == 0)
2410                         goto normal_read;
2411
2412                 /* 
2413                  * Set up the packet header before send. We
2414                  * assume here the sendfile will work (get the
2415                  * correct amount of data).
2416                  */
2417
2418                 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2419                 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2420                 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2421                 SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
2422                 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2423                 SCVAL(outbuf,smb_vwv0,0xFF);
2424                 set_message(outbuf,12,smb_maxcnt,False);
2425                 header.data = (uint8 *)outbuf;
2426                 header.length = data - outbuf;
2427                 header.free = NULL;
2428
2429                 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
2430                         /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2431                         if (errno == ENOSYS) {
2432                                 goto normal_read;
2433                         }
2434
2435                         /*
2436                          * Special hack for broken Linux with no working sendfile. If we
2437                          * return EINTR we sent the header but not the rest of the data.
2438                          * Fake this up by doing read/write calls.
2439                          */
2440
2441                         if (errno == EINTR) {
2442                                 /* Ensure we don't do this again. */
2443                                 set_use_sendfile(SNUM(conn), False);
2444                                 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2445
2446                                 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2447                                                         len_outbuf - (data-outbuf))) == -1) {
2448                                         DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2449                                                 fsp->fsp_name, strerror(errno) ));
2450                                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
2451                                 }
2452                                 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2453                                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2454                                 /* Returning -1 here means successful sendfile. */
2455                                 return -1;
2456                         }
2457
2458                         DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2459                                 fsp->fsp_name, strerror(errno) ));
2460                         exit_server_cleanly("send_file_readX sendfile failed");
2461                 }
2462
2463                 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2464                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2465                 /* Returning -1 here means successful sendfile. */
2466                 return -1;
2467         }
2468
2469   normal_read:
2470
2471 #endif
2472
2473         nread = read_file(fsp,data,startpos,smb_maxcnt);
2474   
2475         if (nread < 0) {
2476                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2477         }
2478
2479         outsize = set_message(outbuf,12,nread,False);
2480         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2481         SSVAL(outbuf,smb_vwv5,nread);
2482         SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2483         SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
2484         SSVAL(smb_buf(outbuf),-2,nread);
2485   
2486         DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2487                 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2488
2489         /* Returning the number of bytes we want to send back - including header. */
2490         return outsize;
2491 }
2492
2493 /****************************************************************************
2494  Reply to a read and X.
2495 ****************************************************************************/
2496
2497 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2498 {
2499         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2500         SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2501         ssize_t nread = -1;
2502         size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2503 #if 0
2504         size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2505 #endif
2506
2507         START_PROFILE(SMBreadX);
2508
2509         /* If it's an IPC, pass off the pipe handler. */
2510         if (IS_IPC(conn)) {
2511                 END_PROFILE(SMBreadX);
2512                 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2513         }
2514
2515         CHECK_FSP(fsp,conn);
2516         if (!CHECK_READ(fsp,inbuf)) {
2517                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2518         }
2519
2520         set_message(outbuf,12,0,True);
2521
2522         if (global_client_caps & CAP_LARGE_READX) {
2523                 if (SVAL(inbuf,smb_vwv7) == 1) {
2524                         smb_maxcnt |= (1<<16);
2525                 }
2526                 if (smb_maxcnt > BUFFER_SIZE) {
2527                         DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2528                                 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
2529                         END_PROFILE(SMBreadX);
2530                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2531                 }
2532         }
2533
2534         if(CVAL(inbuf,smb_wct) == 12) {
2535 #ifdef LARGE_SMB_OFF_T
2536                 /*
2537                  * This is a large offset (64 bit) read.
2538                  */
2539                 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2540
2541 #else /* !LARGE_SMB_OFF_T */
2542
2543                 /*
2544                  * Ensure we haven't been sent a >32 bit offset.
2545                  */
2546
2547                 if(IVAL(inbuf,smb_vwv10) != 0) {
2548                         DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2549 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2550                         END_PROFILE(SMBreadX);
2551                         return ERROR_DOS(ERRDOS,ERRbadaccess);
2552                 }
2553
2554 #endif /* LARGE_SMB_OFF_T */
2555
2556         }
2557
2558         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2559                 END_PROFILE(SMBreadX);
2560                 return ERROR_DOS(ERRDOS,ERRlock);
2561         }
2562
2563         if (schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
2564                 END_PROFILE(SMBreadX);
2565                 return -1;
2566         }
2567
2568         nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2569         if (nread != -1)
2570                 nread = chain_reply(inbuf,outbuf,length,bufsize);
2571
2572         END_PROFILE(SMBreadX);
2573         return nread;
2574 }
2575
2576 /****************************************************************************
2577  Reply to a writebraw (core+ or LANMAN1.0 protocol).
2578 ****************************************************************************/
2579
2580 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2581 {
2582         ssize_t nwritten=0;
2583         ssize_t total_written=0;
2584         size_t numtowrite=0;
2585         size_t tcount;
2586         SMB_OFF_T startpos;
2587         char *data=NULL;
2588         BOOL write_through;
2589         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2590         int outsize = 0;
2591         START_PROFILE(SMBwritebraw);
2592
2593         if (srv_is_signing_active()) {
2594                 exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2595         }
2596
2597         CHECK_FSP(fsp,conn);
2598         if (!CHECK_WRITE(fsp)) {
2599                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2600         }
2601   
2602         tcount = IVAL(inbuf,smb_vwv1);
2603         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2604         write_through = BITSETW(inbuf+smb_vwv7,0);
2605
2606         /* We have to deal with slightly different formats depending
2607                 on whether we are using the core+ or lanman1.0 protocol */
2608
2609         if(Protocol <= PROTOCOL_COREPLUS) {
2610                 numtowrite = SVAL(smb_buf(inbuf),-2);
2611                 data = smb_buf(inbuf);
2612         } else {
2613                 numtowrite = SVAL(inbuf,smb_vwv10);
2614                 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2615         }
2616
2617         /* force the error type */
2618         SCVAL(inbuf,smb_com,SMBwritec);
2619         SCVAL(outbuf,smb_com,SMBwritec);
2620
2621         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2622                 END_PROFILE(SMBwritebraw);
2623                 return(ERROR_DOS(ERRDOS,ERRlock));
2624         }
2625
2626         if (numtowrite>0)
2627                 nwritten = write_file(fsp,data,startpos,numtowrite);
2628   
2629         DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2630                 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2631
2632         if (nwritten < (ssize_t)numtowrite)  {
2633                 END_PROFILE(SMBwritebraw);
2634                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2635         }
2636
2637         total_written = nwritten;
2638
2639         /* Return a message to the redirector to tell it to send more bytes */
2640         SCVAL(outbuf,smb_com,SMBwritebraw);
2641         SSVALS(outbuf,smb_vwv0,-1);
2642         outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2643         show_msg(outbuf);
2644         if (!send_smb(smbd_server_fd(),outbuf))
2645                 exit_server_cleanly("reply_writebraw: send_smb failed.");
2646   
2647         /* Now read the raw data into the buffer and write it */
2648         if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2649                 exit_server_cleanly("secondary writebraw failed");
2650         }
2651   
2652         /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2653         numtowrite = smb_len(inbuf);
2654
2655         /* Set up outbuf to return the correct return */
2656         outsize = set_message(outbuf,1,0,True);
2657         SCVAL(outbuf,smb_com,SMBwritec);
2658
2659         if (numtowrite != 0) {
2660
2661                 if (numtowrite > BUFFER_SIZE) {
2662                         DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2663                                 (unsigned int)numtowrite ));
2664                         exit_server_cleanly("secondary writebraw failed");
2665                 }
2666
2667                 if (tcount > nwritten+numtowrite) {
2668                         DEBUG(3,("Client overestimated the write %d %d %d\n",
2669                                 (int)tcount,(int)nwritten,(int)numtowrite));
2670                 }
2671
2672                 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2673                         DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2674                                 strerror(errno) ));
2675                         exit_server_cleanly("secondary writebraw failed");
2676                 }
2677
2678                 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2679                 if (nwritten == -1) {
2680                         END_PROFILE(SMBwritebraw);
2681                         return(UNIXERROR(ERRHRD,ERRdiskfull));
2682                 }
2683
2684                 if (nwritten < (ssize_t)numtowrite) {
2685                         SCVAL(outbuf,smb_rcls,ERRHRD);
2686                         SSVAL(outbuf,smb_err,ERRdiskfull);      
2687                 }
2688
2689                 if (nwritten > 0)
2690                         total_written += nwritten;
2691         }
2692  
2693         SSVAL(outbuf,smb_vwv0,total_written);
2694
2695         sync_file(conn, fsp, write_through);
2696
2697         DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2698                 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2699
2700         /* we won't return a status if write through is not selected - this follows what WfWg does */
2701         END_PROFILE(SMBwritebraw);
2702         if (!write_through && total_written==tcount) {
2703
2704 #if RABBIT_PELLET_FIX
2705                 /*
2706                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2707                  * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2708                  */
2709                 if (!send_keepalive(smbd_server_fd()))
2710                         exit_server_cleanly("reply_writebraw: send of keepalive failed");
2711 #endif
2712                 return(-1);
2713         }
2714
2715         return(outsize);
2716 }
2717
2718 #undef DBGC_CLASS
2719 #define DBGC_CLASS DBGC_LOCKING
2720
2721 /****************************************************************************
2722  Reply to a writeunlock (core+).
2723 ****************************************************************************/
2724
2725 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, 
2726                       int size, int dum_buffsize)
2727 {
2728         ssize_t nwritten = -1;
2729         size_t numtowrite;
2730         SMB_OFF_T startpos;
2731         char *data;
2732         NTSTATUS status = NT_STATUS_OK;
2733         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2734         int outsize = 0;
2735         START_PROFILE(SMBwriteunlock);
2736         
2737         CHECK_FSP(fsp,conn);
2738         if (!CHECK_WRITE(fsp)) {
2739                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2740         }
2741
2742         numtowrite = SVAL(inbuf,smb_vwv1);
2743         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2744         data = smb_buf(inbuf) + 3;
2745   
2746         if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2747                 END_PROFILE(SMBwriteunlock);
2748                 return ERROR_DOS(ERRDOS,ERRlock);
2749         }
2750
2751         /* The special X/Open SMB protocol handling of
2752            zero length writes is *NOT* done for
2753            this call */
2754         if(numtowrite == 0) {
2755                 nwritten = 0;
2756         } else {
2757                 nwritten = write_file(fsp,data,startpos,numtowrite);
2758         }
2759   
2760         sync_file(conn, fsp, False /* write through */);
2761
2762         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2763                 END_PROFILE(SMBwriteunlock);
2764                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2765         }
2766
2767         if (numtowrite) {
2768                 status = do_unlock(fsp,
2769                                 (uint32)SVAL(inbuf,smb_pid),
2770                                 (SMB_BIG_UINT)numtowrite, 
2771                                 (SMB_BIG_UINT)startpos,
2772                                 WINDOWS_LOCK);
2773
2774                 if (NT_STATUS_V(status)) {
2775                         END_PROFILE(SMBwriteunlock);
2776                         return ERROR_NT(status);
2777                 }
2778         }
2779         
2780         outsize = set_message(outbuf,1,0,True);
2781         
2782         SSVAL(outbuf,smb_vwv0,nwritten);
2783         
2784         DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2785                  fsp->fnum, (int)numtowrite, (int)nwritten));
2786         
2787         END_PROFILE(SMBwriteunlock);
2788         return outsize;
2789 }
2790
2791 #undef DBGC_CLASS
2792 #define DBGC_CLASS DBGC_ALL
2793
2794 /****************************************************************************
2795  Reply to a write.
2796 ****************************************************************************/
2797
2798 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2799 {
2800         size_t numtowrite;
2801         ssize_t nwritten = -1;
2802         SMB_OFF_T startpos;
2803         char *data;
2804         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2805         int outsize = 0;
2806         START_PROFILE(SMBwrite);
2807
2808         /* If it's an IPC, pass off the pipe handler. */
2809         if (IS_IPC(conn)) {
2810                 END_PROFILE(SMBwrite);
2811                 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2812         }
2813
2814         CHECK_FSP(fsp,conn);
2815         if (!CHECK_WRITE(fsp)) {
2816                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2817         }
2818
2819         numtowrite = SVAL(inbuf,smb_vwv1);
2820         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2821         data = smb_buf(inbuf) + 3;
2822   
2823         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2824                 END_PROFILE(SMBwrite);
2825                 return ERROR_DOS(ERRDOS,ERRlock);
2826         }
2827
2828         /*
2829          * X/Open SMB protocol says that if smb_vwv1 is
2830          * zero then the file size should be extended or
2831          * truncated to the size given in smb_vwv[2-3].
2832          */
2833
2834         if(numtowrite == 0) {
2835                 /*
2836                  * This is actually an allocate call, and set EOF. JRA.
2837                  */
2838                 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2839                 if (nwritten < 0) {
2840                         END_PROFILE(SMBwrite);
2841                         return ERROR_NT(NT_STATUS_DISK_FULL);
2842                 }
2843                 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2844                 if (nwritten < 0) {
2845                         END_PROFILE(SMBwrite);
2846                         return ERROR_NT(NT_STATUS_DISK_FULL);
2847                 }
2848         } else
2849                 nwritten = write_file(fsp,data,startpos,numtowrite);
2850   
2851         sync_file(conn, fsp, False);
2852
2853         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2854                 END_PROFILE(SMBwrite);
2855                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2856         }
2857
2858         outsize = set_message(outbuf,1,0,True);
2859   
2860         SSVAL(outbuf,smb_vwv0,nwritten);
2861
2862         if (nwritten < (ssize_t)numtowrite) {
2863                 SCVAL(outbuf,smb_rcls,ERRHRD);
2864                 SSVAL(outbuf,smb_err,ERRdiskfull);      
2865         }
2866   
2867         DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2868
2869         END_PROFILE(SMBwrite);
2870         return(outsize);
2871 }
2872
2873 /****************************************************************************
2874  Reply to a write and X.
2875 ****************************************************************************/
2876
2877 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2878 {
2879         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2880         SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2881         size_t numtowrite = SVAL(inbuf,smb_vwv10);
2882         BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2883         ssize_t nwritten = -1;
2884         unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2885         unsigned int smblen = smb_len(inbuf);
2886         char *data;
2887         BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2888         START_PROFILE(SMBwriteX);
2889
2890         /* If it's an IPC, pass off the pipe handler. */
2891         if (IS_IPC(conn)) {
2892                 END_PROFILE(SMBwriteX);
2893                 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2894         }
2895
2896         CHECK_FSP(fsp,conn);
2897         if (!CHECK_WRITE(fsp)) {
2898                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2899         }
2900
2901         set_message(outbuf,6,0,True);
2902   
2903         /* Deal with possible LARGE_WRITEX */
2904         if (large_writeX) {
2905                 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2906         }
2907
2908         if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2909                 END_PROFILE(SMBwriteX);
2910                 return ERROR_DOS(ERRDOS,ERRbadmem);
2911         }
2912
2913         data = smb_base(inbuf) + smb_doff;
2914
2915         if(CVAL(inbuf,smb_wct) == 14) {
2916 #ifdef LARGE_SMB_OFF_T
2917                 /*
2918                  * This is a large offset (64 bit) write.
2919                  */
2920                 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2921
2922 #else /* !LARGE_SMB_OFF_T */
2923
2924                 /*
2925                  * Ensure we haven't been sent a >32 bit offset.
2926                  */
2927
2928                 if(IVAL(inbuf,smb_vwv12) != 0) {
2929                         DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2930 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2931                         END_PROFILE(SMBwriteX);
2932                         return ERROR_DOS(ERRDOS,ERRbadaccess);
2933                 }
2934
2935 #endif /* LARGE_SMB_OFF_T */
2936         }
2937
2938         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2939                 END_PROFILE(SMBwriteX);
2940                 return ERROR_DOS(ERRDOS,ERRlock);
2941         }
2942
2943         /* X/Open SMB protocol says that, unlike SMBwrite
2944         if the length is zero then NO truncation is
2945         done, just a write of zero. To truncate a file,
2946         use SMBwrite. */
2947
2948         if(numtowrite == 0) {
2949                 nwritten = 0;
2950         } else {
2951
2952                 if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize,
2953                                         fsp,data,startpos,numtowrite)) {
2954                         END_PROFILE(SMBwriteX);
2955                         return -1;
2956                 }
2957
2958                 nwritten = write_file(fsp,data,startpos,numtowrite);
2959         }
2960   
2961         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2962                 END_PROFILE(SMBwriteX);
2963                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2964         }
2965
2966         SSVAL(outbuf,smb_vwv2,nwritten);
2967         if (large_writeX)
2968                 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2969
2970         if (nwritten < (ssize_t)numtowrite) {
2971                 SCVAL(outbuf,smb_rcls,ERRHRD);
2972                 SSVAL(outbuf,smb_err,ERRdiskfull);      
2973         }
2974
2975         DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2976                 fsp->fnum, (int)numtowrite, (int)nwritten));
2977
2978         sync_file(conn, fsp, write_through);
2979
2980         END_PROFILE(SMBwriteX);
2981         return chain_reply(inbuf,outbuf,length,bufsize);
2982 }
2983
2984 /****************************************************************************
2985  Reply to a lseek.
2986 ****************************************************************************/
2987
2988 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2989 {
2990         SMB_OFF_T startpos;
2991         SMB_OFF_T res= -1;
2992         int mode,umode;
2993         int outsize = 0;
2994         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2995         START_PROFILE(SMBlseek);
2996
2997         CHECK_FSP(fsp,conn);
2998
2999         flush_write_cache(fsp, SEEK_FLUSH);
3000
3001         mode = SVAL(inbuf,smb_vwv1) & 3;
3002         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3003         startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
3004
3005         switch (mode) {
3006                 case 0:
3007                         umode = SEEK_SET;
3008                         res = startpos;
3009                         break;
3010                 case 1:
3011                         umode = SEEK_CUR;
3012                         res = fsp->fh->pos + startpos;
3013                         break;
3014                 case 2:
3015                         umode = SEEK_END;
3016                         break;
3017                 default:
3018                         umode = SEEK_SET;
3019                         res = startpos;
3020                         break;
3021         }
3022
3023         if (umode == SEEK_END) {
3024                 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
3025                         if(errno == EINVAL) {
3026                                 SMB_OFF_T current_pos = startpos;
3027                                 SMB_STRUCT_STAT sbuf;
3028
3029                                 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3030                                         END_PROFILE(SMBlseek);
3031                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3032                                 }
3033
3034                                 current_pos += sbuf.st_size;
3035                                 if(current_pos < 0)
3036                                         res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
3037                         }
3038                 }
3039
3040                 if(res == -1) {
3041                         END_PROFILE(SMBlseek);
3042                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3043                 }
3044         }
3045
3046         fsp->fh->pos = res;
3047   
3048         outsize = set_message(outbuf,2,0,True);
3049         SIVAL(outbuf,smb_vwv0,res);
3050   
3051         DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3052                 fsp->fnum, (double)startpos, (double)res, mode));
3053
3054         END_PROFILE(SMBlseek);
3055         return(outsize);
3056 }
3057
3058 /****************************************************************************
3059  Reply to a flush.
3060 ****************************************************************************/
3061
3062 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3063 {
3064         int outsize = set_message(outbuf,0,0,False);
3065         uint16 fnum = SVAL(inbuf,smb_vwv0);
3066         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3067         START_PROFILE(SMBflush);
3068
3069         if (fnum != 0xFFFF)
3070                 CHECK_FSP(fsp,conn);
3071         
3072         if (!fsp) {
3073                 file_sync_all(conn);
3074         } else {
3075                 sync_file(conn,fsp, True);
3076         }
3077         
3078         DEBUG(3,("flush\n"));
3079         END_PROFILE(SMBflush);
3080         return(outsize);
3081 }
3082
3083 /****************************************************************************
3084  Reply to a exit.
3085  conn POINTER CAN BE NULL HERE !
3086 ****************************************************************************/
3087
3088 int reply_exit(connection_struct *conn, 
3089                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3090 {
3091         int outsize;
3092         START_PROFILE(SMBexit);
3093
3094         file_close_pid(SVAL(inbuf,smb_pid),SVAL(inbuf,smb_uid));
3095
3096         outsize = set_message(outbuf,0,0,False);
3097
3098         DEBUG(3,("exit\n"));
3099
3100         END_PROFILE(SMBexit);
3101         return(outsize);
3102 }
3103
3104 /****************************************************************************
3105  Reply to a close - has to deal with closing a directory opened by NT SMB's.
3106 ****************************************************************************/
3107
3108 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
3109                 int dum_buffsize)
3110 {
3111         int outsize = 0;
3112         time_t mtime;
3113         int32 eclass = 0, err = 0;
3114         files_struct *fsp = NULL;
3115         START_PROFILE(SMBclose);
3116
3117         outsize = set_message(outbuf,0,0,False);
3118
3119         /* If it's an IPC, pass off to the pipe handler. */
3120         if (IS_IPC(conn)) {
3121                 END_PROFILE(SMBclose);
3122                 return reply_pipe_close(conn, inbuf,outbuf);
3123         }
3124
3125         fsp = file_fsp(inbuf,smb_vwv0);
3126
3127         /*
3128          * We can only use CHECK_FSP if we know it's not a directory.
3129          */
3130
3131         if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3132                 END_PROFILE(SMBclose);
3133                 return ERROR_DOS(ERRDOS,ERRbadfid);
3134         }
3135
3136         if(fsp->is_directory) {
3137                 /*
3138                  * Special case - close NT SMB directory handle.
3139                  */
3140                 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
3141                 close_file(fsp,NORMAL_CLOSE);
3142         } else {
3143                 /*
3144                  * Close ordinary file.
3145                  */
3146                 int close_err;
3147
3148                 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3149                          fsp->fh->fd, fsp->fnum,
3150                          conn->num_files_open));
3151  
3152                 /*
3153                  * Take care of any time sent in the close.
3154                  */
3155
3156                 mtime = srv_make_unix_date3(inbuf+smb_vwv1);
3157                 fsp_set_pending_modtime(fsp, mtime);
3158
3159                 /*
3160                  * close_file() returns the unix errno if an error
3161                  * was detected on close - normally this is due to
3162                  * a disk full error. If not then it was probably an I/O error.
3163                  */
3164  
3165                 if((close_err = close_file(fsp,NORMAL_CLOSE)) != 0) {
3166                         errno = close_err;
3167                         END_PROFILE(SMBclose);
3168                         return (UNIXERROR(ERRHRD,ERRgeneral));
3169                 }
3170         }  
3171
3172         /* We have a cached error */
3173         if(eclass || err) {
3174                 END_PROFILE(SMBclose);
3175                 return ERROR_DOS(eclass,err);
3176         }
3177
3178         END_PROFILE(SMBclose);
3179         return(outsize);
3180 }
3181
3182 /****************************************************************************
3183  Reply to a writeclose (Core+ protocol).
3184 ****************************************************************************/
3185
3186 int reply_writeclose(connection_struct *conn,
3187                      char *inbuf,char *outbuf, int size, int dum_buffsize)
3188 {
3189         size_t numtowrite;
3190         ssize_t nwritten = -1;
3191         int outsize = 0;
3192         int close_err = 0;
3193         SMB_OFF_T startpos;
3194         char *data;
3195         time_t mtime;
3196         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3197         START_PROFILE(SMBwriteclose);
3198
3199         CHECK_FSP(fsp,conn);
3200         if (!CHECK_WRITE(fsp)) {
3201                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3202         }
3203
3204         numtowrite = SVAL(inbuf,smb_vwv1);
3205         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3206         mtime = srv_make_unix_date3(inbuf+smb_vwv4);
3207         data = smb_buf(inbuf) + 1;
3208   
3209         if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3210                 END_PROFILE(SMBwriteclose);
3211                 return ERROR_DOS(ERRDOS,ERRlock);
3212         }
3213   
3214         nwritten = write_file(fsp,data,startpos,numtowrite);
3215
3216         set_filetime(conn, fsp->fsp_name,mtime);
3217   
3218         /*
3219          * More insanity. W2K only closes the file if writelen > 0.
3220          * JRA.
3221          */
3222
3223         if (numtowrite) {
3224                 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3225                         fsp->fsp_name ));
3226                 close_err = close_file(fsp,NORMAL_CLOSE);
3227         }
3228
3229         DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3230                  fsp->fnum, (int)numtowrite, (int)nwritten,
3231                  conn->num_files_open));
3232   
3233         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3234                 END_PROFILE(SMBwriteclose);
3235                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3236         }
3237  
3238         if(close_err != 0) {
3239                 errno = close_err;
3240                 END_PROFILE(SMBwriteclose);
3241                 return(UNIXERROR(ERRHRD,ERRgeneral));
3242         }
3243  
3244         outsize = set_message(outbuf,1,0,True);
3245   
3246         SSVAL(outbuf,smb_vwv0,nwritten);
3247         END_PROFILE(SMBwriteclose);
3248         return(outsize);
3249 }
3250
3251 #undef DBGC_CLASS
3252 #define DBGC_CLASS DBGC_LOCKING
3253
3254 /****************************************************************************
3255  Reply to a lock.
3256 ****************************************************************************/
3257
3258 int reply_lock(connection_struct *conn,
3259                char *inbuf,char *outbuf, int length, int dum_buffsize)
3260 {
3261         int outsize = set_message(outbuf,0,0,False);
3262         SMB_BIG_UINT count,offset;
3263         NTSTATUS status;
3264         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3265         struct byte_range_lock *br_lck = NULL;
3266
3267         START_PROFILE(SMBlock);
3268
3269         CHECK_FSP(fsp,conn);
3270
3271         release_level_2_oplocks_on_change(fsp);
3272
3273         count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3274         offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3275
3276         DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3277                  fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
3278
3279         br_lck = do_lock(fsp,
3280                         (uint32)SVAL(inbuf,smb_pid),
3281                         count,
3282                         offset,
3283                         WRITE_LOCK,
3284                         WINDOWS_LOCK,
3285                         False, /* Non-blocking lock. */
3286                         &status);
3287
3288         TALLOC_FREE(br_lck);
3289
3290         if (NT_STATUS_V(status)) {
3291                 END_PROFILE(SMBlock);
3292                 return ERROR_NT(status);
3293         }
3294
3295         END_PROFILE(SMBlock);
3296         return(outsize);
3297 }
3298
3299 /****************************************************************************
3300  Reply to a unlock.
3301 ****************************************************************************/
3302
3303 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, 
3304                  int dum_buffsize)
3305 {
3306         int outsize = set_message(outbuf,0,0,False);
3307         SMB_BIG_UINT count,offset;
3308         NTSTATUS status;
3309         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3310         START_PROFILE(SMBunlock);
3311
3312         CHECK_FSP(fsp,conn);
3313         
3314         count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3315         offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3316         
3317         status = do_unlock(fsp,
3318                         (uint32)SVAL(inbuf,smb_pid),
3319                         count,
3320                         offset,
3321                         WINDOWS_LOCK);
3322
3323         if (NT_STATUS_V(status)) {
3324                 END_PROFILE(SMBunlock);
3325                 return ERROR_NT(status);
3326         }
3327
3328         DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3329                     fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
3330         
3331         END_PROFILE(SMBunlock);
3332         return(outsize);
3333 }
3334
3335 #undef DBGC_CLASS
3336 #define DBGC_CLASS DBGC_ALL
3337
3338 /****************************************************************************
3339  Reply to a tdis.
3340  conn POINTER CAN BE NULL HERE !
3341 ****************************************************************************/
3342
3343 int reply_tdis(connection_struct *conn, 
3344                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3345 {
3346         int outsize = set_message(outbuf,0,0,False);
3347         uint16 vuid;
3348         START_PROFILE(SMBtdis);
3349
3350         vuid = SVAL(inbuf,smb_uid);
3351
3352         if (!conn) {
3353                 DEBUG(4,("Invalid connection in tdis\n"));
3354                 END_PROFILE(SMBtdis);
3355                 return ERROR_DOS(ERRSRV,ERRinvnid);
3356         }
3357
3358         conn->used = False;
3359
3360         close_cnum(conn,vuid);
3361   
3362         END_PROFILE(SMBtdis);
3363         return outsize;
3364 }
3365
3366 /****************************************************************************
3367  Reply to a echo.
3368  conn POINTER CAN BE NULL HERE !
3369 ****************************************************************************/
3370
3371 int reply_echo(connection_struct *conn,
3372                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3373 {
3374         int smb_reverb = SVAL(inbuf,smb_vwv0);
3375         int seq_num;
3376         unsigned int data_len = smb_buflen(inbuf);
3377         int outsize = set_message(outbuf,1,data_len,True);
3378         START_PROFILE(SMBecho);
3379
3380         if (data_len > BUFFER_SIZE) {
3381                 DEBUG(0,("reply_echo: data_len too large.\n"));
3382                 END_PROFILE(SMBecho);
3383                 return -1;
3384         }
3385
3386         /* copy any incoming data back out */
3387         if (data_len > 0)
3388                 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3389
3390         if (smb_reverb > 100) {
3391                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3392                 smb_reverb = 100;
3393         }
3394
3395         for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3396                 SSVAL(outbuf,smb_vwv0,seq_num);
3397
3398                 smb_setlen(outbuf,outsize - 4);
3399
3400                 show_msg(outbuf);
3401                 if (!send_smb(smbd_server_fd(),outbuf))
3402                         exit_server_cleanly("reply_echo: send_smb failed.");
3403         }
3404
3405         DEBUG(3,("echo %d times\n", smb_reverb));
3406
3407         smb_echo_count++;
3408
3409         END_PROFILE(SMBecho);
3410         return -1;
3411 }
3412
3413 /****************************************************************************
3414  Reply to a printopen.
3415 ****************************************************************************/
3416
3417 int reply_printopen(connection_struct *conn, 
3418                     char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3419 {
3420         int outsize = 0;
3421         files_struct *fsp;
3422         NTSTATUS status;
3423         
3424         START_PROFILE(SMBsplopen);
3425         
3426         if (!CAN_PRINT(conn)) {
3427                 END_PROFILE(SMBsplopen);
3428                 return ERROR_DOS(ERRDOS,ERRnoaccess);
3429         }
3430
3431         /* Open for exclusive use, write only. */
3432         status = print_fsp_open(conn, NULL, &fsp);
3433
3434         if (!NT_STATUS_IS_OK(status)) {
3435                 END_PROFILE(SMBsplopen);
3436                 return(ERROR_NT(status));
3437         }
3438
3439         outsize = set_message(outbuf,1,0,True);
3440         SSVAL(outbuf,smb_vwv0,fsp->fnum);
3441   
3442         DEBUG(3,("openprint fd=%d fnum=%d\n",
3443                  fsp->fh->fd, fsp->fnum));
3444
3445         END_PROFILE(SMBsplopen);
3446         return(outsize);
3447 }
3448
3449 /****************************************************************************
3450  Reply to a printclose.
3451 ****************************************************************************/
3452
3453 int reply_printclose(connection_struct *conn,
3454                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3455 {
3456         int outsize = set_message(outbuf,0,0,False);
3457         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3458         int close_err = 0;
3459         START_PROFILE(SMBsplclose);
3460
3461         CHECK_FSP(fsp,conn);
3462
3463         if (!CAN_PRINT(conn)) {
3464                 END_PROFILE(SMBsplclose);
3465                 return ERROR_NT(NT_STATUS_DOS(ERRSRV, ERRerror));
3466         }
3467   
3468         DEBUG(3,("printclose fd=%d fnum=%d\n",
3469                  fsp->fh->fd,fsp->fnum));
3470   
3471         close_err = close_file(fsp,NORMAL_CLOSE);
3472
3473         if(close_err != 0) {
3474                 errno = close_err;
3475                 END_PROFILE(SMBsplclose);
3476                 return(UNIXERROR(ERRHRD,ERRgeneral));
3477         }
3478
3479         END_PROFILE(SMBsplclose);
3480         return(outsize);
3481 }
3482
3483 /****************************************************************************
3484  Reply to a printqueue.
3485 ****************************************************************************/
3486
3487 int reply_printqueue(connection_struct *conn,
3488                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3489 {
3490         int outsize = set_message(outbuf,2,3,True);
3491         int max_count = SVAL(inbuf,smb_vwv0);
3492         int start_index = SVAL(inbuf,smb_vwv1);
3493         START_PROFILE(SMBsplretq);
3494
3495         /* we used to allow the client to get the cnum wrong, but that
3496            is really quite gross and only worked when there was only
3497            one printer - I think we should now only accept it if they
3498            get it right (tridge) */
3499         if (!CAN_PRINT(conn)) {
3500                 END_PROFILE(SMBsplretq);
3501                 return ERROR_DOS(ERRDOS,ERRnoaccess);
3502         }
3503
3504         SSVAL(outbuf,smb_vwv0,0);
3505         SSVAL(outbuf,smb_vwv1,0);
3506         SCVAL(smb_buf(outbuf),0,1);
3507         SSVAL(smb_buf(outbuf),1,0);
3508   
3509         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3510                  start_index, max_count));
3511
3512         {
3513                 print_queue_struct *queue = NULL;
3514                 print_status_struct status;
3515                 char *p = smb_buf(outbuf) + 3;
3516                 int count = print_queue_status(SNUM(conn), &queue, &status);
3517                 int num_to_get = ABS(max_count);
3518                 int first = (max_count>0?start_index:start_index+max_count+1);
3519                 int i;
3520
3521                 if (first >= count)
3522                         num_to_get = 0;
3523                 else
3524                         num_to_get = MIN(num_to_get,count-first);
3525     
3526
3527                 for (i=first;i<first+num_to_get;i++) {
3528                         srv_put_dos_date2(p,0,queue[i].time);
3529                         SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3530                         SSVAL(p,5, queue[i].job);
3531                         SIVAL(p,7,queue[i].size);
3532                         SCVAL(p,11,0);
3533                         srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3534                         p += 28;
3535                 }
3536
3537                 if (count > 0) {
3538                         outsize = set_message(outbuf,2,28*count+3,False); 
3539                         SSVAL(outbuf,smb_vwv0,count);
3540                         SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3541                         SCVAL(smb_buf(outbuf),0,1);
3542                         SSVAL(smb_buf(outbuf),1,28*count);
3543                 }
3544
3545                 SAFE_FREE(queue);
3546           
3547                 DEBUG(3,("%d entries returned in queue\n",count));
3548         }
3549   
3550         END_PROFILE(SMBsplretq);
3551         return(outsize);
3552 }
3553
3554 /****************************************************************************
3555  Reply to a printwrite.
3556 ****************************************************************************/
3557
3558 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3559 {
3560         int numtowrite;
3561         int outsize = set_message(outbuf,0,0,False);
3562         char *data;
3563         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3564
3565         START_PROFILE(SMBsplwr);
3566   
3567         if (!CAN_PRINT(conn)) {
3568                 END_PROFILE(SMBsplwr);
3569                 return ERROR_DOS(ERRDOS,ERRnoaccess);
3570         }
3571
3572         CHECK_FSP(fsp,conn);
3573         if (!CHECK_WRITE(fsp)) {
3574                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3575         }
3576
3577         numtowrite = SVAL(smb_buf(inbuf),1);
3578         data = smb_buf(inbuf) + 3;
3579   
3580         if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3581                 END_PROFILE(SMBsplwr);
3582                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3583         }
3584
3585         DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3586   
3587         END_PROFILE(SMBsplwr);
3588         return(outsize);
3589 }
3590
3591 /****************************************************************************
3592  Reply to a mkdir.
3593 ****************************************************************************/
3594
3595 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3596 {
3597         pstring directory;
3598         int outsize;
3599         NTSTATUS status;
3600         SMB_STRUCT_STAT sbuf;
3601
3602         START_PROFILE(SMBmkdir);
3603  
3604         srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3605         if (!NT_STATUS_IS_OK(status)) {
3606                 END_PROFILE(SMBmkdir);
3607                 return ERROR_NT(status);
3608         }
3609
3610         RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3611
3612         status = unix_convert(conn, directory, False, NULL, &sbuf);
3613         if (!NT_STATUS_IS_OK(status)) {
3614                 END_PROFILE(SMBmkdir);
3615                 return ERROR_NT(status);
3616         }
3617
3618         status = create_directory(conn, directory);
3619
3620         DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
3621
3622         if (!NT_STATUS_IS_OK(status)) {
3623
3624                 if (!use_nt_status()
3625                     && NT_STATUS_EQUAL(status,
3626                                        NT_STATUS_OBJECT_NAME_COLLISION)) {
3627                         /*
3628                          * Yes, in the DOS error code case we get a
3629                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
3630                          * samba4 torture test.
3631                          */
3632                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
3633                 }
3634
3635                 END_PROFILE(SMBmkdir);
3636                 return ERROR_NT(status);
3637         }
3638
3639         outsize = set_message(outbuf,0,0,False);
3640
3641         DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3642
3643         END_PROFILE(SMBmkdir);
3644         return(outsize);
3645 }
3646
3647 /****************************************************************************
3648  Static function used by reply_rmdir to delete an entire directory
3649  tree recursively. Return True on ok, False on fail.
3650 ****************************************************************************/
3651
3652 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3653 {
3654         const char *dname = NULL;
3655         BOOL ret = True;
3656         long offset = 0;
3657         struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3658
3659         if(dir_hnd == NULL)
3660                 return False;
3661
3662         while((dname = ReadDirName(dir_hnd, &offset))) {
3663                 pstring fullname;
3664                 SMB_STRUCT_STAT st;
3665
3666                 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3667                         continue;
3668
3669                 if (!is_visible_file(conn, directory, dname, &st, False))
3670                         continue;
3671
3672                 /* Construct the full name. */
3673                 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3674                         errno = ENOMEM;
3675                         ret = False;
3676                         break;
3677                 }
3678
3679                 pstrcpy(fullname, directory);
3680                 pstrcat(fullname, "/");
3681                 pstrcat(fullname, dname);
3682
3683                 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3684                         ret = False;
3685                         break;
3686                 }
3687
3688                 if(st.st_mode & S_IFDIR) {
3689                         if(!recursive_rmdir(conn, fullname)) {
3690                                 ret = False;
3691                                 break;
3692                         }
3693                         if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3694                                 ret = False;
3695                                 break;
3696                         }
3697                 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3698                         ret = False;
3699                         break;
3700                 }
3701         }
3702         CloseDir(dir_hnd);
3703         return ret;
3704 }
3705
3706 /****************************************************************************
3707  The internals of the rmdir code - called elsewhere.
3708 ****************************************************************************/
3709
3710 BOOL rmdir_internals(connection_struct *conn, const char *directory)
3711 {
3712         int ret;
3713         SMB_STRUCT_STAT st;
3714
3715         ret = SMB_VFS_RMDIR(conn,directory);
3716         if (ret == 0) {
3717                 notify_fname(conn, NOTIFY_ACTION_REMOVED,
3718                              FILE_NOTIFY_CHANGE_DIR_NAME,
3719                              directory);
3720                 return True;
3721         }
3722
3723         if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3724                 /* 
3725                  * Check to see if the only thing in this directory are
3726                  * vetoed files/directories. If so then delete them and
3727                  * retry. If we fail to delete any of them (and we *don't*
3728                  * do a recursive delete) then fail the rmdir.
3729                  */
3730                 const char *dname;
3731                 long dirpos = 0;
3732                 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3733
3734                 if(dir_hnd == NULL) {
3735                         errno = ENOTEMPTY;
3736                         goto err;
3737                 }
3738
3739                 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3740                         if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3741                                 continue;
3742                         if (!is_visible_file(conn, directory, dname, &st, False))
3743                                 continue;
3744                         if(!IS_VETO_PATH(conn, dname)) {
3745                                 CloseDir(dir_hnd);
3746                                 errno = ENOTEMPTY;
3747                                 goto err;
3748                         }
3749                 }
3750
3751                 /* We only have veto files/directories. Recursive delete. */
3752
3753                 RewindDir(dir_hnd,&dirpos);
3754                 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3755                         pstring fullname;
3756
3757                         if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3758                                 continue;
3759                         if (!is_visible_file(conn, directory, dname, &st, False))
3760                                 continue;
3761
3762                         /* Construct the full name. */
3763                         if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3764                                 errno = ENOMEM;
3765                                 break;
3766                         }
3767
3768                         pstrcpy(fullname, directory);
3769                         pstrcat(fullname, "/");
3770                         pstrcat(fullname, dname);
3771                    
3772                         if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3773                                 break;
3774                         if(st.st_mode & S_IFDIR) {
3775                                 if(lp_recursive_veto_delete(SNUM(conn))) {
3776                                         if(!recursive_rmdir(conn, fullname))
3777                                                 break;
3778                                 }
3779                                 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3780                                         break;
3781                         } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3782                                 break;
3783                 }
3784                 CloseDir(dir_hnd);
3785                 /* Retry the rmdir */
3786                 ret = SMB_VFS_RMDIR(conn,directory);
3787         }
3788
3789   err:
3790
3791         if (ret != 0) {
3792                 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
3793                          "%s\n", directory,strerror(errno)));
3794                 return False;
3795         }
3796
3797         notify_fname(conn, NOTIFY_ACTION_REMOVED,
3798                      FILE_NOTIFY_CHANGE_DIR_NAME,
3799                      directory);
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, pstring 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  * Do the notify calls from a rename
4118  */
4119
4120 static void notify_rename(connection_struct *conn, BOOL is_dir,
4121                           const char *oldpath, const char *newpath)
4122 {
4123         char *olddir, *newdir;
4124         const char *oldname, *newname;
4125         uint32 mask;
4126
4127         mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
4128                 : FILE_NOTIFY_CHANGE_FILE_NAME;
4129
4130         if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
4131             || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
4132                 TALLOC_FREE(olddir);
4133                 return;
4134         }
4135
4136         if (strcmp(olddir, newdir) == 0) {
4137                 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
4138                 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
4139         }
4140         else {
4141                 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
4142                 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
4143         }
4144         TALLOC_FREE(olddir);
4145         TALLOC_FREE(newdir);
4146
4147         /* this is a strange one. w2k3 gives an additional event for
4148            CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
4149            files, but not directories */
4150         if (!is_dir) {
4151                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
4152                              FILE_NOTIFY_CHANGE_ATTRIBUTES
4153                              |FILE_NOTIFY_CHANGE_CREATION,
4154                              newpath);
4155         }
4156 }
4157
4158 /****************************************************************************
4159  The guts of the rename command, split out so it may be called by the NT SMB
4160  code. 
4161 ****************************************************************************/
4162
4163 NTSTATUS rename_internals(connection_struct *conn, pstring name,
4164                           pstring newname, uint32 attrs,
4165                           BOOL replace_if_exists, BOOL has_wild)
4166 {
4167         pstring directory;
4168         pstring mask;
4169         pstring last_component_src;
4170         pstring last_component_dest;
4171         char *p;
4172         int count=0;
4173         NTSTATUS status = NT_STATUS_OK;
4174         SMB_STRUCT_STAT sbuf1, sbuf2;
4175         struct share_mode_lock *lck = NULL;
4176
4177         *directory = *mask = 0;
4178
4179         ZERO_STRUCT(sbuf1);
4180         ZERO_STRUCT(sbuf2);
4181
4182         status = unix_convert(conn, name, has_wild, last_component_src,
4183                               &sbuf1);
4184         if (!NT_STATUS_IS_OK(status)) {
4185                 return status;
4186         }
4187
4188         status = unix_convert(conn, newname, True, last_component_dest,
4189                               &sbuf2);
4190         if (!NT_STATUS_IS_OK(status)) {
4191                 return status;
4192         }
4193
4194         /*
4195          * Split the old name into directory and last component
4196          * strings. Note that unix_convert may have stripped off a 
4197          * leading ./ from both name and newname if the rename is 
4198          * at the root of the share. We need to make sure either both
4199          * name and newname contain a / character or neither of them do
4200          * as this is checked in resolve_wildcards().
4201          */
4202
4203         p = strrchr_m(name,'/');
4204         if (!p) {
4205                 pstrcpy(directory,".");
4206                 pstrcpy(mask,name);
4207         } else {
4208                 *p = 0;
4209                 pstrcpy(directory,name);
4210                 pstrcpy(mask,p+1);
4211                 *p = '/'; /* Replace needed for exceptional test below. */
4212         }
4213
4214         /*
4215          * We should only check the mangled cache
4216          * here if unix_convert failed. This means
4217          * that the path in 'mask' doesn't exist
4218          * on the file system and so we need to look
4219          * for a possible mangle. This patch from
4220          * Tine Smukavec <valentin.smukavec@hermes.si>.
4221          */
4222
4223         if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params))
4224                 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
4225
4226         if (!has_wild) {
4227                 /*
4228                  * No wildcards - just process the one file.
4229                  */
4230                 BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
4231
4232                 /* Add a terminating '/' to the directory name. */
4233                 pstrcat(directory,"/");
4234                 pstrcat(directory,mask);
4235                 
4236                 /* Ensure newname contains a '/' also */
4237                 if(strrchr_m(newname,'/') == 0) {
4238                         pstring tmpstr;
4239                         
4240                         pstrcpy(tmpstr, "./");
4241                         pstrcat(tmpstr, newname);
4242                         pstrcpy(newname, tmpstr);
4243                 }
4244                 
4245                 DEBUG(3, ("rename_internals: case_sensitive = %d, "
4246                           "case_preserve = %d, short case preserve = %d, "
4247                           "directory = %s, newname = %s, "
4248                           "last_component_dest = %s, is_8_3 = %d\n", 
4249                           conn->case_sensitive, conn->case_preserve,
4250                           conn->short_case_preserve, directory, 
4251                           newname, last_component_dest, is_short_name));
4252
4253                 /*
4254                  * Check for special case with case preserving and not
4255                  * case sensitive, if directory and newname are identical,
4256                  * and the old last component differs from the original
4257                  * last component only by case, then we should allow
4258                  * the rename (user is trying to change the case of the
4259                  * filename).
4260                  */
4261                 if((conn->case_sensitive == False) && 
4262                    (((conn->case_preserve == True) && 
4263                      (is_short_name == False)) || 
4264                     ((conn->short_case_preserve == True) && 
4265                      (is_short_name == True))) &&
4266                    strcsequal(directory, newname)) {
4267                         pstring modified_last_component;
4268
4269                         /*
4270                          * Get the last component of the modified name.
4271                          * Note that we guarantee that newname contains a '/'
4272                          * character above.
4273                          */
4274                         p = strrchr_m(newname,'/');
4275                         pstrcpy(modified_last_component,p+1);
4276                         
4277                         if(strcsequal(modified_last_component, 
4278                                       last_component_dest) == False) {
4279                                 /*
4280                                  * Replace the modified last component with
4281                                  * the original.
4282                                  */
4283                                 pstrcpy(p+1, last_component_dest);
4284                         }
4285                 }
4286         
4287                 resolve_wildcards(directory,newname);
4288         
4289                 /*
4290                  * The source object must exist.
4291                  */
4292
4293                 if (!vfs_object_exist(conn, directory, &sbuf1)) {
4294                         DEBUG(3, ("rename_internals: source doesn't exist "
4295                                   "doing rename %s -> %s\n",
4296                                 directory,newname));
4297
4298                         if (errno == ENOTDIR || errno == EISDIR
4299                             || errno == ENOENT) {
4300                                 /*
4301                                  * Must return different errors depending on
4302                                  * whether the parent directory existed or
4303                                  * not.
4304                                  */
4305
4306                                 p = strrchr_m(directory, '/');
4307                                 if (!p)
4308                                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4309                                 *p = '\0';
4310                                 if (vfs_object_exist(conn, directory, NULL))
4311                                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4312                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4313                         }
4314                         status = map_nt_error_from_unix(errno);
4315                         DEBUG(3, ("rename_internals: Error %s rename %s -> "
4316                                   "%s\n", nt_errstr(status), directory,
4317                                   newname));
4318
4319                         return status;
4320                 }
4321
4322                 status = can_rename(conn,directory,attrs,&sbuf1);
4323
4324                 if (!NT_STATUS_IS_OK(status)) {
4325                         DEBUG(3,("rename_internals: Error %s rename %s -> "
4326                                  "%s\n", nt_errstr(status), directory,
4327                                  newname));
4328                         return status;
4329                 }
4330
4331                 /*
4332                  * If the src and dest names are identical - including case,
4333                  * don't do the rename, just return success.
4334                  */
4335
4336                 if (strcsequal(directory, newname)) {
4337                         rename_open_files(conn, NULL, sbuf1.st_dev,
4338                                           sbuf1.st_ino, newname);
4339                         DEBUG(3, ("rename_internals: identical names in "
4340                                   "rename %s - returning success\n",
4341                                   directory));
4342                         return NT_STATUS_OK;
4343                 }
4344
4345                 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
4346                         DEBUG(3,("rename_internals: dest exists doing "
4347                                  "rename %s -> %s\n", directory, newname));
4348                         return NT_STATUS_OBJECT_NAME_COLLISION;
4349                 }
4350
4351                 if (rename_path_prefix_equal(directory, newname)) {
4352                         return NT_STATUS_SHARING_VIOLATION;
4353                 }
4354
4355                 lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino,
4356                                           NULL, NULL);
4357
4358                 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
4359                         DEBUG(3,("rename_internals: succeeded doing rename "
4360                                  "on %s -> %s\n", directory, newname));
4361                         rename_open_files(conn, lck, sbuf1.st_dev,
4362                                           sbuf1.st_ino, newname);
4363                         TALLOC_FREE(lck);
4364                         notify_rename(conn, S_ISDIR(sbuf1.st_mode),
4365                                       directory, newname);
4366                         return NT_STATUS_OK;    
4367                 }
4368
4369                 TALLOC_FREE(lck);
4370                 if (errno == ENOTDIR || errno == EISDIR) {
4371                         status = NT_STATUS_OBJECT_NAME_COLLISION;
4372                 } else {
4373                         status = map_nt_error_from_unix(errno);
4374                 }
4375                 
4376                 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4377                         nt_errstr(status), directory,newname));
4378
4379                 return status;
4380         } else {
4381                 /*
4382                  * Wildcards - process each file that matches.
4383                  */
4384                 struct smb_Dir *dir_hnd = NULL;
4385                 const char *dname;
4386                 long offset = 0;
4387                 pstring destname;
4388                 
4389                 if (strequal(mask,"????????.???"))
4390                         pstrcpy(mask,"*");
4391                         
4392                 status = check_name(conn, directory);
4393                 if (!NT_STATUS_IS_OK(status)) {
4394                         return status;
4395                 }
4396         
4397                 dir_hnd = OpenDir(conn, directory, mask, attrs);
4398                 if (dir_hnd == NULL) {
4399                         return map_nt_error_from_unix(errno);
4400                 }
4401                 
4402                 status = NT_STATUS_NO_SUCH_FILE;
4403                 /*
4404                  * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4405                  * - gentest fix. JRA
4406                  */
4407                         
4408                 while ((dname = ReadDirName(dir_hnd, &offset))) {
4409                         pstring fname;
4410                         BOOL sysdir_entry = False;
4411
4412                         pstrcpy(fname,dname);
4413                                 
4414                         /* Quick check for "." and ".." */
4415                         if (fname[0] == '.') {
4416                                 if (!fname[1]
4417                                     || (fname[1] == '.' && !fname[2])) {
4418                                         if (attrs & aDIR) {
4419                                                 sysdir_entry = True;
4420                                         } else {
4421                                                 continue;
4422                                         }
4423                                 }
4424                         }
4425
4426                         if (!is_visible_file(conn, directory, dname, &sbuf1,
4427                                              False)) {
4428                                 continue;
4429                         }
4430
4431                         if(!mask_match(fname, mask, conn->case_sensitive)) {
4432                                 continue;
4433                         }
4434                                 
4435                         if (sysdir_entry) {
4436                                 status = NT_STATUS_OBJECT_NAME_INVALID;
4437                                 break;
4438                         }
4439
4440                         status = NT_STATUS_ACCESS_DENIED;
4441                         slprintf(fname, sizeof(fname)-1, "%s/%s", directory,
4442                                  dname);
4443                         if (!vfs_object_exist(conn, fname, &sbuf1)) {
4444                                 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4445                                 DEBUG(6, ("rename %s failed. Error %s\n",
4446                                           fname, nt_errstr(status)));
4447                                 continue;
4448                         }
4449                         status = can_rename(conn,fname,attrs,&sbuf1);
4450                         if (!NT_STATUS_IS_OK(status)) {
4451                                 DEBUG(6, ("rename %s refused\n", fname));
4452                                 continue;
4453                         }
4454                         pstrcpy(destname,newname);
4455                         
4456                         if (!resolve_wildcards(fname,destname)) {
4457                                 DEBUG(6, ("resolve_wildcards %s %s failed\n", 
4458                                           fname, destname));
4459                                 continue;
4460                         }
4461                                 
4462                         if (strcsequal(fname,destname)) {
4463                                 rename_open_files(conn, NULL, sbuf1.st_dev,
4464                                                   sbuf1.st_ino, newname);
4465                                 DEBUG(3,("rename_internals: identical names "
4466                                          "in wildcard rename %s - success\n",
4467                                          fname));
4468                                 count++;
4469                                 status = NT_STATUS_OK;
4470                                 continue;
4471                         }
4472
4473                         if (!replace_if_exists
4474                             && vfs_file_exist(conn,destname, NULL)) {
4475                                 DEBUG(6,("file_exist %s\n", destname));
4476                                 status = NT_STATUS_OBJECT_NAME_COLLISION;
4477                                 continue;
4478                         }
4479                                 
4480                         if (rename_path_prefix_equal(fname, destname)) {
4481                                 return NT_STATUS_SHARING_VIOLATION;
4482                         }
4483
4484                         lck = get_share_mode_lock(NULL, sbuf1.st_dev,
4485                                                   sbuf1.st_ino, NULL, NULL);
4486
4487                         if (!SMB_VFS_RENAME(conn,fname,destname)) {
4488                                 rename_open_files(conn, lck, sbuf1.st_dev,
4489                                                   sbuf1.st_ino, newname);
4490                                 count++;
4491                                 status = NT_STATUS_OK;
4492                         }
4493                         TALLOC_FREE(lck);
4494                         DEBUG(3,("rename_internals: doing rename on %s -> "
4495                                  "%s\n",fname,destname));
4496                 }
4497                 CloseDir(dir_hnd);
4498         }
4499
4500 #if 0
4501         /* Don't think needed any more - JRA. */
4502                 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
4503                         if (!rcdest && bad_path_dest) {
4504                                 if (ms_has_wild(last_component_dest))
4505                                         return NT_STATUS_OBJECT_NAME_INVALID;
4506                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4507                         }
4508                 }
4509 #endif
4510
4511         if (count == 0 && NT_STATUS_IS_OK(status)) {
4512                 status = map_nt_error_from_unix(errno);
4513         }
4514         
4515         return status;
4516 }
4517
4518 /****************************************************************************
4519  Reply to a mv.
4520 ****************************************************************************/
4521
4522 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, 
4523              int dum_buffsize)
4524 {
4525         int outsize = 0;
4526         pstring name;
4527         pstring newname;
4528         char *p;
4529         uint32 attrs = SVAL(inbuf,smb_vwv0);
4530         NTSTATUS status;
4531         BOOL path1_contains_wcard = False;
4532         BOOL path2_contains_wcard = False;
4533
4534         START_PROFILE(SMBmv);
4535
4536         p = smb_buf(inbuf) + 1;
4537         p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path1_contains_wcard);
4538         if (!NT_STATUS_IS_OK(status)) {
4539                 END_PROFILE(SMBmv);
4540                 return ERROR_NT(status);
4541         }
4542         p++;
4543         p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &path2_contains_wcard);
4544         if (!NT_STATUS_IS_OK(status)) {
4545                 END_PROFILE(SMBmv);
4546                 return ERROR_NT(status);
4547         }
4548         
4549         RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4550         RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4551         
4552         DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4553         
4554         status = rename_internals(conn, name, newname, attrs, False, path1_contains_wcard);
4555         if (!NT_STATUS_IS_OK(status)) {
4556                 END_PROFILE(SMBmv);
4557                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4558                         /* We have re-scheduled this call. */
4559                         return -1;
4560                 }
4561                 return ERROR_NT(status);
4562         }
4563
4564         outsize = set_message(outbuf,0,0,False);
4565   
4566         END_PROFILE(SMBmv);
4567         return(outsize);
4568 }
4569
4570 /*******************************************************************
4571  Copy a file as part of a reply_copy.
4572 ******************************************************************/
4573
4574 /*
4575  * TODO: check error codes on all callers
4576  */
4577
4578 NTSTATUS copy_file(char *src, char *dest1,connection_struct *conn, int ofun,
4579                    int count, BOOL target_is_directory)
4580 {
4581         SMB_STRUCT_STAT src_sbuf, sbuf2;
4582         SMB_OFF_T ret=-1;
4583         files_struct *fsp1,*fsp2;
4584         pstring dest;
4585         uint32 dosattrs;
4586         uint32 new_create_disposition;
4587         NTSTATUS status;
4588         int close_err;
4589  
4590         pstrcpy(dest,dest1);
4591         if (target_is_directory) {
4592                 char *p = strrchr_m(src,'/');
4593                 if (p) {
4594                         p++;
4595                 } else {
4596                         p = src;
4597                 }
4598                 pstrcat(dest,"/");
4599                 pstrcat(dest,p);
4600         }
4601
4602         if (!vfs_file_exist(conn,src,&src_sbuf)) {
4603                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4604         }
4605
4606         if (!target_is_directory && count) {
4607                 new_create_disposition = FILE_OPEN;
4608         } else {
4609                 if (!map_open_params_to_ntcreate(dest1,0,ofun,
4610                                 NULL, NULL, &new_create_disposition, NULL)) {
4611                         return NT_STATUS_INVALID_PARAMETER;
4612                 }
4613         }
4614
4615         status = open_file_ntcreate(conn,src,&src_sbuf,
4616                         FILE_GENERIC_READ,
4617                         FILE_SHARE_READ|FILE_SHARE_WRITE,
4618                         FILE_OPEN,
4619                         0,
4620                         FILE_ATTRIBUTE_NORMAL,
4621                         INTERNAL_OPEN_ONLY,
4622                         NULL, &fsp1);
4623
4624         if (!NT_STATUS_IS_OK(status)) {
4625                 return status;
4626         }
4627
4628         dosattrs = dos_mode(conn, src, &src_sbuf);
4629         if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
4630                 ZERO_STRUCTP(&sbuf2);
4631         }
4632
4633         status = open_file_ntcreate(conn,dest,&sbuf2,
4634                         FILE_GENERIC_WRITE,
4635                         FILE_SHARE_READ|FILE_SHARE_WRITE,
4636                         new_create_disposition,
4637                         0,
4638                         dosattrs,
4639                         INTERNAL_OPEN_ONLY,
4640                         NULL, &fsp2);
4641
4642         if (!NT_STATUS_IS_OK(status)) {
4643                 close_file(fsp1,ERROR_CLOSE);
4644                 return status;
4645         }
4646
4647         if ((ofun&3) == 1) {
4648                 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
4649                         DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4650                         /*
4651                          * Stop the copy from occurring.
4652                          */
4653                         ret = -1;
4654                         src_sbuf.st_size = 0;
4655                 }
4656         }
4657   
4658         if (src_sbuf.st_size) {
4659                 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4660         }
4661
4662         close_file(fsp1,NORMAL_CLOSE);
4663
4664         /* Ensure the modtime is set correctly on the destination file. */
4665         fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime);
4666
4667         /*
4668          * As we are opening fsp1 read-only we only expect
4669          * an error on close on fsp2 if we are out of space.
4670          * Thus we don't look at the error return from the
4671          * close of fsp1.
4672          */
4673         close_err = close_file(fsp2,NORMAL_CLOSE);
4674
4675         if (close_err != 0) {
4676                 return map_nt_error_from_unix(close_err);
4677         }
4678
4679         if (ret != (SMB_OFF_T)src_sbuf.st_size) {
4680                 return NT_STATUS_DISK_FULL;
4681         }
4682
4683         return NT_STATUS_OK;
4684 }
4685
4686 /****************************************************************************
4687  Reply to a file copy.
4688 ****************************************************************************/
4689
4690 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4691 {
4692         int outsize = 0;
4693         pstring name;
4694         pstring directory;
4695         pstring mask,newname;
4696         char *p;
4697         int count=0;
4698         int error = ERRnoaccess;
4699         int err = 0;
4700         BOOL has_wild;
4701         BOOL exists=False;
4702         int tid2 = SVAL(inbuf,smb_vwv0);
4703         int ofun = SVAL(inbuf,smb_vwv1);
4704         int flags = SVAL(inbuf,smb_vwv2);
4705         BOOL target_is_directory=False;
4706         BOOL path_contains_wcard1 = False;
4707         BOOL path_contains_wcard2 = False;
4708         SMB_STRUCT_STAT sbuf1, sbuf2;
4709         NTSTATUS status;
4710         START_PROFILE(SMBcopy);
4711
4712         *directory = *mask = 0;
4713
4714         p = smb_buf(inbuf);
4715         p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard1);
4716         if (!NT_STATUS_IS_OK(status)) {
4717                 END_PROFILE(SMBcopy);
4718                 return ERROR_NT(status);
4719         }
4720         p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &path_contains_wcard2);
4721         if (!NT_STATUS_IS_OK(status)) {
4722                 END_PROFILE(SMBcopy);
4723                 return ERROR_NT(status);
4724         }
4725    
4726         DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4727    
4728         if (tid2 != conn->cnum) {
4729                 /* can't currently handle inter share copies XXXX */
4730                 DEBUG(3,("Rejecting inter-share copy\n"));
4731                 END_PROFILE(SMBcopy);
4732                 return ERROR_DOS(ERRSRV,ERRinvdevice);
4733         }
4734
4735         RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4736         RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4737
4738         status = unix_convert(conn, name, path_contains_wcard1, NULL, &sbuf1);
4739         if (!NT_STATUS_IS_OK(status)) {
4740                 END_PROFILE(SMBcopy);
4741                 return ERROR_NT(status);
4742         }
4743
4744         status = unix_convert(conn, newname, path_contains_wcard2, NULL, &sbuf2);
4745         if (!NT_STATUS_IS_OK(status)) {
4746                 END_PROFILE(SMBcopy);
4747                 return ERROR_NT(status);
4748         }
4749
4750         target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4751
4752         if ((flags&1) && target_is_directory) {
4753                 END_PROFILE(SMBcopy);
4754                 return ERROR_DOS(ERRDOS,ERRbadfile);
4755         }
4756
4757         if ((flags&2) && !target_is_directory) {
4758                 END_PROFILE(SMBcopy);
4759                 return ERROR_DOS(ERRDOS,ERRbadpath);
4760         }
4761
4762         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4763                 /* wants a tree copy! XXXX */
4764                 DEBUG(3,("Rejecting tree copy\n"));
4765                 END_PROFILE(SMBcopy);
4766                 return ERROR_DOS(ERRSRV,ERRerror);
4767         }
4768
4769         p = strrchr_m(name,'/');
4770         if (!p) {
4771                 pstrcpy(directory,"./");
4772                 pstrcpy(mask,name);
4773         } else {
4774                 *p = 0;
4775                 pstrcpy(directory,name);
4776                 pstrcpy(mask,p+1);
4777         }
4778
4779         /*
4780          * We should only check the mangled cache
4781          * here if unix_convert failed. This means
4782          * that the path in 'mask' doesn't exist
4783          * on the file system and so we need to look
4784          * for a possible mangle. This patch from
4785          * Tine Smukavec <valentin.smukavec@hermes.si>.
4786          */
4787
4788         if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params))
4789                 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
4790
4791         has_wild = path_contains_wcard1;
4792
4793         if (!has_wild) {
4794                 pstrcat(directory,"/");
4795                 pstrcat(directory,mask);
4796                 if (resolve_wildcards(directory,newname)
4797                     && NT_STATUS_IS_OK(status = copy_file(
4798                                                directory,newname,conn,ofun,
4799                                                count,target_is_directory))) 
4800                         count++;
4801                 if(!count && !NT_STATUS_IS_OK(status)) {
4802                         END_PROFILE(SMBcopy);
4803                         return ERROR_NT(status);
4804                 }
4805                 if (!count) {
4806                         exists = vfs_file_exist(conn,directory,NULL);
4807                 }
4808         } else {
4809                 struct smb_Dir *dir_hnd = NULL;
4810                 const char *dname;
4811                 long offset = 0;
4812                 pstring destname;
4813
4814                 if (strequal(mask,"????????.???"))
4815                         pstrcpy(mask,"*");
4816
4817                 status = check_name(conn, directory);
4818                 if (!NT_STATUS_IS_OK(status)) {
4819                         return ERROR_NT(status);
4820                 }
4821                 
4822                 dir_hnd = OpenDir(conn, directory, mask, 0);
4823                 if (dir_hnd == NULL) {
4824                         status = map_nt_error_from_unix(errno);
4825                         return ERROR_NT(status);
4826                 }
4827
4828                 error = ERRbadfile;
4829
4830                 while ((dname = ReadDirName(dir_hnd, &offset))) {
4831                         pstring fname;
4832                         pstrcpy(fname,dname);
4833     
4834                         if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
4835                                 continue;
4836                         }
4837
4838                         if(!mask_match(fname, mask, conn->case_sensitive)) {
4839                                 continue;
4840                         }
4841
4842                         error = ERRnoaccess;
4843                         slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4844                         pstrcpy(destname,newname);
4845                         if (resolve_wildcards(fname,destname) &&
4846                                         NT_STATUS_IS_OK(status = copy_file(
4847                                                 fname,destname,conn,ofun,
4848                                                 count,target_is_directory))) {
4849                                 count++;
4850                         }
4851                         DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4852                 }
4853                 CloseDir(dir_hnd);
4854         }
4855   
4856         if (count == 0) {
4857                 if(err) {
4858                         /* Error on close... */
4859                         errno = err;
4860                         END_PROFILE(SMBcopy);
4861                         return(UNIXERROR(ERRHRD,ERRgeneral));
4862                 }
4863
4864                 END_PROFILE(SMBcopy);
4865                 return ERROR_DOS(ERRDOS,error);
4866         }
4867   
4868         outsize = set_message(outbuf,1,0,True);
4869         SSVAL(outbuf,smb_vwv0,count);
4870
4871         END_PROFILE(SMBcopy);
4872         return(outsize);
4873 }
4874
4875 /****************************************************************************
4876  Reply to a setdir.
4877 ****************************************************************************/
4878
4879 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4880 {
4881         int snum;
4882         int outsize = 0;
4883         pstring newdir;
4884         NTSTATUS status;
4885
4886         START_PROFILE(pathworks_setdir);
4887   
4888         snum = SNUM(conn);
4889         if (!CAN_SETDIR(snum)) {
4890                 END_PROFILE(pathworks_setdir);
4891                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4892         }
4893
4894         srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
4895         if (!NT_STATUS_IS_OK(status)) {
4896                 END_PROFILE(pathworks_setdir);
4897                 return ERROR_NT(status);
4898         }
4899   
4900         RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf);
4901
4902         if (strlen(newdir) != 0) {
4903                 if (!vfs_directory_exist(conn,newdir,NULL)) {
4904                         END_PROFILE(pathworks_setdir);
4905                         return ERROR_DOS(ERRDOS,ERRbadpath);
4906                 }
4907                 set_conn_connectpath(conn,newdir);
4908         }
4909   
4910         outsize = set_message(outbuf,0,0,False);
4911         SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4912   
4913         DEBUG(3,("setdir %s\n", newdir));
4914
4915         END_PROFILE(pathworks_setdir);
4916         return(outsize);
4917 }
4918
4919 #undef DBGC_CLASS
4920 #define DBGC_CLASS DBGC_LOCKING
4921
4922 /****************************************************************************
4923  Get a lock pid, dealing with large count requests.
4924 ****************************************************************************/
4925
4926 uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4927 {
4928         if(!large_file_format)
4929                 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
4930         else
4931                 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4932 }
4933
4934 /****************************************************************************
4935  Get a lock count, dealing with large count requests.
4936 ****************************************************************************/
4937
4938 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4939 {
4940         SMB_BIG_UINT count = 0;
4941
4942         if(!large_file_format) {
4943                 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4944         } else {
4945
4946 #if defined(HAVE_LONGLONG)
4947                 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4948                         ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4949 #else /* HAVE_LONGLONG */
4950
4951                 /*
4952                  * NT4.x seems to be broken in that it sends large file (64 bit)
4953                  * lockingX calls even if the CAP_LARGE_FILES was *not*
4954                  * negotiated. For boxes without large unsigned ints truncate the
4955                  * lock count by dropping the top 32 bits.
4956                  */
4957
4958                 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4959                         DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4960                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4961                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4962                                 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4963                 }
4964
4965                 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4966 #endif /* HAVE_LONGLONG */
4967         }
4968
4969         return count;
4970 }
4971
4972 #if !defined(HAVE_LONGLONG)
4973 /****************************************************************************
4974  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4975 ****************************************************************************/
4976
4977 static uint32 map_lock_offset(uint32 high, uint32 low)
4978 {
4979         unsigned int i;
4980         uint32 mask = 0;
4981         uint32 highcopy = high;
4982  
4983         /*
4984          * Try and find out how many significant bits there are in high.
4985          */
4986  
4987         for(i = 0; highcopy; i++)
4988                 highcopy >>= 1;
4989  
4990         /*
4991          * We use 31 bits not 32 here as POSIX
4992          * lock offsets may not be negative.
4993          */
4994  
4995         mask = (~0) << (31 - i);
4996  
4997         if(low & mask)
4998                 return 0; /* Fail. */
4999  
5000         high <<= (31 - i);
5001  
5002         return (high|low);
5003 }
5004 #endif /* !defined(HAVE_LONGLONG) */
5005
5006 /****************************************************************************
5007  Get a lock offset, dealing with large offset requests.
5008 ****************************************************************************/
5009
5010 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
5011 {
5012         SMB_BIG_UINT offset = 0;
5013
5014         *err = False;
5015
5016         if(!large_file_format) {
5017                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
5018         } else {
5019
5020 #if defined(HAVE_LONGLONG)
5021                 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
5022                                 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
5023 #else /* HAVE_LONGLONG */
5024
5025                 /*
5026                  * NT4.x seems to be broken in that it sends large file (64 bit)
5027                  * lockingX calls even if the CAP_LARGE_FILES was *not*
5028                  * negotiated. For boxes without large unsigned ints mangle the
5029                  * lock offset by mapping the top 32 bits onto the lower 32.
5030                  */
5031       
5032                 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
5033                         uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5034                         uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
5035                         uint32 new_low = 0;
5036
5037                         if((new_low = map_lock_offset(high, low)) == 0) {
5038                                 *err = True;
5039                                 return (SMB_BIG_UINT)-1;
5040                         }
5041
5042                         DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
5043                                 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
5044                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
5045                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
5046                 }
5047
5048                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5049 #endif /* HAVE_LONGLONG */
5050         }
5051
5052         return offset;
5053 }
5054
5055 /****************************************************************************
5056  Reply to a lockingX request.
5057 ****************************************************************************/
5058
5059 int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
5060                    int length, int bufsize)
5061 {
5062         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
5063         unsigned char locktype = CVAL(inbuf,smb_vwv3);
5064         unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
5065         uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
5066         uint16 num_locks = SVAL(inbuf,smb_vwv7);
5067         SMB_BIG_UINT count = 0, offset = 0;
5068         uint32 lock_pid;
5069         int32 lock_timeout = IVAL(inbuf,smb_vwv4);
5070         int i;
5071         char *data;
5072         BOOL large_file_format =
5073                 (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
5074         BOOL err;
5075         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5076
5077         START_PROFILE(SMBlockingX);
5078         
5079         CHECK_FSP(fsp,conn);
5080         
5081         data = smb_buf(inbuf);
5082
5083         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
5084                 /* we don't support these - and CANCEL_LOCK makes w2k
5085                    and XP reboot so I don't really want to be
5086                    compatible! (tridge) */
5087                 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
5088         }
5089         
5090         /* Check if this is an oplock break on a file
5091            we have granted an oplock on.
5092         */
5093         if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
5094                 /* Client can insist on breaking to none. */
5095                 BOOL break_to_none = (oplocklevel == 0);
5096                 BOOL result;
5097
5098                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
5099                          "for fnum = %d\n", (unsigned int)oplocklevel,
5100                          fsp->fnum ));
5101
5102                 /*
5103                  * Make sure we have granted an exclusive or batch oplock on
5104                  * this file.
5105                  */
5106                 
5107                 if (fsp->oplock_type == 0) {
5108
5109                         /* The Samba4 nbench simulator doesn't understand
5110                            the difference between break to level2 and break
5111                            to none from level2 - it sends oplock break
5112                            replies in both cases. Don't keep logging an error
5113                            message here - just ignore it. JRA. */
5114
5115                         DEBUG(5,("reply_lockingX: Error : oplock break from "
5116                                  "client for fnum = %d (oplock=%d) and no "
5117                                  "oplock granted on this file (%s).\n",
5118                                  fsp->fnum, fsp->oplock_type, fsp->fsp_name));
5119
5120                         /* if this is a pure oplock break request then don't
5121                          * send a reply */
5122                         if (num_locks == 0 && num_ulocks == 0) {
5123                                 END_PROFILE(SMBlockingX);
5124                                 return -1;
5125                         } else {
5126                                 END_PROFILE(SMBlockingX);
5127                                 return ERROR_DOS(ERRDOS,ERRlock);
5128                         }
5129                 }
5130
5131                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
5132                     (break_to_none)) {
5133                         result = remove_oplock(fsp);
5134                 } else {
5135                         result = downgrade_oplock(fsp);
5136                 }
5137                 
5138                 if (!result) {
5139                         DEBUG(0, ("reply_lockingX: error in removing "
5140                                   "oplock on file %s\n", fsp->fsp_name));
5141                         /* Hmmm. Is this panic justified? */
5142                         smb_panic("internal tdb error");
5143                 }
5144
5145                 reply_to_oplock_break_requests(fsp);
5146
5147                 /* if this is a pure oplock break request then don't send a
5148                  * reply */
5149                 if (num_locks == 0 && num_ulocks == 0) {
5150                         /* Sanity check - ensure a pure oplock break is not a
5151                            chained request. */
5152                         if(CVAL(inbuf,smb_vwv0) != 0xff)
5153                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
5154                                          "break is a chained %d request !\n",
5155                                          (unsigned int)CVAL(inbuf,smb_vwv0) ));
5156                         END_PROFILE(SMBlockingX);
5157                         return -1;
5158                 }
5159         }
5160
5161         /*
5162          * We do this check *after* we have checked this is not a oplock break
5163          * response message. JRA.
5164          */
5165         
5166         release_level_2_oplocks_on_change(fsp);
5167         
5168         /* Data now points at the beginning of the list
5169            of smb_unlkrng structs */
5170         for(i = 0; i < (int)num_ulocks; i++) {
5171                 lock_pid = get_lock_pid( data, i, large_file_format);
5172                 count = get_lock_count( data, i, large_file_format);
5173                 offset = get_lock_offset( data, i, large_file_format, &err);
5174                 
5175                 /*
5176                  * There is no error code marked "stupid client bug".... :-).
5177                  */
5178                 if(err) {
5179                         END_PROFILE(SMBlockingX);
5180                         return ERROR_DOS(ERRDOS,ERRnoaccess);
5181                 }
5182
5183                 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
5184                           "pid %u, file %s\n", (double)offset, (double)count,
5185                           (unsigned int)lock_pid, fsp->fsp_name ));
5186                 
5187                 status = do_unlock(fsp,
5188                                 lock_pid,
5189                                 count,
5190                                 offset,
5191                                 WINDOWS_LOCK);
5192
5193                 if (NT_STATUS_V(status)) {
5194                         END_PROFILE(SMBlockingX);
5195                         return ERROR_NT(status);
5196                 }
5197         }
5198
5199         /* Setup the timeout in seconds. */
5200
5201         if (!lp_blocking_locks(SNUM(conn))) {
5202                 lock_timeout = 0;
5203         }
5204         
5205         /* Now do any requested locks */
5206         data += ((large_file_format ? 20 : 10)*num_ulocks);
5207         
5208         /* Data now points at the beginning of the list
5209            of smb_lkrng structs */
5210         
5211         for(i = 0; i < (int)num_locks; i++) {
5212                 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
5213                                 READ_LOCK:WRITE_LOCK);
5214                 lock_pid = get_lock_pid( data, i, large_file_format);
5215                 count = get_lock_count( data, i, large_file_format);
5216                 offset = get_lock_offset( data, i, large_file_format, &err);
5217                 
5218                 /*
5219                  * There is no error code marked "stupid client bug".... :-).
5220                  */
5221                 if(err) {
5222                         END_PROFILE(SMBlockingX);
5223                         return ERROR_DOS(ERRDOS,ERRnoaccess);
5224                 }
5225                 
5226                 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
5227                           "%u, file %s timeout = %d\n", (double)offset,
5228                           (double)count, (unsigned int)lock_pid,
5229                           fsp->fsp_name, (int)lock_timeout ));
5230                 
5231                 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
5232                         if (lp_blocking_locks(SNUM(conn))) {
5233
5234                                 /* Schedule a message to ourselves to
5235                                    remove the blocking lock record and
5236                                    return the right error. */
5237
5238                                 if (!blocking_lock_cancel(fsp,
5239                                                 lock_pid,
5240                                                 offset,
5241                                                 count,
5242                                                 WINDOWS_LOCK,
5243                                                 locktype,
5244                                                 NT_STATUS_FILE_LOCK_CONFLICT)) {
5245                                         END_PROFILE(SMBlockingX);
5246                                         return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
5247                                 }
5248                         }
5249                         /* Remove a matching pending lock. */
5250                         status = do_lock_cancel(fsp,
5251                                                 lock_pid,
5252                                                 count,
5253                                                 offset,
5254                                                 WINDOWS_LOCK);
5255                 } else {
5256                         BOOL blocking_lock = lock_timeout ? True : False;
5257                         BOOL defer_lock = False;
5258                         struct byte_range_lock *br_lck;
5259
5260                         br_lck = do_lock(fsp,
5261                                         lock_pid,
5262                                         count,
5263                                         offset, 
5264                                         lock_type,
5265                                         WINDOWS_LOCK,
5266                                         blocking_lock,
5267                                         &status);
5268
5269                         if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5270                                 /* Windows internal resolution for blocking locks seems
5271                                    to be about 200ms... Don't wait for less than that. JRA. */
5272                                 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
5273                                         lock_timeout = lp_lock_spin_time();
5274                                 }
5275                                 defer_lock = True;
5276                         }
5277
5278                         /* This heuristic seems to match W2K3 very well. If a
5279                            lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
5280                            it pretends we asked for a timeout of between 150 - 300 milliseconds as
5281                            far as I can tell. Replacement for do_lock_spin(). JRA. */
5282
5283                         if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
5284                                         NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
5285                                 defer_lock = True;
5286                                 lock_timeout = lp_lock_spin_time();
5287                         }
5288
5289                         if (br_lck && defer_lock) {
5290                                 /*
5291                                  * A blocking lock was requested. Package up
5292                                  * this smb into a queued request and push it
5293                                  * onto the blocking lock queue.
5294                                  */
5295                                 if(push_blocking_lock_request(br_lck,
5296                                                         inbuf, length,
5297                                                         fsp,
5298                                                         lock_timeout,
5299                                                         i,
5300                                                         lock_pid,
5301                                                         lock_type,
5302                                                         WINDOWS_LOCK,
5303                                                         offset,
5304                                                         count)) {
5305                                         TALLOC_FREE(br_lck);
5306                                         END_PROFILE(SMBlockingX);
5307                                         return -1;
5308                                 }
5309                         }
5310
5311                         TALLOC_FREE(br_lck);
5312                 }
5313
5314                 if (NT_STATUS_V(status)) {
5315                         END_PROFILE(SMBlockingX);
5316                         return ERROR_NT(status);
5317                 }
5318         }
5319         
5320         /* If any of the above locks failed, then we must unlock
5321            all of the previous locks (X/Open spec). */
5322
5323         if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
5324                         (i != num_locks) &&
5325                         (num_locks != 0)) {
5326                 /*
5327                  * Ensure we don't do a remove on the lock that just failed,
5328                  * as under POSIX rules, if we have a lock already there, we
5329                  * will delete it (and we shouldn't) .....
5330                  */
5331                 for(i--; i >= 0; i--) {
5332                         lock_pid = get_lock_pid( data, i, large_file_format);
5333                         count = get_lock_count( data, i, large_file_format);
5334                         offset = get_lock_offset( data, i, large_file_format,
5335                                                   &err);
5336                         
5337                         /*
5338                          * There is no error code marked "stupid client
5339                          * bug".... :-).
5340                          */
5341                         if(err) {
5342                                 END_PROFILE(SMBlockingX);
5343                                 return ERROR_DOS(ERRDOS,ERRnoaccess);
5344                         }
5345                         
5346                         do_unlock(fsp,
5347                                 lock_pid,
5348                                 count,
5349                                 offset,
5350                                 WINDOWS_LOCK);
5351                 }
5352                 END_PROFILE(SMBlockingX);
5353                 return ERROR_NT(status);
5354         }
5355
5356         set_message(outbuf,2,0,True);
5357         
5358         DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5359                   fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
5360         
5361         END_PROFILE(SMBlockingX);
5362         return chain_reply(inbuf,outbuf,length,bufsize);
5363 }
5364
5365 #undef DBGC_CLASS
5366 #define DBGC_CLASS DBGC_ALL
5367
5368 /****************************************************************************
5369  Reply to a SMBreadbmpx (read block multiplex) request.
5370 ****************************************************************************/
5371
5372 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5373 {
5374         ssize_t nread = -1;
5375         ssize_t total_read;
5376         char *data;
5377         SMB_OFF_T startpos;
5378         int outsize;
5379         size_t maxcount;
5380         int max_per_packet;
5381         size_t tcount;
5382         int pad;
5383         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5384         START_PROFILE(SMBreadBmpx);
5385
5386         /* this function doesn't seem to work - disable by default */
5387         if (!lp_readbmpx()) {
5388                 END_PROFILE(SMBreadBmpx);
5389                 return ERROR_DOS(ERRSRV,ERRuseSTD);
5390         }
5391
5392         outsize = set_message(outbuf,8,0,True);
5393
5394         CHECK_FSP(fsp,conn);
5395         if (!CHECK_READ(fsp,inbuf)) {
5396                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5397         }
5398
5399         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5400         maxcount = SVAL(inbuf,smb_vwv3);
5401
5402         data = smb_buf(outbuf);
5403         pad = ((long)data)%4;
5404         if (pad)
5405                 pad = 4 - pad;
5406         data += pad;
5407
5408         max_per_packet = bufsize-(outsize+pad);
5409         tcount = maxcount;
5410         total_read = 0;
5411
5412         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5413                 END_PROFILE(SMBreadBmpx);
5414                 return ERROR_DOS(ERRDOS,ERRlock);
5415         }
5416
5417         do {
5418                 size_t N = MIN(max_per_packet,tcount-total_read);
5419   
5420                 nread = read_file(fsp,data,startpos,N);
5421
5422                 if (nread <= 0)
5423                         nread = 0;
5424
5425                 if (nread < (ssize_t)N)
5426                         tcount = total_read + nread;
5427
5428                 set_message(outbuf,8,nread+pad,False);
5429                 SIVAL(outbuf,smb_vwv0,startpos);
5430                 SSVAL(outbuf,smb_vwv2,tcount);
5431                 SSVAL(outbuf,smb_vwv6,nread);
5432                 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5433
5434                 show_msg(outbuf);
5435                 if (!send_smb(smbd_server_fd(),outbuf))
5436                         exit_server_cleanly("reply_readbmpx: send_smb failed.");
5437
5438                 total_read += nread;
5439                 startpos += nread;
5440         } while (total_read < (ssize_t)tcount);
5441
5442         END_PROFILE(SMBreadBmpx);
5443         return(-1);
5444 }
5445
5446 /****************************************************************************
5447  Reply to a SMBsetattrE.
5448 ****************************************************************************/
5449
5450 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5451 {
5452         struct utimbuf unix_times;
5453         int outsize = 0;
5454         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5455         START_PROFILE(SMBsetattrE);
5456
5457         outsize = set_message(outbuf,0,0,False);
5458
5459         if(!fsp || (fsp->conn != conn)) {
5460                 END_PROFILE(SMBsetattrE);
5461                 return ERROR_DOS(ERRDOS,ERRbadfid);
5462         }
5463
5464         /*
5465          * Convert the DOS times into unix times. Ignore create
5466          * time as UNIX can't set this.
5467          */
5468
5469         unix_times.actime = srv_make_unix_date2(inbuf+smb_vwv3);
5470         unix_times.modtime = srv_make_unix_date2(inbuf+smb_vwv5);
5471   
5472         /* 
5473          * Patch from Ray Frush <frush@engr.colostate.edu>
5474          * Sometimes times are sent as zero - ignore them.
5475          */
5476
5477         if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5478                 /* Ignore request */
5479                 if( DEBUGLVL( 3 ) ) {
5480                         dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5481                         dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5482                 }
5483                 END_PROFILE(SMBsetattrE);
5484                 return(outsize);
5485         } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5486                 /* set modify time = to access time if modify time was unset */
5487                 unix_times.modtime = unix_times.actime;
5488         }
5489
5490         /* Set the date on this file */
5491         /* Should we set pending modtime here ? JRA */
5492         if(file_utime(conn, fsp->fsp_name, &unix_times)) {
5493                 END_PROFILE(SMBsetattrE);
5494                 return ERROR_DOS(ERRDOS,ERRnoaccess);
5495         }
5496   
5497         DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
5498                 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
5499
5500         END_PROFILE(SMBsetattrE);
5501         return(outsize);
5502 }
5503
5504
5505 /* Back from the dead for OS/2..... JRA. */
5506
5507 /****************************************************************************
5508  Reply to a SMBwritebmpx (write block multiplex primary) request.
5509 ****************************************************************************/
5510
5511 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5512 {
5513         size_t numtowrite;
5514         ssize_t nwritten = -1;
5515         int outsize = 0;
5516         SMB_OFF_T startpos;
5517         size_t tcount;
5518         BOOL write_through;
5519         int smb_doff;
5520         char *data;
5521         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5522         START_PROFILE(SMBwriteBmpx);
5523
5524         CHECK_FSP(fsp,conn);
5525         if (!CHECK_WRITE(fsp)) {
5526                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5527         }
5528         if (HAS_CACHED_ERROR(fsp)) {
5529                 return(CACHED_ERROR(fsp));
5530         }
5531
5532         tcount = SVAL(inbuf,smb_vwv1);
5533         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
5534         write_through = BITSETW(inbuf+smb_vwv7,0);
5535         numtowrite = SVAL(inbuf,smb_vwv10);
5536         smb_doff = SVAL(inbuf,smb_vwv11);
5537
5538         data = smb_base(inbuf) + smb_doff;
5539
5540         /* If this fails we need to send an SMBwriteC response,
5541                 not an SMBwritebmpx - set this up now so we don't forget */
5542         SCVAL(outbuf,smb_com,SMBwritec);
5543
5544         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
5545                 END_PROFILE(SMBwriteBmpx);
5546                 return(ERROR_DOS(ERRDOS,ERRlock));
5547         }
5548
5549         nwritten = write_file(fsp,data,startpos,numtowrite);
5550
5551         sync_file(conn, fsp, write_through);
5552   
5553         if(nwritten < (ssize_t)numtowrite) {
5554                 END_PROFILE(SMBwriteBmpx);
5555                 return(UNIXERROR(ERRHRD,ERRdiskfull));
5556         }
5557
5558         /* If the maximum to be written to this file
5559                 is greater than what we just wrote then set
5560                 up a secondary struct to be attached to this
5561                 fd, we will use this to cache error messages etc. */
5562
5563         if((ssize_t)tcount > nwritten) {
5564                 write_bmpx_struct *wbms;
5565                 if(fsp->wbmpx_ptr != NULL)
5566                         wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5567                 else
5568                         wbms = SMB_MALLOC_P(write_bmpx_struct);
5569                 if(!wbms) {
5570                         DEBUG(0,("Out of memory in reply_readmpx\n"));
5571                         END_PROFILE(SMBwriteBmpx);
5572                         return(ERROR_DOS(ERRSRV,ERRnoresource));
5573                 }
5574                 wbms->wr_mode = write_through;
5575                 wbms->wr_discard = False; /* No errors yet */
5576                 wbms->wr_total_written = nwritten;
5577                 wbms->wr_errclass = 0;
5578                 wbms->wr_error = 0;
5579                 fsp->wbmpx_ptr = wbms;
5580         }
5581
5582         /* We are returning successfully, set the message type back to
5583                 SMBwritebmpx */
5584         SCVAL(outbuf,smb_com,SMBwriteBmpx);
5585   
5586         outsize = set_message(outbuf,1,0,True);
5587   
5588         SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5589   
5590         DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5591                         fsp->fnum, (int)numtowrite, (int)nwritten ) );
5592
5593         if (write_through && tcount==nwritten) {
5594                 /* We need to send both a primary and a secondary response */
5595                 smb_setlen(outbuf,outsize - 4);
5596                 show_msg(outbuf);
5597                 if (!send_smb(smbd_server_fd(),outbuf))
5598                         exit_server_cleanly("reply_writebmpx: send_smb failed.");
5599
5600                 /* Now the secondary */
5601                 outsize = set_message(outbuf,1,0,True);
5602                 SCVAL(outbuf,smb_com,SMBwritec);
5603                 SSVAL(outbuf,smb_vwv0,nwritten);
5604         }
5605
5606         END_PROFILE(SMBwriteBmpx);
5607         return(outsize);
5608 }
5609
5610 /****************************************************************************
5611  Reply to a SMBwritebs (write block multiplex secondary) request.
5612 ****************************************************************************/
5613
5614 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5615 {
5616         size_t numtowrite;
5617         ssize_t nwritten = -1;
5618         int outsize = 0;
5619         SMB_OFF_T startpos;
5620         size_t tcount;
5621         BOOL write_through;
5622         int smb_doff;
5623         char *data;
5624         write_bmpx_struct *wbms;
5625         BOOL send_response = False; 
5626         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5627         START_PROFILE(SMBwriteBs);
5628
5629         CHECK_FSP(fsp,conn);
5630         if (!CHECK_WRITE(fsp)) {
5631                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5632         }
5633
5634         tcount = SVAL(inbuf,smb_vwv1);
5635         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5636         numtowrite = SVAL(inbuf,smb_vwv6);
5637         smb_doff = SVAL(inbuf,smb_vwv7);
5638
5639         data = smb_base(inbuf) + smb_doff;
5640
5641         /* We need to send an SMBwriteC response, not an SMBwritebs */
5642         SCVAL(outbuf,smb_com,SMBwritec);
5643
5644         /* This fd should have an auxiliary struct attached,
5645                 check that it does */
5646         wbms = fsp->wbmpx_ptr;
5647         if(!wbms) {
5648                 END_PROFILE(SMBwriteBs);
5649                 return(-1);
5650         }
5651
5652         /* If write through is set we can return errors, else we must cache them */
5653         write_through = wbms->wr_mode;
5654
5655         /* Check for an earlier error */
5656         if(wbms->wr_discard) {
5657                 END_PROFILE(SMBwriteBs);
5658                 return -1; /* Just discard the packet */
5659         }
5660
5661         nwritten = write_file(fsp,data,startpos,numtowrite);
5662
5663         sync_file(conn, fsp, write_through);
5664   
5665         if (nwritten < (ssize_t)numtowrite) {
5666                 if(write_through) {
5667                         /* We are returning an error - we can delete the aux struct */
5668                         if (wbms)
5669                                 free((char *)wbms);
5670                         fsp->wbmpx_ptr = NULL;
5671                         END_PROFILE(SMBwriteBs);
5672                         return(ERROR_DOS(ERRHRD,ERRdiskfull));
5673                 }
5674                 wbms->wr_errclass = ERRHRD;
5675                 wbms->wr_error = ERRdiskfull;
5676                 wbms->wr_status = NT_STATUS_DISK_FULL;
5677                 wbms->wr_discard = True;
5678                 END_PROFILE(SMBwriteBs);
5679                 return -1;
5680         }
5681
5682         /* Increment the total written, if this matches tcount
5683                 we can discard the auxiliary struct (hurrah !) and return a writeC */
5684         wbms->wr_total_written += nwritten;
5685         if(wbms->wr_total_written >= tcount) {
5686                 if (write_through) {
5687                         outsize = set_message(outbuf,1,0,True);
5688                         SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);    
5689                         send_response = True;
5690                 }
5691
5692                 free((char *)wbms);
5693                 fsp->wbmpx_ptr = NULL;
5694         }
5695
5696         if(send_response) {
5697                 END_PROFILE(SMBwriteBs);
5698                 return(outsize);
5699         }
5700
5701         END_PROFILE(SMBwriteBs);
5702         return(-1);
5703 }
5704
5705 /****************************************************************************
5706  Reply to a SMBgetattrE.
5707 ****************************************************************************/
5708
5709 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5710 {
5711         SMB_STRUCT_STAT sbuf;
5712         int outsize = 0;
5713         int mode;
5714         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5715         START_PROFILE(SMBgetattrE);
5716
5717         outsize = set_message(outbuf,11,0,True);
5718
5719         if(!fsp || (fsp->conn != conn)) {
5720                 END_PROFILE(SMBgetattrE);
5721                 return ERROR_DOS(ERRDOS,ERRbadfid);
5722         }
5723
5724         /* Do an fstat on this file */
5725         if(fsp_stat(fsp, &sbuf)) {
5726                 END_PROFILE(SMBgetattrE);
5727                 return(UNIXERROR(ERRDOS,ERRnoaccess));
5728         }
5729   
5730         mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5731   
5732         /*
5733          * Convert the times into dos times. Set create
5734          * date to be last modify date as UNIX doesn't save
5735          * this.
5736          */
5737
5738         srv_put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5739         srv_put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5740         /* Should we check pending modtime here ? JRA */
5741         srv_put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5742
5743         if (mode & aDIR) {
5744                 SIVAL(outbuf,smb_vwv6,0);
5745                 SIVAL(outbuf,smb_vwv8,0);
5746         } else {
5747                 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
5748                 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5749                 SIVAL(outbuf,smb_vwv8,allocation_size);
5750         }
5751         SSVAL(outbuf,smb_vwv10, mode);
5752   
5753         DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5754   
5755         END_PROFILE(SMBgetattrE);
5756         return(outsize);
5757 }