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