Implemented the level 1010 NT rename level. Many fixes for Samba4 test
[vlendec/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                 END_PROFILE(SMBgetatr);
501                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
502         }
503  
504         outsize = set_message(outbuf,10,0,True);
505
506         SSVAL(outbuf,smb_vwv0,mode);
507         if(lp_dos_filetime_resolution(SNUM(conn)) )
508                 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
509         else
510                 put_dos_date3(outbuf,smb_vwv1,mtime);
511         SIVAL(outbuf,smb_vwv3,(uint32)size);
512
513         if (Protocol >= PROTOCOL_NT1)
514                 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
515   
516         DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
517   
518         END_PROFILE(SMBgetatr);
519         return(outsize);
520 }
521
522 /****************************************************************************
523  Reply to a setatr.
524 ****************************************************************************/
525
526 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
527 {
528         pstring fname;
529         int outsize = 0;
530         BOOL ok=False;
531         int mode;
532         time_t mtime;
533         SMB_STRUCT_STAT sbuf;
534         BOOL bad_path = False;
535         char *p;
536
537         START_PROFILE(SMBsetatr);
538
539         p = smb_buf(inbuf) + 1;
540         p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
541         unix_convert(fname,conn,0,&bad_path,&sbuf);
542
543         mode = SVAL(inbuf,smb_vwv0);
544         mtime = make_unix_date3(inbuf+smb_vwv1);
545   
546         if (mode != FILE_ATTRIBUTE_NORMAL) {
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         } else {
555                 ok = True;
556         }
557
558         if (ok)
559                 ok = set_filetime(conn,fname,mtime);
560   
561         if (!ok) {
562                 END_PROFILE(SMBsetatr);
563                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
564         }
565  
566         outsize = set_message(outbuf,0,0,True);
567   
568         DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
569   
570         END_PROFILE(SMBsetatr);
571         return(outsize);
572 }
573
574 /****************************************************************************
575  Reply to a dskattr.
576 ****************************************************************************/
577
578 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
579 {
580         int outsize = 0;
581         SMB_BIG_UINT dfree,dsize,bsize;
582         START_PROFILE(SMBdskattr);
583
584         SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize);
585   
586         outsize = set_message(outbuf,5,0,True);
587         
588         if (Protocol <= PROTOCOL_LANMAN2) {
589                 double total_space, free_space;
590                 /* we need to scale this to a number that DOS6 can handle. We
591                    use floating point so we can handle large drives on systems
592                    that don't have 64 bit integers 
593
594                    we end up displaying a maximum of 2G to DOS systems
595                 */
596                 total_space = dsize * (double)bsize;
597                 free_space = dfree * (double)bsize;
598
599                 dsize = (total_space+63*512) / (64*512);
600                 dfree = (free_space+63*512) / (64*512);
601                 
602                 if (dsize > 0xFFFF) dsize = 0xFFFF;
603                 if (dfree > 0xFFFF) dfree = 0xFFFF;
604
605                 SSVAL(outbuf,smb_vwv0,dsize);
606                 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
607                 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
608                 SSVAL(outbuf,smb_vwv3,dfree);
609         } else {
610                 SSVAL(outbuf,smb_vwv0,dsize);
611                 SSVAL(outbuf,smb_vwv1,bsize/512);
612                 SSVAL(outbuf,smb_vwv2,512);
613                 SSVAL(outbuf,smb_vwv3,dfree);
614         }
615
616         DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
617
618         END_PROFILE(SMBdskattr);
619         return(outsize);
620 }
621
622 /****************************************************************************
623  Reply to a search.
624  Can be called from SMBsearch, SMBffirst or SMBfunique.
625 ****************************************************************************/
626
627 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
628 {
629         pstring mask;
630         pstring directory;
631         pstring fname;
632         SMB_OFF_T size;
633         int mode;
634         time_t date;
635         int dirtype;
636         int outsize = 0;
637         int numentries = 0;
638         BOOL finished = False;
639         int maxentries;
640         int i;
641         char *p;
642         BOOL ok = False;
643         int status_len;
644         pstring path;
645         char status[21];
646         int dptr_num= -1;
647         BOOL check_descend = False;
648         BOOL expect_close = False;
649         BOOL can_open = True;
650         BOOL bad_path = False;
651         START_PROFILE(SMBsearch);
652
653         *mask = *directory = *fname = 0;
654
655         /* If we were called as SMBffirst then we must expect close. */
656         if(CVAL(inbuf,smb_com) == SMBffirst)
657                 expect_close = True;
658   
659         outsize = set_message(outbuf,1,3,True);
660         maxentries = SVAL(inbuf,smb_vwv0); 
661         dirtype = SVAL(inbuf,smb_vwv1);
662         p = smb_buf(inbuf) + 1;
663         p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
664         p++;
665         status_len = SVAL(p, 0);
666         p += 2;
667   
668         /* dirtype &= ~aDIR; */
669
670         if (status_len == 0) {
671                 SMB_STRUCT_STAT sbuf;
672                 pstring dir2;
673
674                 pstrcpy(directory,path);
675                 pstrcpy(dir2,path);
676                 unix_convert(directory,conn,0,&bad_path,&sbuf);
677                 unix_format(dir2);
678
679                 if (!check_name(directory,conn))
680                         can_open = False;
681
682                 p = strrchr_m(dir2,'/');
683                 if (p == NULL) {
684                         pstrcpy(mask,dir2);
685                         *dir2 = 0;
686                 } else {
687                         *p = 0;
688                         pstrcpy(mask,p+1);
689                 }
690
691                 p = strrchr_m(directory,'/');
692                 if (!p) 
693                         *directory = 0;
694                 else
695                         *p = 0;
696
697                 if (strlen(directory) == 0)
698                         pstrcpy(directory,".");
699                 memset((char *)status,'\0',21);
700                 SCVAL(status,0,(dirtype & 0x1F));
701         } else {
702                 int status_dirtype;
703
704                 memcpy(status,p,21);
705                 status_dirtype = CVAL(status,0) & 0x1F;
706                 if (status_dirtype != (dirtype & 0x1F))
707                         dirtype = status_dirtype;
708
709                 conn->dirptr = dptr_fetch(status+12,&dptr_num);      
710                 if (!conn->dirptr)
711                         goto SearchEmpty;
712                 string_set(&conn->dirpath,dptr_path(dptr_num));
713                 pstrcpy(mask, dptr_wcard(dptr_num));
714         }
715
716         if (can_open) {
717                 p = smb_buf(outbuf) + 3;
718                 ok = True;
719      
720                 if (status_len == 0) {
721                         dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
722                         if (dptr_num < 0) {
723                                 if(dptr_num == -2) {
724                                         END_PROFILE(SMBsearch);
725                                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
726                                 }
727                                 END_PROFILE(SMBsearch);
728                                 return ERROR_DOS(ERRDOS,ERRnofids);
729                         }
730                         dptr_set_wcard(dptr_num, strdup(mask));
731                         dptr_set_attr(dptr_num, dirtype);
732                 } else {
733                         dirtype = dptr_attr(dptr_num);
734                 }
735
736                 DEBUG(4,("dptr_num is %d\n",dptr_num));
737
738                 if (ok) {
739                         if ((dirtype&0x1F) == aVOLID) {   
740                                 memcpy(p,status,21);
741                                 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
742                                 dptr_fill(p+12,dptr_num);
743                                 if (dptr_zero(p+12) && (status_len==0))
744                                         numentries = 1;
745                                 else
746                                         numentries = 0;
747                                 p += DIR_STRUCT_SIZE;
748                         } else {
749                                 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
750                                 conn->dirpath,lp_dontdescend(SNUM(conn))));
751                                 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
752                                         check_descend = True;
753
754                                 for (i=numentries;(i<maxentries) && !finished;i++) {
755                                         finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
756                                         if (!finished) {
757                                                 memcpy(p,status,21);
758                                                 make_dir_struct(p,mask,fname,size,mode,date);
759                                                 dptr_fill(p+12,dptr_num);
760                                                 numentries++;
761                                         }
762                                         p += DIR_STRUCT_SIZE;
763                                 }
764                         }
765                 } /* if (ok ) */
766         }
767
768
769   SearchEmpty:
770
771         if (numentries == 0 || !ok) {
772                 SCVAL(outbuf,smb_rcls,ERRDOS);
773                 SSVAL(outbuf,smb_err,ERRnofiles);
774                 dptr_close(&dptr_num);
775         }
776
777         /* If we were called as SMBffirst with smb_search_id == NULL
778                 and no entries were found then return error and close dirptr 
779                 (X/Open spec) */
780
781         if(ok && expect_close && numentries == 0 && status_len == 0) {
782                 SCVAL(outbuf,smb_rcls,ERRDOS);
783                 SSVAL(outbuf,smb_err,ERRnofiles);
784                 /* Also close the dptr - we know it's gone */
785                 dptr_close(&dptr_num);
786         }
787
788         /* If we were called as SMBfunique, then we can close the dirptr now ! */
789         if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
790                 dptr_close(&dptr_num);
791
792         SSVAL(outbuf,smb_vwv0,numentries);
793         SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
794         SCVAL(smb_buf(outbuf),0,5);
795         SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
796
797         if (Protocol >= PROTOCOL_NT1)
798                 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
799   
800         outsize += DIR_STRUCT_SIZE*numentries;
801         smb_setlen(outbuf,outsize - 4);
802   
803         if ((! *directory) && dptr_path(dptr_num))
804                 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
805
806         DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
807                 smb_fn_name(CVAL(inbuf,smb_com)), 
808                 mask, directory, dirtype, numentries, maxentries ) );
809
810         END_PROFILE(SMBsearch);
811         return(outsize);
812 }
813
814 /****************************************************************************
815  Reply to a fclose (stop directory search).
816 ****************************************************************************/
817
818 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
819 {
820         int outsize = 0;
821         int status_len;
822         pstring path;
823         char status[21];
824         int dptr_num= -2;
825         char *p;
826
827         START_PROFILE(SMBfclose);
828
829         outsize = set_message(outbuf,1,0,True);
830         p = smb_buf(inbuf) + 1;
831         p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
832         p++;
833         status_len = SVAL(p,0);
834         p += 2;
835
836         if (status_len == 0) {
837                 END_PROFILE(SMBfclose);
838                 return ERROR_DOS(ERRSRV,ERRsrverror);
839         }
840
841         memcpy(status,p,21);
842
843         if(dptr_fetch(status+12,&dptr_num)) {
844                 /*  Close the dptr - we know it's gone */
845                 dptr_close(&dptr_num);
846         }
847
848         SSVAL(outbuf,smb_vwv0,0);
849
850         DEBUG(3,("search close\n"));
851
852         END_PROFILE(SMBfclose);
853         return(outsize);
854 }
855
856 /****************************************************************************
857  Reply to an open.
858 ****************************************************************************/
859
860 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
861 {
862         pstring fname;
863         int outsize = 0;
864         int fmode=0;
865         int share_mode;
866         SMB_OFF_T size = 0;
867         time_t mtime=0;
868         mode_t unixmode;
869         int rmode=0;
870         SMB_STRUCT_STAT sbuf;
871         BOOL bad_path = False;
872         files_struct *fsp;
873         int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
874         START_PROFILE(SMBopen);
875  
876         share_mode = SVAL(inbuf,smb_vwv0);
877
878         srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
879
880         RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
881
882         unix_convert(fname,conn,0,&bad_path,&sbuf);
883     
884         unixmode = unix_mode(conn,aARCH,fname);
885       
886         fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
887                         unixmode, oplock_request,&rmode,NULL);
888
889         if (!fsp) {
890                 END_PROFILE(SMBopen);
891                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
892         }
893
894         size = sbuf.st_size;
895         fmode = dos_mode(conn,fname,&sbuf);
896         mtime = sbuf.st_mtime;
897
898         if (fmode & aDIR) {
899                 DEBUG(3,("attempt to open a directory %s\n",fname));
900                 close_file(fsp,False);
901                 END_PROFILE(SMBopen);
902                 return ERROR_DOS(ERRDOS,ERRnoaccess);
903         }
904   
905         outsize = set_message(outbuf,7,0,True);
906         SSVAL(outbuf,smb_vwv0,fsp->fnum);
907         SSVAL(outbuf,smb_vwv1,fmode);
908         if(lp_dos_filetime_resolution(SNUM(conn)) )
909                 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
910         else
911                 put_dos_date3(outbuf,smb_vwv2,mtime);
912         SIVAL(outbuf,smb_vwv4,(uint32)size);
913         SSVAL(outbuf,smb_vwv6,rmode);
914
915         if (oplock_request && lp_fake_oplocks(SNUM(conn)))
916                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
917     
918         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
919                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
920         END_PROFILE(SMBopen);
921         return(outsize);
922 }
923
924 /****************************************************************************
925  Reply to an open and X.
926 ****************************************************************************/
927
928 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
929 {
930         pstring fname;
931         int smb_mode = SVAL(inbuf,smb_vwv3);
932         int smb_attr = SVAL(inbuf,smb_vwv5);
933         /* Breakout the oplock request bits so we can set the
934                 reply bits separately. */
935         BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
936         BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
937         BOOL oplock_request = ex_oplock_request | core_oplock_request;
938 #if 0
939         int open_flags = SVAL(inbuf,smb_vwv2);
940         int smb_sattr = SVAL(inbuf,smb_vwv4); 
941         uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
942 #endif
943         int smb_ofun = SVAL(inbuf,smb_vwv8);
944         mode_t unixmode;
945         SMB_OFF_T size=0;
946         int fmode=0,mtime=0,rmode=0;
947         SMB_STRUCT_STAT sbuf;
948         int smb_action = 0;
949         BOOL bad_path = False;
950         files_struct *fsp;
951         START_PROFILE(SMBopenX);
952
953         /* If it's an IPC, pass off the pipe handler. */
954         if (IS_IPC(conn)) {
955                 if (lp_nt_pipe_support()) {
956                         END_PROFILE(SMBopenX);
957                         return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
958                 } else {
959                         END_PROFILE(SMBopenX);
960                         return ERROR_DOS(ERRSRV,ERRaccess);
961                 }
962         }
963
964         /* XXXX we need to handle passed times, sattr and flags */
965         srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
966
967         RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
968
969         unix_convert(fname,conn,0,&bad_path,&sbuf);
970     
971         unixmode = unix_mode(conn,smb_attr | aARCH, fname);
972       
973         fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
974                         oplock_request, &rmode,&smb_action);
975       
976         if (!fsp) {
977                 END_PROFILE(SMBopenX);
978                 return set_bad_path_error(errno, bad_path, outbuf, 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                 END_PROFILE(SMBcreate);
1101                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1102         }
1103  
1104         outsize = set_message(outbuf,1,0,True);
1105         SSVAL(outbuf,smb_vwv0,fsp->fnum);
1106
1107         if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1108                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1109  
1110         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1111                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1112  
1113         DEBUG( 2, ( "new file %s\n", fname ) );
1114         DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname, fsp->fd, createmode, (int)unixmode ) );
1115
1116         END_PROFILE(SMBcreate);
1117         return(outsize);
1118 }
1119
1120 /****************************************************************************
1121  Reply to a create temporary file.
1122 ****************************************************************************/
1123
1124 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1125 {
1126         pstring fname;
1127         int outsize = 0;
1128         int createmode;
1129         mode_t unixmode;
1130         BOOL bad_path = False;
1131         files_struct *fsp;
1132         int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1133         int tmpfd;
1134         SMB_STRUCT_STAT sbuf;
1135         char *p, *s;
1136
1137         START_PROFILE(SMBctemp);
1138
1139         createmode = SVAL(inbuf,smb_vwv0);
1140         srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
1141         pstrcat(fname,"\\TMXXXXXX");
1142
1143         RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1144
1145         unix_convert(fname,conn,0,&bad_path,&sbuf);
1146   
1147         unixmode = unix_mode(conn,createmode,fname);
1148   
1149         tmpfd = smb_mkstemp(fname);
1150         if (tmpfd == -1) {
1151                 END_PROFILE(SMBctemp);
1152                 return(UNIXERROR(ERRDOS,ERRnoaccess));
1153         }
1154
1155         SMB_VFS_STAT(conn,fname,&sbuf);
1156
1157         /* Open file in dos compatibility share mode. */
1158         /* We should fail if file does not exist. */
1159         fsp = open_file_shared(conn,fname,&sbuf,
1160                 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1161                 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1162                 unixmode, oplock_request, NULL, NULL);
1163
1164         /* close fd from smb_mkstemp() */
1165         close(tmpfd);
1166
1167         if (!fsp) {
1168                 END_PROFILE(SMBctemp);
1169                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1170         }
1171
1172         outsize = set_message(outbuf,1,0,True);
1173         SSVAL(outbuf,smb_vwv0,fsp->fnum);
1174
1175         /* the returned filename is relative to the directory */
1176         s = strrchr_m(fname, '/');
1177         if (!s)
1178                 s = fname;
1179         else
1180                 s++;
1181
1182         p = smb_buf(outbuf);
1183         SSVALS(p, 0, -1); /* what is this? not in spec */
1184         SSVAL(p, 2, strlen(s));
1185         p += 4;
1186         p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
1187         outsize = set_message_end(outbuf, p);
1188
1189         if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1190                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1191   
1192         if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1193                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1194
1195         DEBUG( 2, ( "created temp file %s\n", fname ) );
1196         DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1197                         fname, fsp->fd, createmode, (int)unixmode ) );
1198
1199         END_PROFILE(SMBctemp);
1200         return(outsize);
1201 }
1202
1203 /*******************************************************************
1204  Check if a user is allowed to rename a file.
1205 ********************************************************************/
1206
1207 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1208 {
1209         int smb_action;
1210         int access_mode;
1211         files_struct *fsp;
1212
1213         if (!CAN_WRITE(conn))
1214                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1215         
1216         if (S_ISDIR(pst->st_mode))
1217                 return NT_STATUS_OK;
1218
1219         /* We need a better way to return NT status codes from open... */
1220         unix_ERR_class = 0;
1221         unix_ERR_code = 0;
1222
1223         fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1224                 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1225
1226         if (!fsp) {
1227                 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1228                 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1229                         ret = NT_STATUS_SHARING_VIOLATION;
1230                 unix_ERR_class = 0;
1231                 unix_ERR_code = 0;
1232                 return ret;
1233         }
1234         close_file(fsp,False);
1235         return NT_STATUS_OK;
1236 }
1237
1238 /*******************************************************************
1239  Check if a user is allowed to delete a file.
1240 ********************************************************************/
1241
1242 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
1243 {
1244         SMB_STRUCT_STAT sbuf;
1245         int fmode;
1246         int smb_action;
1247         int access_mode;
1248         files_struct *fsp;
1249
1250         DEBUG(10,("can_delete: %s, dirtype = %d\n",
1251                 fname, dirtype ));
1252
1253         if (!CAN_WRITE(conn))
1254                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1255
1256         if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0)
1257                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1258
1259         fmode = dos_mode(conn,fname,&sbuf);
1260
1261         /* Can't delete a directory. */
1262         if (fmode & aDIR)
1263                 return NT_STATUS_FILE_IS_A_DIRECTORY;
1264 #if 0 /* JRATEST */
1265         else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1266                 return NT_STATUS_OBJECT_NAME_INVALID;
1267 #endif /* JRATEST */
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 = NT_STATUS_OK;
2884                 if(errno == ENOENT) {
2885                         unix_ERR_class = ERRDOS;
2886                         if (bad_path) {
2887                                 unix_ERR_code = ERRbadpath;
2888                                 nterr = NT_STATUS_OBJECT_PATH_NOT_FOUND;
2889                         } else {
2890                                 unix_ERR_code = ERRbadfile;
2891                                 nterr = NT_STATUS_OBJECT_NAME_NOT_FOUND;
2892                         }
2893                 }
2894                 if (!NT_STATUS_IS_OK(nterr))
2895                         return nterr;
2896                 return map_nt_error_from_unix(errno);
2897         }
2898         
2899         return NT_STATUS_OK;
2900 }
2901
2902 /****************************************************************************
2903  Reply to a mkdir.
2904 ****************************************************************************/
2905
2906 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2907 {
2908         pstring directory;
2909         int outsize;
2910         NTSTATUS status;
2911         START_PROFILE(SMBmkdir);
2912  
2913         srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
2914
2915         RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
2916
2917         status = mkdir_internal(conn, directory);
2918         if (!NT_STATUS_IS_OK(status))
2919                 return ERROR_NT(status);
2920
2921         outsize = set_message(outbuf,0,0,True);
2922
2923         DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
2924
2925         END_PROFILE(SMBmkdir);
2926         return(outsize);
2927 }
2928
2929 /****************************************************************************
2930  Static function used by reply_rmdir to delete an entire directory
2931  tree recursively. Return False on ok, True on fail.
2932 ****************************************************************************/
2933
2934 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
2935 {
2936         const char *dname = NULL;
2937         BOOL ret = False;
2938         void *dirptr = OpenDir(conn, directory, False);
2939
2940         if(dirptr == NULL)
2941                 return True;
2942
2943         while((dname = ReadDirName(dirptr))) {
2944                 pstring fullname;
2945                 SMB_STRUCT_STAT st;
2946
2947                 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2948                         continue;
2949
2950                 /* Construct the full name. */
2951                 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
2952                         errno = ENOMEM;
2953                         ret = True;
2954                         break;
2955                 }
2956
2957                 pstrcpy(fullname, directory);
2958                 pstrcat(fullname, "/");
2959                 pstrcat(fullname, dname);
2960
2961                 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
2962                         ret = True;
2963                         break;
2964                 }
2965
2966                 if(st.st_mode & S_IFDIR) {
2967                         if(recursive_rmdir(conn, fullname)!=0) {
2968                                 ret = True;
2969                                 break;
2970                         }
2971                         if(SMB_VFS_RMDIR(conn,fullname) != 0) {
2972                                 ret = True;
2973                                 break;
2974                         }
2975                 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
2976                         ret = True;
2977                         break;
2978                 }
2979         }
2980         CloseDir(dirptr);
2981         return ret;
2982 }
2983
2984 /****************************************************************************
2985  The internals of the rmdir code - called elsewhere.
2986 ****************************************************************************/
2987
2988 BOOL rmdir_internals(connection_struct *conn, char *directory)
2989 {
2990         BOOL ok;
2991
2992         ok = (SMB_VFS_RMDIR(conn,directory) == 0);
2993         if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
2994                 /* 
2995                  * Check to see if the only thing in this directory are
2996                  * vetoed files/directories. If so then delete them and
2997                  * retry. If we fail to delete any of them (and we *don't*
2998                  * do a recursive delete) then fail the rmdir.
2999                  */
3000                 BOOL all_veto_files = True;
3001                 const char *dname;
3002                 void *dirptr = OpenDir(conn, directory, False);
3003
3004                 if(dirptr != NULL) {
3005                         int dirpos = TellDir(dirptr);
3006                         while ((dname = ReadDirName(dirptr))) {
3007                                 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3008                                         continue;
3009                                 if(!IS_VETO_PATH(conn, dname)) {
3010                                         all_veto_files = False;
3011                                         break;
3012                                 }
3013                         }
3014
3015                         if(all_veto_files) {
3016                                 SeekDir(dirptr,dirpos);
3017                                 while ((dname = ReadDirName(dirptr))) {
3018                                         pstring fullname;
3019                                         SMB_STRUCT_STAT st;
3020
3021                                         if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3022                                                 continue;
3023
3024                                         /* Construct the full name. */
3025                                         if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3026                                                 errno = ENOMEM;
3027                                                 break;
3028                                         }
3029
3030                                         pstrcpy(fullname, directory);
3031                                         pstrcat(fullname, "/");
3032                                         pstrcat(fullname, dname);
3033                      
3034                                         if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3035                                                 break;
3036                                         if(st.st_mode & S_IFDIR) {
3037                                                 if(lp_recursive_veto_delete(SNUM(conn))) {
3038                                                         if(recursive_rmdir(conn, fullname) != 0)
3039                                                                 break;
3040                                                 }
3041                                                 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3042                                                         break;
3043                                         } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3044                                                 break;
3045                                 }
3046                                 CloseDir(dirptr);
3047                                 /* Retry the rmdir */
3048                                 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3049                         } else {
3050                                 CloseDir(dirptr);
3051                         }
3052                 } else {
3053                         errno = ENOTEMPTY;
3054                 }
3055         }
3056
3057         if (!ok)
3058                 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3059
3060         return ok;
3061 }
3062
3063 /****************************************************************************
3064  Reply to a rmdir.
3065 ****************************************************************************/
3066
3067 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3068 {
3069         pstring directory;
3070         int outsize = 0;
3071         BOOL ok = False;
3072         BOOL bad_path = False;
3073         SMB_STRUCT_STAT sbuf;
3074         START_PROFILE(SMBrmdir);
3075
3076         srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
3077
3078         RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3079
3080         unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3081   
3082         if (check_name(directory,conn)) {
3083                 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3084                 ok = rmdir_internals(conn, directory);
3085         }
3086   
3087         if (!ok) {
3088                 END_PROFILE(SMBrmdir);
3089                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3090         }
3091  
3092         outsize = set_message(outbuf,0,0,True);
3093   
3094         DEBUG( 3, ( "rmdir %s\n", directory ) );
3095   
3096         END_PROFILE(SMBrmdir);
3097         return(outsize);
3098 }
3099
3100 /*******************************************************************
3101  Resolve wildcards in a filename rename.
3102 ********************************************************************/
3103
3104 static BOOL resolve_wildcards(const char *name1, char *name2)
3105 {
3106         fstring root1,root2;
3107         fstring ext1,ext2;
3108         char *p,*p2, *pname1, *pname2;
3109         int available_space;
3110         
3111
3112         pname1 = strrchr_m(name1,'/');
3113         pname2 = strrchr_m(name2,'/');
3114
3115         if (!pname1 || !pname2)
3116                 return(False);
3117   
3118         fstrcpy(root1,pname1);
3119         fstrcpy(root2,pname2);
3120         p = strrchr_m(root1,'.');
3121         if (p) {
3122                 *p = 0;
3123                 fstrcpy(ext1,p+1);
3124         } else {
3125                 fstrcpy(ext1,"");    
3126         }
3127         p = strrchr_m(root2,'.');
3128         if (p) {
3129                 *p = 0;
3130                 fstrcpy(ext2,p+1);
3131         } else {
3132                 fstrcpy(ext2,"");    
3133         }
3134
3135         p = root1;
3136         p2 = root2;
3137         while (*p2) {
3138                 if (*p2 == '?') {
3139                         *p2 = *p;
3140                         p2++;
3141                 } else {
3142                         p2++;
3143                 }
3144                 if (*p)
3145                         p++;
3146         }
3147
3148         p = ext1;
3149         p2 = ext2;
3150         while (*p2) {
3151                 if (*p2 == '?') {
3152                         *p2 = *p;
3153                         p2++;
3154                 } else {
3155                         p2++;
3156                 }
3157                 if (*p)
3158                         p++;
3159         }
3160
3161         available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3162         
3163         if (ext2[0]) {
3164                 snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3165         } else {
3166                 pstrcpy_base(pname2, root2, name2);
3167         }
3168
3169         return(True);
3170 }
3171
3172 /****************************************************************************
3173  Ensure open files have their names updates.
3174 ****************************************************************************/
3175
3176 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3177 {
3178         files_struct *fsp;
3179         BOOL did_rename = False;
3180
3181         for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3182                 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3183                         fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3184                         fsp->fsp_name, newname ));
3185                 string_set(&fsp->fsp_name, newname);
3186                 did_rename = True;
3187         }
3188
3189         if (!did_rename)
3190                 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3191                         (unsigned int)dev, (double)inode, newname ));
3192 }
3193
3194 /****************************************************************************
3195  Rename an open file - given an fsp.
3196 ****************************************************************************/
3197
3198 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, BOOL replace_if_exists)
3199 {
3200         SMB_STRUCT_STAT sbuf;
3201         BOOL bad_path = False;
3202         pstring newname_last_component;
3203         NTSTATUS error = NT_STATUS_OK;
3204         BOOL dest_exists;
3205
3206         ZERO_STRUCT(sbuf);
3207         unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3208
3209         /* Ensure newname contains a '/' */
3210         if(strrchr_m(newname,'/') == 0) {
3211                 pstring tmpstr;
3212                 
3213                 pstrcpy(tmpstr, "./");
3214                 pstrcat(tmpstr, newname);
3215                 pstrcpy(newname, tmpstr);
3216         }
3217
3218         /*
3219          * Check for special case with case preserving and not
3220          * case sensitive. If the old last component differs from the original
3221          * last component only by case, then we should allow
3222          * the rename (user is trying to change the case of the
3223          * filename).
3224          */
3225
3226         if((case_sensitive == False) && (case_preserve == True) &&
3227                         strequal(newname, fsp->fsp_name)) {
3228                 char *p;
3229                 pstring newname_modified_last_component;
3230
3231                 /*
3232                  * Get the last component of the modified name.
3233                  * Note that we guarantee that newname contains a '/'
3234                  * character above.
3235                  */
3236                 p = strrchr_m(newname,'/');
3237                 pstrcpy(newname_modified_last_component,p+1);
3238                         
3239                 if(strcsequal(newname_modified_last_component, 
3240                               newname_last_component) == False) {
3241                         /*
3242                          * Replace the modified last component with
3243                          * the original.
3244                          */
3245                         pstrcpy(p+1, newname_last_component);
3246                 }
3247         }
3248
3249         /*
3250          * If the src and dest names are identical - including case,
3251          * don't do the rename, just return success.
3252          */
3253
3254         if (strcsequal(fsp->fsp_name, newname)) {
3255                 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3256                         newname));
3257                 return NT_STATUS_OK;
3258         }
3259
3260         dest_exists = vfs_object_exist(conn,newname,NULL);
3261
3262         if(!replace_if_exists && dest_exists) {
3263                 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3264                         fsp->fsp_name,newname));
3265                 return NT_STATUS_OBJECT_NAME_COLLISION;
3266         }
3267
3268         error = can_rename(newname,conn,&sbuf);
3269
3270         if (dest_exists && !NT_STATUS_IS_OK(error)) {
3271                 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3272                         nt_errstr(error), fsp->fsp_name,newname));
3273                 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3274                         error = NT_STATUS_ACCESS_DENIED;
3275                 return error;
3276         }
3277
3278         if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3279                 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3280                         fsp->fsp_name,newname));
3281                 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3282                 return NT_STATUS_OK;    
3283         }
3284
3285         if (errno == ENOTDIR || errno == EISDIR)
3286                 error = NT_STATUS_OBJECT_NAME_COLLISION;
3287         else
3288                 error = map_nt_error_from_unix(errno);
3289                 
3290         DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3291                 nt_errstr(error), fsp->fsp_name,newname));
3292
3293         return error;
3294 }
3295
3296 /****************************************************************************
3297  The guts of the rename command, split out so it may be called by the NT SMB
3298  code. 
3299 ****************************************************************************/
3300
3301 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists)
3302 {
3303         pstring directory;
3304         pstring mask;
3305         pstring newname_last_component;
3306         char *p;
3307         BOOL has_wild;
3308         BOOL bad_path1 = False;
3309         BOOL bad_path2 = False;
3310         int count=0;
3311         NTSTATUS error = NT_STATUS_OK;
3312         BOOL rc = True;
3313         SMB_STRUCT_STAT sbuf1, sbuf2;
3314
3315         *directory = *mask = 0;
3316
3317         ZERO_STRUCT(sbuf1);
3318         ZERO_STRUCT(sbuf2);
3319         rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3320         unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3321
3322         /*
3323          * Split the old name into directory and last component
3324          * strings. Note that unix_convert may have stripped off a 
3325          * leading ./ from both name and newname if the rename is 
3326          * at the root of the share. We need to make sure either both
3327          * name and newname contain a / character or neither of them do
3328          * as this is checked in resolve_wildcards().
3329          */
3330         
3331         p = strrchr_m(name,'/');
3332         if (!p) {
3333                 pstrcpy(directory,".");
3334                 pstrcpy(mask,name);
3335         } else {
3336                 *p = 0;
3337                 pstrcpy(directory,name);
3338                 pstrcpy(mask,p+1);
3339                 *p = '/'; /* Replace needed for exceptional test below. */
3340         }
3341
3342         /*
3343          * We should only check the mangled cache
3344          * here if unix_convert failed. This means
3345          * that the path in 'mask' doesn't exist
3346          * on the file system and so we need to look
3347          * for a possible mangle. This patch from
3348          * Tine Smukavec <valentin.smukavec@hermes.si>.
3349          */
3350
3351         if (!rc && mangle_is_mangled(mask))
3352                 mangle_check_cache( mask );
3353
3354         has_wild = ms_has_wild(mask);
3355
3356         if (!has_wild) {
3357                 /*
3358                  * No wildcards - just process the one file.
3359                  */
3360                 BOOL is_short_name = mangle_is_8_3(name, True);
3361
3362                 /* Add a terminating '/' to the directory name. */
3363                 pstrcat(directory,"/");
3364                 pstrcat(directory,mask);
3365                 
3366                 /* Ensure newname contains a '/' also */
3367                 if(strrchr_m(newname,'/') == 0) {
3368                         pstring tmpstr;
3369                         
3370                         pstrcpy(tmpstr, "./");
3371                         pstrcat(tmpstr, newname);
3372                         pstrcpy(newname, tmpstr);
3373                 }
3374                 
3375                 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3376 directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", 
3377                          case_sensitive, case_preserve, short_case_preserve, directory, 
3378                          newname, newname_last_component, is_short_name));
3379
3380                 /*
3381                  * Check for special case with case preserving and not
3382                  * case sensitive, if directory and newname are identical,
3383                  * and the old last component differs from the original
3384                  * last component only by case, then we should allow
3385                  * the rename (user is trying to change the case of the
3386                  * filename).
3387                  */
3388                 if((case_sensitive == False) && 
3389                    (((case_preserve == True) && 
3390                      (is_short_name == False)) || 
3391                     ((short_case_preserve == True) && 
3392                      (is_short_name == True))) &&
3393                    strcsequal(directory, newname)) {
3394                         pstring newname_modified_last_component;
3395
3396                         /*
3397                          * Get the last component of the modified name.
3398                          * Note that we guarantee that newname contains a '/'
3399                          * character above.
3400                          */
3401                         p = strrchr_m(newname,'/');
3402                         pstrcpy(newname_modified_last_component,p+1);
3403                         
3404                         if(strcsequal(newname_modified_last_component, 
3405                                       newname_last_component) == False) {
3406                                 /*
3407                                  * Replace the modified last component with
3408                                  * the original.
3409                                  */
3410                                 pstrcpy(p+1, newname_last_component);
3411                         }
3412                 }
3413         
3414                 resolve_wildcards(directory,newname);
3415         
3416                 /*
3417                  * The source object must exist.
3418                  */
3419
3420                 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3421                         DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3422                                 directory,newname));
3423
3424                         if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3425                                 /*
3426                                  * Must return different errors depending on whether the parent
3427                                  * directory existed or not.
3428                                  */
3429
3430                                 p = strrchr_m(directory, '/');
3431                                 if (!p)
3432                                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3433                                 *p = '\0';
3434                                 if (vfs_object_exist(conn, directory, NULL))
3435                                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3436                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3437                         }
3438                         error = map_nt_error_from_unix(errno);
3439                         DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3440                                 nt_errstr(error), directory,newname));
3441
3442                         return error;
3443                 }
3444
3445                 error = can_rename(directory,conn,&sbuf1);
3446
3447                 if (!NT_STATUS_IS_OK(error)) {
3448                         DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3449                                 nt_errstr(error), directory,newname));
3450                         return error;
3451                 }
3452
3453                 /*
3454                  * If the src and dest names are identical - including case,
3455                  * don't do the rename, just return success.
3456                  */
3457
3458                 if (strcsequal(directory, newname)) {
3459                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3460                         DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3461                         return NT_STATUS_OK;
3462                 }
3463
3464                 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3465                         DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3466                                 directory,newname));
3467                         return NT_STATUS_OBJECT_NAME_COLLISION;
3468                 }
3469
3470                 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3471                         DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3472                                 directory,newname));
3473                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3474                         return NT_STATUS_OK;    
3475                 }
3476
3477                 if (errno == ENOTDIR || errno == EISDIR)
3478                         error = NT_STATUS_OBJECT_NAME_COLLISION;
3479                 else
3480                         error = map_nt_error_from_unix(errno);
3481                 
3482                 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3483                         nt_errstr(error), directory,newname));
3484
3485                 return error;
3486         } else {
3487                 /*
3488                  * Wildcards - process each file that matches.
3489                  */
3490                 void *dirptr = NULL;
3491                 const char *dname;
3492                 pstring destname;
3493                 
3494                 if (check_name(directory,conn))
3495                         dirptr = OpenDir(conn, directory, True);
3496                 
3497                 if (dirptr) {
3498                         error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3499                         
3500                         if (strequal(mask,"????????.???"))
3501                                 pstrcpy(mask,"*");
3502                         
3503                         while ((dname = ReadDirName(dirptr))) {
3504                                 pstring fname;
3505
3506                                 pstrcpy(fname,dname);
3507                                 
3508                                 if(!mask_match(fname, mask, case_sensitive))
3509                                         continue;
3510                                 
3511                                 error = NT_STATUS_ACCESS_DENIED;
3512                                 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3513                                 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3514                                         error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3515                                         DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3516                                         continue;
3517                                 }
3518                                 error = can_rename(fname,conn,&sbuf1);
3519                                 if (!NT_STATUS_IS_OK(error)) {
3520                                         DEBUG(6,("rename %s refused\n", fname));
3521                                         continue;
3522                                 }
3523                                 pstrcpy(destname,newname);
3524                                 
3525                                 if (!resolve_wildcards(fname,destname)) {
3526                                         DEBUG(6,("resolve_wildcards %s %s failed\n", 
3527                                                  fname, destname));
3528                                         continue;
3529                                 }
3530                                 
3531                                 if (!replace_if_exists && 
3532                                     vfs_file_exist(conn,destname, NULL)) {
3533                                         DEBUG(6,("file_exist %s\n", destname));
3534                                         error = NT_STATUS_OBJECT_NAME_COLLISION;
3535                                         continue;
3536                                 }
3537                                 
3538                                 if (!SMB_VFS_RENAME(conn,fname,destname)) {
3539                                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3540                                         count++;
3541                                 }
3542                                 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3543                         }
3544                         CloseDir(dirptr);
3545                 }
3546         }
3547         
3548         if (count == 0 && NT_STATUS_IS_OK(error)) {
3549                 error = map_nt_error_from_unix(errno);
3550         }
3551         
3552         return error;
3553 }
3554
3555 /****************************************************************************
3556  Reply to a mv.
3557 ****************************************************************************/
3558
3559 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, 
3560              int dum_buffsize)
3561 {
3562         int outsize = 0;
3563         pstring name;
3564         pstring newname;
3565         char *p;
3566         NTSTATUS status;
3567
3568         START_PROFILE(SMBmv);
3569
3570         p = smb_buf(inbuf) + 1;
3571         p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
3572         p++;
3573         p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
3574         
3575         RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3576         RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3577         
3578         DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3579         
3580         status = rename_internals(conn, name, newname, False);
3581         if (!NT_STATUS_IS_OK(status)) {
3582                 return ERROR_NT(status);
3583         }
3584
3585         /*
3586          * Win2k needs a changenotify request response before it will
3587          * update after a rename..
3588          */     
3589         process_pending_change_notify_queue((time_t)0);
3590         outsize = set_message(outbuf,0,0,True);
3591   
3592         END_PROFILE(SMBmv);
3593         return(outsize);
3594 }
3595
3596 /*******************************************************************
3597  Copy a file as part of a reply_copy.
3598 ******************************************************************/
3599
3600 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3601                       int count,BOOL target_is_directory, int *err_ret)
3602 {
3603         int Access,action;
3604         SMB_STRUCT_STAT src_sbuf, sbuf2;
3605         SMB_OFF_T ret=-1;
3606         files_struct *fsp1,*fsp2;
3607         pstring dest;
3608   
3609         *err_ret = 0;
3610
3611         pstrcpy(dest,dest1);
3612         if (target_is_directory) {
3613                 char *p = strrchr_m(src,'/');
3614                 if (p) 
3615                         p++;
3616                 else
3617                         p = src;
3618                 pstrcat(dest,"/");
3619                 pstrcat(dest,p);
3620         }
3621
3622         if (!vfs_file_exist(conn,src,&src_sbuf))
3623                 return(False);
3624
3625         fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3626                                         (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3627
3628         if (!fsp1)
3629                 return(False);
3630
3631         if (!target_is_directory && count)
3632                 ofun = FILE_EXISTS_OPEN;
3633
3634         if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
3635                 ZERO_STRUCTP(&sbuf2);
3636
3637         fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3638                         ofun,src_sbuf.st_mode,0,&Access,&action);
3639
3640         if (!fsp2) {
3641                 close_file(fsp1,False);
3642                 return(False);
3643         }
3644
3645         if ((ofun&3) == 1) {
3646                 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3647                         DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3648                         /*
3649                          * Stop the copy from occurring.
3650                          */
3651                         ret = -1;
3652                         src_sbuf.st_size = 0;
3653                 }
3654         }
3655   
3656         if (src_sbuf.st_size)
3657                 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
3658
3659         close_file(fsp1,False);
3660
3661         /* Ensure the modtime is set correctly on the destination file. */
3662         fsp2->pending_modtime = src_sbuf.st_mtime;
3663
3664         /*
3665          * As we are opening fsp1 read-only we only expect
3666          * an error on close on fsp2 if we are out of space.
3667          * Thus we don't look at the error return from the
3668          * close of fsp1.
3669          */
3670         *err_ret = close_file(fsp2,False);
3671
3672         return(ret == (SMB_OFF_T)src_sbuf.st_size);
3673 }
3674
3675 /****************************************************************************
3676  Reply to a file copy.
3677 ****************************************************************************/
3678
3679 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3680 {
3681         int outsize = 0;
3682         pstring name;
3683         pstring directory;
3684         pstring mask,newname;
3685         char *p;
3686         int count=0;
3687         int error = ERRnoaccess;
3688         int err = 0;
3689         BOOL has_wild;
3690         BOOL exists=False;
3691         int tid2 = SVAL(inbuf,smb_vwv0);
3692         int ofun = SVAL(inbuf,smb_vwv1);
3693         int flags = SVAL(inbuf,smb_vwv2);
3694         BOOL target_is_directory=False;
3695         BOOL bad_path1 = False;
3696         BOOL bad_path2 = False;
3697         BOOL rc = True;
3698         SMB_STRUCT_STAT sbuf1, sbuf2;
3699
3700         START_PROFILE(SMBcopy);
3701
3702         *directory = *mask = 0;
3703
3704         p = smb_buf(inbuf);
3705         p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
3706         p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
3707    
3708         DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3709    
3710         if (tid2 != conn->cnum) {
3711                 /* can't currently handle inter share copies XXXX */
3712                 DEBUG(3,("Rejecting inter-share copy\n"));
3713                 END_PROFILE(SMBcopy);
3714                 return ERROR_DOS(ERRSRV,ERRinvdevice);
3715         }
3716
3717         RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3718         RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3719
3720         rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3721         unix_convert(newname,conn,0,&bad_path2,&sbuf2);
3722
3723         target_is_directory = VALID_STAT_OF_DIR(sbuf2);
3724
3725         if ((flags&1) && target_is_directory) {
3726                 END_PROFILE(SMBcopy);
3727                 return ERROR_DOS(ERRDOS,ERRbadfile);
3728         }
3729
3730         if ((flags&2) && !target_is_directory) {
3731                 END_PROFILE(SMBcopy);
3732                 return ERROR_DOS(ERRDOS,ERRbadpath);
3733         }
3734
3735         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
3736                 /* wants a tree copy! XXXX */
3737                 DEBUG(3,("Rejecting tree copy\n"));
3738                 END_PROFILE(SMBcopy);
3739                 return ERROR_DOS(ERRSRV,ERRerror);
3740         }
3741
3742         p = strrchr_m(name,'/');
3743         if (!p) {
3744                 pstrcpy(directory,"./");
3745                 pstrcpy(mask,name);
3746         } else {
3747                 *p = 0;
3748                 pstrcpy(directory,name);
3749                 pstrcpy(mask,p+1);
3750         }
3751
3752         /*
3753          * We should only check the mangled cache
3754          * here if unix_convert failed. This means
3755          * that the path in 'mask' doesn't exist
3756          * on the file system and so we need to look
3757          * for a possible mangle. This patch from
3758          * Tine Smukavec <valentin.smukavec@hermes.si>.
3759          */
3760
3761         if (!rc && mangle_is_mangled(mask))
3762                 mangle_check_cache( mask );
3763
3764         has_wild = ms_has_wild(mask);
3765
3766         if (!has_wild) {
3767                 pstrcat(directory,"/");
3768                 pstrcat(directory,mask);
3769                 if (resolve_wildcards(directory,newname) &&
3770                                 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
3771                         count++;
3772                 if(!count && err) {
3773                         errno = err;
3774                         END_PROFILE(SMBcopy);
3775                         return(UNIXERROR(ERRHRD,ERRgeneral));
3776                 }
3777                 if (!count) {
3778                         exists = vfs_file_exist(conn,directory,NULL);
3779                 }
3780         } else {
3781                 void *dirptr = NULL;
3782                 const char *dname;
3783                 pstring destname;
3784
3785                 if (check_name(directory,conn))
3786                         dirptr = OpenDir(conn, directory, True);
3787
3788                 if (dirptr) {
3789                         error = ERRbadfile;
3790
3791                         if (strequal(mask,"????????.???"))
3792                                 pstrcpy(mask,"*");
3793
3794                         while ((dname = ReadDirName(dirptr))) {
3795                                 pstring fname;
3796                                 pstrcpy(fname,dname);
3797     
3798                                 if(!mask_match(fname, mask, case_sensitive))
3799                                         continue;
3800
3801                                 error = ERRnoaccess;
3802                                 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3803                                 pstrcpy(destname,newname);
3804                                 if (resolve_wildcards(fname,destname) && 
3805                                                 copy_file(fname,destname,conn,ofun,
3806                                                 count,target_is_directory,&err))
3807                                         count++;
3808                                 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3809                         }
3810                         CloseDir(dirptr);
3811                 }
3812         }
3813   
3814         if (count == 0) {
3815                 if(err) {
3816                         /* Error on close... */
3817                         errno = err;
3818                         END_PROFILE(SMBcopy);
3819                         return(UNIXERROR(ERRHRD,ERRgeneral));
3820                 }
3821
3822                 if (exists) {
3823                         END_PROFILE(SMBcopy);
3824                         return ERROR_DOS(ERRDOS,error);
3825                 } else {
3826                         if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3827                                 unix_ERR_class = ERRDOS;
3828                                 unix_ERR_code = ERRbadpath;
3829                         }
3830                         END_PROFILE(SMBcopy);
3831                         return(UNIXERROR(ERRDOS,error));
3832                 }
3833         }
3834   
3835         outsize = set_message(outbuf,1,0,True);
3836         SSVAL(outbuf,smb_vwv0,count);
3837
3838         END_PROFILE(SMBcopy);
3839         return(outsize);
3840 }
3841
3842 /****************************************************************************
3843  Reply to a setdir.
3844 ****************************************************************************/
3845
3846 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3847 {
3848         int snum;
3849         int outsize = 0;
3850         BOOL ok = False;
3851         pstring newdir;
3852
3853         START_PROFILE(pathworks_setdir);
3854   
3855         snum = SNUM(conn);
3856         if (!CAN_SETDIR(snum)) {
3857                 END_PROFILE(pathworks_setdir);
3858                 return ERROR_DOS(ERRDOS,ERRnoaccess);
3859         }
3860
3861         srvstr_pull_buf(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE);
3862   
3863         if (strlen(newdir) == 0) {
3864                 ok = True;
3865         } else {
3866                 ok = vfs_directory_exist(conn,newdir,NULL);
3867                 if (ok)
3868                         string_set(&conn->connectpath,newdir);
3869         }
3870   
3871         if (!ok) {
3872                 END_PROFILE(pathworks_setdir);
3873                 return ERROR_DOS(ERRDOS,ERRbadpath);
3874         }
3875   
3876         outsize = set_message(outbuf,0,0,True);
3877         SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
3878   
3879         DEBUG(3,("setdir %s\n", newdir));
3880
3881         END_PROFILE(pathworks_setdir);
3882         return(outsize);
3883 }
3884
3885 /****************************************************************************
3886  Get a lock pid, dealing with large count requests.
3887 ****************************************************************************/
3888
3889 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
3890 {
3891         if(!large_file_format)
3892                 return SVAL(data,SMB_LPID_OFFSET(data_offset));
3893         else
3894                 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
3895 }
3896
3897 /****************************************************************************
3898  Get a lock count, dealing with large count requests.
3899 ****************************************************************************/
3900
3901 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
3902 {
3903         SMB_BIG_UINT count = 0;
3904
3905         if(!large_file_format) {
3906                 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
3907         } else {
3908
3909 #if defined(HAVE_LONGLONG)
3910                 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
3911                         ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
3912 #else /* HAVE_LONGLONG */
3913
3914                 /*
3915                  * NT4.x seems to be broken in that it sends large file (64 bit)
3916                  * lockingX calls even if the CAP_LARGE_FILES was *not*
3917                  * negotiated. For boxes without large unsigned ints truncate the
3918                  * lock count by dropping the top 32 bits.
3919                  */
3920
3921                 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
3922                         DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
3923                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
3924                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
3925                                 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
3926                 }
3927
3928                 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
3929 #endif /* HAVE_LONGLONG */
3930         }
3931
3932         return count;
3933 }
3934
3935 #if !defined(HAVE_LONGLONG)
3936 /****************************************************************************
3937  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
3938 ****************************************************************************/
3939
3940 static uint32 map_lock_offset(uint32 high, uint32 low)
3941 {
3942         unsigned int i;
3943         uint32 mask = 0;
3944         uint32 highcopy = high;
3945  
3946         /*
3947          * Try and find out how many significant bits there are in high.
3948          */
3949  
3950         for(i = 0; highcopy; i++)
3951                 highcopy >>= 1;
3952  
3953         /*
3954          * We use 31 bits not 32 here as POSIX
3955          * lock offsets may not be negative.
3956          */
3957  
3958         mask = (~0) << (31 - i);
3959  
3960         if(low & mask)
3961                 return 0; /* Fail. */
3962  
3963         high <<= (31 - i);
3964  
3965         return (high|low);
3966 }
3967 #endif /* !defined(HAVE_LONGLONG) */
3968
3969 /****************************************************************************
3970  Get a lock offset, dealing with large offset requests.
3971 ****************************************************************************/
3972
3973 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
3974 {
3975         SMB_BIG_UINT offset = 0;
3976
3977         *err = False;
3978
3979         if(!large_file_format) {
3980                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
3981         } else {
3982
3983 #if defined(HAVE_LONGLONG)
3984                 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
3985                                 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
3986 #else /* HAVE_LONGLONG */
3987
3988                 /*
3989                  * NT4.x seems to be broken in that it sends large file (64 bit)
3990                  * lockingX calls even if the CAP_LARGE_FILES was *not*
3991                  * negotiated. For boxes without large unsigned ints mangle the
3992                  * lock offset by mapping the top 32 bits onto the lower 32.
3993                  */
3994       
3995                 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
3996                         uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3997                         uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
3998                         uint32 new_low = 0;
3999
4000                         if((new_low = map_lock_offset(high, low)) == 0) {
4001                                 *err = True;
4002                                 return (SMB_BIG_UINT)-1;
4003                         }
4004
4005                         DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4006                                 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4007                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4008                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4009                 }
4010
4011                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4012 #endif /* HAVE_LONGLONG */
4013         }
4014
4015         return offset;
4016 }
4017
4018 /****************************************************************************
4019  Reply to a lockingX request.
4020 ****************************************************************************/
4021
4022 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4023 {
4024         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4025         unsigned char locktype = CVAL(inbuf,smb_vwv3);
4026         unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4027         uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4028         uint16 num_locks = SVAL(inbuf,smb_vwv7);
4029         SMB_BIG_UINT count = 0, offset = 0;
4030         uint16 lock_pid;
4031         int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4032         int i;
4033         char *data;
4034         BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4035         BOOL err;
4036         NTSTATUS status;
4037
4038         START_PROFILE(SMBlockingX);
4039         
4040         CHECK_FSP(fsp,conn);
4041         
4042         data = smb_buf(inbuf);
4043
4044         if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
4045                 /* we don't support these - and CANCEL_LOCK makes w2k
4046                    and XP reboot so I don't really want to be
4047                    compatible! (tridge) */
4048                 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4049         }
4050         
4051         /* Check if this is an oplock break on a file
4052            we have granted an oplock on.
4053         */
4054         if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4055                 /* Client can insist on breaking to none. */
4056                 BOOL break_to_none = (oplocklevel == 0);
4057                 
4058                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4059                          (unsigned int)oplocklevel, fsp->fnum ));
4060
4061                 /*
4062                  * Make sure we have granted an exclusive or batch oplock on this file.
4063                  */
4064                 
4065                 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4066                         DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4067 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4068
4069                         /* if this is a pure oplock break request then don't send a reply */
4070                         if (num_locks == 0 && num_ulocks == 0) {
4071                                 END_PROFILE(SMBlockingX);
4072                                 return -1;
4073                         } else {
4074                                 END_PROFILE(SMBlockingX);
4075                                 return ERROR_DOS(ERRDOS,ERRlock);
4076                         }
4077                 }
4078
4079                 if (remove_oplock(fsp, break_to_none) == False) {
4080                         DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4081                                  fsp->fsp_name ));
4082                 }
4083                 
4084                 /* if this is a pure oplock break request then don't send a reply */
4085                 if (num_locks == 0 && num_ulocks == 0) {
4086                         /* Sanity check - ensure a pure oplock break is not a
4087                            chained request. */
4088                         if(CVAL(inbuf,smb_vwv0) != 0xff)
4089                                 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4090                                          (unsigned int)CVAL(inbuf,smb_vwv0) ));
4091                         END_PROFILE(SMBlockingX);
4092                         return -1;
4093                 }
4094         }
4095
4096         /*
4097          * We do this check *after* we have checked this is not a oplock break
4098          * response message. JRA.
4099          */
4100         
4101         release_level_2_oplocks_on_change(fsp);
4102         
4103         /* Data now points at the beginning of the list
4104            of smb_unlkrng structs */
4105         for(i = 0; i < (int)num_ulocks; i++) {
4106                 lock_pid = get_lock_pid( data, i, large_file_format);
4107                 count = get_lock_count( data, i, large_file_format);
4108                 offset = get_lock_offset( data, i, large_file_format, &err);
4109                 
4110                 /*
4111                  * There is no error code marked "stupid client bug".... :-).
4112                  */
4113                 if(err) {
4114                         END_PROFILE(SMBlockingX);
4115                         return ERROR_DOS(ERRDOS,ERRnoaccess);
4116                 }
4117
4118                 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4119                           (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4120                 
4121                 status = do_unlock(fsp,conn,lock_pid,count,offset);
4122                 if (NT_STATUS_V(status)) {
4123                         END_PROFILE(SMBlockingX);
4124                         return ERROR_NT(status);
4125                 }
4126         }
4127
4128         /* Setup the timeout in seconds. */
4129
4130         lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+499)/500);
4131         
4132         /* Now do any requested locks */
4133         data += ((large_file_format ? 20 : 10)*num_ulocks);
4134         
4135         /* Data now points at the beginning of the list
4136            of smb_lkrng structs */
4137         
4138         for(i = 0; i < (int)num_locks; i++) {
4139                 lock_pid = get_lock_pid( data, i, large_file_format);
4140                 count = get_lock_count( data, i, large_file_format);
4141                 offset = get_lock_offset( data, i, large_file_format, &err);
4142                 
4143                 /*
4144                  * There is no error code marked "stupid client bug".... :-).
4145                  */
4146                 if(err) {
4147                         END_PROFILE(SMBlockingX);
4148                         return ERROR_DOS(ERRDOS,ERRnoaccess);
4149                 }
4150                 
4151                 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4152                         (double)offset, (double)count, (unsigned int)lock_pid,
4153                         fsp->fsp_name, (int)lock_timeout ));
4154                 
4155                 status = do_lock_spin(fsp,conn,lock_pid, count,offset, 
4156                                  ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
4157                 if (NT_STATUS_V(status)) {
4158                         if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4159                                 /*
4160                                  * A blocking lock was requested. Package up
4161                                  * this smb into a queued request and push it
4162                                  * onto the blocking lock queue.
4163                                  */
4164                                 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4165                                         END_PROFILE(SMBlockingX);
4166                                         return -1;
4167                                 }
4168                         }
4169                         break;
4170                 }
4171         }
4172         
4173         /* If any of the above locks failed, then we must unlock
4174            all of the previous locks (X/Open spec). */
4175         if (i != num_locks && num_locks != 0) {
4176                 /*
4177                  * Ensure we don't do a remove on the lock that just failed,
4178                  * as under POSIX rules, if we have a lock already there, we
4179                  * will delete it (and we shouldn't) .....
4180                  */
4181                 for(i--; i >= 0; i--) {
4182                         lock_pid = get_lock_pid( data, i, large_file_format);
4183                         count = get_lock_count( data, i, large_file_format);
4184                         offset = get_lock_offset( data, i, large_file_format, &err);
4185                         
4186                         /*
4187                          * There is no error code marked "stupid client bug".... :-).
4188                          */
4189                         if(err) {
4190                                 END_PROFILE(SMBlockingX);
4191                                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4192                         }
4193                         
4194                         do_unlock(fsp,conn,lock_pid,count,offset);
4195                 }
4196                 END_PROFILE(SMBlockingX);
4197                 return ERROR_NT(status);
4198         }
4199
4200         set_message(outbuf,2,0,True);
4201         
4202         DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4203                     fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4204         
4205         END_PROFILE(SMBlockingX);
4206         return chain_reply(inbuf,outbuf,length,bufsize);
4207 }
4208
4209 /****************************************************************************
4210  Reply to a SMBreadbmpx (read block multiplex) request.
4211 ****************************************************************************/
4212
4213 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4214 {
4215         ssize_t nread = -1;
4216         ssize_t total_read;
4217         char *data;
4218         SMB_OFF_T startpos;
4219         int outsize;
4220         size_t maxcount;
4221         int max_per_packet;
4222         size_t tcount;
4223         int pad;
4224         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4225         START_PROFILE(SMBreadBmpx);
4226
4227         /* this function doesn't seem to work - disable by default */
4228         if (!lp_readbmpx()) {
4229                 END_PROFILE(SMBreadBmpx);
4230                 return ERROR_DOS(ERRSRV,ERRuseSTD);
4231         }
4232
4233         outsize = set_message(outbuf,8,0,True);
4234
4235         CHECK_FSP(fsp,conn);
4236         CHECK_READ(fsp);
4237
4238         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4239         maxcount = SVAL(inbuf,smb_vwv3);
4240
4241         data = smb_buf(outbuf);
4242         pad = ((long)data)%4;
4243         if (pad)
4244                 pad = 4 - pad;
4245         data += pad;
4246
4247         max_per_packet = bufsize-(outsize+pad);
4248         tcount = maxcount;
4249         total_read = 0;
4250
4251         if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4252                 END_PROFILE(SMBreadBmpx);
4253                 return ERROR_DOS(ERRDOS,ERRlock);
4254         }
4255
4256         do {
4257                 size_t N = MIN(max_per_packet,tcount-total_read);
4258   
4259                 nread = read_file(fsp,data,startpos,N);
4260
4261                 if (nread <= 0)
4262                         nread = 0;
4263
4264                 if (nread < (ssize_t)N)
4265                         tcount = total_read + nread;
4266
4267                 set_message(outbuf,8,nread,False);
4268                 SIVAL(outbuf,smb_vwv0,startpos);
4269                 SSVAL(outbuf,smb_vwv2,tcount);
4270                 SSVAL(outbuf,smb_vwv6,nread);
4271                 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4272
4273                 if (!send_smb(smbd_server_fd(),outbuf))
4274                         exit_server("reply_readbmpx: send_smb failed.");
4275
4276                 total_read += nread;
4277                 startpos += nread;
4278         } while (total_read < (ssize_t)tcount);
4279
4280         END_PROFILE(SMBreadBmpx);
4281         return(-1);
4282 }
4283
4284 /****************************************************************************
4285  Reply to a SMBsetattrE.
4286 ****************************************************************************/
4287
4288 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4289 {
4290         struct utimbuf unix_times;
4291         int outsize = 0;
4292         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4293         START_PROFILE(SMBsetattrE);
4294
4295         outsize = set_message(outbuf,0,0,True);
4296
4297         if(!fsp || (fsp->conn != conn)) {
4298                 END_PROFILE(SMBgetattrE);
4299                 return ERROR_DOS(ERRDOS,ERRbadfid);
4300         }
4301
4302         /*
4303          * Convert the DOS times into unix times. Ignore create
4304          * time as UNIX can't set this.
4305          */
4306
4307         unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4308         unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4309   
4310         /* 
4311          * Patch from Ray Frush <frush@engr.colostate.edu>
4312          * Sometimes times are sent as zero - ignore them.
4313          */
4314
4315         if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4316                 /* Ignore request */
4317                 if( DEBUGLVL( 3 ) ) {
4318                         dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4319                         dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4320                 }
4321                 END_PROFILE(SMBsetattrE);
4322                 return(outsize);
4323         } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4324                 /* set modify time = to access time if modify time was 0 */
4325                 unix_times.modtime = unix_times.actime;
4326         }
4327
4328         /* Set the date on this file */
4329         if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4330                 END_PROFILE(SMBsetattrE);
4331                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4332         }
4333   
4334         DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4335                 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4336
4337         END_PROFILE(SMBsetattrE);
4338         return(outsize);
4339 }
4340
4341
4342 /* Back from the dead for OS/2..... JRA. */
4343
4344 /****************************************************************************
4345  Reply to a SMBwritebmpx (write block multiplex primary) request.
4346 ****************************************************************************/
4347
4348 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4349 {
4350         size_t numtowrite;
4351         ssize_t nwritten = -1;
4352         int outsize = 0;
4353         SMB_OFF_T startpos;
4354         size_t tcount;
4355         BOOL write_through;
4356         int smb_doff;
4357         char *data;
4358         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4359         START_PROFILE(SMBwriteBmpx);
4360
4361         CHECK_FSP(fsp,conn);
4362         CHECK_WRITE(fsp);
4363         CHECK_ERROR(fsp);
4364
4365         tcount = SVAL(inbuf,smb_vwv1);
4366         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4367         write_through = BITSETW(inbuf+smb_vwv7,0);
4368         numtowrite = SVAL(inbuf,smb_vwv10);
4369         smb_doff = SVAL(inbuf,smb_vwv11);
4370
4371         data = smb_base(inbuf) + smb_doff;
4372
4373         /* If this fails we need to send an SMBwriteC response,
4374                 not an SMBwritebmpx - set this up now so we don't forget */
4375         SCVAL(outbuf,smb_com,SMBwritec);
4376
4377         if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4378                 END_PROFILE(SMBwriteBmpx);
4379                 return(ERROR_DOS(ERRDOS,ERRlock));
4380         }
4381
4382         nwritten = write_file(fsp,data,startpos,numtowrite);
4383
4384         if(lp_syncalways(SNUM(conn)) || write_through)
4385                 sync_file(conn,fsp);
4386   
4387         if(nwritten < (ssize_t)numtowrite) {
4388                 END_PROFILE(SMBwriteBmpx);
4389                 return(UNIXERROR(ERRHRD,ERRdiskfull));
4390         }
4391
4392         /* If the maximum to be written to this file
4393                 is greater than what we just wrote then set
4394                 up a secondary struct to be attached to this
4395                 fd, we will use this to cache error messages etc. */
4396
4397         if((ssize_t)tcount > nwritten) {
4398                 write_bmpx_struct *wbms;
4399                 if(fsp->wbmpx_ptr != NULL)
4400                         wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4401                 else
4402                         wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4403                 if(!wbms) {
4404                         DEBUG(0,("Out of memory in reply_readmpx\n"));
4405                         END_PROFILE(SMBwriteBmpx);
4406                         return(ERROR_DOS(ERRSRV,ERRnoresource));
4407                 }
4408                 wbms->wr_mode = write_through;
4409                 wbms->wr_discard = False; /* No errors yet */
4410                 wbms->wr_total_written = nwritten;
4411                 wbms->wr_errclass = 0;
4412                 wbms->wr_error = 0;
4413                 fsp->wbmpx_ptr = wbms;
4414         }
4415
4416         /* We are returning successfully, set the message type back to
4417                 SMBwritebmpx */
4418         SCVAL(outbuf,smb_com,SMBwriteBmpx);
4419   
4420         outsize = set_message(outbuf,1,0,True);
4421   
4422         SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4423   
4424         DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4425                         fsp->fnum, (int)numtowrite, (int)nwritten ) );
4426
4427         if (write_through && tcount==nwritten) {
4428                 /* We need to send both a primary and a secondary response */
4429                 smb_setlen(outbuf,outsize - 4);
4430                 if (!send_smb(smbd_server_fd(),outbuf))
4431                         exit_server("reply_writebmpx: send_smb failed.");
4432
4433                 /* Now the secondary */
4434                 outsize = set_message(outbuf,1,0,True);
4435                 SCVAL(outbuf,smb_com,SMBwritec);
4436                 SSVAL(outbuf,smb_vwv0,nwritten);
4437         }
4438
4439         END_PROFILE(SMBwriteBmpx);
4440         return(outsize);
4441 }
4442
4443 /****************************************************************************
4444  Reply to a SMBwritebs (write block multiplex secondary) request.
4445 ****************************************************************************/
4446
4447 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4448 {
4449         size_t numtowrite;
4450         ssize_t nwritten = -1;
4451         int outsize = 0;
4452         SMB_OFF_T startpos;
4453         size_t tcount;
4454         BOOL write_through;
4455         int smb_doff;
4456         char *data;
4457         write_bmpx_struct *wbms;
4458         BOOL send_response = False; 
4459         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4460         START_PROFILE(SMBwriteBs);
4461
4462         CHECK_FSP(fsp,conn);
4463         CHECK_WRITE(fsp);
4464
4465         tcount = SVAL(inbuf,smb_vwv1);
4466         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4467         numtowrite = SVAL(inbuf,smb_vwv6);
4468         smb_doff = SVAL(inbuf,smb_vwv7);
4469
4470         data = smb_base(inbuf) + smb_doff;
4471
4472         /* We need to send an SMBwriteC response, not an SMBwritebs */
4473         SCVAL(outbuf,smb_com,SMBwritec);
4474
4475         /* This fd should have an auxiliary struct attached,
4476                 check that it does */
4477         wbms = fsp->wbmpx_ptr;
4478         if(!wbms) {
4479                 END_PROFILE(SMBwriteBs);
4480                 return(-1);
4481         }
4482
4483         /* If write through is set we can return errors, else we must cache them */
4484         write_through = wbms->wr_mode;
4485
4486         /* Check for an earlier error */
4487         if(wbms->wr_discard) {
4488                 END_PROFILE(SMBwriteBs);
4489                 return -1; /* Just discard the packet */
4490         }
4491
4492         nwritten = write_file(fsp,data,startpos,numtowrite);
4493
4494         if(lp_syncalways(SNUM(conn)) || write_through)
4495                 sync_file(conn,fsp);
4496   
4497         if (nwritten < (ssize_t)numtowrite) {
4498                 if(write_through) {
4499                         /* We are returning an error - we can delete the aux struct */
4500                         if (wbms)
4501                                 free((char *)wbms);
4502                         fsp->wbmpx_ptr = NULL;
4503                         END_PROFILE(SMBwriteBs);
4504                         return(ERROR_DOS(ERRHRD,ERRdiskfull));
4505                 }
4506                 END_PROFILE(SMBwriteBs);
4507                 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4508         }
4509
4510         /* Increment the total written, if this matches tcount
4511                 we can discard the auxiliary struct (hurrah !) and return a writeC */
4512         wbms->wr_total_written += nwritten;
4513         if(wbms->wr_total_written >= tcount) {
4514                 if (write_through) {
4515                         outsize = set_message(outbuf,1,0,True);
4516                         SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);    
4517                         send_response = True;
4518                 }
4519
4520                 free((char *)wbms);
4521                 fsp->wbmpx_ptr = NULL;
4522         }
4523
4524         if(send_response) {
4525                 END_PROFILE(SMBwriteBs);
4526                 return(outsize);
4527         }
4528
4529         END_PROFILE(SMBwriteBs);
4530         return(-1);
4531 }
4532
4533 /****************************************************************************
4534  Reply to a SMBgetattrE.
4535 ****************************************************************************/
4536
4537 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4538 {
4539         SMB_STRUCT_STAT sbuf;
4540         int outsize = 0;
4541         int mode;
4542         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4543         START_PROFILE(SMBgetattrE);
4544
4545         outsize = set_message(outbuf,11,0,True);
4546
4547         if(!fsp || (fsp->conn != conn)) {
4548                 END_PROFILE(SMBgetattrE);
4549                 return ERROR_DOS(ERRDOS,ERRbadfid);
4550         }
4551
4552         /* Do an fstat on this file */
4553         if(fsp_stat(fsp, &sbuf)) {
4554                 END_PROFILE(SMBgetattrE);
4555                 return(UNIXERROR(ERRDOS,ERRnoaccess));
4556         }
4557   
4558         mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4559   
4560         /*
4561          * Convert the times into dos times. Set create
4562          * date to be last modify date as UNIX doesn't save
4563          * this.
4564          */
4565
4566         put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4567         put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4568         put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4569
4570         if (mode & aDIR) {
4571                 SIVAL(outbuf,smb_vwv6,0);
4572                 SIVAL(outbuf,smb_vwv8,0);
4573         } else {
4574                 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
4575                 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4576                 SIVAL(outbuf,smb_vwv8,allocation_size);
4577         }
4578         SSVAL(outbuf,smb_vwv10, mode);
4579   
4580         DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4581   
4582         END_PROFILE(SMBgetattrE);
4583         return(outsize);
4584 }