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