r7447: Sync up a little between HEAD and 3.0 in preparation for moving
[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 #if 0
2573         /* Enable when the AIO code is moved over. JRA. */
2574         if (schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
2575                 END_PROFILE(SMBreadX);
2576                 return -1;
2577         }
2578 #endif
2579
2580         nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2581         if (nread != -1)
2582                 nread = chain_reply(inbuf,outbuf,length,bufsize);
2583
2584         END_PROFILE(SMBreadX);
2585         return nread;
2586 }
2587
2588 /****************************************************************************
2589  Reply to a writebraw (core+ or LANMAN1.0 protocol).
2590 ****************************************************************************/
2591
2592 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2593 {
2594         ssize_t nwritten=0;
2595         ssize_t total_written=0;
2596         size_t numtowrite=0;
2597         size_t tcount;
2598         SMB_OFF_T startpos;
2599         char *data=NULL;
2600         BOOL write_through;
2601         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2602         int outsize = 0;
2603         START_PROFILE(SMBwritebraw);
2604
2605         if (srv_is_signing_active()) {
2606                 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2607         }
2608
2609         CHECK_FSP(fsp,conn);
2610         CHECK_WRITE(fsp);
2611   
2612         tcount = IVAL(inbuf,smb_vwv1);
2613         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2614         write_through = BITSETW(inbuf+smb_vwv7,0);
2615
2616         /* We have to deal with slightly different formats depending
2617                 on whether we are using the core+ or lanman1.0 protocol */
2618
2619         if(Protocol <= PROTOCOL_COREPLUS) {
2620                 numtowrite = SVAL(smb_buf(inbuf),-2);
2621                 data = smb_buf(inbuf);
2622         } else {
2623                 numtowrite = SVAL(inbuf,smb_vwv10);
2624                 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2625         }
2626
2627         /* force the error type */
2628         SCVAL(inbuf,smb_com,SMBwritec);
2629         SCVAL(outbuf,smb_com,SMBwritec);
2630
2631         if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2632                 END_PROFILE(SMBwritebraw);
2633                 return(ERROR_DOS(ERRDOS,ERRlock));
2634         }
2635
2636         if (numtowrite>0)
2637                 nwritten = write_file(fsp,data,startpos,numtowrite);
2638   
2639         DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2640                 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2641
2642         if (nwritten < (ssize_t)numtowrite)  {
2643                 END_PROFILE(SMBwritebraw);
2644                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2645         }
2646
2647         total_written = nwritten;
2648
2649         /* Return a message to the redirector to tell it to send more bytes */
2650         SCVAL(outbuf,smb_com,SMBwritebraw);
2651         SSVALS(outbuf,smb_vwv0,-1);
2652         outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2653         show_msg(outbuf);
2654         if (!send_smb(smbd_server_fd(),outbuf))
2655                 exit_server("reply_writebraw: send_smb failed.");
2656   
2657         /* Now read the raw data into the buffer and write it */
2658         if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2659                 exit_server("secondary writebraw failed");
2660         }
2661   
2662         /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2663         numtowrite = smb_len(inbuf);
2664
2665         /* Set up outbuf to return the correct return */
2666         outsize = set_message(outbuf,1,0,True);
2667         SCVAL(outbuf,smb_com,SMBwritec);
2668         SSVAL(outbuf,smb_vwv0,total_written);
2669
2670         if (numtowrite != 0) {
2671
2672                 if (numtowrite > BUFFER_SIZE) {
2673                         DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2674                                 (unsigned int)numtowrite ));
2675                         exit_server("secondary writebraw failed");
2676                 }
2677
2678                 if (tcount > nwritten+numtowrite) {
2679                         DEBUG(3,("Client overestimated the write %d %d %d\n",
2680                                 (int)tcount,(int)nwritten,(int)numtowrite));
2681                 }
2682
2683                 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2684                         DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2685                                 strerror(errno) ));
2686                         exit_server("secondary writebraw failed");
2687                 }
2688
2689                 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2690
2691                 if (nwritten < (ssize_t)numtowrite) {
2692                         SCVAL(outbuf,smb_rcls,ERRHRD);
2693                         SSVAL(outbuf,smb_err,ERRdiskfull);      
2694                 }
2695
2696                 if (nwritten > 0)
2697                         total_written += nwritten;
2698         }
2699  
2700         if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2701                 sync_file(conn,fsp);
2702
2703         DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2704                 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2705
2706         /* we won't return a status if write through is not selected - this follows what WfWg does */
2707         END_PROFILE(SMBwritebraw);
2708         if (!write_through && total_written==tcount) {
2709
2710 #if RABBIT_PELLET_FIX
2711                 /*
2712                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2713                  * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2714                  */
2715                 if (!send_keepalive(smbd_server_fd()))
2716                         exit_server("reply_writebraw: send of keepalive failed");
2717 #endif
2718                 return(-1);
2719         }
2720
2721         return(outsize);
2722 }
2723
2724 #undef DBGC_CLASS
2725 #define DBGC_CLASS DBGC_LOCKING
2726
2727 /****************************************************************************
2728  Reply to a writeunlock (core+).
2729 ****************************************************************************/
2730
2731 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, 
2732                       int size, int dum_buffsize)
2733 {
2734         ssize_t nwritten = -1;
2735         size_t numtowrite;
2736         SMB_OFF_T startpos;
2737         char *data;
2738         NTSTATUS status = NT_STATUS_OK;
2739         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2740         int outsize = 0;
2741         START_PROFILE(SMBwriteunlock);
2742         
2743         CHECK_FSP(fsp,conn);
2744         CHECK_WRITE(fsp);
2745
2746         numtowrite = SVAL(inbuf,smb_vwv1);
2747         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2748         data = smb_buf(inbuf) + 3;
2749   
2750         if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2751                 END_PROFILE(SMBwriteunlock);
2752                 return ERROR_DOS(ERRDOS,ERRlock);
2753         }
2754
2755         /* The special X/Open SMB protocol handling of
2756            zero length writes is *NOT* done for
2757            this call */
2758         if(numtowrite == 0)
2759                 nwritten = 0;
2760         else
2761                 nwritten = write_file(fsp,data,startpos,numtowrite);
2762   
2763         if (lp_syncalways(SNUM(conn)))
2764                 sync_file(conn,fsp);
2765
2766         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2767                 END_PROFILE(SMBwriteunlock);
2768                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2769         }
2770
2771         if (numtowrite) {
2772                 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite, 
2773                                    (SMB_BIG_UINT)startpos);
2774                 if (NT_STATUS_V(status)) {
2775                         END_PROFILE(SMBwriteunlock);
2776                         return ERROR_NT(status);
2777                 }
2778         }
2779         
2780         outsize = set_message(outbuf,1,0,True);
2781         
2782         SSVAL(outbuf,smb_vwv0,nwritten);
2783         
2784         DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2785                  fsp->fnum, (int)numtowrite, (int)nwritten));
2786         
2787         END_PROFILE(SMBwriteunlock);
2788         return outsize;
2789 }
2790
2791 #undef DBGC_CLASS
2792 #define DBGC_CLASS DBGC_ALL
2793
2794 /****************************************************************************
2795  Reply to a write.
2796 ****************************************************************************/
2797
2798 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2799 {
2800         size_t numtowrite;
2801         ssize_t nwritten = -1;
2802         SMB_OFF_T startpos;
2803         char *data;
2804         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2805         int outsize = 0;
2806         START_PROFILE(SMBwrite);
2807
2808         /* If it's an IPC, pass off the pipe handler. */
2809         if (IS_IPC(conn)) {
2810                 END_PROFILE(SMBwrite);
2811                 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2812         }
2813
2814         CHECK_FSP(fsp,conn);
2815         CHECK_WRITE(fsp);
2816
2817         numtowrite = SVAL(inbuf,smb_vwv1);
2818         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2819         data = smb_buf(inbuf) + 3;
2820   
2821         if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2822                 END_PROFILE(SMBwrite);
2823                 return ERROR_DOS(ERRDOS,ERRlock);
2824         }
2825
2826         /*
2827          * X/Open SMB protocol says that if smb_vwv1 is
2828          * zero then the file size should be extended or
2829          * truncated to the size given in smb_vwv[2-3].
2830          */
2831
2832         if(numtowrite == 0) {
2833                 /*
2834                  * This is actually an allocate call, and set EOF. JRA.
2835                  */
2836                 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2837                 if (nwritten < 0) {
2838                         END_PROFILE(SMBwrite);
2839                         return ERROR_NT(NT_STATUS_DISK_FULL);
2840                 }
2841                 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2842                 if (nwritten < 0) {
2843                         END_PROFILE(SMBwrite);
2844                         return ERROR_NT(NT_STATUS_DISK_FULL);
2845                 }
2846         } else
2847                 nwritten = write_file(fsp,data,startpos,numtowrite);
2848   
2849         if (lp_syncalways(SNUM(conn)))
2850                 sync_file(conn,fsp);
2851
2852         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2853                 END_PROFILE(SMBwrite);
2854                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2855         }
2856
2857         outsize = set_message(outbuf,1,0,True);
2858   
2859         SSVAL(outbuf,smb_vwv0,nwritten);
2860
2861         if (nwritten < (ssize_t)numtowrite) {
2862                 SCVAL(outbuf,smb_rcls,ERRHRD);
2863                 SSVAL(outbuf,smb_err,ERRdiskfull);      
2864         }
2865   
2866         DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2867
2868         END_PROFILE(SMBwrite);
2869         return(outsize);
2870 }
2871
2872 /****************************************************************************
2873  Reply to a write and X.
2874 ****************************************************************************/
2875
2876 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2877 {
2878         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2879         SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2880         size_t numtowrite = SVAL(inbuf,smb_vwv10);
2881         BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2882         ssize_t nwritten = -1;
2883         unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2884         unsigned int smblen = smb_len(inbuf);
2885         char *data;
2886         BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2887         START_PROFILE(SMBwriteX);
2888
2889         /* If it's an IPC, pass off the pipe handler. */
2890         if (IS_IPC(conn)) {
2891                 END_PROFILE(SMBwriteX);
2892                 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2893         }
2894
2895         CHECK_FSP(fsp,conn);
2896         CHECK_WRITE(fsp);
2897
2898         set_message(outbuf,6,0,True);
2899   
2900         /* Deal with possible LARGE_WRITEX */
2901         if (large_writeX) {
2902                 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2903         }
2904
2905         if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2906                 END_PROFILE(SMBwriteX);
2907                 return ERROR_DOS(ERRDOS,ERRbadmem);
2908         }
2909
2910         data = smb_base(inbuf) + smb_doff;
2911
2912         if(CVAL(inbuf,smb_wct) == 14) {
2913 #ifdef LARGE_SMB_OFF_T
2914                 /*
2915                  * This is a large offset (64 bit) write.
2916                  */
2917                 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2918
2919 #else /* !LARGE_SMB_OFF_T */
2920
2921                 /*
2922                  * Ensure we haven't been sent a >32 bit offset.
2923                  */
2924
2925                 if(IVAL(inbuf,smb_vwv12) != 0) {
2926                         DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2927 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2928                         END_PROFILE(SMBwriteX);
2929                         return ERROR_DOS(ERRDOS,ERRbadaccess);
2930                 }
2931
2932 #endif /* LARGE_SMB_OFF_T */
2933         }
2934
2935         if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2936                 END_PROFILE(SMBwriteX);
2937                 return ERROR_DOS(ERRDOS,ERRlock);
2938         }
2939
2940         /* X/Open SMB protocol says that, unlike SMBwrite
2941         if the length is zero then NO truncation is
2942         done, just a write of zero. To truncate a file,
2943         use SMBwrite. */
2944
2945         if(numtowrite == 0) {
2946                 nwritten = 0;
2947         } else {
2948
2949 #if 0
2950                 /* Enable when AIO code is moved over. JRA. */
2951
2952                 if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize,
2953                                         fsp,data,startpos,numtowrite)) {
2954                         END_PROFILE(SMBwriteX);
2955                         return -1;
2956                 }
2957 #endif
2958
2959                 nwritten = write_file(fsp,data,startpos,numtowrite);
2960         }
2961   
2962         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2963                 END_PROFILE(SMBwriteX);
2964                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2965         }
2966
2967         SSVAL(outbuf,smb_vwv2,nwritten);
2968         if (large_writeX)
2969                 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2970
2971         if (nwritten < (ssize_t)numtowrite) {
2972                 SCVAL(outbuf,smb_rcls,ERRHRD);
2973                 SSVAL(outbuf,smb_err,ERRdiskfull);      
2974         }
2975
2976         DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2977                 fsp->fnum, (int)numtowrite, (int)nwritten));
2978
2979         if (lp_syncalways(SNUM(conn)) || write_through)
2980                 sync_file(conn,fsp);
2981
2982         END_PROFILE(SMBwriteX);
2983         return chain_reply(inbuf,outbuf,length,bufsize);
2984 }
2985
2986 /****************************************************************************
2987  Reply to a lseek.
2988 ****************************************************************************/
2989
2990 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2991 {
2992         SMB_OFF_T startpos;
2993         SMB_OFF_T res= -1;
2994         int mode,umode;
2995         int outsize = 0;
2996         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2997         START_PROFILE(SMBlseek);
2998
2999         CHECK_FSP(fsp,conn);
3000
3001         flush_write_cache(fsp, SEEK_FLUSH);
3002
3003         mode = SVAL(inbuf,smb_vwv1) & 3;
3004         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3005         startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
3006
3007         switch (mode) {
3008                 case 0:
3009                         umode = SEEK_SET;
3010                         res = startpos;
3011                         break;
3012                 case 1:
3013                         umode = SEEK_CUR;
3014                         res = fsp->pos + startpos;
3015                         break;
3016                 case 2:
3017                         umode = SEEK_END;
3018                         break;
3019                 default:
3020                         umode = SEEK_SET;
3021                         res = startpos;
3022                         break;
3023         }
3024
3025         if (umode == SEEK_END) {
3026                 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
3027                         if(errno == EINVAL) {
3028                                 SMB_OFF_T current_pos = startpos;
3029                                 SMB_STRUCT_STAT sbuf;
3030
3031                                 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
3032                                         END_PROFILE(SMBlseek);
3033                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3034                                 }
3035
3036                                 current_pos += sbuf.st_size;
3037                                 if(current_pos < 0)
3038                                         res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
3039                         }
3040                 }
3041
3042                 if(res == -1) {
3043                         END_PROFILE(SMBlseek);
3044                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3045                 }
3046         }
3047
3048         fsp->pos = res;
3049   
3050         outsize = set_message(outbuf,2,0,True);
3051         SIVAL(outbuf,smb_vwv0,res);
3052   
3053         DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3054                 fsp->fnum, (double)startpos, (double)res, mode));
3055
3056         END_PROFILE(SMBlseek);
3057         return(outsize);
3058 }
3059
3060 /****************************************************************************
3061  Reply to a flush.
3062 ****************************************************************************/
3063
3064 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3065 {
3066         int outsize = set_message(outbuf,0,0,True);
3067         uint16 fnum = SVAL(inbuf,smb_vwv0);
3068         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3069         START_PROFILE(SMBflush);
3070
3071         if (fnum != 0xFFFF)
3072                 CHECK_FSP(fsp,conn);
3073         
3074         if (!fsp) {
3075                 file_sync_all(conn);
3076         } else {
3077                 sync_file(conn,fsp);
3078         }
3079         
3080         DEBUG(3,("flush\n"));
3081         END_PROFILE(SMBflush);
3082         return(outsize);
3083 }
3084
3085 /****************************************************************************
3086  Reply to a exit.
3087 ****************************************************************************/
3088
3089 int reply_exit(connection_struct *conn, 
3090                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3091 {
3092         int outsize;
3093         START_PROFILE(SMBexit);
3094
3095         file_close_pid(SVAL(inbuf,smb_pid));
3096
3097         outsize = set_message(outbuf,0,0,True);
3098
3099         DEBUG(3,("exit\n"));
3100
3101         END_PROFILE(SMBexit);
3102         return(outsize);
3103 }
3104
3105 /****************************************************************************
3106  Reply to a close - has to deal with closing a directory opened by NT SMB's.
3107 ****************************************************************************/
3108
3109 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
3110                 int dum_buffsize)
3111 {
3112         int outsize = 0;
3113         time_t mtime;
3114         int32 eclass = 0, err = 0;
3115         files_struct *fsp = NULL;
3116         START_PROFILE(SMBclose);
3117
3118         outsize = set_message(outbuf,0,0,True);
3119
3120         /* If it's an IPC, pass off to the pipe handler. */
3121         if (IS_IPC(conn)) {
3122                 END_PROFILE(SMBclose);
3123                 return reply_pipe_close(conn, inbuf,outbuf);
3124         }
3125
3126         fsp = file_fsp(inbuf,smb_vwv0);
3127
3128         /*
3129          * We can only use CHECK_FSP if we know it's not a directory.
3130          */
3131
3132         if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3133                 END_PROFILE(SMBclose);
3134                 return ERROR_DOS(ERRDOS,ERRbadfid);
3135         }
3136
3137         if(fsp->is_directory) {
3138                 /*
3139                  * Special case - close NT SMB directory handle.
3140                  */
3141                 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
3142                 close_file(fsp,True);
3143         } else {
3144                 /*
3145                  * Close ordinary file.
3146                  */
3147                 int close_err;
3148                 pstring file_name;
3149
3150                 /* Save the name for time set in close. */
3151                 pstrcpy( file_name, fsp->fsp_name);
3152
3153                 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3154                          fsp->fd, fsp->fnum,
3155                          conn->num_files_open));
3156  
3157                 /*
3158                  * Take care of any time sent in the close.
3159                  */
3160
3161                 mtime = make_unix_date3(inbuf+smb_vwv1);
3162                 fsp_set_pending_modtime(fsp, mtime);
3163
3164                 /*
3165                  * close_file() returns the unix errno if an error
3166                  * was detected on close - normally this is due to
3167                  * a disk full error. If not then it was probably an I/O error.
3168                  */
3169  
3170                 if((close_err = close_file(fsp,True)) != 0) {
3171                         errno = close_err;
3172                         END_PROFILE(SMBclose);
3173                         return (UNIXERROR(ERRHRD,ERRgeneral));
3174                 }
3175         }  
3176
3177         /* We have a cached error */
3178         if(eclass || err) {
3179                 END_PROFILE(SMBclose);
3180                 return ERROR_DOS(eclass,err);
3181         }
3182
3183         END_PROFILE(SMBclose);
3184         return(outsize);
3185 }
3186
3187 /****************************************************************************
3188  Reply to a writeclose (Core+ protocol).
3189 ****************************************************************************/
3190
3191 int reply_writeclose(connection_struct *conn,
3192                      char *inbuf,char *outbuf, int size, int dum_buffsize)
3193 {
3194         size_t numtowrite;
3195         ssize_t nwritten = -1;
3196         int outsize = 0;
3197         int close_err = 0;
3198         SMB_OFF_T startpos;
3199         char *data;
3200         time_t mtime;
3201         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3202         START_PROFILE(SMBwriteclose);
3203
3204         CHECK_FSP(fsp,conn);
3205         CHECK_WRITE(fsp);
3206
3207         numtowrite = SVAL(inbuf,smb_vwv1);
3208         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3209         mtime = make_unix_date3(inbuf+smb_vwv4);
3210         data = smb_buf(inbuf) + 1;
3211   
3212         if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3213                 END_PROFILE(SMBwriteclose);
3214                 return ERROR_DOS(ERRDOS,ERRlock);
3215         }
3216   
3217         nwritten = write_file(fsp,data,startpos,numtowrite);
3218
3219         set_filetime(conn, fsp->fsp_name,mtime);
3220   
3221         /*
3222          * More insanity. W2K only closes the file if writelen > 0.
3223          * JRA.
3224          */
3225
3226         if (numtowrite) {
3227                 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3228                         fsp->fsp_name ));
3229                 close_err = close_file(fsp,True);
3230         }
3231
3232         DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3233                  fsp->fnum, (int)numtowrite, (int)nwritten,
3234                  conn->num_files_open));
3235   
3236         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3237                 END_PROFILE(SMBwriteclose);
3238                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3239         }
3240  
3241         if(close_err != 0) {
3242                 errno = close_err;
3243                 END_PROFILE(SMBwriteclose);
3244                 return(UNIXERROR(ERRHRD,ERRgeneral));
3245         }
3246  
3247         outsize = set_message(outbuf,1,0,True);
3248   
3249         SSVAL(outbuf,smb_vwv0,nwritten);
3250         END_PROFILE(SMBwriteclose);
3251         return(outsize);
3252 }
3253
3254 #undef DBGC_CLASS
3255 #define DBGC_CLASS DBGC_LOCKING
3256
3257 /****************************************************************************
3258  Reply to a lock.
3259 ****************************************************************************/
3260
3261 int reply_lock(connection_struct *conn,
3262                char *inbuf,char *outbuf, int length, int dum_buffsize)
3263 {
3264         int outsize = set_message(outbuf,0,0,True);
3265         SMB_BIG_UINT count,offset;
3266         NTSTATUS status;
3267         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3268         BOOL my_lock_ctx = False;
3269
3270         START_PROFILE(SMBlock);
3271
3272         CHECK_FSP(fsp,conn);
3273
3274         release_level_2_oplocks_on_change(fsp);
3275
3276         count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3277         offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3278
3279         DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3280                  fsp->fd, fsp->fnum, (double)offset, (double)count));
3281
3282         status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
3283         if (NT_STATUS_V(status)) {
3284 #if 0
3285                 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
3286                 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
3287                         /*
3288                          * A blocking lock was requested. Package up
3289                          * this smb into a queued request and push it
3290                          * onto the blocking lock queue.
3291                          */
3292                         if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
3293                                 END_PROFILE(SMBlock);
3294                                 return -1;
3295                         }
3296                 }
3297 #endif
3298                 END_PROFILE(SMBlock);
3299                 return ERROR_NT(status);
3300         }
3301
3302         END_PROFILE(SMBlock);
3303         return(outsize);
3304 }
3305
3306 /****************************************************************************
3307  Reply to a unlock.
3308 ****************************************************************************/
3309
3310 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, 
3311                  int dum_buffsize)
3312 {
3313         int outsize = set_message(outbuf,0,0,True);
3314         SMB_BIG_UINT count,offset;
3315         NTSTATUS status;
3316         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3317         START_PROFILE(SMBunlock);
3318
3319         CHECK_FSP(fsp,conn);
3320         
3321         count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3322         offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3323         
3324         status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
3325         if (NT_STATUS_V(status)) {
3326                 END_PROFILE(SMBunlock);
3327                 return ERROR_NT(status);
3328         }
3329
3330         DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3331                     fsp->fd, fsp->fnum, (double)offset, (double)count ) );
3332         
3333         END_PROFILE(SMBunlock);
3334         return(outsize);
3335 }
3336
3337 #undef DBGC_CLASS
3338 #define DBGC_CLASS DBGC_ALL
3339
3340 /****************************************************************************
3341  Reply to a tdis.
3342 ****************************************************************************/
3343
3344 int reply_tdis(connection_struct *conn, 
3345                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3346 {
3347         int outsize = set_message(outbuf,0,0,True);
3348         uint16 vuid;
3349         START_PROFILE(SMBtdis);
3350
3351         vuid = SVAL(inbuf,smb_uid);
3352
3353         if (!conn) {
3354                 DEBUG(4,("Invalid connection in tdis\n"));
3355                 END_PROFILE(SMBtdis);
3356                 return ERROR_DOS(ERRSRV,ERRinvnid);
3357         }
3358
3359         conn->used = False;
3360
3361         close_cnum(conn,vuid);
3362   
3363         END_PROFILE(SMBtdis);
3364         return outsize;
3365 }
3366
3367 /****************************************************************************
3368  Reply to a echo.
3369 ****************************************************************************/
3370
3371 int reply_echo(connection_struct *conn,
3372                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3373 {
3374         int smb_reverb = SVAL(inbuf,smb_vwv0);
3375         int seq_num;
3376         unsigned int data_len = smb_buflen(inbuf);
3377         int outsize = set_message(outbuf,1,data_len,True);
3378         START_PROFILE(SMBecho);
3379
3380         if (data_len > BUFFER_SIZE) {
3381                 DEBUG(0,("reply_echo: data_len too large.\n"));
3382                 END_PROFILE(SMBecho);
3383                 return -1;
3384         }
3385
3386         /* copy any incoming data back out */
3387         if (data_len > 0)
3388                 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3389
3390         if (smb_reverb > 100) {
3391                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3392                 smb_reverb = 100;
3393         }
3394
3395         for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3396                 SSVAL(outbuf,smb_vwv0,seq_num);
3397
3398                 smb_setlen(outbuf,outsize - 4);
3399
3400                 show_msg(outbuf);
3401                 if (!send_smb(smbd_server_fd(),outbuf))
3402                         exit_server("reply_echo: send_smb failed.");
3403         }
3404
3405         DEBUG(3,("echo %d times\n", smb_reverb));
3406
3407         smb_echo_count++;
3408
3409         END_PROFILE(SMBecho);
3410         return -1;
3411 }
3412
3413 /****************************************************************************
3414  Reply to a printopen.
3415 ****************************************************************************/
3416
3417 int reply_printopen(connection_struct *conn, 
3418                     char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3419 {
3420         int outsize = 0;
3421         files_struct *fsp;
3422         START_PROFILE(SMBsplopen);
3423         
3424         if (!CAN_PRINT(conn)) {
3425                 END_PROFILE(SMBsplopen);
3426                 return ERROR_DOS(ERRDOS,ERRnoaccess);
3427         }
3428
3429         /* Open for exclusive use, write only. */
3430         fsp = print_fsp_open(conn, NULL);
3431
3432         if (!fsp) {
3433                 END_PROFILE(SMBsplopen);
3434                 return(UNIXERROR(ERRDOS,ERRnoaccess));
3435         }
3436
3437         outsize = set_message(outbuf,1,0,True);
3438         SSVAL(outbuf,smb_vwv0,fsp->fnum);
3439   
3440         DEBUG(3,("openprint fd=%d fnum=%d\n",
3441                  fsp->fd, fsp->fnum));
3442
3443         END_PROFILE(SMBsplopen);
3444         return(outsize);
3445 }
3446
3447 /****************************************************************************
3448  Reply to a printclose.
3449 ****************************************************************************/
3450
3451 int reply_printclose(connection_struct *conn,
3452                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3453 {
3454         int outsize = set_message(outbuf,0,0,True);
3455         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3456         int close_err = 0;
3457         START_PROFILE(SMBsplclose);
3458
3459         CHECK_FSP(fsp,conn);
3460
3461         if (!CAN_PRINT(conn)) {
3462                 END_PROFILE(SMBsplclose);
3463                 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
3464         }
3465   
3466         DEBUG(3,("printclose fd=%d fnum=%d\n",
3467                  fsp->fd,fsp->fnum));
3468   
3469         close_err = close_file(fsp,True);
3470
3471         if(close_err != 0) {
3472                 errno = close_err;
3473                 END_PROFILE(SMBsplclose);
3474                 return(UNIXERROR(ERRHRD,ERRgeneral));
3475         }
3476
3477         END_PROFILE(SMBsplclose);
3478         return(outsize);
3479 }
3480
3481 /****************************************************************************
3482  Reply to a printqueue.
3483 ****************************************************************************/
3484
3485 int reply_printqueue(connection_struct *conn,
3486                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3487 {
3488         int outsize = set_message(outbuf,2,3,True);
3489         int max_count = SVAL(inbuf,smb_vwv0);
3490         int start_index = SVAL(inbuf,smb_vwv1);
3491         START_PROFILE(SMBsplretq);
3492
3493         /* we used to allow the client to get the cnum wrong, but that
3494            is really quite gross and only worked when there was only
3495            one printer - I think we should now only accept it if they
3496            get it right (tridge) */
3497         if (!CAN_PRINT(conn)) {
3498                 END_PROFILE(SMBsplretq);
3499                 return ERROR_DOS(ERRDOS,ERRnoaccess);
3500         }
3501
3502         SSVAL(outbuf,smb_vwv0,0);
3503         SSVAL(outbuf,smb_vwv1,0);
3504         SCVAL(smb_buf(outbuf),0,1);
3505         SSVAL(smb_buf(outbuf),1,0);
3506   
3507         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3508                  start_index, max_count));
3509
3510         {
3511                 print_queue_struct *queue = NULL;
3512                 print_status_struct status;
3513                 char *p = smb_buf(outbuf) + 3;
3514                 int count = print_queue_status(SNUM(conn), &queue, &status);
3515                 int num_to_get = ABS(max_count);
3516                 int first = (max_count>0?start_index:start_index+max_count+1);
3517                 int i;
3518
3519                 if (first >= count)
3520                         num_to_get = 0;
3521                 else
3522                         num_to_get = MIN(num_to_get,count-first);
3523     
3524
3525                 for (i=first;i<first+num_to_get;i++) {
3526                         put_dos_date2(p,0,queue[i].time);
3527                         SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3528                         SSVAL(p,5, queue[i].job);
3529                         SIVAL(p,7,queue[i].size);
3530                         SCVAL(p,11,0);
3531                         srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3532                         p += 28;
3533                 }
3534
3535                 if (count > 0) {
3536                         outsize = set_message(outbuf,2,28*count+3,False); 
3537                         SSVAL(outbuf,smb_vwv0,count);
3538                         SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3539                         SCVAL(smb_buf(outbuf),0,1);
3540                         SSVAL(smb_buf(outbuf),1,28*count);
3541                 }
3542
3543                 SAFE_FREE(queue);
3544           
3545                 DEBUG(3,("%d entries returned in queue\n",count));
3546         }
3547   
3548         END_PROFILE(SMBsplretq);
3549         return(outsize);
3550 }
3551
3552 /****************************************************************************
3553  Reply to a printwrite.
3554 ****************************************************************************/
3555
3556 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3557 {
3558         int numtowrite;
3559         int outsize = set_message(outbuf,0,0,True);
3560         char *data;
3561         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3562
3563         START_PROFILE(SMBsplwr);
3564   
3565         if (!CAN_PRINT(conn)) {
3566                 END_PROFILE(SMBsplwr);
3567                 return ERROR_DOS(ERRDOS,ERRnoaccess);
3568         }
3569
3570         CHECK_FSP(fsp,conn);
3571         CHECK_WRITE(fsp);
3572
3573         numtowrite = SVAL(smb_buf(inbuf),1);
3574         data = smb_buf(inbuf) + 3;
3575   
3576         if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3577                 END_PROFILE(SMBsplwr);
3578                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3579         }
3580
3581         DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3582   
3583         END_PROFILE(SMBsplwr);
3584         return(outsize);
3585 }
3586
3587 /****************************************************************************
3588  The guts of the mkdir command, split out so it may be called by the NT SMB
3589  code. 
3590 ****************************************************************************/
3591
3592 NTSTATUS mkdir_internal(connection_struct *conn, const pstring directory, BOOL bad_path)
3593 {
3594         int ret= -1;
3595         
3596         if(!CAN_WRITE(conn)) {
3597                 DEBUG(5,("mkdir_internal: failing create on read-only share %s\n", lp_servicename(SNUM(conn))));
3598                 errno = EACCES;
3599                 return map_nt_error_from_unix(errno);
3600         }
3601
3602         if (bad_path) {
3603                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3604         }
3605
3606         if (!check_name(directory, conn)) {
3607                 if(errno == ENOENT) {
3608                         if (bad_path) {
3609                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3610                         } else {
3611                                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3612                         }
3613                 }
3614                 return map_nt_error_from_unix(errno);
3615         }
3616
3617         ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
3618         if (ret == -1) {
3619                 if(errno == ENOENT) {
3620                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3621                 }
3622                 return map_nt_error_from_unix(errno);
3623         }
3624         
3625         return NT_STATUS_OK;
3626 }
3627
3628 /****************************************************************************
3629  Reply to a mkdir.
3630 ****************************************************************************/
3631
3632 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3633 {
3634         pstring directory;
3635         int outsize;
3636         NTSTATUS status;
3637         BOOL bad_path = False;
3638         SMB_STRUCT_STAT sbuf;
3639
3640         START_PROFILE(SMBmkdir);
3641  
3642         srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3643         if (!NT_STATUS_IS_OK(status)) {
3644                 END_PROFILE(SMBmkdir);
3645                 return ERROR_NT(status);
3646         }
3647
3648         RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3649
3650         unix_convert(directory,conn,0,&bad_path,&sbuf);
3651
3652         if( is_ntfs_stream_name(directory)) {
3653                 DEBUG(5,("reply_mkdir: failing create on filename %s with colon in name\n", directory));
3654                 END_PROFILE(SMBmkdir);
3655                 return ERROR_FORCE_DOS(ERRDOS, ERRinvalidname);
3656         }
3657
3658         status = mkdir_internal(conn, directory,bad_path);
3659         if (!NT_STATUS_IS_OK(status)) {
3660                 END_PROFILE(SMBmkdir);
3661                 return ERROR_NT(status);
3662         }
3663
3664         if (lp_inherit_owner(SNUM(conn))) {
3665                 /* Ensure we're checking for a symlink here.... */
3666                 /* We don't want to get caught by a symlink racer. */
3667
3668                 if(SMB_VFS_LSTAT(conn,directory, &sbuf) != 0) {
3669                         END_PROFILE(SMBmkdir);
3670                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3671                 }
3672                                                                                                                                                    
3673                 if(!S_ISDIR(sbuf.st_mode)) {
3674                         DEBUG(0,("reply_mkdir: %s is not a directory !\n", directory ));
3675                         END_PROFILE(SMBmkdir);
3676                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3677                 }
3678
3679                 change_owner_to_parent(conn, NULL, directory, &sbuf);
3680         }
3681
3682         outsize = set_message(outbuf,0,0,True);
3683
3684         DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3685
3686         END_PROFILE(SMBmkdir);
3687         return(outsize);
3688 }
3689
3690 /****************************************************************************
3691  Static function used by reply_rmdir to delete an entire directory
3692  tree recursively. Return False on ok, True on fail.
3693 ****************************************************************************/
3694
3695 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3696 {
3697         const char *dname = NULL;
3698         BOOL ret = False;
3699         long offset = 0;
3700         struct smb_Dir *dir_hnd = OpenDir(conn, directory);
3701
3702         if(dir_hnd == NULL)
3703                 return True;
3704
3705         while((dname = ReadDirName(dir_hnd, &offset))) {
3706                 pstring fullname;
3707                 SMB_STRUCT_STAT st;
3708
3709                 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3710                         continue;
3711
3712                 if (!is_visible_file(conn, directory, dname, &st, False))
3713                         continue;
3714
3715                 /* Construct the full name. */
3716                 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3717                         errno = ENOMEM;
3718                         ret = True;
3719                         break;
3720                 }
3721
3722                 pstrcpy(fullname, directory);
3723                 pstrcat(fullname, "/");
3724                 pstrcat(fullname, dname);
3725
3726                 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3727                         ret = True;
3728                         break;
3729                 }
3730
3731                 if(st.st_mode & S_IFDIR) {
3732                         if(recursive_rmdir(conn, fullname)!=0) {
3733                                 ret = True;
3734                                 break;
3735                         }
3736                         if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3737                                 ret = True;
3738                                 break;
3739                         }
3740                 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3741                         ret = True;
3742                         break;
3743                 }
3744         }
3745         CloseDir(dir_hnd);
3746         return ret;
3747 }
3748
3749 /****************************************************************************
3750  The internals of the rmdir code - called elsewhere.
3751 ****************************************************************************/
3752
3753 BOOL rmdir_internals(connection_struct *conn, char *directory)
3754 {
3755         BOOL ok;
3756         SMB_STRUCT_STAT st;
3757
3758         ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3759         if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3760                 /* 
3761                  * Check to see if the only thing in this directory are
3762                  * vetoed files/directories. If so then delete them and
3763                  * retry. If we fail to delete any of them (and we *don't*
3764                  * do a recursive delete) then fail the rmdir.
3765                  */
3766                 BOOL all_veto_files = True;
3767                 const char *dname;
3768                 struct smb_Dir *dir_hnd = OpenDir(conn, directory);
3769
3770                 if(dir_hnd != NULL) {
3771                         long dirpos = TellDir(dir_hnd);
3772                         while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3773                                 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3774                                         continue;
3775                                 if (!is_visible_file(conn, directory, dname, &st, False))
3776                                         continue;
3777                                 if(!IS_VETO_PATH(conn, dname)) {
3778                                         all_veto_files = False;
3779                                         break;
3780                                 }
3781                         }
3782
3783                         if(all_veto_files) {
3784                                 SeekDir(dir_hnd,dirpos);
3785                                 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3786                                         pstring fullname;
3787
3788                                         if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3789                                                 continue;
3790                                         if (!is_visible_file(conn, directory, dname, &st, False))
3791                                                 continue;
3792
3793                                         /* Construct the full name. */
3794                                         if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3795                                                 errno = ENOMEM;
3796                                                 break;
3797                                         }
3798
3799                                         pstrcpy(fullname, directory);
3800                                         pstrcat(fullname, "/");
3801                                         pstrcat(fullname, dname);
3802                      
3803                                         if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3804                                                 break;
3805                                         if(st.st_mode & S_IFDIR) {
3806                                                 if(lp_recursive_veto_delete(SNUM(conn))) {
3807                                                         if(recursive_rmdir(conn, fullname) != 0)
3808                                                                 break;
3809                                                 }
3810                                                 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3811                                                         break;
3812                                         } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3813                                                 break;
3814                                 }
3815                                 CloseDir(dir_hnd);
3816                                 /* Retry the rmdir */
3817                                 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3818                         } else {
3819                                 CloseDir(dir_hnd);
3820                         }
3821                 } else {
3822                         errno = ENOTEMPTY;
3823                 }
3824         }
3825
3826         if (!ok)
3827                 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3828
3829         return ok;
3830 }
3831
3832 /****************************************************************************
3833  Reply to a rmdir.
3834 ****************************************************************************/
3835
3836 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3837 {
3838         pstring directory;
3839         int outsize = 0;
3840         BOOL ok = False;
3841         BOOL bad_path = False;
3842         SMB_STRUCT_STAT sbuf;
3843         NTSTATUS status;
3844         START_PROFILE(SMBrmdir);
3845
3846         srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3847         if (!NT_STATUS_IS_OK(status)) {
3848                 END_PROFILE(SMBrmdir);
3849                 return ERROR_NT(status);
3850         }
3851
3852         RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3853
3854         unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3855         if (bad_path) {
3856                 END_PROFILE(SMBrmdir);
3857                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3858         }
3859   
3860         if (check_name(directory,conn)) {
3861                 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3862                 ok = rmdir_internals(conn, directory);
3863         }
3864   
3865         if (!ok) {
3866                 END_PROFILE(SMBrmdir);
3867                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3868         }
3869  
3870         outsize = set_message(outbuf,0,0,True);
3871   
3872         DEBUG( 3, ( "rmdir %s\n", directory ) );
3873   
3874         END_PROFILE(SMBrmdir);
3875         return(outsize);
3876 }
3877
3878 /*******************************************************************
3879  Resolve wildcards in a filename rename.
3880  Note that name is in UNIX charset and thus potentially can be more
3881  than fstring buffer (255 bytes) especially in default UTF-8 case.
3882  Therefore, we use pstring inside and all calls should ensure that
3883  name2 is at least pstring-long (they do already)
3884 ********************************************************************/
3885
3886 static BOOL resolve_wildcards(const char *name1, char *name2)
3887 {
3888         pstring root1,root2;
3889         pstring ext1,ext2;
3890         char *p,*p2, *pname1, *pname2;
3891         int available_space, actual_space;
3892         
3893
3894         pname1 = strrchr_m(name1,'/');
3895         pname2 = strrchr_m(name2,'/');
3896
3897         if (!pname1 || !pname2)
3898                 return(False);
3899   
3900         pstrcpy(root1,pname1);
3901         pstrcpy(root2,pname2);
3902         p = strrchr_m(root1,'.');
3903         if (p) {
3904                 *p = 0;
3905                 pstrcpy(ext1,p+1);
3906         } else {
3907                 pstrcpy(ext1,"");    
3908         }
3909         p = strrchr_m(root2,'.');
3910         if (p) {
3911                 *p = 0;
3912                 pstrcpy(ext2,p+1);
3913         } else {
3914                 pstrcpy(ext2,"");    
3915         }
3916
3917         p = root1;
3918         p2 = root2;
3919         while (*p2) {
3920                 if (*p2 == '?') {
3921                         *p2 = *p;
3922                         p2++;
3923                 } else if (*p2 == '*') {
3924                         pstrcpy(p2, p);
3925                         break;
3926                 } else {
3927                         p2++;
3928                 }
3929                 if (*p)
3930                         p++;
3931         }
3932
3933         p = ext1;
3934         p2 = ext2;
3935         while (*p2) {
3936                 if (*p2 == '?') {
3937                         *p2 = *p;
3938                         p2++;
3939                 } else if (*p2 == '*') {
3940                         pstrcpy(p2, p);
3941                         break;
3942                 } else {
3943                         p2++;
3944                 }
3945                 if (*p)
3946                         p++;
3947         }
3948
3949         available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3950         
3951         if (ext2[0]) {
3952                 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3953                 if (actual_space >= available_space - 1) {
3954                         DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3955                                 actual_space - available_space));
3956                 }
3957         } else {
3958                 pstrcpy_base(pname2, root2, name2);
3959         }
3960
3961         return(True);
3962 }
3963
3964 /****************************************************************************
3965  Ensure open files have their names updates.
3966 ****************************************************************************/
3967
3968 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3969 {
3970         files_struct *fsp;
3971         BOOL did_rename = False;
3972
3973         for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3974                 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3975                         fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3976                         fsp->fsp_name, newname ));
3977                 string_set(&fsp->fsp_name, newname);
3978                 did_rename = True;
3979         }
3980
3981         if (!did_rename)
3982                 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3983                         (unsigned int)dev, (double)inode, newname ));
3984 }
3985
3986 /****************************************************************************
3987  Rename an open file - given an fsp.
3988 ****************************************************************************/
3989
3990 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint16 attrs, BOOL replace_if_exists)
3991 {
3992         SMB_STRUCT_STAT sbuf;
3993         BOOL bad_path = False;
3994         pstring newname_last_component;
3995         NTSTATUS error = NT_STATUS_OK;
3996         BOOL dest_exists;
3997         BOOL rcdest = True;
3998
3999         ZERO_STRUCT(sbuf);
4000         rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
4001
4002         /* Quick check for "." and ".." */
4003         if (!bad_path && newname_last_component[0] == '.') {
4004                 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
4005                         return NT_STATUS_ACCESS_DENIED;
4006                 }
4007         }
4008         if (!rcdest && bad_path) {
4009                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4010         }
4011
4012         /* Ensure newname contains a '/' */
4013         if(strrchr_m(newname,'/') == 0) {
4014                 pstring tmpstr;
4015                 
4016                 pstrcpy(tmpstr, "./");
4017                 pstrcat(tmpstr, newname);
4018                 pstrcpy(newname, tmpstr);
4019         }
4020
4021         /*
4022          * Check for special case with case preserving and not
4023          * case sensitive. If the old last component differs from the original
4024          * last component only by case, then we should allow
4025          * the rename (user is trying to change the case of the
4026          * filename).
4027          */
4028
4029         if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
4030                         strequal(newname, fsp->fsp_name)) {
4031                 char *p;
4032                 pstring newname_modified_last_component;
4033
4034                 /*
4035                  * Get the last component of the modified name.
4036                  * Note that we guarantee that newname contains a '/'
4037                  * character above.
4038                  */
4039                 p = strrchr_m(newname,'/');
4040                 pstrcpy(newname_modified_last_component,p+1);
4041                         
4042                 if(strcsequal(newname_modified_last_component, 
4043                               newname_last_component) == False) {
4044                         /*
4045                          * Replace the modified last component with
4046                          * the original.
4047                          */
4048                         pstrcpy(p+1, newname_last_component);
4049                 }
4050         }
4051
4052         /*
4053          * If the src and dest names are identical - including case,
4054          * don't do the rename, just return success.
4055          */
4056
4057         if (strcsequal(fsp->fsp_name, newname)) {
4058                 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4059                         newname));
4060                 return NT_STATUS_OK;
4061         }
4062
4063         dest_exists = vfs_object_exist(conn,newname,NULL);
4064
4065         if(!replace_if_exists && dest_exists) {
4066                 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4067                         fsp->fsp_name,newname));
4068                 return NT_STATUS_OBJECT_NAME_COLLISION;
4069         }
4070
4071         error = can_rename(conn,newname,attrs,&sbuf);
4072
4073         if (dest_exists && !NT_STATUS_IS_OK(error)) {
4074                 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4075                         nt_errstr(error), fsp->fsp_name,newname));
4076                 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
4077                         error = NT_STATUS_ACCESS_DENIED;
4078                 return error;
4079         }
4080
4081         if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
4082                 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4083                         fsp->fsp_name,newname));
4084                 rename_open_files(conn, fsp->dev, fsp->inode, newname);
4085                 return NT_STATUS_OK;    
4086         }
4087
4088         if (errno == ENOTDIR || errno == EISDIR)
4089                 error = NT_STATUS_OBJECT_NAME_COLLISION;
4090         else
4091                 error = map_nt_error_from_unix(errno);
4092                 
4093         DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4094                 nt_errstr(error), fsp->fsp_name,newname));
4095
4096         return error;
4097 }
4098
4099 /****************************************************************************
4100  The guts of the rename command, split out so it may be called by the NT SMB
4101  code. 
4102 ****************************************************************************/
4103
4104 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
4105 {
4106         pstring directory;
4107         pstring mask;
4108         pstring last_component_src;
4109         pstring last_component_dest;
4110         char *p;
4111         BOOL has_wild;
4112         BOOL bad_path_src = False;
4113         BOOL bad_path_dest = False;
4114         int count=0;
4115         NTSTATUS error = NT_STATUS_OK;
4116         BOOL rc = True;
4117         BOOL rcdest = True;
4118         SMB_STRUCT_STAT sbuf1, sbuf2;
4119
4120         *directory = *mask = 0;
4121
4122         ZERO_STRUCT(sbuf1);
4123         ZERO_STRUCT(sbuf2);
4124
4125         rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
4126         if (!rc && bad_path_src) {
4127                 if (ms_has_wild(last_component_src))
4128                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4129                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4130         }
4131
4132         /* Quick check for "." and ".." */
4133         if (last_component_src[0] == '.') {
4134                 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
4135                         return NT_STATUS_OBJECT_NAME_INVALID;
4136                 }
4137         }
4138
4139         rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
4140
4141         /* Quick check for "." and ".." */
4142         if (last_component_dest[0] == '.') {
4143                 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
4144                         return NT_STATUS_OBJECT_NAME_INVALID;
4145                 }
4146         }
4147
4148         /*
4149          * Split the old name into directory and last component
4150          * strings. Note that unix_convert may have stripped off a 
4151          * leading ./ from both name and newname if the rename is 
4152          * at the root of the share. We need to make sure either both
4153          * name and newname contain a / character or neither of them do
4154          * as this is checked in resolve_wildcards().
4155          */
4156
4157         p = strrchr_m(name,'/');
4158         if (!p) {
4159                 pstrcpy(directory,".");
4160                 pstrcpy(mask,name);
4161         } else {
4162                 *p = 0;
4163                 pstrcpy(directory,name);
4164                 pstrcpy(mask,p+1);
4165                 *p = '/'; /* Replace needed for exceptional test below. */
4166         }
4167
4168         /*
4169          * We should only check the mangled cache
4170          * here if unix_convert failed. This means
4171          * that the path in 'mask' doesn't exist
4172          * on the file system and so we need to look
4173          * for a possible mangle. This patch from
4174          * Tine Smukavec <valentin.smukavec@hermes.si>.
4175          */
4176
4177         if (!rc && mangle_is_mangled(mask,SNUM(conn)))
4178                 mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
4179
4180         has_wild = ms_has_wild(mask);
4181
4182         if (!has_wild) {
4183                 /*
4184                  * No wildcards - just process the one file.
4185                  */
4186                 BOOL is_short_name = mangle_is_8_3(name, True, SNUM(conn));
4187
4188                 /* Add a terminating '/' to the directory name. */
4189                 pstrcat(directory,"/");
4190                 pstrcat(directory,mask);
4191                 
4192                 /* Ensure newname contains a '/' also */
4193                 if(strrchr_m(newname,'/') == 0) {
4194                         pstring tmpstr;
4195                         
4196                         pstrcpy(tmpstr, "./");
4197                         pstrcat(tmpstr, newname);
4198                         pstrcpy(newname, tmpstr);
4199                 }
4200                 
4201                 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
4202 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", 
4203                          conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory, 
4204                          newname, last_component_dest, is_short_name));
4205
4206                 /*
4207                  * Check for special case with case preserving and not
4208                  * case sensitive, if directory and newname are identical,
4209                  * and the old last component differs from the original
4210                  * last component only by case, then we should allow
4211                  * the rename (user is trying to change the case of the
4212                  * filename).
4213                  */
4214                 if((conn->case_sensitive == False) && 
4215                    (((conn->case_preserve == True) && 
4216                      (is_short_name == False)) || 
4217                     ((conn->short_case_preserve == True) && 
4218                      (is_short_name == True))) &&
4219                    strcsequal(directory, newname)) {
4220                         pstring modified_last_component;
4221
4222                         /*
4223                          * Get the last component of the modified name.
4224                          * Note that we guarantee that newname contains a '/'
4225                          * character above.
4226                          */
4227                         p = strrchr_m(newname,'/');
4228                         pstrcpy(modified_last_component,p+1);
4229                         
4230                         if(strcsequal(modified_last_component, 
4231                                       last_component_dest) == False) {
4232                                 /*
4233                                  * Replace the modified last component with
4234                                  * the original.
4235                                  */
4236                                 pstrcpy(p+1, last_component_dest);
4237                         }
4238                 }
4239         
4240                 resolve_wildcards(directory,newname);
4241         
4242                 /*
4243                  * The source object must exist.
4244                  */
4245
4246                 if (!vfs_object_exist(conn, directory, &sbuf1)) {
4247                         DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
4248                                 directory,newname));
4249
4250                         if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
4251                                 /*
4252                                  * Must return different errors depending on whether the parent
4253                                  * directory existed or not.
4254                                  */
4255
4256                                 p = strrchr_m(directory, '/');
4257                                 if (!p)
4258                                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4259                                 *p = '\0';
4260                                 if (vfs_object_exist(conn, directory, NULL))
4261                                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4262                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4263                         }
4264                         error = map_nt_error_from_unix(errno);
4265                         DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4266                                 nt_errstr(error), directory,newname));
4267
4268                         return error;
4269                 }
4270
4271                 if (!rcdest && bad_path_dest) {
4272                         if (ms_has_wild(last_component_dest))
4273                                 return NT_STATUS_OBJECT_NAME_INVALID;
4274                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4275                 }
4276
4277                 error = can_rename(conn,directory,attrs,&sbuf1);
4278
4279                 if (!NT_STATUS_IS_OK(error)) {
4280                         DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4281                                 nt_errstr(error), directory,newname));
4282                         return error;
4283                 }
4284
4285                 /*
4286                  * If the src and dest names are identical - including case,
4287                  * don't do the rename, just return success.
4288                  */
4289
4290                 if (strcsequal(directory, newname)) {
4291                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4292                         DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
4293                         return NT_STATUS_OK;
4294                 }
4295
4296                 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
4297                         DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
4298                                 directory,newname));
4299                         return NT_STATUS_OBJECT_NAME_COLLISION;
4300                 }
4301
4302                 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
4303                         DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
4304                                 directory,newname));
4305                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4306                         return NT_STATUS_OK;    
4307                 }
4308
4309                 if (errno == ENOTDIR || errno == EISDIR)
4310                         error = NT_STATUS_OBJECT_NAME_COLLISION;
4311                 else
4312                         error = map_nt_error_from_unix(errno);
4313                 
4314                 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4315                         nt_errstr(error), directory,newname));
4316
4317                 return error;
4318         } else {
4319                 /*
4320                  * Wildcards - process each file that matches.
4321                  */
4322                 struct smb_Dir *dir_hnd = NULL;
4323                 const char *dname;
4324                 pstring destname;
4325                 
4326                 if (check_name(directory,conn))
4327                         dir_hnd = OpenDir(conn, directory);
4328                 
4329                 if (dir_hnd) {
4330                         long offset = 0;
4331                         error = NT_STATUS_NO_SUCH_FILE;
4332 /*                      Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
4333                         
4334                         if (strequal(mask,"????????.???"))
4335                                 pstrcpy(mask,"*");
4336                         
4337                         while ((dname = ReadDirName(dir_hnd, &offset))) {
4338                                 pstring fname;
4339                                 BOOL sysdir_entry = False;
4340
4341                                 pstrcpy(fname,dname);
4342                                 
4343                                 /* Quick check for "." and ".." */
4344                                 if (fname[0] == '.') {
4345                                         if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4346                                                 if (attrs & aDIR) {
4347                                                         sysdir_entry = True;
4348                                                 } else {
4349                                                         continue;
4350                                                 }
4351                                         }
4352                                 }
4353
4354                                 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4355                                         continue;
4356
4357                                 if(!mask_match(fname, mask, conn->case_sensitive))
4358                                         continue;
4359                                 
4360                                 if (sysdir_entry) {
4361                                         error = NT_STATUS_OBJECT_NAME_INVALID;
4362                                         break;
4363                                 }
4364
4365                                 error = NT_STATUS_ACCESS_DENIED;
4366                                 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
4367                                 if (!vfs_object_exist(conn, fname, &sbuf1)) {
4368                                         error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4369                                         DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
4370                                         continue;
4371                                 }
4372                                 error = can_rename(conn,fname,attrs,&sbuf1);
4373                                 if (!NT_STATUS_IS_OK(error)) {
4374                                         DEBUG(6,("rename %s refused\n", fname));
4375                                         continue;
4376                                 }
4377                                 pstrcpy(destname,newname);
4378                                 
4379                                 if (!resolve_wildcards(fname,destname)) {
4380                                         DEBUG(6,("resolve_wildcards %s %s failed\n", 
4381                                                  fname, destname));
4382                                         continue;
4383                                 }
4384                                 
4385                                 if (strcsequal(fname,destname)) {
4386                                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4387                                         DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
4388                                         count++;
4389                                         error = NT_STATUS_OK;
4390                                         continue;
4391                                 }
4392
4393                                 if (!replace_if_exists && 
4394                                     vfs_file_exist(conn,destname, NULL)) {
4395                                         DEBUG(6,("file_exist %s\n", destname));
4396                                         error = NT_STATUS_OBJECT_NAME_COLLISION;
4397                                         continue;
4398                                 }
4399                                 
4400                                 if (!SMB_VFS_RENAME(conn,fname,destname)) {
4401                                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4402                                         count++;
4403                                         error = NT_STATUS_OK;
4404                                 }
4405                                 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
4406                         }
4407                         CloseDir(dir_hnd);
4408                 }
4409
4410                 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
4411                         if (!rcdest && bad_path_dest) {
4412                                 if (ms_has_wild(last_component_dest))
4413                                         return NT_STATUS_OBJECT_NAME_INVALID;
4414                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4415                         }
4416                 }
4417         }
4418         
4419         if (count == 0 && NT_STATUS_IS_OK(error)) {
4420                 error = map_nt_error_from_unix(errno);
4421         }
4422         
4423         return error;
4424 }
4425
4426 /****************************************************************************
4427  Reply to a mv.
4428 ****************************************************************************/
4429
4430 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, 
4431              int dum_buffsize)
4432 {
4433         int outsize = 0;
4434         pstring name;
4435         pstring newname;
4436         char *p;
4437         uint16 attrs = SVAL(inbuf,smb_vwv0);
4438         NTSTATUS status;
4439
4440         START_PROFILE(SMBmv);
4441
4442         p = smb_buf(inbuf) + 1;
4443         p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4444         if (!NT_STATUS_IS_OK(status)) {
4445                 END_PROFILE(SMBmv);
4446                 return ERROR_NT(status);
4447         }
4448         p++;
4449         p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4450         if (!NT_STATUS_IS_OK(status)) {
4451                 END_PROFILE(SMBmv);
4452                 return ERROR_NT(status);
4453         }
4454         
4455         RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4456         RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4457         
4458         DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4459         
4460         status = rename_internals(conn, name, newname, attrs, False);
4461         if (!NT_STATUS_IS_OK(status)) {
4462                 END_PROFILE(SMBmv);
4463                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4464                         /* We have re-scheduled this call. */
4465                         return -1;
4466                 }
4467                 return ERROR_NT(status);
4468         }
4469
4470         /*
4471          * Win2k needs a changenotify request response before it will
4472          * update after a rename..
4473          */     
4474         process_pending_change_notify_queue((time_t)0);
4475         outsize = set_message(outbuf,0,0,True);
4476   
4477         END_PROFILE(SMBmv);
4478         return(outsize);
4479 }
4480
4481 /*******************************************************************
4482  Copy a file as part of a reply_copy.
4483 ******************************************************************/
4484
4485 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4486                       int count,BOOL target_is_directory, int *err_ret)
4487 {
4488         int Access,action;
4489         SMB_STRUCT_STAT src_sbuf, sbuf2;
4490         SMB_OFF_T ret=-1;
4491         files_struct *fsp1,*fsp2;
4492         pstring dest;
4493         uint32 dosattrs;
4494  
4495         *err_ret = 0;
4496
4497         pstrcpy(dest,dest1);
4498         if (target_is_directory) {
4499                 char *p = strrchr_m(src,'/');
4500                 if (p) 
4501                         p++;
4502                 else
4503                         p = src;
4504                 pstrcat(dest,"/");
4505                 pstrcat(dest,p);
4506         }
4507
4508         if (!vfs_file_exist(conn,src,&src_sbuf))
4509                 return(False);
4510
4511         fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
4512                                         (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,INTERNAL_OPEN_ONLY,
4513                                         &Access,&action);
4514
4515         if (!fsp1)
4516                 return(False);
4517
4518         if (!target_is_directory && count)
4519                 ofun = FILE_EXISTS_OPEN;
4520
4521         dosattrs = dos_mode(conn, src, &src_sbuf);
4522         if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
4523                 ZERO_STRUCTP(&sbuf2);
4524
4525         fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4526                         ofun,dosattrs,INTERNAL_OPEN_ONLY,&Access,&action);
4527
4528         if (!fsp2) {
4529                 close_file(fsp1,False);
4530                 return(False);
4531         }
4532
4533         if ((ofun&3) == 1) {
4534                 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4535                         DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4536                         /*
4537                          * Stop the copy from occurring.
4538                          */
4539                         ret = -1;
4540                         src_sbuf.st_size = 0;
4541                 }
4542         }
4543   
4544         if (src_sbuf.st_size)
4545                 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4546
4547         close_file(fsp1,False);
4548
4549         /* Ensure the modtime is set correctly on the destination file. */
4550         fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime);
4551
4552         /*
4553          * As we are opening fsp1 read-only we only expect
4554          * an error on close on fsp2 if we are out of space.
4555          * Thus we don't look at the error return from the
4556          * close of fsp1.
4557          */
4558         *err_ret = close_file(fsp2,False);
4559
4560         return(ret == (SMB_OFF_T)src_sbuf.st_size);
4561 }
4562
4563 /****************************************************************************
4564  Reply to a file copy.
4565 ****************************************************************************/
4566
4567 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4568 {
4569         int outsize = 0;
4570         pstring name;
4571         pstring directory;
4572         pstring mask,newname;
4573         char *p;
4574         int count=0;
4575         int error = ERRnoaccess;
4576         int err = 0;
4577         BOOL has_wild;
4578         BOOL exists=False;
4579         int tid2 = SVAL(inbuf,smb_vwv0);
4580         int ofun = SVAL(inbuf,smb_vwv1);
4581         int flags = SVAL(inbuf,smb_vwv2);
4582         BOOL target_is_directory=False;
4583         BOOL bad_path1 = False;
4584         BOOL bad_path2 = False;
4585         BOOL rc = True;
4586         SMB_STRUCT_STAT sbuf1, sbuf2;
4587         NTSTATUS status;
4588
4589         START_PROFILE(SMBcopy);
4590
4591         *directory = *mask = 0;
4592
4593         p = smb_buf(inbuf);
4594         p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4595         if (!NT_STATUS_IS_OK(status)) {
4596                 END_PROFILE(SMBcopy);
4597                 return ERROR_NT(status);
4598         }
4599         p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4600         if (!NT_STATUS_IS_OK(status)) {
4601                 END_PROFILE(SMBcopy);
4602                 return ERROR_NT(status);
4603         }
4604    
4605         DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4606    
4607         if (tid2 != conn->cnum) {
4608                 /* can't currently handle inter share copies XXXX */
4609                 DEBUG(3,("Rejecting inter-share copy\n"));
4610                 END_PROFILE(SMBcopy);
4611                 return ERROR_DOS(ERRSRV,ERRinvdevice);
4612         }
4613
4614         RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4615         RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4616
4617         rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4618         unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4619
4620         target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4621
4622         if ((flags&1) && target_is_directory) {
4623                 END_PROFILE(SMBcopy);
4624                 return ERROR_DOS(ERRDOS,ERRbadfile);
4625         }
4626
4627         if ((flags&2) && !target_is_directory) {
4628                 END_PROFILE(SMBcopy);
4629                 return ERROR_DOS(ERRDOS,ERRbadpath);
4630         }
4631
4632         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4633                 /* wants a tree copy! XXXX */
4634                 DEBUG(3,("Rejecting tree copy\n"));
4635                 END_PROFILE(SMBcopy);
4636                 return ERROR_DOS(ERRSRV,ERRerror);
4637         }
4638
4639         p = strrchr_m(name,'/');
4640         if (!p) {
4641                 pstrcpy(directory,"./");
4642                 pstrcpy(mask,name);
4643         } else {
4644                 *p = 0;
4645                 pstrcpy(directory,name);
4646                 pstrcpy(mask,p+1);
4647         }
4648
4649         /*
4650          * We should only check the mangled cache
4651          * here if unix_convert failed. This means
4652          * that the path in 'mask' doesn't exist
4653          * on the file system and so we need to look
4654          * for a possible mangle. This patch from
4655          * Tine Smukavec <valentin.smukavec@hermes.si>.
4656          */
4657
4658         if (!rc && mangle_is_mangled(mask, SNUM(conn)))
4659                 mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
4660
4661         has_wild = ms_has_wild(mask);
4662
4663         if (!has_wild) {
4664                 pstrcat(directory,"/");
4665                 pstrcat(directory,mask);
4666                 if (resolve_wildcards(directory,newname) &&
4667                                 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4668                         count++;
4669                 if(!count && err) {
4670                         errno = err;
4671                         END_PROFILE(SMBcopy);
4672                         return(UNIXERROR(ERRHRD,ERRgeneral));
4673                 }
4674                 if (!count) {
4675                         exists = vfs_file_exist(conn,directory,NULL);
4676                 }
4677         } else {
4678                 struct smb_Dir *dir_hnd = NULL;
4679                 const char *dname;
4680                 pstring destname;
4681
4682                 if (check_name(directory,conn))
4683                         dir_hnd = OpenDir(conn, directory);
4684
4685                 if (dir_hnd) {
4686                         long offset = 0;
4687                         error = ERRbadfile;
4688
4689                         if (strequal(mask,"????????.???"))
4690                                 pstrcpy(mask,"*");
4691
4692                         while ((dname = ReadDirName(dir_hnd, &offset))) {
4693                                 pstring fname;
4694                                 pstrcpy(fname,dname);
4695     
4696                                 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4697                                         continue;
4698
4699                                 if(!mask_match(fname, mask, conn->case_sensitive))
4700                                         continue;
4701
4702                                 error = ERRnoaccess;
4703                                 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4704                                 pstrcpy(destname,newname);
4705                                 if (resolve_wildcards(fname,destname) && 
4706                                                 copy_file(fname,destname,conn,ofun,
4707                                                 count,target_is_directory,&err))
4708                                         count++;
4709                                 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4710                         }
4711                         CloseDir(dir_hnd);
4712                 }
4713         }
4714   
4715         if (count == 0) {
4716                 if(err) {
4717                         /* Error on close... */
4718                         errno = err;
4719                         END_PROFILE(SMBcopy);
4720                         return(UNIXERROR(ERRHRD,ERRgeneral));
4721                 }
4722
4723                 if (exists) {
4724                         END_PROFILE(SMBcopy);
4725                         return ERROR_DOS(ERRDOS,error);
4726                 } else {
4727                         if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4728                                 set_saved_error_triple(ERRDOS, ERRbadpath, NT_STATUS_OK);
4729                         }
4730                         END_PROFILE(SMBcopy);
4731                         return(UNIXERROR(ERRDOS,error));
4732                 }
4733         }
4734   
4735         outsize = set_message(outbuf,1,0,True);
4736         SSVAL(outbuf,smb_vwv0,count);
4737
4738         END_PROFILE(SMBcopy);
4739         return(outsize);
4740 }
4741
4742 /****************************************************************************
4743  Reply to a setdir.
4744 ****************************************************************************/
4745
4746 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4747 {
4748         int snum;
4749         int outsize = 0;
4750         BOOL ok = False;
4751         pstring newdir;
4752         NTSTATUS status;
4753
4754         START_PROFILE(pathworks_setdir);
4755   
4756         snum = SNUM(conn);
4757         if (!CAN_SETDIR(snum)) {
4758                 END_PROFILE(pathworks_setdir);
4759                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4760         }
4761
4762         srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False);
4763         if (!NT_STATUS_IS_OK(status)) {
4764                 END_PROFILE(pathworks_setdir);
4765                 return ERROR_NT(status);
4766         }
4767   
4768         RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf);
4769
4770         if (strlen(newdir) == 0) {
4771                 ok = True;
4772         } else {
4773                 ok = vfs_directory_exist(conn,newdir,NULL);
4774                 if (ok)
4775                         string_set(&conn->connectpath,newdir);
4776         }
4777   
4778         if (!ok) {
4779                 END_PROFILE(pathworks_setdir);
4780                 return ERROR_DOS(ERRDOS,ERRbadpath);
4781         }
4782   
4783         outsize = set_message(outbuf,0,0,True);
4784         SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4785   
4786         DEBUG(3,("setdir %s\n", newdir));
4787
4788         END_PROFILE(pathworks_setdir);
4789         return(outsize);
4790 }
4791
4792 #undef DBGC_CLASS
4793 #define DBGC_CLASS DBGC_LOCKING
4794
4795 /****************************************************************************
4796  Get a lock pid, dealing with large count requests.
4797 ****************************************************************************/
4798
4799 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4800 {
4801         if(!large_file_format)
4802                 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4803         else
4804                 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4805 }
4806
4807 /****************************************************************************
4808  Get a lock count, dealing with large count requests.
4809 ****************************************************************************/
4810
4811 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4812 {
4813         SMB_BIG_UINT count = 0;
4814
4815         if(!large_file_format) {
4816                 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4817         } else {
4818
4819 #if defined(HAVE_LONGLONG)
4820                 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4821                         ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4822 #else /* HAVE_LONGLONG */
4823
4824                 /*
4825                  * NT4.x seems to be broken in that it sends large file (64 bit)
4826                  * lockingX calls even if the CAP_LARGE_FILES was *not*
4827                  * negotiated. For boxes without large unsigned ints truncate the
4828                  * lock count by dropping the top 32 bits.
4829                  */
4830
4831                 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4832                         DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4833                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4834                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4835                                 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4836                 }
4837
4838                 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4839 #endif /* HAVE_LONGLONG */
4840         }
4841
4842         return count;
4843 }
4844
4845 #if !defined(HAVE_LONGLONG)
4846 /****************************************************************************
4847  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4848 ****************************************************************************/
4849
4850 static uint32 map_lock_offset(uint32 high, uint32 low)
4851 {
4852         unsigned int i;
4853         uint32 mask = 0;
4854         uint32 highcopy = high;
4855  
4856         /*
4857          * Try and find out how many significant bits there are in high.
4858          */
4859  
4860         for(i = 0; highcopy; i++)
4861                 highcopy >>= 1;
4862  
4863         /*
4864          * We use 31 bits not 32 here as POSIX
4865          * lock offsets may not be negative.
4866          */
4867  
4868         mask = (~0) << (31 - i);
4869  
4870         if(low & mask)
4871                 return 0; /* Fail. */
4872  
4873         high <<= (31 - i);
4874  
4875         return (high|low);
4876 }
4877 #endif /* !defined(HAVE_LONGLONG) */
4878
4879 /****************************************************************************
4880  Get a lock offset, dealing with large offset requests.
4881 ****************************************************************************/
4882
4883 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4884 {
4885         SMB_BIG_UINT offset = 0;
4886
4887         *err = False;
4888
4889         if(!large_file_format) {
4890                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4891         } else {
4892
4893 #if defined(HAVE_LONGLONG)
4894                 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4895                                 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4896 #else /* HAVE_LONGLONG */
4897
4898                 /*
4899                  * NT4.x seems to be broken in that it sends large file (64 bit)
4900                  * lockingX calls even if the CAP_LARGE_FILES was *not*
4901                  * negotiated. For boxes without large unsigned ints mangle the
4902                  * lock offset by mapping the top 32 bits onto the lower 32.
4903                  */
4904       
4905                 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4906                         uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4907                         uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4908                         uint32 new_low = 0;
4909
4910                         if((new_low = map_lock_offset(high, low)) == 0) {
4911                                 *err = True;
4912                                 return (SMB_BIG_UINT)-1;
4913                         }
4914
4915                         DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4916                                 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4917                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4918                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4919                 }
4920
4921                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4922 #endif /* HAVE_LONGLONG */
4923         }
4924
4925         return offset;
4926 }
4927
4928 /****************************************************************************
4929  Reply to a lockingX request.
4930 ****************************************************************************/
4931
4932 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4933 {
4934         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4935         unsigned char locktype = CVAL(inbuf,smb_vwv3);
4936         unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4937         uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4938         uint16 num_locks = SVAL(inbuf,smb_vwv7);
4939         SMB_BIG_UINT count = 0, offset = 0;
4940         uint16 lock_pid;
4941         int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4942         int i;
4943         char *data;
4944         BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4945         BOOL err;
4946         BOOL my_lock_ctx = False;
4947         NTSTATUS status;
4948
4949         START_PROFILE(SMBlockingX);
4950         
4951         CHECK_FSP(fsp,conn);
4952         
4953         data = smb_buf(inbuf);
4954
4955         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
4956                 /* we don't support these - and CANCEL_LOCK makes w2k
4957                    and XP reboot so I don't really want to be
4958                    compatible! (tridge) */
4959                 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4960         }
4961         
4962         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
4963                 /* Need to make this like a cancel.... JRA. */
4964                 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4965         }
4966         
4967         /* Check if this is an oplock break on a file
4968            we have granted an oplock on.
4969         */
4970         if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4971                 /* Client can insist on breaking to none. */
4972                 BOOL break_to_none = (oplocklevel == 0);
4973                 
4974                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4975                          (unsigned int)oplocklevel, fsp->fnum ));
4976
4977                 /*
4978                  * Make sure we have granted an exclusive or batch oplock on this file.
4979                  */
4980                 
4981                 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4982                         DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4983 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4984
4985                         /* if this is a pure oplock break request then don't send a reply */
4986                         if (num_locks == 0 && num_ulocks == 0) {
4987                                 END_PROFILE(SMBlockingX);
4988                                 return -1;
4989                         } else {
4990                                 END_PROFILE(SMBlockingX);
4991                                 return ERROR_DOS(ERRDOS,ERRlock);
4992                         }
4993                 }
4994
4995                 if (remove_oplock(fsp, break_to_none) == False) {
4996                         DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4997                                  fsp->fsp_name ));
4998                 }
4999                 
5000                 /* if this is a pure oplock break request then don't send a reply */
5001                 if (num_locks == 0 && num_ulocks == 0) {
5002                         /* Sanity check - ensure a pure oplock break is not a
5003                            chained request. */
5004                         if(CVAL(inbuf,smb_vwv0) != 0xff)
5005                                 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
5006                                          (unsigned int)CVAL(inbuf,smb_vwv0) ));
5007                         END_PROFILE(SMBlockingX);
5008                         return -1;
5009                 }
5010         }
5011
5012         /*
5013          * We do this check *after* we have checked this is not a oplock break
5014          * response message. JRA.
5015          */
5016         
5017         release_level_2_oplocks_on_change(fsp);
5018         
5019         /* Data now points at the beginning of the list
5020            of smb_unlkrng structs */
5021         for(i = 0; i < (int)num_ulocks; i++) {
5022                 lock_pid = get_lock_pid( data, i, large_file_format);
5023                 count = get_lock_count( data, i, large_file_format);
5024                 offset = get_lock_offset( data, i, large_file_format, &err);
5025                 
5026                 /*
5027                  * There is no error code marked "stupid client bug".... :-).
5028                  */
5029                 if(err) {
5030                         END_PROFILE(SMBlockingX);
5031                         return ERROR_DOS(ERRDOS,ERRnoaccess);
5032                 }
5033
5034                 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
5035                           (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
5036                 
5037                 status = do_unlock(fsp,conn,lock_pid,count,offset);
5038                 if (NT_STATUS_V(status)) {
5039                         END_PROFILE(SMBlockingX);
5040                         return ERROR_NT(status);
5041                 }
5042         }
5043
5044         /* Setup the timeout in seconds. */
5045
5046         lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
5047         
5048         /* Now do any requested locks */
5049         data += ((large_file_format ? 20 : 10)*num_ulocks);
5050         
5051         /* Data now points at the beginning of the list
5052            of smb_lkrng structs */
5053         
5054         for(i = 0; i < (int)num_locks; i++) {
5055                 lock_pid = get_lock_pid( data, i, large_file_format);
5056                 count = get_lock_count( data, i, large_file_format);
5057                 offset = get_lock_offset( data, i, large_file_format, &err);
5058                 
5059                 /*
5060                  * There is no error code marked "stupid client bug".... :-).
5061                  */
5062                 if(err) {
5063                         END_PROFILE(SMBlockingX);
5064                         return ERROR_DOS(ERRDOS,ERRnoaccess);
5065                 }
5066                 
5067                 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
5068                         (double)offset, (double)count, (unsigned int)lock_pid,
5069                         fsp->fsp_name, (int)lock_timeout ));
5070                 
5071                 status = do_lock_spin(fsp,conn,lock_pid, count,offset, 
5072                                  ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
5073                 if (NT_STATUS_V(status)) {
5074                         /*
5075                          * Interesting fact found by IFSTEST /t LockOverlappedTest...
5076                          * Even if it's our own lock context, we need to wait here as
5077                          * there may be an unlock on the way.
5078                          * So I removed a "&& !my_lock_ctx" from the following
5079                          * if statement. JRA.
5080                          */
5081                         if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
5082                                 /*
5083                                  * A blocking lock was requested. Package up
5084                                  * this smb into a queued request and push it
5085                                  * onto the blocking lock queue.
5086                                  */
5087                                 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
5088                                         END_PROFILE(SMBlockingX);
5089                                         return -1;
5090                                 }
5091                         }
5092                         break;
5093                 }
5094         }
5095         
5096         /* If any of the above locks failed, then we must unlock
5097            all of the previous locks (X/Open spec). */
5098         if (i != num_locks && num_locks != 0) {
5099                 /*
5100                  * Ensure we don't do a remove on the lock that just failed,
5101                  * as under POSIX rules, if we have a lock already there, we
5102                  * will delete it (and we shouldn't) .....
5103                  */
5104                 for(i--; i >= 0; i--) {
5105                         lock_pid = get_lock_pid( data, i, large_file_format);
5106                         count = get_lock_count( data, i, large_file_format);
5107                         offset = get_lock_offset( data, i, large_file_format, &err);
5108                         
5109                         /*
5110                          * There is no error code marked "stupid client bug".... :-).
5111                          */
5112                         if(err) {
5113                                 END_PROFILE(SMBlockingX);
5114                                 return ERROR_DOS(ERRDOS,ERRnoaccess);
5115                         }
5116                         
5117                         do_unlock(fsp,conn,lock_pid,count,offset);
5118                 }
5119                 END_PROFILE(SMBlockingX);
5120                 return ERROR_NT(status);
5121         }
5122
5123         set_message(outbuf,2,0,True);
5124         
5125         DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5126                     fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
5127         
5128         END_PROFILE(SMBlockingX);
5129         return chain_reply(inbuf,outbuf,length,bufsize);
5130 }
5131
5132 #undef DBGC_CLASS
5133 #define DBGC_CLASS DBGC_ALL
5134
5135 /****************************************************************************
5136  Reply to a SMBreadbmpx (read block multiplex) request.
5137 ****************************************************************************/
5138
5139 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5140 {
5141         ssize_t nread = -1;
5142         ssize_t total_read;
5143         char *data;
5144         SMB_OFF_T startpos;
5145         int outsize;
5146         size_t maxcount;
5147         int max_per_packet;
5148         size_t tcount;
5149         int pad;
5150         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5151         START_PROFILE(SMBreadBmpx);
5152
5153         /* this function doesn't seem to work - disable by default */
5154         if (!lp_readbmpx()) {
5155                 END_PROFILE(SMBreadBmpx);
5156                 return ERROR_DOS(ERRSRV,ERRuseSTD);
5157         }
5158
5159         outsize = set_message(outbuf,8,0,True);
5160
5161         CHECK_FSP(fsp,conn);
5162         CHECK_READ(fsp);
5163
5164         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5165         maxcount = SVAL(inbuf,smb_vwv3);
5166
5167         data = smb_buf(outbuf);
5168         pad = ((long)data)%4;
5169         if (pad)
5170                 pad = 4 - pad;
5171         data += pad;
5172
5173         max_per_packet = bufsize-(outsize+pad);
5174         tcount = maxcount;
5175         total_read = 0;
5176
5177         if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5178                 END_PROFILE(SMBreadBmpx);
5179                 return ERROR_DOS(ERRDOS,ERRlock);
5180         }
5181
5182         do {
5183                 size_t N = MIN(max_per_packet,tcount-total_read);
5184   
5185                 nread = read_file(fsp,data,startpos,N);
5186
5187                 if (nread <= 0)
5188                         nread = 0;
5189
5190                 if (nread < (ssize_t)N)
5191                         tcount = total_read + nread;
5192
5193                 set_message(outbuf,8,nread,False);
5194                 SIVAL(outbuf,smb_vwv0,startpos);
5195                 SSVAL(outbuf,smb_vwv2,tcount);
5196                 SSVAL(outbuf,smb_vwv6,nread);
5197                 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5198
5199                 show_msg(outbuf);
5200                 if (!send_smb(smbd_server_fd(),outbuf))
5201                         exit_server("reply_readbmpx: send_smb failed.");
5202
5203                 total_read += nread;
5204                 startpos += nread;
5205         } while (total_read < (ssize_t)tcount);
5206
5207         END_PROFILE(SMBreadBmpx);
5208         return(-1);
5209 }
5210
5211 /****************************************************************************
5212  Reply to a SMBsetattrE.
5213 ****************************************************************************/
5214
5215 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5216 {
5217         struct utimbuf unix_times;
5218         int outsize = 0;
5219         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5220         START_PROFILE(SMBsetattrE);
5221
5222         outsize = set_message(outbuf,0,0,True);
5223
5224         if(!fsp || (fsp->conn != conn)) {
5225                 END_PROFILE(SMBgetattrE);
5226                 return ERROR_DOS(ERRDOS,ERRbadfid);
5227         }
5228
5229         /*
5230          * Convert the DOS times into unix times. Ignore create
5231          * time as UNIX can't set this.
5232          */
5233
5234         unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
5235         unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
5236   
5237         /* 
5238          * Patch from Ray Frush <frush@engr.colostate.edu>
5239          * Sometimes times are sent as zero - ignore them.
5240          */
5241
5242         if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5243                 /* Ignore request */
5244                 if( DEBUGLVL( 3 ) ) {
5245                         dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5246                         dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5247                 }
5248                 END_PROFILE(SMBsetattrE);
5249                 return(outsize);
5250         } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5251                 /* set modify time = to access time if modify time was unset */
5252                 unix_times.modtime = unix_times.actime;
5253         }
5254
5255         /* Set the date on this file */
5256         /* Should we set pending modtime here ? JRA */
5257         if(file_utime(conn, fsp->fsp_name, &unix_times)) {
5258                 END_PROFILE(SMBsetattrE);
5259                 return ERROR_DOS(ERRDOS,ERRnoaccess);
5260         }
5261   
5262         DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
5263                 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
5264
5265         END_PROFILE(SMBsetattrE);
5266         return(outsize);
5267 }
5268
5269
5270 /* Back from the dead for OS/2..... JRA. */
5271
5272 /****************************************************************************
5273  Reply to a SMBwritebmpx (write block multiplex primary) request.
5274 ****************************************************************************/
5275
5276 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5277 {
5278         size_t numtowrite;
5279         ssize_t nwritten = -1;
5280         int outsize = 0;
5281         SMB_OFF_T startpos;
5282         size_t tcount;
5283         BOOL write_through;
5284         int smb_doff;
5285         char *data;
5286         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5287         START_PROFILE(SMBwriteBmpx);
5288
5289         CHECK_FSP(fsp,conn);
5290         CHECK_WRITE(fsp);
5291         if (HAS_CACHED_ERROR(fsp)) {
5292                 return(CACHED_ERROR(fsp));
5293         }
5294
5295         tcount = SVAL(inbuf,smb_vwv1);
5296         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
5297         write_through = BITSETW(inbuf+smb_vwv7,0);
5298         numtowrite = SVAL(inbuf,smb_vwv10);
5299         smb_doff = SVAL(inbuf,smb_vwv11);
5300
5301         data = smb_base(inbuf) + smb_doff;
5302
5303         /* If this fails we need to send an SMBwriteC response,
5304                 not an SMBwritebmpx - set this up now so we don't forget */
5305         SCVAL(outbuf,smb_com,SMBwritec);
5306
5307         if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
5308                 END_PROFILE(SMBwriteBmpx);
5309                 return(ERROR_DOS(ERRDOS,ERRlock));
5310         }
5311
5312         nwritten = write_file(fsp,data,startpos,numtowrite);
5313
5314         if(lp_syncalways(SNUM(conn)) || write_through)
5315                 sync_file(conn,fsp);
5316   
5317         if(nwritten < (ssize_t)numtowrite) {
5318                 END_PROFILE(SMBwriteBmpx);
5319                 return(UNIXERROR(ERRHRD,ERRdiskfull));
5320         }
5321
5322         /* If the maximum to be written to this file
5323                 is greater than what we just wrote then set
5324                 up a secondary struct to be attached to this
5325                 fd, we will use this to cache error messages etc. */
5326
5327         if((ssize_t)tcount > nwritten) {
5328                 write_bmpx_struct *wbms;
5329                 if(fsp->wbmpx_ptr != NULL)
5330                         wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5331                 else
5332                         wbms = SMB_MALLOC_P(write_bmpx_struct);
5333                 if(!wbms) {
5334                         DEBUG(0,("Out of memory in reply_readmpx\n"));
5335                         END_PROFILE(SMBwriteBmpx);
5336                         return(ERROR_DOS(ERRSRV,ERRnoresource));
5337                 }
5338                 wbms->wr_mode = write_through;
5339                 wbms->wr_discard = False; /* No errors yet */
5340                 wbms->wr_total_written = nwritten;
5341                 wbms->wr_errclass = 0;
5342                 wbms->wr_error = 0;
5343                 fsp->wbmpx_ptr = wbms;
5344         }
5345
5346         /* We are returning successfully, set the message type back to
5347                 SMBwritebmpx */
5348         SCVAL(outbuf,smb_com,SMBwriteBmpx);
5349   
5350         outsize = set_message(outbuf,1,0,True);
5351   
5352         SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5353   
5354         DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5355                         fsp->fnum, (int)numtowrite, (int)nwritten ) );
5356
5357         if (write_through && tcount==nwritten) {
5358                 /* We need to send both a primary and a secondary response */
5359                 smb_setlen(outbuf,outsize - 4);
5360                 show_msg(outbuf);
5361                 if (!send_smb(smbd_server_fd(),outbuf))
5362                         exit_server("reply_writebmpx: send_smb failed.");
5363
5364                 /* Now the secondary */
5365                 outsize = set_message(outbuf,1,0,True);
5366                 SCVAL(outbuf,smb_com,SMBwritec);
5367                 SSVAL(outbuf,smb_vwv0,nwritten);
5368         }
5369
5370         END_PROFILE(SMBwriteBmpx);
5371         return(outsize);
5372 }
5373
5374 /****************************************************************************
5375  Reply to a SMBwritebs (write block multiplex secondary) request.
5376 ****************************************************************************/
5377
5378 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5379 {
5380         size_t numtowrite;
5381         ssize_t nwritten = -1;
5382         int outsize = 0;
5383         SMB_OFF_T startpos;
5384         size_t tcount;
5385         BOOL write_through;
5386         int smb_doff;
5387         char *data;
5388         write_bmpx_struct *wbms;
5389         BOOL send_response = False; 
5390         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5391         START_PROFILE(SMBwriteBs);
5392
5393         CHECK_FSP(fsp,conn);
5394         CHECK_WRITE(fsp);
5395
5396         tcount = SVAL(inbuf,smb_vwv1);
5397         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5398         numtowrite = SVAL(inbuf,smb_vwv6);
5399         smb_doff = SVAL(inbuf,smb_vwv7);
5400
5401         data = smb_base(inbuf) + smb_doff;
5402
5403         /* We need to send an SMBwriteC response, not an SMBwritebs */
5404         SCVAL(outbuf,smb_com,SMBwritec);
5405
5406         /* This fd should have an auxiliary struct attached,
5407                 check that it does */
5408         wbms = fsp->wbmpx_ptr;
5409         if(!wbms) {
5410                 END_PROFILE(SMBwriteBs);
5411                 return(-1);
5412         }
5413
5414         /* If write through is set we can return errors, else we must cache them */
5415         write_through = wbms->wr_mode;
5416
5417         /* Check for an earlier error */
5418         if(wbms->wr_discard) {
5419                 END_PROFILE(SMBwriteBs);
5420                 return -1; /* Just discard the packet */
5421         }
5422
5423         nwritten = write_file(fsp,data,startpos,numtowrite);
5424
5425         if(lp_syncalways(SNUM(conn)) || write_through)
5426                 sync_file(conn,fsp);
5427   
5428         if (nwritten < (ssize_t)numtowrite) {
5429                 if(write_through) {
5430                         /* We are returning an error - we can delete the aux struct */
5431                         if (wbms)
5432                                 free((char *)wbms);
5433                         fsp->wbmpx_ptr = NULL;
5434                         END_PROFILE(SMBwriteBs);
5435                         return(ERROR_DOS(ERRHRD,ERRdiskfull));
5436                 }
5437                 wbms->wr_errclass = ERRHRD;
5438                 wbms->wr_error = ERRdiskfull;
5439                 wbms->wr_status = NT_STATUS_DISK_FULL;
5440                 wbms->wr_discard = True;
5441                 END_PROFILE(SMBwriteBs);
5442                 return -1;
5443         }
5444
5445         /* Increment the total written, if this matches tcount
5446                 we can discard the auxiliary struct (hurrah !) and return a writeC */
5447         wbms->wr_total_written += nwritten;
5448         if(wbms->wr_total_written >= tcount) {
5449                 if (write_through) {
5450                         outsize = set_message(outbuf,1,0,True);
5451                         SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);    
5452                         send_response = True;
5453                 }
5454
5455                 free((char *)wbms);
5456                 fsp->wbmpx_ptr = NULL;
5457         }
5458
5459         if(send_response) {
5460                 END_PROFILE(SMBwriteBs);
5461                 return(outsize);
5462         }
5463
5464         END_PROFILE(SMBwriteBs);
5465         return(-1);
5466 }
5467
5468 /****************************************************************************
5469  Reply to a SMBgetattrE.
5470 ****************************************************************************/
5471
5472 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5473 {
5474         SMB_STRUCT_STAT sbuf;
5475         int outsize = 0;
5476         int mode;
5477         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5478         START_PROFILE(SMBgetattrE);
5479
5480         outsize = set_message(outbuf,11,0,True);
5481
5482         if(!fsp || (fsp->conn != conn)) {
5483                 END_PROFILE(SMBgetattrE);
5484                 return ERROR_DOS(ERRDOS,ERRbadfid);
5485         }
5486
5487         /* Do an fstat on this file */
5488         if(fsp_stat(fsp, &sbuf)) {
5489                 END_PROFILE(SMBgetattrE);
5490                 return(UNIXERROR(ERRDOS,ERRnoaccess));
5491         }
5492   
5493         mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5494   
5495         /*
5496          * Convert the times into dos times. Set create
5497          * date to be last modify date as UNIX doesn't save
5498          * this.
5499          */
5500
5501         put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5502         put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5503         /* Should we check pending modtime here ? JRA */
5504         put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5505
5506         if (mode & aDIR) {
5507                 SIVAL(outbuf,smb_vwv6,0);
5508                 SIVAL(outbuf,smb_vwv8,0);
5509         } else {
5510                 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
5511                 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5512                 SIVAL(outbuf,smb_vwv8,allocation_size);
5513         }
5514         SSVAL(outbuf,smb_vwv10, mode);
5515   
5516         DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5517   
5518         END_PROFILE(SMBgetattrE);
5519         return(outsize);
5520 }