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