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