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