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