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