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