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