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