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