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