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