r6502: add LOCKING debug class - pull PRINTINGDB class definition from trunk
[jra/samba/.git] / source3 / smbd / reply.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Main SMB reply routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Andrew Bartlett      2001
6    Copyright (C) Jeremy Allison 1992-2004.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22 /*
23    This file handles most of the reply_ calls that the server
24    makes to handle specific protocols
25 */
26
27 #include "includes.h"
28
29 /* look in server.c for some explanation of these variables */
30 extern 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 #undef DBGC_CLASS
2133 #define DBGC_CLASS DBGC_LOCKING
2134
2135 /****************************************************************************
2136  Reply to a lockread (core+ protocol).
2137 ****************************************************************************/
2138
2139 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2140 {
2141         ssize_t nread = -1;
2142         char *data;
2143         int outsize = 0;
2144         SMB_OFF_T startpos;
2145         size_t numtoread;
2146         NTSTATUS status;
2147         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2148         BOOL my_lock_ctx = False;
2149         START_PROFILE(SMBlockread);
2150
2151         CHECK_FSP(fsp,conn);
2152         CHECK_READ(fsp);
2153
2154         release_level_2_oplocks_on_change(fsp);
2155
2156         numtoread = SVAL(inbuf,smb_vwv1);
2157         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2158   
2159         outsize = set_message(outbuf,5,3,True);
2160         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2161         data = smb_buf(outbuf) + 3;
2162         
2163         /*
2164          * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2165          * protocol request that predates the read/write lock concept. 
2166          * Thus instead of asking for a read lock here we need to ask
2167          * for a write lock. JRA.
2168          * Note that the requested lock size is unaffected by max_recv.
2169          */
2170         
2171         status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), 
2172                          (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
2173
2174         if (NT_STATUS_V(status)) {
2175 #if 0
2176                 /*
2177                  * We used to make lockread a blocking lock. It turns out
2178                  * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
2179                  * tester. JRA.
2180                  */
2181
2182                 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2183                         /*
2184                          * A blocking lock was requested. Package up
2185                          * this smb into a queued request and push it
2186                          * onto the blocking lock queue.
2187                          */
2188                         if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
2189                                                                 (SMB_BIG_UINT)numtoread)) {
2190                                 END_PROFILE(SMBlockread);
2191                                 return -1;
2192                         }
2193                 }
2194 #endif
2195                 END_PROFILE(SMBlockread);
2196                 return ERROR_NT(status);
2197         }
2198
2199         /*
2200          * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2201          */
2202
2203         if (numtoread > max_recv) {
2204                 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2205 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2206                         (unsigned int)numtoread, (unsigned int)max_recv ));
2207                 numtoread = MIN(numtoread,max_recv);
2208         }
2209         nread = read_file(fsp,data,startpos,numtoread);
2210
2211         if (nread < 0) {
2212                 END_PROFILE(SMBlockread);
2213                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2214         }
2215         
2216         outsize += nread;
2217         SSVAL(outbuf,smb_vwv0,nread);
2218         SSVAL(outbuf,smb_vwv5,nread+3);
2219         SSVAL(smb_buf(outbuf),1,nread);
2220         
2221         DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2222                  fsp->fnum, (int)numtoread, (int)nread));
2223
2224         END_PROFILE(SMBlockread);
2225         return(outsize);
2226 }
2227
2228 #undef DBGC_CLASS
2229 #define DBGC_CLASS DBGC_ALL
2230
2231 /****************************************************************************
2232  Reply to a read.
2233 ****************************************************************************/
2234
2235 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2236 {
2237         size_t numtoread;
2238         ssize_t nread = 0;
2239         char *data;
2240         SMB_OFF_T startpos;
2241         int outsize = 0;
2242         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2243         START_PROFILE(SMBread);
2244
2245         CHECK_FSP(fsp,conn);
2246         CHECK_READ(fsp);
2247
2248         numtoread = SVAL(inbuf,smb_vwv1);
2249         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2250
2251         outsize = set_message(outbuf,5,3,True);
2252         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2253         /*
2254          * The requested read size cannot be greater than max_recv. JRA.
2255          */
2256         if (numtoread > max_recv) {
2257                 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2258 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2259                         (unsigned int)numtoread, (unsigned int)max_recv ));
2260                 numtoread = MIN(numtoread,max_recv);
2261         }
2262
2263         data = smb_buf(outbuf) + 3;
2264   
2265         if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2266                 END_PROFILE(SMBread);
2267                 return ERROR_DOS(ERRDOS,ERRlock);
2268         }
2269
2270         if (numtoread > 0)
2271                 nread = read_file(fsp,data,startpos,numtoread);
2272
2273         if (nread < 0) {
2274                 END_PROFILE(SMBread);
2275                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2276         }
2277   
2278         outsize += nread;
2279         SSVAL(outbuf,smb_vwv0,nread);
2280         SSVAL(outbuf,smb_vwv5,nread+3);
2281         SCVAL(smb_buf(outbuf),0,1);
2282         SSVAL(smb_buf(outbuf),1,nread);
2283   
2284         DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2285                 fsp->fnum, (int)numtoread, (int)nread ) );
2286
2287         END_PROFILE(SMBread);
2288         return(outsize);
2289 }
2290
2291 /****************************************************************************
2292  Reply to a read and X - possibly using sendfile.
2293 ****************************************************************************/
2294
2295 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2296                 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2297 {
2298         int outsize = 0;
2299         ssize_t nread = -1;
2300         char *data = smb_buf(outbuf);
2301
2302 #if defined(WITH_SENDFILE)
2303         /*
2304          * We can only use sendfile on a non-chained packet 
2305          * but we can use on a non-oplocked file. tridge proved this
2306          * on a train in Germany :-). JRA.
2307          */
2308
2309         if (chain_size ==0 && (CVAL(inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) &&
2310                         (lp_write_cache_size(SNUM(conn)) == 0) ) {
2311                 SMB_STRUCT_STAT sbuf;
2312                 DATA_BLOB header;
2313
2314                 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
2315                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2316
2317                 if (startpos > sbuf.st_size)
2318                         goto normal_read;
2319
2320                 if (smb_maxcnt > (sbuf.st_size - startpos))
2321                         smb_maxcnt = (sbuf.st_size - startpos);
2322
2323                 if (smb_maxcnt == 0)
2324                         goto normal_read;
2325
2326                 /* 
2327                  * Set up the packet header before send. We
2328                  * assume here the sendfile will work (get the
2329                  * correct amount of data).
2330                  */
2331
2332                 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2333                 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2334                 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2335                 SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
2336                 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2337                 SCVAL(outbuf,smb_vwv0,0xFF);
2338                 set_message(outbuf,12,smb_maxcnt,False);
2339                 header.data = outbuf;
2340                 header.length = data - outbuf;
2341                 header.free = NULL;
2342
2343                 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt)) == -1) {
2344                         /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2345                         if (errno == ENOSYS) {
2346                                 goto normal_read;
2347                         }
2348
2349                         /*
2350                          * Special hack for broken Linux with no working sendfile. If we
2351                          * return EINTR we sent the header but not the rest of the data.
2352                          * Fake this up by doing read/write calls.
2353                          */
2354
2355                         if (errno == EINTR) {
2356                                 /* Ensure we don't do this again. */
2357                                 set_use_sendfile(SNUM(conn), False);
2358                                 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2359
2360                                 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2361                                                         len_outbuf - (data-outbuf))) == -1) {
2362                                         DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2363                                                 fsp->fsp_name, strerror(errno) ));
2364                                         exit_server("send_file_readX: fake_sendfile failed");
2365                                 }
2366                                 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2367                                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2368                                 /* Returning -1 here means successful sendfile. */
2369                                 return -1;
2370                         }
2371
2372                         DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2373                                 fsp->fsp_name, strerror(errno) ));
2374                         exit_server("send_file_readX sendfile failed");
2375                 }
2376
2377                 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2378                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2379                 /* Returning -1 here means successful sendfile. */
2380                 return -1;
2381         }
2382
2383   normal_read:
2384
2385 #endif
2386
2387         nread = read_file(fsp,data,startpos,smb_maxcnt);
2388   
2389         if (nread < 0) {
2390                 END_PROFILE(SMBreadX);
2391                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2392         }
2393
2394         outsize = set_message(outbuf,12,nread,False);
2395         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2396         SSVAL(outbuf,smb_vwv5,nread);
2397         SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2398         SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
2399         SSVAL(smb_buf(outbuf),-2,nread);
2400   
2401         DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2402                 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2403
2404         /* Returning the number of bytes we want to send back - including header. */
2405         return outsize;
2406 }
2407
2408 /****************************************************************************
2409  Reply to a read and X.
2410 ****************************************************************************/
2411
2412 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2413 {
2414         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2415         SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2416         ssize_t nread = -1;
2417         size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2418 #if 0
2419         size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2420 #endif
2421
2422         START_PROFILE(SMBreadX);
2423
2424         /* If it's an IPC, pass off the pipe handler. */
2425         if (IS_IPC(conn)) {
2426                 END_PROFILE(SMBreadX);
2427                 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2428         }
2429
2430         CHECK_FSP(fsp,conn);
2431         CHECK_READ(fsp);
2432
2433         set_message(outbuf,12,0,True);
2434
2435         if (global_client_caps & CAP_LARGE_READX) {
2436                 if (SVAL(inbuf,smb_vwv7) == 1) {
2437                         smb_maxcnt |= (1<<16);
2438                 }
2439                 if (smb_maxcnt > BUFFER_SIZE) {
2440                         DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2441                                 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
2442                         END_PROFILE(SMBreadX);
2443                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2444                 }
2445         }
2446
2447         if(CVAL(inbuf,smb_wct) == 12) {
2448 #ifdef LARGE_SMB_OFF_T
2449                 /*
2450                  * This is a large offset (64 bit) read.
2451                  */
2452                 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2453
2454 #else /* !LARGE_SMB_OFF_T */
2455
2456                 /*
2457                  * Ensure we haven't been sent a >32 bit offset.
2458                  */
2459
2460                 if(IVAL(inbuf,smb_vwv10) != 0) {
2461                         DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2462 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2463                         END_PROFILE(SMBreadX);
2464                         return ERROR_DOS(ERRDOS,ERRbadaccess);
2465                 }
2466
2467 #endif /* LARGE_SMB_OFF_T */
2468
2469         }
2470
2471         if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2472                 END_PROFILE(SMBreadX);
2473                 return ERROR_DOS(ERRDOS,ERRlock);
2474         }
2475
2476         nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2477         if (nread != -1)
2478                 nread = chain_reply(inbuf,outbuf,length,bufsize);
2479
2480         END_PROFILE(SMBreadX);
2481         return nread;
2482 }
2483
2484 /****************************************************************************
2485  Reply to a writebraw (core+ or LANMAN1.0 protocol).
2486 ****************************************************************************/
2487
2488 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2489 {
2490         ssize_t nwritten=0;
2491         ssize_t total_written=0;
2492         size_t numtowrite=0;
2493         size_t tcount;
2494         SMB_OFF_T startpos;
2495         char *data=NULL;
2496         BOOL write_through;
2497         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2498         int outsize = 0;
2499         START_PROFILE(SMBwritebraw);
2500
2501         if (srv_is_signing_active()) {
2502                 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2503         }
2504
2505         CHECK_FSP(fsp,conn);
2506         CHECK_WRITE(fsp);
2507   
2508         tcount = IVAL(inbuf,smb_vwv1);
2509         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2510         write_through = BITSETW(inbuf+smb_vwv7,0);
2511
2512         /* We have to deal with slightly different formats depending
2513                 on whether we are using the core+ or lanman1.0 protocol */
2514
2515         if(Protocol <= PROTOCOL_COREPLUS) {
2516                 numtowrite = SVAL(smb_buf(inbuf),-2);
2517                 data = smb_buf(inbuf);
2518         } else {
2519                 numtowrite = SVAL(inbuf,smb_vwv10);
2520                 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2521         }
2522
2523         /* force the error type */
2524         SCVAL(inbuf,smb_com,SMBwritec);
2525         SCVAL(outbuf,smb_com,SMBwritec);
2526
2527         if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2528                 END_PROFILE(SMBwritebraw);
2529                 return(ERROR_DOS(ERRDOS,ERRlock));
2530         }
2531
2532         if (numtowrite>0)
2533                 nwritten = write_file(fsp,data,startpos,numtowrite);
2534   
2535         DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2536                 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2537
2538         if (nwritten < (ssize_t)numtowrite)  {
2539                 END_PROFILE(SMBwritebraw);
2540                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2541         }
2542
2543         total_written = nwritten;
2544
2545         /* Return a message to the redirector to tell it to send more bytes */
2546         SCVAL(outbuf,smb_com,SMBwritebraw);
2547         SSVALS(outbuf,smb_vwv0,-1);
2548         outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2549         if (!send_smb(smbd_server_fd(),outbuf))
2550                 exit_server("reply_writebraw: send_smb failed.");
2551   
2552         /* Now read the raw data into the buffer and write it */
2553         if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2554                 exit_server("secondary writebraw failed");
2555         }
2556   
2557         /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2558         numtowrite = smb_len(inbuf);
2559
2560         /* Set up outbuf to return the correct return */
2561         outsize = set_message(outbuf,1,0,True);
2562         SCVAL(outbuf,smb_com,SMBwritec);
2563         SSVAL(outbuf,smb_vwv0,total_written);
2564
2565         if (numtowrite != 0) {
2566
2567                 if (numtowrite > BUFFER_SIZE) {
2568                         DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2569                                 (unsigned int)numtowrite ));
2570                         exit_server("secondary writebraw failed");
2571                 }
2572
2573                 if (tcount > nwritten+numtowrite) {
2574                         DEBUG(3,("Client overestimated the write %d %d %d\n",
2575                                 (int)tcount,(int)nwritten,(int)numtowrite));
2576                 }
2577
2578                 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2579                         DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2580                                 strerror(errno) ));
2581                         exit_server("secondary writebraw failed");
2582                 }
2583
2584                 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2585
2586                 if (nwritten < (ssize_t)numtowrite) {
2587                         SCVAL(outbuf,smb_rcls,ERRHRD);
2588                         SSVAL(outbuf,smb_err,ERRdiskfull);      
2589                 }
2590
2591                 if (nwritten > 0)
2592                         total_written += nwritten;
2593         }
2594  
2595         if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2596                 sync_file(conn,fsp);
2597
2598         DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2599                 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2600
2601         /* we won't return a status if write through is not selected - this follows what WfWg does */
2602         END_PROFILE(SMBwritebraw);
2603         if (!write_through && total_written==tcount) {
2604
2605 #if RABBIT_PELLET_FIX
2606                 /*
2607                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2608                  * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2609                  */
2610                 if (!send_keepalive(smbd_server_fd()))
2611                         exit_server("reply_writebraw: send of keepalive failed");
2612 #endif
2613                 return(-1);
2614         }
2615
2616         return(outsize);
2617 }
2618
2619 #undef DBGC_CLASS
2620 #define DBGC_CLASS DBGC_LOCKING
2621
2622 /****************************************************************************
2623  Reply to a writeunlock (core+).
2624 ****************************************************************************/
2625
2626 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, 
2627                       int size, int dum_buffsize)
2628 {
2629         ssize_t nwritten = -1;
2630         size_t numtowrite;
2631         SMB_OFF_T startpos;
2632         char *data;
2633         NTSTATUS status = NT_STATUS_OK;
2634         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2635         int outsize = 0;
2636         START_PROFILE(SMBwriteunlock);
2637         
2638         CHECK_FSP(fsp,conn);
2639         CHECK_WRITE(fsp);
2640
2641         numtowrite = SVAL(inbuf,smb_vwv1);
2642         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2643         data = smb_buf(inbuf) + 3;
2644   
2645         if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2646                 END_PROFILE(SMBwriteunlock);
2647                 return ERROR_DOS(ERRDOS,ERRlock);
2648         }
2649
2650         /* The special X/Open SMB protocol handling of
2651            zero length writes is *NOT* done for
2652            this call */
2653         if(numtowrite == 0)
2654                 nwritten = 0;
2655         else
2656                 nwritten = write_file(fsp,data,startpos,numtowrite);
2657   
2658         if (lp_syncalways(SNUM(conn)))
2659                 sync_file(conn,fsp);
2660
2661         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2662                 END_PROFILE(SMBwriteunlock);
2663                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2664         }
2665
2666         if (numtowrite) {
2667                 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite, 
2668                                    (SMB_BIG_UINT)startpos);
2669                 if (NT_STATUS_V(status)) {
2670                         END_PROFILE(SMBwriteunlock);
2671                         return ERROR_NT(status);
2672                 }
2673         }
2674         
2675         outsize = set_message(outbuf,1,0,True);
2676         
2677         SSVAL(outbuf,smb_vwv0,nwritten);
2678         
2679         DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2680                  fsp->fnum, (int)numtowrite, (int)nwritten));
2681         
2682         END_PROFILE(SMBwriteunlock);
2683         return outsize;
2684 }
2685
2686 #undef DBGC_CLASS
2687 #define DBGC_CLASS DBGC_ALL
2688
2689 /****************************************************************************
2690  Reply to a write.
2691 ****************************************************************************/
2692
2693 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2694 {
2695         size_t numtowrite;
2696         ssize_t nwritten = -1;
2697         SMB_OFF_T startpos;
2698         char *data;
2699         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2700         int outsize = 0;
2701         START_PROFILE(SMBwrite);
2702
2703         /* If it's an IPC, pass off the pipe handler. */
2704         if (IS_IPC(conn)) {
2705                 END_PROFILE(SMBwrite);
2706                 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2707         }
2708
2709         CHECK_FSP(fsp,conn);
2710         CHECK_WRITE(fsp);
2711
2712         numtowrite = SVAL(inbuf,smb_vwv1);
2713         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2714         data = smb_buf(inbuf) + 3;
2715   
2716         if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2717                 END_PROFILE(SMBwrite);
2718                 return ERROR_DOS(ERRDOS,ERRlock);
2719         }
2720
2721         /*
2722          * X/Open SMB protocol says that if smb_vwv1 is
2723          * zero then the file size should be extended or
2724          * truncated to the size given in smb_vwv[2-3].
2725          */
2726
2727         if(numtowrite == 0) {
2728                 /*
2729                  * This is actually an allocate call, and set EOF. JRA.
2730                  */
2731                 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2732                 if (nwritten < 0) {
2733                         END_PROFILE(SMBwrite);
2734                         return ERROR_NT(NT_STATUS_DISK_FULL);
2735                 }
2736                 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2737                 if (nwritten < 0) {
2738                         END_PROFILE(SMBwrite);
2739                         return ERROR_NT(NT_STATUS_DISK_FULL);
2740                 }
2741         } else
2742                 nwritten = write_file(fsp,data,startpos,numtowrite);
2743   
2744         if (lp_syncalways(SNUM(conn)))
2745                 sync_file(conn,fsp);
2746
2747         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2748                 END_PROFILE(SMBwrite);
2749                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2750         }
2751
2752         outsize = set_message(outbuf,1,0,True);
2753   
2754         SSVAL(outbuf,smb_vwv0,nwritten);
2755
2756         if (nwritten < (ssize_t)numtowrite) {
2757                 SCVAL(outbuf,smb_rcls,ERRHRD);
2758                 SSVAL(outbuf,smb_err,ERRdiskfull);      
2759         }
2760   
2761         DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2762
2763         END_PROFILE(SMBwrite);
2764         return(outsize);
2765 }
2766
2767 /****************************************************************************
2768  Reply to a write and X.
2769 ****************************************************************************/
2770
2771 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2772 {
2773         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2774         SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2775         size_t numtowrite = SVAL(inbuf,smb_vwv10);
2776         BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2777         ssize_t nwritten = -1;
2778         unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2779         unsigned int smblen = smb_len(inbuf);
2780         char *data;
2781         BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2782         START_PROFILE(SMBwriteX);
2783
2784         /* If it's an IPC, pass off the pipe handler. */
2785         if (IS_IPC(conn)) {
2786                 END_PROFILE(SMBwriteX);
2787                 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2788         }
2789
2790         CHECK_FSP(fsp,conn);
2791         CHECK_WRITE(fsp);
2792
2793         /* Deal with possible LARGE_WRITEX */
2794         if (large_writeX)
2795                 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2796
2797         if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2798                 END_PROFILE(SMBwriteX);
2799                 return ERROR_DOS(ERRDOS,ERRbadmem);
2800         }
2801
2802         data = smb_base(inbuf) + smb_doff;
2803
2804         if(CVAL(inbuf,smb_wct) == 14) {
2805 #ifdef LARGE_SMB_OFF_T
2806                 /*
2807                  * This is a large offset (64 bit) write.
2808                  */
2809                 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2810
2811 #else /* !LARGE_SMB_OFF_T */
2812
2813                 /*
2814                  * Ensure we haven't been sent a >32 bit offset.
2815                  */
2816
2817                 if(IVAL(inbuf,smb_vwv12) != 0) {
2818                         DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2819 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2820                         END_PROFILE(SMBwriteX);
2821                         return ERROR_DOS(ERRDOS,ERRbadaccess);
2822                 }
2823
2824 #endif /* LARGE_SMB_OFF_T */
2825         }
2826
2827         if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2828                 END_PROFILE(SMBwriteX);
2829                 return ERROR_DOS(ERRDOS,ERRlock);
2830         }
2831
2832         /* X/Open SMB protocol says that, unlike SMBwrite
2833         if the length is zero then NO truncation is
2834         done, just a write of zero. To truncate a file,
2835         use SMBwrite. */
2836
2837         if(numtowrite == 0)
2838                 nwritten = 0;
2839         else
2840                 nwritten = write_file(fsp,data,startpos,numtowrite);
2841   
2842         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2843                 END_PROFILE(SMBwriteX);
2844                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2845         }
2846
2847         set_message(outbuf,6,0,True);
2848   
2849         SSVAL(outbuf,smb_vwv2,nwritten);
2850         if (large_writeX)
2851                 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2852
2853         if (nwritten < (ssize_t)numtowrite) {
2854                 SCVAL(outbuf,smb_rcls,ERRHRD);
2855                 SSVAL(outbuf,smb_err,ERRdiskfull);      
2856         }
2857
2858         DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2859                 fsp->fnum, (int)numtowrite, (int)nwritten));
2860
2861         if (lp_syncalways(SNUM(conn)) || write_through)
2862                 sync_file(conn,fsp);
2863
2864         END_PROFILE(SMBwriteX);
2865         return chain_reply(inbuf,outbuf,length,bufsize);
2866 }
2867
2868 /****************************************************************************
2869  Reply to a lseek.
2870 ****************************************************************************/
2871
2872 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2873 {
2874         SMB_OFF_T startpos;
2875         SMB_OFF_T res= -1;
2876         int mode,umode;
2877         int outsize = 0;
2878         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2879         START_PROFILE(SMBlseek);
2880
2881         CHECK_FSP(fsp,conn);
2882
2883         flush_write_cache(fsp, SEEK_FLUSH);
2884
2885         mode = SVAL(inbuf,smb_vwv1) & 3;
2886         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2887         startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2888
2889         switch (mode) {
2890                 case 0:
2891                         umode = SEEK_SET;
2892                         res = startpos;
2893                         break;
2894                 case 1:
2895                         umode = SEEK_CUR;
2896                         res = fsp->pos + startpos;
2897                         break;
2898                 case 2:
2899                         umode = SEEK_END;
2900                         break;
2901                 default:
2902                         umode = SEEK_SET;
2903                         res = startpos;
2904                         break;
2905         }
2906
2907         if (umode == SEEK_END) {
2908                 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2909                         if(errno == EINVAL) {
2910                                 SMB_OFF_T current_pos = startpos;
2911                                 SMB_STRUCT_STAT sbuf;
2912
2913                                 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2914                                         END_PROFILE(SMBlseek);
2915                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2916                                 }
2917
2918                                 current_pos += sbuf.st_size;
2919                                 if(current_pos < 0)
2920                                         res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2921                         }
2922                 }
2923
2924                 if(res == -1) {
2925                         END_PROFILE(SMBlseek);
2926                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2927                 }
2928         }
2929
2930         fsp->pos = res;
2931   
2932         outsize = set_message(outbuf,2,0,True);
2933         SIVAL(outbuf,smb_vwv0,res);
2934   
2935         DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2936                 fsp->fnum, (double)startpos, (double)res, mode));
2937
2938         END_PROFILE(SMBlseek);
2939         return(outsize);
2940 }
2941
2942 /****************************************************************************
2943  Reply to a flush.
2944 ****************************************************************************/
2945
2946 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2947 {
2948         int outsize = set_message(outbuf,0,0,True);
2949         uint16 fnum = SVAL(inbuf,smb_vwv0);
2950         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2951         START_PROFILE(SMBflush);
2952
2953         if (fnum != 0xFFFF)
2954                 CHECK_FSP(fsp,conn);
2955         
2956         if (!fsp) {
2957                 file_sync_all(conn);
2958         } else {
2959                 sync_file(conn,fsp);
2960         }
2961         
2962         DEBUG(3,("flush\n"));
2963         END_PROFILE(SMBflush);
2964         return(outsize);
2965 }
2966
2967 /****************************************************************************
2968  Reply to a exit.
2969 ****************************************************************************/
2970
2971 int reply_exit(connection_struct *conn, 
2972                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2973 {
2974         int outsize;
2975         START_PROFILE(SMBexit);
2976
2977         file_close_pid(SVAL(inbuf,smb_pid));
2978
2979         outsize = set_message(outbuf,0,0,True);
2980
2981         DEBUG(3,("exit\n"));
2982
2983         END_PROFILE(SMBexit);
2984         return(outsize);
2985 }
2986
2987 /****************************************************************************
2988  Reply to a close - has to deal with closing a directory opened by NT SMB's.
2989 ****************************************************************************/
2990
2991 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2992                 int dum_buffsize)
2993 {
2994         int outsize = 0;
2995         time_t mtime;
2996         int32 eclass = 0, err = 0;
2997         files_struct *fsp = NULL;
2998         START_PROFILE(SMBclose);
2999
3000         outsize = set_message(outbuf,0,0,True);
3001
3002         /* If it's an IPC, pass off to the pipe handler. */
3003         if (IS_IPC(conn)) {
3004                 END_PROFILE(SMBclose);
3005                 return reply_pipe_close(conn, inbuf,outbuf);
3006         }
3007
3008         fsp = file_fsp(inbuf,smb_vwv0);
3009
3010         /*
3011          * We can only use CHECK_FSP if we know it's not a directory.
3012          */
3013
3014         if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3015                 END_PROFILE(SMBclose);
3016                 return ERROR_DOS(ERRDOS,ERRbadfid);
3017         }
3018
3019         if(fsp->is_directory) {
3020                 /*
3021                  * Special case - close NT SMB directory handle.
3022                  */
3023                 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
3024                 close_file(fsp,True);
3025         } else {
3026                 /*
3027                  * Close ordinary file.
3028                  */
3029                 int close_err;
3030                 pstring file_name;
3031
3032                 /* Save the name for time set in close. */
3033                 pstrcpy( file_name, fsp->fsp_name);
3034
3035                 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3036                          fsp->fd, fsp->fnum,
3037                          conn->num_files_open));
3038  
3039                 /*
3040                  * Take care of any time sent in the close.
3041                  */
3042
3043                 mtime = make_unix_date3(inbuf+smb_vwv1);
3044                 fsp_set_pending_modtime(fsp, mtime);
3045
3046                 /*
3047                  * close_file() returns the unix errno if an error
3048                  * was detected on close - normally this is due to
3049                  * a disk full error. If not then it was probably an I/O error.
3050                  */
3051  
3052                 if((close_err = close_file(fsp,True)) != 0) {
3053                         errno = close_err;
3054                         END_PROFILE(SMBclose);
3055                         return (UNIXERROR(ERRHRD,ERRgeneral));
3056                 }
3057         }  
3058
3059         /* We have a cached error */
3060         if(eclass || err) {
3061                 END_PROFILE(SMBclose);
3062                 return ERROR_DOS(eclass,err);
3063         }
3064
3065         END_PROFILE(SMBclose);
3066         return(outsize);
3067 }
3068
3069 /****************************************************************************
3070  Reply to a writeclose (Core+ protocol).
3071 ****************************************************************************/
3072
3073 int reply_writeclose(connection_struct *conn,
3074                      char *inbuf,char *outbuf, int size, int dum_buffsize)
3075 {
3076         size_t numtowrite;
3077         ssize_t nwritten = -1;
3078         int outsize = 0;
3079         int close_err = 0;
3080         SMB_OFF_T startpos;
3081         char *data;
3082         time_t mtime;
3083         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3084         START_PROFILE(SMBwriteclose);
3085
3086         CHECK_FSP(fsp,conn);
3087         CHECK_WRITE(fsp);
3088
3089         numtowrite = SVAL(inbuf,smb_vwv1);
3090         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3091         mtime = make_unix_date3(inbuf+smb_vwv4);
3092         data = smb_buf(inbuf) + 1;
3093   
3094         if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3095                 END_PROFILE(SMBwriteclose);
3096                 return ERROR_DOS(ERRDOS,ERRlock);
3097         }
3098   
3099         nwritten = write_file(fsp,data,startpos,numtowrite);
3100
3101         set_filetime(conn, fsp->fsp_name,mtime);
3102   
3103         /*
3104          * More insanity. W2K only closes the file if writelen > 0.
3105          * JRA.
3106          */
3107
3108         if (numtowrite) {
3109                 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3110                         fsp->fsp_name ));
3111                 close_err = close_file(fsp,True);
3112         }
3113
3114         DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3115                  fsp->fnum, (int)numtowrite, (int)nwritten,
3116                  conn->num_files_open));
3117   
3118         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3119                 END_PROFILE(SMBwriteclose);
3120                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3121         }
3122  
3123         if(close_err != 0) {
3124                 errno = close_err;
3125                 END_PROFILE(SMBwriteclose);
3126                 return(UNIXERROR(ERRHRD,ERRgeneral));
3127         }
3128  
3129         outsize = set_message(outbuf,1,0,True);
3130   
3131         SSVAL(outbuf,smb_vwv0,nwritten);
3132         END_PROFILE(SMBwriteclose);
3133         return(outsize);
3134 }
3135
3136 #undef DBGC_CLASS
3137 #define DBGC_CLASS DBGC_LOCKING
3138
3139 /****************************************************************************
3140  Reply to a lock.
3141 ****************************************************************************/
3142
3143 int reply_lock(connection_struct *conn,
3144                char *inbuf,char *outbuf, int length, int dum_buffsize)
3145 {
3146         int outsize = set_message(outbuf,0,0,True);
3147         SMB_BIG_UINT count,offset;
3148         NTSTATUS status;
3149         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3150         BOOL my_lock_ctx = False;
3151
3152         START_PROFILE(SMBlock);
3153
3154         CHECK_FSP(fsp,conn);
3155
3156         release_level_2_oplocks_on_change(fsp);
3157
3158         count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3159         offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3160
3161         DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3162                  fsp->fd, fsp->fnum, (double)offset, (double)count));
3163
3164         status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
3165         if (NT_STATUS_V(status)) {
3166 #if 0
3167                 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
3168                 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
3169                         /*
3170                          * A blocking lock was requested. Package up
3171                          * this smb into a queued request and push it
3172                          * onto the blocking lock queue.
3173                          */
3174                         if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
3175                                 END_PROFILE(SMBlock);
3176                                 return -1;
3177                         }
3178                 }
3179 #endif
3180                 END_PROFILE(SMBlock);
3181                 return ERROR_NT(status);
3182         }
3183
3184         END_PROFILE(SMBlock);
3185         return(outsize);
3186 }
3187
3188 /****************************************************************************
3189  Reply to a unlock.
3190 ****************************************************************************/
3191
3192 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, 
3193                  int dum_buffsize)
3194 {
3195         int outsize = set_message(outbuf,0,0,True);
3196         SMB_BIG_UINT count,offset;
3197         NTSTATUS status;
3198         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3199         START_PROFILE(SMBunlock);
3200
3201         CHECK_FSP(fsp,conn);
3202         
3203         count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3204         offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3205         
3206         status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
3207         if (NT_STATUS_V(status)) {
3208                 END_PROFILE(SMBunlock);
3209                 return ERROR_NT(status);
3210         }
3211
3212         DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3213                     fsp->fd, fsp->fnum, (double)offset, (double)count ) );
3214         
3215         END_PROFILE(SMBunlock);
3216         return(outsize);
3217 }
3218
3219 #undef DBGC_CLASS
3220 #define DBGC_CLASS DBGC_ALL
3221
3222 /****************************************************************************
3223  Reply to a tdis.
3224 ****************************************************************************/
3225
3226 int reply_tdis(connection_struct *conn, 
3227                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3228 {
3229         int outsize = set_message(outbuf,0,0,True);
3230         uint16 vuid;
3231         START_PROFILE(SMBtdis);
3232
3233         vuid = SVAL(inbuf,smb_uid);
3234
3235         if (!conn) {
3236                 DEBUG(4,("Invalid connection in tdis\n"));
3237                 END_PROFILE(SMBtdis);
3238                 return ERROR_DOS(ERRSRV,ERRinvnid);
3239         }
3240
3241         conn->used = False;
3242
3243         close_cnum(conn,vuid);
3244   
3245         END_PROFILE(SMBtdis);
3246         return outsize;
3247 }
3248
3249 /****************************************************************************
3250  Reply to a echo.
3251 ****************************************************************************/
3252
3253 int reply_echo(connection_struct *conn,
3254                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3255 {
3256         int smb_reverb = SVAL(inbuf,smb_vwv0);
3257         int seq_num;
3258         unsigned int data_len = smb_buflen(inbuf);
3259         int outsize = set_message(outbuf,1,data_len,True);
3260         START_PROFILE(SMBecho);
3261
3262         if (data_len > BUFFER_SIZE) {
3263                 DEBUG(0,("reply_echo: data_len too large.\n"));
3264                 END_PROFILE(SMBecho);
3265                 return -1;
3266         }
3267
3268         /* copy any incoming data back out */
3269         if (data_len > 0)
3270                 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3271
3272         if (smb_reverb > 100) {
3273                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3274                 smb_reverb = 100;
3275         }
3276
3277         for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3278                 SSVAL(outbuf,smb_vwv0,seq_num);
3279
3280                 smb_setlen(outbuf,outsize - 4);
3281
3282                 if (!send_smb(smbd_server_fd(),outbuf))
3283                         exit_server("reply_echo: send_smb failed.");
3284         }
3285
3286         DEBUG(3,("echo %d times\n", smb_reverb));
3287
3288         smb_echo_count++;
3289
3290         END_PROFILE(SMBecho);
3291         return -1;
3292 }
3293
3294 /****************************************************************************
3295  Reply to a printopen.
3296 ****************************************************************************/
3297
3298 int reply_printopen(connection_struct *conn, 
3299                     char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3300 {
3301         int outsize = 0;
3302         files_struct *fsp;
3303         START_PROFILE(SMBsplopen);
3304         
3305         if (!CAN_PRINT(conn)) {
3306                 END_PROFILE(SMBsplopen);
3307                 return ERROR_DOS(ERRDOS,ERRnoaccess);
3308         }
3309
3310         /* Open for exclusive use, write only. */
3311         fsp = print_fsp_open(conn, NULL);
3312
3313         if (!fsp) {
3314                 END_PROFILE(SMBsplopen);
3315                 return(UNIXERROR(ERRDOS,ERRnoaccess));
3316         }
3317
3318         outsize = set_message(outbuf,1,0,True);
3319         SSVAL(outbuf,smb_vwv0,fsp->fnum);
3320   
3321         DEBUG(3,("openprint fd=%d fnum=%d\n",
3322                  fsp->fd, fsp->fnum));
3323
3324         END_PROFILE(SMBsplopen);
3325         return(outsize);
3326 }
3327
3328 /****************************************************************************
3329  Reply to a printclose.
3330 ****************************************************************************/
3331
3332 int reply_printclose(connection_struct *conn,
3333                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3334 {
3335         int outsize = set_message(outbuf,0,0,True);
3336         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3337         int close_err = 0;
3338         START_PROFILE(SMBsplclose);
3339
3340         CHECK_FSP(fsp,conn);
3341
3342         if (!CAN_PRINT(conn)) {
3343                 END_PROFILE(SMBsplclose);
3344                 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
3345         }
3346   
3347         DEBUG(3,("printclose fd=%d fnum=%d\n",
3348                  fsp->fd,fsp->fnum));
3349   
3350         close_err = close_file(fsp,True);
3351
3352         if(close_err != 0) {
3353                 errno = close_err;
3354                 END_PROFILE(SMBsplclose);
3355                 return(UNIXERROR(ERRHRD,ERRgeneral));
3356         }
3357
3358         END_PROFILE(SMBsplclose);
3359         return(outsize);
3360 }
3361
3362 /****************************************************************************
3363  Reply to a printqueue.
3364 ****************************************************************************/
3365
3366 int reply_printqueue(connection_struct *conn,
3367                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3368 {
3369         int outsize = set_message(outbuf,2,3,True);
3370         int max_count = SVAL(inbuf,smb_vwv0);
3371         int start_index = SVAL(inbuf,smb_vwv1);
3372         START_PROFILE(SMBsplretq);
3373
3374         /* we used to allow the client to get the cnum wrong, but that
3375            is really quite gross and only worked when there was only
3376            one printer - I think we should now only accept it if they
3377            get it right (tridge) */
3378         if (!CAN_PRINT(conn)) {
3379                 END_PROFILE(SMBsplretq);
3380                 return ERROR_DOS(ERRDOS,ERRnoaccess);
3381         }
3382
3383         SSVAL(outbuf,smb_vwv0,0);
3384         SSVAL(outbuf,smb_vwv1,0);
3385         SCVAL(smb_buf(outbuf),0,1);
3386         SSVAL(smb_buf(outbuf),1,0);
3387   
3388         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3389                  start_index, max_count));
3390
3391         {
3392                 print_queue_struct *queue = NULL;
3393                 print_status_struct status;
3394                 char *p = smb_buf(outbuf) + 3;
3395                 int count = print_queue_status(SNUM(conn), &queue, &status);
3396                 int num_to_get = ABS(max_count);
3397                 int first = (max_count>0?start_index:start_index+max_count+1);
3398                 int i;
3399
3400                 if (first >= count)
3401                         num_to_get = 0;
3402                 else
3403                         num_to_get = MIN(num_to_get,count-first);
3404     
3405
3406                 for (i=first;i<first+num_to_get;i++) {
3407                         put_dos_date2(p,0,queue[i].time);
3408                         SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3409                         SSVAL(p,5, queue[i].job);
3410                         SIVAL(p,7,queue[i].size);
3411                         SCVAL(p,11,0);
3412                         srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3413                         p += 28;
3414                 }
3415
3416                 if (count > 0) {
3417                         outsize = set_message(outbuf,2,28*count+3,False); 
3418                         SSVAL(outbuf,smb_vwv0,count);
3419                         SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3420                         SCVAL(smb_buf(outbuf),0,1);
3421                         SSVAL(smb_buf(outbuf),1,28*count);
3422                 }
3423
3424                 SAFE_FREE(queue);
3425           
3426                 DEBUG(3,("%d entries returned in queue\n",count));
3427         }
3428   
3429         END_PROFILE(SMBsplretq);
3430         return(outsize);
3431 }
3432
3433 /****************************************************************************
3434  Reply to a printwrite.
3435 ****************************************************************************/
3436
3437 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3438 {
3439         int numtowrite;
3440         int outsize = set_message(outbuf,0,0,True);
3441         char *data;
3442         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3443
3444         START_PROFILE(SMBsplwr);
3445   
3446         if (!CAN_PRINT(conn)) {
3447                 END_PROFILE(SMBsplwr);
3448                 return ERROR_DOS(ERRDOS,ERRnoaccess);
3449         }
3450
3451         CHECK_FSP(fsp,conn);
3452         CHECK_WRITE(fsp);
3453
3454         numtowrite = SVAL(smb_buf(inbuf),1);
3455         data = smb_buf(inbuf) + 3;
3456   
3457         if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3458                 END_PROFILE(SMBsplwr);
3459                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3460         }
3461
3462         DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3463   
3464         END_PROFILE(SMBsplwr);
3465         return(outsize);
3466 }
3467
3468 /****************************************************************************
3469  The guts of the mkdir command, split out so it may be called by the NT SMB
3470  code. 
3471 ****************************************************************************/
3472
3473 NTSTATUS mkdir_internal(connection_struct *conn, const pstring directory, BOOL bad_path)
3474 {
3475         int ret= -1;
3476         
3477         if(!CAN_WRITE(conn)) {
3478                 DEBUG(5,("mkdir_internal: failing create on read-only share %s\n", lp_servicename(SNUM(conn))));
3479                 errno = EACCES;
3480                 return map_nt_error_from_unix(errno);
3481         }
3482
3483         if (bad_path) {
3484                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3485         }
3486
3487         if (!check_name(directory, conn)) {
3488                 if(errno == ENOENT) {
3489                         if (bad_path) {
3490                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3491                         } else {
3492                                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3493                         }
3494                 }
3495                 return map_nt_error_from_unix(errno);
3496         }
3497
3498         ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
3499         if (ret == -1) {
3500                 if(errno == ENOENT) {
3501                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3502                 }
3503                 return map_nt_error_from_unix(errno);
3504         }
3505         
3506         return NT_STATUS_OK;
3507 }
3508
3509 /****************************************************************************
3510  Reply to a mkdir.
3511 ****************************************************************************/
3512
3513 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3514 {
3515         pstring directory;
3516         int outsize;
3517         NTSTATUS status;
3518         BOOL bad_path = False;
3519         SMB_STRUCT_STAT sbuf;
3520
3521         START_PROFILE(SMBmkdir);
3522  
3523         srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3524         if (!NT_STATUS_IS_OK(status)) {
3525                 END_PROFILE(SMBmkdir);
3526                 return ERROR_NT(status);
3527         }
3528
3529         RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3530
3531         unix_convert(directory,conn,0,&bad_path,&sbuf);
3532
3533         if( strchr_m(directory, ':')) {
3534                 DEBUG(5,("reply_mkdir: failing create on filename %s with colon in name\n", directory));
3535                 END_PROFILE(SMBmkdir);
3536                 return ERROR_FORCE_DOS(ERRDOS, ERRinvalidname);
3537         }
3538
3539         status = mkdir_internal(conn, directory,bad_path);
3540         if (!NT_STATUS_IS_OK(status)) {
3541                 END_PROFILE(SMBmkdir);
3542                 return ERROR_NT(status);
3543         }
3544
3545         if (lp_inherit_owner(SNUM(conn))) {
3546                 /* Ensure we're checking for a symlink here.... */
3547                 /* We don't want to get caught by a symlink racer. */
3548
3549                 if(SMB_VFS_LSTAT(conn,directory, &sbuf) != 0) {
3550                         END_PROFILE(SMBmkdir);
3551                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3552                 }
3553                                                                                                                                                    
3554                 if(!S_ISDIR(sbuf.st_mode)) {
3555                         DEBUG(0,("reply_mkdir: %s is not a directory !\n", directory ));
3556                         END_PROFILE(SMBmkdir);
3557                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3558                 }
3559
3560                 change_owner_to_parent(conn, NULL, directory, &sbuf);
3561         }
3562
3563         outsize = set_message(outbuf,0,0,True);
3564
3565         DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3566
3567         END_PROFILE(SMBmkdir);
3568         return(outsize);
3569 }
3570
3571 /****************************************************************************
3572  Static function used by reply_rmdir to delete an entire directory
3573  tree recursively. Return False on ok, True on fail.
3574 ****************************************************************************/
3575
3576 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3577 {
3578         const char *dname = NULL;
3579         BOOL ret = False;
3580         long offset = 0;
3581         struct smb_Dir *dir_hnd = OpenDir(conn, directory);
3582
3583         if(dir_hnd == NULL)
3584                 return True;
3585
3586         while((dname = ReadDirName(dir_hnd, &offset))) {
3587                 pstring fullname;
3588                 SMB_STRUCT_STAT st;
3589
3590                 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3591                         continue;
3592
3593                 if (!is_visible_file(conn, directory, dname, &st, False))
3594                         continue;
3595
3596                 /* Construct the full name. */
3597                 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3598                         errno = ENOMEM;
3599                         ret = True;
3600                         break;
3601                 }
3602
3603                 pstrcpy(fullname, directory);
3604                 pstrcat(fullname, "/");
3605                 pstrcat(fullname, dname);
3606
3607                 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3608                         ret = True;
3609                         break;
3610                 }
3611
3612                 if(st.st_mode & S_IFDIR) {
3613                         if(recursive_rmdir(conn, fullname)!=0) {
3614                                 ret = True;
3615                                 break;
3616                         }
3617                         if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3618                                 ret = True;
3619                                 break;
3620                         }
3621                 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3622                         ret = True;
3623                         break;
3624                 }
3625         }
3626         CloseDir(dir_hnd);
3627         return ret;
3628 }
3629
3630 /****************************************************************************
3631  The internals of the rmdir code - called elsewhere.
3632 ****************************************************************************/
3633
3634 BOOL rmdir_internals(connection_struct *conn, char *directory)
3635 {
3636         BOOL ok;
3637         SMB_STRUCT_STAT st;
3638
3639         ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3640         if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3641                 /* 
3642                  * Check to see if the only thing in this directory are
3643                  * vetoed files/directories. If so then delete them and
3644                  * retry. If we fail to delete any of them (and we *don't*
3645                  * do a recursive delete) then fail the rmdir.
3646                  */
3647                 BOOL all_veto_files = True;
3648                 const char *dname;
3649                 struct smb_Dir *dir_hnd = OpenDir(conn, directory);
3650
3651                 if(dir_hnd != NULL) {
3652                         long dirpos = TellDir(dir_hnd);
3653                         while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3654                                 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3655                                         continue;
3656                                 if (!is_visible_file(conn, directory, dname, &st, False))
3657                                         continue;
3658                                 if(!IS_VETO_PATH(conn, dname)) {
3659                                         all_veto_files = False;
3660                                         break;
3661                                 }
3662                         }
3663
3664                         if(all_veto_files) {
3665                                 SeekDir(dir_hnd,dirpos);
3666                                 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3667                                         pstring fullname;
3668
3669                                         if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3670                                                 continue;
3671                                         if (!is_visible_file(conn, directory, dname, &st, False))
3672                                                 continue;
3673
3674                                         /* Construct the full name. */
3675                                         if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3676                                                 errno = ENOMEM;
3677                                                 break;
3678                                         }
3679
3680                                         pstrcpy(fullname, directory);
3681                                         pstrcat(fullname, "/");
3682                                         pstrcat(fullname, dname);
3683                      
3684                                         if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3685                                                 break;
3686                                         if(st.st_mode & S_IFDIR) {
3687                                                 if(lp_recursive_veto_delete(SNUM(conn))) {
3688                                                         if(recursive_rmdir(conn, fullname) != 0)
3689                                                                 break;
3690                                                 }
3691                                                 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3692                                                         break;
3693                                         } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3694                                                 break;
3695                                 }
3696                                 CloseDir(dir_hnd);
3697                                 /* Retry the rmdir */
3698                                 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3699                         } else {
3700                                 CloseDir(dir_hnd);
3701                         }
3702                 } else {
3703                         errno = ENOTEMPTY;
3704                 }
3705         }
3706
3707         if (!ok)
3708                 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3709
3710         return ok;
3711 }
3712
3713 /****************************************************************************
3714  Reply to a rmdir.
3715 ****************************************************************************/
3716
3717 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3718 {
3719         pstring directory;
3720         int outsize = 0;
3721         BOOL ok = False;
3722         BOOL bad_path = False;
3723         SMB_STRUCT_STAT sbuf;
3724         NTSTATUS status;
3725         START_PROFILE(SMBrmdir);
3726
3727         srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3728         if (!NT_STATUS_IS_OK(status)) {
3729                 END_PROFILE(SMBrmdir);
3730                 return ERROR_NT(status);
3731         }
3732
3733         RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3734
3735         unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3736         if (bad_path) {
3737                 END_PROFILE(SMBrmdir);
3738                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3739         }
3740   
3741         if (check_name(directory,conn)) {
3742                 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3743                 ok = rmdir_internals(conn, directory);
3744         }
3745   
3746         if (!ok) {
3747                 END_PROFILE(SMBrmdir);
3748                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3749         }
3750  
3751         outsize = set_message(outbuf,0,0,True);
3752   
3753         DEBUG( 3, ( "rmdir %s\n", directory ) );
3754   
3755         END_PROFILE(SMBrmdir);
3756         return(outsize);
3757 }
3758
3759 /*******************************************************************
3760  Resolve wildcards in a filename rename.
3761  Note that name is in UNIX charset and thus potentially can be more
3762  than fstring buffer (255 bytes) especially in default UTF-8 case.
3763  Therefore, we use pstring inside and all calls should ensure that
3764  name2 is at least pstring-long (they do already)
3765 ********************************************************************/
3766
3767 static BOOL resolve_wildcards(const char *name1, char *name2)
3768 {
3769         pstring root1,root2;
3770         pstring ext1,ext2;
3771         char *p,*p2, *pname1, *pname2;
3772         int available_space, actual_space;
3773         
3774
3775         pname1 = strrchr_m(name1,'/');
3776         pname2 = strrchr_m(name2,'/');
3777
3778         if (!pname1 || !pname2)
3779                 return(False);
3780   
3781         pstrcpy(root1,pname1);
3782         pstrcpy(root2,pname2);
3783         p = strrchr_m(root1,'.');
3784         if (p) {
3785                 *p = 0;
3786                 pstrcpy(ext1,p+1);
3787         } else {
3788                 pstrcpy(ext1,"");    
3789         }
3790         p = strrchr_m(root2,'.');
3791         if (p) {
3792                 *p = 0;
3793                 pstrcpy(ext2,p+1);
3794         } else {
3795                 pstrcpy(ext2,"");    
3796         }
3797
3798         p = root1;
3799         p2 = root2;
3800         while (*p2) {
3801                 if (*p2 == '?') {
3802                         *p2 = *p;
3803                         p2++;
3804                 } else if (*p2 == '*') {
3805                         pstrcpy(p2, p);
3806                         break;
3807                 } else {
3808                         p2++;
3809                 }
3810                 if (*p)
3811                         p++;
3812         }
3813
3814         p = ext1;
3815         p2 = ext2;
3816         while (*p2) {
3817                 if (*p2 == '?') {
3818                         *p2 = *p;
3819                         p2++;
3820                 } else if (*p2 == '*') {
3821                         pstrcpy(p2, p);
3822                         break;
3823                 } else {
3824                         p2++;
3825                 }
3826                 if (*p)
3827                         p++;
3828         }
3829
3830         available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3831         
3832         if (ext2[0]) {
3833                 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3834                 if (actual_space >= available_space - 1) {
3835                         DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3836                                 actual_space - available_space));
3837                 }
3838         } else {
3839                 pstrcpy_base(pname2, root2, name2);
3840         }
3841
3842         return(True);
3843 }
3844
3845 /****************************************************************************
3846  Ensure open files have their names updates.
3847 ****************************************************************************/
3848
3849 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3850 {
3851         files_struct *fsp;
3852         BOOL did_rename = False;
3853
3854         for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3855                 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3856                         fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3857                         fsp->fsp_name, newname ));
3858                 string_set(&fsp->fsp_name, newname);
3859                 did_rename = True;
3860         }
3861
3862         if (!did_rename)
3863                 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3864                         (unsigned int)dev, (double)inode, newname ));
3865 }
3866
3867 /****************************************************************************
3868  Rename an open file - given an fsp.
3869 ****************************************************************************/
3870
3871 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint16 attrs, BOOL replace_if_exists)
3872 {
3873         SMB_STRUCT_STAT sbuf;
3874         BOOL bad_path = False;
3875         pstring newname_last_component;
3876         NTSTATUS error = NT_STATUS_OK;
3877         BOOL dest_exists;
3878         BOOL rcdest = True;
3879
3880         ZERO_STRUCT(sbuf);
3881         rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3882
3883         /* Quick check for "." and ".." */
3884         if (!bad_path && newname_last_component[0] == '.') {
3885                 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3886                         return NT_STATUS_ACCESS_DENIED;
3887                 }
3888         }
3889         if (!rcdest && bad_path) {
3890                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3891         }
3892
3893         /* Ensure newname contains a '/' */
3894         if(strrchr_m(newname,'/') == 0) {
3895                 pstring tmpstr;
3896                 
3897                 pstrcpy(tmpstr, "./");
3898                 pstrcat(tmpstr, newname);
3899                 pstrcpy(newname, tmpstr);
3900         }
3901
3902         /*
3903          * Check for special case with case preserving and not
3904          * case sensitive. If the old last component differs from the original
3905          * last component only by case, then we should allow
3906          * the rename (user is trying to change the case of the
3907          * filename).
3908          */
3909
3910         if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
3911                         strequal(newname, fsp->fsp_name)) {
3912                 char *p;
3913                 pstring newname_modified_last_component;
3914
3915                 /*
3916                  * Get the last component of the modified name.
3917                  * Note that we guarantee that newname contains a '/'
3918                  * character above.
3919                  */
3920                 p = strrchr_m(newname,'/');
3921                 pstrcpy(newname_modified_last_component,p+1);
3922                         
3923                 if(strcsequal(newname_modified_last_component, 
3924                               newname_last_component) == False) {
3925                         /*
3926                          * Replace the modified last component with
3927                          * the original.
3928                          */
3929                         pstrcpy(p+1, newname_last_component);
3930                 }
3931         }
3932
3933         /*
3934          * If the src and dest names are identical - including case,
3935          * don't do the rename, just return success.
3936          */
3937
3938         if (strcsequal(fsp->fsp_name, newname)) {
3939                 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3940                         newname));
3941                 return NT_STATUS_OK;
3942         }
3943
3944         dest_exists = vfs_object_exist(conn,newname,NULL);
3945
3946         if(!replace_if_exists && dest_exists) {
3947                 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3948                         fsp->fsp_name,newname));
3949                 return NT_STATUS_OBJECT_NAME_COLLISION;
3950         }
3951
3952         error = can_rename(conn,newname,attrs,&sbuf);
3953
3954         if (dest_exists && !NT_STATUS_IS_OK(error)) {
3955                 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3956                         nt_errstr(error), fsp->fsp_name,newname));
3957                 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3958                         error = NT_STATUS_ACCESS_DENIED;
3959                 return error;
3960         }
3961
3962         if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3963                 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3964                         fsp->fsp_name,newname));
3965                 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3966                 return NT_STATUS_OK;    
3967         }
3968
3969         if (errno == ENOTDIR || errno == EISDIR)
3970                 error = NT_STATUS_OBJECT_NAME_COLLISION;
3971         else
3972                 error = map_nt_error_from_unix(errno);
3973                 
3974         DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3975                 nt_errstr(error), fsp->fsp_name,newname));
3976
3977         return error;
3978 }
3979
3980 /****************************************************************************
3981  The guts of the rename command, split out so it may be called by the NT SMB
3982  code. 
3983 ****************************************************************************/
3984
3985 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
3986 {
3987         pstring directory;
3988         pstring mask;
3989         pstring last_component_src;
3990         pstring last_component_dest;
3991         char *p;
3992         BOOL has_wild;
3993         BOOL bad_path_src = False;
3994         BOOL bad_path_dest = False;
3995         int count=0;
3996         NTSTATUS error = NT_STATUS_OK;
3997         BOOL rc = True;
3998         BOOL rcdest = True;
3999         SMB_STRUCT_STAT sbuf1, sbuf2;
4000
4001         *directory = *mask = 0;
4002
4003         ZERO_STRUCT(sbuf1);
4004         ZERO_STRUCT(sbuf2);
4005
4006         rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
4007         if (!rc && bad_path_src) {
4008                 if (ms_has_wild(last_component_src))
4009                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4010                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4011         }
4012
4013         /* Quick check for "." and ".." */
4014         if (last_component_src[0] == '.') {
4015                 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
4016                         return NT_STATUS_OBJECT_NAME_INVALID;
4017                 }
4018         }
4019
4020         rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
4021
4022         /* Quick check for "." and ".." */
4023         if (last_component_dest[0] == '.') {
4024                 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
4025                         return NT_STATUS_OBJECT_NAME_INVALID;
4026                 }
4027         }
4028
4029         /*
4030          * Split the old name into directory and last component
4031          * strings. Note that unix_convert may have stripped off a 
4032          * leading ./ from both name and newname if the rename is 
4033          * at the root of the share. We need to make sure either both
4034          * name and newname contain a / character or neither of them do
4035          * as this is checked in resolve_wildcards().
4036          */
4037
4038         p = strrchr_m(name,'/');
4039         if (!p) {
4040                 pstrcpy(directory,".");
4041                 pstrcpy(mask,name);
4042         } else {
4043                 *p = 0;
4044                 pstrcpy(directory,name);
4045                 pstrcpy(mask,p+1);
4046                 *p = '/'; /* Replace needed for exceptional test below. */
4047         }
4048
4049         /*
4050          * We should only check the mangled cache
4051          * here if unix_convert failed. This means
4052          * that the path in 'mask' doesn't exist
4053          * on the file system and so we need to look
4054          * for a possible mangle. This patch from
4055          * Tine Smukavec <valentin.smukavec@hermes.si>.
4056          */
4057
4058         if (!rc && mangle_is_mangled(mask))
4059                 mangle_check_cache( mask, sizeof(pstring)-1 );
4060
4061         has_wild = ms_has_wild(mask);
4062
4063         if (!has_wild) {
4064                 /*
4065                  * No wildcards - just process the one file.
4066                  */
4067                 BOOL is_short_name = mangle_is_8_3(name, True);
4068
4069                 /* Add a terminating '/' to the directory name. */
4070                 pstrcat(directory,"/");
4071                 pstrcat(directory,mask);
4072                 
4073                 /* Ensure newname contains a '/' also */
4074                 if(strrchr_m(newname,'/') == 0) {
4075                         pstring tmpstr;
4076                         
4077                         pstrcpy(tmpstr, "./");
4078                         pstrcat(tmpstr, newname);
4079                         pstrcpy(newname, tmpstr);
4080                 }
4081                 
4082                 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
4083 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", 
4084                          conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory, 
4085                          newname, last_component_dest, is_short_name));
4086
4087                 /*
4088                  * Check for special case with case preserving and not
4089                  * case sensitive, if directory and newname are identical,
4090                  * and the old last component differs from the original
4091                  * last component only by case, then we should allow
4092                  * the rename (user is trying to change the case of the
4093                  * filename).
4094                  */
4095                 if((conn->case_sensitive == False) && 
4096                    (((conn->case_preserve == True) && 
4097                      (is_short_name == False)) || 
4098                     ((conn->short_case_preserve == True) && 
4099                      (is_short_name == True))) &&
4100                    strcsequal(directory, newname)) {
4101                         pstring modified_last_component;
4102
4103                         /*
4104                          * Get the last component of the modified name.
4105                          * Note that we guarantee that newname contains a '/'
4106                          * character above.
4107                          */
4108                         p = strrchr_m(newname,'/');
4109                         pstrcpy(modified_last_component,p+1);
4110                         
4111                         if(strcsequal(modified_last_component, 
4112                                       last_component_dest) == False) {
4113                                 /*
4114                                  * Replace the modified last component with
4115                                  * the original.
4116                                  */
4117                                 pstrcpy(p+1, last_component_dest);
4118                         }
4119                 }
4120         
4121                 resolve_wildcards(directory,newname);
4122         
4123                 /*
4124                  * The source object must exist.
4125                  */
4126
4127                 if (!vfs_object_exist(conn, directory, &sbuf1)) {
4128                         DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
4129                                 directory,newname));
4130
4131                         if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
4132                                 /*
4133                                  * Must return different errors depending on whether the parent
4134                                  * directory existed or not.
4135                                  */
4136
4137                                 p = strrchr_m(directory, '/');
4138                                 if (!p)
4139                                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4140                                 *p = '\0';
4141                                 if (vfs_object_exist(conn, directory, NULL))
4142                                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4143                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4144                         }
4145                         error = map_nt_error_from_unix(errno);
4146                         DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4147                                 nt_errstr(error), directory,newname));
4148
4149                         return error;
4150                 }
4151
4152                 if (!rcdest && bad_path_dest) {
4153                         if (ms_has_wild(last_component_dest))
4154                                 return NT_STATUS_OBJECT_NAME_INVALID;
4155                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4156                 }
4157
4158                 error = can_rename(conn,directory,attrs,&sbuf1);
4159
4160                 if (!NT_STATUS_IS_OK(error)) {
4161                         DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4162                                 nt_errstr(error), directory,newname));
4163                         return error;
4164                 }
4165
4166                 /*
4167                  * If the src and dest names are identical - including case,
4168                  * don't do the rename, just return success.
4169                  */
4170
4171                 if (strcsequal(directory, newname)) {
4172                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4173                         DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
4174                         return NT_STATUS_OK;
4175                 }
4176
4177                 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
4178                         DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
4179                                 directory,newname));
4180                         return NT_STATUS_OBJECT_NAME_COLLISION;
4181                 }
4182
4183                 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
4184                         DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
4185                                 directory,newname));
4186                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4187                         return NT_STATUS_OK;    
4188                 }
4189
4190                 if (errno == ENOTDIR || errno == EISDIR)
4191                         error = NT_STATUS_OBJECT_NAME_COLLISION;
4192                 else
4193                         error = map_nt_error_from_unix(errno);
4194                 
4195                 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4196                         nt_errstr(error), directory,newname));
4197
4198                 return error;
4199         } else {
4200                 /*
4201                  * Wildcards - process each file that matches.
4202                  */
4203                 struct smb_Dir *dir_hnd = NULL;
4204                 const char *dname;
4205                 pstring destname;
4206                 
4207                 if (check_name(directory,conn))
4208                         dir_hnd = OpenDir(conn, directory);
4209                 
4210                 if (dir_hnd) {
4211                         long offset = 0;
4212                         error = NT_STATUS_NO_SUCH_FILE;
4213 /*                      Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
4214                         
4215                         if (strequal(mask,"????????.???"))
4216                                 pstrcpy(mask,"*");
4217                         
4218                         while ((dname = ReadDirName(dir_hnd, &offset))) {
4219                                 pstring fname;
4220                                 BOOL sysdir_entry = False;
4221
4222                                 pstrcpy(fname,dname);
4223                                 
4224                                 /* Quick check for "." and ".." */
4225                                 if (fname[0] == '.') {
4226                                         if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4227                                                 if (attrs & aDIR) {
4228                                                         sysdir_entry = True;
4229                                                 } else {
4230                                                         continue;
4231                                                 }
4232                                         }
4233                                 }
4234
4235                                 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4236                                         continue;
4237
4238                                 if(!mask_match(fname, mask, conn->case_sensitive))
4239                                         continue;
4240                                 
4241                                 if (sysdir_entry) {
4242                                         error = NT_STATUS_OBJECT_NAME_INVALID;
4243                                         break;
4244                                 }
4245
4246                                 error = NT_STATUS_ACCESS_DENIED;
4247                                 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
4248                                 if (!vfs_object_exist(conn, fname, &sbuf1)) {
4249                                         error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4250                                         DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
4251                                         continue;
4252                                 }
4253                                 error = can_rename(conn,fname,attrs,&sbuf1);
4254                                 if (!NT_STATUS_IS_OK(error)) {
4255                                         DEBUG(6,("rename %s refused\n", fname));
4256                                         continue;
4257                                 }
4258                                 pstrcpy(destname,newname);
4259                                 
4260                                 if (!resolve_wildcards(fname,destname)) {
4261                                         DEBUG(6,("resolve_wildcards %s %s failed\n", 
4262                                                  fname, destname));
4263                                         continue;
4264                                 }
4265                                 
4266                                 if (strcsequal(fname,destname)) {
4267                                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4268                                         DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
4269                                         count++;
4270                                         error = NT_STATUS_OK;
4271                                         continue;
4272                                 }
4273
4274                                 if (!replace_if_exists && 
4275                                     vfs_file_exist(conn,destname, NULL)) {
4276                                         DEBUG(6,("file_exist %s\n", destname));
4277                                         error = NT_STATUS_OBJECT_NAME_COLLISION;
4278                                         continue;
4279                                 }
4280                                 
4281                                 if (!SMB_VFS_RENAME(conn,fname,destname)) {
4282                                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4283                                         count++;
4284                                         error = NT_STATUS_OK;
4285                                 }
4286                                 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
4287                         }
4288                         CloseDir(dir_hnd);
4289                 }
4290
4291                 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
4292                         if (!rcdest && bad_path_dest) {
4293                                 if (ms_has_wild(last_component_dest))
4294                                         return NT_STATUS_OBJECT_NAME_INVALID;
4295                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4296                         }
4297                 }
4298         }
4299         
4300         if (count == 0 && NT_STATUS_IS_OK(error)) {
4301                 error = map_nt_error_from_unix(errno);
4302         }
4303         
4304         return error;
4305 }
4306
4307 /****************************************************************************
4308  Reply to a mv.
4309 ****************************************************************************/
4310
4311 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, 
4312              int dum_buffsize)
4313 {
4314         int outsize = 0;
4315         pstring name;
4316         pstring newname;
4317         char *p;
4318         uint16 attrs = SVAL(inbuf,smb_vwv0);
4319         NTSTATUS status;
4320
4321         START_PROFILE(SMBmv);
4322
4323         p = smb_buf(inbuf) + 1;
4324         p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4325         if (!NT_STATUS_IS_OK(status)) {
4326                 END_PROFILE(SMBmv);
4327                 return ERROR_NT(status);
4328         }
4329         p++;
4330         p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4331         if (!NT_STATUS_IS_OK(status)) {
4332                 END_PROFILE(SMBmv);
4333                 return ERROR_NT(status);
4334         }
4335         
4336         RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4337         RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4338         
4339         DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4340         
4341         status = rename_internals(conn, name, newname, attrs, False);
4342         if (!NT_STATUS_IS_OK(status)) {
4343                 END_PROFILE(SMBmv);
4344                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4345                         /* We have re-scheduled this call. */
4346                         return -1;
4347                 }
4348                 return ERROR_NT(status);
4349         }
4350
4351         /*
4352          * Win2k needs a changenotify request response before it will
4353          * update after a rename..
4354          */     
4355         process_pending_change_notify_queue((time_t)0);
4356         outsize = set_message(outbuf,0,0,True);
4357   
4358         END_PROFILE(SMBmv);
4359         return(outsize);
4360 }
4361
4362 /*******************************************************************
4363  Copy a file as part of a reply_copy.
4364 ******************************************************************/
4365
4366 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4367                       int count,BOOL target_is_directory, int *err_ret)
4368 {
4369         int Access,action;
4370         SMB_STRUCT_STAT src_sbuf, sbuf2;
4371         SMB_OFF_T ret=-1;
4372         files_struct *fsp1,*fsp2;
4373         pstring dest;
4374         uint32 dosattrs;
4375  
4376         *err_ret = 0;
4377
4378         pstrcpy(dest,dest1);
4379         if (target_is_directory) {
4380                 char *p = strrchr_m(src,'/');
4381                 if (p) 
4382                         p++;
4383                 else
4384                         p = src;
4385                 pstrcat(dest,"/");
4386                 pstrcat(dest,p);
4387         }
4388
4389         if (!vfs_file_exist(conn,src,&src_sbuf))
4390                 return(False);
4391
4392         fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
4393                                         (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,INTERNAL_OPEN_ONLY,
4394                                         &Access,&action);
4395
4396         if (!fsp1)
4397                 return(False);
4398
4399         if (!target_is_directory && count)
4400                 ofun = FILE_EXISTS_OPEN;
4401
4402         dosattrs = dos_mode(conn, src, &src_sbuf);
4403         if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
4404                 ZERO_STRUCTP(&sbuf2);
4405
4406         fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4407                         ofun,dosattrs,INTERNAL_OPEN_ONLY,&Access,&action);
4408
4409         if (!fsp2) {
4410                 close_file(fsp1,False);
4411                 return(False);
4412         }
4413
4414         if ((ofun&3) == 1) {
4415                 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4416                         DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4417                         /*
4418                          * Stop the copy from occurring.
4419                          */
4420                         ret = -1;
4421                         src_sbuf.st_size = 0;
4422                 }
4423         }
4424   
4425         if (src_sbuf.st_size)
4426                 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4427
4428         close_file(fsp1,False);
4429
4430         /* Ensure the modtime is set correctly on the destination file. */
4431         fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime);
4432
4433         /*
4434          * As we are opening fsp1 read-only we only expect
4435          * an error on close on fsp2 if we are out of space.
4436          * Thus we don't look at the error return from the
4437          * close of fsp1.
4438          */
4439         *err_ret = close_file(fsp2,False);
4440
4441         return(ret == (SMB_OFF_T)src_sbuf.st_size);
4442 }
4443
4444 /****************************************************************************
4445  Reply to a file copy.
4446 ****************************************************************************/
4447
4448 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4449 {
4450         int outsize = 0;
4451         pstring name;
4452         pstring directory;
4453         pstring mask,newname;
4454         char *p;
4455         int count=0;
4456         int error = ERRnoaccess;
4457         int err = 0;
4458         BOOL has_wild;
4459         BOOL exists=False;
4460         int tid2 = SVAL(inbuf,smb_vwv0);
4461         int ofun = SVAL(inbuf,smb_vwv1);
4462         int flags = SVAL(inbuf,smb_vwv2);
4463         BOOL target_is_directory=False;
4464         BOOL bad_path1 = False;
4465         BOOL bad_path2 = False;
4466         BOOL rc = True;
4467         SMB_STRUCT_STAT sbuf1, sbuf2;
4468         NTSTATUS status;
4469
4470         START_PROFILE(SMBcopy);
4471
4472         *directory = *mask = 0;
4473
4474         p = smb_buf(inbuf);
4475         p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4476         if (!NT_STATUS_IS_OK(status)) {
4477                 END_PROFILE(SMBcopy);
4478                 return ERROR_NT(status);
4479         }
4480         p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4481         if (!NT_STATUS_IS_OK(status)) {
4482                 END_PROFILE(SMBcopy);
4483                 return ERROR_NT(status);
4484         }
4485    
4486         DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4487    
4488         if (tid2 != conn->cnum) {
4489                 /* can't currently handle inter share copies XXXX */
4490                 DEBUG(3,("Rejecting inter-share copy\n"));
4491                 END_PROFILE(SMBcopy);
4492                 return ERROR_DOS(ERRSRV,ERRinvdevice);
4493         }
4494
4495         RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4496         RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4497
4498         rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4499         unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4500
4501         target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4502
4503         if ((flags&1) && target_is_directory) {
4504                 END_PROFILE(SMBcopy);
4505                 return ERROR_DOS(ERRDOS,ERRbadfile);
4506         }
4507
4508         if ((flags&2) && !target_is_directory) {
4509                 END_PROFILE(SMBcopy);
4510                 return ERROR_DOS(ERRDOS,ERRbadpath);
4511         }
4512
4513         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4514                 /* wants a tree copy! XXXX */
4515                 DEBUG(3,("Rejecting tree copy\n"));
4516                 END_PROFILE(SMBcopy);
4517                 return ERROR_DOS(ERRSRV,ERRerror);
4518         }
4519
4520         p = strrchr_m(name,'/');
4521         if (!p) {
4522                 pstrcpy(directory,"./");
4523                 pstrcpy(mask,name);
4524         } else {
4525                 *p = 0;
4526                 pstrcpy(directory,name);
4527                 pstrcpy(mask,p+1);
4528         }
4529
4530         /*
4531          * We should only check the mangled cache
4532          * here if unix_convert failed. This means
4533          * that the path in 'mask' doesn't exist
4534          * on the file system and so we need to look
4535          * for a possible mangle. This patch from
4536          * Tine Smukavec <valentin.smukavec@hermes.si>.
4537          */
4538
4539         if (!rc && mangle_is_mangled(mask))
4540                 mangle_check_cache( mask, sizeof(pstring)-1 );
4541
4542         has_wild = ms_has_wild(mask);
4543
4544         if (!has_wild) {
4545                 pstrcat(directory,"/");
4546                 pstrcat(directory,mask);
4547                 if (resolve_wildcards(directory,newname) &&
4548                                 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4549                         count++;
4550                 if(!count && err) {
4551                         errno = err;
4552                         END_PROFILE(SMBcopy);
4553                         return(UNIXERROR(ERRHRD,ERRgeneral));
4554                 }
4555                 if (!count) {
4556                         exists = vfs_file_exist(conn,directory,NULL);
4557                 }
4558         } else {
4559                 struct smb_Dir *dir_hnd = NULL;
4560                 const char *dname;
4561                 pstring destname;
4562
4563                 if (check_name(directory,conn))
4564                         dir_hnd = OpenDir(conn, directory);
4565
4566                 if (dir_hnd) {
4567                         long offset = 0;
4568                         error = ERRbadfile;
4569
4570                         if (strequal(mask,"????????.???"))
4571                                 pstrcpy(mask,"*");
4572
4573                         while ((dname = ReadDirName(dir_hnd, &offset))) {
4574                                 pstring fname;
4575                                 pstrcpy(fname,dname);
4576     
4577                                 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4578                                         continue;
4579
4580                                 if(!mask_match(fname, mask, conn->case_sensitive))
4581                                         continue;
4582
4583                                 error = ERRnoaccess;
4584                                 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4585                                 pstrcpy(destname,newname);
4586                                 if (resolve_wildcards(fname,destname) && 
4587                                                 copy_file(fname,destname,conn,ofun,
4588                                                 count,target_is_directory,&err))
4589                                         count++;
4590                                 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4591                         }
4592                         CloseDir(dir_hnd);
4593                 }
4594         }
4595   
4596         if (count == 0) {
4597                 if(err) {
4598                         /* Error on close... */
4599                         errno = err;
4600                         END_PROFILE(SMBcopy);
4601                         return(UNIXERROR(ERRHRD,ERRgeneral));
4602                 }
4603
4604                 if (exists) {
4605                         END_PROFILE(SMBcopy);
4606                         return ERROR_DOS(ERRDOS,error);
4607                 } else {
4608                         if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4609                                 set_saved_error_triple(ERRDOS, ERRbadpath, NT_STATUS_OK);
4610                         }
4611                         END_PROFILE(SMBcopy);
4612                         return(UNIXERROR(ERRDOS,error));
4613                 }
4614         }
4615   
4616         outsize = set_message(outbuf,1,0,True);
4617         SSVAL(outbuf,smb_vwv0,count);
4618
4619         END_PROFILE(SMBcopy);
4620         return(outsize);
4621 }
4622
4623 /****************************************************************************
4624  Reply to a setdir.
4625 ****************************************************************************/
4626
4627 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4628 {
4629         int snum;
4630         int outsize = 0;
4631         BOOL ok = False;
4632         pstring newdir;
4633         NTSTATUS status;
4634
4635         START_PROFILE(pathworks_setdir);
4636   
4637         snum = SNUM(conn);
4638         if (!CAN_SETDIR(snum)) {
4639                 END_PROFILE(pathworks_setdir);
4640                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4641         }
4642
4643         srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False);
4644         if (!NT_STATUS_IS_OK(status)) {
4645                 END_PROFILE(pathworks_setdir);
4646                 return ERROR_NT(status);
4647         }
4648   
4649         RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf);
4650
4651         if (strlen(newdir) == 0) {
4652                 ok = True;
4653         } else {
4654                 ok = vfs_directory_exist(conn,newdir,NULL);
4655                 if (ok)
4656                         string_set(&conn->connectpath,newdir);
4657         }
4658   
4659         if (!ok) {
4660                 END_PROFILE(pathworks_setdir);
4661                 return ERROR_DOS(ERRDOS,ERRbadpath);
4662         }
4663   
4664         outsize = set_message(outbuf,0,0,True);
4665         SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4666   
4667         DEBUG(3,("setdir %s\n", newdir));
4668
4669         END_PROFILE(pathworks_setdir);
4670         return(outsize);
4671 }
4672
4673 #undef DBGC_CLASS
4674 #define DBGC_CLASS DBGC_LOCKING
4675
4676 /****************************************************************************
4677  Get a lock pid, dealing with large count requests.
4678 ****************************************************************************/
4679
4680 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4681 {
4682         if(!large_file_format)
4683                 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4684         else
4685                 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4686 }
4687
4688 /****************************************************************************
4689  Get a lock count, dealing with large count requests.
4690 ****************************************************************************/
4691
4692 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4693 {
4694         SMB_BIG_UINT count = 0;
4695
4696         if(!large_file_format) {
4697                 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4698         } else {
4699
4700 #if defined(HAVE_LONGLONG)
4701                 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4702                         ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4703 #else /* HAVE_LONGLONG */
4704
4705                 /*
4706                  * NT4.x seems to be broken in that it sends large file (64 bit)
4707                  * lockingX calls even if the CAP_LARGE_FILES was *not*
4708                  * negotiated. For boxes without large unsigned ints truncate the
4709                  * lock count by dropping the top 32 bits.
4710                  */
4711
4712                 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4713                         DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4714                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4715                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4716                                 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4717                 }
4718
4719                 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4720 #endif /* HAVE_LONGLONG */
4721         }
4722
4723         return count;
4724 }
4725
4726 #if !defined(HAVE_LONGLONG)
4727 /****************************************************************************
4728  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4729 ****************************************************************************/
4730
4731 static uint32 map_lock_offset(uint32 high, uint32 low)
4732 {
4733         unsigned int i;
4734         uint32 mask = 0;
4735         uint32 highcopy = high;
4736  
4737         /*
4738          * Try and find out how many significant bits there are in high.
4739          */
4740  
4741         for(i = 0; highcopy; i++)
4742                 highcopy >>= 1;
4743  
4744         /*
4745          * We use 31 bits not 32 here as POSIX
4746          * lock offsets may not be negative.
4747          */
4748  
4749         mask = (~0) << (31 - i);
4750  
4751         if(low & mask)
4752                 return 0; /* Fail. */
4753  
4754         high <<= (31 - i);
4755  
4756         return (high|low);
4757 }
4758 #endif /* !defined(HAVE_LONGLONG) */
4759
4760 /****************************************************************************
4761  Get a lock offset, dealing with large offset requests.
4762 ****************************************************************************/
4763
4764 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4765 {
4766         SMB_BIG_UINT offset = 0;
4767
4768         *err = False;
4769
4770         if(!large_file_format) {
4771                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4772         } else {
4773
4774 #if defined(HAVE_LONGLONG)
4775                 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4776                                 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4777 #else /* HAVE_LONGLONG */
4778
4779                 /*
4780                  * NT4.x seems to be broken in that it sends large file (64 bit)
4781                  * lockingX calls even if the CAP_LARGE_FILES was *not*
4782                  * negotiated. For boxes without large unsigned ints mangle the
4783                  * lock offset by mapping the top 32 bits onto the lower 32.
4784                  */
4785       
4786                 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4787                         uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4788                         uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4789                         uint32 new_low = 0;
4790
4791                         if((new_low = map_lock_offset(high, low)) == 0) {
4792                                 *err = True;
4793                                 return (SMB_BIG_UINT)-1;
4794                         }
4795
4796                         DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4797                                 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4798                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4799                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4800                 }
4801
4802                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4803 #endif /* HAVE_LONGLONG */
4804         }
4805
4806         return offset;
4807 }
4808
4809 /****************************************************************************
4810  Reply to a lockingX request.
4811 ****************************************************************************/
4812
4813 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4814 {
4815         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4816         unsigned char locktype = CVAL(inbuf,smb_vwv3);
4817         unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4818         uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4819         uint16 num_locks = SVAL(inbuf,smb_vwv7);
4820         SMB_BIG_UINT count = 0, offset = 0;
4821         uint16 lock_pid;
4822         int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4823         int i;
4824         char *data;
4825         BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4826         BOOL err;
4827         BOOL my_lock_ctx = False;
4828         NTSTATUS status;
4829
4830         START_PROFILE(SMBlockingX);
4831         
4832         CHECK_FSP(fsp,conn);
4833         
4834         data = smb_buf(inbuf);
4835
4836         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
4837                 /* we don't support these - and CANCEL_LOCK makes w2k
4838                    and XP reboot so I don't really want to be
4839                    compatible! (tridge) */
4840                 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4841         }
4842         
4843         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
4844                 /* Need to make this like a cancel.... JRA. */
4845                 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4846         }
4847         
4848         /* Check if this is an oplock break on a file
4849            we have granted an oplock on.
4850         */
4851         if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4852                 /* Client can insist on breaking to none. */
4853                 BOOL break_to_none = (oplocklevel == 0);
4854                 
4855                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4856                          (unsigned int)oplocklevel, fsp->fnum ));
4857
4858                 /*
4859                  * Make sure we have granted an exclusive or batch oplock on this file.
4860                  */
4861                 
4862                 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4863                         DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4864 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4865
4866                         /* if this is a pure oplock break request then don't send a reply */
4867                         if (num_locks == 0 && num_ulocks == 0) {
4868                                 END_PROFILE(SMBlockingX);
4869                                 return -1;
4870                         } else {
4871                                 END_PROFILE(SMBlockingX);
4872                                 return ERROR_DOS(ERRDOS,ERRlock);
4873                         }
4874                 }
4875
4876                 if (remove_oplock(fsp, break_to_none) == False) {
4877                         DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4878                                  fsp->fsp_name ));
4879                 }
4880                 
4881                 /* if this is a pure oplock break request then don't send a reply */
4882                 if (num_locks == 0 && num_ulocks == 0) {
4883                         /* Sanity check - ensure a pure oplock break is not a
4884                            chained request. */
4885                         if(CVAL(inbuf,smb_vwv0) != 0xff)
4886                                 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4887                                          (unsigned int)CVAL(inbuf,smb_vwv0) ));
4888                         END_PROFILE(SMBlockingX);
4889                         return -1;
4890                 }
4891         }
4892
4893         /*
4894          * We do this check *after* we have checked this is not a oplock break
4895          * response message. JRA.
4896          */
4897         
4898         release_level_2_oplocks_on_change(fsp);
4899         
4900         /* Data now points at the beginning of the list
4901            of smb_unlkrng structs */
4902         for(i = 0; i < (int)num_ulocks; i++) {
4903                 lock_pid = get_lock_pid( data, i, large_file_format);
4904                 count = get_lock_count( data, i, large_file_format);
4905                 offset = get_lock_offset( data, i, large_file_format, &err);
4906                 
4907                 /*
4908                  * There is no error code marked "stupid client bug".... :-).
4909                  */
4910                 if(err) {
4911                         END_PROFILE(SMBlockingX);
4912                         return ERROR_DOS(ERRDOS,ERRnoaccess);
4913                 }
4914
4915                 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4916                           (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4917                 
4918                 status = do_unlock(fsp,conn,lock_pid,count,offset);
4919                 if (NT_STATUS_V(status)) {
4920                         END_PROFILE(SMBlockingX);
4921                         return ERROR_NT(status);
4922                 }
4923         }
4924
4925         /* Setup the timeout in seconds. */
4926
4927         lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4928         
4929         /* Now do any requested locks */
4930         data += ((large_file_format ? 20 : 10)*num_ulocks);
4931         
4932         /* Data now points at the beginning of the list
4933            of smb_lkrng structs */
4934         
4935         for(i = 0; i < (int)num_locks; i++) {
4936                 lock_pid = get_lock_pid( data, i, large_file_format);
4937                 count = get_lock_count( data, i, large_file_format);
4938                 offset = get_lock_offset( data, i, large_file_format, &err);
4939                 
4940                 /*
4941                  * There is no error code marked "stupid client bug".... :-).
4942                  */
4943                 if(err) {
4944                         END_PROFILE(SMBlockingX);
4945                         return ERROR_DOS(ERRDOS,ERRnoaccess);
4946                 }
4947                 
4948                 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4949                         (double)offset, (double)count, (unsigned int)lock_pid,
4950                         fsp->fsp_name, (int)lock_timeout ));
4951                 
4952                 status = do_lock_spin(fsp,conn,lock_pid, count,offset, 
4953                                  ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4954                 if (NT_STATUS_V(status)) {
4955                         /*
4956                          * Interesting fact found by IFSTEST /t LockOverlappedTest...
4957                          * Even if it's our own lock context, we need to wait here as
4958                          * there may be an unlock on the way.
4959                          * So I removed a "&& !my_lock_ctx" from the following
4960                          * if statement. JRA.
4961                          */
4962                         if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4963                                 /*
4964                                  * A blocking lock was requested. Package up
4965                                  * this smb into a queued request and push it
4966                                  * onto the blocking lock queue.
4967                                  */
4968                                 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4969                                         END_PROFILE(SMBlockingX);
4970                                         return -1;
4971                                 }
4972                         }
4973                         break;
4974                 }
4975         }
4976         
4977         /* If any of the above locks failed, then we must unlock
4978            all of the previous locks (X/Open spec). */
4979         if (i != num_locks && num_locks != 0) {
4980                 /*
4981                  * Ensure we don't do a remove on the lock that just failed,
4982                  * as under POSIX rules, if we have a lock already there, we
4983                  * will delete it (and we shouldn't) .....
4984                  */
4985                 for(i--; i >= 0; i--) {
4986                         lock_pid = get_lock_pid( data, i, large_file_format);
4987                         count = get_lock_count( data, i, large_file_format);
4988                         offset = get_lock_offset( data, i, large_file_format, &err);
4989                         
4990                         /*
4991                          * There is no error code marked "stupid client bug".... :-).
4992                          */
4993                         if(err) {
4994                                 END_PROFILE(SMBlockingX);
4995                                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4996                         }
4997                         
4998                         do_unlock(fsp,conn,lock_pid,count,offset);
4999                 }
5000                 END_PROFILE(SMBlockingX);
5001                 return ERROR_NT(status);
5002         }
5003
5004         set_message(outbuf,2,0,True);
5005         
5006         DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5007                     fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
5008         
5009         END_PROFILE(SMBlockingX);
5010         return chain_reply(inbuf,outbuf,length,bufsize);
5011 }
5012
5013 #undef DBGC_CLASS
5014 #define DBGC_CLASS DBGC_ALL
5015
5016 /****************************************************************************
5017  Reply to a SMBreadbmpx (read block multiplex) request.
5018 ****************************************************************************/
5019
5020 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5021 {
5022         ssize_t nread = -1;
5023         ssize_t total_read;
5024         char *data;
5025         SMB_OFF_T startpos;
5026         int outsize;
5027         size_t maxcount;
5028         int max_per_packet;
5029         size_t tcount;
5030         int pad;
5031         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5032         START_PROFILE(SMBreadBmpx);
5033
5034         /* this function doesn't seem to work - disable by default */
5035         if (!lp_readbmpx()) {
5036                 END_PROFILE(SMBreadBmpx);
5037                 return ERROR_DOS(ERRSRV,ERRuseSTD);
5038         }
5039
5040         outsize = set_message(outbuf,8,0,True);
5041
5042         CHECK_FSP(fsp,conn);
5043         CHECK_READ(fsp);
5044
5045         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5046         maxcount = SVAL(inbuf,smb_vwv3);
5047
5048         data = smb_buf(outbuf);
5049         pad = ((long)data)%4;
5050         if (pad)
5051                 pad = 4 - pad;
5052         data += pad;
5053
5054         max_per_packet = bufsize-(outsize+pad);
5055         tcount = maxcount;
5056         total_read = 0;
5057
5058         if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5059                 END_PROFILE(SMBreadBmpx);
5060                 return ERROR_DOS(ERRDOS,ERRlock);
5061         }
5062
5063         do {
5064                 size_t N = MIN(max_per_packet,tcount-total_read);
5065   
5066                 nread = read_file(fsp,data,startpos,N);
5067
5068                 if (nread <= 0)
5069                         nread = 0;
5070
5071                 if (nread < (ssize_t)N)
5072                         tcount = total_read + nread;
5073
5074                 set_message(outbuf,8,nread,False);
5075                 SIVAL(outbuf,smb_vwv0,startpos);
5076                 SSVAL(outbuf,smb_vwv2,tcount);
5077                 SSVAL(outbuf,smb_vwv6,nread);
5078                 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5079
5080                 if (!send_smb(smbd_server_fd(),outbuf))
5081                         exit_server("reply_readbmpx: send_smb failed.");
5082
5083                 total_read += nread;
5084                 startpos += nread;
5085         } while (total_read < (ssize_t)tcount);
5086
5087         END_PROFILE(SMBreadBmpx);
5088         return(-1);
5089 }
5090
5091 /****************************************************************************
5092  Reply to a SMBsetattrE.
5093 ****************************************************************************/
5094
5095 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5096 {
5097         struct utimbuf unix_times;
5098         int outsize = 0;
5099         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5100         START_PROFILE(SMBsetattrE);
5101
5102         outsize = set_message(outbuf,0,0,True);
5103
5104         if(!fsp || (fsp->conn != conn)) {
5105                 END_PROFILE(SMBgetattrE);
5106                 return ERROR_DOS(ERRDOS,ERRbadfid);
5107         }
5108
5109         /*
5110          * Convert the DOS times into unix times. Ignore create
5111          * time as UNIX can't set this.
5112          */
5113
5114         unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
5115         unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
5116   
5117         /* 
5118          * Patch from Ray Frush <frush@engr.colostate.edu>
5119          * Sometimes times are sent as zero - ignore them.
5120          */
5121
5122         if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5123                 /* Ignore request */
5124                 if( DEBUGLVL( 3 ) ) {
5125                         dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5126                         dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5127                 }
5128                 END_PROFILE(SMBsetattrE);
5129                 return(outsize);
5130         } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5131                 /* set modify time = to access time if modify time was unset */
5132                 unix_times.modtime = unix_times.actime;
5133         }
5134
5135         /* Set the date on this file */
5136         /* Should we set pending modtime here ? JRA */
5137         if(file_utime(conn, fsp->fsp_name, &unix_times)) {
5138                 END_PROFILE(SMBsetattrE);
5139                 return ERROR_DOS(ERRDOS,ERRnoaccess);
5140         }
5141   
5142         DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
5143                 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
5144
5145         END_PROFILE(SMBsetattrE);
5146         return(outsize);
5147 }
5148
5149
5150 /* Back from the dead for OS/2..... JRA. */
5151
5152 /****************************************************************************
5153  Reply to a SMBwritebmpx (write block multiplex primary) request.
5154 ****************************************************************************/
5155
5156 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5157 {
5158         size_t numtowrite;
5159         ssize_t nwritten = -1;
5160         int outsize = 0;
5161         SMB_OFF_T startpos;
5162         size_t tcount;
5163         BOOL write_through;
5164         int smb_doff;
5165         char *data;
5166         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5167         START_PROFILE(SMBwriteBmpx);
5168
5169         CHECK_FSP(fsp,conn);
5170         CHECK_WRITE(fsp);
5171         if (HAS_CACHED_ERROR(fsp)) {
5172                 return(CACHED_ERROR(fsp));
5173         }
5174
5175         tcount = SVAL(inbuf,smb_vwv1);
5176         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
5177         write_through = BITSETW(inbuf+smb_vwv7,0);
5178         numtowrite = SVAL(inbuf,smb_vwv10);
5179         smb_doff = SVAL(inbuf,smb_vwv11);
5180
5181         data = smb_base(inbuf) + smb_doff;
5182
5183         /* If this fails we need to send an SMBwriteC response,
5184                 not an SMBwritebmpx - set this up now so we don't forget */
5185         SCVAL(outbuf,smb_com,SMBwritec);
5186
5187         if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
5188                 END_PROFILE(SMBwriteBmpx);
5189                 return(ERROR_DOS(ERRDOS,ERRlock));
5190         }
5191
5192         nwritten = write_file(fsp,data,startpos,numtowrite);
5193
5194         if(lp_syncalways(SNUM(conn)) || write_through)
5195                 sync_file(conn,fsp);
5196   
5197         if(nwritten < (ssize_t)numtowrite) {
5198                 END_PROFILE(SMBwriteBmpx);
5199                 return(UNIXERROR(ERRHRD,ERRdiskfull));
5200         }
5201
5202         /* If the maximum to be written to this file
5203                 is greater than what we just wrote then set
5204                 up a secondary struct to be attached to this
5205                 fd, we will use this to cache error messages etc. */
5206
5207         if((ssize_t)tcount > nwritten) {
5208                 write_bmpx_struct *wbms;
5209                 if(fsp->wbmpx_ptr != NULL)
5210                         wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5211                 else
5212                         wbms = SMB_MALLOC_P(write_bmpx_struct);
5213                 if(!wbms) {
5214                         DEBUG(0,("Out of memory in reply_readmpx\n"));
5215                         END_PROFILE(SMBwriteBmpx);
5216                         return(ERROR_DOS(ERRSRV,ERRnoresource));
5217                 }
5218                 wbms->wr_mode = write_through;
5219                 wbms->wr_discard = False; /* No errors yet */
5220                 wbms->wr_total_written = nwritten;
5221                 wbms->wr_errclass = 0;
5222                 wbms->wr_error = 0;
5223                 fsp->wbmpx_ptr = wbms;
5224         }
5225
5226         /* We are returning successfully, set the message type back to
5227                 SMBwritebmpx */
5228         SCVAL(outbuf,smb_com,SMBwriteBmpx);
5229   
5230         outsize = set_message(outbuf,1,0,True);
5231   
5232         SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5233   
5234         DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5235                         fsp->fnum, (int)numtowrite, (int)nwritten ) );
5236
5237         if (write_through && tcount==nwritten) {
5238                 /* We need to send both a primary and a secondary response */
5239                 smb_setlen(outbuf,outsize - 4);
5240                 if (!send_smb(smbd_server_fd(),outbuf))
5241                         exit_server("reply_writebmpx: send_smb failed.");
5242
5243                 /* Now the secondary */
5244                 outsize = set_message(outbuf,1,0,True);
5245                 SCVAL(outbuf,smb_com,SMBwritec);
5246                 SSVAL(outbuf,smb_vwv0,nwritten);
5247         }
5248
5249         END_PROFILE(SMBwriteBmpx);
5250         return(outsize);
5251 }
5252
5253 /****************************************************************************
5254  Reply to a SMBwritebs (write block multiplex secondary) request.
5255 ****************************************************************************/
5256
5257 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5258 {
5259         size_t numtowrite;
5260         ssize_t nwritten = -1;
5261         int outsize = 0;
5262         SMB_OFF_T startpos;
5263         size_t tcount;
5264         BOOL write_through;
5265         int smb_doff;
5266         char *data;
5267         write_bmpx_struct *wbms;
5268         BOOL send_response = False; 
5269         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5270         START_PROFILE(SMBwriteBs);
5271
5272         CHECK_FSP(fsp,conn);
5273         CHECK_WRITE(fsp);
5274
5275         tcount = SVAL(inbuf,smb_vwv1);
5276         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5277         numtowrite = SVAL(inbuf,smb_vwv6);
5278         smb_doff = SVAL(inbuf,smb_vwv7);
5279
5280         data = smb_base(inbuf) + smb_doff;
5281
5282         /* We need to send an SMBwriteC response, not an SMBwritebs */
5283         SCVAL(outbuf,smb_com,SMBwritec);
5284
5285         /* This fd should have an auxiliary struct attached,
5286                 check that it does */
5287         wbms = fsp->wbmpx_ptr;
5288         if(!wbms) {
5289                 END_PROFILE(SMBwriteBs);
5290                 return(-1);
5291         }
5292
5293         /* If write through is set we can return errors, else we must cache them */
5294         write_through = wbms->wr_mode;
5295
5296         /* Check for an earlier error */
5297         if(wbms->wr_discard) {
5298                 END_PROFILE(SMBwriteBs);
5299                 return -1; /* Just discard the packet */
5300         }
5301
5302         nwritten = write_file(fsp,data,startpos,numtowrite);
5303
5304         if(lp_syncalways(SNUM(conn)) || write_through)
5305                 sync_file(conn,fsp);
5306   
5307         if (nwritten < (ssize_t)numtowrite) {
5308                 if(write_through) {
5309                         /* We are returning an error - we can delete the aux struct */
5310                         if (wbms)
5311                                 free((char *)wbms);
5312                         fsp->wbmpx_ptr = NULL;
5313                         END_PROFILE(SMBwriteBs);
5314                         return(ERROR_DOS(ERRHRD,ERRdiskfull));
5315                 }
5316                 wbms->wr_errclass = ERRHRD;
5317                 wbms->wr_error = ERRdiskfull;
5318                 wbms->wr_status = NT_STATUS_DISK_FULL;
5319                 wbms->wr_discard = True;
5320                 END_PROFILE(SMBwriteBs);
5321                 return -1;
5322         }
5323
5324         /* Increment the total written, if this matches tcount
5325                 we can discard the auxiliary struct (hurrah !) and return a writeC */
5326         wbms->wr_total_written += nwritten;
5327         if(wbms->wr_total_written >= tcount) {
5328                 if (write_through) {
5329                         outsize = set_message(outbuf,1,0,True);
5330                         SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);    
5331                         send_response = True;
5332                 }
5333
5334                 free((char *)wbms);
5335                 fsp->wbmpx_ptr = NULL;
5336         }
5337
5338         if(send_response) {
5339                 END_PROFILE(SMBwriteBs);
5340                 return(outsize);
5341         }
5342
5343         END_PROFILE(SMBwriteBs);
5344         return(-1);
5345 }
5346
5347 /****************************************************************************
5348  Reply to a SMBgetattrE.
5349 ****************************************************************************/
5350
5351 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5352 {
5353         SMB_STRUCT_STAT sbuf;
5354         int outsize = 0;
5355         int mode;
5356         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5357         START_PROFILE(SMBgetattrE);
5358
5359         outsize = set_message(outbuf,11,0,True);
5360
5361         if(!fsp || (fsp->conn != conn)) {
5362                 END_PROFILE(SMBgetattrE);
5363                 return ERROR_DOS(ERRDOS,ERRbadfid);
5364         }
5365
5366         /* Do an fstat on this file */
5367         if(fsp_stat(fsp, &sbuf)) {
5368                 END_PROFILE(SMBgetattrE);
5369                 return(UNIXERROR(ERRDOS,ERRnoaccess));
5370         }
5371   
5372         mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5373   
5374         /*
5375          * Convert the times into dos times. Set create
5376          * date to be last modify date as UNIX doesn't save
5377          * this.
5378          */
5379
5380         put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5381         put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5382         /* Should we check pending modtime here ? JRA */
5383         put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5384
5385         if (mode & aDIR) {
5386                 SIVAL(outbuf,smb_vwv6,0);
5387                 SIVAL(outbuf,smb_vwv8,0);
5388         } else {
5389                 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
5390                 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5391                 SIVAL(outbuf,smb_vwv8,allocation_size);
5392         }
5393         SSVAL(outbuf,smb_vwv10, mode);
5394   
5395         DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5396   
5397         END_PROFILE(SMBgetattrE);
5398         return(outsize);
5399 }