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