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