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