r23992: Some const
[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(const 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(const 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 (S_ISDIR(pst->st_mode)) {
1867                 return NT_STATUS_OK;
1868         }
1869
1870         if (fsp->access_mask & DELETE_ACCESS) {
1871                 return NT_STATUS_OK;
1872         }
1873
1874         return NT_STATUS_ACCESS_DENIED;
1875 }
1876
1877 /*******************************************************************
1878  * unlink a file with all relevant access checks
1879  *******************************************************************/
1880
1881 static NTSTATUS do_unlink(connection_struct *conn, struct smb_request *req,
1882                           char *fname, uint32 dirtype)
1883 {
1884         SMB_STRUCT_STAT sbuf;
1885         uint32 fattr;
1886         files_struct *fsp;
1887         uint32 dirtype_orig = dirtype;
1888         NTSTATUS status;
1889
1890         DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
1891
1892         if (!CAN_WRITE(conn)) {
1893                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1894         }
1895
1896         if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1897                 return map_nt_error_from_unix(errno);
1898         }
1899
1900         fattr = dos_mode(conn,fname,&sbuf);
1901
1902         if (dirtype & FILE_ATTRIBUTE_NORMAL) {
1903                 dirtype = aDIR|aARCH|aRONLY;
1904         }
1905
1906         dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
1907         if (!dirtype) {
1908                 return NT_STATUS_NO_SUCH_FILE;
1909         }
1910
1911         if (!dir_check_ftype(conn, fattr, dirtype)) {
1912                 if (fattr & aDIR) {
1913                         return NT_STATUS_FILE_IS_A_DIRECTORY;
1914                 }
1915                 return NT_STATUS_NO_SUCH_FILE;
1916         }
1917
1918         if (dirtype_orig & 0x8000) {
1919                 /* These will never be set for POSIX. */
1920                 return NT_STATUS_NO_SUCH_FILE;
1921         }
1922
1923 #if 0
1924         if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
1925                 return NT_STATUS_FILE_IS_A_DIRECTORY;
1926         }
1927
1928         if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
1929                 return NT_STATUS_NO_SUCH_FILE;
1930         }
1931
1932         if (dirtype & 0xFF00) {
1933                 /* These will never be set for POSIX. */
1934                 return NT_STATUS_NO_SUCH_FILE;
1935         }
1936
1937         dirtype &= 0xFF;
1938         if (!dirtype) {
1939                 return NT_STATUS_NO_SUCH_FILE;
1940         }
1941
1942         /* Can't delete a directory. */
1943         if (fattr & aDIR) {
1944                 return NT_STATUS_FILE_IS_A_DIRECTORY;
1945         }
1946 #endif
1947
1948 #if 0 /* JRATEST */
1949         else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1950                 return NT_STATUS_OBJECT_NAME_INVALID;
1951 #endif /* JRATEST */
1952
1953         /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
1954
1955           On a Windows share, a file with read-only dosmode can be opened with
1956           DELETE_ACCESS. But on a Samba share (delete readonly = no), it
1957           fails with NT_STATUS_CANNOT_DELETE error.
1958
1959           This semantic causes a problem that a user can not
1960           rename a file with read-only dosmode on a Samba share
1961           from a Windows command prompt (i.e. cmd.exe, but can rename
1962           from Windows Explorer).
1963         */
1964
1965         if (!lp_delete_readonly(SNUM(conn))) {
1966                 if (fattr & aRONLY) {
1967                         return NT_STATUS_CANNOT_DELETE;
1968                 }
1969         }
1970
1971         /* On open checks the open itself will check the share mode, so
1972            don't do it here as we'll get it wrong. */
1973
1974         status = open_file_ntcreate(conn, req, fname, &sbuf,
1975                                     DELETE_ACCESS,
1976                                     FILE_SHARE_NONE,
1977                                     FILE_OPEN,
1978                                     0,
1979                                     FILE_ATTRIBUTE_NORMAL,
1980                                     req != NULL ? 0 : INTERNAL_OPEN_ONLY,
1981                                     NULL, &fsp);
1982
1983         if (!NT_STATUS_IS_OK(status)) {
1984                 DEBUG(10, ("open_file_ntcreate failed: %s\n",
1985                            nt_errstr(status)));
1986                 return status;
1987         }
1988
1989         /* The set is across all open files on this dev/inode pair. */
1990         if (!set_delete_on_close(fsp, True, &current_user.ut)) {
1991                 close_file(fsp, NORMAL_CLOSE);
1992                 return NT_STATUS_ACCESS_DENIED;
1993         }
1994
1995         return close_file(fsp,NORMAL_CLOSE);
1996 }
1997
1998 /****************************************************************************
1999  The guts of the unlink command, split out so it may be called by the NT SMB
2000  code.
2001 ****************************************************************************/
2002
2003 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2004                           uint32 dirtype, char *name, BOOL has_wild)
2005 {
2006         pstring directory;
2007         pstring mask;
2008         char *p;
2009         int count=0;
2010         NTSTATUS status = NT_STATUS_OK;
2011         SMB_STRUCT_STAT sbuf;
2012         
2013         *directory = *mask = 0;
2014         
2015         status = unix_convert(conn, name, has_wild, NULL, &sbuf);
2016         if (!NT_STATUS_IS_OK(status)) {
2017                 return status;
2018         }
2019         
2020         p = strrchr_m(name,'/');
2021         if (!p) {
2022                 pstrcpy(directory,".");
2023                 pstrcpy(mask,name);
2024         } else {
2025                 *p = 0;
2026                 pstrcpy(directory,name);
2027                 pstrcpy(mask,p+1);
2028         }
2029         
2030         /*
2031          * We should only check the mangled cache
2032          * here if unix_convert failed. This means
2033          * that the path in 'mask' doesn't exist
2034          * on the file system and so we need to look
2035          * for a possible mangle. This patch from
2036          * Tine Smukavec <valentin.smukavec@hermes.si>.
2037          */
2038         
2039         if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params))
2040                 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
2041         
2042         if (!has_wild) {
2043                 pstrcat(directory,"/");
2044                 pstrcat(directory,mask);
2045                 if (dirtype == 0) {
2046                         dirtype = FILE_ATTRIBUTE_NORMAL;
2047                 }
2048
2049                 status = check_name(conn, directory);
2050                 if (!NT_STATUS_IS_OK(status)) {
2051                         return status;
2052                 }
2053
2054                 status = do_unlink(conn, req, directory, dirtype);
2055                 if (!NT_STATUS_IS_OK(status)) {
2056                         return status;
2057                 }
2058
2059                 count++;
2060         } else {
2061                 struct smb_Dir *dir_hnd = NULL;
2062                 long offset = 0;
2063                 const char *dname;
2064                 
2065                 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2066                         return NT_STATUS_OBJECT_NAME_INVALID;
2067                 }
2068
2069                 if (strequal(mask,"????????.???")) {
2070                         pstrcpy(mask,"*");
2071                 }
2072
2073                 status = check_name(conn, directory);
2074                 if (!NT_STATUS_IS_OK(status)) {
2075                         return status;
2076                 }
2077
2078                 dir_hnd = OpenDir(conn, directory, mask, dirtype);
2079                 if (dir_hnd == NULL) {
2080                         return map_nt_error_from_unix(errno);
2081                 }
2082                 
2083                 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2084                    the pattern matches against the long name, otherwise the short name 
2085                    We don't implement this yet XXXX
2086                 */
2087                 
2088                 status = NT_STATUS_NO_SUCH_FILE;
2089
2090                 while ((dname = ReadDirName(dir_hnd, &offset))) {
2091                         SMB_STRUCT_STAT st;
2092                         pstring fname;
2093                         pstrcpy(fname,dname);
2094
2095                         if (!is_visible_file(conn, directory, dname, &st, True)) {
2096                                 continue;
2097                         }
2098
2099                         /* Quick check for "." and ".." */
2100                         if (fname[0] == '.') {
2101                                 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
2102                                         continue;
2103                                 }
2104                         }
2105
2106                         if(!mask_match(fname, mask, conn->case_sensitive)) {
2107                                 continue;
2108                         }
2109                                 
2110                         slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2111
2112                         status = check_name(conn, fname);
2113                         if (!NT_STATUS_IS_OK(status)) {
2114                                 CloseDir(dir_hnd);
2115                                 return status;
2116                         }
2117
2118                         status = do_unlink(conn, req, fname, dirtype);
2119                         if (!NT_STATUS_IS_OK(status)) {
2120                                 continue;
2121                         }
2122
2123                         count++;
2124                         DEBUG(3,("unlink_internals: succesful unlink [%s]\n",
2125                                  fname));
2126                 }
2127                 CloseDir(dir_hnd);
2128         }
2129         
2130         if (count == 0 && NT_STATUS_IS_OK(status)) {
2131                 status = map_nt_error_from_unix(errno);
2132         }
2133
2134         return status;
2135 }
2136
2137 /****************************************************************************
2138  Reply to a unlink
2139 ****************************************************************************/
2140
2141 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, 
2142                  int dum_buffsize)
2143 {
2144         int outsize = 0;
2145         pstring name;
2146         uint32 dirtype;
2147         NTSTATUS status;
2148         BOOL path_contains_wcard = False;
2149         struct smb_request req;
2150
2151         START_PROFILE(SMBunlink);
2152
2153         init_smb_request(&req, (uint8 *)inbuf);
2154
2155         dirtype = SVAL(inbuf,smb_vwv0);
2156         
2157         srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name,
2158                               smb_buf(inbuf) + 1, sizeof(name), 0,
2159                               STR_TERMINATE, &status, &path_contains_wcard);
2160         if (!NT_STATUS_IS_OK(status)) {
2161                 END_PROFILE(SMBunlink);
2162                 return ERROR_NT(status);
2163         }
2164
2165         status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &path_contains_wcard);
2166         if (!NT_STATUS_IS_OK(status)) {
2167                 END_PROFILE(SMBunlink);
2168                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2169                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
2170                 }
2171                 return ERROR_NT(status);
2172         }
2173         
2174         DEBUG(3,("reply_unlink : %s\n",name));
2175         
2176         status = unlink_internals(conn, &req, dirtype, name,
2177                                   path_contains_wcard);
2178         if (!NT_STATUS_IS_OK(status)) {
2179                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
2180                         /* We have re-scheduled this call. */
2181                         return -1;
2182                 }
2183                 return ERROR_NT(status);
2184         }
2185
2186         outsize = set_message(inbuf,outbuf,0,0,False);
2187   
2188         END_PROFILE(SMBunlink);
2189         return outsize;
2190 }
2191
2192 /****************************************************************************
2193  Fail for readbraw.
2194 ****************************************************************************/
2195
2196 static void fail_readraw(void)
2197 {
2198         pstring errstr;
2199         slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2200                 strerror(errno) );
2201         exit_server_cleanly(errstr);
2202 }
2203
2204 /****************************************************************************
2205  Fake (read/write) sendfile. Returns -1 on read or write fail.
2206 ****************************************************************************/
2207
2208 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, size_t bufsize)
2209 {
2210         size_t tosend = nread;
2211
2212         while (tosend > 0) {
2213                 ssize_t ret;
2214                 size_t cur_read;
2215
2216                 if (tosend > bufsize) {
2217                         cur_read = bufsize;
2218                 } else {
2219                         cur_read = tosend;
2220                 }
2221                 ret = read_file(fsp,buf,startpos,cur_read);
2222                 if (ret == -1) {
2223                         return -1;
2224                 }
2225
2226                 /* If we had a short read, fill with zeros. */
2227                 if (ret < cur_read) {
2228                         memset(buf, '\0', cur_read - ret);
2229                 }
2230
2231                 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2232                         return -1;
2233                 }
2234                 tosend -= cur_read;
2235                 startpos += cur_read;
2236         }
2237
2238         return (ssize_t)nread;
2239 }
2240
2241 /****************************************************************************
2242  Use sendfile in readbraw.
2243 ****************************************************************************/
2244
2245 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
2246                 ssize_t mincount, char *outbuf, int out_buffsize)
2247 {
2248         ssize_t ret=0;
2249
2250 #if defined(WITH_SENDFILE)
2251         /*
2252          * We can only use sendfile on a non-chained packet 
2253          * but we can use on a non-oplocked file. tridge proved this
2254          * on a train in Germany :-). JRA.
2255          * reply_readbraw has already checked the length.
2256          */
2257
2258         if ( (chain_size == 0) && (nread > 0) &&
2259             (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2260                 DATA_BLOB header;
2261
2262                 _smb_setlen(outbuf,nread);
2263                 header.data = (uint8 *)outbuf;
2264                 header.length = 4;
2265                 header.free = NULL;
2266
2267                 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) {
2268                         /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2269                         if (errno == ENOSYS) {
2270                                 goto normal_readbraw;
2271                         }
2272
2273                         /*
2274                          * Special hack for broken Linux with no working sendfile. If we
2275                          * return EINTR we sent the header but not the rest of the data.
2276                          * Fake this up by doing read/write calls.
2277                          */
2278                         if (errno == EINTR) {
2279                                 /* Ensure we don't do this again. */
2280                                 set_use_sendfile(SNUM(conn), False);
2281                                 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2282
2283                                 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
2284                                         DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2285                                                 fsp->fsp_name, strerror(errno) ));
2286                                         exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2287                                 }
2288                                 return;
2289                         }
2290
2291                         DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2292                                 fsp->fsp_name, strerror(errno) ));
2293                         exit_server_cleanly("send_file_readbraw sendfile failed");
2294                 }
2295
2296                 return;
2297         }
2298 #endif
2299
2300 normal_readbraw:
2301
2302         if (nread > 0) {
2303                 ret = read_file(fsp,outbuf+4,startpos,nread);
2304 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2305                 if (ret < mincount)
2306                         ret = 0;
2307 #else
2308                 if (ret < nread)
2309                         ret = 0;
2310 #endif
2311         }
2312
2313         _smb_setlen(outbuf,ret);
2314         if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2315                 fail_readraw();
2316 }
2317
2318 /****************************************************************************
2319  Reply to a readbraw (core+ protocol).
2320 ****************************************************************************/
2321
2322 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2323 {
2324         ssize_t maxcount,mincount;
2325         size_t nread = 0;
2326         SMB_OFF_T startpos;
2327         char *header = outbuf;
2328         files_struct *fsp;
2329         START_PROFILE(SMBreadbraw);
2330
2331         if (srv_is_signing_active()) {
2332                 exit_server_cleanly("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2333         }
2334
2335         /*
2336          * Special check if an oplock break has been issued
2337          * and the readraw request croses on the wire, we must
2338          * return a zero length response here.
2339          */
2340
2341         fsp = file_fsp(inbuf,smb_vwv0);
2342
2343         if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2344                 /*
2345                  * fsp could be NULL here so use the value from the packet. JRA.
2346                  */
2347                 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2348                 _smb_setlen(header,0);
2349                 if (write_data(smbd_server_fd(),header,4) != 4)
2350                         fail_readraw();
2351                 END_PROFILE(SMBreadbraw);
2352                 return(-1);
2353         }
2354
2355         CHECK_FSP(fsp,conn);
2356
2357         flush_write_cache(fsp, READRAW_FLUSH);
2358
2359         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2360         if(CVAL(inbuf,smb_wct) == 10) {
2361                 /*
2362                  * This is a large offset (64 bit) read.
2363                  */
2364 #ifdef LARGE_SMB_OFF_T
2365
2366                 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2367
2368 #else /* !LARGE_SMB_OFF_T */
2369
2370                 /*
2371                  * Ensure we haven't been sent a >32 bit offset.
2372                  */
2373
2374                 if(IVAL(inbuf,smb_vwv8) != 0) {
2375                         DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2376 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2377                         _smb_setlen(header,0);
2378                         if (write_data(smbd_server_fd(),header,4) != 4)
2379                                 fail_readraw();
2380                         END_PROFILE(SMBreadbraw);
2381                         return(-1);
2382                 }
2383
2384 #endif /* LARGE_SMB_OFF_T */
2385
2386                 if(startpos < 0) {
2387                         DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2388                         _smb_setlen(header,0);
2389                         if (write_data(smbd_server_fd(),header,4) != 4)
2390                                 fail_readraw();
2391                         END_PROFILE(SMBreadbraw);
2392                         return(-1);
2393                 }      
2394         }
2395         maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2396         mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2397
2398         /* ensure we don't overrun the packet size */
2399         maxcount = MIN(65535,maxcount);
2400
2401         if (!is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2402                 SMB_STRUCT_STAT st;
2403                 SMB_OFF_T size = 0;
2404   
2405                 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2406                         size = st.st_size;
2407                 }
2408
2409                 if (startpos >= size) {
2410                         nread = 0;
2411                 } else {
2412                         nread = MIN(maxcount,(size - startpos));          
2413                 }
2414         }
2415
2416 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2417         if (nread < mincount)
2418                 nread = 0;
2419 #endif
2420   
2421         DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos,
2422                                 (unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) );
2423   
2424         send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2425
2426         DEBUG(5,("readbraw finished\n"));
2427         END_PROFILE(SMBreadbraw);
2428         return -1;
2429 }
2430
2431 #undef DBGC_CLASS
2432 #define DBGC_CLASS DBGC_LOCKING
2433
2434 /****************************************************************************
2435  Reply to a lockread (core+ protocol).
2436 ****************************************************************************/
2437
2438 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2439 {
2440         ssize_t nread = -1;
2441         char *data;
2442         int outsize = 0;
2443         SMB_OFF_T startpos;
2444         size_t numtoread;
2445         NTSTATUS status;
2446         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2447         struct byte_range_lock *br_lck = NULL;
2448         START_PROFILE(SMBlockread);
2449
2450         CHECK_FSP(fsp,conn);
2451         if (!CHECK_READ(fsp,inbuf)) {
2452                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2453         }
2454
2455         release_level_2_oplocks_on_change(fsp);
2456
2457         numtoread = SVAL(inbuf,smb_vwv1);
2458         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2459   
2460         outsize = set_message(inbuf,outbuf,5,3,True);
2461         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2462         data = smb_buf(outbuf) + 3;
2463         
2464         /*
2465          * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2466          * protocol request that predates the read/write lock concept. 
2467          * Thus instead of asking for a read lock here we need to ask
2468          * for a write lock. JRA.
2469          * Note that the requested lock size is unaffected by max_recv.
2470          */
2471         
2472         br_lck = do_lock(smbd_messaging_context(),
2473                         fsp,
2474                         (uint32)SVAL(inbuf,smb_pid), 
2475                         (SMB_BIG_UINT)numtoread,
2476                         (SMB_BIG_UINT)startpos,
2477                         WRITE_LOCK,
2478                         WINDOWS_LOCK,
2479                         False, /* Non-blocking lock. */
2480                         &status,
2481                         NULL);
2482         TALLOC_FREE(br_lck);
2483
2484         if (NT_STATUS_V(status)) {
2485                 END_PROFILE(SMBlockread);
2486                 return ERROR_NT(status);
2487         }
2488
2489         /*
2490          * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2491          */
2492
2493         if (numtoread > max_recv) {
2494                 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2495 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2496                         (unsigned int)numtoread, (unsigned int)max_recv ));
2497                 numtoread = MIN(numtoread,max_recv);
2498         }
2499         nread = read_file(fsp,data,startpos,numtoread);
2500
2501         if (nread < 0) {
2502                 END_PROFILE(SMBlockread);
2503                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2504         }
2505         
2506         outsize += nread;
2507         SSVAL(outbuf,smb_vwv0,nread);
2508         SSVAL(outbuf,smb_vwv5,nread+3);
2509         SSVAL(smb_buf(outbuf),1,nread);
2510         
2511         DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2512                  fsp->fnum, (int)numtoread, (int)nread));
2513
2514         END_PROFILE(SMBlockread);
2515         return(outsize);
2516 }
2517
2518 #undef DBGC_CLASS
2519 #define DBGC_CLASS DBGC_ALL
2520
2521 /****************************************************************************
2522  Reply to a read.
2523 ****************************************************************************/
2524
2525 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2526 {
2527         size_t numtoread;
2528         ssize_t nread = 0;
2529         char *data;
2530         SMB_OFF_T startpos;
2531         int outsize = 0;
2532         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2533         START_PROFILE(SMBread);
2534
2535         CHECK_FSP(fsp,conn);
2536         if (!CHECK_READ(fsp,inbuf)) {
2537                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2538         }
2539
2540         numtoread = SVAL(inbuf,smb_vwv1);
2541         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2542
2543         outsize = set_message(inbuf,outbuf,5,3,True);
2544         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2545         /*
2546          * The requested read size cannot be greater than max_recv. JRA.
2547          */
2548         if (numtoread > max_recv) {
2549                 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2550 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2551                         (unsigned int)numtoread, (unsigned int)max_recv ));
2552                 numtoread = MIN(numtoread,max_recv);
2553         }
2554
2555         data = smb_buf(outbuf) + 3;
2556   
2557         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2558                 END_PROFILE(SMBread);
2559                 return ERROR_DOS(ERRDOS,ERRlock);
2560         }
2561
2562         if (numtoread > 0)
2563                 nread = read_file(fsp,data,startpos,numtoread);
2564
2565         if (nread < 0) {
2566                 END_PROFILE(SMBread);
2567                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2568         }
2569   
2570         outsize += nread;
2571         SSVAL(outbuf,smb_vwv0,nread);
2572         SSVAL(outbuf,smb_vwv5,nread+3);
2573         SCVAL(smb_buf(outbuf),0,1);
2574         SSVAL(smb_buf(outbuf),1,nread);
2575   
2576         DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2577                 fsp->fnum, (int)numtoread, (int)nread ) );
2578
2579         END_PROFILE(SMBread);
2580         return(outsize);
2581 }
2582
2583 /****************************************************************************
2584  Setup readX header.
2585 ****************************************************************************/
2586
2587 static int setup_readX_header(char *inbuf, char *outbuf, size_t smb_maxcnt)
2588 {
2589         int outsize;
2590         char *data = smb_buf(outbuf);
2591
2592         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2593         SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2594         SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2595         SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
2596         SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2597         SCVAL(outbuf,smb_vwv0,0xFF);
2598         outsize = set_message(inbuf, outbuf,12,smb_maxcnt,False);
2599         /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
2600         _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
2601         return outsize;
2602 }
2603
2604 /****************************************************************************
2605  Reply to a read and X - possibly using sendfile.
2606 ****************************************************************************/
2607
2608 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2609                 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2610 {
2611         SMB_STRUCT_STAT sbuf;
2612         int outsize = 0;
2613         ssize_t nread = -1;
2614         char *data = smb_buf(outbuf);
2615
2616         if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
2617                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2618         }
2619
2620         if (startpos > sbuf.st_size) {
2621                 smb_maxcnt = 0;
2622         } else if (smb_maxcnt > (sbuf.st_size - startpos)) {
2623                 smb_maxcnt = (sbuf.st_size - startpos);
2624         }
2625
2626         if (smb_maxcnt == 0) {
2627                 goto normal_read;
2628         }
2629
2630 #if defined(WITH_SENDFILE)
2631         /*
2632          * We can only use sendfile on a non-chained packet 
2633          * but we can use on a non-oplocked file. tridge proved this
2634          * on a train in Germany :-). JRA.
2635          */
2636
2637         if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
2638             lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
2639                 DATA_BLOB header;
2640
2641                 /* 
2642                  * Set up the packet header before send. We
2643                  * assume here the sendfile will work (get the
2644                  * correct amount of data).
2645                  */
2646
2647                 setup_readX_header(inbuf,outbuf,smb_maxcnt);
2648                 set_message(inbuf,outbuf,12,smb_maxcnt,False);
2649                 header.data = (uint8 *)outbuf;
2650                 header.length = data - outbuf;
2651                 header.free = NULL;
2652
2653                 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
2654                         /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2655                         if (errno == ENOSYS) {
2656                                 goto normal_read;
2657                         }
2658
2659                         /*
2660                          * Special hack for broken Linux with no working sendfile. If we
2661                          * return EINTR we sent the header but not the rest of the data.
2662                          * Fake this up by doing read/write calls.
2663                          */
2664
2665                         if (errno == EINTR) {
2666                                 /* Ensure we don't do this again. */
2667                                 set_use_sendfile(SNUM(conn), False);
2668                                 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2669
2670                                 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2671                                                         len_outbuf - (data-outbuf))) == -1) {
2672                                         DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2673                                                 fsp->fsp_name, strerror(errno) ));
2674                                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
2675                                 }
2676                                 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2677                                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2678                                 /* Returning -1 here means successful sendfile. */
2679                                 return -1;
2680                         }
2681
2682                         DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2683                                 fsp->fsp_name, strerror(errno) ));
2684                         exit_server_cleanly("send_file_readX sendfile failed");
2685                 }
2686
2687                 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2688                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2689                 /* Returning -1 here means successful sendfile. */
2690                 return -1;
2691         }
2692
2693 #endif
2694
2695 normal_read:
2696
2697         if ((smb_maxcnt & 0xFF0000) > 0x10000) {
2698                 int sendlen = setup_readX_header(inbuf,outbuf,smb_maxcnt) - smb_maxcnt;
2699                 /* Send out the header. */
2700                 if (write_data(smbd_server_fd(),outbuf,sendlen) != sendlen) {
2701                         DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
2702                                 fsp->fsp_name, strerror(errno) ));
2703                         exit_server_cleanly("send_file_readX sendfile failed");
2704                 }
2705                 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2706                                         len_outbuf - (data-outbuf))) == -1) {
2707                         DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2708                                 fsp->fsp_name, strerror(errno) ));
2709                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
2710                 }
2711                 return -1;
2712         } else {
2713                 nread = read_file(fsp,data,startpos,smb_maxcnt);
2714
2715                 if (nread < 0) {
2716                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2717                 }
2718
2719                 outsize = setup_readX_header(inbuf, outbuf,nread);
2720
2721                 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2722                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2723
2724                 /* Returning the number of bytes we want to send back - including header. */
2725                 return outsize;
2726         }
2727 }
2728
2729 /****************************************************************************
2730  Reply to a read and X.
2731 ****************************************************************************/
2732
2733 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2734 {
2735         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2736         SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2737         ssize_t nread = -1;
2738         size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2739         BOOL big_readX = False;
2740 #if 0
2741         size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2742 #endif
2743
2744         START_PROFILE(SMBreadX);
2745
2746         /* If it's an IPC, pass off the pipe handler. */
2747         if (IS_IPC(conn)) {
2748                 END_PROFILE(SMBreadX);
2749                 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2750         }
2751
2752         CHECK_FSP(fsp,conn);
2753         if (!CHECK_READ(fsp,inbuf)) {
2754                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2755         }
2756
2757         set_message(inbuf,outbuf,12,0,True);
2758
2759         if (global_client_caps & CAP_LARGE_READX) {
2760                 size_t upper_size = SVAL(inbuf,smb_vwv7);
2761                 smb_maxcnt |= (upper_size<<16);
2762                 if (upper_size > 1) {
2763                         /* Can't do this on a chained packet. */
2764                         if ((CVAL(inbuf,smb_vwv0) != 0xFF)) {
2765                                 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
2766                         }
2767                         /* We currently don't do this on signed or sealed data. */
2768                         if (srv_is_signing_active() || srv_encryption_on()) {
2769                                 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
2770                         }
2771                         /* Is there room in the reply for this data ? */
2772                         if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2)))  {
2773                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2774                         }
2775                         big_readX = True;
2776                 }
2777         }
2778
2779         if(CVAL(inbuf,smb_wct) == 12) {
2780 #ifdef LARGE_SMB_OFF_T
2781                 /*
2782                  * This is a large offset (64 bit) read.
2783                  */
2784                 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2785
2786 #else /* !LARGE_SMB_OFF_T */
2787
2788                 /*
2789                  * Ensure we haven't been sent a >32 bit offset.
2790                  */
2791
2792                 if(IVAL(inbuf,smb_vwv10) != 0) {
2793                         DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2794 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2795                         END_PROFILE(SMBreadX);
2796                         return ERROR_DOS(ERRDOS,ERRbadaccess);
2797                 }
2798
2799 #endif /* LARGE_SMB_OFF_T */
2800
2801         }
2802
2803         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2804                 END_PROFILE(SMBreadX);
2805                 return ERROR_DOS(ERRDOS,ERRlock);
2806         }
2807
2808         if (!big_readX && schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
2809                 END_PROFILE(SMBreadX);
2810                 return -1;
2811         }
2812
2813         nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2814         /* Only call chain_reply if not an error. */
2815         if (nread != -1 && SVAL(outbuf,smb_rcls) == 0) {
2816                 nread = chain_reply(inbuf,outbuf,length,bufsize);
2817         }
2818
2819         END_PROFILE(SMBreadX);
2820         return nread;
2821 }
2822
2823 /****************************************************************************
2824  Reply to a writebraw (core+ or LANMAN1.0 protocol).
2825 ****************************************************************************/
2826
2827 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2828 {
2829         ssize_t nwritten=0;
2830         ssize_t total_written=0;
2831         size_t numtowrite=0;
2832         size_t tcount;
2833         SMB_OFF_T startpos;
2834         char *data=NULL;
2835         BOOL write_through;
2836         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2837         int outsize = 0;
2838         NTSTATUS status;
2839         START_PROFILE(SMBwritebraw);
2840
2841         if (srv_is_signing_active()) {
2842                 exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2843         }
2844
2845         CHECK_FSP(fsp,conn);
2846         if (!CHECK_WRITE(fsp)) {
2847                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2848         }
2849   
2850         tcount = IVAL(inbuf,smb_vwv1);
2851         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2852         write_through = BITSETW(inbuf+smb_vwv7,0);
2853
2854         /* We have to deal with slightly different formats depending
2855                 on whether we are using the core+ or lanman1.0 protocol */
2856
2857         if(Protocol <= PROTOCOL_COREPLUS) {
2858                 numtowrite = SVAL(smb_buf(inbuf),-2);
2859                 data = smb_buf(inbuf);
2860         } else {
2861                 numtowrite = SVAL(inbuf,smb_vwv10);
2862                 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2863         }
2864
2865         /* force the error type */
2866         SCVAL(inbuf,smb_com,SMBwritec);
2867         SCVAL(outbuf,smb_com,SMBwritec);
2868
2869         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2870                 END_PROFILE(SMBwritebraw);
2871                 return(ERROR_DOS(ERRDOS,ERRlock));
2872         }
2873
2874         if (numtowrite>0)
2875                 nwritten = write_file(fsp,data,startpos,numtowrite);
2876   
2877         DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2878                 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2879
2880         if (nwritten < (ssize_t)numtowrite)  {
2881                 END_PROFILE(SMBwritebraw);
2882                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2883         }
2884
2885         total_written = nwritten;
2886
2887         /* Return a message to the redirector to tell it to send more bytes */
2888         SCVAL(outbuf,smb_com,SMBwritebraw);
2889         SSVALS(outbuf,smb_vwv0,-1);
2890         outsize = set_message(inbuf,outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2891         show_msg(outbuf);
2892         if (!send_smb(smbd_server_fd(),outbuf))
2893                 exit_server_cleanly("reply_writebraw: send_smb failed.");
2894   
2895         /* Now read the raw data into the buffer and write it */
2896         if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2897                 exit_server_cleanly("secondary writebraw failed");
2898         }
2899   
2900         /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2901         numtowrite = smb_len(inbuf);
2902
2903         /* Set up outbuf to return the correct return */
2904         outsize = set_message(inbuf,outbuf,1,0,True);
2905         SCVAL(outbuf,smb_com,SMBwritec);
2906
2907         if (numtowrite != 0) {
2908
2909                 if (numtowrite > BUFFER_SIZE) {
2910                         DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2911                                 (unsigned int)numtowrite ));
2912                         exit_server_cleanly("secondary writebraw failed");
2913                 }
2914
2915                 if (tcount > nwritten+numtowrite) {
2916                         DEBUG(3,("Client overestimated the write %d %d %d\n",
2917                                 (int)tcount,(int)nwritten,(int)numtowrite));
2918                 }
2919
2920                 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2921                         DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2922                                 strerror(errno) ));
2923                         exit_server_cleanly("secondary writebraw failed");
2924                 }
2925
2926                 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2927                 if (nwritten == -1) {
2928                         END_PROFILE(SMBwritebraw);
2929                         return(UNIXERROR(ERRHRD,ERRdiskfull));
2930                 }
2931
2932                 if (nwritten < (ssize_t)numtowrite) {
2933                         SCVAL(outbuf,smb_rcls,ERRHRD);
2934                         SSVAL(outbuf,smb_err,ERRdiskfull);      
2935                 }
2936
2937                 if (nwritten > 0)
2938                         total_written += nwritten;
2939         }
2940  
2941         SSVAL(outbuf,smb_vwv0,total_written);
2942
2943         status = sync_file(conn, fsp, write_through);
2944         if (!NT_STATUS_IS_OK(status)) {
2945                 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
2946                         fsp->fsp_name, nt_errstr(status) ));
2947                 END_PROFILE(SMBwritebraw);
2948                 return ERROR_NT(status);
2949         }
2950
2951         DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2952                 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2953
2954         /* we won't return a status if write through is not selected - this follows what WfWg does */
2955         END_PROFILE(SMBwritebraw);
2956         if (!write_through && total_written==tcount) {
2957
2958 #if RABBIT_PELLET_FIX
2959                 /*
2960                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2961                  * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2962                  */
2963                 if (!send_keepalive(smbd_server_fd()))
2964                         exit_server_cleanly("reply_writebraw: send of keepalive failed");
2965 #endif
2966                 return(-1);
2967         }
2968
2969         return(outsize);
2970 }
2971
2972 #undef DBGC_CLASS
2973 #define DBGC_CLASS DBGC_LOCKING
2974
2975 /****************************************************************************
2976  Reply to a writeunlock (core+).
2977 ****************************************************************************/
2978
2979 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, 
2980                       int size, int dum_buffsize)
2981 {
2982         ssize_t nwritten = -1;
2983         size_t numtowrite;
2984         SMB_OFF_T startpos;
2985         char *data;
2986         NTSTATUS status = NT_STATUS_OK;
2987         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2988         int outsize = 0;
2989         START_PROFILE(SMBwriteunlock);
2990         
2991         CHECK_FSP(fsp,conn);
2992         if (!CHECK_WRITE(fsp)) {
2993                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2994         }
2995
2996         numtowrite = SVAL(inbuf,smb_vwv1);
2997         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2998         data = smb_buf(inbuf) + 3;
2999   
3000         if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3001                 END_PROFILE(SMBwriteunlock);
3002                 return ERROR_DOS(ERRDOS,ERRlock);
3003         }
3004
3005         /* The special X/Open SMB protocol handling of
3006            zero length writes is *NOT* done for
3007            this call */
3008         if(numtowrite == 0) {
3009                 nwritten = 0;
3010         } else {
3011                 nwritten = write_file(fsp,data,startpos,numtowrite);
3012         }
3013   
3014         status = sync_file(conn, fsp, False /* write through */);
3015         if (!NT_STATUS_IS_OK(status)) {
3016                 END_PROFILE(SMBwriteunlock);
3017                 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3018                         fsp->fsp_name, nt_errstr(status) ));
3019                 return ERROR_NT(status);
3020         }
3021
3022         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3023                 END_PROFILE(SMBwriteunlock);
3024                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3025         }
3026
3027         if (numtowrite) {
3028                 status = do_unlock(smbd_messaging_context(),
3029                                 fsp,
3030                                 (uint32)SVAL(inbuf,smb_pid),
3031                                 (SMB_BIG_UINT)numtowrite, 
3032                                 (SMB_BIG_UINT)startpos,
3033                                 WINDOWS_LOCK);
3034
3035                 if (NT_STATUS_V(status)) {
3036                         END_PROFILE(SMBwriteunlock);
3037                         return ERROR_NT(status);
3038                 }
3039         }
3040         
3041         outsize = set_message(inbuf,outbuf,1,0,True);
3042         
3043         SSVAL(outbuf,smb_vwv0,nwritten);
3044         
3045         DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3046                  fsp->fnum, (int)numtowrite, (int)nwritten));
3047         
3048         END_PROFILE(SMBwriteunlock);
3049         return outsize;
3050 }
3051
3052 #undef DBGC_CLASS
3053 #define DBGC_CLASS DBGC_ALL
3054
3055 /****************************************************************************
3056  Reply to a write.
3057 ****************************************************************************/
3058
3059 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
3060 {
3061         size_t numtowrite;
3062         ssize_t nwritten = -1;
3063         SMB_OFF_T startpos;
3064         char *data;
3065         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3066         int outsize = 0;
3067         NTSTATUS status;
3068         START_PROFILE(SMBwrite);
3069
3070         /* If it's an IPC, pass off the pipe handler. */
3071         if (IS_IPC(conn)) {
3072                 END_PROFILE(SMBwrite);
3073                 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
3074         }
3075
3076         CHECK_FSP(fsp,conn);
3077         if (!CHECK_WRITE(fsp)) {
3078                 END_PROFILE(SMBwrite);
3079                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3080         }
3081
3082         numtowrite = SVAL(inbuf,smb_vwv1);
3083         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3084         data = smb_buf(inbuf) + 3;
3085   
3086         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3087                 END_PROFILE(SMBwrite);
3088                 return ERROR_DOS(ERRDOS,ERRlock);
3089         }
3090
3091         /*
3092          * X/Open SMB protocol says that if smb_vwv1 is
3093          * zero then the file size should be extended or
3094          * truncated to the size given in smb_vwv[2-3].
3095          */
3096
3097         if(numtowrite == 0) {
3098                 /*
3099                  * This is actually an allocate call, and set EOF. JRA.
3100                  */
3101                 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3102                 if (nwritten < 0) {
3103                         END_PROFILE(SMBwrite);
3104                         return ERROR_NT(NT_STATUS_DISK_FULL);
3105                 }
3106                 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3107                 if (nwritten < 0) {
3108                         END_PROFILE(SMBwrite);
3109                         return ERROR_NT(NT_STATUS_DISK_FULL);
3110                 }
3111         } else
3112                 nwritten = write_file(fsp,data,startpos,numtowrite);
3113   
3114         status = sync_file(conn, fsp, False);
3115         if (!NT_STATUS_IS_OK(status)) {
3116                 END_PROFILE(SMBwrite);
3117                 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3118                         fsp->fsp_name, nt_errstr(status) ));
3119                 return ERROR_NT(status);
3120         }
3121
3122         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3123                 END_PROFILE(SMBwrite);
3124                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3125         }
3126
3127         outsize = set_message(inbuf,outbuf,1,0,True);
3128   
3129         SSVAL(outbuf,smb_vwv0,nwritten);
3130
3131         if (nwritten < (ssize_t)numtowrite) {
3132                 SCVAL(outbuf,smb_rcls,ERRHRD);
3133                 SSVAL(outbuf,smb_err,ERRdiskfull);      
3134         }
3135   
3136         DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3137
3138         END_PROFILE(SMBwrite);
3139         return(outsize);
3140 }
3141
3142 /****************************************************************************
3143  Reply to a write and X.
3144 ****************************************************************************/
3145
3146 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3147 {
3148         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3149         SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
3150         size_t numtowrite = SVAL(inbuf,smb_vwv10);
3151         BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
3152         ssize_t nwritten = -1;
3153         unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
3154         unsigned int smblen = smb_len(inbuf);
3155         char *data;
3156         BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
3157         NTSTATUS status;
3158         START_PROFILE(SMBwriteX);
3159
3160         /* If it's an IPC, pass off the pipe handler. */
3161         if (IS_IPC(conn)) {
3162                 END_PROFILE(SMBwriteX);
3163                 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
3164         }
3165
3166         CHECK_FSP(fsp,conn);
3167         if (!CHECK_WRITE(fsp)) {
3168                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3169         }
3170
3171         set_message(inbuf,outbuf,6,0,True);
3172   
3173         /* Deal with possible LARGE_WRITEX */
3174         if (large_writeX) {
3175                 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
3176         }
3177
3178         if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
3179                 END_PROFILE(SMBwriteX);
3180                 return ERROR_DOS(ERRDOS,ERRbadmem);
3181         }
3182
3183         data = smb_base(inbuf) + smb_doff;
3184
3185         if(CVAL(inbuf,smb_wct) == 14) {
3186 #ifdef LARGE_SMB_OFF_T
3187                 /*
3188                  * This is a large offset (64 bit) write.
3189                  */
3190                 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
3191
3192 #else /* !LARGE_SMB_OFF_T */
3193
3194                 /*
3195                  * Ensure we haven't been sent a >32 bit offset.
3196                  */
3197
3198                 if(IVAL(inbuf,smb_vwv12) != 0) {
3199                         DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
3200 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
3201                         END_PROFILE(SMBwriteX);
3202                         return ERROR_DOS(ERRDOS,ERRbadaccess);
3203                 }
3204
3205 #endif /* LARGE_SMB_OFF_T */
3206         }
3207
3208         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3209                 END_PROFILE(SMBwriteX);
3210                 return ERROR_DOS(ERRDOS,ERRlock);
3211         }
3212
3213         /* X/Open SMB protocol says that, unlike SMBwrite
3214         if the length is zero then NO truncation is
3215         done, just a write of zero. To truncate a file,
3216         use SMBwrite. */
3217
3218         if(numtowrite == 0) {
3219                 nwritten = 0;
3220         } else {
3221
3222                 if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize,
3223                                         fsp,data,startpos,numtowrite)) {
3224                         END_PROFILE(SMBwriteX);
3225                         return -1;
3226                 }
3227
3228                 nwritten = write_file(fsp,data,startpos,numtowrite);
3229         }
3230   
3231         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3232                 END_PROFILE(SMBwriteX);
3233                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3234         }
3235
3236         SSVAL(outbuf,smb_vwv2,nwritten);
3237         if (large_writeX)
3238                 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
3239
3240         if (nwritten < (ssize_t)numtowrite) {
3241                 SCVAL(outbuf,smb_rcls,ERRHRD);
3242                 SSVAL(outbuf,smb_err,ERRdiskfull);      
3243         }
3244
3245         DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
3246                 fsp->fnum, (int)numtowrite, (int)nwritten));
3247
3248         status = sync_file(conn, fsp, write_through);
3249         if (!NT_STATUS_IS_OK(status)) {
3250                 END_PROFILE(SMBwriteX);
3251                 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
3252                         fsp->fsp_name, nt_errstr(status) ));
3253                 return ERROR_NT(status);
3254         }
3255
3256         END_PROFILE(SMBwriteX);
3257         return chain_reply(inbuf,outbuf,length,bufsize);
3258 }
3259
3260 /****************************************************************************
3261  Reply to a lseek.
3262 ****************************************************************************/
3263
3264 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3265 {
3266         SMB_OFF_T startpos;
3267         SMB_OFF_T res= -1;
3268         int mode,umode;
3269         int outsize = 0;
3270         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3271         START_PROFILE(SMBlseek);
3272
3273         CHECK_FSP(fsp,conn);
3274
3275         flush_write_cache(fsp, SEEK_FLUSH);
3276
3277         mode = SVAL(inbuf,smb_vwv1) & 3;
3278         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3279         startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
3280
3281         switch (mode) {
3282                 case 0:
3283                         umode = SEEK_SET;
3284                         res = startpos;
3285                         break;
3286                 case 1:
3287                         umode = SEEK_CUR;
3288                         res = fsp->fh->pos + startpos;
3289                         break;
3290                 case 2:
3291                         umode = SEEK_END;
3292                         break;
3293                 default:
3294                         umode = SEEK_SET;
3295                         res = startpos;
3296                         break;
3297         }
3298
3299         if (umode == SEEK_END) {
3300                 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
3301                         if(errno == EINVAL) {
3302                                 SMB_OFF_T current_pos = startpos;
3303                                 SMB_STRUCT_STAT sbuf;
3304
3305                                 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3306                                         END_PROFILE(SMBlseek);
3307                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3308                                 }
3309
3310                                 current_pos += sbuf.st_size;
3311                                 if(current_pos < 0)
3312                                         res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
3313                         }
3314                 }
3315
3316                 if(res == -1) {
3317                         END_PROFILE(SMBlseek);
3318                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3319                 }
3320         }
3321
3322         fsp->fh->pos = res;
3323   
3324         outsize = set_message(inbuf,outbuf,2,0,True);
3325         SIVAL(outbuf,smb_vwv0,res);
3326   
3327         DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3328                 fsp->fnum, (double)startpos, (double)res, mode));
3329
3330         END_PROFILE(SMBlseek);
3331         return(outsize);
3332 }
3333
3334 /****************************************************************************
3335  Reply to a flush.
3336 ****************************************************************************/
3337
3338 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3339 {
3340         int outsize = set_message(inbuf,outbuf,0,0,False);
3341         uint16 fnum = SVAL(inbuf,smb_vwv0);
3342         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3343         START_PROFILE(SMBflush);
3344
3345         if (fnum != 0xFFFF)
3346                 CHECK_FSP(fsp,conn);
3347         
3348         if (!fsp) {
3349                 file_sync_all(conn);
3350         } else {
3351                 NTSTATUS status = sync_file(conn, fsp, True);
3352                 if (!NT_STATUS_IS_OK(status)) {
3353                         END_PROFILE(SMBflush);
3354                         DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
3355                                 fsp->fsp_name, nt_errstr(status) ));
3356                         return ERROR_NT(status);
3357                 }
3358         }
3359         
3360         DEBUG(3,("flush\n"));
3361         END_PROFILE(SMBflush);
3362         return(outsize);
3363 }
3364
3365 /****************************************************************************
3366  Reply to a exit.
3367  conn POINTER CAN BE NULL HERE !
3368 ****************************************************************************/
3369
3370 int reply_exit(connection_struct *conn, 
3371                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3372 {
3373         int outsize;
3374         START_PROFILE(SMBexit);
3375
3376         file_close_pid(SVAL(inbuf,smb_pid),SVAL(inbuf,smb_uid));
3377
3378         outsize = set_message(inbuf,outbuf,0,0,False);
3379
3380         DEBUG(3,("exit\n"));
3381
3382         END_PROFILE(SMBexit);
3383         return(outsize);
3384 }
3385
3386 /****************************************************************************
3387  Reply to a close - has to deal with closing a directory opened by NT SMB's.
3388 ****************************************************************************/
3389
3390 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
3391                 int dum_buffsize)
3392 {
3393         NTSTATUS status = NT_STATUS_OK;
3394         int outsize = 0;
3395         files_struct *fsp = NULL;
3396         START_PROFILE(SMBclose);
3397
3398         outsize = set_message(inbuf,outbuf,0,0,False);
3399
3400         /* If it's an IPC, pass off to the pipe handler. */
3401         if (IS_IPC(conn)) {
3402                 END_PROFILE(SMBclose);
3403                 return reply_pipe_close(conn, inbuf,outbuf);
3404         }
3405
3406         fsp = file_fsp(inbuf,smb_vwv0);
3407
3408         /*
3409          * We can only use CHECK_FSP if we know it's not a directory.
3410          */
3411
3412         if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3413                 END_PROFILE(SMBclose);
3414                 return ERROR_DOS(ERRDOS,ERRbadfid);
3415         }
3416
3417         if(fsp->is_directory) {
3418                 /*
3419                  * Special case - close NT SMB directory handle.
3420                  */
3421                 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
3422                 status = close_file(fsp,NORMAL_CLOSE);
3423         } else {
3424                 /*
3425                  * Close ordinary file.
3426                  */
3427
3428                 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3429                          fsp->fh->fd, fsp->fnum,
3430                          conn->num_files_open));
3431  
3432                 /*
3433                  * Take care of any time sent in the close.
3434                  */
3435
3436                 fsp_set_pending_modtime(fsp,
3437                                 convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv1)));
3438
3439                 /*
3440                  * close_file() returns the unix errno if an error
3441                  * was detected on close - normally this is due to
3442                  * a disk full error. If not then it was probably an I/O error.
3443                  */
3444  
3445                 status = close_file(fsp,NORMAL_CLOSE);
3446         }  
3447
3448         if(!NT_STATUS_IS_OK(status)) {
3449                 END_PROFILE(SMBclose);
3450                 return ERROR_NT(status);
3451         }
3452
3453         END_PROFILE(SMBclose);
3454         return(outsize);
3455 }
3456
3457 /****************************************************************************
3458  Reply to a writeclose (Core+ protocol).
3459 ****************************************************************************/
3460
3461 int reply_writeclose(connection_struct *conn,
3462                      char *inbuf,char *outbuf, int size, int dum_buffsize)
3463 {
3464         size_t numtowrite;
3465         ssize_t nwritten = -1;
3466         int outsize = 0;
3467         NTSTATUS close_status = NT_STATUS_OK;
3468         SMB_OFF_T startpos;
3469         char *data;
3470         struct timespec mtime;
3471         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3472         START_PROFILE(SMBwriteclose);
3473
3474         CHECK_FSP(fsp,conn);
3475         if (!CHECK_WRITE(fsp)) {
3476                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3477         }
3478
3479         numtowrite = SVAL(inbuf,smb_vwv1);
3480         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3481         mtime = convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv4));
3482         data = smb_buf(inbuf) + 1;
3483   
3484         if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3485                 END_PROFILE(SMBwriteclose);
3486                 return ERROR_DOS(ERRDOS,ERRlock);
3487         }
3488   
3489         nwritten = write_file(fsp,data,startpos,numtowrite);
3490
3491         set_filetime(conn, fsp->fsp_name, mtime);
3492   
3493         /*
3494          * More insanity. W2K only closes the file if writelen > 0.
3495          * JRA.
3496          */
3497
3498         if (numtowrite) {
3499                 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3500                         fsp->fsp_name ));
3501                 close_status = close_file(fsp,NORMAL_CLOSE);
3502         }
3503
3504         DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3505                  fsp->fnum, (int)numtowrite, (int)nwritten,
3506                  conn->num_files_open));
3507   
3508         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3509                 END_PROFILE(SMBwriteclose);
3510                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3511         }
3512  
3513         if(!NT_STATUS_IS_OK(close_status)) {
3514                 END_PROFILE(SMBwriteclose);
3515                 return ERROR_NT(close_status);
3516         }
3517  
3518         outsize = set_message(inbuf,outbuf,1,0,True);
3519   
3520         SSVAL(outbuf,smb_vwv0,nwritten);
3521         END_PROFILE(SMBwriteclose);
3522         return(outsize);
3523 }
3524
3525 #undef DBGC_CLASS
3526 #define DBGC_CLASS DBGC_LOCKING
3527
3528 /****************************************************************************
3529  Reply to a lock.
3530 ****************************************************************************/
3531
3532 int reply_lock(connection_struct *conn,
3533                char *inbuf,char *outbuf, int length, int dum_buffsize)
3534 {
3535         int outsize = set_message(inbuf,outbuf,0,0,False);
3536         SMB_BIG_UINT count,offset;
3537         NTSTATUS status;
3538         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3539         struct byte_range_lock *br_lck = NULL;
3540
3541         START_PROFILE(SMBlock);
3542
3543         CHECK_FSP(fsp,conn);
3544
3545         release_level_2_oplocks_on_change(fsp);
3546
3547         count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3548         offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3549
3550         DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3551                  fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
3552
3553         br_lck = do_lock(smbd_messaging_context(),
3554                         fsp,
3555                         (uint32)SVAL(inbuf,smb_pid),
3556                         count,
3557                         offset,
3558                         WRITE_LOCK,
3559                         WINDOWS_LOCK,
3560                         False, /* Non-blocking lock. */
3561                         &status,
3562                         NULL);
3563
3564         TALLOC_FREE(br_lck);
3565
3566         if (NT_STATUS_V(status)) {
3567                 END_PROFILE(SMBlock);
3568                 return ERROR_NT(status);
3569         }
3570
3571         END_PROFILE(SMBlock);
3572         return(outsize);
3573 }
3574
3575 /****************************************************************************
3576  Reply to a unlock.
3577 ****************************************************************************/
3578
3579 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, 
3580                  int dum_buffsize)
3581 {
3582         int outsize = set_message(inbuf,outbuf,0,0,False);
3583         SMB_BIG_UINT count,offset;
3584         NTSTATUS status;
3585         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3586         START_PROFILE(SMBunlock);
3587
3588         CHECK_FSP(fsp,conn);
3589         
3590         count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3591         offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3592         
3593         status = do_unlock(smbd_messaging_context(),
3594                         fsp,
3595                         (uint32)SVAL(inbuf,smb_pid),
3596                         count,
3597                         offset,
3598                         WINDOWS_LOCK);
3599
3600         if (NT_STATUS_V(status)) {
3601                 END_PROFILE(SMBunlock);
3602                 return ERROR_NT(status);
3603         }
3604
3605         DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3606                     fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
3607         
3608         END_PROFILE(SMBunlock);
3609         return(outsize);
3610 }
3611
3612 #undef DBGC_CLASS
3613 #define DBGC_CLASS DBGC_ALL
3614
3615 /****************************************************************************
3616  Reply to a tdis.
3617  conn POINTER CAN BE NULL HERE !
3618 ****************************************************************************/
3619
3620 int reply_tdis(connection_struct *conn, 
3621                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3622 {
3623         int outsize = set_message(inbuf,outbuf,0,0,False);
3624         uint16 vuid;
3625         START_PROFILE(SMBtdis);
3626
3627         vuid = SVAL(inbuf,smb_uid);
3628
3629         if (!conn) {
3630                 DEBUG(4,("Invalid connection in tdis\n"));
3631                 END_PROFILE(SMBtdis);
3632                 return ERROR_DOS(ERRSRV,ERRinvnid);
3633         }
3634
3635         conn->used = False;
3636
3637         close_cnum(conn,vuid);
3638   
3639         END_PROFILE(SMBtdis);
3640         return outsize;
3641 }
3642
3643 /****************************************************************************
3644  Reply to a echo.
3645  conn POINTER CAN BE NULL HERE !
3646 ****************************************************************************/
3647
3648 int reply_echo(connection_struct *conn,
3649                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3650 {
3651         int smb_reverb = SVAL(inbuf,smb_vwv0);
3652         int seq_num;
3653         unsigned int data_len = smb_buflen(inbuf);
3654         int outsize = set_message(inbuf,outbuf,1,data_len,True);
3655         START_PROFILE(SMBecho);
3656
3657         if (data_len > BUFFER_SIZE) {
3658                 DEBUG(0,("reply_echo: data_len too large.\n"));
3659                 END_PROFILE(SMBecho);
3660                 return -1;
3661         }
3662
3663         /* copy any incoming data back out */
3664         if (data_len > 0)
3665                 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3666
3667         if (smb_reverb > 100) {
3668                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3669                 smb_reverb = 100;
3670         }
3671
3672         for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3673                 SSVAL(outbuf,smb_vwv0,seq_num);
3674
3675                 smb_setlen(inbuf,outbuf,outsize - 4);
3676
3677                 show_msg(outbuf);
3678                 if (!send_smb(smbd_server_fd(),outbuf))
3679                         exit_server_cleanly("reply_echo: send_smb failed.");
3680         }
3681
3682         DEBUG(3,("echo %d times\n", smb_reverb));
3683
3684         smb_echo_count++;
3685
3686         END_PROFILE(SMBecho);
3687         return -1;
3688 }
3689
3690 /****************************************************************************
3691  Reply to a printopen.
3692 ****************************************************************************/
3693
3694 int reply_printopen(connection_struct *conn, 
3695                     char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3696 {
3697         int outsize = 0;
3698         files_struct *fsp;
3699         NTSTATUS status;
3700         
3701         START_PROFILE(SMBsplopen);
3702         
3703         if (!CAN_PRINT(conn)) {
3704                 END_PROFILE(SMBsplopen);
3705                 return ERROR_DOS(ERRDOS,ERRnoaccess);
3706         }
3707
3708         /* Open for exclusive use, write only. */
3709         status = print_fsp_open(conn, NULL, &fsp);
3710
3711         if (!NT_STATUS_IS_OK(status)) {
3712                 END_PROFILE(SMBsplopen);
3713                 return(ERROR_NT(status));
3714         }
3715
3716         outsize = set_message(inbuf,outbuf,1,0,True);
3717         SSVAL(outbuf,smb_vwv0,fsp->fnum);
3718   
3719         DEBUG(3,("openprint fd=%d fnum=%d\n",
3720                  fsp->fh->fd, fsp->fnum));
3721
3722         END_PROFILE(SMBsplopen);
3723         return(outsize);
3724 }
3725
3726 /****************************************************************************
3727  Reply to a printclose.
3728 ****************************************************************************/
3729
3730 int reply_printclose(connection_struct *conn,
3731                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3732 {
3733         int outsize = set_message(inbuf,outbuf,0,0,False);
3734         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3735         NTSTATUS status;
3736         START_PROFILE(SMBsplclose);
3737
3738         CHECK_FSP(fsp,conn);
3739
3740         if (!CAN_PRINT(conn)) {
3741                 END_PROFILE(SMBsplclose);
3742                 return ERROR_NT(NT_STATUS_DOS(ERRSRV, ERRerror));
3743         }
3744   
3745         DEBUG(3,("printclose fd=%d fnum=%d\n",
3746                  fsp->fh->fd,fsp->fnum));
3747   
3748         status = close_file(fsp,NORMAL_CLOSE);
3749
3750         if(!NT_STATUS_IS_OK(status)) {
3751                 END_PROFILE(SMBsplclose);
3752                 return ERROR_NT(status);
3753         }
3754
3755         END_PROFILE(SMBsplclose);
3756         return(outsize);
3757 }
3758
3759 /****************************************************************************
3760  Reply to a printqueue.
3761 ****************************************************************************/
3762
3763 int reply_printqueue(connection_struct *conn,
3764                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3765 {
3766         int outsize = set_message(inbuf,outbuf,2,3,True);
3767         int max_count = SVAL(inbuf,smb_vwv0);
3768         int start_index = SVAL(inbuf,smb_vwv1);
3769         START_PROFILE(SMBsplretq);
3770
3771         /* we used to allow the client to get the cnum wrong, but that
3772            is really quite gross and only worked when there was only
3773            one printer - I think we should now only accept it if they
3774            get it right (tridge) */
3775         if (!CAN_PRINT(conn)) {
3776                 END_PROFILE(SMBsplretq);
3777                 return ERROR_DOS(ERRDOS,ERRnoaccess);
3778         }
3779
3780         SSVAL(outbuf,smb_vwv0,0);
3781         SSVAL(outbuf,smb_vwv1,0);
3782         SCVAL(smb_buf(outbuf),0,1);
3783         SSVAL(smb_buf(outbuf),1,0);
3784   
3785         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3786                  start_index, max_count));
3787
3788         {
3789                 print_queue_struct *queue = NULL;
3790                 print_status_struct status;
3791                 char *p = smb_buf(outbuf) + 3;
3792                 int count = print_queue_status(SNUM(conn), &queue, &status);
3793                 int num_to_get = ABS(max_count);
3794                 int first = (max_count>0?start_index:start_index+max_count+1);
3795                 int i;
3796
3797                 if (first >= count)
3798                         num_to_get = 0;
3799                 else
3800                         num_to_get = MIN(num_to_get,count-first);
3801     
3802
3803                 for (i=first;i<first+num_to_get;i++) {
3804                         srv_put_dos_date2(p,0,queue[i].time);
3805                         SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3806                         SSVAL(p,5, queue[i].job);
3807                         SIVAL(p,7,queue[i].size);
3808                         SCVAL(p,11,0);
3809                         srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3810                         p += 28;
3811                 }
3812
3813                 if (count > 0) {
3814                         outsize = set_message(inbuf,outbuf,2,28*count+3,False); 
3815                         SSVAL(outbuf,smb_vwv0,count);
3816                         SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3817                         SCVAL(smb_buf(outbuf),0,1);
3818                         SSVAL(smb_buf(outbuf),1,28*count);
3819                 }
3820
3821                 SAFE_FREE(queue);
3822           
3823                 DEBUG(3,("%d entries returned in queue\n",count));
3824         }
3825   
3826         END_PROFILE(SMBsplretq);
3827         return(outsize);
3828 }
3829
3830 /****************************************************************************
3831  Reply to a printwrite.
3832 ****************************************************************************/
3833
3834 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3835 {
3836         int numtowrite;
3837         int outsize = set_message(inbuf,outbuf,0,0,False);
3838         char *data;
3839         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3840
3841         START_PROFILE(SMBsplwr);
3842   
3843         if (!CAN_PRINT(conn)) {
3844                 END_PROFILE(SMBsplwr);
3845                 return ERROR_DOS(ERRDOS,ERRnoaccess);
3846         }
3847
3848         CHECK_FSP(fsp,conn);
3849         if (!CHECK_WRITE(fsp)) {
3850                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3851         }
3852
3853         numtowrite = SVAL(smb_buf(inbuf),1);
3854         data = smb_buf(inbuf) + 3;
3855   
3856         if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3857                 END_PROFILE(SMBsplwr);
3858                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3859         }
3860
3861         DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3862   
3863         END_PROFILE(SMBsplwr);
3864         return(outsize);
3865 }
3866
3867 /****************************************************************************
3868  Reply to a mkdir.
3869 ****************************************************************************/
3870
3871 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3872 {
3873         pstring directory;
3874         int outsize;
3875         NTSTATUS status;
3876         SMB_STRUCT_STAT sbuf;
3877
3878         START_PROFILE(SMBmkdir);
3879  
3880         srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), directory,
3881                         smb_buf(inbuf) + 1, sizeof(directory), 0,
3882                         STR_TERMINATE, &status);
3883         if (!NT_STATUS_IS_OK(status)) {
3884                 END_PROFILE(SMBmkdir);
3885                 return ERROR_NT(status);
3886         }
3887
3888         status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory);
3889         if (!NT_STATUS_IS_OK(status)) {
3890                 END_PROFILE(SMBmkdir);
3891                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3892                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3893                 }
3894                 return ERROR_NT(status);
3895         }
3896
3897         status = unix_convert(conn, directory, False, NULL, &sbuf);
3898         if (!NT_STATUS_IS_OK(status)) {
3899                 END_PROFILE(SMBmkdir);
3900                 return ERROR_NT(status);
3901         }
3902
3903         status = check_name(conn, directory);
3904         if (!NT_STATUS_IS_OK(status)) {
3905                 END_PROFILE(SMBmkdir);
3906                 return ERROR_NT(status);
3907         }
3908   
3909         status = create_directory(conn, directory);
3910
3911         DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
3912
3913         if (!NT_STATUS_IS_OK(status)) {
3914
3915                 if (!use_nt_status()
3916                     && NT_STATUS_EQUAL(status,
3917                                        NT_STATUS_OBJECT_NAME_COLLISION)) {
3918                         /*
3919                          * Yes, in the DOS error code case we get a
3920                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
3921                          * samba4 torture test.
3922                          */
3923                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
3924                 }
3925
3926                 END_PROFILE(SMBmkdir);
3927                 return ERROR_NT(status);
3928         }
3929
3930         outsize = set_message(inbuf,outbuf,0,0,False);
3931
3932         DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3933
3934         END_PROFILE(SMBmkdir);
3935         return(outsize);
3936 }
3937
3938 /****************************************************************************
3939  Static function used by reply_rmdir to delete an entire directory
3940  tree recursively. Return True on ok, False on fail.
3941 ****************************************************************************/
3942
3943 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3944 {
3945         const char *dname = NULL;
3946         BOOL ret = True;
3947         long offset = 0;
3948         struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3949
3950         if(dir_hnd == NULL)
3951                 return False;
3952
3953         while((dname = ReadDirName(dir_hnd, &offset))) {
3954                 pstring fullname;
3955                 SMB_STRUCT_STAT st;
3956
3957                 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3958                         continue;
3959
3960                 if (!is_visible_file(conn, directory, dname, &st, False))
3961                         continue;
3962
3963                 /* Construct the full name. */
3964                 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3965                         errno = ENOMEM;
3966                         ret = False;
3967                         break;
3968                 }
3969
3970                 pstrcpy(fullname, directory);
3971                 pstrcat(fullname, "/");
3972                 pstrcat(fullname, dname);
3973
3974                 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3975                         ret = False;
3976                         break;
3977                 }
3978
3979                 if(st.st_mode & S_IFDIR) {
3980                         if(!recursive_rmdir(conn, fullname)) {
3981                                 ret = False;
3982                                 break;
3983                         }
3984                         if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3985                                 ret = False;
3986                                 break;
3987                         }
3988                 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3989                         ret = False;
3990                         break;
3991                 }
3992         }
3993         CloseDir(dir_hnd);
3994         return ret;
3995 }
3996
3997 /****************************************************************************
3998  The internals of the rmdir code - called elsewhere.
3999 ****************************************************************************/
4000
4001 NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
4002 {
4003         int ret;
4004         SMB_STRUCT_STAT st;
4005
4006         /* Might be a symlink. */
4007         if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
4008                 return map_nt_error_from_unix(errno);
4009         }
4010
4011         if (S_ISLNK(st.st_mode)) {
4012                 /* Is what it points to a directory ? */
4013                 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
4014                         return map_nt_error_from_unix(errno);
4015                 }
4016                 if (!(S_ISDIR(st.st_mode))) {
4017                         return NT_STATUS_NOT_A_DIRECTORY;
4018                 }
4019                 ret = SMB_VFS_UNLINK(conn,directory);
4020         } else {
4021                 ret = SMB_VFS_RMDIR(conn,directory);
4022         }
4023         if (ret == 0) {
4024                 notify_fname(conn, NOTIFY_ACTION_REMOVED,
4025                              FILE_NOTIFY_CHANGE_DIR_NAME,
4026                              directory);
4027                 return NT_STATUS_OK;
4028         }
4029
4030         if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
4031                 /* 
4032                  * Check to see if the only thing in this directory are
4033                  * vetoed files/directories. If so then delete them and
4034                  * retry. If we fail to delete any of them (and we *don't*
4035                  * do a recursive delete) then fail the rmdir.
4036                  */
4037                 const char *dname;
4038                 long dirpos = 0;
4039                 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
4040
4041                 if(dir_hnd == NULL) {
4042                         errno = ENOTEMPTY;
4043                         goto err;
4044                 }
4045
4046                 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4047                         if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4048                                 continue;
4049                         if (!is_visible_file(conn, directory, dname, &st, False))
4050                                 continue;
4051                         if(!IS_VETO_PATH(conn, dname)) {
4052                                 CloseDir(dir_hnd);
4053                                 errno = ENOTEMPTY;
4054                                 goto err;
4055                         }
4056                 }
4057
4058                 /* We only have veto files/directories. Recursive delete. */
4059
4060                 RewindDir(dir_hnd,&dirpos);
4061                 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4062                         pstring fullname;
4063
4064                         if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4065                                 continue;
4066                         if (!is_visible_file(conn, directory, dname, &st, False))
4067                                 continue;
4068
4069                         /* Construct the full name. */
4070                         if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
4071                                 errno = ENOMEM;
4072                                 break;
4073                         }
4074
4075                         pstrcpy(fullname, directory);
4076                         pstrcat(fullname, "/");
4077                         pstrcat(fullname, dname);
4078                    
4079                         if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
4080                                 break;
4081                         if(st.st_mode & S_IFDIR) {
4082                                 if(lp_recursive_veto_delete(SNUM(conn))) {
4083                                         if(!recursive_rmdir(conn, fullname))
4084                                                 break;
4085                                 }
4086                                 if(SMB_VFS_RMDIR(conn,fullname) != 0)
4087                                         break;
4088                         } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
4089                                 break;
4090                 }
4091                 CloseDir(dir_hnd);
4092                 /* Retry the rmdir */
4093                 ret = SMB_VFS_RMDIR(conn,directory);
4094         }
4095
4096   err:
4097
4098         if (ret != 0) {
4099                 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
4100                          "%s\n", directory,strerror(errno)));
4101                 return map_nt_error_from_unix(errno);
4102         }
4103
4104         notify_fname(conn, NOTIFY_ACTION_REMOVED,
4105                      FILE_NOTIFY_CHANGE_DIR_NAME,
4106                      directory);
4107
4108         return NT_STATUS_OK;
4109 }
4110
4111 /****************************************************************************
4112  Reply to a rmdir.
4113 ****************************************************************************/
4114
4115 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4116 {
4117         pstring directory;
4118         int outsize = 0;
4119         SMB_STRUCT_STAT sbuf;
4120         NTSTATUS status;
4121         START_PROFILE(SMBrmdir);
4122
4123         srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), directory,
4124                         smb_buf(inbuf) + 1, sizeof(directory), 0,
4125                         STR_TERMINATE, &status);
4126         if (!NT_STATUS_IS_OK(status)) {
4127                 END_PROFILE(SMBrmdir);
4128                 return ERROR_NT(status);
4129         }
4130
4131         status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory);
4132         if (!NT_STATUS_IS_OK(status)) {
4133                 END_PROFILE(SMBrmdir);
4134                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4135                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4136                 }
4137                 return ERROR_NT(status);
4138         }
4139
4140         status = unix_convert(conn, directory, False, NULL, &sbuf);
4141         if (!NT_STATUS_IS_OK(status)) {
4142                 END_PROFILE(SMBrmdir);
4143                 return ERROR_NT(status);
4144         }
4145   
4146         status = check_name(conn, directory);
4147         if (!NT_STATUS_IS_OK(status)) {
4148                 END_PROFILE(SMBrmdir);
4149                 return ERROR_NT(status);
4150         }
4151
4152         dptr_closepath(directory,SVAL(inbuf,smb_pid));
4153         status = rmdir_internals(conn, directory);
4154         if (!NT_STATUS_IS_OK(status)) {
4155                 END_PROFILE(SMBrmdir);
4156                 return ERROR_NT(status);
4157         }
4158  
4159         outsize = set_message(inbuf,outbuf,0,0,False);
4160   
4161         DEBUG( 3, ( "rmdir %s\n", directory ) );
4162   
4163         END_PROFILE(SMBrmdir);
4164         return(outsize);
4165 }
4166
4167 /*******************************************************************
4168  Resolve wildcards in a filename rename.
4169  Note that name is in UNIX charset and thus potentially can be more
4170  than fstring buffer (255 bytes) especially in default UTF-8 case.
4171  Therefore, we use pstring inside and all calls should ensure that
4172  name2 is at least pstring-long (they do already)
4173 ********************************************************************/
4174
4175 static BOOL resolve_wildcards(const char *name1, char *name2)
4176 {
4177         pstring root1,root2;
4178         pstring ext1,ext2;
4179         char *p,*p2, *pname1, *pname2;
4180         int available_space, actual_space;
4181         
4182         pname1 = strrchr_m(name1,'/');
4183         pname2 = strrchr_m(name2,'/');
4184
4185         if (!pname1 || !pname2)
4186                 return(False);
4187   
4188         pstrcpy(root1,pname1);
4189         pstrcpy(root2,pname2);
4190         p = strrchr_m(root1,'.');
4191         if (p) {
4192                 *p = 0;
4193                 pstrcpy(ext1,p+1);
4194         } else {
4195                 pstrcpy(ext1,"");    
4196         }
4197         p = strrchr_m(root2,'.');
4198         if (p) {
4199                 *p = 0;
4200                 pstrcpy(ext2,p+1);
4201         } else {
4202                 pstrcpy(ext2,"");    
4203         }
4204
4205         p = root1;
4206         p2 = root2;
4207         while (*p2) {
4208                 if (*p2 == '?') {
4209                         *p2 = *p;
4210                         p2++;
4211                 } else if (*p2 == '*') {
4212                         pstrcpy(p2, p);
4213                         break;
4214                 } else {
4215                         p2++;
4216                 }
4217                 if (*p)
4218                         p++;
4219         }
4220
4221         p = ext1;
4222         p2 = ext2;
4223         while (*p2) {
4224                 if (*p2 == '?') {
4225                         *p2 = *p;
4226                         p2++;
4227                 } else if (*p2 == '*') {
4228                         pstrcpy(p2, p);
4229                         break;
4230                 } else {
4231                         p2++;
4232                 }
4233                 if (*p)
4234                         p++;
4235         }
4236
4237         available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
4238         
4239         if (ext2[0]) {
4240                 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
4241                 if (actual_space >= available_space - 1) {
4242                         DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
4243                                 actual_space - available_space));
4244                 }
4245         } else {
4246                 pstrcpy_base(pname2, root2, name2);
4247         }
4248
4249         return(True);
4250 }
4251
4252 /****************************************************************************
4253  Ensure open files have their names updated. Updated to notify other smbd's
4254  asynchronously.
4255 ****************************************************************************/
4256
4257 static void rename_open_files(connection_struct *conn,
4258                               struct share_mode_lock *lck,
4259                               const char *newname)
4260 {
4261         files_struct *fsp;
4262         BOOL did_rename = False;
4263
4264         for(fsp = file_find_di_first(lck->id); fsp;
4265             fsp = file_find_di_next(fsp)) {
4266                 /* fsp_name is a relative path under the fsp. To change this for other
4267                    sharepaths we need to manipulate relative paths. */
4268                 /* TODO - create the absolute path and manipulate the newname
4269                    relative to the sharepath. */
4270                 if (fsp->conn != conn) {
4271                         continue;
4272                 }
4273                 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
4274                           fsp->fnum, file_id_static_string(&fsp->file_id),
4275                         fsp->fsp_name, newname ));
4276                 string_set(&fsp->fsp_name, newname);
4277                 did_rename = True;
4278         }
4279
4280         if (!did_rename) {
4281                 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
4282                           file_id_static_string(&lck->id), newname ));
4283         }
4284
4285         /* Send messages to all smbd's (not ourself) that the name has changed. */
4286         rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
4287                               newname);
4288 }
4289
4290 /****************************************************************************
4291  We need to check if the source path is a parent directory of the destination
4292  (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
4293  refuse the rename with a sharing violation. Under UNIX the above call can
4294  *succeed* if /foo/bar/baz is a symlink to another area in the share. We
4295  probably need to check that the client is a Windows one before disallowing
4296  this as a UNIX client (one with UNIX extensions) can know the source is a
4297  symlink and make this decision intelligently. Found by an excellent bug
4298  report from <AndyLiebman@aol.com>.
4299 ****************************************************************************/
4300
4301 static BOOL rename_path_prefix_equal(const char *src, const char *dest)
4302 {
4303         const char *psrc = src;
4304         const char *pdst = dest;
4305         size_t slen;
4306
4307         if (psrc[0] == '.' && psrc[1] == '/') {
4308                 psrc += 2;
4309         }
4310         if (pdst[0] == '.' && pdst[1] == '/') {
4311                 pdst += 2;
4312         }
4313         if ((slen = strlen(psrc)) > strlen(pdst)) {
4314                 return False;
4315         }
4316         return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
4317 }
4318
4319 /*
4320  * Do the notify calls from a rename
4321  */
4322
4323 static void notify_rename(connection_struct *conn, BOOL is_dir,
4324                           const char *oldpath, const char *newpath)
4325 {
4326         char *olddir, *newdir;
4327         const char *oldname, *newname;
4328         uint32 mask;
4329
4330         mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
4331                 : FILE_NOTIFY_CHANGE_FILE_NAME;
4332
4333         if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
4334             || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
4335                 TALLOC_FREE(olddir);
4336                 return;
4337         }
4338
4339         if (strcmp(olddir, newdir) == 0) {
4340                 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
4341                 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
4342         }
4343         else {
4344                 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
4345                 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
4346         }
4347         TALLOC_FREE(olddir);
4348         TALLOC_FREE(newdir);
4349
4350         /* this is a strange one. w2k3 gives an additional event for
4351            CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
4352            files, but not directories */
4353         if (!is_dir) {
4354                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
4355                              FILE_NOTIFY_CHANGE_ATTRIBUTES
4356                              |FILE_NOTIFY_CHANGE_CREATION,
4357                              newpath);
4358         }
4359 }
4360
4361 /****************************************************************************
4362  Rename an open file - given an fsp.
4363 ****************************************************************************/
4364
4365 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstring newname, uint32 attrs, BOOL replace_if_exists)
4366 {
4367         SMB_STRUCT_STAT sbuf, sbuf1;
4368         pstring newname_last_component;
4369         NTSTATUS status = NT_STATUS_OK;
4370         struct share_mode_lock *lck = NULL;
4371         BOOL dst_exists;
4372
4373         ZERO_STRUCT(sbuf);
4374
4375         status = unix_convert(conn, newname, False, newname_last_component, &sbuf);
4376
4377         /* If an error we expect this to be NT_STATUS_OBJECT_PATH_NOT_FOUND */
4378
4379         if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND, status)) {
4380                 return status;
4381         }
4382
4383         status = check_name(conn, newname);
4384         if (!NT_STATUS_IS_OK(status)) {
4385                 return status;
4386         }
4387   
4388         /* Ensure newname contains a '/' */
4389         if(strrchr_m(newname,'/') == 0) {
4390                 pstring tmpstr;
4391                 
4392                 pstrcpy(tmpstr, "./");
4393                 pstrcat(tmpstr, newname);
4394                 pstrcpy(newname, tmpstr);
4395         }
4396
4397         /*
4398          * Check for special case with case preserving and not
4399          * case sensitive. If the old last component differs from the original
4400          * last component only by case, then we should allow
4401          * the rename (user is trying to change the case of the
4402          * filename).
4403          */
4404
4405         if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
4406                         strequal(newname, fsp->fsp_name)) {
4407                 char *p;
4408                 pstring newname_modified_last_component;
4409
4410                 /*
4411                  * Get the last component of the modified name.
4412                  * Note that we guarantee that newname contains a '/'
4413                  * character above.
4414                  */
4415                 p = strrchr_m(newname,'/');
4416                 pstrcpy(newname_modified_last_component,p+1);
4417                         
4418                 if(strcsequal(newname_modified_last_component, 
4419                               newname_last_component) == False) {
4420                         /*
4421                          * Replace the modified last component with
4422                          * the original.
4423                          */
4424                         pstrcpy(p+1, newname_last_component);
4425                 }
4426         }
4427
4428         /*
4429          * If the src and dest names are identical - including case,
4430          * don't do the rename, just return success.
4431          */
4432
4433         if (strcsequal(fsp->fsp_name, newname)) {
4434                 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4435                         newname));
4436                 return NT_STATUS_OK;
4437         }
4438
4439         /*
4440          * Have vfs_object_exist also fill sbuf1
4441          */
4442         dst_exists = vfs_object_exist(conn, newname, &sbuf1);
4443
4444         if(!replace_if_exists && dst_exists) {
4445                 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4446                         fsp->fsp_name,newname));
4447                 return NT_STATUS_OBJECT_NAME_COLLISION;
4448         }
4449
4450         if (dst_exists) {
4451                 files_struct *dst_fsp = file_find_di_first(file_id_sbuf(&sbuf1));
4452                 if (dst_fsp) {
4453                         DEBUG(3, ("rename_internals_fsp: Target file open\n"));
4454                         return NT_STATUS_ACCESS_DENIED;
4455                 }
4456         }
4457
4458         /* Ensure we have a valid stat struct for the source. */
4459         if (fsp->fh->fd != -1) {
4460                 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) == -1) {
4461                         return map_nt_error_from_unix(errno);
4462                 }
4463         } else {
4464                 if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
4465                         return map_nt_error_from_unix(errno);
4466                 }
4467         }
4468
4469         status = can_rename(conn, fsp, attrs, &sbuf);
4470
4471         if (!NT_STATUS_IS_OK(status)) {
4472                 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4473                         nt_errstr(status), fsp->fsp_name,newname));
4474                 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
4475                         status = NT_STATUS_ACCESS_DENIED;
4476                 return status;
4477         }
4478
4479         if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
4480                 return NT_STATUS_ACCESS_DENIED;
4481         }
4482
4483         lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
4484
4485         /*
4486          * We have the file open ourselves, so not being able to get the
4487          * corresponding share mode lock is a fatal error.
4488          */
4489
4490         SMB_ASSERT(lck != NULL);
4491
4492         if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
4493                 uint32 create_options = fsp->fh->private_options;
4494
4495                 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4496                         fsp->fsp_name,newname));
4497
4498                 rename_open_files(conn, lck, newname);
4499
4500                 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
4501
4502                 /*
4503                  * A rename acts as a new file create w.r.t. allowing an initial delete
4504                  * on close, probably because in Windows there is a new handle to the
4505                  * new file. If initial delete on close was requested but not
4506                  * originally set, we need to set it here. This is probably not 100% correct,
4507                  * but will work for the CIFSFS client which in non-posix mode
4508                  * depends on these semantics. JRA.
4509                  */
4510
4511                 set_allow_initial_delete_on_close(lck, fsp, True);
4512
4513                 if (create_options & FILE_DELETE_ON_CLOSE) {
4514                         status = can_set_delete_on_close(fsp, True, 0);
4515
4516                         if (NT_STATUS_IS_OK(status)) {
4517                                 /* Note that here we set the *inital* delete on close flag,
4518                                  * not the regular one. The magic gets handled in close. */
4519                                 fsp->initial_delete_on_close = True;
4520                         }
4521                 }
4522                 TALLOC_FREE(lck);
4523                 return NT_STATUS_OK;    
4524         }
4525
4526         TALLOC_FREE(lck);
4527
4528         if (errno == ENOTDIR || errno == EISDIR) {
4529                 status = NT_STATUS_OBJECT_NAME_COLLISION;
4530         } else {
4531                 status = map_nt_error_from_unix(errno);
4532         }
4533                 
4534         DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4535                 nt_errstr(status), fsp->fsp_name,newname));
4536
4537         return status;
4538 }
4539
4540 /****************************************************************************
4541  The guts of the rename command, split out so it may be called by the NT SMB
4542  code. 
4543 ****************************************************************************/
4544
4545 NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
4546                                 pstring name,
4547                                 pstring newname,
4548                                 uint32 attrs,
4549                                 BOOL replace_if_exists,
4550                                 BOOL src_has_wild,
4551                                 BOOL dest_has_wild)
4552 {
4553         pstring directory;
4554         pstring mask;
4555         pstring last_component_src;
4556         pstring last_component_dest;
4557         char *p;
4558         int count=0;
4559         NTSTATUS status = NT_STATUS_OK;
4560         SMB_STRUCT_STAT sbuf1, sbuf2;
4561         struct smb_Dir *dir_hnd = NULL;
4562         const char *dname;
4563         long offset = 0;
4564         pstring destname;
4565
4566         *directory = *mask = 0;
4567
4568         ZERO_STRUCT(sbuf1);
4569         ZERO_STRUCT(sbuf2);
4570
4571         status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1);
4572         if (!NT_STATUS_IS_OK(status)) {
4573                 return status;
4574         }
4575
4576         status = unix_convert(conn, newname, dest_has_wild, last_component_dest, &sbuf2);
4577         if (!NT_STATUS_IS_OK(status)) {
4578                 return status;
4579         }
4580
4581         /*
4582          * Split the old name into directory and last component
4583          * strings. Note that unix_convert may have stripped off a 
4584          * leading ./ from both name and newname if the rename is 
4585          * at the root of the share. We need to make sure either both
4586          * name and newname contain a / character or neither of them do
4587          * as this is checked in resolve_wildcards().
4588          */
4589
4590         p = strrchr_m(name,'/');
4591         if (!p) {
4592                 pstrcpy(directory,".");
4593                 pstrcpy(mask,name);
4594         } else {
4595                 *p = 0;
4596                 pstrcpy(directory,name);
4597                 pstrcpy(mask,p+1);
4598                 *p = '/'; /* Replace needed for exceptional test below. */
4599         }
4600
4601         /*
4602          * We should only check the mangled cache
4603          * here if unix_convert failed. This means
4604          * that the path in 'mask' doesn't exist
4605          * on the file system and so we need to look
4606          * for a possible mangle. This patch from
4607          * Tine Smukavec <valentin.smukavec@hermes.si>.
4608          */
4609
4610         if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
4611                 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
4612         }
4613
4614         if (!src_has_wild) {
4615                 files_struct *fsp;
4616
4617                 /*
4618                  * No wildcards - just process the one file.
4619                  */
4620                 BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
4621
4622                 /* Add a terminating '/' to the directory name. */
4623                 pstrcat(directory,"/");
4624                 pstrcat(directory,mask);
4625                 
4626                 /* Ensure newname contains a '/' also */
4627                 if(strrchr_m(newname,'/') == 0) {
4628                         pstring tmpstr;
4629                         
4630                         pstrcpy(tmpstr, "./");
4631                         pstrcat(tmpstr, newname);
4632                         pstrcpy(newname, tmpstr);
4633                 }
4634                 
4635                 DEBUG(3, ("rename_internals: case_sensitive = %d, "
4636                           "case_preserve = %d, short case preserve = %d, "
4637                           "directory = %s, newname = %s, "
4638                           "last_component_dest = %s, is_8_3 = %d\n", 
4639                           conn->case_sensitive, conn->case_preserve,
4640                           conn->short_case_preserve, directory, 
4641                           newname, last_component_dest, is_short_name));
4642
4643                 /* The dest name still may have wildcards. */
4644                 if (dest_has_wild) {
4645                         if (!resolve_wildcards(directory,newname)) {
4646                                 DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n", 
4647                                           directory,newname));
4648                                 return NT_STATUS_NO_MEMORY;
4649                         }
4650                 }
4651                                 
4652                 ZERO_STRUCT(sbuf1);
4653                 SMB_VFS_STAT(conn, directory, &sbuf1);
4654
4655                 status = S_ISDIR(sbuf1.st_mode) ?
4656                         open_directory(conn, req, directory, &sbuf1,
4657                                        DELETE_ACCESS,
4658                                        FILE_SHARE_READ|FILE_SHARE_WRITE,
4659                                        FILE_OPEN, 0, 0, NULL,
4660                                        &fsp)
4661                         : open_file_ntcreate(conn, req, directory, &sbuf1,
4662                                              DELETE_ACCESS,
4663                                              FILE_SHARE_READ|FILE_SHARE_WRITE,
4664                                              FILE_OPEN, 0, 0, 0, NULL,
4665                                              &fsp);
4666
4667                 if (!NT_STATUS_IS_OK(status)) {
4668                         DEBUG(3, ("Could not open rename source %s: %s\n",
4669                                   directory, nt_errstr(status)));
4670                         return status;
4671                 }
4672
4673                 status = rename_internals_fsp(conn, fsp, newname, attrs,
4674                                               replace_if_exists);
4675
4676                 close_file(fsp, NORMAL_CLOSE);
4677
4678                 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
4679                           nt_errstr(status), directory,newname));
4680
4681                 return status;
4682         }
4683
4684         /*
4685          * Wildcards - process each file that matches.
4686          */
4687         if (strequal(mask,"????????.???")) {
4688                 pstrcpy(mask,"*");
4689         }
4690                         
4691         status = check_name(conn, directory);
4692         if (!NT_STATUS_IS_OK(status)) {
4693                 return status;
4694         }
4695         
4696         dir_hnd = OpenDir(conn, directory, mask, attrs);
4697         if (dir_hnd == NULL) {
4698                 return map_nt_error_from_unix(errno);
4699         }
4700                 
4701         status = NT_STATUS_NO_SUCH_FILE;
4702         /*
4703          * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4704          * - gentest fix. JRA
4705          */
4706                         
4707         while ((dname = ReadDirName(dir_hnd, &offset))) {
4708                 files_struct *fsp;
4709                 pstring fname;
4710                 BOOL sysdir_entry = False;
4711
4712                 pstrcpy(fname,dname);
4713                                 
4714                 /* Quick check for "." and ".." */
4715                 if (fname[0] == '.') {
4716                         if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4717                                 if (attrs & aDIR) {
4718                                         sysdir_entry = True;
4719                                 } else {
4720                                         continue;
4721                                 }
4722                         }
4723                 }
4724
4725                 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
4726                         continue;
4727                 }
4728
4729                 if(!mask_match(fname, mask, conn->case_sensitive)) {
4730                         continue;
4731                 }
4732                                 
4733                 if (sysdir_entry) {
4734                         status = NT_STATUS_OBJECT_NAME_INVALID;
4735                         break;
4736                 }
4737
4738                 slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname);
4739
4740                 pstrcpy(destname,newname);
4741                         
4742                 if (!resolve_wildcards(fname,destname)) {
4743                         DEBUG(6, ("resolve_wildcards %s %s failed\n", 
4744                                   fname, destname));
4745                         continue;
4746                 }
4747                                 
4748                 ZERO_STRUCT(sbuf1);
4749                 SMB_VFS_STAT(conn, fname, &sbuf1);
4750
4751                 status = S_ISDIR(sbuf1.st_mode) ?
4752                         open_directory(conn, req, fname, &sbuf1,
4753                                        DELETE_ACCESS,
4754                                        FILE_SHARE_READ|FILE_SHARE_WRITE,
4755                                        FILE_OPEN, 0, 0, NULL,
4756                                        &fsp)
4757                         : open_file_ntcreate(conn, req, fname, &sbuf1,
4758                                              DELETE_ACCESS,
4759                                              FILE_SHARE_READ|FILE_SHARE_WRITE,
4760                                              FILE_OPEN, 0, 0, 0, NULL,
4761                                              &fsp);
4762
4763                 if (!NT_STATUS_IS_OK(status)) {
4764                         DEBUG(3,("rename_internals: open_file_ntcreate "
4765                                  "returned %s rename %s -> %s\n",
4766                                  nt_errstr(status), directory, newname));
4767                         break;
4768                 }
4769
4770                 status = rename_internals_fsp(conn, fsp, destname, attrs,
4771                                               replace_if_exists);
4772
4773                 close_file(fsp, NORMAL_CLOSE);
4774
4775                 if (!NT_STATUS_IS_OK(status)) {
4776                         DEBUG(3, ("rename_internals_fsp returned %s for "
4777                                   "rename %s -> %s\n", nt_errstr(status),
4778                                   directory, newname));
4779                         break;
4780                 }
4781
4782                 count++;
4783
4784                 DEBUG(3,("rename_internals: doing rename on %s -> "
4785                          "%s\n",fname,destname));
4786         }
4787         CloseDir(dir_hnd);
4788
4789         if (count == 0 && NT_STATUS_IS_OK(status)) {
4790                 status = map_nt_error_from_unix(errno);
4791         }
4792         
4793         return status;
4794 }
4795
4796 /****************************************************************************
4797  Reply to a mv.
4798 ****************************************************************************/
4799
4800 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, 
4801              int dum_buffsize)
4802 {
4803         int outsize = 0;
4804         pstring name;
4805         pstring newname;
4806         char *p;
4807         uint32 attrs = SVAL(inbuf,smb_vwv0);
4808         NTSTATUS status;
4809         BOOL src_has_wcard = False;
4810         BOOL dest_has_wcard = False;
4811         struct smb_request req;
4812
4813         START_PROFILE(SMBmv);
4814
4815         init_smb_request(&req, (uint8 *)inbuf);
4816
4817         p = smb_buf(inbuf) + 1;
4818         p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p,
4819                                    sizeof(name), 0, STR_TERMINATE, &status,
4820                                    &src_has_wcard);
4821         if (!NT_STATUS_IS_OK(status)) {
4822                 END_PROFILE(SMBmv);
4823                 return ERROR_NT(status);
4824         }
4825         p++;
4826         p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p,
4827                                    sizeof(newname), 0, STR_TERMINATE, &status,
4828                                    &dest_has_wcard);
4829         if (!NT_STATUS_IS_OK(status)) {
4830                 END_PROFILE(SMBmv);
4831                 return ERROR_NT(status);
4832         }
4833         
4834         status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &src_has_wcard);
4835         if (!NT_STATUS_IS_OK(status)) {
4836                 END_PROFILE(SMBmv);
4837                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4838                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4839                 }
4840                 return ERROR_NT(status);
4841         }
4842
4843         status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_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         DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4853         
4854         status = rename_internals(conn, &req, name, newname, attrs, False,
4855                                   src_has_wcard, dest_has_wcard);
4856         if (!NT_STATUS_IS_OK(status)) {
4857                 END_PROFILE(SMBmv);
4858                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4859                         /* We have re-scheduled this call. */
4860                         return -1;
4861                 }
4862                 return ERROR_NT(status);
4863         }
4864
4865         outsize = set_message(inbuf,outbuf,0,0,False);
4866   
4867         END_PROFILE(SMBmv);
4868         return(outsize);
4869 }
4870
4871 /*******************************************************************
4872  Copy a file as part of a reply_copy.
4873 ******************************************************************/
4874
4875 /*
4876  * TODO: check error codes on all callers
4877  */
4878
4879 NTSTATUS copy_file(connection_struct *conn,
4880                         char *src,
4881                         char *dest1,
4882                         int ofun,
4883                         int count,
4884                         BOOL target_is_directory)
4885 {
4886         SMB_STRUCT_STAT src_sbuf, sbuf2;
4887         SMB_OFF_T ret=-1;
4888         files_struct *fsp1,*fsp2;
4889         pstring dest;
4890         uint32 dosattrs;
4891         uint32 new_create_disposition;
4892         NTSTATUS status;
4893  
4894         pstrcpy(dest,dest1);
4895         if (target_is_directory) {
4896                 char *p = strrchr_m(src,'/');
4897                 if (p) {
4898                         p++;
4899                 } else {
4900                         p = src;
4901                 }
4902                 pstrcat(dest,"/");
4903                 pstrcat(dest,p);
4904         }
4905
4906         if (!vfs_file_exist(conn,src,&src_sbuf)) {
4907                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4908         }
4909
4910         if (!target_is_directory && count) {
4911                 new_create_disposition = FILE_OPEN;
4912         } else {
4913                 if (!map_open_params_to_ntcreate(dest1,0,ofun,
4914                                 NULL, NULL, &new_create_disposition, NULL)) {
4915                         return NT_STATUS_INVALID_PARAMETER;
4916                 }
4917         }
4918
4919         status = open_file_ntcreate(conn, NULL, src, &src_sbuf,
4920                         FILE_GENERIC_READ,
4921                         FILE_SHARE_READ|FILE_SHARE_WRITE,
4922                         FILE_OPEN,
4923                         0,
4924                         FILE_ATTRIBUTE_NORMAL,
4925                         INTERNAL_OPEN_ONLY,
4926                         NULL, &fsp1);
4927
4928         if (!NT_STATUS_IS_OK(status)) {
4929                 return status;
4930         }
4931
4932         dosattrs = dos_mode(conn, src, &src_sbuf);
4933         if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
4934                 ZERO_STRUCTP(&sbuf2);
4935         }
4936
4937         status = open_file_ntcreate(conn, NULL, dest, &sbuf2,
4938                         FILE_GENERIC_WRITE,
4939                         FILE_SHARE_READ|FILE_SHARE_WRITE,
4940                         new_create_disposition,
4941                         0,
4942                         dosattrs,
4943                         INTERNAL_OPEN_ONLY,
4944                         NULL, &fsp2);
4945
4946         if (!NT_STATUS_IS_OK(status)) {
4947                 close_file(fsp1,ERROR_CLOSE);
4948                 return status;
4949         }
4950
4951         if ((ofun&3) == 1) {
4952                 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
4953                         DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4954                         /*
4955                          * Stop the copy from occurring.
4956                          */
4957                         ret = -1;
4958                         src_sbuf.st_size = 0;
4959                 }
4960         }
4961   
4962         if (src_sbuf.st_size) {
4963                 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4964         }
4965
4966         close_file(fsp1,NORMAL_CLOSE);
4967
4968         /* Ensure the modtime is set correctly on the destination file. */
4969         fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
4970
4971         /*
4972          * As we are opening fsp1 read-only we only expect
4973          * an error on close on fsp2 if we are out of space.
4974          * Thus we don't look at the error return from the
4975          * close of fsp1.
4976          */
4977         status = close_file(fsp2,NORMAL_CLOSE);
4978
4979         if (!NT_STATUS_IS_OK(status)) {
4980                 return status;
4981         }
4982
4983         if (ret != (SMB_OFF_T)src_sbuf.st_size) {
4984                 return NT_STATUS_DISK_FULL;
4985         }
4986
4987         return NT_STATUS_OK;
4988 }
4989
4990 /****************************************************************************
4991  Reply to a file copy.
4992 ****************************************************************************/
4993
4994 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4995 {
4996         int outsize = 0;
4997         pstring name;
4998         pstring directory;
4999         pstring mask,newname;
5000         char *p;
5001         int count=0;
5002         int error = ERRnoaccess;
5003         int err = 0;
5004         int tid2 = SVAL(inbuf,smb_vwv0);
5005         int ofun = SVAL(inbuf,smb_vwv1);
5006         int flags = SVAL(inbuf,smb_vwv2);
5007         BOOL target_is_directory=False;
5008         BOOL source_has_wild = False;
5009         BOOL dest_has_wild = False;
5010         SMB_STRUCT_STAT sbuf1, sbuf2;
5011         NTSTATUS status;
5012         START_PROFILE(SMBcopy);
5013
5014         *directory = *mask = 0;
5015
5016         p = smb_buf(inbuf);
5017         p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p,
5018                                    sizeof(name), 0, STR_TERMINATE, &status,
5019                                    &source_has_wild);
5020         if (!NT_STATUS_IS_OK(status)) {
5021                 END_PROFILE(SMBcopy);
5022                 return ERROR_NT(status);
5023         }
5024         p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p,
5025                                    sizeof(newname), 0, STR_TERMINATE, &status,
5026                                    &dest_has_wild);
5027         if (!NT_STATUS_IS_OK(status)) {
5028                 END_PROFILE(SMBcopy);
5029                 return ERROR_NT(status);
5030         }
5031    
5032         DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
5033    
5034         if (tid2 != conn->cnum) {
5035                 /* can't currently handle inter share copies XXXX */
5036                 DEBUG(3,("Rejecting inter-share copy\n"));
5037                 END_PROFILE(SMBcopy);
5038                 return ERROR_DOS(ERRSRV,ERRinvdevice);
5039         }
5040
5041         status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &source_has_wild);
5042         if (!NT_STATUS_IS_OK(status)) {
5043                 END_PROFILE(SMBcopy);
5044                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5045                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5046                 }
5047                 return ERROR_NT(status);
5048         }
5049
5050         status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_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 = unix_convert(conn, name, source_has_wild, NULL, &sbuf1);
5060         if (!NT_STATUS_IS_OK(status)) {
5061                 END_PROFILE(SMBcopy);
5062                 return ERROR_NT(status);
5063         }
5064
5065         status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2);
5066         if (!NT_STATUS_IS_OK(status)) {
5067                 END_PROFILE(SMBcopy);
5068                 return ERROR_NT(status);
5069         }
5070
5071         target_is_directory = VALID_STAT_OF_DIR(sbuf2);
5072
5073         if ((flags&1) && target_is_directory) {
5074                 END_PROFILE(SMBcopy);
5075                 return ERROR_DOS(ERRDOS,ERRbadfile);
5076         }
5077
5078         if ((flags&2) && !target_is_directory) {
5079                 END_PROFILE(SMBcopy);
5080                 return ERROR_DOS(ERRDOS,ERRbadpath);
5081         }
5082
5083         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
5084                 /* wants a tree copy! XXXX */
5085                 DEBUG(3,("Rejecting tree copy\n"));
5086                 END_PROFILE(SMBcopy);
5087                 return ERROR_DOS(ERRSRV,ERRerror);
5088         }
5089
5090         p = strrchr_m(name,'/');
5091         if (!p) {
5092                 pstrcpy(directory,"./");
5093                 pstrcpy(mask,name);
5094         } else {
5095                 *p = 0;
5096                 pstrcpy(directory,name);
5097                 pstrcpy(mask,p+1);
5098         }
5099
5100         /*
5101          * We should only check the mangled cache
5102          * here if unix_convert failed. This means
5103          * that the path in 'mask' doesn't exist
5104          * on the file system and so we need to look
5105          * for a possible mangle. This patch from
5106          * Tine Smukavec <valentin.smukavec@hermes.si>.
5107          */
5108
5109         if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5110                 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
5111         }
5112
5113         if (!source_has_wild) {
5114                 pstrcat(directory,"/");
5115                 pstrcat(directory,mask);
5116                 if (dest_has_wild) {
5117                         if (!resolve_wildcards(directory,newname)) {
5118                                 END_PROFILE(SMBcopy);
5119                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
5120                         }
5121                 }
5122
5123                 status = check_name(conn, directory);
5124                 if (!NT_STATUS_IS_OK(status)) {
5125                         return ERROR_NT(status);
5126                 }
5127                 
5128                 status = check_name(conn, newname);
5129                 if (!NT_STATUS_IS_OK(status)) {
5130                         return ERROR_NT(status);
5131                 }
5132                 
5133                 status = copy_file(conn,directory,newname,ofun,
5134                                         count,target_is_directory);
5135
5136                 if(!NT_STATUS_IS_OK(status)) {
5137                         END_PROFILE(SMBcopy);
5138                         return ERROR_NT(status);
5139                 } else {
5140                         count++;
5141                 }
5142         } else {
5143                 struct smb_Dir *dir_hnd = NULL;
5144                 const char *dname;
5145                 long offset = 0;
5146                 pstring destname;
5147
5148                 if (strequal(mask,"????????.???"))
5149                         pstrcpy(mask,"*");
5150
5151                 status = check_name(conn, directory);
5152                 if (!NT_STATUS_IS_OK(status)) {
5153                         return ERROR_NT(status);
5154                 }
5155                 
5156                 dir_hnd = OpenDir(conn, directory, mask, 0);
5157                 if (dir_hnd == NULL) {
5158                         status = map_nt_error_from_unix(errno);
5159                         return ERROR_NT(status);
5160                 }
5161
5162                 error = ERRbadfile;
5163
5164                 while ((dname = ReadDirName(dir_hnd, &offset))) {
5165                         pstring fname;
5166                         pstrcpy(fname,dname);
5167     
5168                         if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5169                                 continue;
5170                         }
5171
5172                         if(!mask_match(fname, mask, conn->case_sensitive)) {
5173                                 continue;
5174                         }
5175
5176                         error = ERRnoaccess;
5177                         slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
5178                         pstrcpy(destname,newname);
5179                         if (!resolve_wildcards(fname,destname)) {
5180                                 continue;
5181                         }
5182
5183                         status = check_name(conn, fname);
5184                         if (!NT_STATUS_IS_OK(status)) {
5185                                 return ERROR_NT(status);
5186                         }
5187                 
5188                         status = check_name(conn, destname);
5189                         if (!NT_STATUS_IS_OK(status)) {
5190                                 return ERROR_NT(status);
5191                         }
5192                 
5193                         DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
5194
5195                         status = copy_file(conn,fname,destname,ofun,
5196                                         count,target_is_directory);
5197                         if (NT_STATUS_IS_OK(status)) {
5198                                 count++;
5199                         }
5200                 }
5201                 CloseDir(dir_hnd);
5202         }
5203   
5204         if (count == 0) {
5205                 if(err) {
5206                         /* Error on close... */
5207                         errno = err;
5208                         END_PROFILE(SMBcopy);
5209                         return(UNIXERROR(ERRHRD,ERRgeneral));
5210                 }
5211
5212                 END_PROFILE(SMBcopy);
5213                 return ERROR_DOS(ERRDOS,error);
5214         }
5215   
5216         outsize = set_message(inbuf,outbuf,1,0,True);
5217         SSVAL(outbuf,smb_vwv0,count);
5218
5219         END_PROFILE(SMBcopy);
5220         return(outsize);
5221 }
5222
5223 /****************************************************************************
5224  Reply to a setdir.
5225 ****************************************************************************/
5226
5227 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5228 {
5229         int snum;
5230         int outsize = 0;
5231         pstring newdir;
5232         NTSTATUS status;
5233
5234         START_PROFILE(pathworks_setdir);
5235   
5236         snum = SNUM(conn);
5237         if (!CAN_SETDIR(snum)) {
5238                 END_PROFILE(pathworks_setdir);
5239                 return ERROR_DOS(ERRDOS,ERRnoaccess);
5240         }
5241
5242         srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), newdir,
5243                         smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE,
5244                         &status);
5245         if (!NT_STATUS_IS_OK(status)) {
5246                 END_PROFILE(pathworks_setdir);
5247                 return ERROR_NT(status);
5248         }
5249   
5250         status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newdir);
5251         if (!NT_STATUS_IS_OK(status)) {
5252                 END_PROFILE(pathworks_setdir);
5253                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5254                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5255                 }
5256                 return ERROR_NT(status);
5257         }
5258
5259         if (strlen(newdir) != 0) {
5260                 if (!vfs_directory_exist(conn,newdir,NULL)) {
5261                         END_PROFILE(pathworks_setdir);
5262                         return ERROR_DOS(ERRDOS,ERRbadpath);
5263                 }
5264                 set_conn_connectpath(conn,newdir);
5265         }
5266   
5267         outsize = set_message(inbuf,outbuf,0,0,False);
5268         SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
5269   
5270         DEBUG(3,("setdir %s\n", newdir));
5271
5272         END_PROFILE(pathworks_setdir);
5273         return(outsize);
5274 }
5275
5276 #undef DBGC_CLASS
5277 #define DBGC_CLASS DBGC_LOCKING
5278
5279 /****************************************************************************
5280  Get a lock pid, dealing with large count requests.
5281 ****************************************************************************/
5282
5283 uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
5284 {
5285         if(!large_file_format)
5286                 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
5287         else
5288                 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
5289 }
5290
5291 /****************************************************************************
5292  Get a lock count, dealing with large count requests.
5293 ****************************************************************************/
5294
5295 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
5296 {
5297         SMB_BIG_UINT count = 0;
5298
5299         if(!large_file_format) {
5300                 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
5301         } else {
5302
5303 #if defined(HAVE_LONGLONG)
5304                 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
5305                         ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
5306 #else /* HAVE_LONGLONG */
5307
5308                 /*
5309                  * NT4.x seems to be broken in that it sends large file (64 bit)
5310                  * lockingX calls even if the CAP_LARGE_FILES was *not*
5311                  * negotiated. For boxes without large unsigned ints truncate the
5312                  * lock count by dropping the top 32 bits.
5313                  */
5314
5315                 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
5316                         DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
5317                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
5318                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
5319                                 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
5320                 }
5321
5322                 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
5323 #endif /* HAVE_LONGLONG */
5324         }
5325
5326         return count;
5327 }
5328
5329 #if !defined(HAVE_LONGLONG)
5330 /****************************************************************************
5331  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
5332 ****************************************************************************/
5333
5334 static uint32 map_lock_offset(uint32 high, uint32 low)
5335 {
5336         unsigned int i;
5337         uint32 mask = 0;
5338         uint32 highcopy = high;
5339  
5340         /*
5341          * Try and find out how many significant bits there are in high.
5342          */
5343  
5344         for(i = 0; highcopy; i++)
5345                 highcopy >>= 1;
5346  
5347         /*
5348          * We use 31 bits not 32 here as POSIX
5349          * lock offsets may not be negative.
5350          */
5351  
5352         mask = (~0) << (31 - i);
5353  
5354         if(low & mask)
5355                 return 0; /* Fail. */
5356  
5357         high <<= (31 - i);
5358  
5359         return (high|low);
5360 }
5361 #endif /* !defined(HAVE_LONGLONG) */
5362
5363 /****************************************************************************
5364  Get a lock offset, dealing with large offset requests.
5365 ****************************************************************************/
5366
5367 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
5368 {
5369         SMB_BIG_UINT offset = 0;
5370
5371         *err = False;
5372
5373         if(!large_file_format) {
5374                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
5375         } else {
5376
5377 #if defined(HAVE_LONGLONG)
5378                 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
5379                                 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
5380 #else /* HAVE_LONGLONG */
5381
5382                 /*
5383                  * NT4.x seems to be broken in that it sends large file (64 bit)
5384                  * lockingX calls even if the CAP_LARGE_FILES was *not*
5385                  * negotiated. For boxes without large unsigned ints mangle the
5386                  * lock offset by mapping the top 32 bits onto the lower 32.
5387                  */
5388       
5389                 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
5390                         uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5391                         uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
5392                         uint32 new_low = 0;
5393
5394                         if((new_low = map_lock_offset(high, low)) == 0) {
5395                                 *err = True;
5396                                 return (SMB_BIG_UINT)-1;
5397                         }
5398
5399                         DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
5400                                 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
5401                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
5402                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
5403                 }
5404
5405                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5406 #endif /* HAVE_LONGLONG */
5407         }
5408
5409         return offset;
5410 }
5411
5412 /****************************************************************************
5413  Reply to a lockingX request.
5414 ****************************************************************************/
5415
5416 int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
5417                    int length, int bufsize)
5418 {
5419         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
5420         unsigned char locktype = CVAL(inbuf,smb_vwv3);
5421         unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
5422         uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
5423         uint16 num_locks = SVAL(inbuf,smb_vwv7);
5424         SMB_BIG_UINT count = 0, offset = 0;
5425         uint32 lock_pid;
5426         int32 lock_timeout = IVAL(inbuf,smb_vwv4);
5427         int i;
5428         char *data;
5429         BOOL large_file_format =
5430                 (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
5431         BOOL err;
5432         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5433
5434         START_PROFILE(SMBlockingX);
5435         
5436         CHECK_FSP(fsp,conn);
5437         
5438         data = smb_buf(inbuf);
5439
5440         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
5441                 /* we don't support these - and CANCEL_LOCK makes w2k
5442                    and XP reboot so I don't really want to be
5443                    compatible! (tridge) */
5444                 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
5445         }
5446         
5447         /* Check if this is an oplock break on a file
5448            we have granted an oplock on.
5449         */
5450         if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
5451                 /* Client can insist on breaking to none. */
5452                 BOOL break_to_none = (oplocklevel == 0);
5453                 BOOL result;
5454
5455                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
5456                          "for fnum = %d\n", (unsigned int)oplocklevel,
5457                          fsp->fnum ));
5458
5459                 /*
5460                  * Make sure we have granted an exclusive or batch oplock on
5461                  * this file.
5462                  */
5463                 
5464                 if (fsp->oplock_type == 0) {
5465
5466                         /* The Samba4 nbench simulator doesn't understand
5467                            the difference between break to level2 and break
5468                            to none from level2 - it sends oplock break
5469                            replies in both cases. Don't keep logging an error
5470                            message here - just ignore it. JRA. */
5471
5472                         DEBUG(5,("reply_lockingX: Error : oplock break from "
5473                                  "client for fnum = %d (oplock=%d) and no "
5474                                  "oplock granted on this file (%s).\n",
5475                                  fsp->fnum, fsp->oplock_type, fsp->fsp_name));
5476
5477                         /* if this is a pure oplock break request then don't
5478                          * send a reply */
5479                         if (num_locks == 0 && num_ulocks == 0) {
5480                                 END_PROFILE(SMBlockingX);
5481                                 return -1;
5482                         } else {
5483                                 END_PROFILE(SMBlockingX);
5484                                 return ERROR_DOS(ERRDOS,ERRlock);
5485                         }
5486                 }
5487
5488                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
5489                     (break_to_none)) {
5490                         result = remove_oplock(fsp);
5491                 } else {
5492                         result = downgrade_oplock(fsp);
5493                 }
5494                 
5495                 if (!result) {
5496                         DEBUG(0, ("reply_lockingX: error in removing "
5497                                   "oplock on file %s\n", fsp->fsp_name));
5498                         /* Hmmm. Is this panic justified? */
5499                         smb_panic("internal tdb error");
5500                 }
5501
5502                 reply_to_oplock_break_requests(fsp);
5503
5504                 /* if this is a pure oplock break request then don't send a
5505                  * reply */
5506                 if (num_locks == 0 && num_ulocks == 0) {
5507                         /* Sanity check - ensure a pure oplock break is not a
5508                            chained request. */
5509                         if(CVAL(inbuf,smb_vwv0) != 0xff)
5510                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
5511                                          "break is a chained %d request !\n",
5512                                          (unsigned int)CVAL(inbuf,smb_vwv0) ));
5513                         END_PROFILE(SMBlockingX);
5514                         return -1;
5515                 }
5516         }
5517
5518         /*
5519          * We do this check *after* we have checked this is not a oplock break
5520          * response message. JRA.
5521          */
5522         
5523         release_level_2_oplocks_on_change(fsp);
5524         
5525         /* Data now points at the beginning of the list
5526            of smb_unlkrng structs */
5527         for(i = 0; i < (int)num_ulocks; i++) {
5528                 lock_pid = get_lock_pid( data, i, large_file_format);
5529                 count = get_lock_count( data, i, large_file_format);
5530                 offset = get_lock_offset( data, i, large_file_format, &err);
5531                 
5532                 /*
5533                  * There is no error code marked "stupid client bug".... :-).
5534                  */
5535                 if(err) {
5536                         END_PROFILE(SMBlockingX);
5537                         return ERROR_DOS(ERRDOS,ERRnoaccess);
5538                 }
5539
5540                 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
5541                           "pid %u, file %s\n", (double)offset, (double)count,
5542                           (unsigned int)lock_pid, fsp->fsp_name ));
5543                 
5544                 status = do_unlock(smbd_messaging_context(),
5545                                 fsp,
5546                                 lock_pid,
5547                                 count,
5548                                 offset,
5549                                 WINDOWS_LOCK);
5550
5551                 if (NT_STATUS_V(status)) {
5552                         END_PROFILE(SMBlockingX);
5553                         return ERROR_NT(status);
5554                 }
5555         }
5556
5557         /* Setup the timeout in seconds. */
5558
5559         if (!lp_blocking_locks(SNUM(conn))) {
5560                 lock_timeout = 0;
5561         }
5562         
5563         /* Now do any requested locks */
5564         data += ((large_file_format ? 20 : 10)*num_ulocks);
5565         
5566         /* Data now points at the beginning of the list
5567            of smb_lkrng structs */
5568         
5569         for(i = 0; i < (int)num_locks; i++) {
5570                 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
5571                                 READ_LOCK:WRITE_LOCK);
5572                 lock_pid = get_lock_pid( data, i, large_file_format);
5573                 count = get_lock_count( data, i, large_file_format);
5574                 offset = get_lock_offset( data, i, large_file_format, &err);
5575                 
5576                 /*
5577                  * There is no error code marked "stupid client bug".... :-).
5578                  */
5579                 if(err) {
5580                         END_PROFILE(SMBlockingX);
5581                         return ERROR_DOS(ERRDOS,ERRnoaccess);
5582                 }
5583                 
5584                 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
5585                           "%u, file %s timeout = %d\n", (double)offset,
5586                           (double)count, (unsigned int)lock_pid,
5587                           fsp->fsp_name, (int)lock_timeout ));
5588                 
5589                 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
5590                         if (lp_blocking_locks(SNUM(conn))) {
5591
5592                                 /* Schedule a message to ourselves to
5593                                    remove the blocking lock record and
5594                                    return the right error. */
5595
5596                                 if (!blocking_lock_cancel(fsp,
5597                                                 lock_pid,
5598                                                 offset,
5599                                                 count,
5600                                                 WINDOWS_LOCK,
5601                                                 locktype,
5602                                                 NT_STATUS_FILE_LOCK_CONFLICT)) {
5603                                         END_PROFILE(SMBlockingX);
5604                                         return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
5605                                 }
5606                         }
5607                         /* Remove a matching pending lock. */
5608                         status = do_lock_cancel(fsp,
5609                                                 lock_pid,
5610                                                 count,
5611                                                 offset,
5612                                                 WINDOWS_LOCK);
5613                 } else {
5614                         BOOL blocking_lock = lock_timeout ? True : False;
5615                         BOOL defer_lock = False;
5616                         struct byte_range_lock *br_lck;
5617                         uint32 block_smbpid;
5618
5619                         br_lck = do_lock(smbd_messaging_context(),
5620                                         fsp,
5621                                         lock_pid,
5622                                         count,
5623                                         offset, 
5624                                         lock_type,
5625                                         WINDOWS_LOCK,
5626                                         blocking_lock,
5627                                         &status,
5628                                         &block_smbpid);
5629
5630                         if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5631                                 /* Windows internal resolution for blocking locks seems
5632                                    to be about 200ms... Don't wait for less than that. JRA. */
5633                                 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
5634                                         lock_timeout = lp_lock_spin_time();
5635                                 }
5636                                 defer_lock = True;
5637                         }
5638
5639                         /* This heuristic seems to match W2K3 very well. If a
5640                            lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
5641                            it pretends we asked for a timeout of between 150 - 300 milliseconds as
5642                            far as I can tell. Replacement for do_lock_spin(). JRA. */
5643
5644                         if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
5645                                         NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
5646                                 defer_lock = True;
5647                                 lock_timeout = lp_lock_spin_time();
5648                         }
5649
5650                         if (br_lck && defer_lock) {
5651                                 /*
5652                                  * A blocking lock was requested. Package up
5653                                  * this smb into a queued request and push it
5654                                  * onto the blocking lock queue.
5655                                  */
5656                                 if(push_blocking_lock_request(br_lck,
5657                                                         inbuf, length,
5658                                                         fsp,
5659                                                         lock_timeout,
5660                                                         i,
5661                                                         lock_pid,
5662                                                         lock_type,
5663                                                         WINDOWS_LOCK,
5664                                                         offset,
5665                                                         count,
5666                                                         block_smbpid)) {
5667                                         TALLOC_FREE(br_lck);
5668                                         END_PROFILE(SMBlockingX);
5669                                         return -1;
5670                                 }
5671                         }
5672
5673                         TALLOC_FREE(br_lck);
5674                 }
5675
5676                 if (NT_STATUS_V(status)) {
5677                         END_PROFILE(SMBlockingX);
5678                         return ERROR_NT(status);
5679                 }
5680         }
5681         
5682         /* If any of the above locks failed, then we must unlock
5683            all of the previous locks (X/Open spec). */
5684
5685         if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
5686                         (i != num_locks) &&
5687                         (num_locks != 0)) {
5688                 /*
5689                  * Ensure we don't do a remove on the lock that just failed,
5690                  * as under POSIX rules, if we have a lock already there, we
5691                  * will delete it (and we shouldn't) .....
5692                  */
5693                 for(i--; i >= 0; i--) {
5694                         lock_pid = get_lock_pid( data, i, large_file_format);
5695                         count = get_lock_count( data, i, large_file_format);
5696                         offset = get_lock_offset( data, i, large_file_format,
5697                                                   &err);
5698                         
5699                         /*
5700                          * There is no error code marked "stupid client
5701                          * bug".... :-).
5702                          */
5703                         if(err) {
5704                                 END_PROFILE(SMBlockingX);
5705                                 return ERROR_DOS(ERRDOS,ERRnoaccess);
5706                         }
5707                         
5708                         do_unlock(smbd_messaging_context(),
5709                                 fsp,
5710                                 lock_pid,
5711                                 count,
5712                                 offset,
5713                                 WINDOWS_LOCK);
5714                 }
5715                 END_PROFILE(SMBlockingX);
5716                 return ERROR_NT(status);
5717         }
5718
5719         set_message(inbuf,outbuf,2,0,True);
5720         
5721         DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5722                   fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
5723         
5724         END_PROFILE(SMBlockingX);
5725         return chain_reply(inbuf,outbuf,length,bufsize);
5726 }
5727
5728 #undef DBGC_CLASS
5729 #define DBGC_CLASS DBGC_ALL
5730
5731 /****************************************************************************
5732  Reply to a SMBreadbmpx (read block multiplex) request.
5733 ****************************************************************************/
5734
5735 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5736 {
5737         ssize_t nread = -1;
5738         ssize_t total_read;
5739         char *data;
5740         SMB_OFF_T startpos;
5741         int outsize;
5742         size_t maxcount;
5743         int max_per_packet;
5744         size_t tcount;
5745         int pad;
5746         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5747         START_PROFILE(SMBreadBmpx);
5748
5749         /* this function doesn't seem to work - disable by default */
5750         if (!lp_readbmpx()) {
5751                 END_PROFILE(SMBreadBmpx);
5752                 return ERROR_DOS(ERRSRV,ERRuseSTD);
5753         }
5754
5755         outsize = set_message(inbuf,outbuf,8,0,True);
5756
5757         CHECK_FSP(fsp,conn);
5758         if (!CHECK_READ(fsp,inbuf)) {
5759                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5760         }
5761
5762         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5763         maxcount = SVAL(inbuf,smb_vwv3);
5764
5765         data = smb_buf(outbuf);
5766         pad = ((long)data)%4;
5767         if (pad)
5768                 pad = 4 - pad;
5769         data += pad;
5770
5771         max_per_packet = bufsize-(outsize+pad);
5772         tcount = maxcount;
5773         total_read = 0;
5774
5775         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5776                 END_PROFILE(SMBreadBmpx);
5777                 return ERROR_DOS(ERRDOS,ERRlock);
5778         }
5779
5780         do {
5781                 size_t N = MIN(max_per_packet,tcount-total_read);
5782   
5783                 nread = read_file(fsp,data,startpos,N);
5784
5785                 if (nread <= 0)
5786                         nread = 0;
5787
5788                 if (nread < (ssize_t)N)
5789                         tcount = total_read + nread;
5790
5791                 set_message(inbuf,outbuf,8,nread+pad,False);
5792                 SIVAL(outbuf,smb_vwv0,startpos);
5793                 SSVAL(outbuf,smb_vwv2,tcount);
5794                 SSVAL(outbuf,smb_vwv6,nread);
5795                 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5796
5797                 show_msg(outbuf);
5798                 if (!send_smb(smbd_server_fd(),outbuf))
5799                         exit_server_cleanly("reply_readbmpx: send_smb failed.");
5800
5801                 total_read += nread;
5802                 startpos += nread;
5803         } while (total_read < (ssize_t)tcount);
5804
5805         END_PROFILE(SMBreadBmpx);
5806         return(-1);
5807 }
5808
5809 /****************************************************************************
5810  Reply to a SMBsetattrE.
5811 ****************************************************************************/
5812
5813 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5814 {
5815         struct timespec ts[2];
5816         int outsize = 0;
5817         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5818         START_PROFILE(SMBsetattrE);
5819
5820         outsize = set_message(inbuf,outbuf,0,0,False);
5821
5822         if(!fsp || (fsp->conn != conn)) {
5823                 END_PROFILE(SMBsetattrE);
5824                 return ERROR_DOS(ERRDOS,ERRbadfid);
5825         }
5826
5827         /*
5828          * Convert the DOS times into unix times. Ignore create
5829          * time as UNIX can't set this.
5830          */
5831
5832         ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv3)); /* atime. */
5833         ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv5)); /* mtime. */
5834   
5835         /* 
5836          * Patch from Ray Frush <frush@engr.colostate.edu>
5837          * Sometimes times are sent as zero - ignore them.
5838          */
5839
5840         if (null_timespec(ts[0]) && null_timespec(ts[1])) {
5841                 /* Ignore request */
5842                 if( DEBUGLVL( 3 ) ) {
5843                         dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5844                         dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5845                 }
5846                 END_PROFILE(SMBsetattrE);
5847                 return(outsize);
5848         } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
5849                 /* set modify time = to access time if modify time was unset */
5850                 ts[1] = ts[0];
5851         }
5852
5853         /* Set the date on this file */
5854         /* Should we set pending modtime here ? JRA */
5855         if(file_ntimes(conn, fsp->fsp_name, ts)) {
5856                 END_PROFILE(SMBsetattrE);
5857                 return ERROR_DOS(ERRDOS,ERRnoaccess);
5858         }
5859   
5860         DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
5861                 fsp->fnum,
5862                 (unsigned int)ts[0].tv_sec,
5863                 (unsigned int)ts[1].tv_sec));
5864
5865         END_PROFILE(SMBsetattrE);
5866         return(outsize);
5867 }
5868
5869
5870 /* Back from the dead for OS/2..... JRA. */
5871
5872 /****************************************************************************
5873  Reply to a SMBwritebmpx (write block multiplex primary) request.
5874 ****************************************************************************/
5875
5876 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5877 {
5878         size_t numtowrite;
5879         ssize_t nwritten = -1;
5880         int outsize = 0;
5881         SMB_OFF_T startpos;
5882         size_t tcount;
5883         BOOL write_through;
5884         int smb_doff;
5885         char *data;
5886         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5887         NTSTATUS status;
5888         START_PROFILE(SMBwriteBmpx);
5889
5890         CHECK_FSP(fsp,conn);
5891         if (!CHECK_WRITE(fsp)) {
5892                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5893         }
5894         if (HAS_CACHED_ERROR(fsp)) {
5895                 return(CACHED_ERROR(fsp));
5896         }
5897
5898         tcount = SVAL(inbuf,smb_vwv1);
5899         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
5900         write_through = BITSETW(inbuf+smb_vwv7,0);
5901         numtowrite = SVAL(inbuf,smb_vwv10);
5902         smb_doff = SVAL(inbuf,smb_vwv11);
5903
5904         data = smb_base(inbuf) + smb_doff;
5905
5906         /* If this fails we need to send an SMBwriteC response,
5907                 not an SMBwritebmpx - set this up now so we don't forget */
5908         SCVAL(outbuf,smb_com,SMBwritec);
5909
5910         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
5911                 END_PROFILE(SMBwriteBmpx);
5912                 return(ERROR_DOS(ERRDOS,ERRlock));
5913         }
5914
5915         nwritten = write_file(fsp,data,startpos,numtowrite);
5916
5917         status = sync_file(conn, fsp, write_through);
5918         if (!NT_STATUS_IS_OK(status)) {
5919                 END_PROFILE(SMBwriteBmpx);
5920                 DEBUG(5,("reply_writebmpx: sync_file for %s returned %s\n",
5921                         fsp->fsp_name, nt_errstr(status) ));
5922                 return ERROR_NT(status);
5923         }
5924   
5925         if(nwritten < (ssize_t)numtowrite) {
5926                 END_PROFILE(SMBwriteBmpx);
5927                 return(UNIXERROR(ERRHRD,ERRdiskfull));
5928         }
5929
5930         /* If the maximum to be written to this file
5931                 is greater than what we just wrote then set
5932                 up a secondary struct to be attached to this
5933                 fd, we will use this to cache error messages etc. */
5934
5935         if((ssize_t)tcount > nwritten) {
5936                 write_bmpx_struct *wbms;
5937                 if(fsp->wbmpx_ptr != NULL)
5938                         wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5939                 else
5940                         wbms = SMB_MALLOC_P(write_bmpx_struct);
5941                 if(!wbms) {
5942                         DEBUG(0,("Out of memory in reply_readmpx\n"));
5943                         END_PROFILE(SMBwriteBmpx);
5944                         return(ERROR_DOS(ERRSRV,ERRnoresource));
5945                 }
5946                 wbms->wr_mode = write_through;
5947                 wbms->wr_discard = False; /* No errors yet */
5948                 wbms->wr_total_written = nwritten;
5949                 wbms->wr_errclass = 0;
5950                 wbms->wr_error = 0;
5951                 fsp->wbmpx_ptr = wbms;
5952         }
5953
5954         /* We are returning successfully, set the message type back to
5955                 SMBwritebmpx */
5956         SCVAL(outbuf,smb_com,SMBwriteBmpx);
5957   
5958         outsize = set_message(inbuf,outbuf,1,0,True);
5959   
5960         SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5961   
5962         DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5963                         fsp->fnum, (int)numtowrite, (int)nwritten ) );
5964
5965         if (write_through && tcount==nwritten) {
5966                 /* We need to send both a primary and a secondary response */
5967                 smb_setlen(inbuf,outbuf,outsize - 4);
5968                 show_msg(outbuf);
5969                 if (!send_smb(smbd_server_fd(),outbuf))
5970                         exit_server_cleanly("reply_writebmpx: send_smb failed.");
5971
5972                 /* Now the secondary */
5973                 outsize = set_message(inbuf,outbuf,1,0,True);
5974                 SCVAL(outbuf,smb_com,SMBwritec);
5975                 SSVAL(outbuf,smb_vwv0,nwritten);
5976         }
5977
5978         END_PROFILE(SMBwriteBmpx);
5979         return(outsize);
5980 }
5981
5982 /****************************************************************************
5983  Reply to a SMBwritebs (write block multiplex secondary) request.
5984 ****************************************************************************/
5985
5986 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5987 {
5988         size_t numtowrite;
5989         ssize_t nwritten = -1;
5990         int outsize = 0;
5991         SMB_OFF_T startpos;
5992         size_t tcount;
5993         BOOL write_through;
5994         int smb_doff;
5995         char *data;
5996         write_bmpx_struct *wbms;
5997         BOOL send_response = False; 
5998         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5999         NTSTATUS status;
6000         START_PROFILE(SMBwriteBs);
6001
6002         CHECK_FSP(fsp,conn);
6003         if (!CHECK_WRITE(fsp)) {
6004                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
6005         }
6006
6007         tcount = SVAL(inbuf,smb_vwv1);
6008         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
6009         numtowrite = SVAL(inbuf,smb_vwv6);
6010         smb_doff = SVAL(inbuf,smb_vwv7);
6011
6012         data = smb_base(inbuf) + smb_doff;
6013
6014         /* We need to send an SMBwriteC response, not an SMBwritebs */
6015         SCVAL(outbuf,smb_com,SMBwritec);
6016
6017         /* This fd should have an auxiliary struct attached,
6018                 check that it does */
6019         wbms = fsp->wbmpx_ptr;
6020         if(!wbms) {
6021                 END_PROFILE(SMBwriteBs);
6022                 return(-1);
6023         }
6024
6025         /* If write through is set we can return errors, else we must cache them */
6026         write_through = wbms->wr_mode;
6027
6028         /* Check for an earlier error */
6029         if(wbms->wr_discard) {
6030                 END_PROFILE(SMBwriteBs);
6031                 return -1; /* Just discard the packet */
6032         }
6033
6034         nwritten = write_file(fsp,data,startpos,numtowrite);
6035
6036         status = sync_file(conn, fsp, write_through);
6037   
6038         if (nwritten < (ssize_t)numtowrite || !NT_STATUS_IS_OK(status)) {
6039                 if(write_through) {
6040                         /* We are returning an error - we can delete the aux struct */
6041                         if (wbms)
6042                                 free((char *)wbms);
6043                         fsp->wbmpx_ptr = NULL;
6044                         END_PROFILE(SMBwriteBs);
6045                         return(ERROR_DOS(ERRHRD,ERRdiskfull));
6046                 }
6047                 wbms->wr_errclass = ERRHRD;
6048                 wbms->wr_error = ERRdiskfull;
6049                 wbms->wr_status = NT_STATUS_DISK_FULL;
6050                 wbms->wr_discard = True;
6051                 END_PROFILE(SMBwriteBs);
6052                 return -1;
6053         }
6054
6055         /* Increment the total written, if this matches tcount
6056                 we can discard the auxiliary struct (hurrah !) and return a writeC */
6057         wbms->wr_total_written += nwritten;
6058         if(wbms->wr_total_written >= tcount) {
6059                 if (write_through) {
6060                         outsize = set_message(inbuf,outbuf,1,0,True);
6061                         SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);    
6062                         send_response = True;
6063                 }
6064
6065                 free((char *)wbms);
6066                 fsp->wbmpx_ptr = NULL;
6067         }
6068
6069         if(send_response) {
6070                 END_PROFILE(SMBwriteBs);
6071                 return(outsize);
6072         }
6073
6074         END_PROFILE(SMBwriteBs);
6075         return(-1);
6076 }
6077
6078 /****************************************************************************
6079  Reply to a SMBgetattrE.
6080 ****************************************************************************/
6081
6082 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
6083 {
6084         SMB_STRUCT_STAT sbuf;
6085         int outsize = 0;
6086         int mode;
6087         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
6088         START_PROFILE(SMBgetattrE);
6089
6090         outsize = set_message(inbuf,outbuf,11,0,True);
6091
6092         if(!fsp || (fsp->conn != conn)) {
6093                 END_PROFILE(SMBgetattrE);
6094                 return ERROR_DOS(ERRDOS,ERRbadfid);
6095         }
6096
6097         /* Do an fstat on this file */
6098         if(fsp_stat(fsp, &sbuf)) {
6099                 END_PROFILE(SMBgetattrE);
6100                 return(UNIXERROR(ERRDOS,ERRnoaccess));
6101         }
6102   
6103         mode = dos_mode(conn,fsp->fsp_name,&sbuf);
6104   
6105         /*
6106          * Convert the times into dos times. Set create
6107          * date to be last modify date as UNIX doesn't save
6108          * this.
6109          */
6110
6111         srv_put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
6112         srv_put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
6113         /* Should we check pending modtime here ? JRA */
6114         srv_put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
6115
6116         if (mode & aDIR) {
6117                 SIVAL(outbuf,smb_vwv6,0);
6118                 SIVAL(outbuf,smb_vwv8,0);
6119         } else {
6120                 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
6121                 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
6122                 SIVAL(outbuf,smb_vwv8,allocation_size);
6123         }
6124         SSVAL(outbuf,smb_vwv10, mode);
6125   
6126         DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
6127   
6128         END_PROFILE(SMBgetattrE);
6129         return(outsize);
6130 }