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