r24347: fake_sendfile does not need Inbuf/Outbuf
[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(char *inbuf, char *outbuf, size_t smb_maxcnt)
2732 {
2733         int outsize;
2734         char *data = smb_buf(outbuf);
2735
2736         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2737         SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2738         SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2739         SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
2740         SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2741         SCVAL(outbuf,smb_vwv0,0xFF);
2742         outsize = set_message(inbuf, outbuf,12,smb_maxcnt,False);
2743         /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
2744         _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
2745         return outsize;
2746 }
2747
2748 /****************************************************************************
2749  Reply to a read and X - possibly using sendfile.
2750 ****************************************************************************/
2751
2752 static void send_file_readX(connection_struct *conn, struct smb_request *req,
2753                             files_struct *fsp, SMB_OFF_T startpos,
2754                             size_t smb_maxcnt)
2755 {
2756         SMB_STRUCT_STAT sbuf;
2757         ssize_t nread = -1;
2758         char *data;
2759         char *inbuf, *outbuf;
2760         int length, len_outbuf;
2761
2762         if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &len_outbuf)) {
2763                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2764                 return;
2765         }
2766
2767         set_message(inbuf, outbuf, 12, 0, True);
2768
2769         data = smb_buf(outbuf);
2770
2771         if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
2772                 reply_unixerror(req, ERRDOS, ERRnoaccess);
2773                 return;
2774         }
2775
2776         if (startpos > sbuf.st_size) {
2777                 smb_maxcnt = 0;
2778         } else if (smb_maxcnt > (sbuf.st_size - startpos)) {
2779                 smb_maxcnt = (sbuf.st_size - startpos);
2780         }
2781
2782         if (smb_maxcnt == 0) {
2783                 goto normal_read;
2784         }
2785
2786 #if defined(WITH_SENDFILE)
2787         /*
2788          * We can only use sendfile on a non-chained packet 
2789          * but we can use on a non-oplocked file. tridge proved this
2790          * on a train in Germany :-). JRA.
2791          */
2792
2793         if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
2794             lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
2795                 DATA_BLOB header;
2796
2797                 /* 
2798                  * Set up the packet header before send. We
2799                  * assume here the sendfile will work (get the
2800                  * correct amount of data).
2801                  */
2802
2803                 setup_readX_header(inbuf,outbuf,smb_maxcnt);
2804                 set_message(inbuf,outbuf,12,smb_maxcnt,False);
2805                 header.data = (uint8 *)outbuf;
2806                 header.length = data - outbuf;
2807                 header.free = NULL;
2808
2809                 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
2810                         /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2811                         if (errno == ENOSYS) {
2812                                 goto normal_read;
2813                         }
2814
2815                         /*
2816                          * Special hack for broken Linux with no working sendfile. If we
2817                          * return EINTR we sent the header but not the rest of the data.
2818                          * Fake this up by doing read/write calls.
2819                          */
2820
2821                         if (errno == EINTR) {
2822                                 /* Ensure we don't do this again. */
2823                                 set_use_sendfile(SNUM(conn), False);
2824                                 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2825                                 nread = fake_sendfile(fsp, startpos,
2826                                                       smb_maxcnt);
2827                                 if (nread == -1) {
2828                                         DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2829                                                 fsp->fsp_name, strerror(errno) ));
2830                                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
2831                                 }
2832                                 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2833                                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2834                                 /* No outbuf here means successful sendfile. */
2835                                 TALLOC_FREE(req->outbuf);
2836                                 return;
2837                         }
2838
2839                         DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2840                                 fsp->fsp_name, strerror(errno) ));
2841                         exit_server_cleanly("send_file_readX sendfile failed");
2842                 }
2843
2844                 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2845                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2846                 /* No outbuf here means successful sendfile. */
2847                 TALLOC_FREE(req->outbuf);
2848                 return;
2849         }
2850
2851 #endif
2852
2853 normal_read:
2854
2855         if ((smb_maxcnt & 0xFF0000) > 0x10000) {
2856                 int sendlen = setup_readX_header(inbuf,outbuf,smb_maxcnt) - smb_maxcnt;
2857                 /* Send out the header. */
2858                 if (write_data(smbd_server_fd(),outbuf,sendlen) != sendlen) {
2859                         DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
2860                                 fsp->fsp_name, strerror(errno) ));
2861                         exit_server_cleanly("send_file_readX sendfile failed");
2862                 }
2863                 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
2864                 if (nread == -1) {
2865                         DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2866                                 fsp->fsp_name, strerror(errno) ));
2867                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
2868                 }
2869                 TALLOC_FREE(req->outbuf);
2870                 return;
2871         } else {
2872                 nread = read_file(fsp,data,startpos,smb_maxcnt);
2873
2874                 if (nread < 0) {
2875                         reply_unixerror(req, ERRDOS, ERRnoaccess);
2876                         return;
2877                 }
2878
2879                 setup_readX_header(inbuf, outbuf,nread);
2880
2881                 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2882                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2883
2884                 chain_reply_new(req);
2885
2886                 return;
2887         }
2888 }
2889
2890 /****************************************************************************
2891  Reply to a read and X.
2892 ****************************************************************************/
2893
2894 void reply_read_and_X(connection_struct *conn, struct smb_request *req)
2895 {
2896         files_struct *fsp;
2897         SMB_OFF_T startpos;
2898         size_t smb_maxcnt;
2899         BOOL big_readX = False;
2900 #if 0
2901         size_t smb_mincnt = SVAL(req->inbuf,smb_vwv6);
2902 #endif
2903
2904         START_PROFILE(SMBreadX);
2905
2906         if ((req->wct != 10) && (req->wct != 12)) {
2907                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2908                 return;
2909         }
2910
2911         fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
2912         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
2913         smb_maxcnt = SVAL(req->inbuf,smb_vwv5);
2914
2915         /* If it's an IPC, pass off the pipe handler. */
2916         if (IS_IPC(conn)) {
2917                 reply_pipe_read_and_X(req);
2918                 END_PROFILE(SMBreadX);
2919                 return;
2920         }
2921
2922         if (!check_fsp(conn, req, fsp, &current_user)) {
2923                 END_PROFILE(SMBreadX);
2924                 return;
2925         }
2926
2927         if (!CHECK_READ(fsp,req->inbuf)) {
2928                 reply_doserror(req, ERRDOS,ERRbadaccess);
2929                 END_PROFILE(SMBreadX);
2930                 return;
2931         }
2932
2933         if (global_client_caps & CAP_LARGE_READX) {
2934                 size_t upper_size = SVAL(req->inbuf,smb_vwv7);
2935                 smb_maxcnt |= (upper_size<<16);
2936                 if (upper_size > 1) {
2937                         /* Can't do this on a chained packet. */
2938                         if ((CVAL(req->inbuf,smb_vwv0) != 0xFF)) {
2939                                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
2940                                 END_PROFILE(SMBreadX);
2941                                 return;
2942                         }
2943                         /* We currently don't do this on signed or sealed data. */
2944                         if (srv_is_signing_active() || srv_encryption_on()) {
2945                                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
2946                                 END_PROFILE(SMBreadX);
2947                                 return;
2948                         }
2949                         /* Is there room in the reply for this data ? */
2950                         if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2)))  {
2951                                 reply_nterror(req,
2952                                               NT_STATUS_INVALID_PARAMETER);
2953                                 END_PROFILE(SMBreadX);
2954                                 return;
2955                         }
2956                         big_readX = True;
2957                 }
2958         }
2959
2960         if (req->wct == 12) {
2961 #ifdef LARGE_SMB_OFF_T
2962                 /*
2963                  * This is a large offset (64 bit) read.
2964                  */
2965                 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv10)) << 32);
2966
2967 #else /* !LARGE_SMB_OFF_T */
2968
2969                 /*
2970                  * Ensure we haven't been sent a >32 bit offset.
2971                  */
2972
2973                 if(IVAL(req->inbuf,smb_vwv10) != 0) {
2974                         DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
2975                                  "used and we don't support 64 bit offsets.\n",
2976                                  (unsigned int)IVAL(req->inbuf,smb_vwv10) ));
2977                         END_PROFILE(SMBreadX);
2978                         reply_doserror(req, ERRDOS, ERRbadaccess);
2979                         return;
2980                 }
2981
2982 #endif /* LARGE_SMB_OFF_T */
2983
2984         }
2985
2986         if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)smb_maxcnt,
2987                       (SMB_BIG_UINT)startpos, READ_LOCK)) {
2988                 END_PROFILE(SMBreadX);
2989                 reply_doserror(req, ERRDOS, ERRlock);
2990                 return;
2991         }
2992
2993         if (!big_readX
2994             && schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
2995                 END_PROFILE(SMBreadX);
2996                 reply_post_legacy(req, -1);
2997                 return;
2998         }
2999
3000         send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3001
3002         END_PROFILE(SMBreadX);
3003         return;
3004 }
3005
3006 /****************************************************************************
3007  Reply to a writebraw (core+ or LANMAN1.0 protocol).
3008 ****************************************************************************/
3009
3010 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3011 {
3012         ssize_t nwritten=0;
3013         ssize_t total_written=0;
3014         size_t numtowrite=0;
3015         size_t tcount;
3016         SMB_OFF_T startpos;
3017         char *data=NULL;
3018         BOOL write_through;
3019         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3020         int outsize = 0;
3021         NTSTATUS status;
3022         START_PROFILE(SMBwritebraw);
3023
3024         if (srv_is_signing_active()) {
3025                 exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
3026         }
3027
3028         CHECK_FSP(fsp,conn);
3029         if (!CHECK_WRITE(fsp)) {
3030                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3031         }
3032   
3033         tcount = IVAL(inbuf,smb_vwv1);
3034         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
3035         write_through = BITSETW(inbuf+smb_vwv7,0);
3036
3037         /* We have to deal with slightly different formats depending
3038                 on whether we are using the core+ or lanman1.0 protocol */
3039
3040         if(Protocol <= PROTOCOL_COREPLUS) {
3041                 numtowrite = SVAL(smb_buf(inbuf),-2);
3042                 data = smb_buf(inbuf);
3043         } else {
3044                 numtowrite = SVAL(inbuf,smb_vwv10);
3045                 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
3046         }
3047
3048         /* force the error type */
3049         SCVAL(inbuf,smb_com,SMBwritec);
3050         SCVAL(outbuf,smb_com,SMBwritec);
3051
3052         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3053                 END_PROFILE(SMBwritebraw);
3054                 return(ERROR_DOS(ERRDOS,ERRlock));
3055         }
3056
3057         if (numtowrite>0)
3058                 nwritten = write_file(fsp,data,startpos,numtowrite);
3059   
3060         DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
3061                 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
3062
3063         if (nwritten < (ssize_t)numtowrite)  {
3064                 END_PROFILE(SMBwritebraw);
3065                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3066         }
3067
3068         total_written = nwritten;
3069
3070         /* Return a message to the redirector to tell it to send more bytes */
3071         SCVAL(outbuf,smb_com,SMBwritebraw);
3072         SSVALS(outbuf,smb_vwv0,-1);
3073         outsize = set_message(inbuf,outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3074         show_msg(outbuf);
3075         if (!send_smb(smbd_server_fd(),outbuf))
3076                 exit_server_cleanly("reply_writebraw: send_smb failed.");
3077   
3078         /* Now read the raw data into the buffer and write it */
3079         if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
3080                 exit_server_cleanly("secondary writebraw failed");
3081         }
3082   
3083         /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
3084         numtowrite = smb_len(inbuf);
3085
3086         /* Set up outbuf to return the correct return */
3087         outsize = set_message(inbuf,outbuf,1,0,True);
3088         SCVAL(outbuf,smb_com,SMBwritec);
3089
3090         if (numtowrite != 0) {
3091
3092                 if (numtowrite > BUFFER_SIZE) {
3093                         DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
3094                                 (unsigned int)numtowrite ));
3095                         exit_server_cleanly("secondary writebraw failed");
3096                 }
3097
3098                 if (tcount > nwritten+numtowrite) {
3099                         DEBUG(3,("Client overestimated the write %d %d %d\n",
3100                                 (int)tcount,(int)nwritten,(int)numtowrite));
3101                 }
3102
3103                 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
3104                         DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
3105                                 strerror(errno) ));
3106                         exit_server_cleanly("secondary writebraw failed");
3107                 }
3108
3109                 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
3110                 if (nwritten == -1) {
3111                         END_PROFILE(SMBwritebraw);
3112                         return(UNIXERROR(ERRHRD,ERRdiskfull));
3113                 }
3114
3115                 if (nwritten < (ssize_t)numtowrite) {
3116                         SCVAL(outbuf,smb_rcls,ERRHRD);
3117                         SSVAL(outbuf,smb_err,ERRdiskfull);      
3118                 }
3119
3120                 if (nwritten > 0)
3121                         total_written += nwritten;
3122         }
3123  
3124         SSVAL(outbuf,smb_vwv0,total_written);
3125
3126         status = sync_file(conn, fsp, write_through);
3127         if (!NT_STATUS_IS_OK(status)) {
3128                 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3129                         fsp->fsp_name, nt_errstr(status) ));
3130                 END_PROFILE(SMBwritebraw);
3131                 return ERROR_NT(status);
3132         }
3133
3134         DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
3135                 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
3136
3137         /* we won't return a status if write through is not selected - this follows what WfWg does */
3138         END_PROFILE(SMBwritebraw);
3139         if (!write_through && total_written==tcount) {
3140
3141 #if RABBIT_PELLET_FIX
3142                 /*
3143                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3144                  * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
3145                  */
3146                 if (!send_keepalive(smbd_server_fd()))
3147                         exit_server_cleanly("reply_writebraw: send of keepalive failed");
3148 #endif
3149                 return(-1);
3150         }
3151
3152         return(outsize);
3153 }
3154
3155 #undef DBGC_CLASS
3156 #define DBGC_CLASS DBGC_LOCKING
3157
3158 /****************************************************************************
3159  Reply to a writeunlock (core+).
3160 ****************************************************************************/
3161
3162 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, 
3163                       int size, int dum_buffsize)
3164 {
3165         ssize_t nwritten = -1;
3166         size_t numtowrite;
3167         SMB_OFF_T startpos;
3168         char *data;
3169         NTSTATUS status = NT_STATUS_OK;
3170         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3171         int outsize = 0;
3172         START_PROFILE(SMBwriteunlock);
3173         
3174         CHECK_FSP(fsp,conn);
3175         if (!CHECK_WRITE(fsp)) {
3176                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3177         }
3178
3179         numtowrite = SVAL(inbuf,smb_vwv1);
3180         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3181         data = smb_buf(inbuf) + 3;
3182   
3183         if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3184                 END_PROFILE(SMBwriteunlock);
3185                 return ERROR_DOS(ERRDOS,ERRlock);
3186         }
3187
3188         /* The special X/Open SMB protocol handling of
3189            zero length writes is *NOT* done for
3190            this call */
3191         if(numtowrite == 0) {
3192                 nwritten = 0;
3193         } else {
3194                 nwritten = write_file(fsp,data,startpos,numtowrite);
3195         }
3196   
3197         status = sync_file(conn, fsp, False /* write through */);
3198         if (!NT_STATUS_IS_OK(status)) {
3199                 END_PROFILE(SMBwriteunlock);
3200                 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3201                         fsp->fsp_name, nt_errstr(status) ));
3202                 return ERROR_NT(status);
3203         }
3204
3205         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3206                 END_PROFILE(SMBwriteunlock);
3207                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3208         }
3209
3210         if (numtowrite) {
3211                 status = do_unlock(smbd_messaging_context(),
3212                                 fsp,
3213                                 (uint32)SVAL(inbuf,smb_pid),
3214                                 (SMB_BIG_UINT)numtowrite, 
3215                                 (SMB_BIG_UINT)startpos,
3216                                 WINDOWS_LOCK);
3217
3218                 if (NT_STATUS_V(status)) {
3219                         END_PROFILE(SMBwriteunlock);
3220                         return ERROR_NT(status);
3221                 }
3222         }
3223         
3224         outsize = set_message(inbuf,outbuf,1,0,True);
3225         
3226         SSVAL(outbuf,smb_vwv0,nwritten);
3227         
3228         DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3229                  fsp->fnum, (int)numtowrite, (int)nwritten));
3230         
3231         END_PROFILE(SMBwriteunlock);
3232         return outsize;
3233 }
3234
3235 #undef DBGC_CLASS
3236 #define DBGC_CLASS DBGC_ALL
3237
3238 /****************************************************************************
3239  Reply to a write.
3240 ****************************************************************************/
3241
3242 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
3243 {
3244         size_t numtowrite;
3245         ssize_t nwritten = -1;
3246         SMB_OFF_T startpos;
3247         char *data;
3248         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3249         int outsize = 0;
3250         NTSTATUS status;
3251         START_PROFILE(SMBwrite);
3252
3253         /* If it's an IPC, pass off the pipe handler. */
3254         if (IS_IPC(conn)) {
3255                 END_PROFILE(SMBwrite);
3256                 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
3257         }
3258
3259         CHECK_FSP(fsp,conn);
3260         if (!CHECK_WRITE(fsp)) {
3261                 END_PROFILE(SMBwrite);
3262                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3263         }
3264
3265         numtowrite = SVAL(inbuf,smb_vwv1);
3266         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3267         data = smb_buf(inbuf) + 3;
3268   
3269         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3270                 END_PROFILE(SMBwrite);
3271                 return ERROR_DOS(ERRDOS,ERRlock);
3272         }
3273
3274         /*
3275          * X/Open SMB protocol says that if smb_vwv1 is
3276          * zero then the file size should be extended or
3277          * truncated to the size given in smb_vwv[2-3].
3278          */
3279
3280         if(numtowrite == 0) {
3281                 /*
3282                  * This is actually an allocate call, and set EOF. JRA.
3283                  */
3284                 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3285                 if (nwritten < 0) {
3286                         END_PROFILE(SMBwrite);
3287                         return ERROR_NT(NT_STATUS_DISK_FULL);
3288                 }
3289                 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3290                 if (nwritten < 0) {
3291                         END_PROFILE(SMBwrite);
3292                         return ERROR_NT(NT_STATUS_DISK_FULL);
3293                 }
3294         } else
3295                 nwritten = write_file(fsp,data,startpos,numtowrite);
3296   
3297         status = sync_file(conn, fsp, False);
3298         if (!NT_STATUS_IS_OK(status)) {
3299                 END_PROFILE(SMBwrite);
3300                 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3301                         fsp->fsp_name, nt_errstr(status) ));
3302                 return ERROR_NT(status);
3303         }
3304
3305         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3306                 END_PROFILE(SMBwrite);
3307                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3308         }
3309
3310         outsize = set_message(inbuf,outbuf,1,0,True);
3311   
3312         SSVAL(outbuf,smb_vwv0,nwritten);
3313
3314         if (nwritten < (ssize_t)numtowrite) {
3315                 SCVAL(outbuf,smb_rcls,ERRHRD);
3316                 SSVAL(outbuf,smb_err,ERRdiskfull);      
3317         }
3318   
3319         DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3320
3321         END_PROFILE(SMBwrite);
3322         return(outsize);
3323 }
3324
3325 /****************************************************************************
3326  Reply to a write and X.
3327 ****************************************************************************/
3328
3329 void reply_write_and_X(connection_struct *conn, struct smb_request *req)
3330 {
3331         files_struct *fsp;
3332         SMB_OFF_T startpos;
3333         size_t numtowrite;
3334         BOOL write_through;
3335         ssize_t nwritten;
3336         unsigned int smb_doff;
3337         unsigned int smblen;
3338         char *data;
3339         BOOL large_writeX;
3340         NTSTATUS status;
3341
3342         START_PROFILE(SMBwriteX);
3343
3344         if ((req->wct != 12) && (req->wct != 14)) {
3345                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3346                 END_PROFILE(SMBwriteX);
3347                 return;
3348         }
3349
3350         numtowrite = SVAL(req->inbuf,smb_vwv10);
3351         smb_doff = SVAL(req->inbuf,smb_vwv11);
3352         smblen = smb_len(req->inbuf);
3353         large_writeX = ((req->wct == 14) && (smblen > 0xFFFF));
3354
3355         /* Deal with possible LARGE_WRITEX */
3356         if (large_writeX) {
3357                 numtowrite |= ((((size_t)SVAL(req->inbuf,smb_vwv9)) & 1 )<<16);
3358         }
3359
3360         if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
3361                 reply_doserror(req, ERRDOS, ERRbadmem);
3362                 END_PROFILE(SMBwriteX);
3363                 return;
3364         }
3365
3366         /* If it's an IPC, pass off the pipe handler. */
3367         if (IS_IPC(conn)) {
3368                 reply_pipe_write_and_X(req);
3369                 END_PROFILE(SMBwriteX);
3370                 return;
3371         }
3372
3373         fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
3374         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
3375         write_through = BITSETW(req->inbuf+smb_vwv7,0);
3376
3377         if (!check_fsp(conn, req, fsp, &current_user)) {
3378                 END_PROFILE(SMBwriteX);
3379                 return;
3380         }
3381
3382         if (!CHECK_WRITE(fsp)) {
3383                 reply_doserror(req, ERRDOS, ERRbadaccess);
3384                 END_PROFILE(SMBwriteX);
3385                 return;
3386         }
3387
3388         data = smb_base(req->inbuf) + smb_doff;
3389
3390         if(req->wct == 14) {
3391 #ifdef LARGE_SMB_OFF_T
3392                 /*
3393                  * This is a large offset (64 bit) write.
3394                  */
3395                 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv12)) << 32);
3396
3397 #else /* !LARGE_SMB_OFF_T */
3398
3399                 /*
3400                  * Ensure we haven't been sent a >32 bit offset.
3401                  */
3402
3403                 if(IVAL(req->inbuf,smb_vwv12) != 0) {
3404                         DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
3405                                  "used and we don't support 64 bit offsets.\n",
3406                                  (unsigned int)IVAL(inbuf,smb_vwv12) ));
3407                         reply_doserror(req, ERRDOS, ERRbadaccess);
3408                         END_PROFILE(SMBwriteX);
3409                         return;
3410                 }
3411
3412 #endif /* LARGE_SMB_OFF_T */
3413         }
3414
3415         if (is_locked(fsp,(uint32)req->smbpid,
3416                       (SMB_BIG_UINT)numtowrite,
3417                       (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3418                 reply_doserror(req, ERRDOS, ERRlock);
3419                 END_PROFILE(SMBwriteX);
3420                 return;
3421         }
3422
3423         /* X/Open SMB protocol says that, unlike SMBwrite
3424         if the length is zero then NO truncation is
3425         done, just a write of zero. To truncate a file,
3426         use SMBwrite. */
3427
3428         if(numtowrite == 0) {
3429                 nwritten = 0;
3430         } else {
3431
3432                 if (schedule_aio_write_and_X(conn, req, fsp, data, startpos,
3433                                              numtowrite)) {
3434                         END_PROFILE(SMBwriteX);
3435                         return;
3436                 }
3437
3438                 nwritten = write_file(fsp,data,startpos,numtowrite);
3439                 reply_outbuf(req, 6, 0);
3440         }
3441   
3442         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3443                 reply_unixerror(req, ERRHRD, ERRdiskfull);
3444                 END_PROFILE(SMBwriteX);
3445                 return;
3446         }
3447
3448         SSVAL(req->outbuf,smb_vwv2,nwritten);
3449         if (large_writeX)
3450                 SSVAL(req->outbuf,smb_vwv4,(nwritten>>16)&1);
3451
3452         if (nwritten < (ssize_t)numtowrite) {
3453                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3454                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3455         }
3456
3457         DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
3458                 fsp->fnum, (int)numtowrite, (int)nwritten));
3459
3460         status = sync_file(conn, fsp, write_through);
3461         if (!NT_STATUS_IS_OK(status)) {
3462                 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
3463                         fsp->fsp_name, nt_errstr(status) ));
3464                 reply_nterror(req, status);
3465                 END_PROFILE(SMBwriteX);
3466                 return;
3467         }
3468
3469         END_PROFILE(SMBwriteX);
3470         chain_reply_new(req);
3471         return;
3472 }
3473
3474 /****************************************************************************
3475  Reply to a lseek.
3476 ****************************************************************************/
3477
3478 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3479 {
3480         SMB_OFF_T startpos;
3481         SMB_OFF_T res= -1;
3482         int mode,umode;
3483         int outsize = 0;
3484         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3485         START_PROFILE(SMBlseek);
3486
3487         CHECK_FSP(fsp,conn);
3488
3489         flush_write_cache(fsp, SEEK_FLUSH);
3490
3491         mode = SVAL(inbuf,smb_vwv1) & 3;
3492         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3493         startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
3494
3495         switch (mode) {
3496                 case 0:
3497                         umode = SEEK_SET;
3498                         res = startpos;
3499                         break;
3500                 case 1:
3501                         umode = SEEK_CUR;
3502                         res = fsp->fh->pos + startpos;
3503                         break;
3504                 case 2:
3505                         umode = SEEK_END;
3506                         break;
3507                 default:
3508                         umode = SEEK_SET;
3509                         res = startpos;
3510                         break;
3511         }
3512
3513         if (umode == SEEK_END) {
3514                 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
3515                         if(errno == EINVAL) {
3516                                 SMB_OFF_T current_pos = startpos;
3517                                 SMB_STRUCT_STAT sbuf;
3518
3519                                 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3520                                         END_PROFILE(SMBlseek);
3521                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3522                                 }
3523
3524                                 current_pos += sbuf.st_size;
3525                                 if(current_pos < 0)
3526                                         res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
3527                         }
3528                 }
3529
3530                 if(res == -1) {
3531                         END_PROFILE(SMBlseek);
3532                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3533                 }
3534         }
3535
3536         fsp->fh->pos = res;
3537   
3538         outsize = set_message(inbuf,outbuf,2,0,True);
3539         SIVAL(outbuf,smb_vwv0,res);
3540   
3541         DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3542                 fsp->fnum, (double)startpos, (double)res, mode));
3543
3544         END_PROFILE(SMBlseek);
3545         return(outsize);
3546 }
3547
3548 /****************************************************************************
3549  Reply to a flush.
3550 ****************************************************************************/
3551
3552 void reply_flush(connection_struct *conn, struct smb_request *req)
3553 {
3554         uint16 fnum;
3555         files_struct *fsp;
3556
3557         START_PROFILE(SMBflush);
3558
3559         if (req->wct < 1) {
3560                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3561                 return;
3562         }
3563
3564         fnum = SVAL(req->inbuf,smb_vwv0);
3565         fsp = file_fsp(fnum);
3566
3567         if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp, &current_user)) {
3568                 return;
3569         }
3570         
3571         if (!fsp) {
3572                 file_sync_all(conn);
3573         } else {
3574                 NTSTATUS status = sync_file(conn, fsp, True);
3575                 if (!NT_STATUS_IS_OK(status)) {
3576                         DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
3577                                 fsp->fsp_name, nt_errstr(status) ));
3578                         reply_nterror(req, status);
3579                         END_PROFILE(SMBflush);
3580                         return;
3581                 }
3582         }
3583         
3584         reply_outbuf(req, 0, 0);
3585
3586         DEBUG(3,("flush\n"));
3587         END_PROFILE(SMBflush);
3588         return;
3589 }
3590
3591 /****************************************************************************
3592  Reply to a exit.
3593  conn POINTER CAN BE NULL HERE !
3594 ****************************************************************************/
3595
3596 void reply_exit(connection_struct *conn, struct smb_request *req)
3597 {
3598         START_PROFILE(SMBexit);
3599
3600         file_close_pid(req->smbpid, req->vuid);
3601
3602         reply_outbuf(req, 0, 0);
3603
3604         DEBUG(3,("exit\n"));
3605
3606         END_PROFILE(SMBexit);
3607         return;
3608 }
3609
3610 /****************************************************************************
3611  Reply to a close - has to deal with closing a directory opened by NT SMB's.
3612 ****************************************************************************/
3613
3614 void reply_close(connection_struct *conn, struct smb_request *req)
3615 {
3616         NTSTATUS status = NT_STATUS_OK;
3617         files_struct *fsp = NULL;
3618         START_PROFILE(SMBclose);
3619
3620         if (req->wct < 3) {
3621                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3622                 END_PROFILE(SMBclose);
3623                 return;
3624         }
3625
3626         /* If it's an IPC, pass off to the pipe handler. */
3627         if (IS_IPC(conn)) {
3628                 reply_pipe_close(conn, req);
3629                 END_PROFILE(SMBclose);
3630                 return;
3631         }
3632
3633         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3634
3635         /*
3636          * We can only use CHECK_FSP if we know it's not a directory.
3637          */
3638
3639         if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3640                 reply_doserror(req, ERRDOS, ERRbadfid);
3641                 END_PROFILE(SMBclose);
3642                 return;
3643         }
3644
3645         if(fsp->is_directory) {
3646                 /*
3647                  * Special case - close NT SMB directory handle.
3648                  */
3649                 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
3650                 status = close_file(fsp,NORMAL_CLOSE);
3651         } else {
3652                 /*
3653                  * Close ordinary file.
3654                  */
3655
3656                 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3657                          fsp->fh->fd, fsp->fnum,
3658                          conn->num_files_open));
3659  
3660                 /*
3661                  * Take care of any time sent in the close.
3662                  */
3663
3664                 fsp_set_pending_modtime(fsp, convert_time_t_to_timespec(
3665                                                 srv_make_unix_date3(
3666                                                         req->inbuf+smb_vwv1)));
3667
3668                 /*
3669                  * close_file() returns the unix errno if an error
3670                  * was detected on close - normally this is due to
3671                  * a disk full error. If not then it was probably an I/O error.
3672                  */
3673  
3674                 status = close_file(fsp,NORMAL_CLOSE);
3675         }  
3676
3677         if (!NT_STATUS_IS_OK(status)) {
3678                 reply_nterror(req, status);
3679                 END_PROFILE(SMBclose);
3680                 return;
3681         }
3682
3683         reply_outbuf(req, 0, 0);
3684         END_PROFILE(SMBclose);
3685         return;
3686 }
3687
3688 /****************************************************************************
3689  Reply to a writeclose (Core+ protocol).
3690 ****************************************************************************/
3691
3692 int reply_writeclose(connection_struct *conn,
3693                      char *inbuf,char *outbuf, int size, int dum_buffsize)
3694 {
3695         size_t numtowrite;
3696         ssize_t nwritten = -1;
3697         int outsize = 0;
3698         NTSTATUS close_status = NT_STATUS_OK;
3699         SMB_OFF_T startpos;
3700         char *data;
3701         struct timespec mtime;
3702         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3703         START_PROFILE(SMBwriteclose);
3704
3705         CHECK_FSP(fsp,conn);
3706         if (!CHECK_WRITE(fsp)) {
3707                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3708         }
3709
3710         numtowrite = SVAL(inbuf,smb_vwv1);
3711         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3712         mtime = convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv4));
3713         data = smb_buf(inbuf) + 1;
3714   
3715         if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3716                 END_PROFILE(SMBwriteclose);
3717                 return ERROR_DOS(ERRDOS,ERRlock);
3718         }
3719   
3720         nwritten = write_file(fsp,data,startpos,numtowrite);
3721
3722         set_filetime(conn, fsp->fsp_name, mtime);
3723   
3724         /*
3725          * More insanity. W2K only closes the file if writelen > 0.
3726          * JRA.
3727          */
3728
3729         if (numtowrite) {
3730                 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3731                         fsp->fsp_name ));
3732                 close_status = close_file(fsp,NORMAL_CLOSE);
3733         }
3734
3735         DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3736                  fsp->fnum, (int)numtowrite, (int)nwritten,
3737                  conn->num_files_open));
3738   
3739         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3740                 END_PROFILE(SMBwriteclose);
3741                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3742         }
3743  
3744         if(!NT_STATUS_IS_OK(close_status)) {
3745                 END_PROFILE(SMBwriteclose);
3746                 return ERROR_NT(close_status);
3747         }
3748  
3749         outsize = set_message(inbuf,outbuf,1,0,True);
3750   
3751         SSVAL(outbuf,smb_vwv0,nwritten);
3752         END_PROFILE(SMBwriteclose);
3753         return(outsize);
3754 }
3755
3756 #undef DBGC_CLASS
3757 #define DBGC_CLASS DBGC_LOCKING
3758
3759 /****************************************************************************
3760  Reply to a lock.
3761 ****************************************************************************/
3762
3763 int reply_lock(connection_struct *conn,
3764                char *inbuf,char *outbuf, int length, int dum_buffsize)
3765 {
3766         int outsize = set_message(inbuf,outbuf,0,0,False);
3767         SMB_BIG_UINT count,offset;
3768         NTSTATUS status;
3769         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3770         struct byte_range_lock *br_lck = NULL;
3771
3772         START_PROFILE(SMBlock);
3773
3774         CHECK_FSP(fsp,conn);
3775
3776         release_level_2_oplocks_on_change(fsp);
3777
3778         count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3779         offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3780
3781         DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3782                  fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
3783
3784         br_lck = do_lock(smbd_messaging_context(),
3785                         fsp,
3786                         (uint32)SVAL(inbuf,smb_pid),
3787                         count,
3788                         offset,
3789                         WRITE_LOCK,
3790                         WINDOWS_LOCK,
3791                         False, /* Non-blocking lock. */
3792                         &status,
3793                         NULL);
3794
3795         TALLOC_FREE(br_lck);
3796
3797         if (NT_STATUS_V(status)) {
3798                 END_PROFILE(SMBlock);
3799                 return ERROR_NT(status);
3800         }
3801
3802         END_PROFILE(SMBlock);
3803         return(outsize);
3804 }
3805
3806 /****************************************************************************
3807  Reply to a unlock.
3808 ****************************************************************************/
3809
3810 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, 
3811                  int dum_buffsize)
3812 {
3813         int outsize = set_message(inbuf,outbuf,0,0,False);
3814         SMB_BIG_UINT count,offset;
3815         NTSTATUS status;
3816         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3817         START_PROFILE(SMBunlock);
3818
3819         CHECK_FSP(fsp,conn);
3820         
3821         count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3822         offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3823         
3824         status = do_unlock(smbd_messaging_context(),
3825                         fsp,
3826                         (uint32)SVAL(inbuf,smb_pid),
3827                         count,
3828                         offset,
3829                         WINDOWS_LOCK);
3830
3831         if (NT_STATUS_V(status)) {
3832                 END_PROFILE(SMBunlock);
3833                 return ERROR_NT(status);
3834         }
3835
3836         DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3837                     fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
3838         
3839         END_PROFILE(SMBunlock);
3840         return(outsize);
3841 }
3842
3843 #undef DBGC_CLASS
3844 #define DBGC_CLASS DBGC_ALL
3845
3846 /****************************************************************************
3847  Reply to a tdis.
3848  conn POINTER CAN BE NULL HERE !
3849 ****************************************************************************/
3850
3851 void reply_tdis(connection_struct *conn, struct smb_request *req)
3852 {
3853         START_PROFILE(SMBtdis);
3854
3855         if (!conn) {
3856                 DEBUG(4,("Invalid connection in tdis\n"));
3857                 reply_doserror(req, ERRSRV, ERRinvnid);
3858                 END_PROFILE(SMBtdis);
3859                 return;
3860         }
3861
3862         conn->used = False;
3863
3864         close_cnum(conn,req->vuid);
3865
3866         reply_outbuf(req, 0, 0);
3867         END_PROFILE(SMBtdis);
3868         return;
3869 }
3870
3871 /****************************************************************************
3872  Reply to a echo.
3873  conn POINTER CAN BE NULL HERE !
3874 ****************************************************************************/
3875
3876 void reply_echo(connection_struct *conn, struct smb_request *req)
3877 {
3878         int smb_reverb;
3879         int seq_num;
3880         unsigned int data_len = smb_buflen(req->inbuf);
3881
3882         START_PROFILE(SMBecho);
3883
3884         if (req->wct < 1) {
3885                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3886                 END_PROFILE(SMBecho);
3887                 return;
3888         }
3889
3890         if (data_len > BUFFER_SIZE) {
3891                 DEBUG(0,("reply_echo: data_len too large.\n"));
3892                 reply_nterror(req, NT_STATUS_INSUFFICIENT_RESOURCES);
3893                 END_PROFILE(SMBecho);
3894                 return;
3895         }
3896
3897         smb_reverb = SVAL(req->inbuf,smb_vwv0);
3898
3899         reply_outbuf(req, 1, data_len);
3900
3901         /* copy any incoming data back out */
3902         if (data_len > 0) {
3903                 memcpy(smb_buf(req->outbuf),smb_buf(req->inbuf),data_len);
3904         }
3905
3906         if (smb_reverb > 100) {
3907                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3908                 smb_reverb = 100;
3909         }
3910
3911         for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3912                 SSVAL(req->outbuf,smb_vwv0,seq_num);
3913
3914                 show_msg((char *)req->outbuf);
3915                 if (!send_smb(smbd_server_fd(),(char *)req->outbuf))
3916                         exit_server_cleanly("reply_echo: send_smb failed.");
3917         }
3918
3919         DEBUG(3,("echo %d times\n", smb_reverb));
3920
3921         TALLOC_FREE(req->outbuf);
3922
3923         smb_echo_count++;
3924
3925         END_PROFILE(SMBecho);
3926         return;
3927 }
3928
3929 /****************************************************************************
3930  Reply to a printopen.
3931 ****************************************************************************/
3932
3933 int reply_printopen(connection_struct *conn, 
3934                     char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3935 {
3936         int outsize = 0;
3937         files_struct *fsp;
3938         NTSTATUS status;
3939         
3940         START_PROFILE(SMBsplopen);
3941         
3942         if (!CAN_PRINT(conn)) {
3943                 END_PROFILE(SMBsplopen);
3944                 return ERROR_DOS(ERRDOS,ERRnoaccess);
3945         }
3946
3947         /* Open for exclusive use, write only. */
3948         status = print_fsp_open(conn, NULL, &fsp);
3949
3950         if (!NT_STATUS_IS_OK(status)) {
3951                 END_PROFILE(SMBsplopen);
3952                 return(ERROR_NT(status));
3953         }
3954
3955         outsize = set_message(inbuf,outbuf,1,0,True);
3956         SSVAL(outbuf,smb_vwv0,fsp->fnum);
3957   
3958         DEBUG(3,("openprint fd=%d fnum=%d\n",
3959                  fsp->fh->fd, fsp->fnum));
3960
3961         END_PROFILE(SMBsplopen);
3962         return(outsize);
3963 }
3964
3965 /****************************************************************************
3966  Reply to a printclose.
3967 ****************************************************************************/
3968
3969 int reply_printclose(connection_struct *conn,
3970                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3971 {
3972         int outsize = set_message(inbuf,outbuf,0,0,False);
3973         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3974         NTSTATUS status;
3975         START_PROFILE(SMBsplclose);
3976
3977         CHECK_FSP(fsp,conn);
3978
3979         if (!CAN_PRINT(conn)) {
3980                 END_PROFILE(SMBsplclose);
3981                 return ERROR_NT(NT_STATUS_DOS(ERRSRV, ERRerror));
3982         }
3983   
3984         DEBUG(3,("printclose fd=%d fnum=%d\n",
3985                  fsp->fh->fd,fsp->fnum));
3986   
3987         status = close_file(fsp,NORMAL_CLOSE);
3988
3989         if(!NT_STATUS_IS_OK(status)) {
3990                 END_PROFILE(SMBsplclose);
3991                 return ERROR_NT(status);
3992         }
3993
3994         END_PROFILE(SMBsplclose);
3995         return(outsize);
3996 }
3997
3998 /****************************************************************************
3999  Reply to a printqueue.
4000 ****************************************************************************/
4001
4002 int reply_printqueue(connection_struct *conn,
4003                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4004 {
4005         int outsize = set_message(inbuf,outbuf,2,3,True);
4006         int max_count = SVAL(inbuf,smb_vwv0);
4007         int start_index = SVAL(inbuf,smb_vwv1);
4008         START_PROFILE(SMBsplretq);
4009
4010         /* we used to allow the client to get the cnum wrong, but that
4011            is really quite gross and only worked when there was only
4012            one printer - I think we should now only accept it if they
4013            get it right (tridge) */
4014         if (!CAN_PRINT(conn)) {
4015                 END_PROFILE(SMBsplretq);
4016                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4017         }
4018
4019         SSVAL(outbuf,smb_vwv0,0);
4020         SSVAL(outbuf,smb_vwv1,0);
4021         SCVAL(smb_buf(outbuf),0,1);
4022         SSVAL(smb_buf(outbuf),1,0);
4023   
4024         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
4025                  start_index, max_count));
4026
4027         {
4028                 print_queue_struct *queue = NULL;
4029                 print_status_struct status;
4030                 char *p = smb_buf(outbuf) + 3;
4031                 int count = print_queue_status(SNUM(conn), &queue, &status);
4032                 int num_to_get = ABS(max_count);
4033                 int first = (max_count>0?start_index:start_index+max_count+1);
4034                 int i;
4035
4036                 if (first >= count)
4037                         num_to_get = 0;
4038                 else
4039                         num_to_get = MIN(num_to_get,count-first);
4040     
4041
4042                 for (i=first;i<first+num_to_get;i++) {
4043                         srv_put_dos_date2(p,0,queue[i].time);
4044                         SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
4045                         SSVAL(p,5, queue[i].job);
4046                         SIVAL(p,7,queue[i].size);
4047                         SCVAL(p,11,0);
4048                         srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p+12,
4049                                     queue[i].fs_user, 16, STR_ASCII);
4050                         p += 28;
4051                 }
4052
4053                 if (count > 0) {
4054                         outsize = set_message(inbuf,outbuf,2,28*count+3,False); 
4055                         SSVAL(outbuf,smb_vwv0,count);
4056                         SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
4057                         SCVAL(smb_buf(outbuf),0,1);
4058                         SSVAL(smb_buf(outbuf),1,28*count);
4059                 }
4060
4061                 SAFE_FREE(queue);
4062           
4063                 DEBUG(3,("%d entries returned in queue\n",count));
4064         }
4065   
4066         END_PROFILE(SMBsplretq);
4067         return(outsize);
4068 }
4069
4070 /****************************************************************************
4071  Reply to a printwrite.
4072 ****************************************************************************/
4073
4074 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4075 {
4076         int numtowrite;
4077         int outsize = set_message(inbuf,outbuf,0,0,False);
4078         char *data;
4079         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
4080
4081         START_PROFILE(SMBsplwr);
4082   
4083         if (!CAN_PRINT(conn)) {
4084                 END_PROFILE(SMBsplwr);
4085                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4086         }
4087
4088         CHECK_FSP(fsp,conn);
4089         if (!CHECK_WRITE(fsp)) {
4090                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
4091         }
4092
4093         numtowrite = SVAL(smb_buf(inbuf),1);
4094         data = smb_buf(inbuf) + 3;
4095   
4096         if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
4097                 END_PROFILE(SMBsplwr);
4098                 return(UNIXERROR(ERRHRD,ERRdiskfull));
4099         }
4100
4101         DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
4102   
4103         END_PROFILE(SMBsplwr);
4104         return(outsize);
4105 }
4106
4107 /****************************************************************************
4108  Reply to a mkdir.
4109 ****************************************************************************/
4110
4111 void reply_mkdir(connection_struct *conn, struct smb_request *req)
4112 {
4113         pstring directory;
4114         NTSTATUS status;
4115         SMB_STRUCT_STAT sbuf;
4116
4117         START_PROFILE(SMBmkdir);
4118  
4119         srvstr_get_path((char *)req->inbuf, req->flags2, directory,
4120                         smb_buf(req->inbuf) + 1, sizeof(directory), 0,
4121                         STR_TERMINATE, &status);
4122         if (!NT_STATUS_IS_OK(status)) {
4123                 reply_nterror(req, status);
4124                 END_PROFILE(SMBmkdir);
4125                 return;
4126         }
4127
4128         status = resolve_dfspath(conn,
4129                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
4130                                  directory);
4131         if (!NT_STATUS_IS_OK(status)) {
4132                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4133                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
4134                                         ERRSRV, ERRbadpath);
4135                         END_PROFILE(SMBmkdir);
4136                         return;
4137                 }
4138                 reply_nterror(req, status);
4139                 END_PROFILE(SMBmkdir);
4140                 return;
4141         }
4142
4143         status = unix_convert(conn, directory, False, NULL, &sbuf);
4144         if (!NT_STATUS_IS_OK(status)) {
4145                 reply_nterror(req, status);
4146                 END_PROFILE(SMBmkdir);
4147                 return;
4148         }
4149
4150         status = check_name(conn, directory);
4151         if (!NT_STATUS_IS_OK(status)) {
4152                 reply_nterror(req, status);
4153                 END_PROFILE(SMBmkdir);
4154                 return;
4155         }
4156   
4157         status = create_directory(conn, directory);
4158
4159         DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
4160
4161         if (!NT_STATUS_IS_OK(status)) {
4162
4163                 if (!use_nt_status()
4164                     && NT_STATUS_EQUAL(status,
4165                                        NT_STATUS_OBJECT_NAME_COLLISION)) {
4166                         /*
4167                          * Yes, in the DOS error code case we get a
4168                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
4169                          * samba4 torture test.
4170                          */
4171                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
4172                 }
4173
4174                 reply_nterror(req, status);
4175                 END_PROFILE(SMBmkdir);
4176                 return;
4177         }
4178
4179         reply_outbuf(req, 0, 0);
4180
4181         DEBUG( 3, ( "mkdir %s\n", directory ) );
4182
4183         END_PROFILE(SMBmkdir);
4184         return;
4185 }
4186
4187 /****************************************************************************
4188  Static function used by reply_rmdir to delete an entire directory
4189  tree recursively. Return True on ok, False on fail.
4190 ****************************************************************************/
4191
4192 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
4193 {
4194         const char *dname = NULL;
4195         BOOL ret = True;
4196         long offset = 0;
4197         struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
4198
4199         if(dir_hnd == NULL)
4200                 return False;
4201
4202         while((dname = ReadDirName(dir_hnd, &offset))) {
4203                 pstring fullname;
4204                 SMB_STRUCT_STAT st;
4205
4206                 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4207                         continue;
4208
4209                 if (!is_visible_file(conn, directory, dname, &st, False))
4210                         continue;
4211
4212                 /* Construct the full name. */
4213                 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
4214                         errno = ENOMEM;
4215                         ret = False;
4216                         break;
4217                 }
4218
4219                 pstrcpy(fullname, directory);
4220                 pstrcat(fullname, "/");
4221                 pstrcat(fullname, dname);
4222
4223                 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
4224                         ret = False;
4225                         break;
4226                 }
4227
4228                 if(st.st_mode & S_IFDIR) {
4229                         if(!recursive_rmdir(conn, fullname)) {
4230                                 ret = False;
4231                                 break;
4232                         }
4233                         if(SMB_VFS_RMDIR(conn,fullname) != 0) {
4234                                 ret = False;
4235                                 break;
4236                         }
4237                 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
4238                         ret = False;
4239                         break;
4240                 }
4241         }
4242         CloseDir(dir_hnd);
4243         return ret;
4244 }
4245
4246 /****************************************************************************
4247  The internals of the rmdir code - called elsewhere.
4248 ****************************************************************************/
4249
4250 NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
4251 {
4252         int ret;
4253         SMB_STRUCT_STAT st;
4254
4255         /* Might be a symlink. */
4256         if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
4257                 return map_nt_error_from_unix(errno);
4258         }
4259
4260         if (S_ISLNK(st.st_mode)) {
4261                 /* Is what it points to a directory ? */
4262                 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
4263                         return map_nt_error_from_unix(errno);
4264                 }
4265                 if (!(S_ISDIR(st.st_mode))) {
4266                         return NT_STATUS_NOT_A_DIRECTORY;
4267                 }
4268                 ret = SMB_VFS_UNLINK(conn,directory);
4269         } else {
4270                 ret = SMB_VFS_RMDIR(conn,directory);
4271         }
4272         if (ret == 0) {
4273                 notify_fname(conn, NOTIFY_ACTION_REMOVED,
4274                              FILE_NOTIFY_CHANGE_DIR_NAME,
4275                              directory);
4276                 return NT_STATUS_OK;
4277         }
4278
4279         if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
4280                 /* 
4281                  * Check to see if the only thing in this directory are
4282                  * vetoed files/directories. If so then delete them and
4283                  * retry. If we fail to delete any of them (and we *don't*
4284                  * do a recursive delete) then fail the rmdir.
4285                  */
4286                 const char *dname;
4287                 long dirpos = 0;
4288                 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
4289
4290                 if(dir_hnd == NULL) {
4291                         errno = ENOTEMPTY;
4292                         goto err;
4293                 }
4294
4295                 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4296                         if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4297                                 continue;
4298                         if (!is_visible_file(conn, directory, dname, &st, False))
4299                                 continue;
4300                         if(!IS_VETO_PATH(conn, dname)) {
4301                                 CloseDir(dir_hnd);
4302                                 errno = ENOTEMPTY;
4303                                 goto err;
4304                         }
4305                 }
4306
4307                 /* We only have veto files/directories. Recursive delete. */
4308
4309                 RewindDir(dir_hnd,&dirpos);
4310                 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4311                         pstring fullname;
4312
4313                         if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4314                                 continue;
4315                         if (!is_visible_file(conn, directory, dname, &st, False))
4316                                 continue;
4317
4318                         /* Construct the full name. */
4319                         if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
4320                                 errno = ENOMEM;
4321                                 break;
4322                         }
4323
4324                         pstrcpy(fullname, directory);
4325                         pstrcat(fullname, "/");
4326                         pstrcat(fullname, dname);
4327                    
4328                         if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
4329                                 break;
4330                         if(st.st_mode & S_IFDIR) {
4331                                 if(lp_recursive_veto_delete(SNUM(conn))) {
4332                                         if(!recursive_rmdir(conn, fullname))
4333                                                 break;
4334                                 }
4335                                 if(SMB_VFS_RMDIR(conn,fullname) != 0)
4336                                         break;
4337                         } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
4338                                 break;
4339                 }
4340                 CloseDir(dir_hnd);
4341                 /* Retry the rmdir */
4342                 ret = SMB_VFS_RMDIR(conn,directory);
4343         }
4344
4345   err:
4346
4347         if (ret != 0) {
4348                 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
4349                          "%s\n", directory,strerror(errno)));
4350                 return map_nt_error_from_unix(errno);
4351         }
4352
4353         notify_fname(conn, NOTIFY_ACTION_REMOVED,
4354                      FILE_NOTIFY_CHANGE_DIR_NAME,
4355                      directory);
4356
4357         return NT_STATUS_OK;
4358 }
4359
4360 /****************************************************************************
4361  Reply to a rmdir.
4362 ****************************************************************************/
4363
4364 void reply_rmdir(connection_struct *conn, struct smb_request *req)
4365 {
4366         pstring directory;
4367         SMB_STRUCT_STAT sbuf;
4368         NTSTATUS status;
4369         START_PROFILE(SMBrmdir);
4370
4371         srvstr_get_path((char *)req->inbuf, req->flags2, directory,
4372                         smb_buf(req->inbuf) + 1, sizeof(directory), 0,
4373                         STR_TERMINATE, &status);
4374         if (!NT_STATUS_IS_OK(status)) {
4375                 reply_nterror(req, status);
4376                 END_PROFILE(SMBrmdir);
4377                 return;
4378         }
4379
4380         status = resolve_dfspath(conn,
4381                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
4382                                  directory);
4383         if (!NT_STATUS_IS_OK(status)) {
4384                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4385                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
4386                                         ERRSRV, ERRbadpath);
4387                         END_PROFILE(SMBrmdir);
4388                         return;
4389                 }
4390                 reply_nterror(req, status);
4391                 END_PROFILE(SMBrmdir);
4392                 return;
4393         }
4394
4395         status = unix_convert(conn, directory, False, NULL, &sbuf);
4396         if (!NT_STATUS_IS_OK(status)) {
4397                 reply_nterror(req, status);
4398                 END_PROFILE(SMBrmdir);
4399                 return;
4400         }
4401   
4402         status = check_name(conn, directory);
4403         if (!NT_STATUS_IS_OK(status)) {
4404                 reply_nterror(req, status);
4405                 END_PROFILE(SMBrmdir);
4406                 return;
4407         }
4408
4409         dptr_closepath(directory, req->smbpid);
4410         status = rmdir_internals(conn, directory);
4411         if (!NT_STATUS_IS_OK(status)) {
4412                 reply_nterror(req, status);
4413                 END_PROFILE(SMBrmdir);
4414                 return;
4415         }
4416  
4417         reply_outbuf(req, 0, 0);
4418   
4419         DEBUG( 3, ( "rmdir %s\n", directory ) );
4420   
4421         END_PROFILE(SMBrmdir);
4422         return;
4423 }
4424
4425 /*******************************************************************
4426  Resolve wildcards in a filename rename.
4427  Note that name is in UNIX charset and thus potentially can be more
4428  than fstring buffer (255 bytes) especially in default UTF-8 case.
4429  Therefore, we use pstring inside and all calls should ensure that
4430  name2 is at least pstring-long (they do already)
4431 ********************************************************************/
4432
4433 static BOOL resolve_wildcards(const char *name1, char *name2)
4434 {
4435         pstring root1,root2;
4436         pstring ext1,ext2;
4437         char *p,*p2, *pname1, *pname2;
4438         int available_space, actual_space;
4439         
4440         pname1 = strrchr_m(name1,'/');
4441         pname2 = strrchr_m(name2,'/');
4442
4443         if (!pname1 || !pname2)
4444                 return(False);
4445   
4446         pstrcpy(root1,pname1);
4447         pstrcpy(root2,pname2);
4448         p = strrchr_m(root1,'.');
4449         if (p) {
4450                 *p = 0;
4451                 pstrcpy(ext1,p+1);
4452         } else {
4453                 pstrcpy(ext1,"");    
4454         }
4455         p = strrchr_m(root2,'.');
4456         if (p) {
4457                 *p = 0;
4458                 pstrcpy(ext2,p+1);
4459         } else {
4460                 pstrcpy(ext2,"");    
4461         }
4462
4463         p = root1;
4464         p2 = root2;
4465         while (*p2) {
4466                 if (*p2 == '?') {
4467                         *p2 = *p;
4468                         p2++;
4469                 } else if (*p2 == '*') {
4470                         pstrcpy(p2, p);
4471                         break;
4472                 } else {
4473                         p2++;
4474                 }
4475                 if (*p)
4476                         p++;
4477         }
4478
4479         p = ext1;
4480         p2 = ext2;
4481         while (*p2) {
4482                 if (*p2 == '?') {
4483                         *p2 = *p;
4484                         p2++;
4485                 } else if (*p2 == '*') {
4486                         pstrcpy(p2, p);
4487                         break;
4488                 } else {
4489                         p2++;
4490                 }
4491                 if (*p)
4492                         p++;
4493         }
4494
4495         available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
4496         
4497         if (ext2[0]) {
4498                 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
4499                 if (actual_space >= available_space - 1) {
4500                         DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
4501                                 actual_space - available_space));
4502                 }
4503         } else {
4504                 pstrcpy_base(pname2, root2, name2);
4505         }
4506
4507         return(True);
4508 }
4509
4510 /****************************************************************************
4511  Ensure open files have their names updated. Updated to notify other smbd's
4512  asynchronously.
4513 ****************************************************************************/
4514
4515 static void rename_open_files(connection_struct *conn,
4516                               struct share_mode_lock *lck,
4517                               const char *newname)
4518 {
4519         files_struct *fsp;
4520         BOOL did_rename = False;
4521
4522         for(fsp = file_find_di_first(lck->id); fsp;
4523             fsp = file_find_di_next(fsp)) {
4524                 /* fsp_name is a relative path under the fsp. To change this for other
4525                    sharepaths we need to manipulate relative paths. */
4526                 /* TODO - create the absolute path and manipulate the newname
4527                    relative to the sharepath. */
4528                 if (fsp->conn != conn) {
4529                         continue;
4530                 }
4531                 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
4532                           fsp->fnum, file_id_static_string(&fsp->file_id),
4533                         fsp->fsp_name, newname ));
4534                 string_set(&fsp->fsp_name, newname);
4535                 did_rename = True;
4536         }
4537
4538         if (!did_rename) {
4539                 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
4540                           file_id_static_string(&lck->id), newname ));
4541         }
4542
4543         /* Send messages to all smbd's (not ourself) that the name has changed. */
4544         rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
4545                               newname);
4546 }
4547
4548 /****************************************************************************
4549  We need to check if the source path is a parent directory of the destination
4550  (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
4551  refuse the rename with a sharing violation. Under UNIX the above call can
4552  *succeed* if /foo/bar/baz is a symlink to another area in the share. We
4553  probably need to check that the client is a Windows one before disallowing
4554  this as a UNIX client (one with UNIX extensions) can know the source is a
4555  symlink and make this decision intelligently. Found by an excellent bug
4556  report from <AndyLiebman@aol.com>.
4557 ****************************************************************************/
4558
4559 static BOOL rename_path_prefix_equal(const char *src, const char *dest)
4560 {
4561         const char *psrc = src;
4562         const char *pdst = dest;
4563         size_t slen;
4564
4565         if (psrc[0] == '.' && psrc[1] == '/') {
4566                 psrc += 2;
4567         }
4568         if (pdst[0] == '.' && pdst[1] == '/') {
4569                 pdst += 2;
4570         }
4571         if ((slen = strlen(psrc)) > strlen(pdst)) {
4572                 return False;
4573         }
4574         return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
4575 }
4576
4577 /*
4578  * Do the notify calls from a rename
4579  */
4580
4581 static void notify_rename(connection_struct *conn, BOOL is_dir,
4582                           const char *oldpath, const char *newpath)
4583 {
4584         char *olddir, *newdir;
4585         const char *oldname, *newname;
4586         uint32 mask;
4587
4588         mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
4589                 : FILE_NOTIFY_CHANGE_FILE_NAME;
4590
4591         if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
4592             || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
4593                 TALLOC_FREE(olddir);
4594                 return;
4595         }
4596
4597         if (strcmp(olddir, newdir) == 0) {
4598                 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
4599                 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
4600         }
4601         else {
4602                 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
4603                 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
4604         }
4605         TALLOC_FREE(olddir);
4606         TALLOC_FREE(newdir);
4607
4608         /* this is a strange one. w2k3 gives an additional event for
4609            CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
4610            files, but not directories */
4611         if (!is_dir) {
4612                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
4613                              FILE_NOTIFY_CHANGE_ATTRIBUTES
4614                              |FILE_NOTIFY_CHANGE_CREATION,
4615                              newpath);
4616         }
4617 }
4618
4619 /****************************************************************************
4620  Rename an open file - given an fsp.
4621 ****************************************************************************/
4622
4623 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstring newname, uint32 attrs, BOOL replace_if_exists)
4624 {
4625         SMB_STRUCT_STAT sbuf, sbuf1;
4626         pstring newname_last_component;
4627         NTSTATUS status = NT_STATUS_OK;
4628         struct share_mode_lock *lck = NULL;
4629         BOOL dst_exists;
4630
4631         ZERO_STRUCT(sbuf);
4632
4633         status = unix_convert(conn, newname, False, newname_last_component, &sbuf);
4634
4635         /* If an error we expect this to be NT_STATUS_OBJECT_PATH_NOT_FOUND */
4636
4637         if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND, status)) {
4638                 return status;
4639         }
4640
4641         status = check_name(conn, newname);
4642         if (!NT_STATUS_IS_OK(status)) {
4643                 return status;
4644         }
4645   
4646         /* Ensure newname contains a '/' */
4647         if(strrchr_m(newname,'/') == 0) {
4648                 pstring tmpstr;
4649                 
4650                 pstrcpy(tmpstr, "./");
4651                 pstrcat(tmpstr, newname);
4652                 pstrcpy(newname, tmpstr);
4653         }
4654
4655         /*
4656          * Check for special case with case preserving and not
4657          * case sensitive. If the old last component differs from the original
4658          * last component only by case, then we should allow
4659          * the rename (user is trying to change the case of the
4660          * filename).
4661          */
4662
4663         if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
4664                         strequal(newname, fsp->fsp_name)) {
4665                 char *p;
4666                 pstring newname_modified_last_component;
4667
4668                 /*
4669                  * Get the last component of the modified name.
4670                  * Note that we guarantee that newname contains a '/'
4671                  * character above.
4672                  */
4673                 p = strrchr_m(newname,'/');
4674                 pstrcpy(newname_modified_last_component,p+1);
4675                         
4676                 if(strcsequal(newname_modified_last_component, 
4677                               newname_last_component) == False) {
4678                         /*
4679                          * Replace the modified last component with
4680                          * the original.
4681                          */
4682                         pstrcpy(p+1, newname_last_component);
4683                 }
4684         }
4685
4686         /*
4687          * If the src and dest names are identical - including case,
4688          * don't do the rename, just return success.
4689          */
4690
4691         if (strcsequal(fsp->fsp_name, newname)) {
4692                 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4693                         newname));
4694                 return NT_STATUS_OK;
4695         }
4696
4697         /*
4698          * Have vfs_object_exist also fill sbuf1
4699          */
4700         dst_exists = vfs_object_exist(conn, newname, &sbuf1);
4701
4702         if(!replace_if_exists && dst_exists) {
4703                 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4704                         fsp->fsp_name,newname));
4705                 return NT_STATUS_OBJECT_NAME_COLLISION;
4706         }
4707
4708         if (dst_exists) {
4709                 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
4710                 files_struct *dst_fsp = file_find_di_first(fileid);
4711                 if (dst_fsp) {
4712                         DEBUG(3, ("rename_internals_fsp: Target file open\n"));
4713                         return NT_STATUS_ACCESS_DENIED;
4714                 }
4715         }
4716
4717         /* Ensure we have a valid stat struct for the source. */
4718         if (fsp->fh->fd != -1) {
4719                 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) == -1) {
4720                         return map_nt_error_from_unix(errno);
4721                 }
4722         } else {
4723                 if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
4724                         return map_nt_error_from_unix(errno);
4725                 }
4726         }
4727
4728         status = can_rename(conn, fsp, attrs, &sbuf);
4729
4730         if (!NT_STATUS_IS_OK(status)) {
4731                 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4732                         nt_errstr(status), fsp->fsp_name,newname));
4733                 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
4734                         status = NT_STATUS_ACCESS_DENIED;
4735                 return status;
4736         }
4737
4738         if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
4739                 return NT_STATUS_ACCESS_DENIED;
4740         }
4741
4742         lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
4743
4744         /*
4745          * We have the file open ourselves, so not being able to get the
4746          * corresponding share mode lock is a fatal error.
4747          */
4748
4749         SMB_ASSERT(lck != NULL);
4750
4751         if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
4752                 uint32 create_options = fsp->fh->private_options;
4753
4754                 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4755                         fsp->fsp_name,newname));
4756
4757                 rename_open_files(conn, lck, newname);
4758
4759                 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
4760
4761                 /*
4762                  * A rename acts as a new file create w.r.t. allowing an initial delete
4763                  * on close, probably because in Windows there is a new handle to the
4764                  * new file. If initial delete on close was requested but not
4765                  * originally set, we need to set it here. This is probably not 100% correct,
4766                  * but will work for the CIFSFS client which in non-posix mode
4767                  * depends on these semantics. JRA.
4768                  */
4769
4770                 set_allow_initial_delete_on_close(lck, fsp, True);
4771
4772                 if (create_options & FILE_DELETE_ON_CLOSE) {
4773                         status = can_set_delete_on_close(fsp, True, 0);
4774
4775                         if (NT_STATUS_IS_OK(status)) {
4776                                 /* Note that here we set the *inital* delete on close flag,
4777                                  * not the regular one. The magic gets handled in close. */
4778                                 fsp->initial_delete_on_close = True;
4779                         }
4780                 }
4781                 TALLOC_FREE(lck);
4782                 return NT_STATUS_OK;    
4783         }
4784
4785         TALLOC_FREE(lck);
4786
4787         if (errno == ENOTDIR || errno == EISDIR) {
4788                 status = NT_STATUS_OBJECT_NAME_COLLISION;
4789         } else {
4790                 status = map_nt_error_from_unix(errno);
4791         }
4792                 
4793         DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4794                 nt_errstr(status), fsp->fsp_name,newname));
4795
4796         return status;
4797 }
4798
4799 /****************************************************************************
4800  The guts of the rename command, split out so it may be called by the NT SMB
4801  code. 
4802 ****************************************************************************/
4803
4804 NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
4805                                 pstring name,
4806                                 pstring newname,
4807                                 uint32 attrs,
4808                                 BOOL replace_if_exists,
4809                                 BOOL src_has_wild,
4810                                 BOOL dest_has_wild)
4811 {
4812         pstring directory;
4813         pstring mask;
4814         pstring last_component_src;
4815         pstring last_component_dest;
4816         char *p;
4817         int count=0;
4818         NTSTATUS status = NT_STATUS_OK;
4819         SMB_STRUCT_STAT sbuf1, sbuf2;
4820         struct smb_Dir *dir_hnd = NULL;
4821         const char *dname;
4822         long offset = 0;
4823         pstring destname;
4824
4825         *directory = *mask = 0;
4826
4827         ZERO_STRUCT(sbuf1);
4828         ZERO_STRUCT(sbuf2);
4829
4830         status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1);
4831         if (!NT_STATUS_IS_OK(status)) {
4832                 return status;
4833         }
4834
4835         status = unix_convert(conn, newname, dest_has_wild, last_component_dest, &sbuf2);
4836         if (!NT_STATUS_IS_OK(status)) {
4837                 return status;
4838         }
4839
4840         /*
4841          * Split the old name into directory and last component
4842          * strings. Note that unix_convert may have stripped off a 
4843          * leading ./ from both name and newname if the rename is 
4844          * at the root of the share. We need to make sure either both
4845          * name and newname contain a / character or neither of them do
4846          * as this is checked in resolve_wildcards().
4847          */
4848
4849         p = strrchr_m(name,'/');
4850         if (!p) {
4851                 pstrcpy(directory,".");
4852                 pstrcpy(mask,name);
4853         } else {
4854                 *p = 0;
4855                 pstrcpy(directory,name);
4856                 pstrcpy(mask,p+1);
4857                 *p = '/'; /* Replace needed for exceptional test below. */
4858         }
4859
4860         /*
4861          * We should only check the mangled cache
4862          * here if unix_convert failed. This means
4863          * that the path in 'mask' doesn't exist
4864          * on the file system and so we need to look
4865          * for a possible mangle. This patch from
4866          * Tine Smukavec <valentin.smukavec@hermes.si>.
4867          */
4868
4869         if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
4870                 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
4871         }
4872
4873         if (!src_has_wild) {
4874                 files_struct *fsp;
4875
4876                 /*
4877                  * No wildcards - just process the one file.
4878                  */
4879                 BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
4880
4881                 /* Add a terminating '/' to the directory name. */
4882                 pstrcat(directory,"/");
4883                 pstrcat(directory,mask);
4884                 
4885                 /* Ensure newname contains a '/' also */
4886                 if(strrchr_m(newname,'/') == 0) {
4887                         pstring tmpstr;
4888                         
4889                         pstrcpy(tmpstr, "./");
4890                         pstrcat(tmpstr, newname);
4891                         pstrcpy(newname, tmpstr);
4892                 }
4893                 
4894                 DEBUG(3, ("rename_internals: case_sensitive = %d, "
4895                           "case_preserve = %d, short case preserve = %d, "
4896                           "directory = %s, newname = %s, "
4897                           "last_component_dest = %s, is_8_3 = %d\n", 
4898                           conn->case_sensitive, conn->case_preserve,
4899                           conn->short_case_preserve, directory, 
4900                           newname, last_component_dest, is_short_name));
4901
4902                 /* The dest name still may have wildcards. */
4903                 if (dest_has_wild) {
4904                         if (!resolve_wildcards(directory,newname)) {
4905                                 DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n", 
4906                                           directory,newname));
4907                                 return NT_STATUS_NO_MEMORY;
4908                         }
4909                 }
4910                                 
4911                 ZERO_STRUCT(sbuf1);
4912                 SMB_VFS_STAT(conn, directory, &sbuf1);
4913
4914                 status = S_ISDIR(sbuf1.st_mode) ?
4915                         open_directory(conn, req, directory, &sbuf1,
4916                                        DELETE_ACCESS,
4917                                        FILE_SHARE_READ|FILE_SHARE_WRITE,
4918                                        FILE_OPEN, 0, 0, NULL,
4919                                        &fsp)
4920                         : open_file_ntcreate(conn, req, directory, &sbuf1,
4921                                              DELETE_ACCESS,
4922                                              FILE_SHARE_READ|FILE_SHARE_WRITE,
4923                                              FILE_OPEN, 0, 0, 0, NULL,
4924                                              &fsp);
4925
4926                 if (!NT_STATUS_IS_OK(status)) {
4927                         DEBUG(3, ("Could not open rename source %s: %s\n",
4928                                   directory, nt_errstr(status)));
4929                         return status;
4930                 }
4931
4932                 status = rename_internals_fsp(conn, fsp, newname, attrs,
4933                                               replace_if_exists);
4934
4935                 close_file(fsp, NORMAL_CLOSE);
4936
4937                 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
4938                           nt_errstr(status), directory,newname));
4939
4940                 return status;
4941         }
4942
4943         /*
4944          * Wildcards - process each file that matches.
4945          */
4946         if (strequal(mask,"????????.???")) {
4947                 pstrcpy(mask,"*");
4948         }
4949                         
4950         status = check_name(conn, directory);
4951         if (!NT_STATUS_IS_OK(status)) {
4952                 return status;
4953         }
4954         
4955         dir_hnd = OpenDir(conn, directory, mask, attrs);
4956         if (dir_hnd == NULL) {
4957                 return map_nt_error_from_unix(errno);
4958         }
4959                 
4960         status = NT_STATUS_NO_SUCH_FILE;
4961         /*
4962          * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4963          * - gentest fix. JRA
4964          */
4965                         
4966         while ((dname = ReadDirName(dir_hnd, &offset))) {
4967                 files_struct *fsp;
4968                 pstring fname;
4969                 BOOL sysdir_entry = False;
4970
4971                 pstrcpy(fname,dname);
4972                                 
4973                 /* Quick check for "." and ".." */
4974                 if (fname[0] == '.') {
4975                         if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4976                                 if (attrs & aDIR) {
4977                                         sysdir_entry = True;
4978                                 } else {
4979                                         continue;
4980                                 }
4981                         }
4982                 }
4983
4984                 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
4985                         continue;
4986                 }
4987
4988                 if(!mask_match(fname, mask, conn->case_sensitive)) {
4989                         continue;
4990                 }
4991                                 
4992                 if (sysdir_entry) {
4993                         status = NT_STATUS_OBJECT_NAME_INVALID;
4994                         break;
4995                 }
4996
4997                 slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname);
4998
4999                 pstrcpy(destname,newname);
5000                         
5001                 if (!resolve_wildcards(fname,destname)) {
5002                         DEBUG(6, ("resolve_wildcards %s %s failed\n", 
5003                                   fname, destname));
5004                         continue;
5005                 }
5006                                 
5007                 ZERO_STRUCT(sbuf1);
5008                 SMB_VFS_STAT(conn, fname, &sbuf1);
5009
5010                 status = S_ISDIR(sbuf1.st_mode) ?
5011                         open_directory(conn, req, fname, &sbuf1,
5012                                        DELETE_ACCESS,
5013                                        FILE_SHARE_READ|FILE_SHARE_WRITE,
5014                                        FILE_OPEN, 0, 0, NULL,
5015                                        &fsp)
5016                         : open_file_ntcreate(conn, req, fname, &sbuf1,
5017                                              DELETE_ACCESS,
5018                                              FILE_SHARE_READ|FILE_SHARE_WRITE,
5019                                              FILE_OPEN, 0, 0, 0, NULL,
5020                                              &fsp);
5021
5022                 if (!NT_STATUS_IS_OK(status)) {
5023                         DEBUG(3,("rename_internals: open_file_ntcreate "
5024                                  "returned %s rename %s -> %s\n",
5025                                  nt_errstr(status), directory, newname));
5026                         break;
5027                 }
5028
5029                 status = rename_internals_fsp(conn, fsp, destname, attrs,
5030                                               replace_if_exists);
5031
5032                 close_file(fsp, NORMAL_CLOSE);
5033
5034                 if (!NT_STATUS_IS_OK(status)) {
5035                         DEBUG(3, ("rename_internals_fsp returned %s for "
5036                                   "rename %s -> %s\n", nt_errstr(status),
5037                                   directory, newname));
5038                         break;
5039                 }
5040
5041                 count++;
5042
5043                 DEBUG(3,("rename_internals: doing rename on %s -> "
5044                          "%s\n",fname,destname));
5045         }
5046         CloseDir(dir_hnd);
5047
5048         if (count == 0 && NT_STATUS_IS_OK(status)) {
5049                 status = map_nt_error_from_unix(errno);
5050         }
5051         
5052         return status;
5053 }
5054
5055 /****************************************************************************
5056  Reply to a mv.
5057 ****************************************************************************/
5058
5059 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, 
5060              int dum_buffsize)
5061 {
5062         int outsize = 0;
5063         pstring name;
5064         pstring newname;
5065         char *p;
5066         uint32 attrs = SVAL(inbuf,smb_vwv0);
5067         NTSTATUS status;
5068         BOOL src_has_wcard = False;
5069         BOOL dest_has_wcard = False;
5070         struct smb_request req;
5071
5072         START_PROFILE(SMBmv);
5073
5074         init_smb_request(&req, (uint8 *)inbuf);
5075
5076         p = smb_buf(inbuf) + 1;
5077         p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p,
5078                                    sizeof(name), 0, STR_TERMINATE, &status,
5079                                    &src_has_wcard);
5080         if (!NT_STATUS_IS_OK(status)) {
5081                 END_PROFILE(SMBmv);
5082                 return ERROR_NT(status);
5083         }
5084         p++;
5085         p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p,
5086                                    sizeof(newname), 0, STR_TERMINATE, &status,
5087                                    &dest_has_wcard);
5088         if (!NT_STATUS_IS_OK(status)) {
5089                 END_PROFILE(SMBmv);
5090                 return ERROR_NT(status);
5091         }
5092         
5093         status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &src_has_wcard);
5094         if (!NT_STATUS_IS_OK(status)) {
5095                 END_PROFILE(SMBmv);
5096                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5097                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5098                 }
5099                 return ERROR_NT(status);
5100         }
5101
5102         status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
5103         if (!NT_STATUS_IS_OK(status)) {
5104                 END_PROFILE(SMBmv);
5105                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5106                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5107                 }
5108                 return ERROR_NT(status);
5109         }
5110         
5111         DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
5112         
5113         status = rename_internals(conn, &req, name, newname, attrs, False,
5114                                   src_has_wcard, dest_has_wcard);
5115         if (!NT_STATUS_IS_OK(status)) {
5116                 END_PROFILE(SMBmv);
5117                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
5118                         /* We have re-scheduled this call. */
5119                         return -1;
5120                 }
5121                 return ERROR_NT(status);
5122         }
5123
5124         outsize = set_message(inbuf,outbuf,0,0,False);
5125   
5126         END_PROFILE(SMBmv);
5127         return(outsize);
5128 }
5129
5130 /*******************************************************************
5131  Copy a file as part of a reply_copy.
5132 ******************************************************************/
5133
5134 /*
5135  * TODO: check error codes on all callers
5136  */
5137
5138 NTSTATUS copy_file(connection_struct *conn,
5139                         char *src,
5140                         char *dest1,
5141                         int ofun,
5142                         int count,
5143                         BOOL target_is_directory)
5144 {
5145         SMB_STRUCT_STAT src_sbuf, sbuf2;
5146         SMB_OFF_T ret=-1;
5147         files_struct *fsp1,*fsp2;
5148         pstring dest;
5149         uint32 dosattrs;
5150         uint32 new_create_disposition;
5151         NTSTATUS status;
5152  
5153         pstrcpy(dest,dest1);
5154         if (target_is_directory) {
5155                 char *p = strrchr_m(src,'/');
5156                 if (p) {
5157                         p++;
5158                 } else {
5159                         p = src;
5160                 }
5161                 pstrcat(dest,"/");
5162                 pstrcat(dest,p);
5163         }
5164
5165         if (!vfs_file_exist(conn,src,&src_sbuf)) {
5166                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5167         }
5168
5169         if (!target_is_directory && count) {
5170                 new_create_disposition = FILE_OPEN;
5171         } else {
5172                 if (!map_open_params_to_ntcreate(dest1,0,ofun,
5173                                 NULL, NULL, &new_create_disposition, NULL)) {
5174                         return NT_STATUS_INVALID_PARAMETER;
5175                 }
5176         }
5177
5178         status = open_file_ntcreate(conn, NULL, src, &src_sbuf,
5179                         FILE_GENERIC_READ,
5180                         FILE_SHARE_READ|FILE_SHARE_WRITE,
5181                         FILE_OPEN,
5182                         0,
5183                         FILE_ATTRIBUTE_NORMAL,
5184                         INTERNAL_OPEN_ONLY,
5185                         NULL, &fsp1);
5186
5187         if (!NT_STATUS_IS_OK(status)) {
5188                 return status;
5189         }
5190
5191         dosattrs = dos_mode(conn, src, &src_sbuf);
5192         if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
5193                 ZERO_STRUCTP(&sbuf2);
5194         }
5195
5196         status = open_file_ntcreate(conn, NULL, dest, &sbuf2,
5197                         FILE_GENERIC_WRITE,
5198                         FILE_SHARE_READ|FILE_SHARE_WRITE,
5199                         new_create_disposition,
5200                         0,
5201                         dosattrs,
5202                         INTERNAL_OPEN_ONLY,
5203                         NULL, &fsp2);
5204
5205         if (!NT_STATUS_IS_OK(status)) {
5206                 close_file(fsp1,ERROR_CLOSE);
5207                 return status;
5208         }
5209
5210         if ((ofun&3) == 1) {
5211                 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
5212                         DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
5213                         /*
5214                          * Stop the copy from occurring.
5215                          */
5216                         ret = -1;
5217                         src_sbuf.st_size = 0;
5218                 }
5219         }
5220   
5221         if (src_sbuf.st_size) {
5222                 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
5223         }
5224
5225         close_file(fsp1,NORMAL_CLOSE);
5226
5227         /* Ensure the modtime is set correctly on the destination file. */
5228         fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
5229
5230         /*
5231          * As we are opening fsp1 read-only we only expect
5232          * an error on close on fsp2 if we are out of space.
5233          * Thus we don't look at the error return from the
5234          * close of fsp1.
5235          */
5236         status = close_file(fsp2,NORMAL_CLOSE);
5237
5238         if (!NT_STATUS_IS_OK(status)) {
5239                 return status;
5240         }
5241
5242         if (ret != (SMB_OFF_T)src_sbuf.st_size) {
5243                 return NT_STATUS_DISK_FULL;
5244         }
5245
5246         return NT_STATUS_OK;
5247 }
5248
5249 /****************************************************************************
5250  Reply to a file copy.
5251 ****************************************************************************/
5252
5253 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5254 {
5255         int outsize = 0;
5256         pstring name;
5257         pstring directory;
5258         pstring mask,newname;
5259         char *p;
5260         int count=0;
5261         int error = ERRnoaccess;
5262         int err = 0;
5263         int tid2 = SVAL(inbuf,smb_vwv0);
5264         int ofun = SVAL(inbuf,smb_vwv1);
5265         int flags = SVAL(inbuf,smb_vwv2);
5266         BOOL target_is_directory=False;
5267         BOOL source_has_wild = False;
5268         BOOL dest_has_wild = False;
5269         SMB_STRUCT_STAT sbuf1, sbuf2;
5270         NTSTATUS status;
5271         START_PROFILE(SMBcopy);
5272
5273         *directory = *mask = 0;
5274
5275         p = smb_buf(inbuf);
5276         p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p,
5277                                    sizeof(name), 0, STR_TERMINATE, &status,
5278                                    &source_has_wild);
5279         if (!NT_STATUS_IS_OK(status)) {
5280                 END_PROFILE(SMBcopy);
5281                 return ERROR_NT(status);
5282         }
5283         p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p,
5284                                    sizeof(newname), 0, STR_TERMINATE, &status,
5285                                    &dest_has_wild);
5286         if (!NT_STATUS_IS_OK(status)) {
5287                 END_PROFILE(SMBcopy);
5288                 return ERROR_NT(status);
5289         }
5290    
5291         DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
5292    
5293         if (tid2 != conn->cnum) {
5294                 /* can't currently handle inter share copies XXXX */
5295                 DEBUG(3,("Rejecting inter-share copy\n"));
5296                 END_PROFILE(SMBcopy);
5297                 return ERROR_DOS(ERRSRV,ERRinvdevice);
5298         }
5299
5300         status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &source_has_wild);
5301         if (!NT_STATUS_IS_OK(status)) {
5302                 END_PROFILE(SMBcopy);
5303                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5304                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5305                 }
5306                 return ERROR_NT(status);
5307         }
5308
5309         status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wild);
5310         if (!NT_STATUS_IS_OK(status)) {
5311                 END_PROFILE(SMBcopy);
5312                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5313                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5314                 }
5315                 return ERROR_NT(status);
5316         }
5317
5318         status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1);
5319         if (!NT_STATUS_IS_OK(status)) {
5320                 END_PROFILE(SMBcopy);
5321                 return ERROR_NT(status);
5322         }
5323
5324         status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2);
5325         if (!NT_STATUS_IS_OK(status)) {
5326                 END_PROFILE(SMBcopy);
5327                 return ERROR_NT(status);
5328         }
5329
5330         target_is_directory = VALID_STAT_OF_DIR(sbuf2);
5331
5332         if ((flags&1) && target_is_directory) {
5333                 END_PROFILE(SMBcopy);
5334                 return ERROR_DOS(ERRDOS,ERRbadfile);
5335         }
5336
5337         if ((flags&2) && !target_is_directory) {
5338                 END_PROFILE(SMBcopy);
5339                 return ERROR_DOS(ERRDOS,ERRbadpath);
5340         }
5341
5342         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
5343                 /* wants a tree copy! XXXX */
5344                 DEBUG(3,("Rejecting tree copy\n"));
5345                 END_PROFILE(SMBcopy);
5346                 return ERROR_DOS(ERRSRV,ERRerror);
5347         }
5348
5349         p = strrchr_m(name,'/');
5350         if (!p) {
5351                 pstrcpy(directory,"./");
5352                 pstrcpy(mask,name);
5353         } else {
5354                 *p = 0;
5355                 pstrcpy(directory,name);
5356                 pstrcpy(mask,p+1);
5357         }
5358
5359         /*
5360          * We should only check the mangled cache
5361          * here if unix_convert failed. This means
5362          * that the path in 'mask' doesn't exist
5363          * on the file system and so we need to look
5364          * for a possible mangle. This patch from
5365          * Tine Smukavec <valentin.smukavec@hermes.si>.
5366          */
5367
5368         if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5369                 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
5370         }
5371
5372         if (!source_has_wild) {
5373                 pstrcat(directory,"/");
5374                 pstrcat(directory,mask);
5375                 if (dest_has_wild) {
5376                         if (!resolve_wildcards(directory,newname)) {
5377                                 END_PROFILE(SMBcopy);
5378                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
5379                         }
5380                 }
5381
5382                 status = check_name(conn, directory);
5383                 if (!NT_STATUS_IS_OK(status)) {
5384                         return ERROR_NT(status);
5385                 }
5386                 
5387                 status = check_name(conn, newname);
5388                 if (!NT_STATUS_IS_OK(status)) {
5389                         return ERROR_NT(status);
5390                 }
5391                 
5392                 status = copy_file(conn,directory,newname,ofun,
5393                                         count,target_is_directory);
5394
5395                 if(!NT_STATUS_IS_OK(status)) {
5396                         END_PROFILE(SMBcopy);
5397                         return ERROR_NT(status);
5398                 } else {
5399                         count++;
5400                 }
5401         } else {
5402                 struct smb_Dir *dir_hnd = NULL;
5403                 const char *dname;
5404                 long offset = 0;
5405                 pstring destname;
5406
5407                 if (strequal(mask,"????????.???"))
5408                         pstrcpy(mask,"*");
5409
5410                 status = check_name(conn, directory);
5411                 if (!NT_STATUS_IS_OK(status)) {
5412                         return ERROR_NT(status);
5413                 }
5414                 
5415                 dir_hnd = OpenDir(conn, directory, mask, 0);
5416                 if (dir_hnd == NULL) {
5417                         status = map_nt_error_from_unix(errno);
5418                         return ERROR_NT(status);
5419                 }
5420
5421                 error = ERRbadfile;
5422
5423                 while ((dname = ReadDirName(dir_hnd, &offset))) {
5424                         pstring fname;
5425                         pstrcpy(fname,dname);
5426     
5427                         if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5428                                 continue;
5429                         }
5430
5431                         if(!mask_match(fname, mask, conn->case_sensitive)) {
5432                                 continue;
5433                         }
5434
5435                         error = ERRnoaccess;
5436                         slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
5437                         pstrcpy(destname,newname);
5438                         if (!resolve_wildcards(fname,destname)) {
5439                                 continue;
5440                         }
5441
5442                         status = check_name(conn, fname);
5443                         if (!NT_STATUS_IS_OK(status)) {
5444                                 return ERROR_NT(status);
5445                         }
5446                 
5447                         status = check_name(conn, destname);
5448                         if (!NT_STATUS_IS_OK(status)) {
5449                                 return ERROR_NT(status);
5450                         }
5451                 
5452                         DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
5453
5454                         status = copy_file(conn,fname,destname,ofun,
5455                                         count,target_is_directory);
5456                         if (NT_STATUS_IS_OK(status)) {
5457                                 count++;
5458                         }
5459                 }
5460                 CloseDir(dir_hnd);
5461         }
5462   
5463         if (count == 0) {
5464                 if(err) {
5465                         /* Error on close... */
5466                         errno = err;
5467                         END_PROFILE(SMBcopy);
5468                         return(UNIXERROR(ERRHRD,ERRgeneral));
5469                 }
5470
5471                 END_PROFILE(SMBcopy);
5472                 return ERROR_DOS(ERRDOS,error);
5473         }
5474   
5475         outsize = set_message(inbuf,outbuf,1,0,True);
5476         SSVAL(outbuf,smb_vwv0,count);
5477
5478         END_PROFILE(SMBcopy);
5479         return(outsize);
5480 }
5481
5482 /****************************************************************************
5483  Reply to a setdir.
5484 ****************************************************************************/
5485
5486 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5487 {
5488         int snum;
5489         int outsize = 0;
5490         pstring newdir;
5491         NTSTATUS status;
5492
5493         START_PROFILE(pathworks_setdir);
5494   
5495         snum = SNUM(conn);
5496         if (!CAN_SETDIR(snum)) {
5497                 END_PROFILE(pathworks_setdir);
5498                 return ERROR_DOS(ERRDOS,ERRnoaccess);
5499         }
5500
5501         srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), newdir,
5502                         smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE,
5503                         &status);
5504         if (!NT_STATUS_IS_OK(status)) {
5505                 END_PROFILE(pathworks_setdir);
5506                 return ERROR_NT(status);
5507         }
5508   
5509         status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newdir);
5510         if (!NT_STATUS_IS_OK(status)) {
5511                 END_PROFILE(pathworks_setdir);
5512                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5513                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5514                 }
5515                 return ERROR_NT(status);
5516         }
5517
5518         if (strlen(newdir) != 0) {
5519                 if (!vfs_directory_exist(conn,newdir,NULL)) {
5520                         END_PROFILE(pathworks_setdir);
5521                         return ERROR_DOS(ERRDOS,ERRbadpath);
5522                 }
5523                 set_conn_connectpath(conn,newdir);
5524         }
5525   
5526         outsize = set_message(inbuf,outbuf,0,0,False);
5527         SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
5528   
5529         DEBUG(3,("setdir %s\n", newdir));
5530
5531         END_PROFILE(pathworks_setdir);
5532         return(outsize);
5533 }
5534
5535 #undef DBGC_CLASS
5536 #define DBGC_CLASS DBGC_LOCKING
5537
5538 /****************************************************************************
5539  Get a lock pid, dealing with large count requests.
5540 ****************************************************************************/
5541
5542 uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
5543 {
5544         if(!large_file_format)
5545                 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
5546         else
5547                 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
5548 }
5549
5550 /****************************************************************************
5551  Get a lock count, dealing with large count requests.
5552 ****************************************************************************/
5553
5554 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
5555 {
5556         SMB_BIG_UINT count = 0;
5557
5558         if(!large_file_format) {
5559                 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
5560         } else {
5561
5562 #if defined(HAVE_LONGLONG)
5563                 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
5564                         ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
5565 #else /* HAVE_LONGLONG */
5566
5567                 /*
5568                  * NT4.x seems to be broken in that it sends large file (64 bit)
5569                  * lockingX calls even if the CAP_LARGE_FILES was *not*
5570                  * negotiated. For boxes without large unsigned ints truncate the
5571                  * lock count by dropping the top 32 bits.
5572                  */
5573
5574                 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
5575                         DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
5576                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
5577                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
5578                                 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
5579                 }
5580
5581                 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
5582 #endif /* HAVE_LONGLONG */
5583         }
5584
5585         return count;
5586 }
5587
5588 #if !defined(HAVE_LONGLONG)
5589 /****************************************************************************
5590  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
5591 ****************************************************************************/
5592
5593 static uint32 map_lock_offset(uint32 high, uint32 low)
5594 {
5595         unsigned int i;
5596         uint32 mask = 0;
5597         uint32 highcopy = high;
5598  
5599         /*
5600          * Try and find out how many significant bits there are in high.
5601          */
5602  
5603         for(i = 0; highcopy; i++)
5604                 highcopy >>= 1;
5605  
5606         /*
5607          * We use 31 bits not 32 here as POSIX
5608          * lock offsets may not be negative.
5609          */
5610  
5611         mask = (~0) << (31 - i);
5612  
5613         if(low & mask)
5614                 return 0; /* Fail. */
5615  
5616         high <<= (31 - i);
5617  
5618         return (high|low);
5619 }
5620 #endif /* !defined(HAVE_LONGLONG) */
5621
5622 /****************************************************************************
5623  Get a lock offset, dealing with large offset requests.
5624 ****************************************************************************/
5625
5626 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
5627 {
5628         SMB_BIG_UINT offset = 0;
5629
5630         *err = False;
5631
5632         if(!large_file_format) {
5633                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
5634         } else {
5635
5636 #if defined(HAVE_LONGLONG)
5637                 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
5638                                 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
5639 #else /* HAVE_LONGLONG */
5640
5641                 /*
5642                  * NT4.x seems to be broken in that it sends large file (64 bit)
5643                  * lockingX calls even if the CAP_LARGE_FILES was *not*
5644                  * negotiated. For boxes without large unsigned ints mangle the
5645                  * lock offset by mapping the top 32 bits onto the lower 32.
5646                  */
5647       
5648                 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
5649                         uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5650                         uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
5651                         uint32 new_low = 0;
5652
5653                         if((new_low = map_lock_offset(high, low)) == 0) {
5654                                 *err = True;
5655                                 return (SMB_BIG_UINT)-1;
5656                         }
5657
5658                         DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
5659                                 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
5660                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
5661                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
5662                 }
5663
5664                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5665 #endif /* HAVE_LONGLONG */
5666         }
5667
5668         return offset;
5669 }
5670
5671 /****************************************************************************
5672  Reply to a lockingX request.
5673 ****************************************************************************/
5674
5675 int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
5676                    int length, int bufsize)
5677 {
5678         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv2));
5679         unsigned char locktype = CVAL(inbuf,smb_vwv3);
5680         unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
5681         uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
5682         uint16 num_locks = SVAL(inbuf,smb_vwv7);
5683         SMB_BIG_UINT count = 0, offset = 0;
5684         uint32 lock_pid;
5685         int32 lock_timeout = IVAL(inbuf,smb_vwv4);
5686         int i;
5687         char *data;
5688         BOOL large_file_format =
5689                 (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
5690         BOOL err;
5691         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5692
5693         START_PROFILE(SMBlockingX);
5694         
5695         CHECK_FSP(fsp,conn);
5696         
5697         data = smb_buf(inbuf);
5698
5699         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
5700                 /* we don't support these - and CANCEL_LOCK makes w2k
5701                    and XP reboot so I don't really want to be
5702                    compatible! (tridge) */
5703                 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
5704         }
5705         
5706         /* Check if this is an oplock break on a file
5707            we have granted an oplock on.
5708         */
5709         if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
5710                 /* Client can insist on breaking to none. */
5711                 BOOL break_to_none = (oplocklevel == 0);
5712                 BOOL result;
5713
5714                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
5715                          "for fnum = %d\n", (unsigned int)oplocklevel,
5716                          fsp->fnum ));
5717
5718                 /*
5719                  * Make sure we have granted an exclusive or batch oplock on
5720                  * this file.
5721                  */
5722                 
5723                 if (fsp->oplock_type == 0) {
5724
5725                         /* The Samba4 nbench simulator doesn't understand
5726                            the difference between break to level2 and break
5727                            to none from level2 - it sends oplock break
5728                            replies in both cases. Don't keep logging an error
5729                            message here - just ignore it. JRA. */
5730
5731                         DEBUG(5,("reply_lockingX: Error : oplock break from "
5732                                  "client for fnum = %d (oplock=%d) and no "
5733                                  "oplock granted on this file (%s).\n",
5734                                  fsp->fnum, fsp->oplock_type, fsp->fsp_name));
5735
5736                         /* if this is a pure oplock break request then don't
5737                          * send a reply */
5738                         if (num_locks == 0 && num_ulocks == 0) {
5739                                 END_PROFILE(SMBlockingX);
5740                                 return -1;
5741                         } else {
5742                                 END_PROFILE(SMBlockingX);
5743                                 return ERROR_DOS(ERRDOS,ERRlock);
5744                         }
5745                 }
5746
5747                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
5748                     (break_to_none)) {
5749                         result = remove_oplock(fsp);
5750                 } else {
5751                         result = downgrade_oplock(fsp);
5752                 }
5753                 
5754                 if (!result) {
5755                         DEBUG(0, ("reply_lockingX: error in removing "
5756                                   "oplock on file %s\n", fsp->fsp_name));
5757                         /* Hmmm. Is this panic justified? */
5758                         smb_panic("internal tdb error");
5759                 }
5760
5761                 reply_to_oplock_break_requests(fsp);
5762
5763                 /* if this is a pure oplock break request then don't send a
5764                  * reply */
5765                 if (num_locks == 0 && num_ulocks == 0) {
5766                         /* Sanity check - ensure a pure oplock break is not a
5767                            chained request. */
5768                         if(CVAL(inbuf,smb_vwv0) != 0xff)
5769                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
5770                                          "break is a chained %d request !\n",
5771                                          (unsigned int)CVAL(inbuf,smb_vwv0) ));
5772                         END_PROFILE(SMBlockingX);
5773                         return -1;
5774                 }
5775         }
5776
5777         /*
5778          * We do this check *after* we have checked this is not a oplock break
5779          * response message. JRA.
5780          */
5781         
5782         release_level_2_oplocks_on_change(fsp);
5783         
5784         /* Data now points at the beginning of the list
5785            of smb_unlkrng structs */
5786         for(i = 0; i < (int)num_ulocks; i++) {
5787                 lock_pid = get_lock_pid( data, i, large_file_format);
5788                 count = get_lock_count( data, i, large_file_format);
5789                 offset = get_lock_offset( data, i, large_file_format, &err);
5790                 
5791                 /*
5792                  * There is no error code marked "stupid client bug".... :-).
5793                  */
5794                 if(err) {
5795                         END_PROFILE(SMBlockingX);
5796                         return ERROR_DOS(ERRDOS,ERRnoaccess);
5797                 }
5798
5799                 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
5800                           "pid %u, file %s\n", (double)offset, (double)count,
5801                           (unsigned int)lock_pid, fsp->fsp_name ));
5802                 
5803                 status = do_unlock(smbd_messaging_context(),
5804                                 fsp,
5805                                 lock_pid,
5806                                 count,
5807                                 offset,
5808                                 WINDOWS_LOCK);
5809
5810                 if (NT_STATUS_V(status)) {
5811                         END_PROFILE(SMBlockingX);
5812                         return ERROR_NT(status);
5813                 }
5814         }
5815
5816         /* Setup the timeout in seconds. */
5817
5818         if (!lp_blocking_locks(SNUM(conn))) {
5819                 lock_timeout = 0;
5820         }
5821         
5822         /* Now do any requested locks */
5823         data += ((large_file_format ? 20 : 10)*num_ulocks);
5824         
5825         /* Data now points at the beginning of the list
5826            of smb_lkrng structs */
5827         
5828         for(i = 0; i < (int)num_locks; i++) {
5829                 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
5830                                 READ_LOCK:WRITE_LOCK);
5831                 lock_pid = get_lock_pid( data, i, large_file_format);
5832                 count = get_lock_count( data, i, large_file_format);
5833                 offset = get_lock_offset( data, i, large_file_format, &err);
5834                 
5835                 /*
5836                  * There is no error code marked "stupid client bug".... :-).
5837                  */
5838                 if(err) {
5839                         END_PROFILE(SMBlockingX);
5840                         return ERROR_DOS(ERRDOS,ERRnoaccess);
5841                 }
5842                 
5843                 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
5844                           "%u, file %s timeout = %d\n", (double)offset,
5845                           (double)count, (unsigned int)lock_pid,
5846                           fsp->fsp_name, (int)lock_timeout ));
5847                 
5848                 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
5849                         if (lp_blocking_locks(SNUM(conn))) {
5850
5851                                 /* Schedule a message to ourselves to
5852                                    remove the blocking lock record and
5853                                    return the right error. */
5854
5855                                 if (!blocking_lock_cancel(fsp,
5856                                                 lock_pid,
5857                                                 offset,
5858                                                 count,
5859                                                 WINDOWS_LOCK,
5860                                                 locktype,
5861                                                 NT_STATUS_FILE_LOCK_CONFLICT)) {
5862                                         END_PROFILE(SMBlockingX);
5863                                         return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
5864                                 }
5865                         }
5866                         /* Remove a matching pending lock. */
5867                         status = do_lock_cancel(fsp,
5868                                                 lock_pid,
5869                                                 count,
5870                                                 offset,
5871                                                 WINDOWS_LOCK);
5872                 } else {
5873                         BOOL blocking_lock = lock_timeout ? True : False;
5874                         BOOL defer_lock = False;
5875                         struct byte_range_lock *br_lck;
5876                         uint32 block_smbpid;
5877
5878                         br_lck = do_lock(smbd_messaging_context(),
5879                                         fsp,
5880                                         lock_pid,
5881                                         count,
5882                                         offset, 
5883                                         lock_type,
5884                                         WINDOWS_LOCK,
5885                                         blocking_lock,
5886                                         &status,
5887                                         &block_smbpid);
5888
5889                         if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5890                                 /* Windows internal resolution for blocking locks seems
5891                                    to be about 200ms... Don't wait for less than that. JRA. */
5892                                 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
5893                                         lock_timeout = lp_lock_spin_time();
5894                                 }
5895                                 defer_lock = True;
5896                         }
5897
5898                         /* This heuristic seems to match W2K3 very well. If a
5899                            lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
5900                            it pretends we asked for a timeout of between 150 - 300 milliseconds as
5901                            far as I can tell. Replacement for do_lock_spin(). JRA. */
5902
5903                         if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
5904                                         NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
5905                                 defer_lock = True;
5906                                 lock_timeout = lp_lock_spin_time();
5907                         }
5908
5909                         if (br_lck && defer_lock) {
5910                                 /*
5911                                  * A blocking lock was requested. Package up
5912                                  * this smb into a queued request and push it
5913                                  * onto the blocking lock queue.
5914                                  */
5915                                 if(push_blocking_lock_request(br_lck,
5916                                                         inbuf, length,
5917                                                         fsp,
5918                                                         lock_timeout,
5919                                                         i,
5920                                                         lock_pid,
5921                                                         lock_type,
5922                                                         WINDOWS_LOCK,
5923                                                         offset,
5924                                                         count,
5925                                                         block_smbpid)) {
5926                                         TALLOC_FREE(br_lck);
5927                                         END_PROFILE(SMBlockingX);
5928                                         return -1;
5929                                 }
5930                         }
5931
5932                         TALLOC_FREE(br_lck);
5933                 }
5934
5935                 if (NT_STATUS_V(status)) {
5936                         END_PROFILE(SMBlockingX);
5937                         return ERROR_NT(status);
5938                 }
5939         }
5940         
5941         /* If any of the above locks failed, then we must unlock
5942            all of the previous locks (X/Open spec). */
5943
5944         if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
5945                         (i != num_locks) &&
5946                         (num_locks != 0)) {
5947                 /*
5948                  * Ensure we don't do a remove on the lock that just failed,
5949                  * as under POSIX rules, if we have a lock already there, we
5950                  * will delete it (and we shouldn't) .....
5951                  */
5952                 for(i--; i >= 0; i--) {
5953                         lock_pid = get_lock_pid( data, i, large_file_format);
5954                         count = get_lock_count( data, i, large_file_format);
5955                         offset = get_lock_offset( data, i, large_file_format,
5956                                                   &err);
5957                         
5958                         /*
5959                          * There is no error code marked "stupid client
5960                          * bug".... :-).
5961                          */
5962                         if(err) {
5963                                 END_PROFILE(SMBlockingX);
5964                                 return ERROR_DOS(ERRDOS,ERRnoaccess);
5965                         }
5966                         
5967                         do_unlock(smbd_messaging_context(),
5968                                 fsp,
5969                                 lock_pid,
5970                                 count,
5971                                 offset,
5972                                 WINDOWS_LOCK);
5973                 }
5974                 END_PROFILE(SMBlockingX);
5975                 return ERROR_NT(status);
5976         }
5977
5978         set_message(inbuf,outbuf,2,0,True);
5979         
5980         DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5981                   fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
5982         
5983         END_PROFILE(SMBlockingX);
5984         return chain_reply(inbuf,&outbuf,length,bufsize);
5985 }
5986
5987 #undef DBGC_CLASS
5988 #define DBGC_CLASS DBGC_ALL
5989
5990 /****************************************************************************
5991  Reply to a SMBreadbmpx (read block multiplex) request.
5992 ****************************************************************************/
5993
5994 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5995 {
5996         ssize_t nread = -1;
5997         ssize_t total_read;
5998         char *data;
5999         SMB_OFF_T startpos;
6000         int outsize;
6001         size_t maxcount;
6002         int max_per_packet;
6003         size_t tcount;
6004         int pad;
6005         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6006         START_PROFILE(SMBreadBmpx);
6007
6008         /* this function doesn't seem to work - disable by default */
6009         if (!lp_readbmpx()) {
6010                 END_PROFILE(SMBreadBmpx);
6011                 return ERROR_DOS(ERRSRV,ERRuseSTD);
6012         }
6013
6014         outsize = set_message(inbuf,outbuf,8,0,True);
6015
6016         CHECK_FSP(fsp,conn);
6017         if (!CHECK_READ(fsp,inbuf)) {
6018                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
6019         }
6020
6021         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
6022         maxcount = SVAL(inbuf,smb_vwv3);
6023
6024         data = smb_buf(outbuf);
6025         pad = ((long)data)%4;
6026         if (pad)
6027                 pad = 4 - pad;
6028         data += pad;
6029
6030         max_per_packet = bufsize-(outsize+pad);
6031         tcount = maxcount;
6032         total_read = 0;
6033
6034         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
6035                 END_PROFILE(SMBreadBmpx);
6036                 return ERROR_DOS(ERRDOS,ERRlock);
6037         }
6038
6039         do {
6040                 size_t N = MIN(max_per_packet,tcount-total_read);
6041   
6042                 nread = read_file(fsp,data,startpos,N);
6043
6044                 if (nread <= 0)
6045                         nread = 0;
6046
6047                 if (nread < (ssize_t)N)
6048                         tcount = total_read + nread;
6049
6050                 set_message(inbuf,outbuf,8,nread+pad,False);
6051                 SIVAL(outbuf,smb_vwv0,startpos);
6052                 SSVAL(outbuf,smb_vwv2,tcount);
6053                 SSVAL(outbuf,smb_vwv6,nread);
6054                 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
6055
6056                 show_msg(outbuf);
6057                 if (!send_smb(smbd_server_fd(),outbuf))
6058                         exit_server_cleanly("reply_readbmpx: send_smb failed.");
6059
6060                 total_read += nread;
6061                 startpos += nread;
6062         } while (total_read < (ssize_t)tcount);
6063
6064         END_PROFILE(SMBreadBmpx);
6065         return(-1);
6066 }
6067
6068 /****************************************************************************
6069  Reply to a SMBsetattrE.
6070 ****************************************************************************/
6071
6072 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
6073 {
6074         struct timespec ts[2];
6075         int outsize = 0;
6076         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6077         START_PROFILE(SMBsetattrE);
6078
6079         outsize = set_message(inbuf,outbuf,0,0,False);
6080
6081         if(!fsp || (fsp->conn != conn)) {
6082                 END_PROFILE(SMBsetattrE);
6083                 return ERROR_DOS(ERRDOS,ERRbadfid);
6084         }
6085
6086         /*
6087          * Convert the DOS times into unix times. Ignore create
6088          * time as UNIX can't set this.
6089          */
6090
6091         ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv3)); /* atime. */
6092         ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv5)); /* mtime. */
6093   
6094         /* 
6095          * Patch from Ray Frush <frush@engr.colostate.edu>
6096          * Sometimes times are sent as zero - ignore them.
6097          */
6098
6099         if (null_timespec(ts[0]) && null_timespec(ts[1])) {
6100                 /* Ignore request */
6101                 if( DEBUGLVL( 3 ) ) {
6102                         dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
6103                         dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
6104                 }
6105                 END_PROFILE(SMBsetattrE);
6106                 return(outsize);
6107         } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
6108                 /* set modify time = to access time if modify time was unset */
6109                 ts[1] = ts[0];
6110         }
6111
6112         /* Set the date on this file */
6113         /* Should we set pending modtime here ? JRA */
6114         if(file_ntimes(conn, fsp->fsp_name, ts)) {
6115                 END_PROFILE(SMBsetattrE);
6116                 return ERROR_DOS(ERRDOS,ERRnoaccess);
6117         }
6118   
6119         DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
6120                 fsp->fnum,
6121                 (unsigned int)ts[0].tv_sec,
6122                 (unsigned int)ts[1].tv_sec));
6123
6124         END_PROFILE(SMBsetattrE);
6125         return(outsize);
6126 }
6127
6128
6129 /* Back from the dead for OS/2..... JRA. */
6130
6131 /****************************************************************************
6132  Reply to a SMBwritebmpx (write block multiplex primary) request.
6133 ****************************************************************************/
6134
6135 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
6136 {
6137         size_t numtowrite;
6138         ssize_t nwritten = -1;
6139         int outsize = 0;
6140         SMB_OFF_T startpos;
6141         size_t tcount;
6142         BOOL write_through;
6143         int smb_doff;
6144         char *data;
6145         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6146         NTSTATUS status;
6147         START_PROFILE(SMBwriteBmpx);
6148
6149         CHECK_FSP(fsp,conn);
6150         if (!CHECK_WRITE(fsp)) {
6151                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
6152         }
6153         if (HAS_CACHED_ERROR(fsp)) {
6154                 return(CACHED_ERROR(fsp));
6155         }
6156
6157         tcount = SVAL(inbuf,smb_vwv1);
6158         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
6159         write_through = BITSETW(inbuf+smb_vwv7,0);
6160         numtowrite = SVAL(inbuf,smb_vwv10);
6161         smb_doff = SVAL(inbuf,smb_vwv11);
6162
6163         data = smb_base(inbuf) + smb_doff;
6164
6165         /* If this fails we need to send an SMBwriteC response,
6166                 not an SMBwritebmpx - set this up now so we don't forget */
6167         SCVAL(outbuf,smb_com,SMBwritec);
6168
6169         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
6170                 END_PROFILE(SMBwriteBmpx);
6171                 return(ERROR_DOS(ERRDOS,ERRlock));
6172         }
6173
6174         nwritten = write_file(fsp,data,startpos,numtowrite);
6175
6176         status = sync_file(conn, fsp, write_through);
6177         if (!NT_STATUS_IS_OK(status)) {
6178                 END_PROFILE(SMBwriteBmpx);
6179                 DEBUG(5,("reply_writebmpx: sync_file for %s returned %s\n",
6180                         fsp->fsp_name, nt_errstr(status) ));
6181                 return ERROR_NT(status);
6182         }
6183   
6184         if(nwritten < (ssize_t)numtowrite) {
6185                 END_PROFILE(SMBwriteBmpx);
6186                 return(UNIXERROR(ERRHRD,ERRdiskfull));
6187         }
6188
6189         /* If the maximum to be written to this file
6190                 is greater than what we just wrote then set
6191                 up a secondary struct to be attached to this
6192                 fd, we will use this to cache error messages etc. */
6193
6194         if((ssize_t)tcount > nwritten) {
6195                 write_bmpx_struct *wbms;
6196                 if(fsp->wbmpx_ptr != NULL)
6197                         wbms = fsp->wbmpx_ptr; /* Use an existing struct */
6198                 else
6199                         wbms = SMB_MALLOC_P(write_bmpx_struct);
6200                 if(!wbms) {
6201                         DEBUG(0,("Out of memory in reply_readmpx\n"));
6202                         END_PROFILE(SMBwriteBmpx);
6203                         return(ERROR_DOS(ERRSRV,ERRnoresource));
6204                 }
6205                 wbms->wr_mode = write_through;
6206                 wbms->wr_discard = False; /* No errors yet */
6207                 wbms->wr_total_written = nwritten;
6208                 wbms->wr_errclass = 0;
6209                 wbms->wr_error = 0;
6210                 fsp->wbmpx_ptr = wbms;
6211         }
6212
6213         /* We are returning successfully, set the message type back to
6214                 SMBwritebmpx */
6215         SCVAL(outbuf,smb_com,SMBwriteBmpx);
6216   
6217         outsize = set_message(inbuf,outbuf,1,0,True);
6218   
6219         SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
6220   
6221         DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
6222                         fsp->fnum, (int)numtowrite, (int)nwritten ) );
6223
6224         if (write_through && tcount==nwritten) {
6225                 /* We need to send both a primary and a secondary response */
6226                 smb_setlen(inbuf,outbuf,outsize - 4);
6227                 show_msg(outbuf);
6228                 if (!send_smb(smbd_server_fd(),outbuf))
6229                         exit_server_cleanly("reply_writebmpx: send_smb failed.");
6230
6231                 /* Now the secondary */
6232                 outsize = set_message(inbuf,outbuf,1,0,True);
6233                 SCVAL(outbuf,smb_com,SMBwritec);
6234                 SSVAL(outbuf,smb_vwv0,nwritten);
6235         }
6236
6237         END_PROFILE(SMBwriteBmpx);
6238         return(outsize);
6239 }
6240
6241 /****************************************************************************
6242  Reply to a SMBwritebs (write block multiplex secondary) request.
6243 ****************************************************************************/
6244
6245 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
6246 {
6247         size_t numtowrite;
6248         ssize_t nwritten = -1;
6249         int outsize = 0;
6250         SMB_OFF_T startpos;
6251         size_t tcount;
6252         BOOL write_through;
6253         int smb_doff;
6254         char *data;
6255         write_bmpx_struct *wbms;
6256         BOOL send_response = False; 
6257         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6258         NTSTATUS status;
6259         START_PROFILE(SMBwriteBs);
6260
6261         CHECK_FSP(fsp,conn);
6262         if (!CHECK_WRITE(fsp)) {
6263                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
6264         }
6265
6266         tcount = SVAL(inbuf,smb_vwv1);
6267         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
6268         numtowrite = SVAL(inbuf,smb_vwv6);
6269         smb_doff = SVAL(inbuf,smb_vwv7);
6270
6271         data = smb_base(inbuf) + smb_doff;
6272
6273         /* We need to send an SMBwriteC response, not an SMBwritebs */
6274         SCVAL(outbuf,smb_com,SMBwritec);
6275
6276         /* This fd should have an auxiliary struct attached,
6277                 check that it does */
6278         wbms = fsp->wbmpx_ptr;
6279         if(!wbms) {
6280                 END_PROFILE(SMBwriteBs);
6281                 return(-1);
6282         }
6283
6284         /* If write through is set we can return errors, else we must cache them */
6285         write_through = wbms->wr_mode;
6286
6287         /* Check for an earlier error */
6288         if(wbms->wr_discard) {
6289                 END_PROFILE(SMBwriteBs);
6290                 return -1; /* Just discard the packet */
6291         }
6292
6293         nwritten = write_file(fsp,data,startpos,numtowrite);
6294
6295         status = sync_file(conn, fsp, write_through);
6296   
6297         if (nwritten < (ssize_t)numtowrite || !NT_STATUS_IS_OK(status)) {
6298                 if(write_through) {
6299                         /* We are returning an error - we can delete the aux struct */
6300                         if (wbms)
6301                                 free((char *)wbms);
6302                         fsp->wbmpx_ptr = NULL;
6303                         END_PROFILE(SMBwriteBs);
6304                         return(ERROR_DOS(ERRHRD,ERRdiskfull));
6305                 }
6306                 wbms->wr_errclass = ERRHRD;
6307                 wbms->wr_error = ERRdiskfull;
6308                 wbms->wr_status = NT_STATUS_DISK_FULL;
6309                 wbms->wr_discard = True;
6310                 END_PROFILE(SMBwriteBs);
6311                 return -1;
6312         }
6313
6314         /* Increment the total written, if this matches tcount
6315                 we can discard the auxiliary struct (hurrah !) and return a writeC */
6316         wbms->wr_total_written += nwritten;
6317         if(wbms->wr_total_written >= tcount) {
6318                 if (write_through) {
6319                         outsize = set_message(inbuf,outbuf,1,0,True);
6320                         SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);    
6321                         send_response = True;
6322                 }
6323
6324                 free((char *)wbms);
6325                 fsp->wbmpx_ptr = NULL;
6326         }
6327
6328         if(send_response) {
6329                 END_PROFILE(SMBwriteBs);
6330                 return(outsize);
6331         }
6332
6333         END_PROFILE(SMBwriteBs);
6334         return(-1);
6335 }
6336
6337 /****************************************************************************
6338  Reply to a SMBgetattrE.
6339 ****************************************************************************/
6340
6341 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
6342 {
6343         SMB_STRUCT_STAT sbuf;
6344         int outsize = 0;
6345         int mode;
6346         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6347         START_PROFILE(SMBgetattrE);
6348
6349         outsize = set_message(inbuf,outbuf,11,0,True);
6350
6351         if(!fsp || (fsp->conn != conn)) {
6352                 END_PROFILE(SMBgetattrE);
6353                 return ERROR_DOS(ERRDOS,ERRbadfid);
6354         }
6355
6356         /* Do an fstat on this file */
6357         if(fsp_stat(fsp, &sbuf)) {
6358                 END_PROFILE(SMBgetattrE);
6359                 return(UNIXERROR(ERRDOS,ERRnoaccess));
6360         }
6361   
6362         mode = dos_mode(conn,fsp->fsp_name,&sbuf);
6363   
6364         /*
6365          * Convert the times into dos times. Set create
6366          * date to be last modify date as UNIX doesn't save
6367          * this.
6368          */
6369
6370         srv_put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
6371         srv_put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
6372         /* Should we check pending modtime here ? JRA */
6373         srv_put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
6374
6375         if (mode & aDIR) {
6376                 SIVAL(outbuf,smb_vwv6,0);
6377                 SIVAL(outbuf,smb_vwv8,0);
6378         } else {
6379                 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
6380                 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
6381                 SIVAL(outbuf,smb_vwv8,allocation_size);
6382         }
6383         SSVAL(outbuf,smb_vwv10, mode);
6384   
6385         DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
6386   
6387         END_PROFILE(SMBgetattrE);
6388         return(outsize);
6389 }