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