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