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