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