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