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