r4143: Make strict locking an enum. Auto means use oplock optimization.
[ira/wip.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)) {
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)) {
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)) {
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)) {
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, WRITE_LOCK)) {
2443                 END_PROFILE(SMBwriteunlock);
2444                 return ERROR_DOS(ERRDOS,ERRlock);
2445         }
2446
2447         /* The special X/Open SMB protocol handling of
2448            zero length writes is *NOT* done for
2449            this call */
2450         if(numtowrite == 0)
2451                 nwritten = 0;
2452         else
2453                 nwritten = write_file(fsp,data,startpos,numtowrite);
2454   
2455         if (lp_syncalways(SNUM(conn)))
2456                 sync_file(conn,fsp);
2457
2458         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2459                 END_PROFILE(SMBwriteunlock);
2460                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2461         }
2462
2463         if (numtowrite) {
2464                 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite, 
2465                                    (SMB_BIG_UINT)startpos);
2466                 if (NT_STATUS_V(status)) {
2467                         END_PROFILE(SMBwriteunlock);
2468                         return ERROR_NT(status);
2469                 }
2470         }
2471         
2472         outsize = set_message(outbuf,1,0,True);
2473         
2474         SSVAL(outbuf,smb_vwv0,nwritten);
2475         
2476         DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2477                  fsp->fnum, (int)numtowrite, (int)nwritten));
2478         
2479         END_PROFILE(SMBwriteunlock);
2480         return outsize;
2481 }
2482
2483 /****************************************************************************
2484  Reply to a write.
2485 ****************************************************************************/
2486
2487 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2488 {
2489         size_t numtowrite;
2490         ssize_t nwritten = -1;
2491         SMB_OFF_T startpos;
2492         char *data;
2493         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2494         int outsize = 0;
2495         START_PROFILE(SMBwrite);
2496
2497         /* If it's an IPC, pass off the pipe handler. */
2498         if (IS_IPC(conn)) {
2499                 END_PROFILE(SMBwrite);
2500                 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2501         }
2502
2503         CHECK_FSP(fsp,conn);
2504         CHECK_WRITE(fsp);
2505
2506         numtowrite = SVAL(inbuf,smb_vwv1);
2507         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2508         data = smb_buf(inbuf) + 3;
2509   
2510         if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2511                 END_PROFILE(SMBwrite);
2512                 return ERROR_DOS(ERRDOS,ERRlock);
2513         }
2514
2515         /*
2516          * X/Open SMB protocol says that if smb_vwv1 is
2517          * zero then the file size should be extended or
2518          * truncated to the size given in smb_vwv[2-3].
2519          */
2520
2521         if(numtowrite == 0) {
2522                 /*
2523                  * This is actually an allocate call, and set EOF. JRA.
2524                  */
2525                 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2526                 if (nwritten < 0) {
2527                         END_PROFILE(SMBwrite);
2528                         return ERROR_NT(NT_STATUS_DISK_FULL);
2529                 }
2530                 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2531                 if (nwritten < 0) {
2532                         END_PROFILE(SMBwrite);
2533                         return ERROR_NT(NT_STATUS_DISK_FULL);
2534                 }
2535         } else
2536                 nwritten = write_file(fsp,data,startpos,numtowrite);
2537   
2538         if (lp_syncalways(SNUM(conn)))
2539                 sync_file(conn,fsp);
2540
2541         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2542                 END_PROFILE(SMBwrite);
2543                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2544         }
2545
2546         outsize = set_message(outbuf,1,0,True);
2547   
2548         SSVAL(outbuf,smb_vwv0,nwritten);
2549
2550         if (nwritten < (ssize_t)numtowrite) {
2551                 SCVAL(outbuf,smb_rcls,ERRHRD);
2552                 SSVAL(outbuf,smb_err,ERRdiskfull);      
2553         }
2554   
2555         DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2556
2557         END_PROFILE(SMBwrite);
2558         return(outsize);
2559 }
2560
2561 /****************************************************************************
2562  Reply to a write and X.
2563 ****************************************************************************/
2564
2565 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2566 {
2567         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2568         SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2569         size_t numtowrite = SVAL(inbuf,smb_vwv10);
2570         BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2571         ssize_t nwritten = -1;
2572         unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2573         unsigned int smblen = smb_len(inbuf);
2574         char *data;
2575         BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2576         START_PROFILE(SMBwriteX);
2577
2578         /* If it's an IPC, pass off the pipe handler. */
2579         if (IS_IPC(conn)) {
2580                 END_PROFILE(SMBwriteX);
2581                 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2582         }
2583
2584         CHECK_FSP(fsp,conn);
2585         CHECK_WRITE(fsp);
2586
2587         /* Deal with possible LARGE_WRITEX */
2588         if (large_writeX)
2589                 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2590
2591         if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2592                 END_PROFILE(SMBwriteX);
2593                 return ERROR_DOS(ERRDOS,ERRbadmem);
2594         }
2595
2596         data = smb_base(inbuf) + smb_doff;
2597
2598         if(CVAL(inbuf,smb_wct) == 14) {
2599 #ifdef LARGE_SMB_OFF_T
2600                 /*
2601                  * This is a large offset (64 bit) write.
2602                  */
2603                 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2604
2605 #else /* !LARGE_SMB_OFF_T */
2606
2607                 /*
2608                  * Ensure we haven't been sent a >32 bit offset.
2609                  */
2610
2611                 if(IVAL(inbuf,smb_vwv12) != 0) {
2612                         DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2613 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2614                         END_PROFILE(SMBwriteX);
2615                         return ERROR_DOS(ERRDOS,ERRbadaccess);
2616                 }
2617
2618 #endif /* LARGE_SMB_OFF_T */
2619         }
2620
2621         if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2622                 END_PROFILE(SMBwriteX);
2623                 return ERROR_DOS(ERRDOS,ERRlock);
2624         }
2625
2626         /* X/Open SMB protocol says that, unlike SMBwrite
2627         if the length is zero then NO truncation is
2628         done, just a write of zero. To truncate a file,
2629         use SMBwrite. */
2630
2631         if(numtowrite == 0)
2632                 nwritten = 0;
2633         else
2634                 nwritten = write_file(fsp,data,startpos,numtowrite);
2635   
2636         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2637                 END_PROFILE(SMBwriteX);
2638                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2639         }
2640
2641         set_message(outbuf,6,0,True);
2642   
2643         SSVAL(outbuf,smb_vwv2,nwritten);
2644         if (large_writeX)
2645                 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2646
2647         if (nwritten < (ssize_t)numtowrite) {
2648                 SCVAL(outbuf,smb_rcls,ERRHRD);
2649                 SSVAL(outbuf,smb_err,ERRdiskfull);      
2650         }
2651
2652         DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2653                 fsp->fnum, (int)numtowrite, (int)nwritten));
2654
2655         if (lp_syncalways(SNUM(conn)) || write_through)
2656                 sync_file(conn,fsp);
2657
2658         END_PROFILE(SMBwriteX);
2659         return chain_reply(inbuf,outbuf,length,bufsize);
2660 }
2661
2662 /****************************************************************************
2663  Reply to a lseek.
2664 ****************************************************************************/
2665
2666 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2667 {
2668         SMB_OFF_T startpos;
2669         SMB_OFF_T res= -1;
2670         int mode,umode;
2671         int outsize = 0;
2672         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2673         START_PROFILE(SMBlseek);
2674
2675         CHECK_FSP(fsp,conn);
2676
2677         flush_write_cache(fsp, SEEK_FLUSH);
2678
2679         mode = SVAL(inbuf,smb_vwv1) & 3;
2680         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2681         startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2682
2683         switch (mode) {
2684                 case 0:
2685                         umode = SEEK_SET;
2686                         res = startpos;
2687                         break;
2688                 case 1:
2689                         umode = SEEK_CUR;
2690                         res = fsp->pos + startpos;
2691                         break;
2692                 case 2:
2693                         umode = SEEK_END;
2694                         break;
2695                 default:
2696                         umode = SEEK_SET;
2697                         res = startpos;
2698                         break;
2699         }
2700
2701         if (umode == SEEK_END) {
2702                 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2703                         if(errno == EINVAL) {
2704                                 SMB_OFF_T current_pos = startpos;
2705                                 SMB_STRUCT_STAT sbuf;
2706
2707                                 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2708                                         END_PROFILE(SMBlseek);
2709                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2710                                 }
2711
2712                                 current_pos += sbuf.st_size;
2713                                 if(current_pos < 0)
2714                                         res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2715                         }
2716                 }
2717
2718                 if(res == -1) {
2719                         END_PROFILE(SMBlseek);
2720                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2721                 }
2722         }
2723
2724         fsp->pos = res;
2725   
2726         outsize = set_message(outbuf,2,0,True);
2727         SIVAL(outbuf,smb_vwv0,res);
2728   
2729         DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2730                 fsp->fnum, (double)startpos, (double)res, mode));
2731
2732         END_PROFILE(SMBlseek);
2733         return(outsize);
2734 }
2735
2736 /****************************************************************************
2737  Reply to a flush.
2738 ****************************************************************************/
2739
2740 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2741 {
2742         int outsize = set_message(outbuf,0,0,True);
2743         uint16 fnum = SVAL(inbuf,smb_vwv0);
2744         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2745         START_PROFILE(SMBflush);
2746
2747         if (fnum != 0xFFFF)
2748                 CHECK_FSP(fsp,conn);
2749         
2750         if (!fsp) {
2751                 file_sync_all(conn);
2752         } else {
2753                 sync_file(conn,fsp);
2754         }
2755         
2756         DEBUG(3,("flush\n"));
2757         END_PROFILE(SMBflush);
2758         return(outsize);
2759 }
2760
2761 /****************************************************************************
2762  Reply to a exit.
2763 ****************************************************************************/
2764
2765 int reply_exit(connection_struct *conn, 
2766                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2767 {
2768         int outsize;
2769         START_PROFILE(SMBexit);
2770
2771         file_close_pid(SVAL(inbuf,smb_pid));
2772
2773         outsize = set_message(outbuf,0,0,True);
2774
2775         DEBUG(3,("exit\n"));
2776
2777         END_PROFILE(SMBexit);
2778         return(outsize);
2779 }
2780
2781 /****************************************************************************
2782  Reply to a close - has to deal with closing a directory opened by NT SMB's.
2783 ****************************************************************************/
2784
2785 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2786                 int dum_buffsize)
2787 {
2788         extern struct current_user current_user;
2789         int outsize = 0;
2790         time_t mtime;
2791         int32 eclass = 0, err = 0;
2792         files_struct *fsp = NULL;
2793         START_PROFILE(SMBclose);
2794
2795         outsize = set_message(outbuf,0,0,True);
2796
2797         /* If it's an IPC, pass off to the pipe handler. */
2798         if (IS_IPC(conn)) {
2799                 END_PROFILE(SMBclose);
2800                 return reply_pipe_close(conn, inbuf,outbuf);
2801         }
2802
2803         fsp = file_fsp(inbuf,smb_vwv0);
2804
2805         /*
2806          * We can only use CHECK_FSP if we know it's not a directory.
2807          */
2808
2809         if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2810                 END_PROFILE(SMBclose);
2811                 return ERROR_DOS(ERRDOS,ERRbadfid);
2812         }
2813
2814         if(fsp->is_directory) {
2815                 /*
2816                  * Special case - close NT SMB directory handle.
2817                  */
2818                 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2819                 close_file(fsp,True);
2820         } else {
2821                 /*
2822                  * Close ordinary file.
2823                  */
2824                 int close_err;
2825                 pstring file_name;
2826
2827                 /* Save the name for time set in close. */
2828                 pstrcpy( file_name, fsp->fsp_name);
2829
2830                 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2831                          fsp->fd, fsp->fnum,
2832                          conn->num_files_open));
2833  
2834                 /*
2835                  * close_file() returns the unix errno if an error
2836                  * was detected on close - normally this is due to
2837                  * a disk full error. If not then it was probably an I/O error.
2838                  */
2839  
2840                 if((close_err = close_file(fsp,True)) != 0) {
2841                         errno = close_err;
2842                         END_PROFILE(SMBclose);
2843                         return (UNIXERROR(ERRHRD,ERRgeneral));
2844                 }
2845
2846                 /*
2847                  * Now take care of any time sent in the close.
2848                  */
2849
2850                 mtime = make_unix_date3(inbuf+smb_vwv1);
2851                 
2852                 /* try and set the date */
2853                 set_filetime(conn, file_name, mtime);
2854
2855         }  
2856
2857         /* We have a cached error */
2858         if(eclass || err) {
2859                 END_PROFILE(SMBclose);
2860                 return ERROR_DOS(eclass,err);
2861         }
2862
2863         END_PROFILE(SMBclose);
2864         return(outsize);
2865 }
2866
2867 /****************************************************************************
2868  Reply to a writeclose (Core+ protocol).
2869 ****************************************************************************/
2870
2871 int reply_writeclose(connection_struct *conn,
2872                      char *inbuf,char *outbuf, int size, int dum_buffsize)
2873 {
2874         size_t numtowrite;
2875         ssize_t nwritten = -1;
2876         int outsize = 0;
2877         int close_err = 0;
2878         SMB_OFF_T startpos;
2879         char *data;
2880         time_t mtime;
2881         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2882         START_PROFILE(SMBwriteclose);
2883
2884         CHECK_FSP(fsp,conn);
2885         CHECK_WRITE(fsp);
2886
2887         numtowrite = SVAL(inbuf,smb_vwv1);
2888         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2889         mtime = make_unix_date3(inbuf+smb_vwv4);
2890         data = smb_buf(inbuf) + 1;
2891   
2892         if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2893                 END_PROFILE(SMBwriteclose);
2894                 return ERROR_DOS(ERRDOS,ERRlock);
2895         }
2896   
2897         nwritten = write_file(fsp,data,startpos,numtowrite);
2898
2899         set_filetime(conn, fsp->fsp_name,mtime);
2900   
2901         /*
2902          * More insanity. W2K only closes the file if writelen > 0.
2903          * JRA.
2904          */
2905
2906         if (numtowrite) {
2907                 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2908                         fsp->fsp_name ));
2909                 close_err = close_file(fsp,True);
2910         }
2911
2912         DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2913                  fsp->fnum, (int)numtowrite, (int)nwritten,
2914                  conn->num_files_open));
2915   
2916         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2917                 END_PROFILE(SMBwriteclose);
2918                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2919         }
2920  
2921         if(close_err != 0) {
2922                 errno = close_err;
2923                 END_PROFILE(SMBwriteclose);
2924                 return(UNIXERROR(ERRHRD,ERRgeneral));
2925         }
2926  
2927         outsize = set_message(outbuf,1,0,True);
2928   
2929         SSVAL(outbuf,smb_vwv0,nwritten);
2930         END_PROFILE(SMBwriteclose);
2931         return(outsize);
2932 }
2933
2934 /****************************************************************************
2935  Reply to a lock.
2936 ****************************************************************************/
2937
2938 int reply_lock(connection_struct *conn,
2939                char *inbuf,char *outbuf, int length, int dum_buffsize)
2940 {
2941         int outsize = set_message(outbuf,0,0,True);
2942         SMB_BIG_UINT count,offset;
2943         NTSTATUS status;
2944         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2945         BOOL my_lock_ctx = False;
2946
2947         START_PROFILE(SMBlock);
2948
2949         CHECK_FSP(fsp,conn);
2950
2951         release_level_2_oplocks_on_change(fsp);
2952
2953         count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2954         offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2955
2956         DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2957                  fsp->fd, fsp->fnum, (double)offset, (double)count));
2958
2959         status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
2960         if (NT_STATUS_V(status)) {
2961 #if 0
2962                 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
2963                 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2964                         /*
2965                          * A blocking lock was requested. Package up
2966                          * this smb into a queued request and push it
2967                          * onto the blocking lock queue.
2968                          */
2969                         if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2970                                 END_PROFILE(SMBlock);
2971                                 return -1;
2972                         }
2973                 }
2974 #endif
2975                 END_PROFILE(SMBlock);
2976                 return ERROR_NT(status);
2977         }
2978
2979         END_PROFILE(SMBlock);
2980         return(outsize);
2981 }
2982
2983 /****************************************************************************
2984  Reply to a unlock.
2985 ****************************************************************************/
2986
2987 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, 
2988                  int dum_buffsize)
2989 {
2990         int outsize = set_message(outbuf,0,0,True);
2991         SMB_BIG_UINT count,offset;
2992         NTSTATUS status;
2993         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2994         START_PROFILE(SMBunlock);
2995
2996         CHECK_FSP(fsp,conn);
2997         
2998         count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2999         offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3000         
3001         status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
3002         if (NT_STATUS_V(status)) {
3003                 END_PROFILE(SMBunlock);
3004                 return ERROR_NT(status);
3005         }
3006
3007         DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3008                     fsp->fd, fsp->fnum, (double)offset, (double)count ) );
3009         
3010         END_PROFILE(SMBunlock);
3011         return(outsize);
3012 }
3013
3014 /****************************************************************************
3015  Reply to a tdis.
3016 ****************************************************************************/
3017
3018 int reply_tdis(connection_struct *conn, 
3019                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3020 {
3021         int outsize = set_message(outbuf,0,0,True);
3022         uint16 vuid;
3023         START_PROFILE(SMBtdis);
3024
3025         vuid = SVAL(inbuf,smb_uid);
3026
3027         if (!conn) {
3028                 DEBUG(4,("Invalid connection in tdis\n"));
3029                 END_PROFILE(SMBtdis);
3030                 return ERROR_DOS(ERRSRV,ERRinvnid);
3031         }
3032
3033         conn->used = False;
3034
3035         close_cnum(conn,vuid);
3036   
3037         END_PROFILE(SMBtdis);
3038         return outsize;
3039 }
3040
3041 /****************************************************************************
3042  Reply to a echo.
3043 ****************************************************************************/
3044
3045 int reply_echo(connection_struct *conn,
3046                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3047 {
3048         int smb_reverb = SVAL(inbuf,smb_vwv0);
3049         int seq_num;
3050         unsigned int data_len = smb_buflen(inbuf);
3051         int outsize = set_message(outbuf,1,data_len,True);
3052         START_PROFILE(SMBecho);
3053
3054         if (data_len > BUFFER_SIZE) {
3055                 DEBUG(0,("reply_echo: data_len too large.\n"));
3056                 END_PROFILE(SMBecho);
3057                 return -1;
3058         }
3059
3060         /* copy any incoming data back out */
3061         if (data_len > 0)
3062                 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3063
3064         if (smb_reverb > 100) {
3065                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3066                 smb_reverb = 100;
3067         }
3068
3069         for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3070                 SSVAL(outbuf,smb_vwv0,seq_num);
3071
3072                 smb_setlen(outbuf,outsize - 4);
3073
3074                 if (!send_smb(smbd_server_fd(),outbuf))
3075                         exit_server("reply_echo: send_smb failed.");
3076         }
3077
3078         DEBUG(3,("echo %d times\n", smb_reverb));
3079
3080         smb_echo_count++;
3081
3082         END_PROFILE(SMBecho);
3083         return -1;
3084 }
3085
3086 /****************************************************************************
3087  Reply to a printopen.
3088 ****************************************************************************/
3089
3090 int reply_printopen(connection_struct *conn, 
3091                     char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3092 {
3093         int outsize = 0;
3094         files_struct *fsp;
3095         START_PROFILE(SMBsplopen);
3096         
3097         if (!CAN_PRINT(conn)) {
3098                 END_PROFILE(SMBsplopen);
3099                 return ERROR_DOS(ERRDOS,ERRnoaccess);
3100         }
3101
3102         /* Open for exclusive use, write only. */
3103         fsp = print_fsp_open(conn, NULL);
3104
3105         if (!fsp) {
3106                 END_PROFILE(SMBsplopen);
3107                 return(UNIXERROR(ERRDOS,ERRnoaccess));
3108         }
3109
3110         outsize = set_message(outbuf,1,0,True);
3111         SSVAL(outbuf,smb_vwv0,fsp->fnum);
3112   
3113         DEBUG(3,("openprint fd=%d fnum=%d\n",
3114                  fsp->fd, fsp->fnum));
3115
3116         END_PROFILE(SMBsplopen);
3117         return(outsize);
3118 }
3119
3120 /****************************************************************************
3121  Reply to a printclose.
3122 ****************************************************************************/
3123
3124 int reply_printclose(connection_struct *conn,
3125                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3126 {
3127         int outsize = set_message(outbuf,0,0,True);
3128         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3129         int close_err = 0;
3130         START_PROFILE(SMBsplclose);
3131
3132         CHECK_FSP(fsp,conn);
3133
3134         if (!CAN_PRINT(conn)) {
3135                 END_PROFILE(SMBsplclose);
3136                 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
3137         }
3138   
3139         DEBUG(3,("printclose fd=%d fnum=%d\n",
3140                  fsp->fd,fsp->fnum));
3141   
3142         close_err = close_file(fsp,True);
3143
3144         if(close_err != 0) {
3145                 errno = close_err;
3146                 END_PROFILE(SMBsplclose);
3147                 return(UNIXERROR(ERRHRD,ERRgeneral));
3148         }
3149
3150         END_PROFILE(SMBsplclose);
3151         return(outsize);
3152 }
3153
3154 /****************************************************************************
3155  Reply to a printqueue.
3156 ****************************************************************************/
3157
3158 int reply_printqueue(connection_struct *conn,
3159                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3160 {
3161         int outsize = set_message(outbuf,2,3,True);
3162         int max_count = SVAL(inbuf,smb_vwv0);
3163         int start_index = SVAL(inbuf,smb_vwv1);
3164         START_PROFILE(SMBsplretq);
3165
3166         /* we used to allow the client to get the cnum wrong, but that
3167            is really quite gross and only worked when there was only
3168            one printer - I think we should now only accept it if they
3169            get it right (tridge) */
3170         if (!CAN_PRINT(conn)) {
3171                 END_PROFILE(SMBsplretq);
3172                 return ERROR_DOS(ERRDOS,ERRnoaccess);
3173         }
3174
3175         SSVAL(outbuf,smb_vwv0,0);
3176         SSVAL(outbuf,smb_vwv1,0);
3177         SCVAL(smb_buf(outbuf),0,1);
3178         SSVAL(smb_buf(outbuf),1,0);
3179   
3180         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3181                  start_index, max_count));
3182
3183         {
3184                 print_queue_struct *queue = NULL;
3185                 print_status_struct status;
3186                 char *p = smb_buf(outbuf) + 3;
3187                 int count = print_queue_status(SNUM(conn), &queue, &status);
3188                 int num_to_get = ABS(max_count);
3189                 int first = (max_count>0?start_index:start_index+max_count+1);
3190                 int i;
3191
3192                 if (first >= count)
3193                         num_to_get = 0;
3194                 else
3195                         num_to_get = MIN(num_to_get,count-first);
3196     
3197
3198                 for (i=first;i<first+num_to_get;i++) {
3199                         put_dos_date2(p,0,queue[i].time);
3200                         SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3201                         SSVAL(p,5, queue[i].job);
3202                         SIVAL(p,7,queue[i].size);
3203                         SCVAL(p,11,0);
3204                         srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3205                         p += 28;
3206                 }
3207
3208                 if (count > 0) {
3209                         outsize = set_message(outbuf,2,28*count+3,False); 
3210                         SSVAL(outbuf,smb_vwv0,count);
3211                         SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3212                         SCVAL(smb_buf(outbuf),0,1);
3213                         SSVAL(smb_buf(outbuf),1,28*count);
3214                 }
3215
3216                 SAFE_FREE(queue);
3217           
3218                 DEBUG(3,("%d entries returned in queue\n",count));
3219         }
3220   
3221         END_PROFILE(SMBsplretq);
3222         return(outsize);
3223 }
3224
3225 /****************************************************************************
3226  Reply to a printwrite.
3227 ****************************************************************************/
3228
3229 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3230 {
3231         int numtowrite;
3232         int outsize = set_message(outbuf,0,0,True);
3233         char *data;
3234         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3235
3236         START_PROFILE(SMBsplwr);
3237   
3238         if (!CAN_PRINT(conn)) {
3239                 END_PROFILE(SMBsplwr);
3240                 return ERROR_DOS(ERRDOS,ERRnoaccess);
3241         }
3242
3243         CHECK_FSP(fsp,conn);
3244         CHECK_WRITE(fsp);
3245
3246         numtowrite = SVAL(smb_buf(inbuf),1);
3247         data = smb_buf(inbuf) + 3;
3248   
3249         if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3250                 END_PROFILE(SMBsplwr);
3251                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3252         }
3253
3254         DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3255   
3256         END_PROFILE(SMBsplwr);
3257         return(outsize);
3258 }
3259
3260 /****************************************************************************
3261  The guts of the mkdir command, split out so it may be called by the NT SMB
3262  code. 
3263 ****************************************************************************/
3264
3265 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3266 {
3267         BOOL bad_path = False;
3268         SMB_STRUCT_STAT sbuf;
3269         int ret= -1;
3270         
3271         unix_convert(directory,conn,0,&bad_path,&sbuf);
3272
3273         if( strchr_m(directory, ':')) {
3274                 return NT_STATUS_NOT_A_DIRECTORY;
3275         }
3276
3277         if (ms_has_wild(directory)) {
3278                 return NT_STATUS_OBJECT_NAME_INVALID;
3279         }
3280
3281         if (bad_path) {
3282                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3283         }
3284
3285         if (check_name(directory, conn))
3286                 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
3287         
3288         if (ret == -1) {
3289                 if(errno == ENOENT) {
3290                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3291                 }
3292                 return map_nt_error_from_unix(errno);
3293         }
3294         
3295         return NT_STATUS_OK;
3296 }
3297
3298 /****************************************************************************
3299  Reply to a mkdir.
3300 ****************************************************************************/
3301
3302 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3303 {
3304         pstring directory;
3305         int outsize;
3306         NTSTATUS status;
3307         START_PROFILE(SMBmkdir);
3308  
3309         srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3310         if (!NT_STATUS_IS_OK(status)) {
3311                 END_PROFILE(SMBmkdir);
3312                 return ERROR_NT(status);
3313         }
3314
3315         RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3316
3317         status = mkdir_internal(conn, directory);
3318         if (!NT_STATUS_IS_OK(status)) {
3319                 END_PROFILE(SMBmkdir);
3320                 return ERROR_NT(status);
3321         }
3322
3323         outsize = set_message(outbuf,0,0,True);
3324
3325         DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3326
3327         END_PROFILE(SMBmkdir);
3328         return(outsize);
3329 }
3330
3331 /****************************************************************************
3332  Static function used by reply_rmdir to delete an entire directory
3333  tree recursively. Return False on ok, True on fail.
3334 ****************************************************************************/
3335
3336 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3337 {
3338         const char *dname = NULL;
3339         BOOL ret = False;
3340         void *dirptr = OpenDir(conn, directory, False);
3341
3342         if(dirptr == NULL)
3343                 return True;
3344
3345         while((dname = ReadDirName(dirptr))) {
3346                 pstring fullname;
3347                 SMB_STRUCT_STAT st;
3348
3349                 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3350                         continue;
3351
3352                 /* Construct the full name. */
3353                 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3354                         errno = ENOMEM;
3355                         ret = True;
3356                         break;
3357                 }
3358
3359                 pstrcpy(fullname, directory);
3360                 pstrcat(fullname, "/");
3361                 pstrcat(fullname, dname);
3362
3363                 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3364                         ret = True;
3365                         break;
3366                 }
3367
3368                 if(st.st_mode & S_IFDIR) {
3369                         if(recursive_rmdir(conn, fullname)!=0) {
3370                                 ret = True;
3371                                 break;
3372                         }
3373                         if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3374                                 ret = True;
3375                                 break;
3376                         }
3377                 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3378                         ret = True;
3379                         break;
3380                 }
3381         }
3382         CloseDir(dirptr);
3383         return ret;
3384 }
3385
3386 /****************************************************************************
3387  The internals of the rmdir code - called elsewhere.
3388 ****************************************************************************/
3389
3390 BOOL rmdir_internals(connection_struct *conn, char *directory)
3391 {
3392         BOOL ok;
3393
3394         ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3395         if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3396                 /* 
3397                  * Check to see if the only thing in this directory are
3398                  * vetoed files/directories. If so then delete them and
3399                  * retry. If we fail to delete any of them (and we *don't*
3400                  * do a recursive delete) then fail the rmdir.
3401                  */
3402                 BOOL all_veto_files = True;
3403                 const char *dname;
3404                 void *dirptr = OpenDir(conn, directory, False);
3405
3406                 if(dirptr != NULL) {
3407                         int dirpos = TellDir(dirptr);
3408                         while ((dname = ReadDirName(dirptr))) {
3409                                 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3410                                         continue;
3411                                 if(!IS_VETO_PATH(conn, dname)) {
3412                                         all_veto_files = False;
3413                                         break;
3414                                 }
3415                         }
3416
3417                         if(all_veto_files) {
3418                                 SeekDir(dirptr,dirpos);
3419                                 while ((dname = ReadDirName(dirptr))) {
3420                                         pstring fullname;
3421                                         SMB_STRUCT_STAT st;
3422
3423                                         if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3424                                                 continue;
3425
3426                                         /* Construct the full name. */
3427                                         if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3428                                                 errno = ENOMEM;
3429                                                 break;
3430                                         }
3431
3432                                         pstrcpy(fullname, directory);
3433                                         pstrcat(fullname, "/");
3434                                         pstrcat(fullname, dname);
3435                      
3436                                         if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3437                                                 break;
3438                                         if(st.st_mode & S_IFDIR) {
3439                                                 if(lp_recursive_veto_delete(SNUM(conn))) {
3440                                                         if(recursive_rmdir(conn, fullname) != 0)
3441                                                                 break;
3442                                                 }
3443                                                 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3444                                                         break;
3445                                         } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3446                                                 break;
3447                                 }
3448                                 CloseDir(dirptr);
3449                                 /* Retry the rmdir */
3450                                 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3451                         } else {
3452                                 CloseDir(dirptr);
3453                         }
3454                 } else {
3455                         errno = ENOTEMPTY;
3456                 }
3457         }
3458
3459         if (!ok)
3460                 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3461
3462         return ok;
3463 }
3464
3465 /****************************************************************************
3466  Reply to a rmdir.
3467 ****************************************************************************/
3468
3469 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3470 {
3471         pstring directory;
3472         int outsize = 0;
3473         BOOL ok = False;
3474         BOOL bad_path = False;
3475         SMB_STRUCT_STAT sbuf;
3476         NTSTATUS status;
3477         START_PROFILE(SMBrmdir);
3478
3479         srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3480         if (!NT_STATUS_IS_OK(status)) {
3481                 END_PROFILE(SMBrmdir);
3482                 return ERROR_NT(status);
3483         }
3484
3485         RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3486
3487         unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3488         if (bad_path) {
3489                 END_PROFILE(SMBrmdir);
3490                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3491         }
3492   
3493         if (check_name(directory,conn)) {
3494                 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3495                 ok = rmdir_internals(conn, directory);
3496         }
3497   
3498         if (!ok) {
3499                 END_PROFILE(SMBrmdir);
3500                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3501         }
3502  
3503         outsize = set_message(outbuf,0,0,True);
3504   
3505         DEBUG( 3, ( "rmdir %s\n", directory ) );
3506   
3507         END_PROFILE(SMBrmdir);
3508         return(outsize);
3509 }
3510
3511 /*******************************************************************
3512  Resolve wildcards in a filename rename.
3513  Note that name is in UNIX charset and thus potentially can be more
3514  than fstring buffer (255 bytes) especially in default UTF-8 case.
3515  Therefore, we use pstring inside and all calls should ensure that
3516  name2 is at least pstring-long (they do already)
3517 ********************************************************************/
3518
3519 static BOOL resolve_wildcards(const char *name1, char *name2)
3520 {
3521         pstring root1,root2;
3522         pstring ext1,ext2;
3523         char *p,*p2, *pname1, *pname2;
3524         int available_space, actual_space;
3525         
3526
3527         pname1 = strrchr_m(name1,'/');
3528         pname2 = strrchr_m(name2,'/');
3529
3530         if (!pname1 || !pname2)
3531                 return(False);
3532   
3533         pstrcpy(root1,pname1);
3534         pstrcpy(root2,pname2);
3535         p = strrchr_m(root1,'.');
3536         if (p) {
3537                 *p = 0;
3538                 pstrcpy(ext1,p+1);
3539         } else {
3540                 pstrcpy(ext1,"");    
3541         }
3542         p = strrchr_m(root2,'.');
3543         if (p) {
3544                 *p = 0;
3545                 pstrcpy(ext2,p+1);
3546         } else {
3547                 pstrcpy(ext2,"");    
3548         }
3549
3550         p = root1;
3551         p2 = root2;
3552         while (*p2) {
3553                 if (*p2 == '?') {
3554                         *p2 = *p;
3555                         p2++;
3556                 } else if (*p2 == '*') {
3557                         pstrcpy(p2, p);
3558                         break;
3559                 } else {
3560                         p2++;
3561                 }
3562                 if (*p)
3563                         p++;
3564         }
3565
3566         p = ext1;
3567         p2 = ext2;
3568         while (*p2) {
3569                 if (*p2 == '?') {
3570                         *p2 = *p;
3571                         p2++;
3572                 } else if (*p2 == '*') {
3573                         pstrcpy(p2, p);
3574                         break;
3575                 } else {
3576                         p2++;
3577                 }
3578                 if (*p)
3579                         p++;
3580         }
3581
3582         available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3583         
3584         if (ext2[0]) {
3585                 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3586                 if (actual_space >= available_space - 1) {
3587                         DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3588                                 actual_space - available_space));
3589                 }
3590         } else {
3591                 pstrcpy_base(pname2, root2, name2);
3592         }
3593
3594         return(True);
3595 }
3596
3597 /****************************************************************************
3598  Ensure open files have their names updates.
3599 ****************************************************************************/
3600
3601 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3602 {
3603         files_struct *fsp;
3604         BOOL did_rename = False;
3605
3606         for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3607                 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3608                         fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3609                         fsp->fsp_name, newname ));
3610                 string_set(&fsp->fsp_name, newname);
3611                 did_rename = True;
3612         }
3613
3614         if (!did_rename)
3615                 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3616                         (unsigned int)dev, (double)inode, newname ));
3617 }
3618
3619 /****************************************************************************
3620  Rename an open file - given an fsp.
3621 ****************************************************************************/
3622
3623 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint16 attrs, BOOL replace_if_exists)
3624 {
3625         SMB_STRUCT_STAT sbuf;
3626         BOOL bad_path = False;
3627         pstring newname_last_component;
3628         NTSTATUS error = NT_STATUS_OK;
3629         BOOL dest_exists;
3630         BOOL rcdest = True;
3631
3632         ZERO_STRUCT(sbuf);
3633         rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3634
3635         /* Quick check for "." and ".." */
3636         if (!bad_path && newname_last_component[0] == '.') {
3637                 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3638                         return NT_STATUS_ACCESS_DENIED;
3639                 }
3640         }
3641         if (!rcdest && bad_path) {
3642                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3643         }
3644
3645         /* Ensure newname contains a '/' */
3646         if(strrchr_m(newname,'/') == 0) {
3647                 pstring tmpstr;
3648                 
3649                 pstrcpy(tmpstr, "./");
3650                 pstrcat(tmpstr, newname);
3651                 pstrcpy(newname, tmpstr);
3652         }
3653
3654         /*
3655          * Check for special case with case preserving and not
3656          * case sensitive. If the old last component differs from the original
3657          * last component only by case, then we should allow
3658          * the rename (user is trying to change the case of the
3659          * filename).
3660          */
3661
3662         if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
3663                         strequal(newname, fsp->fsp_name)) {
3664                 char *p;
3665                 pstring newname_modified_last_component;
3666
3667                 /*
3668                  * Get the last component of the modified name.
3669                  * Note that we guarantee that newname contains a '/'
3670                  * character above.
3671                  */
3672                 p = strrchr_m(newname,'/');
3673                 pstrcpy(newname_modified_last_component,p+1);
3674                         
3675                 if(strcsequal(newname_modified_last_component, 
3676                               newname_last_component) == False) {
3677                         /*
3678                          * Replace the modified last component with
3679                          * the original.
3680                          */
3681                         pstrcpy(p+1, newname_last_component);
3682                 }
3683         }
3684
3685         /*
3686          * If the src and dest names are identical - including case,
3687          * don't do the rename, just return success.
3688          */
3689
3690         if (strcsequal(fsp->fsp_name, newname)) {
3691                 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3692                         newname));
3693                 return NT_STATUS_OK;
3694         }
3695
3696         dest_exists = vfs_object_exist(conn,newname,NULL);
3697
3698         if(!replace_if_exists && dest_exists) {
3699                 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3700                         fsp->fsp_name,newname));
3701                 return NT_STATUS_OBJECT_NAME_COLLISION;
3702         }
3703
3704         error = can_rename(newname,conn,attrs,&sbuf);
3705
3706         if (dest_exists && !NT_STATUS_IS_OK(error)) {
3707                 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3708                         nt_errstr(error), fsp->fsp_name,newname));
3709                 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3710                         error = NT_STATUS_ACCESS_DENIED;
3711                 return error;
3712         }
3713
3714         if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3715                 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3716                         fsp->fsp_name,newname));
3717                 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3718                 return NT_STATUS_OK;    
3719         }
3720
3721         if (errno == ENOTDIR || errno == EISDIR)
3722                 error = NT_STATUS_OBJECT_NAME_COLLISION;
3723         else
3724                 error = map_nt_error_from_unix(errno);
3725                 
3726         DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3727                 nt_errstr(error), fsp->fsp_name,newname));
3728
3729         return error;
3730 }
3731
3732 /****************************************************************************
3733  The guts of the rename command, split out so it may be called by the NT SMB
3734  code. 
3735 ****************************************************************************/
3736
3737 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
3738 {
3739         pstring directory;
3740         pstring mask;
3741         pstring last_component_src;
3742         pstring last_component_dest;
3743         char *p;
3744         BOOL has_wild;
3745         BOOL bad_path_src = False;
3746         BOOL bad_path_dest = False;
3747         int count=0;
3748         NTSTATUS error = NT_STATUS_OK;
3749         BOOL rc = True;
3750         BOOL rcdest = True;
3751         SMB_STRUCT_STAT sbuf1, sbuf2;
3752
3753         *directory = *mask = 0;
3754
3755         ZERO_STRUCT(sbuf1);
3756         ZERO_STRUCT(sbuf2);
3757
3758         rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
3759         if (!rc && bad_path_src) {
3760                 if (ms_has_wild(last_component_src))
3761                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3762                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3763         }
3764
3765         /* Quick check for "." and ".." */
3766         if (last_component_src[0] == '.') {
3767                 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
3768                         return NT_STATUS_OBJECT_NAME_INVALID;
3769                 }
3770         }
3771
3772         rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
3773
3774         /* Quick check for "." and ".." */
3775         if (last_component_dest[0] == '.') {
3776                 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
3777                         return NT_STATUS_OBJECT_NAME_INVALID;
3778                 }
3779         }
3780
3781         /*
3782          * Split the old name into directory and last component
3783          * strings. Note that unix_convert may have stripped off a 
3784          * leading ./ from both name and newname if the rename is 
3785          * at the root of the share. We need to make sure either both
3786          * name and newname contain a / character or neither of them do
3787          * as this is checked in resolve_wildcards().
3788          */
3789
3790         p = strrchr_m(name,'/');
3791         if (!p) {
3792                 pstrcpy(directory,".");
3793                 pstrcpy(mask,name);
3794         } else {
3795                 *p = 0;
3796                 pstrcpy(directory,name);
3797                 pstrcpy(mask,p+1);
3798                 *p = '/'; /* Replace needed for exceptional test below. */
3799         }
3800
3801         /*
3802          * We should only check the mangled cache
3803          * here if unix_convert failed. This means
3804          * that the path in 'mask' doesn't exist
3805          * on the file system and so we need to look
3806          * for a possible mangle. This patch from
3807          * Tine Smukavec <valentin.smukavec@hermes.si>.
3808          */
3809
3810         if (!rc && mangle_is_mangled(mask))
3811                 mangle_check_cache( mask, sizeof(pstring)-1 );
3812
3813         has_wild = ms_has_wild(mask);
3814
3815         if (!has_wild) {
3816                 /*
3817                  * No wildcards - just process the one file.
3818                  */
3819                 BOOL is_short_name = mangle_is_8_3(name, True);
3820
3821                 /* Add a terminating '/' to the directory name. */
3822                 pstrcat(directory,"/");
3823                 pstrcat(directory,mask);
3824                 
3825                 /* Ensure newname contains a '/' also */
3826                 if(strrchr_m(newname,'/') == 0) {
3827                         pstring tmpstr;
3828                         
3829                         pstrcpy(tmpstr, "./");
3830                         pstrcat(tmpstr, newname);
3831                         pstrcpy(newname, tmpstr);
3832                 }
3833                 
3834                 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3835 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", 
3836                          conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory, 
3837                          newname, last_component_dest, is_short_name));
3838
3839                 /*
3840                  * Check for special case with case preserving and not
3841                  * case sensitive, if directory and newname are identical,
3842                  * and the old last component differs from the original
3843                  * last component only by case, then we should allow
3844                  * the rename (user is trying to change the case of the
3845                  * filename).
3846                  */
3847                 if((conn->case_sensitive == False) && 
3848                    (((conn->case_preserve == True) && 
3849                      (is_short_name == False)) || 
3850                     ((conn->short_case_preserve == True) && 
3851                      (is_short_name == True))) &&
3852                    strcsequal(directory, newname)) {
3853                         pstring modified_last_component;
3854
3855                         /*
3856                          * Get the last component of the modified name.
3857                          * Note that we guarantee that newname contains a '/'
3858                          * character above.
3859                          */
3860                         p = strrchr_m(newname,'/');
3861                         pstrcpy(modified_last_component,p+1);
3862                         
3863                         if(strcsequal(modified_last_component, 
3864                                       last_component_dest) == False) {
3865                                 /*
3866                                  * Replace the modified last component with
3867                                  * the original.
3868                                  */
3869                                 pstrcpy(p+1, last_component_dest);
3870                         }
3871                 }
3872         
3873                 resolve_wildcards(directory,newname);
3874         
3875                 /*
3876                  * The source object must exist.
3877                  */
3878
3879                 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3880                         DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3881                                 directory,newname));
3882
3883                         if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3884                                 /*
3885                                  * Must return different errors depending on whether the parent
3886                                  * directory existed or not.
3887                                  */
3888
3889                                 p = strrchr_m(directory, '/');
3890                                 if (!p)
3891                                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3892                                 *p = '\0';
3893                                 if (vfs_object_exist(conn, directory, NULL))
3894                                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3895                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3896                         }
3897                         error = map_nt_error_from_unix(errno);
3898                         DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3899                                 nt_errstr(error), directory,newname));
3900
3901                         return error;
3902                 }
3903
3904                 if (!rcdest && bad_path_dest) {
3905                         if (ms_has_wild(last_component_dest))
3906                                 return NT_STATUS_OBJECT_NAME_INVALID;
3907                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3908                 }
3909
3910                 error = can_rename(directory,conn,attrs,&sbuf1);
3911
3912                 if (!NT_STATUS_IS_OK(error)) {
3913                         DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3914                                 nt_errstr(error), directory,newname));
3915                         return error;
3916                 }
3917
3918                 /*
3919                  * If the src and dest names are identical - including case,
3920                  * don't do the rename, just return success.
3921                  */
3922
3923                 if (strcsequal(directory, newname)) {
3924                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3925                         DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3926                         return NT_STATUS_OK;
3927                 }
3928
3929                 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3930                         DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3931                                 directory,newname));
3932                         return NT_STATUS_OBJECT_NAME_COLLISION;
3933                 }
3934
3935                 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3936                         DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3937                                 directory,newname));
3938                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3939                         return NT_STATUS_OK;    
3940                 }
3941
3942                 if (errno == ENOTDIR || errno == EISDIR)
3943                         error = NT_STATUS_OBJECT_NAME_COLLISION;
3944                 else
3945                         error = map_nt_error_from_unix(errno);
3946                 
3947                 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3948                         nt_errstr(error), directory,newname));
3949
3950                 return error;
3951         } else {
3952                 /*
3953                  * Wildcards - process each file that matches.
3954                  */
3955                 void *dirptr = NULL;
3956                 const char *dname;
3957                 pstring destname;
3958                 
3959                 if (check_name(directory,conn))
3960                         dirptr = OpenDir(conn, directory, True);
3961                 
3962                 if (dirptr) {
3963                         error = NT_STATUS_NO_SUCH_FILE;
3964 /*                      Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
3965                         
3966                         if (strequal(mask,"????????.???"))
3967                                 pstrcpy(mask,"*");
3968                         
3969                         while ((dname = ReadDirName(dirptr))) {
3970                                 pstring fname;
3971                                 BOOL sysdir_entry = False;
3972
3973                                 pstrcpy(fname,dname);
3974                                 
3975                                 /* Quick check for "." and ".." */
3976                                 if (fname[0] == '.') {
3977                                         if (!fname[1] || (fname[1] == '.' && !fname[2])) {
3978                                                 if (attrs & aDIR) {
3979                                                         sysdir_entry = True;
3980                                                 } else {
3981                                                         continue;
3982                                                 }
3983                                         }
3984                                 }
3985
3986                                 if(!mask_match(fname, mask, conn->case_sensitive))
3987                                         continue;
3988                                 
3989                                 if (sysdir_entry) {
3990                                         error = NT_STATUS_OBJECT_NAME_INVALID;
3991                                         break;
3992                                 }
3993
3994                                 error = NT_STATUS_ACCESS_DENIED;
3995                                 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3996                                 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3997                                         error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3998                                         DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3999                                         continue;
4000                                 }
4001                                 error = can_rename(fname,conn,attrs,&sbuf1);
4002                                 if (!NT_STATUS_IS_OK(error)) {
4003                                         DEBUG(6,("rename %s refused\n", fname));
4004                                         continue;
4005                                 }
4006                                 pstrcpy(destname,newname);
4007                                 
4008                                 if (!resolve_wildcards(fname,destname)) {
4009                                         DEBUG(6,("resolve_wildcards %s %s failed\n", 
4010                                                  fname, destname));
4011                                         continue;
4012                                 }
4013                                 
4014                                 if (strcsequal(fname,destname)) {
4015                                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4016                                         DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
4017                                         count++;
4018                                         error = NT_STATUS_OK;
4019                                         continue;
4020                                 }
4021
4022                                 if (!replace_if_exists && 
4023                                     vfs_file_exist(conn,destname, NULL)) {
4024                                         DEBUG(6,("file_exist %s\n", destname));
4025                                         error = NT_STATUS_OBJECT_NAME_COLLISION;
4026                                         continue;
4027                                 }
4028                                 
4029                                 if (!SMB_VFS_RENAME(conn,fname,destname)) {
4030                                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4031                                         count++;
4032                                         error = NT_STATUS_OK;
4033                                 }
4034                                 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
4035                         }
4036                         CloseDir(dirptr);
4037                 }
4038
4039                 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
4040                         if (!rcdest && bad_path_dest) {
4041                                 if (ms_has_wild(last_component_dest))
4042                                         return NT_STATUS_OBJECT_NAME_INVALID;
4043                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4044                         }
4045                 }
4046         }
4047         
4048         if (count == 0 && NT_STATUS_IS_OK(error)) {
4049                 error = map_nt_error_from_unix(errno);
4050         }
4051         
4052         return error;
4053 }
4054
4055 /****************************************************************************
4056  Reply to a mv.
4057 ****************************************************************************/
4058
4059 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, 
4060              int dum_buffsize)
4061 {
4062         int outsize = 0;
4063         pstring name;
4064         pstring newname;
4065         char *p;
4066         uint16 attrs = SVAL(inbuf,smb_vwv0);
4067         NTSTATUS status;
4068
4069         START_PROFILE(SMBmv);
4070
4071         p = smb_buf(inbuf) + 1;
4072         p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4073         if (!NT_STATUS_IS_OK(status)) {
4074                 END_PROFILE(SMBmv);
4075                 return ERROR_NT(status);
4076         }
4077         p++;
4078         p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4079         if (!NT_STATUS_IS_OK(status)) {
4080                 END_PROFILE(SMBmv);
4081                 return ERROR_NT(status);
4082         }
4083         
4084         RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4085         RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4086         
4087         DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4088         
4089         status = rename_internals(conn, name, newname, attrs, False);
4090         if (!NT_STATUS_IS_OK(status)) {
4091                 END_PROFILE(SMBmv);
4092                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4093                         /* We have re-scheduled this call. */
4094                         clear_cached_errors();
4095                         return -1;
4096                 }
4097                 return ERROR_NT(status);
4098         }
4099
4100         /*
4101          * Win2k needs a changenotify request response before it will
4102          * update after a rename..
4103          */     
4104         process_pending_change_notify_queue((time_t)0);
4105         outsize = set_message(outbuf,0,0,True);
4106   
4107         END_PROFILE(SMBmv);
4108         return(outsize);
4109 }
4110
4111 /*******************************************************************
4112  Copy a file as part of a reply_copy.
4113 ******************************************************************/
4114
4115 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4116                       int count,BOOL target_is_directory, int *err_ret)
4117 {
4118         int Access,action;
4119         SMB_STRUCT_STAT src_sbuf, sbuf2;
4120         SMB_OFF_T ret=-1;
4121         files_struct *fsp1,*fsp2;
4122         pstring dest;
4123         uint32 dosattrs;
4124  
4125         *err_ret = 0;
4126
4127         pstrcpy(dest,dest1);
4128         if (target_is_directory) {
4129                 char *p = strrchr_m(src,'/');
4130                 if (p) 
4131                         p++;
4132                 else
4133                         p = src;
4134                 pstrcat(dest,"/");
4135                 pstrcat(dest,p);
4136         }
4137
4138         if (!vfs_file_exist(conn,src,&src_sbuf))
4139                 return(False);
4140
4141         fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
4142                                         (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,INTERNAL_OPEN_ONLY,
4143                                         &Access,&action);
4144
4145         if (!fsp1)
4146                 return(False);
4147
4148         if (!target_is_directory && count)
4149                 ofun = FILE_EXISTS_OPEN;
4150
4151         dosattrs = dos_mode(conn, src, &src_sbuf);
4152         if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
4153                 ZERO_STRUCTP(&sbuf2);
4154
4155         fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4156                         ofun,dosattrs,INTERNAL_OPEN_ONLY,&Access,&action);
4157
4158         if (!fsp2) {
4159                 close_file(fsp1,False);
4160                 return(False);
4161         }
4162
4163         if ((ofun&3) == 1) {
4164                 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4165                         DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4166                         /*
4167                          * Stop the copy from occurring.
4168                          */
4169                         ret = -1;
4170                         src_sbuf.st_size = 0;
4171                 }
4172         }
4173   
4174         if (src_sbuf.st_size)
4175                 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4176
4177         close_file(fsp1,False);
4178
4179         /* Ensure the modtime is set correctly on the destination file. */
4180         fsp2->pending_modtime = src_sbuf.st_mtime;
4181
4182         /*
4183          * As we are opening fsp1 read-only we only expect
4184          * an error on close on fsp2 if we are out of space.
4185          * Thus we don't look at the error return from the
4186          * close of fsp1.
4187          */
4188         *err_ret = close_file(fsp2,False);
4189
4190         return(ret == (SMB_OFF_T)src_sbuf.st_size);
4191 }
4192
4193 /****************************************************************************
4194  Reply to a file copy.
4195 ****************************************************************************/
4196
4197 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4198 {
4199         int outsize = 0;
4200         pstring name;
4201         pstring directory;
4202         pstring mask,newname;
4203         char *p;
4204         int count=0;
4205         int error = ERRnoaccess;
4206         int err = 0;
4207         BOOL has_wild;
4208         BOOL exists=False;
4209         int tid2 = SVAL(inbuf,smb_vwv0);
4210         int ofun = SVAL(inbuf,smb_vwv1);
4211         int flags = SVAL(inbuf,smb_vwv2);
4212         BOOL target_is_directory=False;
4213         BOOL bad_path1 = False;
4214         BOOL bad_path2 = False;
4215         BOOL rc = True;
4216         SMB_STRUCT_STAT sbuf1, sbuf2;
4217         NTSTATUS status;
4218
4219         START_PROFILE(SMBcopy);
4220
4221         *directory = *mask = 0;
4222
4223         p = smb_buf(inbuf);
4224         p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4225         if (!NT_STATUS_IS_OK(status)) {
4226                 END_PROFILE(SMBcopy);
4227                 return ERROR_NT(status);
4228         }
4229         p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4230         if (!NT_STATUS_IS_OK(status)) {
4231                 END_PROFILE(SMBcopy);
4232                 return ERROR_NT(status);
4233         }
4234    
4235         DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4236    
4237         if (tid2 != conn->cnum) {
4238                 /* can't currently handle inter share copies XXXX */
4239                 DEBUG(3,("Rejecting inter-share copy\n"));
4240                 END_PROFILE(SMBcopy);
4241                 return ERROR_DOS(ERRSRV,ERRinvdevice);
4242         }
4243
4244         RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4245         RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4246
4247         rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4248         unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4249
4250         target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4251
4252         if ((flags&1) && target_is_directory) {
4253                 END_PROFILE(SMBcopy);
4254                 return ERROR_DOS(ERRDOS,ERRbadfile);
4255         }
4256
4257         if ((flags&2) && !target_is_directory) {
4258                 END_PROFILE(SMBcopy);
4259                 return ERROR_DOS(ERRDOS,ERRbadpath);
4260         }
4261
4262         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4263                 /* wants a tree copy! XXXX */
4264                 DEBUG(3,("Rejecting tree copy\n"));
4265                 END_PROFILE(SMBcopy);
4266                 return ERROR_DOS(ERRSRV,ERRerror);
4267         }
4268
4269         p = strrchr_m(name,'/');
4270         if (!p) {
4271                 pstrcpy(directory,"./");
4272                 pstrcpy(mask,name);
4273         } else {
4274                 *p = 0;
4275                 pstrcpy(directory,name);
4276                 pstrcpy(mask,p+1);
4277         }
4278
4279         /*
4280          * We should only check the mangled cache
4281          * here if unix_convert failed. This means
4282          * that the path in 'mask' doesn't exist
4283          * on the file system and so we need to look
4284          * for a possible mangle. This patch from
4285          * Tine Smukavec <valentin.smukavec@hermes.si>.
4286          */
4287
4288         if (!rc && mangle_is_mangled(mask))
4289                 mangle_check_cache( mask, sizeof(pstring)-1 );
4290
4291         has_wild = ms_has_wild(mask);
4292
4293         if (!has_wild) {
4294                 pstrcat(directory,"/");
4295                 pstrcat(directory,mask);
4296                 if (resolve_wildcards(directory,newname) &&
4297                                 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4298                         count++;
4299                 if(!count && err) {
4300                         errno = err;
4301                         END_PROFILE(SMBcopy);
4302                         return(UNIXERROR(ERRHRD,ERRgeneral));
4303                 }
4304                 if (!count) {
4305                         exists = vfs_file_exist(conn,directory,NULL);
4306                 }
4307         } else {
4308                 void *dirptr = NULL;
4309                 const char *dname;
4310                 pstring destname;
4311
4312                 if (check_name(directory,conn))
4313                         dirptr = OpenDir(conn, directory, True);
4314
4315                 if (dirptr) {
4316                         error = ERRbadfile;
4317
4318                         if (strequal(mask,"????????.???"))
4319                                 pstrcpy(mask,"*");
4320
4321                         while ((dname = ReadDirName(dirptr))) {
4322                                 pstring fname;
4323                                 pstrcpy(fname,dname);
4324     
4325                                 if(!mask_match(fname, mask, conn->case_sensitive))
4326                                         continue;
4327
4328                                 error = ERRnoaccess;
4329                                 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4330                                 pstrcpy(destname,newname);
4331                                 if (resolve_wildcards(fname,destname) && 
4332                                                 copy_file(fname,destname,conn,ofun,
4333                                                 count,target_is_directory,&err))
4334                                         count++;
4335                                 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4336                         }
4337                         CloseDir(dirptr);
4338                 }
4339         }
4340   
4341         if (count == 0) {
4342                 if(err) {
4343                         /* Error on close... */
4344                         errno = err;
4345                         END_PROFILE(SMBcopy);
4346                         return(UNIXERROR(ERRHRD,ERRgeneral));
4347                 }
4348
4349                 if (exists) {
4350                         END_PROFILE(SMBcopy);
4351                         return ERROR_DOS(ERRDOS,error);
4352                 } else {
4353                         if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4354                                 unix_ERR_class = ERRDOS;
4355                                 unix_ERR_code = ERRbadpath;
4356                         }
4357                         END_PROFILE(SMBcopy);
4358                         return(UNIXERROR(ERRDOS,error));
4359                 }
4360         }
4361   
4362         outsize = set_message(outbuf,1,0,True);
4363         SSVAL(outbuf,smb_vwv0,count);
4364
4365         END_PROFILE(SMBcopy);
4366         return(outsize);
4367 }
4368
4369 /****************************************************************************
4370  Reply to a setdir.
4371 ****************************************************************************/
4372
4373 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4374 {
4375         int snum;
4376         int outsize = 0;
4377         BOOL ok = False;
4378         pstring newdir;
4379         NTSTATUS status;
4380
4381         START_PROFILE(pathworks_setdir);
4382   
4383         snum = SNUM(conn);
4384         if (!CAN_SETDIR(snum)) {
4385                 END_PROFILE(pathworks_setdir);
4386                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4387         }
4388
4389         srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False);
4390         if (!NT_STATUS_IS_OK(status)) {
4391                 END_PROFILE(pathworks_setdir);
4392                 return ERROR_NT(status);
4393         }
4394   
4395         if (strlen(newdir) == 0) {
4396                 ok = True;
4397         } else {
4398                 ok = vfs_directory_exist(conn,newdir,NULL);
4399                 if (ok)
4400                         string_set(&conn->connectpath,newdir);
4401         }
4402   
4403         if (!ok) {
4404                 END_PROFILE(pathworks_setdir);
4405                 return ERROR_DOS(ERRDOS,ERRbadpath);
4406         }
4407   
4408         outsize = set_message(outbuf,0,0,True);
4409         SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4410   
4411         DEBUG(3,("setdir %s\n", newdir));
4412
4413         END_PROFILE(pathworks_setdir);
4414         return(outsize);
4415 }
4416
4417 /****************************************************************************
4418  Get a lock pid, dealing with large count requests.
4419 ****************************************************************************/
4420
4421 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4422 {
4423         if(!large_file_format)
4424                 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4425         else
4426                 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4427 }
4428
4429 /****************************************************************************
4430  Get a lock count, dealing with large count requests.
4431 ****************************************************************************/
4432
4433 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4434 {
4435         SMB_BIG_UINT count = 0;
4436
4437         if(!large_file_format) {
4438                 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4439         } else {
4440
4441 #if defined(HAVE_LONGLONG)
4442                 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4443                         ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4444 #else /* HAVE_LONGLONG */
4445
4446                 /*
4447                  * NT4.x seems to be broken in that it sends large file (64 bit)
4448                  * lockingX calls even if the CAP_LARGE_FILES was *not*
4449                  * negotiated. For boxes without large unsigned ints truncate the
4450                  * lock count by dropping the top 32 bits.
4451                  */
4452
4453                 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4454                         DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4455                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4456                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4457                                 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4458                 }
4459
4460                 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4461 #endif /* HAVE_LONGLONG */
4462         }
4463
4464         return count;
4465 }
4466
4467 #if !defined(HAVE_LONGLONG)
4468 /****************************************************************************
4469  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4470 ****************************************************************************/
4471
4472 static uint32 map_lock_offset(uint32 high, uint32 low)
4473 {
4474         unsigned int i;
4475         uint32 mask = 0;
4476         uint32 highcopy = high;
4477  
4478         /*
4479          * Try and find out how many significant bits there are in high.
4480          */
4481  
4482         for(i = 0; highcopy; i++)
4483                 highcopy >>= 1;
4484  
4485         /*
4486          * We use 31 bits not 32 here as POSIX
4487          * lock offsets may not be negative.
4488          */
4489  
4490         mask = (~0) << (31 - i);
4491  
4492         if(low & mask)
4493                 return 0; /* Fail. */
4494  
4495         high <<= (31 - i);
4496  
4497         return (high|low);
4498 }
4499 #endif /* !defined(HAVE_LONGLONG) */
4500
4501 /****************************************************************************
4502  Get a lock offset, dealing with large offset requests.
4503 ****************************************************************************/
4504
4505 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4506 {
4507         SMB_BIG_UINT offset = 0;
4508
4509         *err = False;
4510
4511         if(!large_file_format) {
4512                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4513         } else {
4514
4515 #if defined(HAVE_LONGLONG)
4516                 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4517                                 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4518 #else /* HAVE_LONGLONG */
4519
4520                 /*
4521                  * NT4.x seems to be broken in that it sends large file (64 bit)
4522                  * lockingX calls even if the CAP_LARGE_FILES was *not*
4523                  * negotiated. For boxes without large unsigned ints mangle the
4524                  * lock offset by mapping the top 32 bits onto the lower 32.
4525                  */
4526       
4527                 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4528                         uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4529                         uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4530                         uint32 new_low = 0;
4531
4532                         if((new_low = map_lock_offset(high, low)) == 0) {
4533                                 *err = True;
4534                                 return (SMB_BIG_UINT)-1;
4535                         }
4536
4537                         DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4538                                 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4539                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4540                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4541                 }
4542
4543                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4544 #endif /* HAVE_LONGLONG */
4545         }
4546
4547         return offset;
4548 }
4549
4550 /****************************************************************************
4551  Reply to a lockingX request.
4552 ****************************************************************************/
4553
4554 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4555 {
4556         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4557         unsigned char locktype = CVAL(inbuf,smb_vwv3);
4558         unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4559         uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4560         uint16 num_locks = SVAL(inbuf,smb_vwv7);
4561         SMB_BIG_UINT count = 0, offset = 0;
4562         uint16 lock_pid;
4563         int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4564         int i;
4565         char *data;
4566         BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4567         BOOL err;
4568         BOOL my_lock_ctx = False;
4569         NTSTATUS status;
4570
4571         START_PROFILE(SMBlockingX);
4572         
4573         CHECK_FSP(fsp,conn);
4574         
4575         data = smb_buf(inbuf);
4576
4577         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
4578                 /* we don't support these - and CANCEL_LOCK makes w2k
4579                    and XP reboot so I don't really want to be
4580                    compatible! (tridge) */
4581                 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4582         }
4583         
4584         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
4585                 /* Need to make this like a cancel.... JRA. */
4586                 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4587         }
4588         
4589         /* Check if this is an oplock break on a file
4590            we have granted an oplock on.
4591         */
4592         if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4593                 /* Client can insist on breaking to none. */
4594                 BOOL break_to_none = (oplocklevel == 0);
4595                 
4596                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4597                          (unsigned int)oplocklevel, fsp->fnum ));
4598
4599                 /*
4600                  * Make sure we have granted an exclusive or batch oplock on this file.
4601                  */
4602                 
4603                 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4604                         DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4605 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4606
4607                         /* if this is a pure oplock break request then don't send a reply */
4608                         if (num_locks == 0 && num_ulocks == 0) {
4609                                 END_PROFILE(SMBlockingX);
4610                                 return -1;
4611                         } else {
4612                                 END_PROFILE(SMBlockingX);
4613                                 return ERROR_DOS(ERRDOS,ERRlock);
4614                         }
4615                 }
4616
4617                 if (remove_oplock(fsp, break_to_none) == False) {
4618                         DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4619                                  fsp->fsp_name ));
4620                 }
4621                 
4622                 /* if this is a pure oplock break request then don't send a reply */
4623                 if (num_locks == 0 && num_ulocks == 0) {
4624                         /* Sanity check - ensure a pure oplock break is not a
4625                            chained request. */
4626                         if(CVAL(inbuf,smb_vwv0) != 0xff)
4627                                 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4628                                          (unsigned int)CVAL(inbuf,smb_vwv0) ));
4629                         END_PROFILE(SMBlockingX);
4630                         return -1;
4631                 }
4632         }
4633
4634         /*
4635          * We do this check *after* we have checked this is not a oplock break
4636          * response message. JRA.
4637          */
4638         
4639         release_level_2_oplocks_on_change(fsp);
4640         
4641         /* Data now points at the beginning of the list
4642            of smb_unlkrng structs */
4643         for(i = 0; i < (int)num_ulocks; i++) {
4644                 lock_pid = get_lock_pid( data, i, large_file_format);
4645                 count = get_lock_count( data, i, large_file_format);
4646                 offset = get_lock_offset( data, i, large_file_format, &err);
4647                 
4648                 /*
4649                  * There is no error code marked "stupid client bug".... :-).
4650                  */
4651                 if(err) {
4652                         END_PROFILE(SMBlockingX);
4653                         return ERROR_DOS(ERRDOS,ERRnoaccess);
4654                 }
4655
4656                 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4657                           (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4658                 
4659                 status = do_unlock(fsp,conn,lock_pid,count,offset);
4660                 if (NT_STATUS_V(status)) {
4661                         END_PROFILE(SMBlockingX);
4662                         return ERROR_NT(status);
4663                 }
4664         }
4665
4666         /* Setup the timeout in seconds. */
4667
4668         lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4669         
4670         /* Now do any requested locks */
4671         data += ((large_file_format ? 20 : 10)*num_ulocks);
4672         
4673         /* Data now points at the beginning of the list
4674            of smb_lkrng structs */
4675         
4676         for(i = 0; i < (int)num_locks; i++) {
4677                 lock_pid = get_lock_pid( data, i, large_file_format);
4678                 count = get_lock_count( data, i, large_file_format);
4679                 offset = get_lock_offset( data, i, large_file_format, &err);
4680                 
4681                 /*
4682                  * There is no error code marked "stupid client bug".... :-).
4683                  */
4684                 if(err) {
4685                         END_PROFILE(SMBlockingX);
4686                         return ERROR_DOS(ERRDOS,ERRnoaccess);
4687                 }
4688                 
4689                 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4690                         (double)offset, (double)count, (unsigned int)lock_pid,
4691                         fsp->fsp_name, (int)lock_timeout ));
4692                 
4693                 status = do_lock_spin(fsp,conn,lock_pid, count,offset, 
4694                                  ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4695                 if (NT_STATUS_V(status)) {
4696                         /*
4697                          * Interesting fact found by IFSTEST /t LockOverlappedTest...
4698                          * Even if it's our own lock context, we need to wait here as
4699                          * there may be an unlock on the way.
4700                          * So I removed a "&& !my_lock_ctx" from the following
4701                          * if statement. JRA.
4702                          */
4703                         if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4704                                 /*
4705                                  * A blocking lock was requested. Package up
4706                                  * this smb into a queued request and push it
4707                                  * onto the blocking lock queue.
4708                                  */
4709                                 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4710                                         END_PROFILE(SMBlockingX);
4711                                         return -1;
4712                                 }
4713                         }
4714                         break;
4715                 }
4716         }
4717         
4718         /* If any of the above locks failed, then we must unlock
4719            all of the previous locks (X/Open spec). */
4720         if (i != num_locks && num_locks != 0) {
4721                 /*
4722                  * Ensure we don't do a remove on the lock that just failed,
4723                  * as under POSIX rules, if we have a lock already there, we
4724                  * will delete it (and we shouldn't) .....
4725                  */
4726                 for(i--; i >= 0; i--) {
4727                         lock_pid = get_lock_pid( data, i, large_file_format);
4728                         count = get_lock_count( data, i, large_file_format);
4729                         offset = get_lock_offset( data, i, large_file_format, &err);
4730                         
4731                         /*
4732                          * There is no error code marked "stupid client bug".... :-).
4733                          */
4734                         if(err) {
4735                                 END_PROFILE(SMBlockingX);
4736                                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4737                         }
4738                         
4739                         do_unlock(fsp,conn,lock_pid,count,offset);
4740                 }
4741                 END_PROFILE(SMBlockingX);
4742                 return ERROR_NT(status);
4743         }
4744
4745         set_message(outbuf,2,0,True);
4746         
4747         DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4748                     fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4749         
4750         END_PROFILE(SMBlockingX);
4751         return chain_reply(inbuf,outbuf,length,bufsize);
4752 }
4753
4754 /****************************************************************************
4755  Reply to a SMBreadbmpx (read block multiplex) request.
4756 ****************************************************************************/
4757
4758 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4759 {
4760         ssize_t nread = -1;
4761         ssize_t total_read;
4762         char *data;
4763         SMB_OFF_T startpos;
4764         int outsize;
4765         size_t maxcount;
4766         int max_per_packet;
4767         size_t tcount;
4768         int pad;
4769         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4770         START_PROFILE(SMBreadBmpx);
4771
4772         /* this function doesn't seem to work - disable by default */
4773         if (!lp_readbmpx()) {
4774                 END_PROFILE(SMBreadBmpx);
4775                 return ERROR_DOS(ERRSRV,ERRuseSTD);
4776         }
4777
4778         outsize = set_message(outbuf,8,0,True);
4779
4780         CHECK_FSP(fsp,conn);
4781         CHECK_READ(fsp);
4782
4783         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4784         maxcount = SVAL(inbuf,smb_vwv3);
4785
4786         data = smb_buf(outbuf);
4787         pad = ((long)data)%4;
4788         if (pad)
4789                 pad = 4 - pad;
4790         data += pad;
4791
4792         max_per_packet = bufsize-(outsize+pad);
4793         tcount = maxcount;
4794         total_read = 0;
4795
4796         if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
4797                 END_PROFILE(SMBreadBmpx);
4798                 return ERROR_DOS(ERRDOS,ERRlock);
4799         }
4800
4801         do {
4802                 size_t N = MIN(max_per_packet,tcount-total_read);
4803   
4804                 nread = read_file(fsp,data,startpos,N);
4805
4806                 if (nread <= 0)
4807                         nread = 0;
4808
4809                 if (nread < (ssize_t)N)
4810                         tcount = total_read + nread;
4811
4812                 set_message(outbuf,8,nread,False);
4813                 SIVAL(outbuf,smb_vwv0,startpos);
4814                 SSVAL(outbuf,smb_vwv2,tcount);
4815                 SSVAL(outbuf,smb_vwv6,nread);
4816                 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4817
4818                 if (!send_smb(smbd_server_fd(),outbuf))
4819                         exit_server("reply_readbmpx: send_smb failed.");
4820
4821                 total_read += nread;
4822                 startpos += nread;
4823         } while (total_read < (ssize_t)tcount);
4824
4825         END_PROFILE(SMBreadBmpx);
4826         return(-1);
4827 }
4828
4829 /****************************************************************************
4830  Reply to a SMBsetattrE.
4831 ****************************************************************************/
4832
4833 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4834 {
4835         struct utimbuf unix_times;
4836         int outsize = 0;
4837         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4838         START_PROFILE(SMBsetattrE);
4839
4840         outsize = set_message(outbuf,0,0,True);
4841
4842         if(!fsp || (fsp->conn != conn)) {
4843                 END_PROFILE(SMBgetattrE);
4844                 return ERROR_DOS(ERRDOS,ERRbadfid);
4845         }
4846
4847         /*
4848          * Convert the DOS times into unix times. Ignore create
4849          * time as UNIX can't set this.
4850          */
4851
4852         unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4853         unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4854   
4855         /* 
4856          * Patch from Ray Frush <frush@engr.colostate.edu>
4857          * Sometimes times are sent as zero - ignore them.
4858          */
4859
4860         if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4861                 /* Ignore request */
4862                 if( DEBUGLVL( 3 ) ) {
4863                         dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4864                         dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4865                 }
4866                 END_PROFILE(SMBsetattrE);
4867                 return(outsize);
4868         } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4869                 /* set modify time = to access time if modify time was 0 */
4870                 unix_times.modtime = unix_times.actime;
4871         }
4872
4873         /* Set the date on this file */
4874         if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4875                 END_PROFILE(SMBsetattrE);
4876                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4877         }
4878   
4879         DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4880                 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4881
4882         END_PROFILE(SMBsetattrE);
4883         return(outsize);
4884 }
4885
4886
4887 /* Back from the dead for OS/2..... JRA. */
4888
4889 /****************************************************************************
4890  Reply to a SMBwritebmpx (write block multiplex primary) request.
4891 ****************************************************************************/
4892
4893 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4894 {
4895         size_t numtowrite;
4896         ssize_t nwritten = -1;
4897         int outsize = 0;
4898         SMB_OFF_T startpos;
4899         size_t tcount;
4900         BOOL write_through;
4901         int smb_doff;
4902         char *data;
4903         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4904         START_PROFILE(SMBwriteBmpx);
4905
4906         CHECK_FSP(fsp,conn);
4907         CHECK_WRITE(fsp);
4908         CHECK_ERROR(fsp);
4909
4910         tcount = SVAL(inbuf,smb_vwv1);
4911         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4912         write_through = BITSETW(inbuf+smb_vwv7,0);
4913         numtowrite = SVAL(inbuf,smb_vwv10);
4914         smb_doff = SVAL(inbuf,smb_vwv11);
4915
4916         data = smb_base(inbuf) + smb_doff;
4917
4918         /* If this fails we need to send an SMBwriteC response,
4919                 not an SMBwritebmpx - set this up now so we don't forget */
4920         SCVAL(outbuf,smb_com,SMBwritec);
4921
4922         if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
4923                 END_PROFILE(SMBwriteBmpx);
4924                 return(ERROR_DOS(ERRDOS,ERRlock));
4925         }
4926
4927         nwritten = write_file(fsp,data,startpos,numtowrite);
4928
4929         if(lp_syncalways(SNUM(conn)) || write_through)
4930                 sync_file(conn,fsp);
4931   
4932         if(nwritten < (ssize_t)numtowrite) {
4933                 END_PROFILE(SMBwriteBmpx);
4934                 return(UNIXERROR(ERRHRD,ERRdiskfull));
4935         }
4936
4937         /* If the maximum to be written to this file
4938                 is greater than what we just wrote then set
4939                 up a secondary struct to be attached to this
4940                 fd, we will use this to cache error messages etc. */
4941
4942         if((ssize_t)tcount > nwritten) {
4943                 write_bmpx_struct *wbms;
4944                 if(fsp->wbmpx_ptr != NULL)
4945                         wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4946                 else
4947                         wbms = SMB_MALLOC_P(write_bmpx_struct);
4948                 if(!wbms) {
4949                         DEBUG(0,("Out of memory in reply_readmpx\n"));
4950                         END_PROFILE(SMBwriteBmpx);
4951                         return(ERROR_DOS(ERRSRV,ERRnoresource));
4952                 }
4953                 wbms->wr_mode = write_through;
4954                 wbms->wr_discard = False; /* No errors yet */
4955                 wbms->wr_total_written = nwritten;
4956                 wbms->wr_errclass = 0;
4957                 wbms->wr_error = 0;
4958                 fsp->wbmpx_ptr = wbms;
4959         }
4960
4961         /* We are returning successfully, set the message type back to
4962                 SMBwritebmpx */
4963         SCVAL(outbuf,smb_com,SMBwriteBmpx);
4964   
4965         outsize = set_message(outbuf,1,0,True);
4966   
4967         SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4968   
4969         DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4970                         fsp->fnum, (int)numtowrite, (int)nwritten ) );
4971
4972         if (write_through && tcount==nwritten) {
4973                 /* We need to send both a primary and a secondary response */
4974                 smb_setlen(outbuf,outsize - 4);
4975                 if (!send_smb(smbd_server_fd(),outbuf))
4976                         exit_server("reply_writebmpx: send_smb failed.");
4977
4978                 /* Now the secondary */
4979                 outsize = set_message(outbuf,1,0,True);
4980                 SCVAL(outbuf,smb_com,SMBwritec);
4981                 SSVAL(outbuf,smb_vwv0,nwritten);
4982         }
4983
4984         END_PROFILE(SMBwriteBmpx);
4985         return(outsize);
4986 }
4987
4988 /****************************************************************************
4989  Reply to a SMBwritebs (write block multiplex secondary) request.
4990 ****************************************************************************/
4991
4992 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4993 {
4994         size_t numtowrite;
4995         ssize_t nwritten = -1;
4996         int outsize = 0;
4997         SMB_OFF_T startpos;
4998         size_t tcount;
4999         BOOL write_through;
5000         int smb_doff;
5001         char *data;
5002         write_bmpx_struct *wbms;
5003         BOOL send_response = False; 
5004         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5005         START_PROFILE(SMBwriteBs);
5006
5007         CHECK_FSP(fsp,conn);
5008         CHECK_WRITE(fsp);
5009
5010         tcount = SVAL(inbuf,smb_vwv1);
5011         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5012         numtowrite = SVAL(inbuf,smb_vwv6);
5013         smb_doff = SVAL(inbuf,smb_vwv7);
5014
5015         data = smb_base(inbuf) + smb_doff;
5016
5017         /* We need to send an SMBwriteC response, not an SMBwritebs */
5018         SCVAL(outbuf,smb_com,SMBwritec);
5019
5020         /* This fd should have an auxiliary struct attached,
5021                 check that it does */
5022         wbms = fsp->wbmpx_ptr;
5023         if(!wbms) {
5024                 END_PROFILE(SMBwriteBs);
5025                 return(-1);
5026         }
5027
5028         /* If write through is set we can return errors, else we must cache them */
5029         write_through = wbms->wr_mode;
5030
5031         /* Check for an earlier error */
5032         if(wbms->wr_discard) {
5033                 END_PROFILE(SMBwriteBs);
5034                 return -1; /* Just discard the packet */
5035         }
5036
5037         nwritten = write_file(fsp,data,startpos,numtowrite);
5038
5039         if(lp_syncalways(SNUM(conn)) || write_through)
5040                 sync_file(conn,fsp);
5041   
5042         if (nwritten < (ssize_t)numtowrite) {
5043                 if(write_through) {
5044                         /* We are returning an error - we can delete the aux struct */
5045                         if (wbms)
5046                                 free((char *)wbms);
5047                         fsp->wbmpx_ptr = NULL;
5048                         END_PROFILE(SMBwriteBs);
5049                         return(ERROR_DOS(ERRHRD,ERRdiskfull));
5050                 }
5051                 END_PROFILE(SMBwriteBs);
5052                 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
5053         }
5054
5055         /* Increment the total written, if this matches tcount
5056                 we can discard the auxiliary struct (hurrah !) and return a writeC */
5057         wbms->wr_total_written += nwritten;
5058         if(wbms->wr_total_written >= tcount) {
5059                 if (write_through) {
5060                         outsize = set_message(outbuf,1,0,True);
5061                         SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);    
5062                         send_response = True;
5063                 }
5064
5065                 free((char *)wbms);
5066                 fsp->wbmpx_ptr = NULL;
5067         }
5068
5069         if(send_response) {
5070                 END_PROFILE(SMBwriteBs);
5071                 return(outsize);
5072         }
5073
5074         END_PROFILE(SMBwriteBs);
5075         return(-1);
5076 }
5077
5078 /****************************************************************************
5079  Reply to a SMBgetattrE.
5080 ****************************************************************************/
5081
5082 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5083 {
5084         SMB_STRUCT_STAT sbuf;
5085         int outsize = 0;
5086         int mode;
5087         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5088         START_PROFILE(SMBgetattrE);
5089
5090         outsize = set_message(outbuf,11,0,True);
5091
5092         if(!fsp || (fsp->conn != conn)) {
5093                 END_PROFILE(SMBgetattrE);
5094                 return ERROR_DOS(ERRDOS,ERRbadfid);
5095         }
5096
5097         /* Do an fstat on this file */
5098         if(fsp_stat(fsp, &sbuf)) {
5099                 END_PROFILE(SMBgetattrE);
5100                 return(UNIXERROR(ERRDOS,ERRnoaccess));
5101         }
5102   
5103         mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5104   
5105         /*
5106          * Convert the times into dos times. Set create
5107          * date to be last modify date as UNIX doesn't save
5108          * this.
5109          */
5110
5111         put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5112         put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5113         put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5114
5115         if (mode & aDIR) {
5116                 SIVAL(outbuf,smb_vwv6,0);
5117                 SIVAL(outbuf,smb_vwv8,0);
5118         } else {
5119                 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
5120                 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5121                 SIVAL(outbuf,smb_vwv8,allocation_size);
5122         }
5123         SSVAL(outbuf,smb_vwv10, mode);
5124   
5125         DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5126   
5127         END_PROFILE(SMBgetattrE);
5128         return(outsize);
5129 }