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