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