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