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