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