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