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