r24422: Convert reply_ctemp to the new API
[vlendec/samba-autobuild/.git] / source3 / smbd / reply.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Main SMB reply routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Andrew Bartlett      2001
6    Copyright (C) Jeremy Allison 1992-2007.
7    Copyright (C) Volker Lendecke 2007
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22 /*
23    This file handles most of the reply_ calls that the server
24    makes to handle specific protocols
25 */
26
27 #include "includes.h"
28
29 /* look in server.c for some explanation of these variables */
30 extern enum protocol_types Protocol;
31 extern int max_recv;
32 unsigned int smb_echo_count = 0;
33 extern uint32 global_client_caps;
34
35 extern struct current_user current_user;
36 extern BOOL global_encrypted_passwords_negotiated;
37
38 /****************************************************************************
39  Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
40  path or anything including wildcards.
41  We're assuming here that '/' is not the second byte in any multibyte char
42  set (a safe assumption). '\\' *may* be the second byte in a multibyte char
43  set.
44 ****************************************************************************/
45
46 /* Custom version for processing POSIX paths. */
47 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
48
49 static NTSTATUS check_path_syntax_internal(char *path,
50                                            BOOL posix_path,
51                                            BOOL *p_last_component_contains_wcard)
52 {
53         char *d = path;
54         const char *s = path;
55         NTSTATUS ret = NT_STATUS_OK;
56         BOOL start_of_name_component = True;
57
58         *p_last_component_contains_wcard = False;
59
60         while (*s) {
61                 if (IS_PATH_SEP(*s,posix_path)) {
62                         /*
63                          * Safe to assume is not the second part of a mb char
64                          * as this is handled below.
65                          */
66                         /* Eat multiple '/' or '\\' */
67                         while (IS_PATH_SEP(*s,posix_path)) {
68                                 s++;
69                         }
70                         if ((d != path) && (*s != '\0')) {
71                                 /* We only care about non-leading or trailing '/' or '\\' */
72                                 *d++ = '/';
73                         }
74
75                         start_of_name_component = True;
76                         /* New component. */
77                         *p_last_component_contains_wcard = False;
78                         continue;
79                 }
80
81                 if (start_of_name_component) {
82                         if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
83                                 /* Uh oh - "/../" or "\\..\\"  or "/..\0" or "\\..\0" ! */
84
85                                 /*
86                                  * No mb char starts with '.' so we're safe checking the directory separator here.
87                                  */
88
89                                 /* If  we just added a '/' - delete it */
90                                 if ((d > path) && (*(d-1) == '/')) {
91                                         *(d-1) = '\0';
92                                         d--;
93                                 }
94
95                                 /* Are we at the start ? Can't go back further if so. */
96                                 if (d <= path) {
97                                         ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
98                                         break;
99                                 }
100                                 /* Go back one level... */
101                                 /* We know this is safe as '/' cannot be part of a mb sequence. */
102                                 /* NOTE - if this assumption is invalid we are not in good shape... */
103                                 /* Decrement d first as d points to the *next* char to write into. */
104                                 for (d--; d > path; d--) {
105                                         if (*d == '/')
106                                                 break;
107                                 }
108                                 s += 2; /* Else go past the .. */
109                                 /* We're still at the start of a name component, just the previous one. */
110                                 continue;
111
112                         } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
113                                 if (posix_path) {
114                                         /* Eat the '.' */
115                                         s++;
116                                         continue;
117                                 }
118                         }
119
120                 }
121
122                 if (!(*s & 0x80)) {
123                         if (!posix_path) {
124                                 if (*s <= 0x1f) {
125                                         return NT_STATUS_OBJECT_NAME_INVALID;
126                                 }
127                                 switch (*s) {
128                                         case '*':
129                                         case '?':
130                                         case '<':
131                                         case '>':
132                                         case '"':
133                                                 *p_last_component_contains_wcard = True;
134                                                 break;
135                                         default:
136                                                 break;
137                                 }
138                         }
139                         *d++ = *s++;
140                 } else {
141                         size_t siz;
142                         /* Get the size of the next MB character. */
143                         next_codepoint(s,&siz);
144                         switch(siz) {
145                                 case 5:
146                                         *d++ = *s++;
147                                         /*fall through*/
148                                 case 4:
149                                         *d++ = *s++;
150                                         /*fall through*/
151                                 case 3:
152                                         *d++ = *s++;
153                                         /*fall through*/
154                                 case 2:
155                                         *d++ = *s++;
156                                         /*fall through*/
157                                 case 1:
158                                         *d++ = *s++;
159                                         break;
160                                 default:
161                                         DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
162                                         *d = '\0';
163                                         return NT_STATUS_INVALID_PARAMETER;
164                         }
165                 }
166                 start_of_name_component = False;
167         }
168
169         *d = '\0';
170         return ret;
171 }
172
173 /****************************************************************************
174  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
175  No wildcards allowed.
176 ****************************************************************************/
177
178 NTSTATUS check_path_syntax(char *path)
179 {
180         BOOL ignore;
181         return check_path_syntax_internal(path, False, &ignore);
182 }
183
184 /****************************************************************************
185  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
186  Wildcards allowed - p_contains_wcard returns true if the last component contained
187  a wildcard.
188 ****************************************************************************/
189
190 NTSTATUS check_path_syntax_wcard(char *path, BOOL *p_contains_wcard)
191 {
192         return check_path_syntax_internal(path, False, p_contains_wcard);
193 }
194
195 /****************************************************************************
196  Check the path for a POSIX client.
197  We're assuming here that '/' is not the second byte in any multibyte char
198  set (a safe assumption).
199 ****************************************************************************/
200
201 NTSTATUS check_path_syntax_posix(char *path)
202 {
203         BOOL ignore;
204         return check_path_syntax_internal(path, True, &ignore);
205 }
206
207 /****************************************************************************
208  Pull a string and check the path allowing a wilcard - provide for error return.
209 ****************************************************************************/
210
211 size_t srvstr_get_path_wcard(const char *inbuf, uint16 smb_flags2, char *dest,
212                              const char *src, size_t dest_len, size_t src_len,
213                              int flags, NTSTATUS *err, BOOL *contains_wcard)
214 {
215         size_t ret;
216 #ifdef DEVELOPER
217         SMB_ASSERT(dest_len == sizeof(pstring));
218 #endif
219
220         if (src_len == 0) {
221                 ret = srvstr_pull_buf(inbuf, smb_flags2, dest, src,
222                                       dest_len, flags);
223         } else {
224                 ret = srvstr_pull(inbuf, smb_flags2, dest, src,
225                                   dest_len, src_len, flags);
226         }
227
228         *contains_wcard = False;
229
230         if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
231                 /* 
232                  * For a DFS path the function parse_dfs_path()
233                  * will do the path processing, just make a copy.
234                  */
235                 *err = NT_STATUS_OK;
236                 return ret;
237         }
238
239         if (lp_posix_pathnames()) {
240                 *err = check_path_syntax_posix(dest);
241         } else {
242                 *err = check_path_syntax_wcard(dest, contains_wcard);
243         }
244
245         return ret;
246 }
247
248 /****************************************************************************
249  Pull a string and check the path - provide for error return.
250 ****************************************************************************/
251
252 size_t srvstr_get_path(const char *inbuf, uint16 smb_flags2, char *dest,
253                        const char *src, size_t dest_len, size_t src_len,
254                        int flags, NTSTATUS *err)
255 {
256         size_t ret;
257 #ifdef DEVELOPER
258         SMB_ASSERT(dest_len == sizeof(pstring));
259 #endif
260
261         if (src_len == 0) {
262                 ret = srvstr_pull_buf(inbuf, smb_flags2, dest, src,
263                                       dest_len, flags);
264         } else {
265                 ret = srvstr_pull(inbuf, smb_flags2, dest, src,
266                                   dest_len, src_len, flags);
267         }
268
269         if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
270                 /* 
271                  * For a DFS path the function parse_dfs_path()
272                  * will do the path processing, just make a copy.
273                  */
274                 *err = NT_STATUS_OK;
275                 return ret;
276         }
277
278         if (lp_posix_pathnames()) {
279                 *err = check_path_syntax_posix(dest);
280         } else {
281                 *err = check_path_syntax(dest);
282         }
283
284         return ret;
285 }
286
287 /****************************************************************************
288  Check if we have a correct fsp pointing to a file. Replacement for the
289  CHECK_FSP macro.
290 ****************************************************************************/
291
292 BOOL check_fsp(connection_struct *conn, struct smb_request *req,
293                files_struct *fsp, struct current_user *user)
294 {
295         if (!(fsp) || !(conn)) {
296                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
297                 return False;
298         }
299         if (((conn) != (fsp)->conn) || user->vuid != (fsp)->vuid) {
300                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
301                 return False;
302         }
303         if ((fsp)->is_directory) {
304                 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
305                 return False;
306         }
307         if ((fsp)->fh->fd == -1) {
308                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
309                 return False;
310         }
311         (fsp)->num_smb_operations++;
312         return True;
313 }
314
315 /****************************************************************************
316  Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
317 ****************************************************************************/
318
319 BOOL fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
320                       files_struct *fsp, struct current_user *user)
321 {
322         if ((fsp) && (conn) && ((conn)==(fsp)->conn)
323             && (current_user.vuid==(fsp)->vuid)) {
324                 return True;
325         }
326
327         reply_nterror(req, NT_STATUS_INVALID_HANDLE);
328         return False;
329 }
330
331 /****************************************************************************
332  Reply to a (netbios-level) special message.
333 ****************************************************************************/
334
335 void reply_special(char *inbuf)
336 {
337         int msg_type = CVAL(inbuf,0);
338         int msg_flags = CVAL(inbuf,1);
339         fstring name1,name2;
340         char name_type = 0;
341
342         /*
343          * We only really use 4 bytes of the outbuf, but for the smb_setlen
344          * calculation & friends (send_smb uses that) we need the full smb
345          * header.
346          */
347         char outbuf[smb_size];
348         
349         static BOOL already_got_session = False;
350
351         *name1 = *name2 = 0;
352         
353         memset(outbuf, '\0', sizeof(outbuf));
354
355         smb_setlen(inbuf,outbuf,0);
356         
357         switch (msg_type) {
358         case 0x81: /* session request */
359                 
360                 if (already_got_session) {
361                         exit_server_cleanly("multiple session request not permitted");
362                 }
363                 
364                 SCVAL(outbuf,0,0x82);
365                 SCVAL(outbuf,3,0);
366                 if (name_len(inbuf+4) > 50 || 
367                     name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
368                         DEBUG(0,("Invalid name length in session request\n"));
369                         return;
370                 }
371                 name_extract(inbuf,4,name1);
372                 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
373                 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
374                          name1,name2));      
375
376                 set_local_machine_name(name1, True);
377                 set_remote_machine_name(name2, True);
378
379                 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
380                          get_local_machine_name(), get_remote_machine_name(),
381                          name_type));
382
383                 if (name_type == 'R') {
384                         /* We are being asked for a pathworks session --- 
385                            no thanks! */
386                         SCVAL(outbuf, 0,0x83);
387                         break;
388                 }
389
390                 /* only add the client's machine name to the list
391                    of possibly valid usernames if we are operating
392                    in share mode security */
393                 if (lp_security() == SEC_SHARE) {
394                         add_session_user(get_remote_machine_name());
395                 }
396
397                 reload_services(True);
398                 reopen_logs();
399
400                 already_got_session = True;
401                 break;
402                 
403         case 0x89: /* session keepalive request 
404                       (some old clients produce this?) */
405                 SCVAL(outbuf,0,SMBkeepalive);
406                 SCVAL(outbuf,3,0);
407                 break;
408                 
409         case 0x82: /* positive session response */
410         case 0x83: /* negative session response */
411         case 0x84: /* retarget session response */
412                 DEBUG(0,("Unexpected session response\n"));
413                 break;
414                 
415         case SMBkeepalive: /* session keepalive */
416         default:
417                 return;
418         }
419         
420         DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
421                     msg_type, msg_flags));
422
423         send_smb(smbd_server_fd(), outbuf);
424         return;
425 }
426
427 /****************************************************************************
428  Reply to a tcon.
429  conn POINTER CAN BE NULL HERE !
430 ****************************************************************************/
431
432 int reply_tcon(connection_struct *conn,
433                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
434 {
435         TALLOC_CTX *ctx;
436         const char *service;
437         char *service_buf = NULL;
438         char *password = NULL;
439         char *dev = NULL;
440         int outsize = 0;
441         uint16 vuid = SVAL(inbuf,smb_uid);
442         int pwlen=0;
443         NTSTATUS nt_status;
444         char *p;
445         DATA_BLOB password_blob;
446
447         START_PROFILE(SMBtcon);
448
449         ctx = talloc_init("reply_tcon");
450         if (!ctx) {
451                 END_PROFILE(SMBtcon);
452                 return ERROR_NT(NT_STATUS_NO_MEMORY);
453         }
454
455         p = smb_buf(inbuf)+1;
456         p += srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2),
457                         &service_buf, p, STR_TERMINATE) + 1;
458         pwlen = srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2),
459                         &password, p, STR_TERMINATE) + 1;
460         p += pwlen;
461         p += srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2),
462                         &dev, p, STR_TERMINATE) + 1;
463
464         if (service_buf == NULL || password == NULL || dev == NULL) {
465                 TALLOC_FREE(ctx);
466                 END_PROFILE(SMBtcon);
467                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
468         }
469         p = strrchr_m(service_buf,'\\');
470         if (p) {
471                 service = p+1;
472         } else {
473                 service = service_buf;
474         }
475
476         password_blob = data_blob(password, pwlen+1);
477
478         conn = make_connection(service,password_blob,dev,vuid,&nt_status);
479
480         data_blob_clear_free(&password_blob);
481
482         if (!conn) {
483                 TALLOC_FREE(ctx);
484                 END_PROFILE(SMBtcon);
485                 return ERROR_NT(nt_status);
486         }
487
488         outsize = set_message(inbuf,outbuf,2,0,True);
489         SSVAL(outbuf,smb_vwv0,max_recv);
490         SSVAL(outbuf,smb_vwv1,conn->cnum);
491         SSVAL(outbuf,smb_tid,conn->cnum);
492
493         DEBUG(3,("tcon service=%s cnum=%d\n", 
494                  service, conn->cnum));
495
496         END_PROFILE(SMBtcon);
497         TALLOC_FREE(ctx);
498         return(outsize);
499 }
500
501 /****************************************************************************
502  Reply to a tcon and X.
503  conn POINTER CAN BE NULL HERE !
504 ****************************************************************************/
505
506 void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
507 {
508         char *service = NULL;
509         DATA_BLOB password;
510
511         TALLOC_CTX *ctx = NULL;
512         /* what the cleint thinks the device is */
513         char *client_devicetype = NULL;
514         /* what the server tells the client the share represents */
515         const char *server_devicetype;
516         NTSTATUS nt_status;
517         int passlen;
518         char *path = NULL;
519         char *p, *q;
520         uint16 tcon_flags;
521
522         START_PROFILE(SMBtconX);
523
524         if (req->wct < 4) {
525                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
526                 END_PROFILE(SMBtconX);
527                 return;
528         }
529
530         passlen = SVAL(req->inbuf,smb_vwv3);
531         tcon_flags = SVAL(req->inbuf,smb_vwv2);
532
533         /* we might have to close an old one */
534         if ((tcon_flags & 0x1) && conn) {
535                 close_cnum(conn,req->vuid);
536         }
537
538         if ((passlen > MAX_PASS_LEN) || (passlen >= smb_buflen(req->inbuf))) {
539                 reply_doserror(req, ERRDOS, ERRbuftoosmall);
540                 END_PROFILE(SMBtconX);
541                 return;
542         }
543
544         if (global_encrypted_passwords_negotiated) {
545                 password = data_blob(smb_buf(req->inbuf),passlen);
546                 if (lp_security() == SEC_SHARE) {
547                         /*
548                          * Security = share always has a pad byte
549                          * after the password.
550                          */
551                         p = smb_buf(req->inbuf) + passlen + 1;
552                 } else {
553                         p = smb_buf(req->inbuf) + passlen;
554                 }
555         } else {
556                 password = data_blob(smb_buf(req->inbuf),passlen+1);
557                 /* Ensure correct termination */
558                 password.data[passlen]=0;
559                 p = smb_buf(req->inbuf) + passlen + 1;
560         }
561
562         ctx = talloc_init("reply_tcon_and_X");
563         if (!ctx) {
564                 data_blob_clear_free(&password);
565                 reply_nterror(req, NT_STATUS_NO_MEMORY);
566                 END_PROFILE(SMBtconX);
567                 return;
568         }
569         p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2, &path, p,
570                              STR_TERMINATE);
571
572         if (path == NULL) {
573                 data_blob_clear_free(&password);
574                 TALLOC_FREE(ctx);
575                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
576                 END_PROFILE(SMBtconX);
577                 return;
578         }
579
580         /*
581          * the service name can be either: \\server\share
582          * or share directly like on the DELL PowerVault 705
583          */
584         if (*path=='\\') {
585                 q = strchr_m(path+2,'\\');
586                 if (!q) {
587                         data_blob_clear_free(&password);
588                         TALLOC_FREE(ctx);
589                         reply_doserror(req, ERRDOS, ERRnosuchshare);
590                         END_PROFILE(SMBtconX);
591                         return;
592                 }
593                 service = q+1;
594         } else {
595                 service = path;
596         }
597
598         p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
599                                 &client_devicetype, p,
600                                 MIN(6,smb_bufrem(req->inbuf, p)), STR_ASCII);
601
602         if (client_devicetype == NULL) {
603                 data_blob_clear_free(&password);
604                 TALLOC_FREE(ctx);
605                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
606                 END_PROFILE(SMBtconX);
607                 return;
608         }
609
610         DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
611
612         conn = make_connection(service, password, client_devicetype,
613                                req->vuid, &nt_status);
614
615         data_blob_clear_free(&password);
616
617         if (!conn) {
618                 TALLOC_FREE(ctx);
619                 reply_nterror(req, nt_status);
620                 END_PROFILE(SMBtconX);
621                 return;
622         }
623
624         if ( IS_IPC(conn) )
625                 server_devicetype = "IPC";
626         else if ( IS_PRINT(conn) )
627                 server_devicetype = "LPT1:";
628         else
629                 server_devicetype = "A:";
630
631         if (Protocol < PROTOCOL_NT1) {
632                 reply_outbuf(req, 2, 0);
633                 if (message_push_string(&req->outbuf, server_devicetype,
634                                         STR_TERMINATE|STR_ASCII) == -1) {
635                         TALLOC_FREE(ctx);
636                         reply_nterror(req, NT_STATUS_NO_MEMORY);
637                         END_PROFILE(SMBtconX);
638                         return;
639                 }
640         } else {
641                 /* NT sets the fstype of IPC$ to the null string */
642                 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
643
644                 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
645                         /* Return permissions. */
646                         uint32 perm1 = 0;
647                         uint32 perm2 = 0;
648
649                         reply_outbuf(req, 7, 0);
650
651                         if (IS_IPC(conn)) {
652                                 perm1 = FILE_ALL_ACCESS;
653                                 perm2 = FILE_ALL_ACCESS;
654                         } else {
655                                 perm1 = CAN_WRITE(conn) ?
656                                                 SHARE_ALL_ACCESS :
657                                                 SHARE_READ_ONLY;
658                         }
659
660                         SIVAL(req->outbuf, smb_vwv3, perm1);
661                         SIVAL(req->outbuf, smb_vwv5, perm2);
662                 } else {
663                         reply_outbuf(req, 3, 0);
664                 }
665
666                 if ((message_push_string(&req->outbuf, server_devicetype,
667                                          STR_TERMINATE|STR_ASCII) == -1)
668                     || (message_push_string(&req->outbuf, fstype,
669                                             STR_TERMINATE) == -1)) {
670                         TALLOC_FREE(ctx);
671                         reply_nterror(req, NT_STATUS_NO_MEMORY);
672                         END_PROFILE(SMBtconX);
673                         return;
674                 }
675
676                 /* what does setting this bit do? It is set by NT4 and
677                    may affect the ability to autorun mounted cdroms */
678                 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
679                       (lp_csc_policy(SNUM(conn)) << 2));
680
681                 init_dfsroot(conn, req->inbuf, req->outbuf);
682         }
683
684
685         DEBUG(3,("tconX service=%s \n",
686                  service));
687
688         /* set the incoming and outgoing tid to the just created one */
689         SSVAL(req->inbuf,smb_tid,conn->cnum);
690         SSVAL(req->outbuf,smb_tid,conn->cnum);
691
692         TALLOC_FREE(ctx);
693         END_PROFILE(SMBtconX);
694
695         chain_reply_new(req);
696         return;
697 }
698
699 /****************************************************************************
700  Reply to an unknown type.
701 ****************************************************************************/
702
703 int reply_unknown(char *inbuf,char *outbuf)
704 {
705         int type;
706         type = CVAL(inbuf,smb_com);
707   
708         DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
709                  smb_fn_name(type), type, type));
710   
711         return(ERROR_DOS(ERRSRV,ERRunknownsmb));
712 }
713
714 void reply_unknown_new(struct smb_request *req, uint8 type)
715 {
716         DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
717                   smb_fn_name(type), type, type));
718         reply_doserror(req, ERRSRV, ERRunknownsmb);
719         return;
720 }
721
722 /****************************************************************************
723  Reply to an ioctl.
724  conn POINTER CAN BE NULL HERE !
725 ****************************************************************************/
726
727 int reply_ioctl(connection_struct *conn,
728                 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
729 {
730         uint16 device     = SVAL(inbuf,smb_vwv1);
731         uint16 function   = SVAL(inbuf,smb_vwv2);
732         uint32 ioctl_code = (device << 16) + function;
733         int replysize, outsize;
734         char *p;
735         START_PROFILE(SMBioctl);
736
737         DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
738
739         switch (ioctl_code) {
740             case IOCTL_QUERY_JOB_INFO:
741                 replysize = 32;
742                 break;
743             default:
744                 END_PROFILE(SMBioctl);
745                 return(ERROR_DOS(ERRSRV,ERRnosupport));
746         }
747
748         outsize = set_message(inbuf,outbuf,8,replysize+1,True);
749         SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
750         SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
751         SSVAL(outbuf,smb_vwv6,52);        /* Offset to data */
752         p = smb_buf(outbuf) + 1;          /* Allow for alignment */
753
754         switch (ioctl_code) {
755                 case IOCTL_QUERY_JOB_INFO:                  
756                 {
757                         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
758                         if (!fsp) {
759                                 END_PROFILE(SMBioctl);
760                                 return(UNIXERROR(ERRDOS,ERRbadfid));
761                         }
762                         SSVAL(p,0,fsp->rap_print_jobid);             /* Job number */
763                         srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p+2,
764                                     global_myname(), 15,
765                                     STR_TERMINATE|STR_ASCII);
766                         if (conn) {
767                                 srvstr_push(outbuf, SVAL(outbuf, smb_flg2),
768                                             p+18, lp_servicename(SNUM(conn)),
769                                             13, STR_TERMINATE|STR_ASCII);
770                         }
771                         break;
772                 }
773         }
774
775         END_PROFILE(SMBioctl);
776         return outsize;
777 }
778
779 /****************************************************************************
780  Strange checkpath NTSTATUS mapping.
781 ****************************************************************************/
782
783 static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
784 {
785         /* Strange DOS error code semantics only for checkpath... */
786         if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
787                 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
788                         /* We need to map to ERRbadpath */
789                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
790                 }
791         }
792         return status;
793 }
794         
795 /****************************************************************************
796  Reply to a checkpath.
797 ****************************************************************************/
798
799 void reply_checkpath(connection_struct *conn, struct smb_request *req)
800 {
801         pstring name;
802         SMB_STRUCT_STAT sbuf;
803         NTSTATUS status;
804
805         START_PROFILE(SMBcheckpath);
806
807         srvstr_get_path((char *)req->inbuf, req->flags2, name,
808                         smb_buf(req->inbuf) + 1, sizeof(name), 0,
809                         STR_TERMINATE, &status);
810         if (!NT_STATUS_IS_OK(status)) {
811                 status = map_checkpath_error((char *)req->inbuf, status);
812                 reply_nterror(req, status);
813                 END_PROFILE(SMBcheckpath);
814                 return;
815         }
816
817         status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, name);
818         if (!NT_STATUS_IS_OK(status)) {
819                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
820                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
821                                         ERRSRV, ERRbadpath);
822                         END_PROFILE(SMBcheckpath);
823                         return;
824                 }
825                 goto path_err;
826         }
827
828         DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->inbuf,smb_vwv0)));
829
830         status = unix_convert(conn, name, False, NULL, &sbuf);
831         if (!NT_STATUS_IS_OK(status)) {
832                 goto path_err;
833         }
834
835         status = check_name(conn, name);
836         if (!NT_STATUS_IS_OK(status)) {
837                 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
838                 goto path_err;
839         }
840
841         if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
842                 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
843                 status = map_nt_error_from_unix(errno);
844                 goto path_err;
845         }
846
847         if (!S_ISDIR(sbuf.st_mode)) {
848                 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
849                                 ERRDOS, ERRbadpath);
850                 END_PROFILE(SMBcheckpath);
851                 return;
852         }
853
854         reply_outbuf(req, 0, 0);
855
856         END_PROFILE(SMBcheckpath);
857         return;
858
859   path_err:
860
861         END_PROFILE(SMBcheckpath);
862
863         /* We special case this - as when a Windows machine
864                 is parsing a path is steps through the components
865                 one at a time - if a component fails it expects
866                 ERRbadpath, not ERRbadfile.
867         */
868         status = map_checkpath_error((char *)req->inbuf, status);
869         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
870                 /*
871                  * Windows returns different error codes if
872                  * the parent directory is valid but not the
873                  * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
874                  * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
875                  * if the path is invalid.
876                  */
877                 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
878                                 ERRDOS, ERRbadpath);
879                 return;
880         }
881
882         reply_nterror(req, status);
883 }
884
885 /****************************************************************************
886  Reply to a getatr.
887 ****************************************************************************/
888
889 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 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
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 = file_fsp(SVAL(inbuf,smb_vwv0));
2839         START_PROFILE(SMBread);
2840
2841         CHECK_FSP(fsp,conn);
2842         if (!CHECK_READ(fsp,inbuf)) {
2843                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2844         }
2845
2846         numtoread = SVAL(inbuf,smb_vwv1);
2847         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2848
2849         outsize = set_message(inbuf,outbuf,5,3,True);
2850         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2851         /*
2852          * The requested read size cannot be greater than max_recv. JRA.
2853          */
2854         if (numtoread > max_recv) {
2855                 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2856 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2857                         (unsigned int)numtoread, (unsigned int)max_recv ));
2858                 numtoread = MIN(numtoread,max_recv);
2859         }
2860
2861         data = smb_buf(outbuf) + 3;
2862   
2863         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2864                 END_PROFILE(SMBread);
2865                 return ERROR_DOS(ERRDOS,ERRlock);
2866         }
2867
2868         if (numtoread > 0)
2869                 nread = read_file(fsp,data,startpos,numtoread);
2870
2871         if (nread < 0) {
2872                 END_PROFILE(SMBread);
2873                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2874         }
2875   
2876         outsize += nread;
2877         SSVAL(outbuf,smb_vwv0,nread);
2878         SSVAL(outbuf,smb_vwv5,nread+3);
2879         SCVAL(smb_buf(outbuf),0,1);
2880         SSVAL(smb_buf(outbuf),1,nread);
2881   
2882         DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2883                 fsp->fnum, (int)numtoread, (int)nread ) );
2884
2885         END_PROFILE(SMBread);
2886         return(outsize);
2887 }
2888
2889 /****************************************************************************
2890  Setup readX header.
2891 ****************************************************************************/
2892
2893 static int setup_readX_header(const uint8 *inbuf, uint8 *outbuf,
2894                               size_t smb_maxcnt)
2895 {
2896         int outsize;
2897         char *data;
2898
2899         outsize = set_message((char *)inbuf, (char *)outbuf,12,smb_maxcnt,
2900                               False);
2901         data = smb_buf(outbuf);
2902
2903         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2904         SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2905         SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2906         SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
2907         SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2908         SCVAL(outbuf,smb_vwv0,0xFF);
2909         /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
2910         _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
2911         return outsize;
2912 }
2913
2914 /****************************************************************************
2915  Reply to a read and X - possibly using sendfile.
2916 ****************************************************************************/
2917
2918 static void send_file_readX(connection_struct *conn, struct smb_request *req,
2919                             files_struct *fsp, SMB_OFF_T startpos,
2920                             size_t smb_maxcnt)
2921 {
2922         SMB_STRUCT_STAT sbuf;
2923         ssize_t nread = -1;
2924
2925         if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
2926                 reply_unixerror(req, ERRDOS, ERRnoaccess);
2927                 return;
2928         }
2929
2930         if (startpos > sbuf.st_size) {
2931                 smb_maxcnt = 0;
2932         } else if (smb_maxcnt > (sbuf.st_size - startpos)) {
2933                 smb_maxcnt = (sbuf.st_size - startpos);
2934         }
2935
2936         if (smb_maxcnt == 0) {
2937                 goto normal_read;
2938         }
2939
2940 #if defined(WITH_SENDFILE)
2941         /*
2942          * We can only use sendfile on a non-chained packet 
2943          * but we can use on a non-oplocked file. tridge proved this
2944          * on a train in Germany :-). JRA.
2945          */
2946
2947         if ((chain_size == 0) && (CVAL(req->inbuf,smb_vwv0) == 0xFF) &&
2948             lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
2949                 uint8 headerbuf[smb_size + 12 * 2];
2950                 DATA_BLOB header;
2951
2952                 /* 
2953                  * Set up the packet header before send. We
2954                  * assume here the sendfile will work (get the
2955                  * correct amount of data).
2956                  */
2957
2958                 header = data_blob_const(headerbuf, sizeof(headerbuf));
2959
2960                 construct_reply_common((char *)req->inbuf, (char *)headerbuf);
2961                 setup_readX_header(req->inbuf, headerbuf, smb_maxcnt);
2962
2963                 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
2964                         /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2965                         if (errno == ENOSYS) {
2966                                 goto normal_read;
2967                         }
2968
2969                         /*
2970                          * Special hack for broken Linux with no working sendfile. If we
2971                          * return EINTR we sent the header but not the rest of the data.
2972                          * Fake this up by doing read/write calls.
2973                          */
2974
2975                         if (errno == EINTR) {
2976                                 /* Ensure we don't do this again. */
2977                                 set_use_sendfile(SNUM(conn), False);
2978                                 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2979                                 nread = fake_sendfile(fsp, startpos,
2980                                                       smb_maxcnt);
2981                                 if (nread == -1) {
2982                                         DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2983                                                 fsp->fsp_name, strerror(errno) ));
2984                                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
2985                                 }
2986                                 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2987                                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2988                                 /* No outbuf here means successful sendfile. */
2989                                 TALLOC_FREE(req->outbuf);
2990                                 return;
2991                         }
2992
2993                         DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2994                                 fsp->fsp_name, strerror(errno) ));
2995                         exit_server_cleanly("send_file_readX sendfile failed");
2996                 }
2997
2998                 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2999                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3000                 /* No outbuf here means successful sendfile. */
3001                 TALLOC_FREE(req->outbuf);
3002                 return;
3003         }
3004
3005 #endif
3006
3007 normal_read:
3008
3009         if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3010                 uint8 headerbuf[smb_size + 2*12];
3011
3012                 construct_reply_common((char *)req->inbuf, (char *)headerbuf);
3013                 setup_readX_header(req->inbuf, headerbuf, smb_maxcnt);
3014
3015                 /* Send out the header. */
3016                 if (write_data(smbd_server_fd(), (char *)headerbuf,
3017                                sizeof(headerbuf)) != sizeof(headerbuf)) {
3018                         DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3019                                 fsp->fsp_name, strerror(errno) ));
3020                         exit_server_cleanly("send_file_readX sendfile failed");
3021                 }
3022                 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3023                 if (nread == -1) {
3024                         DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3025                                 fsp->fsp_name, strerror(errno) ));
3026                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
3027                 }
3028                 TALLOC_FREE(req->outbuf);
3029                 return;
3030         } else {
3031                 reply_outbuf(req, 12, smb_maxcnt);
3032
3033                 nread = read_file(fsp, smb_buf(req->outbuf), startpos,
3034                                   smb_maxcnt);
3035                 if (nread < 0) {
3036                         reply_unixerror(req, ERRDOS, ERRnoaccess);
3037                         return;
3038                 }
3039
3040                 setup_readX_header(req->inbuf, req->outbuf, nread);
3041
3042                 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3043                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3044
3045                 chain_reply_new(req);
3046
3047                 return;
3048         }
3049 }
3050
3051 /****************************************************************************
3052  Reply to a read and X.
3053 ****************************************************************************/
3054
3055 void reply_read_and_X(connection_struct *conn, struct smb_request *req)
3056 {
3057         files_struct *fsp;
3058         SMB_OFF_T startpos;
3059         size_t smb_maxcnt;
3060         BOOL big_readX = False;
3061 #if 0
3062         size_t smb_mincnt = SVAL(req->inbuf,smb_vwv6);
3063 #endif
3064
3065         START_PROFILE(SMBreadX);
3066
3067         if ((req->wct != 10) && (req->wct != 12)) {
3068                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3069                 return;
3070         }
3071
3072         fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
3073         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
3074         smb_maxcnt = SVAL(req->inbuf,smb_vwv5);
3075
3076         /* If it's an IPC, pass off the pipe handler. */
3077         if (IS_IPC(conn)) {
3078                 reply_pipe_read_and_X(req);
3079                 END_PROFILE(SMBreadX);
3080                 return;
3081         }
3082
3083         if (!check_fsp(conn, req, fsp, &current_user)) {
3084                 END_PROFILE(SMBreadX);
3085                 return;
3086         }
3087
3088         if (!CHECK_READ(fsp,req->inbuf)) {
3089                 reply_doserror(req, ERRDOS,ERRbadaccess);
3090                 END_PROFILE(SMBreadX);
3091                 return;
3092         }
3093
3094         if (global_client_caps & CAP_LARGE_READX) {
3095                 size_t upper_size = SVAL(req->inbuf,smb_vwv7);
3096                 smb_maxcnt |= (upper_size<<16);
3097                 if (upper_size > 1) {
3098                         /* Can't do this on a chained packet. */
3099                         if ((CVAL(req->inbuf,smb_vwv0) != 0xFF)) {
3100                                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3101                                 END_PROFILE(SMBreadX);
3102                                 return;
3103                         }
3104                         /* We currently don't do this on signed or sealed data. */
3105                         if (srv_is_signing_active() || srv_encryption_on()) {
3106                                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3107                                 END_PROFILE(SMBreadX);
3108                                 return;
3109                         }
3110                         /* Is there room in the reply for this data ? */
3111                         if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2)))  {
3112                                 reply_nterror(req,
3113                                               NT_STATUS_INVALID_PARAMETER);
3114                                 END_PROFILE(SMBreadX);
3115                                 return;
3116                         }
3117                         big_readX = True;
3118                 }
3119         }
3120
3121         if (req->wct == 12) {
3122 #ifdef LARGE_SMB_OFF_T
3123                 /*
3124                  * This is a large offset (64 bit) read.
3125                  */
3126                 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv10)) << 32);
3127
3128 #else /* !LARGE_SMB_OFF_T */
3129
3130                 /*
3131                  * Ensure we haven't been sent a >32 bit offset.
3132                  */
3133
3134                 if(IVAL(req->inbuf,smb_vwv10) != 0) {
3135                         DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3136                                  "used and we don't support 64 bit offsets.\n",
3137                                  (unsigned int)IVAL(req->inbuf,smb_vwv10) ));
3138                         END_PROFILE(SMBreadX);
3139                         reply_doserror(req, ERRDOS, ERRbadaccess);
3140                         return;
3141                 }
3142
3143 #endif /* LARGE_SMB_OFF_T */
3144
3145         }
3146
3147         if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)smb_maxcnt,
3148                       (SMB_BIG_UINT)startpos, READ_LOCK)) {
3149                 END_PROFILE(SMBreadX);
3150                 reply_doserror(req, ERRDOS, ERRlock);
3151                 return;
3152         }
3153
3154         if (!big_readX
3155             && schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3156                 END_PROFILE(SMBreadX);
3157                 reply_post_legacy(req, -1);
3158                 return;
3159         }
3160
3161         send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3162
3163         END_PROFILE(SMBreadX);
3164         return;
3165 }
3166
3167 /****************************************************************************
3168  Reply to a writebraw (core+ or LANMAN1.0 protocol).
3169 ****************************************************************************/
3170
3171 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3172 {
3173         ssize_t nwritten=0;
3174         ssize_t total_written=0;
3175         size_t numtowrite=0;
3176         size_t tcount;
3177         SMB_OFF_T startpos;
3178         char *data=NULL;
3179         BOOL write_through;
3180         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3181         int outsize = 0;
3182         NTSTATUS status;
3183         START_PROFILE(SMBwritebraw);
3184
3185         if (srv_is_signing_active()) {
3186                 exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
3187         }
3188
3189         CHECK_FSP(fsp,conn);
3190         if (!CHECK_WRITE(fsp)) {
3191                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3192         }
3193   
3194         tcount = IVAL(inbuf,smb_vwv1);
3195         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
3196         write_through = BITSETW(inbuf+smb_vwv7,0);
3197
3198         /* We have to deal with slightly different formats depending
3199                 on whether we are using the core+ or lanman1.0 protocol */
3200
3201         if(Protocol <= PROTOCOL_COREPLUS) {
3202                 numtowrite = SVAL(smb_buf(inbuf),-2);
3203                 data = smb_buf(inbuf);
3204         } else {
3205                 numtowrite = SVAL(inbuf,smb_vwv10);
3206                 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
3207         }
3208
3209         /* force the error type */
3210         SCVAL(inbuf,smb_com,SMBwritec);
3211         SCVAL(outbuf,smb_com,SMBwritec);
3212
3213         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3214                 END_PROFILE(SMBwritebraw);
3215                 return(ERROR_DOS(ERRDOS,ERRlock));
3216         }
3217
3218         if (numtowrite>0)
3219                 nwritten = write_file(fsp,data,startpos,numtowrite);
3220   
3221         DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
3222                 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
3223
3224         if (nwritten < (ssize_t)numtowrite)  {
3225                 END_PROFILE(SMBwritebraw);
3226                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3227         }
3228
3229         total_written = nwritten;
3230
3231         /* Return a message to the redirector to tell it to send more bytes */
3232         SCVAL(outbuf,smb_com,SMBwritebraw);
3233         SSVALS(outbuf,smb_vwv0,-1);
3234         outsize = set_message(inbuf,outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3235         show_msg(outbuf);
3236         if (!send_smb(smbd_server_fd(),outbuf))
3237                 exit_server_cleanly("reply_writebraw: send_smb failed.");
3238   
3239         /* Now read the raw data into the buffer and write it */
3240         if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
3241                 exit_server_cleanly("secondary writebraw failed");
3242         }
3243   
3244         /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
3245         numtowrite = smb_len(inbuf);
3246
3247         /* Set up outbuf to return the correct return */
3248         outsize = set_message(inbuf,outbuf,1,0,True);
3249         SCVAL(outbuf,smb_com,SMBwritec);
3250
3251         if (numtowrite != 0) {
3252
3253                 if (numtowrite > BUFFER_SIZE) {
3254                         DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
3255                                 (unsigned int)numtowrite ));
3256                         exit_server_cleanly("secondary writebraw failed");
3257                 }
3258
3259                 if (tcount > nwritten+numtowrite) {
3260                         DEBUG(3,("Client overestimated the write %d %d %d\n",
3261                                 (int)tcount,(int)nwritten,(int)numtowrite));
3262                 }
3263
3264                 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
3265                         DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
3266                                 strerror(errno) ));
3267                         exit_server_cleanly("secondary writebraw failed");
3268                 }
3269
3270                 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
3271                 if (nwritten == -1) {
3272                         END_PROFILE(SMBwritebraw);
3273                         return(UNIXERROR(ERRHRD,ERRdiskfull));
3274                 }
3275
3276                 if (nwritten < (ssize_t)numtowrite) {
3277                         SCVAL(outbuf,smb_rcls,ERRHRD);
3278                         SSVAL(outbuf,smb_err,ERRdiskfull);      
3279                 }
3280
3281                 if (nwritten > 0)
3282                         total_written += nwritten;
3283         }
3284  
3285         SSVAL(outbuf,smb_vwv0,total_written);
3286
3287         status = sync_file(conn, fsp, write_through);
3288         if (!NT_STATUS_IS_OK(status)) {
3289                 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3290                         fsp->fsp_name, nt_errstr(status) ));
3291                 END_PROFILE(SMBwritebraw);
3292                 return ERROR_NT(status);
3293         }
3294
3295         DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
3296                 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
3297
3298         /* we won't return a status if write through is not selected - this follows what WfWg does */
3299         END_PROFILE(SMBwritebraw);
3300         if (!write_through && total_written==tcount) {
3301
3302 #if RABBIT_PELLET_FIX
3303                 /*
3304                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3305                  * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
3306                  */
3307                 if (!send_keepalive(smbd_server_fd()))
3308                         exit_server_cleanly("reply_writebraw: send of keepalive failed");
3309 #endif
3310                 return(-1);
3311         }
3312
3313         return(outsize);
3314 }
3315
3316 #undef DBGC_CLASS
3317 #define DBGC_CLASS DBGC_LOCKING
3318
3319 /****************************************************************************
3320  Reply to a writeunlock (core+).
3321 ****************************************************************************/
3322
3323 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, 
3324                       int size, int dum_buffsize)
3325 {
3326         ssize_t nwritten = -1;
3327         size_t numtowrite;
3328         SMB_OFF_T startpos;
3329         char *data;
3330         NTSTATUS status = NT_STATUS_OK;
3331         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3332         int outsize = 0;
3333         START_PROFILE(SMBwriteunlock);
3334         
3335         CHECK_FSP(fsp,conn);
3336         if (!CHECK_WRITE(fsp)) {
3337                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3338         }
3339
3340         numtowrite = SVAL(inbuf,smb_vwv1);
3341         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3342         data = smb_buf(inbuf) + 3;
3343   
3344         if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3345                 END_PROFILE(SMBwriteunlock);
3346                 return ERROR_DOS(ERRDOS,ERRlock);
3347         }
3348
3349         /* The special X/Open SMB protocol handling of
3350            zero length writes is *NOT* done for
3351            this call */
3352         if(numtowrite == 0) {
3353                 nwritten = 0;
3354         } else {
3355                 nwritten = write_file(fsp,data,startpos,numtowrite);
3356         }
3357   
3358         status = sync_file(conn, fsp, False /* write through */);
3359         if (!NT_STATUS_IS_OK(status)) {
3360                 END_PROFILE(SMBwriteunlock);
3361                 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3362                         fsp->fsp_name, nt_errstr(status) ));
3363                 return ERROR_NT(status);
3364         }
3365
3366         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3367                 END_PROFILE(SMBwriteunlock);
3368                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3369         }
3370
3371         if (numtowrite) {
3372                 status = do_unlock(smbd_messaging_context(),
3373                                 fsp,
3374                                 (uint32)SVAL(inbuf,smb_pid),
3375                                 (SMB_BIG_UINT)numtowrite, 
3376                                 (SMB_BIG_UINT)startpos,
3377                                 WINDOWS_LOCK);
3378
3379                 if (NT_STATUS_V(status)) {
3380                         END_PROFILE(SMBwriteunlock);
3381                         return ERROR_NT(status);
3382                 }
3383         }
3384         
3385         outsize = set_message(inbuf,outbuf,1,0,True);
3386         
3387         SSVAL(outbuf,smb_vwv0,nwritten);
3388         
3389         DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3390                  fsp->fnum, (int)numtowrite, (int)nwritten));
3391         
3392         END_PROFILE(SMBwriteunlock);
3393         return outsize;
3394 }
3395
3396 #undef DBGC_CLASS
3397 #define DBGC_CLASS DBGC_ALL
3398
3399 /****************************************************************************
3400  Reply to a write.
3401 ****************************************************************************/
3402
3403 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
3404 {
3405         size_t numtowrite;
3406         ssize_t nwritten = -1;
3407         SMB_OFF_T startpos;
3408         char *data;
3409         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3410         int outsize = 0;
3411         NTSTATUS status;
3412         START_PROFILE(SMBwrite);
3413
3414         /* If it's an IPC, pass off the pipe handler. */
3415         if (IS_IPC(conn)) {
3416                 END_PROFILE(SMBwrite);
3417                 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
3418         }
3419
3420         CHECK_FSP(fsp,conn);
3421         if (!CHECK_WRITE(fsp)) {
3422                 END_PROFILE(SMBwrite);
3423                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3424         }
3425
3426         numtowrite = SVAL(inbuf,smb_vwv1);
3427         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3428         data = smb_buf(inbuf) + 3;
3429   
3430         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3431                 END_PROFILE(SMBwrite);
3432                 return ERROR_DOS(ERRDOS,ERRlock);
3433         }
3434
3435         /*
3436          * X/Open SMB protocol says that if smb_vwv1 is
3437          * zero then the file size should be extended or
3438          * truncated to the size given in smb_vwv[2-3].
3439          */
3440
3441         if(numtowrite == 0) {
3442                 /*
3443                  * This is actually an allocate call, and set EOF. JRA.
3444                  */
3445                 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3446                 if (nwritten < 0) {
3447                         END_PROFILE(SMBwrite);
3448                         return ERROR_NT(NT_STATUS_DISK_FULL);
3449                 }
3450                 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3451                 if (nwritten < 0) {
3452                         END_PROFILE(SMBwrite);
3453                         return ERROR_NT(NT_STATUS_DISK_FULL);
3454                 }
3455         } else
3456                 nwritten = write_file(fsp,data,startpos,numtowrite);
3457   
3458         status = sync_file(conn, fsp, False);
3459         if (!NT_STATUS_IS_OK(status)) {
3460                 END_PROFILE(SMBwrite);
3461                 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3462                         fsp->fsp_name, nt_errstr(status) ));
3463                 return ERROR_NT(status);
3464         }
3465
3466         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3467                 END_PROFILE(SMBwrite);
3468                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3469         }
3470
3471         outsize = set_message(inbuf,outbuf,1,0,True);
3472   
3473         SSVAL(outbuf,smb_vwv0,nwritten);
3474
3475         if (nwritten < (ssize_t)numtowrite) {
3476                 SCVAL(outbuf,smb_rcls,ERRHRD);
3477                 SSVAL(outbuf,smb_err,ERRdiskfull);      
3478         }
3479   
3480         DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3481
3482         END_PROFILE(SMBwrite);
3483         return(outsize);
3484 }
3485
3486 /****************************************************************************
3487  Reply to a write and X.
3488 ****************************************************************************/
3489
3490 void reply_write_and_X(connection_struct *conn, struct smb_request *req)
3491 {
3492         files_struct *fsp;
3493         SMB_OFF_T startpos;
3494         size_t numtowrite;
3495         BOOL write_through;
3496         ssize_t nwritten;
3497         unsigned int smb_doff;
3498         unsigned int smblen;
3499         char *data;
3500         BOOL large_writeX;
3501         NTSTATUS status;
3502
3503         START_PROFILE(SMBwriteX);
3504
3505         if ((req->wct != 12) && (req->wct != 14)) {
3506                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3507                 END_PROFILE(SMBwriteX);
3508                 return;
3509         }
3510
3511         numtowrite = SVAL(req->inbuf,smb_vwv10);
3512         smb_doff = SVAL(req->inbuf,smb_vwv11);
3513         smblen = smb_len(req->inbuf);
3514         large_writeX = ((req->wct == 14) && (smblen > 0xFFFF));
3515
3516         /* Deal with possible LARGE_WRITEX */
3517         if (large_writeX) {
3518                 numtowrite |= ((((size_t)SVAL(req->inbuf,smb_vwv9)) & 1 )<<16);
3519         }
3520
3521         if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
3522                 reply_doserror(req, ERRDOS, ERRbadmem);
3523                 END_PROFILE(SMBwriteX);
3524                 return;
3525         }
3526
3527         /* If it's an IPC, pass off the pipe handler. */
3528         if (IS_IPC(conn)) {
3529                 reply_pipe_write_and_X(req);
3530                 END_PROFILE(SMBwriteX);
3531                 return;
3532         }
3533
3534         fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
3535         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
3536         write_through = BITSETW(req->inbuf+smb_vwv7,0);
3537
3538         if (!check_fsp(conn, req, fsp, &current_user)) {
3539                 END_PROFILE(SMBwriteX);
3540                 return;
3541         }
3542
3543         if (!CHECK_WRITE(fsp)) {
3544                 reply_doserror(req, ERRDOS, ERRbadaccess);
3545                 END_PROFILE(SMBwriteX);
3546                 return;
3547         }
3548
3549         data = smb_base(req->inbuf) + smb_doff;
3550
3551         if(req->wct == 14) {
3552 #ifdef LARGE_SMB_OFF_T
3553                 /*
3554                  * This is a large offset (64 bit) write.
3555                  */
3556                 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv12)) << 32);
3557
3558 #else /* !LARGE_SMB_OFF_T */
3559
3560                 /*
3561                  * Ensure we haven't been sent a >32 bit offset.
3562                  */
3563
3564                 if(IVAL(req->inbuf,smb_vwv12) != 0) {
3565                         DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
3566                                  "used and we don't support 64 bit offsets.\n",
3567                                  (unsigned int)IVAL(inbuf,smb_vwv12) ));
3568                         reply_doserror(req, ERRDOS, ERRbadaccess);
3569                         END_PROFILE(SMBwriteX);
3570                         return;
3571                 }
3572
3573 #endif /* LARGE_SMB_OFF_T */
3574         }
3575
3576         if (is_locked(fsp,(uint32)req->smbpid,
3577                       (SMB_BIG_UINT)numtowrite,
3578                       (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3579                 reply_doserror(req, ERRDOS, ERRlock);
3580                 END_PROFILE(SMBwriteX);
3581                 return;
3582         }
3583
3584         /* X/Open SMB protocol says that, unlike SMBwrite
3585         if the length is zero then NO truncation is
3586         done, just a write of zero. To truncate a file,
3587         use SMBwrite. */
3588
3589         if(numtowrite == 0) {
3590                 nwritten = 0;
3591         } else {
3592
3593                 if (schedule_aio_write_and_X(conn, req, fsp, data, startpos,
3594                                              numtowrite)) {
3595                         END_PROFILE(SMBwriteX);
3596                         return;
3597                 }
3598
3599                 nwritten = write_file(fsp,data,startpos,numtowrite);
3600         }
3601   
3602         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3603                 reply_unixerror(req, ERRHRD, ERRdiskfull);
3604                 END_PROFILE(SMBwriteX);
3605                 return;
3606         }
3607
3608         reply_outbuf(req, 6, 0);
3609         SSVAL(req->outbuf,smb_vwv2,nwritten);
3610         if (large_writeX)
3611                 SSVAL(req->outbuf,smb_vwv4,(nwritten>>16)&1);
3612
3613         if (nwritten < (ssize_t)numtowrite) {
3614                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3615                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3616         }
3617
3618         DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
3619                 fsp->fnum, (int)numtowrite, (int)nwritten));
3620
3621         status = sync_file(conn, fsp, write_through);
3622         if (!NT_STATUS_IS_OK(status)) {
3623                 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
3624                         fsp->fsp_name, nt_errstr(status) ));
3625                 reply_nterror(req, status);
3626                 END_PROFILE(SMBwriteX);
3627                 return;
3628         }
3629
3630         END_PROFILE(SMBwriteX);
3631         chain_reply_new(req);
3632         return;
3633 }
3634
3635 /****************************************************************************
3636  Reply to a lseek.
3637 ****************************************************************************/
3638
3639 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3640 {
3641         SMB_OFF_T startpos;
3642         SMB_OFF_T res= -1;
3643         int mode,umode;
3644         int outsize = 0;
3645         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3646         START_PROFILE(SMBlseek);
3647
3648         CHECK_FSP(fsp,conn);
3649
3650         flush_write_cache(fsp, SEEK_FLUSH);
3651
3652         mode = SVAL(inbuf,smb_vwv1) & 3;
3653         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3654         startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
3655
3656         switch (mode) {
3657                 case 0:
3658                         umode = SEEK_SET;
3659                         res = startpos;
3660                         break;
3661                 case 1:
3662                         umode = SEEK_CUR;
3663                         res = fsp->fh->pos + startpos;
3664                         break;
3665                 case 2:
3666                         umode = SEEK_END;
3667                         break;
3668                 default:
3669                         umode = SEEK_SET;
3670                         res = startpos;
3671                         break;
3672         }
3673
3674         if (umode == SEEK_END) {
3675                 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
3676                         if(errno == EINVAL) {
3677                                 SMB_OFF_T current_pos = startpos;
3678                                 SMB_STRUCT_STAT sbuf;
3679
3680                                 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3681                                         END_PROFILE(SMBlseek);
3682                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3683                                 }
3684
3685                                 current_pos += sbuf.st_size;
3686                                 if(current_pos < 0)
3687                                         res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
3688                         }
3689                 }
3690
3691                 if(res == -1) {
3692                         END_PROFILE(SMBlseek);
3693                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3694                 }
3695         }
3696
3697         fsp->fh->pos = res;
3698   
3699         outsize = set_message(inbuf,outbuf,2,0,True);
3700         SIVAL(outbuf,smb_vwv0,res);
3701   
3702         DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3703                 fsp->fnum, (double)startpos, (double)res, mode));
3704
3705         END_PROFILE(SMBlseek);
3706         return(outsize);
3707 }
3708
3709 /****************************************************************************
3710  Reply to a flush.
3711 ****************************************************************************/
3712
3713 void reply_flush(connection_struct *conn, struct smb_request *req)
3714 {
3715         uint16 fnum;
3716         files_struct *fsp;
3717
3718         START_PROFILE(SMBflush);
3719
3720         if (req->wct < 1) {
3721                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3722                 return;
3723         }
3724
3725         fnum = SVAL(req->inbuf,smb_vwv0);
3726         fsp = file_fsp(fnum);
3727
3728         if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp, &current_user)) {
3729                 return;
3730         }
3731         
3732         if (!fsp) {
3733                 file_sync_all(conn);
3734         } else {
3735                 NTSTATUS status = sync_file(conn, fsp, True);
3736                 if (!NT_STATUS_IS_OK(status)) {
3737                         DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
3738                                 fsp->fsp_name, nt_errstr(status) ));
3739                         reply_nterror(req, status);
3740                         END_PROFILE(SMBflush);
3741                         return;
3742                 }
3743         }
3744         
3745         reply_outbuf(req, 0, 0);
3746
3747         DEBUG(3,("flush\n"));
3748         END_PROFILE(SMBflush);
3749         return;
3750 }
3751
3752 /****************************************************************************
3753  Reply to a exit.
3754  conn POINTER CAN BE NULL HERE !
3755 ****************************************************************************/
3756
3757 void reply_exit(connection_struct *conn, struct smb_request *req)
3758 {
3759         START_PROFILE(SMBexit);
3760
3761         file_close_pid(req->smbpid, req->vuid);
3762
3763         reply_outbuf(req, 0, 0);
3764
3765         DEBUG(3,("exit\n"));
3766
3767         END_PROFILE(SMBexit);
3768         return;
3769 }
3770
3771 /****************************************************************************
3772  Reply to a close - has to deal with closing a directory opened by NT SMB's.
3773 ****************************************************************************/
3774
3775 void reply_close(connection_struct *conn, struct smb_request *req)
3776 {
3777         NTSTATUS status = NT_STATUS_OK;
3778         files_struct *fsp = NULL;
3779         START_PROFILE(SMBclose);
3780
3781         if (req->wct < 3) {
3782                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3783                 END_PROFILE(SMBclose);
3784                 return;
3785         }
3786
3787         /* If it's an IPC, pass off to the pipe handler. */
3788         if (IS_IPC(conn)) {
3789                 reply_pipe_close(conn, req);
3790                 END_PROFILE(SMBclose);
3791                 return;
3792         }
3793
3794         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3795
3796         /*
3797          * We can only use CHECK_FSP if we know it's not a directory.
3798          */
3799
3800         if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3801                 reply_doserror(req, ERRDOS, ERRbadfid);
3802                 END_PROFILE(SMBclose);
3803                 return;
3804         }
3805
3806         if(fsp->is_directory) {
3807                 /*
3808                  * Special case - close NT SMB directory handle.
3809                  */
3810                 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
3811                 status = close_file(fsp,NORMAL_CLOSE);
3812         } else {
3813                 /*
3814                  * Close ordinary file.
3815                  */
3816
3817                 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3818                          fsp->fh->fd, fsp->fnum,
3819                          conn->num_files_open));
3820  
3821                 /*
3822                  * Take care of any time sent in the close.
3823                  */
3824
3825                 fsp_set_pending_modtime(fsp, convert_time_t_to_timespec(
3826                                                 srv_make_unix_date3(
3827                                                         req->inbuf+smb_vwv1)));
3828
3829                 /*
3830                  * close_file() returns the unix errno if an error
3831                  * was detected on close - normally this is due to
3832                  * a disk full error. If not then it was probably an I/O error.
3833                  */
3834  
3835                 status = close_file(fsp,NORMAL_CLOSE);
3836         }  
3837
3838         if (!NT_STATUS_IS_OK(status)) {
3839                 reply_nterror(req, status);
3840                 END_PROFILE(SMBclose);
3841                 return;
3842         }
3843
3844         reply_outbuf(req, 0, 0);
3845         END_PROFILE(SMBclose);
3846         return;
3847 }
3848
3849 /****************************************************************************
3850  Reply to a writeclose (Core+ protocol).
3851 ****************************************************************************/
3852
3853 int reply_writeclose(connection_struct *conn,
3854                      char *inbuf,char *outbuf, int size, int dum_buffsize)
3855 {
3856         size_t numtowrite;
3857         ssize_t nwritten = -1;
3858         int outsize = 0;
3859         NTSTATUS close_status = NT_STATUS_OK;
3860         SMB_OFF_T startpos;
3861         char *data;
3862         struct timespec mtime;
3863         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3864         START_PROFILE(SMBwriteclose);
3865
3866         CHECK_FSP(fsp,conn);
3867         if (!CHECK_WRITE(fsp)) {
3868                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3869         }
3870
3871         numtowrite = SVAL(inbuf,smb_vwv1);
3872         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3873         mtime = convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv4));
3874         data = smb_buf(inbuf) + 1;
3875   
3876         if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3877                 END_PROFILE(SMBwriteclose);
3878                 return ERROR_DOS(ERRDOS,ERRlock);
3879         }
3880   
3881         nwritten = write_file(fsp,data,startpos,numtowrite);
3882
3883         set_filetime(conn, fsp->fsp_name, mtime);
3884   
3885         /*
3886          * More insanity. W2K only closes the file if writelen > 0.
3887          * JRA.
3888          */
3889
3890         if (numtowrite) {
3891                 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3892                         fsp->fsp_name ));
3893                 close_status = close_file(fsp,NORMAL_CLOSE);
3894         }
3895
3896         DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3897                  fsp->fnum, (int)numtowrite, (int)nwritten,
3898                  conn->num_files_open));
3899   
3900         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3901                 END_PROFILE(SMBwriteclose);
3902                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3903         }
3904  
3905         if(!NT_STATUS_IS_OK(close_status)) {
3906                 END_PROFILE(SMBwriteclose);
3907                 return ERROR_NT(close_status);
3908         }
3909  
3910         outsize = set_message(inbuf,outbuf,1,0,True);
3911   
3912         SSVAL(outbuf,smb_vwv0,nwritten);
3913         END_PROFILE(SMBwriteclose);
3914         return(outsize);
3915 }
3916
3917 #undef DBGC_CLASS
3918 #define DBGC_CLASS DBGC_LOCKING
3919
3920 /****************************************************************************
3921  Reply to a lock.
3922 ****************************************************************************/
3923
3924 int reply_lock(connection_struct *conn,
3925                char *inbuf,char *outbuf, int length, int dum_buffsize)
3926 {
3927         int outsize = set_message(inbuf,outbuf,0,0,False);
3928         SMB_BIG_UINT count,offset;
3929         NTSTATUS status;
3930         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3931         struct byte_range_lock *br_lck = NULL;
3932
3933         START_PROFILE(SMBlock);
3934
3935         CHECK_FSP(fsp,conn);
3936
3937         release_level_2_oplocks_on_change(fsp);
3938
3939         count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3940         offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3941
3942         DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3943                  fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
3944
3945         br_lck = do_lock(smbd_messaging_context(),
3946                         fsp,
3947                         (uint32)SVAL(inbuf,smb_pid),
3948                         count,
3949                         offset,
3950                         WRITE_LOCK,
3951                         WINDOWS_LOCK,
3952                         False, /* Non-blocking lock. */
3953                         &status,
3954                         NULL);
3955
3956         TALLOC_FREE(br_lck);
3957
3958         if (NT_STATUS_V(status)) {
3959                 END_PROFILE(SMBlock);
3960                 return ERROR_NT(status);
3961         }
3962
3963         END_PROFILE(SMBlock);
3964         return(outsize);
3965 }
3966
3967 /****************************************************************************
3968  Reply to a unlock.
3969 ****************************************************************************/
3970
3971 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, 
3972                  int dum_buffsize)
3973 {
3974         int outsize = set_message(inbuf,outbuf,0,0,False);
3975         SMB_BIG_UINT count,offset;
3976         NTSTATUS status;
3977         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3978         START_PROFILE(SMBunlock);
3979
3980         CHECK_FSP(fsp,conn);
3981         
3982         count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3983         offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3984         
3985         status = do_unlock(smbd_messaging_context(),
3986                         fsp,
3987                         (uint32)SVAL(inbuf,smb_pid),
3988                         count,
3989                         offset,
3990                         WINDOWS_LOCK);
3991
3992         if (NT_STATUS_V(status)) {
3993                 END_PROFILE(SMBunlock);
3994                 return ERROR_NT(status);
3995         }
3996
3997         DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3998                     fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
3999         
4000         END_PROFILE(SMBunlock);
4001         return(outsize);
4002 }
4003
4004 #undef DBGC_CLASS
4005 #define DBGC_CLASS DBGC_ALL
4006
4007 /****************************************************************************
4008  Reply to a tdis.
4009  conn POINTER CAN BE NULL HERE !
4010 ****************************************************************************/
4011
4012 void reply_tdis(connection_struct *conn, struct smb_request *req)
4013 {
4014         START_PROFILE(SMBtdis);
4015
4016         if (!conn) {
4017                 DEBUG(4,("Invalid connection in tdis\n"));
4018                 reply_doserror(req, ERRSRV, ERRinvnid);
4019                 END_PROFILE(SMBtdis);
4020                 return;
4021         }
4022
4023         conn->used = False;
4024
4025         close_cnum(conn,req->vuid);
4026
4027         reply_outbuf(req, 0, 0);
4028         END_PROFILE(SMBtdis);
4029         return;
4030 }
4031
4032 /****************************************************************************
4033  Reply to a echo.
4034  conn POINTER CAN BE NULL HERE !
4035 ****************************************************************************/
4036
4037 void reply_echo(connection_struct *conn, struct smb_request *req)
4038 {
4039         int smb_reverb;
4040         int seq_num;
4041         unsigned int data_len = smb_buflen(req->inbuf);
4042
4043         START_PROFILE(SMBecho);
4044
4045         if (req->wct < 1) {
4046                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4047                 END_PROFILE(SMBecho);
4048                 return;
4049         }
4050
4051         if (data_len > BUFFER_SIZE) {
4052                 DEBUG(0,("reply_echo: data_len too large.\n"));
4053                 reply_nterror(req, NT_STATUS_INSUFFICIENT_RESOURCES);
4054                 END_PROFILE(SMBecho);
4055                 return;
4056         }
4057
4058         smb_reverb = SVAL(req->inbuf,smb_vwv0);
4059
4060         reply_outbuf(req, 1, data_len);
4061
4062         /* copy any incoming data back out */
4063         if (data_len > 0) {
4064                 memcpy(smb_buf(req->outbuf),smb_buf(req->inbuf),data_len);
4065         }
4066
4067         if (smb_reverb > 100) {
4068                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4069                 smb_reverb = 100;
4070         }
4071
4072         for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
4073                 SSVAL(req->outbuf,smb_vwv0,seq_num);
4074
4075                 show_msg((char *)req->outbuf);
4076                 if (!send_smb(smbd_server_fd(),(char *)req->outbuf))
4077                         exit_server_cleanly("reply_echo: send_smb failed.");
4078         }
4079
4080         DEBUG(3,("echo %d times\n", smb_reverb));
4081
4082         TALLOC_FREE(req->outbuf);
4083
4084         smb_echo_count++;
4085
4086         END_PROFILE(SMBecho);
4087         return;
4088 }
4089
4090 /****************************************************************************
4091  Reply to a printopen.
4092 ****************************************************************************/
4093
4094 int reply_printopen(connection_struct *conn, 
4095                     char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4096 {
4097         int outsize = 0;
4098         files_struct *fsp;
4099         NTSTATUS status;
4100         
4101         START_PROFILE(SMBsplopen);
4102         
4103         if (!CAN_PRINT(conn)) {
4104                 END_PROFILE(SMBsplopen);
4105                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4106         }
4107
4108         /* Open for exclusive use, write only. */
4109         status = print_fsp_open(conn, NULL, &fsp);
4110
4111         if (!NT_STATUS_IS_OK(status)) {
4112                 END_PROFILE(SMBsplopen);
4113                 return(ERROR_NT(status));
4114         }
4115
4116         outsize = set_message(inbuf,outbuf,1,0,True);
4117         SSVAL(outbuf,smb_vwv0,fsp->fnum);
4118   
4119         DEBUG(3,("openprint fd=%d fnum=%d\n",
4120                  fsp->fh->fd, fsp->fnum));
4121
4122         END_PROFILE(SMBsplopen);
4123         return(outsize);
4124 }
4125
4126 /****************************************************************************
4127  Reply to a printclose.
4128 ****************************************************************************/
4129
4130 int reply_printclose(connection_struct *conn,
4131                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4132 {
4133         int outsize = set_message(inbuf,outbuf,0,0,False);
4134         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
4135         NTSTATUS status;
4136         START_PROFILE(SMBsplclose);
4137
4138         CHECK_FSP(fsp,conn);
4139
4140         if (!CAN_PRINT(conn)) {
4141                 END_PROFILE(SMBsplclose);
4142                 return ERROR_NT(NT_STATUS_DOS(ERRSRV, ERRerror));
4143         }
4144   
4145         DEBUG(3,("printclose fd=%d fnum=%d\n",
4146                  fsp->fh->fd,fsp->fnum));
4147   
4148         status = close_file(fsp,NORMAL_CLOSE);
4149
4150         if(!NT_STATUS_IS_OK(status)) {
4151                 END_PROFILE(SMBsplclose);
4152                 return ERROR_NT(status);
4153         }
4154
4155         END_PROFILE(SMBsplclose);
4156         return(outsize);
4157 }
4158
4159 /****************************************************************************
4160  Reply to a printqueue.
4161 ****************************************************************************/
4162
4163 int reply_printqueue(connection_struct *conn,
4164                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4165 {
4166         int outsize = set_message(inbuf,outbuf,2,3,True);
4167         int max_count = SVAL(inbuf,smb_vwv0);
4168         int start_index = SVAL(inbuf,smb_vwv1);
4169         START_PROFILE(SMBsplretq);
4170
4171         /* we used to allow the client to get the cnum wrong, but that
4172            is really quite gross and only worked when there was only
4173            one printer - I think we should now only accept it if they
4174            get it right (tridge) */
4175         if (!CAN_PRINT(conn)) {
4176                 END_PROFILE(SMBsplretq);
4177                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4178         }
4179
4180         SSVAL(outbuf,smb_vwv0,0);
4181         SSVAL(outbuf,smb_vwv1,0);
4182         SCVAL(smb_buf(outbuf),0,1);
4183         SSVAL(smb_buf(outbuf),1,0);
4184   
4185         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
4186                  start_index, max_count));
4187
4188         {
4189                 print_queue_struct *queue = NULL;
4190                 print_status_struct status;
4191                 char *p = smb_buf(outbuf) + 3;
4192                 int count = print_queue_status(SNUM(conn), &queue, &status);
4193                 int num_to_get = ABS(max_count);
4194                 int first = (max_count>0?start_index:start_index+max_count+1);
4195                 int i;
4196
4197                 if (first >= count)
4198                         num_to_get = 0;
4199                 else
4200                         num_to_get = MIN(num_to_get,count-first);
4201     
4202
4203                 for (i=first;i<first+num_to_get;i++) {
4204                         srv_put_dos_date2(p,0,queue[i].time);
4205                         SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
4206                         SSVAL(p,5, queue[i].job);
4207                         SIVAL(p,7,queue[i].size);
4208                         SCVAL(p,11,0);
4209                         srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p+12,
4210                                     queue[i].fs_user, 16, STR_ASCII);
4211                         p += 28;
4212                 }
4213
4214                 if (count > 0) {
4215                         outsize = set_message(inbuf,outbuf,2,28*count+3,False); 
4216                         SSVAL(outbuf,smb_vwv0,count);
4217                         SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
4218                         SCVAL(smb_buf(outbuf),0,1);
4219                         SSVAL(smb_buf(outbuf),1,28*count);
4220                 }
4221
4222                 SAFE_FREE(queue);
4223           
4224                 DEBUG(3,("%d entries returned in queue\n",count));
4225         }
4226   
4227         END_PROFILE(SMBsplretq);
4228         return(outsize);
4229 }
4230
4231 /****************************************************************************
4232  Reply to a printwrite.
4233 ****************************************************************************/
4234
4235 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4236 {
4237         int numtowrite;
4238         int outsize = set_message(inbuf,outbuf,0,0,False);
4239         char *data;
4240         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
4241
4242         START_PROFILE(SMBsplwr);
4243   
4244         if (!CAN_PRINT(conn)) {
4245                 END_PROFILE(SMBsplwr);
4246                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4247         }
4248
4249         CHECK_FSP(fsp,conn);
4250         if (!CHECK_WRITE(fsp)) {
4251                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
4252         }
4253
4254         numtowrite = SVAL(smb_buf(inbuf),1);
4255         data = smb_buf(inbuf) + 3;
4256   
4257         if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
4258                 END_PROFILE(SMBsplwr);
4259                 return(UNIXERROR(ERRHRD,ERRdiskfull));
4260         }
4261
4262         DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
4263   
4264         END_PROFILE(SMBsplwr);
4265         return(outsize);
4266 }
4267
4268 /****************************************************************************
4269  Reply to a mkdir.
4270 ****************************************************************************/
4271
4272 void reply_mkdir(connection_struct *conn, struct smb_request *req)
4273 {
4274         pstring directory;
4275         NTSTATUS status;
4276         SMB_STRUCT_STAT sbuf;
4277
4278         START_PROFILE(SMBmkdir);
4279  
4280         srvstr_get_path((char *)req->inbuf, req->flags2, directory,
4281                         smb_buf(req->inbuf) + 1, sizeof(directory), 0,
4282                         STR_TERMINATE, &status);
4283         if (!NT_STATUS_IS_OK(status)) {
4284                 reply_nterror(req, status);
4285                 END_PROFILE(SMBmkdir);
4286                 return;
4287         }
4288
4289         status = resolve_dfspath(conn,
4290                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
4291                                  directory);
4292         if (!NT_STATUS_IS_OK(status)) {
4293                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4294                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
4295                                         ERRSRV, ERRbadpath);
4296                         END_PROFILE(SMBmkdir);
4297                         return;
4298                 }
4299                 reply_nterror(req, status);
4300                 END_PROFILE(SMBmkdir);
4301                 return;
4302         }
4303
4304         status = unix_convert(conn, directory, False, NULL, &sbuf);
4305         if (!NT_STATUS_IS_OK(status)) {
4306                 reply_nterror(req, status);
4307                 END_PROFILE(SMBmkdir);
4308                 return;
4309         }
4310
4311         status = check_name(conn, directory);
4312         if (!NT_STATUS_IS_OK(status)) {
4313                 reply_nterror(req, status);
4314                 END_PROFILE(SMBmkdir);
4315                 return;
4316         }
4317   
4318         status = create_directory(conn, directory);
4319
4320         DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
4321
4322         if (!NT_STATUS_IS_OK(status)) {
4323
4324                 if (!use_nt_status()
4325                     && NT_STATUS_EQUAL(status,
4326                                        NT_STATUS_OBJECT_NAME_COLLISION)) {
4327                         /*
4328                          * Yes, in the DOS error code case we get a
4329                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
4330                          * samba4 torture test.
4331                          */
4332                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
4333                 }
4334
4335                 reply_nterror(req, status);
4336                 END_PROFILE(SMBmkdir);
4337                 return;
4338         }
4339
4340         reply_outbuf(req, 0, 0);
4341
4342         DEBUG( 3, ( "mkdir %s\n", directory ) );
4343
4344         END_PROFILE(SMBmkdir);
4345         return;
4346 }
4347
4348 /****************************************************************************
4349  Static function used by reply_rmdir to delete an entire directory
4350  tree recursively. Return True on ok, False on fail.
4351 ****************************************************************************/
4352
4353 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
4354 {
4355         const char *dname = NULL;
4356         BOOL ret = True;
4357         long offset = 0;
4358         struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
4359
4360         if(dir_hnd == NULL)
4361                 return False;
4362
4363         while((dname = ReadDirName(dir_hnd, &offset))) {
4364                 pstring fullname;
4365                 SMB_STRUCT_STAT st;
4366
4367                 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4368                         continue;
4369
4370                 if (!is_visible_file(conn, directory, dname, &st, False))
4371                         continue;
4372
4373                 /* Construct the full name. */
4374                 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
4375                         errno = ENOMEM;
4376                         ret = False;
4377                         break;
4378                 }
4379
4380                 pstrcpy(fullname, directory);
4381                 pstrcat(fullname, "/");
4382                 pstrcat(fullname, dname);
4383
4384                 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
4385                         ret = False;
4386                         break;
4387                 }
4388
4389                 if(st.st_mode & S_IFDIR) {
4390                         if(!recursive_rmdir(conn, fullname)) {
4391                                 ret = False;
4392                                 break;
4393                         }
4394                         if(SMB_VFS_RMDIR(conn,fullname) != 0) {
4395                                 ret = False;
4396                                 break;
4397                         }
4398                 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
4399                         ret = False;
4400                         break;
4401                 }
4402         }
4403         CloseDir(dir_hnd);
4404         return ret;
4405 }
4406
4407 /****************************************************************************
4408  The internals of the rmdir code - called elsewhere.
4409 ****************************************************************************/
4410
4411 NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
4412 {
4413         int ret;
4414         SMB_STRUCT_STAT st;
4415
4416         /* Might be a symlink. */
4417         if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
4418                 return map_nt_error_from_unix(errno);
4419         }
4420
4421         if (S_ISLNK(st.st_mode)) {
4422                 /* Is what it points to a directory ? */
4423                 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
4424                         return map_nt_error_from_unix(errno);
4425                 }
4426                 if (!(S_ISDIR(st.st_mode))) {
4427                         return NT_STATUS_NOT_A_DIRECTORY;
4428                 }
4429                 ret = SMB_VFS_UNLINK(conn,directory);
4430         } else {
4431                 ret = SMB_VFS_RMDIR(conn,directory);
4432         }
4433         if (ret == 0) {
4434                 notify_fname(conn, NOTIFY_ACTION_REMOVED,
4435                              FILE_NOTIFY_CHANGE_DIR_NAME,
4436                              directory);
4437                 return NT_STATUS_OK;
4438         }
4439
4440         if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
4441                 /* 
4442                  * Check to see if the only thing in this directory are
4443                  * vetoed files/directories. If so then delete them and
4444                  * retry. If we fail to delete any of them (and we *don't*
4445                  * do a recursive delete) then fail the rmdir.
4446                  */
4447                 const char *dname;
4448                 long dirpos = 0;
4449                 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
4450
4451                 if(dir_hnd == NULL) {
4452                         errno = ENOTEMPTY;
4453                         goto err;
4454                 }
4455
4456                 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4457                         if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4458                                 continue;
4459                         if (!is_visible_file(conn, directory, dname, &st, False))
4460                                 continue;
4461                         if(!IS_VETO_PATH(conn, dname)) {
4462                                 CloseDir(dir_hnd);
4463                                 errno = ENOTEMPTY;
4464                                 goto err;
4465                         }
4466                 }
4467
4468                 /* We only have veto files/directories. Recursive delete. */
4469
4470                 RewindDir(dir_hnd,&dirpos);
4471                 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4472                         pstring fullname;
4473
4474                         if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4475                                 continue;
4476                         if (!is_visible_file(conn, directory, dname, &st, False))
4477                                 continue;
4478
4479                         /* Construct the full name. */
4480                         if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
4481                                 errno = ENOMEM;
4482                                 break;
4483                         }
4484
4485                         pstrcpy(fullname, directory);
4486                         pstrcat(fullname, "/");
4487                         pstrcat(fullname, dname);
4488                    
4489                         if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
4490                                 break;
4491                         if(st.st_mode & S_IFDIR) {
4492                                 if(lp_recursive_veto_delete(SNUM(conn))) {
4493                                         if(!recursive_rmdir(conn, fullname))
4494                                                 break;
4495                                 }
4496                                 if(SMB_VFS_RMDIR(conn,fullname) != 0)
4497                                         break;
4498                         } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
4499                                 break;
4500                 }
4501                 CloseDir(dir_hnd);
4502                 /* Retry the rmdir */
4503                 ret = SMB_VFS_RMDIR(conn,directory);
4504         }
4505
4506   err:
4507
4508         if (ret != 0) {
4509                 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
4510                          "%s\n", directory,strerror(errno)));
4511                 return map_nt_error_from_unix(errno);
4512         }
4513
4514         notify_fname(conn, NOTIFY_ACTION_REMOVED,
4515                      FILE_NOTIFY_CHANGE_DIR_NAME,
4516                      directory);
4517
4518         return NT_STATUS_OK;
4519 }
4520
4521 /****************************************************************************
4522  Reply to a rmdir.
4523 ****************************************************************************/
4524
4525 void reply_rmdir(connection_struct *conn, struct smb_request *req)
4526 {
4527         pstring directory;
4528         SMB_STRUCT_STAT sbuf;
4529         NTSTATUS status;
4530         START_PROFILE(SMBrmdir);
4531
4532         srvstr_get_path((char *)req->inbuf, req->flags2, directory,
4533                         smb_buf(req->inbuf) + 1, sizeof(directory), 0,
4534                         STR_TERMINATE, &status);
4535         if (!NT_STATUS_IS_OK(status)) {
4536                 reply_nterror(req, status);
4537                 END_PROFILE(SMBrmdir);
4538                 return;
4539         }
4540
4541         status = resolve_dfspath(conn,
4542                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
4543                                  directory);
4544         if (!NT_STATUS_IS_OK(status)) {
4545                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4546                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
4547                                         ERRSRV, ERRbadpath);
4548                         END_PROFILE(SMBrmdir);
4549                         return;
4550                 }
4551                 reply_nterror(req, status);
4552                 END_PROFILE(SMBrmdir);
4553                 return;
4554         }
4555
4556         status = unix_convert(conn, directory, False, NULL, &sbuf);
4557         if (!NT_STATUS_IS_OK(status)) {
4558                 reply_nterror(req, status);
4559                 END_PROFILE(SMBrmdir);
4560                 return;
4561         }
4562   
4563         status = check_name(conn, directory);
4564         if (!NT_STATUS_IS_OK(status)) {
4565                 reply_nterror(req, status);
4566                 END_PROFILE(SMBrmdir);
4567                 return;
4568         }
4569
4570         dptr_closepath(directory, req->smbpid);
4571         status = rmdir_internals(conn, directory);
4572         if (!NT_STATUS_IS_OK(status)) {
4573                 reply_nterror(req, status);
4574                 END_PROFILE(SMBrmdir);
4575                 return;
4576         }
4577  
4578         reply_outbuf(req, 0, 0);
4579   
4580         DEBUG( 3, ( "rmdir %s\n", directory ) );
4581   
4582         END_PROFILE(SMBrmdir);
4583         return;
4584 }
4585
4586 /*******************************************************************
4587  Resolve wildcards in a filename rename.
4588  Note that name is in UNIX charset and thus potentially can be more
4589  than fstring buffer (255 bytes) especially in default UTF-8 case.
4590  Therefore, we use pstring inside and all calls should ensure that
4591  name2 is at least pstring-long (they do already)
4592 ********************************************************************/
4593
4594 static BOOL resolve_wildcards(const char *name1, char *name2)
4595 {
4596         pstring root1,root2;
4597         pstring ext1,ext2;
4598         char *p,*p2, *pname1, *pname2;
4599         int available_space, actual_space;
4600         
4601         pname1 = strrchr_m(name1,'/');
4602         pname2 = strrchr_m(name2,'/');
4603
4604         if (!pname1 || !pname2)
4605                 return(False);
4606   
4607         pstrcpy(root1,pname1);
4608         pstrcpy(root2,pname2);
4609         p = strrchr_m(root1,'.');
4610         if (p) {
4611                 *p = 0;
4612                 pstrcpy(ext1,p+1);
4613         } else {
4614                 pstrcpy(ext1,"");    
4615         }
4616         p = strrchr_m(root2,'.');
4617         if (p) {
4618                 *p = 0;
4619                 pstrcpy(ext2,p+1);
4620         } else {
4621                 pstrcpy(ext2,"");    
4622         }
4623
4624         p = root1;
4625         p2 = root2;
4626         while (*p2) {
4627                 if (*p2 == '?') {
4628                         *p2 = *p;
4629                         p2++;
4630                 } else if (*p2 == '*') {
4631                         pstrcpy(p2, p);
4632                         break;
4633                 } else {
4634                         p2++;
4635                 }
4636                 if (*p)
4637                         p++;
4638         }
4639
4640         p = ext1;
4641         p2 = ext2;
4642         while (*p2) {
4643                 if (*p2 == '?') {
4644                         *p2 = *p;
4645                         p2++;
4646                 } else if (*p2 == '*') {
4647                         pstrcpy(p2, p);
4648                         break;
4649                 } else {
4650                         p2++;
4651                 }
4652                 if (*p)
4653                         p++;
4654         }
4655
4656         available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
4657         
4658         if (ext2[0]) {
4659                 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
4660                 if (actual_space >= available_space - 1) {
4661                         DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
4662                                 actual_space - available_space));
4663                 }
4664         } else {
4665                 pstrcpy_base(pname2, root2, name2);
4666         }
4667
4668         return(True);
4669 }
4670
4671 /****************************************************************************
4672  Ensure open files have their names updated. Updated to notify other smbd's
4673  asynchronously.
4674 ****************************************************************************/
4675
4676 static void rename_open_files(connection_struct *conn,
4677                               struct share_mode_lock *lck,
4678                               const char *newname)
4679 {
4680         files_struct *fsp;
4681         BOOL did_rename = False;
4682
4683         for(fsp = file_find_di_first(lck->id); fsp;
4684             fsp = file_find_di_next(fsp)) {
4685                 /* fsp_name is a relative path under the fsp. To change this for other
4686                    sharepaths we need to manipulate relative paths. */
4687                 /* TODO - create the absolute path and manipulate the newname
4688                    relative to the sharepath. */
4689                 if (fsp->conn != conn) {
4690                         continue;
4691                 }
4692                 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
4693                           fsp->fnum, file_id_static_string(&fsp->file_id),
4694                         fsp->fsp_name, newname ));
4695                 string_set(&fsp->fsp_name, newname);
4696                 did_rename = True;
4697         }
4698
4699         if (!did_rename) {
4700                 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
4701                           file_id_static_string(&lck->id), newname ));
4702         }
4703
4704         /* Send messages to all smbd's (not ourself) that the name has changed. */
4705         rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
4706                               newname);
4707 }
4708
4709 /****************************************************************************
4710  We need to check if the source path is a parent directory of the destination
4711  (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
4712  refuse the rename with a sharing violation. Under UNIX the above call can
4713  *succeed* if /foo/bar/baz is a symlink to another area in the share. We
4714  probably need to check that the client is a Windows one before disallowing
4715  this as a UNIX client (one with UNIX extensions) can know the source is a
4716  symlink and make this decision intelligently. Found by an excellent bug
4717  report from <AndyLiebman@aol.com>.
4718 ****************************************************************************/
4719
4720 static BOOL rename_path_prefix_equal(const char *src, const char *dest)
4721 {
4722         const char *psrc = src;
4723         const char *pdst = dest;
4724         size_t slen;
4725
4726         if (psrc[0] == '.' && psrc[1] == '/') {
4727                 psrc += 2;
4728         }
4729         if (pdst[0] == '.' && pdst[1] == '/') {
4730                 pdst += 2;
4731         }
4732         if ((slen = strlen(psrc)) > strlen(pdst)) {
4733                 return False;
4734         }
4735         return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
4736 }
4737
4738 /*
4739  * Do the notify calls from a rename
4740  */
4741
4742 static void notify_rename(connection_struct *conn, BOOL is_dir,
4743                           const char *oldpath, const char *newpath)
4744 {
4745         char *olddir, *newdir;
4746         const char *oldname, *newname;
4747         uint32 mask;
4748
4749         mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
4750                 : FILE_NOTIFY_CHANGE_FILE_NAME;
4751
4752         if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
4753             || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
4754                 TALLOC_FREE(olddir);
4755                 return;
4756         }
4757
4758         if (strcmp(olddir, newdir) == 0) {
4759                 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
4760                 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
4761         }
4762         else {
4763                 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
4764                 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
4765         }
4766         TALLOC_FREE(olddir);
4767         TALLOC_FREE(newdir);
4768
4769         /* this is a strange one. w2k3 gives an additional event for
4770            CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
4771            files, but not directories */
4772         if (!is_dir) {
4773                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
4774                              FILE_NOTIFY_CHANGE_ATTRIBUTES
4775                              |FILE_NOTIFY_CHANGE_CREATION,
4776                              newpath);
4777         }
4778 }
4779
4780 /****************************************************************************
4781  Rename an open file - given an fsp.
4782 ****************************************************************************/
4783
4784 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstring newname, uint32 attrs, BOOL replace_if_exists)
4785 {
4786         SMB_STRUCT_STAT sbuf, sbuf1;
4787         pstring newname_last_component;
4788         NTSTATUS status = NT_STATUS_OK;
4789         struct share_mode_lock *lck = NULL;
4790         BOOL dst_exists;
4791
4792         ZERO_STRUCT(sbuf);
4793
4794         status = unix_convert(conn, newname, False, newname_last_component, &sbuf);
4795
4796         /* If an error we expect this to be NT_STATUS_OBJECT_PATH_NOT_FOUND */
4797
4798         if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND, status)) {
4799                 return status;
4800         }
4801
4802         status = check_name(conn, newname);
4803         if (!NT_STATUS_IS_OK(status)) {
4804                 return status;
4805         }
4806   
4807         /* Ensure newname contains a '/' */
4808         if(strrchr_m(newname,'/') == 0) {
4809                 pstring tmpstr;
4810                 
4811                 pstrcpy(tmpstr, "./");
4812                 pstrcat(tmpstr, newname);
4813                 pstrcpy(newname, tmpstr);
4814         }
4815
4816         /*
4817          * Check for special case with case preserving and not
4818          * case sensitive. If the old last component differs from the original
4819          * last component only by case, then we should allow
4820          * the rename (user is trying to change the case of the
4821          * filename).
4822          */
4823
4824         if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
4825                         strequal(newname, fsp->fsp_name)) {
4826                 char *p;
4827                 pstring newname_modified_last_component;
4828
4829                 /*
4830                  * Get the last component of the modified name.
4831                  * Note that we guarantee that newname contains a '/'
4832                  * character above.
4833                  */
4834                 p = strrchr_m(newname,'/');
4835                 pstrcpy(newname_modified_last_component,p+1);
4836                         
4837                 if(strcsequal(newname_modified_last_component, 
4838                               newname_last_component) == False) {
4839                         /*
4840                          * Replace the modified last component with
4841                          * the original.
4842                          */
4843                         pstrcpy(p+1, newname_last_component);
4844                 }
4845         }
4846
4847         /*
4848          * If the src and dest names are identical - including case,
4849          * don't do the rename, just return success.
4850          */
4851
4852         if (strcsequal(fsp->fsp_name, newname)) {
4853                 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4854                         newname));
4855                 return NT_STATUS_OK;
4856         }
4857
4858         /*
4859          * Have vfs_object_exist also fill sbuf1
4860          */
4861         dst_exists = vfs_object_exist(conn, newname, &sbuf1);
4862
4863         if(!replace_if_exists && dst_exists) {
4864                 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4865                         fsp->fsp_name,newname));
4866                 return NT_STATUS_OBJECT_NAME_COLLISION;
4867         }
4868
4869         if (dst_exists) {
4870                 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
4871                 files_struct *dst_fsp = file_find_di_first(fileid);
4872                 if (dst_fsp) {
4873                         DEBUG(3, ("rename_internals_fsp: Target file open\n"));
4874                         return NT_STATUS_ACCESS_DENIED;
4875                 }
4876         }
4877
4878         /* Ensure we have a valid stat struct for the source. */
4879         if (fsp->fh->fd != -1) {
4880                 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) == -1) {
4881                         return map_nt_error_from_unix(errno);
4882                 }
4883         } else {
4884                 if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
4885                         return map_nt_error_from_unix(errno);
4886                 }
4887         }
4888
4889         status = can_rename(conn, fsp, attrs, &sbuf);
4890
4891         if (!NT_STATUS_IS_OK(status)) {
4892                 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4893                         nt_errstr(status), fsp->fsp_name,newname));
4894                 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
4895                         status = NT_STATUS_ACCESS_DENIED;
4896                 return status;
4897         }
4898
4899         if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
4900                 return NT_STATUS_ACCESS_DENIED;
4901         }
4902
4903         lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
4904
4905         /*
4906          * We have the file open ourselves, so not being able to get the
4907          * corresponding share mode lock is a fatal error.
4908          */
4909
4910         SMB_ASSERT(lck != NULL);
4911
4912         if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
4913                 uint32 create_options = fsp->fh->private_options;
4914
4915                 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4916                         fsp->fsp_name,newname));
4917
4918                 rename_open_files(conn, lck, newname);
4919
4920                 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
4921
4922                 /*
4923                  * A rename acts as a new file create w.r.t. allowing an initial delete
4924                  * on close, probably because in Windows there is a new handle to the
4925                  * new file. If initial delete on close was requested but not
4926                  * originally set, we need to set it here. This is probably not 100% correct,
4927                  * but will work for the CIFSFS client which in non-posix mode
4928                  * depends on these semantics. JRA.
4929                  */
4930
4931                 set_allow_initial_delete_on_close(lck, fsp, True);
4932
4933                 if (create_options & FILE_DELETE_ON_CLOSE) {
4934                         status = can_set_delete_on_close(fsp, True, 0);
4935
4936                         if (NT_STATUS_IS_OK(status)) {
4937                                 /* Note that here we set the *inital* delete on close flag,
4938                                  * not the regular one. The magic gets handled in close. */
4939                                 fsp->initial_delete_on_close = True;
4940                         }
4941                 }
4942                 TALLOC_FREE(lck);
4943                 return NT_STATUS_OK;    
4944         }
4945
4946         TALLOC_FREE(lck);
4947
4948         if (errno == ENOTDIR || errno == EISDIR) {
4949                 status = NT_STATUS_OBJECT_NAME_COLLISION;
4950         } else {
4951                 status = map_nt_error_from_unix(errno);
4952         }
4953                 
4954         DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4955                 nt_errstr(status), fsp->fsp_name,newname));
4956
4957         return status;
4958 }
4959
4960 /****************************************************************************
4961  The guts of the rename command, split out so it may be called by the NT SMB
4962  code. 
4963 ****************************************************************************/
4964
4965 NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
4966                                 pstring name,
4967                                 pstring newname,
4968                                 uint32 attrs,
4969                                 BOOL replace_if_exists,
4970                                 BOOL src_has_wild,
4971                                 BOOL dest_has_wild)
4972 {
4973         pstring directory;
4974         pstring mask;
4975         pstring last_component_src;
4976         pstring last_component_dest;
4977         char *p;
4978         int count=0;
4979         NTSTATUS status = NT_STATUS_OK;
4980         SMB_STRUCT_STAT sbuf1, sbuf2;
4981         struct smb_Dir *dir_hnd = NULL;
4982         const char *dname;
4983         long offset = 0;
4984         pstring destname;
4985
4986         *directory = *mask = 0;
4987
4988         ZERO_STRUCT(sbuf1);
4989         ZERO_STRUCT(sbuf2);
4990
4991         status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1);
4992         if (!NT_STATUS_IS_OK(status)) {
4993                 return status;
4994         }
4995
4996         status = unix_convert(conn, newname, dest_has_wild, last_component_dest, &sbuf2);
4997         if (!NT_STATUS_IS_OK(status)) {
4998                 return status;
4999         }
5000
5001         /*
5002          * Split the old name into directory and last component
5003          * strings. Note that unix_convert may have stripped off a 
5004          * leading ./ from both name and newname if the rename is 
5005          * at the root of the share. We need to make sure either both
5006          * name and newname contain a / character or neither of them do
5007          * as this is checked in resolve_wildcards().
5008          */
5009
5010         p = strrchr_m(name,'/');
5011         if (!p) {
5012                 pstrcpy(directory,".");
5013                 pstrcpy(mask,name);
5014         } else {
5015                 *p = 0;
5016                 pstrcpy(directory,name);
5017                 pstrcpy(mask,p+1);
5018                 *p = '/'; /* Replace needed for exceptional test below. */
5019         }
5020
5021         /*
5022          * We should only check the mangled cache
5023          * here if unix_convert failed. This means
5024          * that the path in 'mask' doesn't exist
5025          * on the file system and so we need to look
5026          * for a possible mangle. This patch from
5027          * Tine Smukavec <valentin.smukavec@hermes.si>.
5028          */
5029
5030         if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5031                 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
5032         }
5033
5034         if (!src_has_wild) {
5035                 files_struct *fsp;
5036
5037                 /*
5038                  * No wildcards - just process the one file.
5039                  */
5040                 BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
5041
5042                 /* Add a terminating '/' to the directory name. */
5043                 pstrcat(directory,"/");
5044                 pstrcat(directory,mask);
5045                 
5046                 /* Ensure newname contains a '/' also */
5047                 if(strrchr_m(newname,'/') == 0) {
5048                         pstring tmpstr;
5049                         
5050                         pstrcpy(tmpstr, "./");
5051                         pstrcat(tmpstr, newname);
5052                         pstrcpy(newname, tmpstr);
5053                 }
5054                 
5055                 DEBUG(3, ("rename_internals: case_sensitive = %d, "
5056                           "case_preserve = %d, short case preserve = %d, "
5057                           "directory = %s, newname = %s, "
5058                           "last_component_dest = %s, is_8_3 = %d\n", 
5059                           conn->case_sensitive, conn->case_preserve,
5060                           conn->short_case_preserve, directory, 
5061                           newname, last_component_dest, is_short_name));
5062
5063                 /* The dest name still may have wildcards. */
5064                 if (dest_has_wild) {
5065                         if (!resolve_wildcards(directory,newname)) {
5066                                 DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n", 
5067                                           directory,newname));
5068                                 return NT_STATUS_NO_MEMORY;
5069                         }
5070                 }
5071                                 
5072                 ZERO_STRUCT(sbuf1);
5073                 SMB_VFS_STAT(conn, directory, &sbuf1);
5074
5075                 status = S_ISDIR(sbuf1.st_mode) ?
5076                         open_directory(conn, req, directory, &sbuf1,
5077                                        DELETE_ACCESS,
5078                                        FILE_SHARE_READ|FILE_SHARE_WRITE,
5079                                        FILE_OPEN, 0, 0, NULL,
5080                                        &fsp)
5081                         : open_file_ntcreate(conn, req, directory, &sbuf1,
5082                                              DELETE_ACCESS,
5083                                              FILE_SHARE_READ|FILE_SHARE_WRITE,
5084                                              FILE_OPEN, 0, 0, 0, NULL,
5085                                              &fsp);
5086
5087                 if (!NT_STATUS_IS_OK(status)) {
5088                         DEBUG(3, ("Could not open rename source %s: %s\n",
5089                                   directory, nt_errstr(status)));
5090                         return status;
5091                 }
5092
5093                 status = rename_internals_fsp(conn, fsp, newname, attrs,
5094                                               replace_if_exists);
5095
5096                 close_file(fsp, NORMAL_CLOSE);
5097
5098                 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
5099                           nt_errstr(status), directory,newname));
5100
5101                 return status;
5102         }
5103
5104         /*
5105          * Wildcards - process each file that matches.
5106          */
5107         if (strequal(mask,"????????.???")) {
5108                 pstrcpy(mask,"*");
5109         }
5110                         
5111         status = check_name(conn, directory);
5112         if (!NT_STATUS_IS_OK(status)) {
5113                 return status;
5114         }
5115         
5116         dir_hnd = OpenDir(conn, directory, mask, attrs);
5117         if (dir_hnd == NULL) {
5118                 return map_nt_error_from_unix(errno);
5119         }
5120                 
5121         status = NT_STATUS_NO_SUCH_FILE;
5122         /*
5123          * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
5124          * - gentest fix. JRA
5125          */
5126                         
5127         while ((dname = ReadDirName(dir_hnd, &offset))) {
5128                 files_struct *fsp;
5129                 pstring fname;
5130                 BOOL sysdir_entry = False;
5131
5132                 pstrcpy(fname,dname);
5133                                 
5134                 /* Quick check for "." and ".." */
5135                 if (fname[0] == '.') {
5136                         if (!fname[1] || (fname[1] == '.' && !fname[2])) {
5137                                 if (attrs & aDIR) {
5138                                         sysdir_entry = True;
5139                                 } else {
5140                                         continue;
5141                                 }
5142                         }
5143                 }
5144
5145                 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5146                         continue;
5147                 }
5148
5149                 if(!mask_match(fname, mask, conn->case_sensitive)) {
5150                         continue;
5151                 }
5152                                 
5153                 if (sysdir_entry) {
5154                         status = NT_STATUS_OBJECT_NAME_INVALID;
5155                         break;
5156                 }
5157
5158                 slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname);
5159
5160                 pstrcpy(destname,newname);
5161                         
5162                 if (!resolve_wildcards(fname,destname)) {
5163                         DEBUG(6, ("resolve_wildcards %s %s failed\n", 
5164                                   fname, destname));
5165                         continue;
5166                 }
5167                                 
5168                 ZERO_STRUCT(sbuf1);
5169                 SMB_VFS_STAT(conn, fname, &sbuf1);
5170
5171                 status = S_ISDIR(sbuf1.st_mode) ?
5172                         open_directory(conn, req, fname, &sbuf1,
5173                                        DELETE_ACCESS,
5174                                        FILE_SHARE_READ|FILE_SHARE_WRITE,
5175                                        FILE_OPEN, 0, 0, NULL,
5176                                        &fsp)
5177                         : open_file_ntcreate(conn, req, fname, &sbuf1,
5178                                              DELETE_ACCESS,
5179                                              FILE_SHARE_READ|FILE_SHARE_WRITE,
5180                                              FILE_OPEN, 0, 0, 0, NULL,
5181                                              &fsp);
5182
5183                 if (!NT_STATUS_IS_OK(status)) {
5184                         DEBUG(3,("rename_internals: open_file_ntcreate "
5185                                  "returned %s rename %s -> %s\n",
5186                                  nt_errstr(status), directory, newname));
5187                         break;
5188                 }
5189
5190                 status = rename_internals_fsp(conn, fsp, destname, attrs,
5191                                               replace_if_exists);
5192
5193                 close_file(fsp, NORMAL_CLOSE);
5194
5195                 if (!NT_STATUS_IS_OK(status)) {
5196                         DEBUG(3, ("rename_internals_fsp returned %s for "
5197                                   "rename %s -> %s\n", nt_errstr(status),
5198                                   directory, newname));
5199                         break;
5200                 }
5201
5202                 count++;
5203
5204                 DEBUG(3,("rename_internals: doing rename on %s -> "
5205                          "%s\n",fname,destname));
5206         }
5207         CloseDir(dir_hnd);
5208
5209         if (count == 0 && NT_STATUS_IS_OK(status)) {
5210                 status = map_nt_error_from_unix(errno);
5211         }
5212         
5213         return status;
5214 }
5215
5216 /****************************************************************************
5217  Reply to a mv.
5218 ****************************************************************************/
5219
5220 void reply_mv(connection_struct *conn, struct smb_request *req)
5221 {
5222         pstring name;
5223         pstring newname;
5224         char *p;
5225         uint32 attrs;
5226         NTSTATUS status;
5227         BOOL src_has_wcard = False;
5228         BOOL dest_has_wcard = False;
5229
5230         START_PROFILE(SMBmv);
5231
5232         if (req->wct < 1) {
5233                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5234                 END_PROFILE(SMBmv);
5235                 return;
5236         }
5237
5238         attrs = SVAL(req->inbuf,smb_vwv0);
5239
5240         p = smb_buf(req->inbuf) + 1;
5241         p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, name, p,
5242                                    sizeof(name), 0, STR_TERMINATE, &status,
5243                                    &src_has_wcard);
5244         if (!NT_STATUS_IS_OK(status)) {
5245                 reply_nterror(req, status);
5246                 END_PROFILE(SMBmv);
5247                 return;
5248         }
5249         p++;
5250         p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, newname, p,
5251                                    sizeof(newname), 0, STR_TERMINATE, &status,
5252                                    &dest_has_wcard);
5253         if (!NT_STATUS_IS_OK(status)) {
5254                 reply_nterror(req, status);
5255                 END_PROFILE(SMBmv);
5256                 return;
5257         }
5258         
5259         status = resolve_dfspath_wcard(conn,
5260                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
5261                                        name, &src_has_wcard);
5262         if (!NT_STATUS_IS_OK(status)) {
5263                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5264                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5265                                         ERRSRV, ERRbadpath);
5266                         END_PROFILE(SMBmv);
5267                         return;
5268                 }
5269                 reply_nterror(req, status);
5270                 END_PROFILE(SMBmv);
5271                 return;
5272         }
5273
5274         status = resolve_dfspath_wcard(conn,
5275                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
5276                                        newname, &dest_has_wcard);
5277         if (!NT_STATUS_IS_OK(status)) {
5278                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5279                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5280                                         ERRSRV, ERRbadpath);
5281                         END_PROFILE(SMBmv);
5282                         return;
5283                 }
5284                 reply_nterror(req, status);
5285                 END_PROFILE(SMBmv);
5286                 return;
5287         }
5288         
5289         DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
5290         
5291         status = rename_internals(conn, req, name, newname, attrs, False,
5292                                   src_has_wcard, dest_has_wcard);
5293         if (!NT_STATUS_IS_OK(status)) {
5294                 if (open_was_deferred(req->mid)) {
5295                         /* We have re-scheduled this call. */
5296                         END_PROFILE(SMBmv);
5297                         return;
5298                 }
5299                 reply_nterror(req, status);
5300                 END_PROFILE(SMBmv);
5301                 return;
5302         }
5303
5304         reply_outbuf(req, 0, 0);
5305   
5306         END_PROFILE(SMBmv);
5307         return;
5308 }
5309
5310 /*******************************************************************
5311  Copy a file as part of a reply_copy.
5312 ******************************************************************/
5313
5314 /*
5315  * TODO: check error codes on all callers
5316  */
5317
5318 NTSTATUS copy_file(connection_struct *conn,
5319                         char *src,
5320                         char *dest1,
5321                         int ofun,
5322                         int count,
5323                         BOOL target_is_directory)
5324 {
5325         SMB_STRUCT_STAT src_sbuf, sbuf2;
5326         SMB_OFF_T ret=-1;
5327         files_struct *fsp1,*fsp2;
5328         pstring dest;
5329         uint32 dosattrs;
5330         uint32 new_create_disposition;
5331         NTSTATUS status;
5332  
5333         pstrcpy(dest,dest1);
5334         if (target_is_directory) {
5335                 char *p = strrchr_m(src,'/');
5336                 if (p) {
5337                         p++;
5338                 } else {
5339                         p = src;
5340                 }
5341                 pstrcat(dest,"/");
5342                 pstrcat(dest,p);
5343         }
5344
5345         if (!vfs_file_exist(conn,src,&src_sbuf)) {
5346                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5347         }
5348
5349         if (!target_is_directory && count) {
5350                 new_create_disposition = FILE_OPEN;
5351         } else {
5352                 if (!map_open_params_to_ntcreate(dest1,0,ofun,
5353                                 NULL, NULL, &new_create_disposition, NULL)) {
5354                         return NT_STATUS_INVALID_PARAMETER;
5355                 }
5356         }
5357
5358         status = open_file_ntcreate(conn, NULL, src, &src_sbuf,
5359                         FILE_GENERIC_READ,
5360                         FILE_SHARE_READ|FILE_SHARE_WRITE,
5361                         FILE_OPEN,
5362                         0,
5363                         FILE_ATTRIBUTE_NORMAL,
5364                         INTERNAL_OPEN_ONLY,
5365                         NULL, &fsp1);
5366
5367         if (!NT_STATUS_IS_OK(status)) {
5368                 return status;
5369         }
5370
5371         dosattrs = dos_mode(conn, src, &src_sbuf);
5372         if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
5373                 ZERO_STRUCTP(&sbuf2);
5374         }
5375
5376         status = open_file_ntcreate(conn, NULL, dest, &sbuf2,
5377                         FILE_GENERIC_WRITE,
5378                         FILE_SHARE_READ|FILE_SHARE_WRITE,
5379                         new_create_disposition,
5380                         0,
5381                         dosattrs,
5382                         INTERNAL_OPEN_ONLY,
5383                         NULL, &fsp2);
5384
5385         if (!NT_STATUS_IS_OK(status)) {
5386                 close_file(fsp1,ERROR_CLOSE);
5387                 return status;
5388         }
5389
5390         if ((ofun&3) == 1) {
5391                 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
5392                         DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
5393                         /*
5394                          * Stop the copy from occurring.
5395                          */
5396                         ret = -1;
5397                         src_sbuf.st_size = 0;
5398                 }
5399         }
5400   
5401         if (src_sbuf.st_size) {
5402                 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
5403         }
5404
5405         close_file(fsp1,NORMAL_CLOSE);
5406
5407         /* Ensure the modtime is set correctly on the destination file. */
5408         fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
5409
5410         /*
5411          * As we are opening fsp1 read-only we only expect
5412          * an error on close on fsp2 if we are out of space.
5413          * Thus we don't look at the error return from the
5414          * close of fsp1.
5415          */
5416         status = close_file(fsp2,NORMAL_CLOSE);
5417
5418         if (!NT_STATUS_IS_OK(status)) {
5419                 return status;
5420         }
5421
5422         if (ret != (SMB_OFF_T)src_sbuf.st_size) {
5423                 return NT_STATUS_DISK_FULL;
5424         }
5425
5426         return NT_STATUS_OK;
5427 }
5428
5429 /****************************************************************************
5430  Reply to a file copy.
5431 ****************************************************************************/
5432
5433 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5434 {
5435         int outsize = 0;
5436         pstring name;
5437         pstring directory;
5438         pstring mask,newname;
5439         char *p;
5440         int count=0;
5441         int error = ERRnoaccess;
5442         int err = 0;
5443         int tid2 = SVAL(inbuf,smb_vwv0);
5444         int ofun = SVAL(inbuf,smb_vwv1);
5445         int flags = SVAL(inbuf,smb_vwv2);
5446         BOOL target_is_directory=False;
5447         BOOL source_has_wild = False;
5448         BOOL dest_has_wild = False;
5449         SMB_STRUCT_STAT sbuf1, sbuf2;
5450         NTSTATUS status;
5451         START_PROFILE(SMBcopy);
5452
5453         *directory = *mask = 0;
5454
5455         p = smb_buf(inbuf);
5456         p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p,
5457                                    sizeof(name), 0, STR_TERMINATE, &status,
5458                                    &source_has_wild);
5459         if (!NT_STATUS_IS_OK(status)) {
5460                 END_PROFILE(SMBcopy);
5461                 return ERROR_NT(status);
5462         }
5463         p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p,
5464                                    sizeof(newname), 0, STR_TERMINATE, &status,
5465                                    &dest_has_wild);
5466         if (!NT_STATUS_IS_OK(status)) {
5467                 END_PROFILE(SMBcopy);
5468                 return ERROR_NT(status);
5469         }
5470    
5471         DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
5472    
5473         if (tid2 != conn->cnum) {
5474                 /* can't currently handle inter share copies XXXX */
5475                 DEBUG(3,("Rejecting inter-share copy\n"));
5476                 END_PROFILE(SMBcopy);
5477                 return ERROR_DOS(ERRSRV,ERRinvdevice);
5478         }
5479
5480         status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &source_has_wild);
5481         if (!NT_STATUS_IS_OK(status)) {
5482                 END_PROFILE(SMBcopy);
5483                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5484                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5485                 }
5486                 return ERROR_NT(status);
5487         }
5488
5489         status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wild);
5490         if (!NT_STATUS_IS_OK(status)) {
5491                 END_PROFILE(SMBcopy);
5492                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5493                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5494                 }
5495                 return ERROR_NT(status);
5496         }
5497
5498         status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1);
5499         if (!NT_STATUS_IS_OK(status)) {
5500                 END_PROFILE(SMBcopy);
5501                 return ERROR_NT(status);
5502         }
5503
5504         status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2);
5505         if (!NT_STATUS_IS_OK(status)) {
5506                 END_PROFILE(SMBcopy);
5507                 return ERROR_NT(status);
5508         }
5509
5510         target_is_directory = VALID_STAT_OF_DIR(sbuf2);
5511
5512         if ((flags&1) && target_is_directory) {
5513                 END_PROFILE(SMBcopy);
5514                 return ERROR_DOS(ERRDOS,ERRbadfile);
5515         }
5516
5517         if ((flags&2) && !target_is_directory) {
5518                 END_PROFILE(SMBcopy);
5519                 return ERROR_DOS(ERRDOS,ERRbadpath);
5520         }
5521
5522         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
5523                 /* wants a tree copy! XXXX */
5524                 DEBUG(3,("Rejecting tree copy\n"));
5525                 END_PROFILE(SMBcopy);
5526                 return ERROR_DOS(ERRSRV,ERRerror);
5527         }
5528
5529         p = strrchr_m(name,'/');
5530         if (!p) {
5531                 pstrcpy(directory,"./");
5532                 pstrcpy(mask,name);
5533         } else {
5534                 *p = 0;
5535                 pstrcpy(directory,name);
5536                 pstrcpy(mask,p+1);
5537         }
5538
5539         /*
5540          * We should only check the mangled cache
5541          * here if unix_convert failed. This means
5542          * that the path in 'mask' doesn't exist
5543          * on the file system and so we need to look
5544          * for a possible mangle. This patch from
5545          * Tine Smukavec <valentin.smukavec@hermes.si>.
5546          */
5547
5548         if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5549                 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
5550         }
5551
5552         if (!source_has_wild) {
5553                 pstrcat(directory,"/");
5554                 pstrcat(directory,mask);
5555                 if (dest_has_wild) {
5556                         if (!resolve_wildcards(directory,newname)) {
5557                                 END_PROFILE(SMBcopy);
5558                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
5559                         }
5560                 }
5561
5562                 status = check_name(conn, directory);
5563                 if (!NT_STATUS_IS_OK(status)) {
5564                         return ERROR_NT(status);
5565                 }
5566                 
5567                 status = check_name(conn, newname);
5568                 if (!NT_STATUS_IS_OK(status)) {
5569                         return ERROR_NT(status);
5570                 }
5571                 
5572                 status = copy_file(conn,directory,newname,ofun,
5573                                         count,target_is_directory);
5574
5575                 if(!NT_STATUS_IS_OK(status)) {
5576                         END_PROFILE(SMBcopy);
5577                         return ERROR_NT(status);
5578                 } else {
5579                         count++;
5580                 }
5581         } else {
5582                 struct smb_Dir *dir_hnd = NULL;
5583                 const char *dname;
5584                 long offset = 0;
5585                 pstring destname;
5586
5587                 if (strequal(mask,"????????.???"))
5588                         pstrcpy(mask,"*");
5589
5590                 status = check_name(conn, directory);
5591                 if (!NT_STATUS_IS_OK(status)) {
5592                         return ERROR_NT(status);
5593                 }
5594                 
5595                 dir_hnd = OpenDir(conn, directory, mask, 0);
5596                 if (dir_hnd == NULL) {
5597                         status = map_nt_error_from_unix(errno);
5598                         return ERROR_NT(status);
5599                 }
5600
5601                 error = ERRbadfile;
5602
5603                 while ((dname = ReadDirName(dir_hnd, &offset))) {
5604                         pstring fname;
5605                         pstrcpy(fname,dname);
5606     
5607                         if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5608                                 continue;
5609                         }
5610
5611                         if(!mask_match(fname, mask, conn->case_sensitive)) {
5612                                 continue;
5613                         }
5614
5615                         error = ERRnoaccess;
5616                         slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
5617                         pstrcpy(destname,newname);
5618                         if (!resolve_wildcards(fname,destname)) {
5619                                 continue;
5620                         }
5621
5622                         status = check_name(conn, fname);
5623                         if (!NT_STATUS_IS_OK(status)) {
5624                                 return ERROR_NT(status);
5625                         }
5626                 
5627                         status = check_name(conn, destname);
5628                         if (!NT_STATUS_IS_OK(status)) {
5629                                 return ERROR_NT(status);
5630                         }
5631                 
5632                         DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
5633
5634                         status = copy_file(conn,fname,destname,ofun,
5635                                         count,target_is_directory);
5636                         if (NT_STATUS_IS_OK(status)) {
5637                                 count++;
5638                         }
5639                 }
5640                 CloseDir(dir_hnd);
5641         }
5642   
5643         if (count == 0) {
5644                 if(err) {
5645                         /* Error on close... */
5646                         errno = err;
5647                         END_PROFILE(SMBcopy);
5648                         return(UNIXERROR(ERRHRD,ERRgeneral));
5649                 }
5650
5651                 END_PROFILE(SMBcopy);
5652                 return ERROR_DOS(ERRDOS,error);
5653         }
5654   
5655         outsize = set_message(inbuf,outbuf,1,0,True);
5656         SSVAL(outbuf,smb_vwv0,count);
5657
5658         END_PROFILE(SMBcopy);
5659         return(outsize);
5660 }
5661
5662 /****************************************************************************
5663  Reply to a setdir.
5664 ****************************************************************************/
5665
5666 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5667 {
5668         int snum;
5669         int outsize = 0;
5670         pstring newdir;
5671         NTSTATUS status;
5672
5673         START_PROFILE(pathworks_setdir);
5674   
5675         snum = SNUM(conn);
5676         if (!CAN_SETDIR(snum)) {
5677                 END_PROFILE(pathworks_setdir);
5678                 return ERROR_DOS(ERRDOS,ERRnoaccess);
5679         }
5680
5681         srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), newdir,
5682                         smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE,
5683                         &status);
5684         if (!NT_STATUS_IS_OK(status)) {
5685                 END_PROFILE(pathworks_setdir);
5686                 return ERROR_NT(status);
5687         }
5688   
5689         status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newdir);
5690         if (!NT_STATUS_IS_OK(status)) {
5691                 END_PROFILE(pathworks_setdir);
5692                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5693                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5694                 }
5695                 return ERROR_NT(status);
5696         }
5697
5698         if (strlen(newdir) != 0) {
5699                 if (!vfs_directory_exist(conn,newdir,NULL)) {
5700                         END_PROFILE(pathworks_setdir);
5701                         return ERROR_DOS(ERRDOS,ERRbadpath);
5702                 }
5703                 set_conn_connectpath(conn,newdir);
5704         }
5705   
5706         outsize = set_message(inbuf,outbuf,0,0,False);
5707         SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
5708   
5709         DEBUG(3,("setdir %s\n", newdir));
5710
5711         END_PROFILE(pathworks_setdir);
5712         return(outsize);
5713 }
5714
5715 #undef DBGC_CLASS
5716 #define DBGC_CLASS DBGC_LOCKING
5717
5718 /****************************************************************************
5719  Get a lock pid, dealing with large count requests.
5720 ****************************************************************************/
5721
5722 uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
5723 {
5724         if(!large_file_format)
5725                 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
5726         else
5727                 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
5728 }
5729
5730 /****************************************************************************
5731  Get a lock count, dealing with large count requests.
5732 ****************************************************************************/
5733
5734 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
5735 {
5736         SMB_BIG_UINT count = 0;
5737
5738         if(!large_file_format) {
5739                 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
5740         } else {
5741
5742 #if defined(HAVE_LONGLONG)
5743                 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
5744                         ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
5745 #else /* HAVE_LONGLONG */
5746
5747                 /*
5748                  * NT4.x seems to be broken in that it sends large file (64 bit)
5749                  * lockingX calls even if the CAP_LARGE_FILES was *not*
5750                  * negotiated. For boxes without large unsigned ints truncate the
5751                  * lock count by dropping the top 32 bits.
5752                  */
5753
5754                 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
5755                         DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
5756                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
5757                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
5758                                 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
5759                 }
5760
5761                 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
5762 #endif /* HAVE_LONGLONG */
5763         }
5764
5765         return count;
5766 }
5767
5768 #if !defined(HAVE_LONGLONG)
5769 /****************************************************************************
5770  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
5771 ****************************************************************************/
5772
5773 static uint32 map_lock_offset(uint32 high, uint32 low)
5774 {
5775         unsigned int i;
5776         uint32 mask = 0;
5777         uint32 highcopy = high;
5778  
5779         /*
5780          * Try and find out how many significant bits there are in high.
5781          */
5782  
5783         for(i = 0; highcopy; i++)
5784                 highcopy >>= 1;
5785  
5786         /*
5787          * We use 31 bits not 32 here as POSIX
5788          * lock offsets may not be negative.
5789          */
5790  
5791         mask = (~0) << (31 - i);
5792  
5793         if(low & mask)
5794                 return 0; /* Fail. */
5795  
5796         high <<= (31 - i);
5797  
5798         return (high|low);
5799 }
5800 #endif /* !defined(HAVE_LONGLONG) */
5801
5802 /****************************************************************************
5803  Get a lock offset, dealing with large offset requests.
5804 ****************************************************************************/
5805
5806 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
5807 {
5808         SMB_BIG_UINT offset = 0;
5809
5810         *err = False;
5811
5812         if(!large_file_format) {
5813                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
5814         } else {
5815
5816 #if defined(HAVE_LONGLONG)
5817                 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
5818                                 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
5819 #else /* HAVE_LONGLONG */
5820
5821                 /*
5822                  * NT4.x seems to be broken in that it sends large file (64 bit)
5823                  * lockingX calls even if the CAP_LARGE_FILES was *not*
5824                  * negotiated. For boxes without large unsigned ints mangle the
5825                  * lock offset by mapping the top 32 bits onto the lower 32.
5826                  */
5827       
5828                 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
5829                         uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5830                         uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
5831                         uint32 new_low = 0;
5832
5833                         if((new_low = map_lock_offset(high, low)) == 0) {
5834                                 *err = True;
5835                                 return (SMB_BIG_UINT)-1;
5836                         }
5837
5838                         DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
5839                                 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
5840                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
5841                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
5842                 }
5843
5844                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5845 #endif /* HAVE_LONGLONG */
5846         }
5847
5848         return offset;
5849 }
5850
5851 /****************************************************************************
5852  Reply to a lockingX request.
5853 ****************************************************************************/
5854
5855 void reply_lockingX(connection_struct *conn, struct smb_request *req)
5856 {
5857         files_struct *fsp;
5858         unsigned char locktype;
5859         unsigned char oplocklevel;
5860         uint16 num_ulocks;
5861         uint16 num_locks;
5862         SMB_BIG_UINT count = 0, offset = 0;
5863         uint32 lock_pid;
5864         int32 lock_timeout;
5865         int i;
5866         char *data;
5867         BOOL large_file_format;
5868         BOOL err;
5869         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5870
5871         START_PROFILE(SMBlockingX);
5872
5873         if (req->wct < 8) {
5874                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5875                 END_PROFILE(SMBlockingX);
5876                 return;
5877         }
5878         
5879         fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
5880         locktype = CVAL(req->inbuf,smb_vwv3);
5881         oplocklevel = CVAL(req->inbuf,smb_vwv3+1);
5882         num_ulocks = SVAL(req->inbuf,smb_vwv6);
5883         num_locks = SVAL(req->inbuf,smb_vwv7);
5884         lock_timeout = IVAL(req->inbuf,smb_vwv4);
5885         large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
5886
5887         if (!check_fsp(conn, req, fsp, &current_user)) {
5888                 END_PROFILE(SMBlockingX);
5889                 return;
5890         }
5891         
5892         data = smb_buf(req->inbuf);
5893
5894         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
5895                 /* we don't support these - and CANCEL_LOCK makes w2k
5896                    and XP reboot so I don't really want to be
5897                    compatible! (tridge) */
5898                 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
5899                 END_PROFILE(SMBlockingX);
5900                 return;
5901         }
5902         
5903         /* Check if this is an oplock break on a file
5904            we have granted an oplock on.
5905         */
5906         if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
5907                 /* Client can insist on breaking to none. */
5908                 BOOL break_to_none = (oplocklevel == 0);
5909                 BOOL result;
5910
5911                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
5912                          "for fnum = %d\n", (unsigned int)oplocklevel,
5913                          fsp->fnum ));
5914
5915                 /*
5916                  * Make sure we have granted an exclusive or batch oplock on
5917                  * this file.
5918                  */
5919                 
5920                 if (fsp->oplock_type == 0) {
5921
5922                         /* The Samba4 nbench simulator doesn't understand
5923                            the difference between break to level2 and break
5924                            to none from level2 - it sends oplock break
5925                            replies in both cases. Don't keep logging an error
5926                            message here - just ignore it. JRA. */
5927
5928                         DEBUG(5,("reply_lockingX: Error : oplock break from "
5929                                  "client for fnum = %d (oplock=%d) and no "
5930                                  "oplock granted on this file (%s).\n",
5931                                  fsp->fnum, fsp->oplock_type, fsp->fsp_name));
5932
5933                         /* if this is a pure oplock break request then don't
5934                          * send a reply */
5935                         if (num_locks == 0 && num_ulocks == 0) {
5936                                 END_PROFILE(SMBlockingX);
5937                                 reply_post_legacy(req, -1);
5938                                 return;
5939                         } else {
5940                                 END_PROFILE(SMBlockingX);
5941                                 reply_doserror(req, ERRDOS, ERRlock);
5942                                 return;
5943                         }
5944                 }
5945
5946                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
5947                     (break_to_none)) {
5948                         result = remove_oplock(fsp);
5949                 } else {
5950                         result = downgrade_oplock(fsp);
5951                 }
5952                 
5953                 if (!result) {
5954                         DEBUG(0, ("reply_lockingX: error in removing "
5955                                   "oplock on file %s\n", fsp->fsp_name));
5956                         /* Hmmm. Is this panic justified? */
5957                         smb_panic("internal tdb error");
5958                 }
5959
5960                 reply_to_oplock_break_requests(fsp);
5961
5962                 /* if this is a pure oplock break request then don't send a
5963                  * reply */
5964                 if (num_locks == 0 && num_ulocks == 0) {
5965                         /* Sanity check - ensure a pure oplock break is not a
5966                            chained request. */
5967                         if(CVAL(req->inbuf,smb_vwv0) != 0xff)
5968                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
5969                                          "break is a chained %d request !\n",
5970                                          (unsigned int)CVAL(req->inbuf,
5971                                                             smb_vwv0) ));
5972                         END_PROFILE(SMBlockingX);
5973                         return;
5974                 }
5975         }
5976
5977         /*
5978          * We do this check *after* we have checked this is not a oplock break
5979          * response message. JRA.
5980          */
5981         
5982         release_level_2_oplocks_on_change(fsp);
5983
5984         if (smb_buflen(req->inbuf) <
5985             (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
5986                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5987                 END_PROFILE(SMBlockingX);
5988                 return;
5989         }
5990         
5991         /* Data now points at the beginning of the list
5992            of smb_unlkrng structs */
5993         for(i = 0; i < (int)num_ulocks; i++) {
5994                 lock_pid = get_lock_pid( data, i, large_file_format);
5995                 count = get_lock_count( data, i, large_file_format);
5996                 offset = get_lock_offset( data, i, large_file_format, &err);
5997                 
5998                 /*
5999                  * There is no error code marked "stupid client bug".... :-).
6000                  */
6001                 if(err) {
6002                         END_PROFILE(SMBlockingX);
6003                         reply_doserror(req, ERRDOS, ERRnoaccess);
6004                         return;
6005                 }
6006
6007                 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
6008                           "pid %u, file %s\n", (double)offset, (double)count,
6009                           (unsigned int)lock_pid, fsp->fsp_name ));
6010                 
6011                 status = do_unlock(smbd_messaging_context(),
6012                                 fsp,
6013                                 lock_pid,
6014                                 count,
6015                                 offset,
6016                                 WINDOWS_LOCK);
6017
6018                 if (NT_STATUS_V(status)) {
6019                         END_PROFILE(SMBlockingX);
6020                         reply_nterror(req, status);
6021                         return;
6022                 }
6023         }
6024
6025         /* Setup the timeout in seconds. */
6026
6027         if (!lp_blocking_locks(SNUM(conn))) {
6028                 lock_timeout = 0;
6029         }
6030         
6031         /* Now do any requested locks */
6032         data += ((large_file_format ? 20 : 10)*num_ulocks);
6033         
6034         /* Data now points at the beginning of the list
6035            of smb_lkrng structs */
6036         
6037         for(i = 0; i < (int)num_locks; i++) {
6038                 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
6039                                 READ_LOCK:WRITE_LOCK);
6040                 lock_pid = get_lock_pid( data, i, large_file_format);
6041                 count = get_lock_count( data, i, large_file_format);
6042                 offset = get_lock_offset( data, i, large_file_format, &err);
6043                 
6044                 /*
6045                  * There is no error code marked "stupid client bug".... :-).
6046                  */
6047                 if(err) {
6048                         END_PROFILE(SMBlockingX);
6049                         reply_doserror(req, ERRDOS, ERRnoaccess);
6050                         return;
6051                 }
6052                 
6053                 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
6054                           "%u, file %s timeout = %d\n", (double)offset,
6055                           (double)count, (unsigned int)lock_pid,
6056                           fsp->fsp_name, (int)lock_timeout ));
6057                 
6058                 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
6059                         if (lp_blocking_locks(SNUM(conn))) {
6060
6061                                 /* Schedule a message to ourselves to
6062                                    remove the blocking lock record and
6063                                    return the right error. */
6064
6065                                 if (!blocking_lock_cancel(fsp,
6066                                                 lock_pid,
6067                                                 offset,
6068                                                 count,
6069                                                 WINDOWS_LOCK,
6070                                                 locktype,
6071                                                 NT_STATUS_FILE_LOCK_CONFLICT)) {
6072                                         END_PROFILE(SMBlockingX);
6073                                         reply_nterror(
6074                                                 req,
6075                                                 NT_STATUS_DOS(
6076                                                         ERRDOS,
6077                                                         ERRcancelviolation));
6078                                         return;
6079                                 }
6080                         }
6081                         /* Remove a matching pending lock. */
6082                         status = do_lock_cancel(fsp,
6083                                                 lock_pid,
6084                                                 count,
6085                                                 offset,
6086                                                 WINDOWS_LOCK);
6087                 } else {
6088                         BOOL blocking_lock = lock_timeout ? True : False;
6089                         BOOL defer_lock = False;
6090                         struct byte_range_lock *br_lck;
6091                         uint32 block_smbpid;
6092
6093                         br_lck = do_lock(smbd_messaging_context(),
6094                                         fsp,
6095                                         lock_pid,
6096                                         count,
6097                                         offset, 
6098                                         lock_type,
6099                                         WINDOWS_LOCK,
6100                                         blocking_lock,
6101                                         &status,
6102                                         &block_smbpid);
6103
6104                         if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6105                                 /* Windows internal resolution for blocking locks seems
6106                                    to be about 200ms... Don't wait for less than that. JRA. */
6107                                 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
6108                                         lock_timeout = lp_lock_spin_time();
6109                                 }
6110                                 defer_lock = True;
6111                         }
6112
6113                         /* This heuristic seems to match W2K3 very well. If a
6114                            lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
6115                            it pretends we asked for a timeout of between 150 - 300 milliseconds as
6116                            far as I can tell. Replacement for do_lock_spin(). JRA. */
6117
6118                         if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
6119                                         NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
6120                                 defer_lock = True;
6121                                 lock_timeout = lp_lock_spin_time();
6122                         }
6123
6124                         if (br_lck && defer_lock) {
6125                                 /*
6126                                  * A blocking lock was requested. Package up
6127                                  * this smb into a queued request and push it
6128                                  * onto the blocking lock queue.
6129                                  */
6130                                 if(push_blocking_lock_request(br_lck,
6131                                                         (char *)req->inbuf,
6132                                                         smb_len(req->inbuf)+4,
6133                                                         fsp,
6134                                                         lock_timeout,
6135                                                         i,
6136                                                         lock_pid,
6137                                                         lock_type,
6138                                                         WINDOWS_LOCK,
6139                                                         offset,
6140                                                         count,
6141                                                         block_smbpid)) {
6142                                         TALLOC_FREE(br_lck);
6143                                         END_PROFILE(SMBlockingX);
6144                                         reply_post_legacy(req, -1);
6145                                         return;
6146                                 }
6147                         }
6148
6149                         TALLOC_FREE(br_lck);
6150                 }
6151
6152                 if (NT_STATUS_V(status)) {
6153                         END_PROFILE(SMBlockingX);
6154                         reply_nterror(req, status);
6155                         return;
6156                 }
6157         }
6158         
6159         /* If any of the above locks failed, then we must unlock
6160            all of the previous locks (X/Open spec). */
6161
6162         if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
6163                         (i != num_locks) &&
6164                         (num_locks != 0)) {
6165                 /*
6166                  * Ensure we don't do a remove on the lock that just failed,
6167                  * as under POSIX rules, if we have a lock already there, we
6168                  * will delete it (and we shouldn't) .....
6169                  */
6170                 for(i--; i >= 0; i--) {
6171                         lock_pid = get_lock_pid( data, i, large_file_format);
6172                         count = get_lock_count( data, i, large_file_format);
6173                         offset = get_lock_offset( data, i, large_file_format,
6174                                                   &err);
6175                         
6176                         /*
6177                          * There is no error code marked "stupid client
6178                          * bug".... :-).
6179                          */
6180                         if(err) {
6181                                 END_PROFILE(SMBlockingX);
6182                                 reply_doserror(req, ERRDOS, ERRnoaccess);
6183                                 return;
6184                         }
6185                         
6186                         do_unlock(smbd_messaging_context(),
6187                                 fsp,
6188                                 lock_pid,
6189                                 count,
6190                                 offset,
6191                                 WINDOWS_LOCK);
6192                 }
6193                 END_PROFILE(SMBlockingX);
6194                 reply_nterror(req, status);
6195                 return;
6196         }
6197
6198         reply_outbuf(req, 2, 0);
6199         
6200         DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
6201                   fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
6202         
6203         END_PROFILE(SMBlockingX);
6204         chain_reply_new(req);
6205 }
6206
6207 #undef DBGC_CLASS
6208 #define DBGC_CLASS DBGC_ALL
6209
6210 /****************************************************************************
6211  Reply to a SMBreadbmpx (read block multiplex) request.
6212 ****************************************************************************/
6213
6214 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
6215 {
6216         ssize_t nread = -1;
6217         ssize_t total_read;
6218         char *data;
6219         SMB_OFF_T startpos;
6220         int outsize;
6221         size_t maxcount;
6222         int max_per_packet;
6223         size_t tcount;
6224         int pad;
6225         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6226         START_PROFILE(SMBreadBmpx);
6227
6228         /* this function doesn't seem to work - disable by default */
6229         if (!lp_readbmpx()) {
6230                 END_PROFILE(SMBreadBmpx);
6231                 return ERROR_DOS(ERRSRV,ERRuseSTD);
6232         }
6233
6234         outsize = set_message(inbuf,outbuf,8,0,True);
6235
6236         CHECK_FSP(fsp,conn);
6237         if (!CHECK_READ(fsp,inbuf)) {
6238                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
6239         }
6240
6241         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
6242         maxcount = SVAL(inbuf,smb_vwv3);
6243
6244         data = smb_buf(outbuf);
6245         pad = ((long)data)%4;
6246         if (pad)
6247                 pad = 4 - pad;
6248         data += pad;
6249
6250         max_per_packet = bufsize-(outsize+pad);
6251         tcount = maxcount;
6252         total_read = 0;
6253
6254         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
6255                 END_PROFILE(SMBreadBmpx);
6256                 return ERROR_DOS(ERRDOS,ERRlock);
6257         }
6258
6259         do {
6260                 size_t N = MIN(max_per_packet,tcount-total_read);
6261   
6262                 nread = read_file(fsp,data,startpos,N);
6263
6264                 if (nread <= 0)
6265                         nread = 0;
6266
6267                 if (nread < (ssize_t)N)
6268                         tcount = total_read + nread;
6269
6270                 set_message(inbuf,outbuf,8,nread+pad,False);
6271                 SIVAL(outbuf,smb_vwv0,startpos);
6272                 SSVAL(outbuf,smb_vwv2,tcount);
6273                 SSVAL(outbuf,smb_vwv6,nread);
6274                 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
6275
6276                 show_msg(outbuf);
6277                 if (!send_smb(smbd_server_fd(),outbuf))
6278                         exit_server_cleanly("reply_readbmpx: send_smb failed.");
6279
6280                 total_read += nread;
6281                 startpos += nread;
6282         } while (total_read < (ssize_t)tcount);
6283
6284         END_PROFILE(SMBreadBmpx);
6285         return(-1);
6286 }
6287
6288 /****************************************************************************
6289  Reply to a SMBsetattrE.
6290 ****************************************************************************/
6291
6292 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
6293 {
6294         struct timespec ts[2];
6295         int outsize = 0;
6296         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6297         START_PROFILE(SMBsetattrE);
6298
6299         outsize = set_message(inbuf,outbuf,0,0,False);
6300
6301         if(!fsp || (fsp->conn != conn)) {
6302                 END_PROFILE(SMBsetattrE);
6303                 return ERROR_DOS(ERRDOS,ERRbadfid);
6304         }
6305
6306         /*
6307          * Convert the DOS times into unix times. Ignore create
6308          * time as UNIX can't set this.
6309          */
6310
6311         ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv3)); /* atime. */
6312         ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv5)); /* mtime. */
6313   
6314         /* 
6315          * Patch from Ray Frush <frush@engr.colostate.edu>
6316          * Sometimes times are sent as zero - ignore them.
6317          */
6318
6319         if (null_timespec(ts[0]) && null_timespec(ts[1])) {
6320                 /* Ignore request */
6321                 if( DEBUGLVL( 3 ) ) {
6322                         dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
6323                         dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
6324                 }
6325                 END_PROFILE(SMBsetattrE);
6326                 return(outsize);
6327         } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
6328                 /* set modify time = to access time if modify time was unset */
6329                 ts[1] = ts[0];
6330         }
6331
6332         /* Set the date on this file */
6333         /* Should we set pending modtime here ? JRA */
6334         if(file_ntimes(conn, fsp->fsp_name, ts)) {
6335                 END_PROFILE(SMBsetattrE);
6336                 return ERROR_DOS(ERRDOS,ERRnoaccess);
6337         }
6338   
6339         DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
6340                 fsp->fnum,
6341                 (unsigned int)ts[0].tv_sec,
6342                 (unsigned int)ts[1].tv_sec));
6343
6344         END_PROFILE(SMBsetattrE);
6345         return(outsize);
6346 }
6347
6348
6349 /* Back from the dead for OS/2..... JRA. */
6350
6351 /****************************************************************************
6352  Reply to a SMBwritebmpx (write block multiplex primary) request.
6353 ****************************************************************************/
6354
6355 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
6356 {
6357         size_t numtowrite;
6358         ssize_t nwritten = -1;
6359         int outsize = 0;
6360         SMB_OFF_T startpos;
6361         size_t tcount;
6362         BOOL write_through;
6363         int smb_doff;
6364         char *data;
6365         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6366         NTSTATUS status;
6367         START_PROFILE(SMBwriteBmpx);
6368
6369         CHECK_FSP(fsp,conn);
6370         if (!CHECK_WRITE(fsp)) {
6371                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
6372         }
6373         if (HAS_CACHED_ERROR(fsp)) {
6374                 return(CACHED_ERROR(fsp));
6375         }
6376
6377         tcount = SVAL(inbuf,smb_vwv1);
6378         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
6379         write_through = BITSETW(inbuf+smb_vwv7,0);
6380         numtowrite = SVAL(inbuf,smb_vwv10);
6381         smb_doff = SVAL(inbuf,smb_vwv11);
6382
6383         data = smb_base(inbuf) + smb_doff;
6384
6385         /* If this fails we need to send an SMBwriteC response,
6386                 not an SMBwritebmpx - set this up now so we don't forget */
6387         SCVAL(outbuf,smb_com,SMBwritec);
6388
6389         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
6390                 END_PROFILE(SMBwriteBmpx);
6391                 return(ERROR_DOS(ERRDOS,ERRlock));
6392         }
6393
6394         nwritten = write_file(fsp,data,startpos,numtowrite);
6395
6396         status = sync_file(conn, fsp, write_through);
6397         if (!NT_STATUS_IS_OK(status)) {
6398                 END_PROFILE(SMBwriteBmpx);
6399                 DEBUG(5,("reply_writebmpx: sync_file for %s returned %s\n",
6400                         fsp->fsp_name, nt_errstr(status) ));
6401                 return ERROR_NT(status);
6402         }
6403   
6404         if(nwritten < (ssize_t)numtowrite) {
6405                 END_PROFILE(SMBwriteBmpx);
6406                 return(UNIXERROR(ERRHRD,ERRdiskfull));
6407         }
6408
6409         /* If the maximum to be written to this file
6410                 is greater than what we just wrote then set
6411                 up a secondary struct to be attached to this
6412                 fd, we will use this to cache error messages etc. */
6413
6414         if((ssize_t)tcount > nwritten) {
6415                 write_bmpx_struct *wbms;
6416                 if(fsp->wbmpx_ptr != NULL)
6417                         wbms = fsp->wbmpx_ptr; /* Use an existing struct */
6418                 else
6419                         wbms = SMB_MALLOC_P(write_bmpx_struct);
6420                 if(!wbms) {
6421                         DEBUG(0,("Out of memory in reply_readmpx\n"));
6422                         END_PROFILE(SMBwriteBmpx);
6423                         return(ERROR_DOS(ERRSRV,ERRnoresource));
6424                 }
6425                 wbms->wr_mode = write_through;
6426                 wbms->wr_discard = False; /* No errors yet */
6427                 wbms->wr_total_written = nwritten;
6428                 wbms->wr_errclass = 0;
6429                 wbms->wr_error = 0;
6430                 fsp->wbmpx_ptr = wbms;
6431         }
6432
6433         /* We are returning successfully, set the message type back to
6434                 SMBwritebmpx */
6435         SCVAL(outbuf,smb_com,SMBwriteBmpx);
6436   
6437         outsize = set_message(inbuf,outbuf,1,0,True);
6438   
6439         SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
6440   
6441         DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
6442                         fsp->fnum, (int)numtowrite, (int)nwritten ) );
6443
6444         if (write_through && tcount==nwritten) {
6445                 /* We need to send both a primary and a secondary response */
6446                 smb_setlen(inbuf,outbuf,outsize - 4);
6447                 show_msg(outbuf);
6448                 if (!send_smb(smbd_server_fd(),outbuf))
6449                         exit_server_cleanly("reply_writebmpx: send_smb failed.");
6450
6451                 /* Now the secondary */
6452                 outsize = set_message(inbuf,outbuf,1,0,True);
6453                 SCVAL(outbuf,smb_com,SMBwritec);
6454                 SSVAL(outbuf,smb_vwv0,nwritten);
6455         }
6456
6457         END_PROFILE(SMBwriteBmpx);
6458         return(outsize);
6459 }
6460
6461 /****************************************************************************
6462  Reply to a SMBwritebs (write block multiplex secondary) request.
6463 ****************************************************************************/
6464
6465 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
6466 {
6467         size_t numtowrite;
6468         ssize_t nwritten = -1;
6469         int outsize = 0;
6470         SMB_OFF_T startpos;
6471         size_t tcount;
6472         BOOL write_through;
6473         int smb_doff;
6474         char *data;
6475         write_bmpx_struct *wbms;
6476         BOOL send_response = False; 
6477         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6478         NTSTATUS status;
6479         START_PROFILE(SMBwriteBs);
6480
6481         CHECK_FSP(fsp,conn);
6482         if (!CHECK_WRITE(fsp)) {
6483                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
6484         }
6485
6486         tcount = SVAL(inbuf,smb_vwv1);
6487         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
6488         numtowrite = SVAL(inbuf,smb_vwv6);
6489         smb_doff = SVAL(inbuf,smb_vwv7);
6490
6491         data = smb_base(inbuf) + smb_doff;
6492
6493         /* We need to send an SMBwriteC response, not an SMBwritebs */
6494         SCVAL(outbuf,smb_com,SMBwritec);
6495
6496         /* This fd should have an auxiliary struct attached,
6497                 check that it does */
6498         wbms = fsp->wbmpx_ptr;
6499         if(!wbms) {
6500                 END_PROFILE(SMBwriteBs);
6501                 return(-1);
6502         }
6503
6504         /* If write through is set we can return errors, else we must cache them */
6505         write_through = wbms->wr_mode;
6506
6507         /* Check for an earlier error */
6508         if(wbms->wr_discard) {
6509                 END_PROFILE(SMBwriteBs);
6510                 return -1; /* Just discard the packet */
6511         }
6512
6513         nwritten = write_file(fsp,data,startpos,numtowrite);
6514
6515         status = sync_file(conn, fsp, write_through);
6516   
6517         if (nwritten < (ssize_t)numtowrite || !NT_STATUS_IS_OK(status)) {
6518                 if(write_through) {
6519                         /* We are returning an error - we can delete the aux struct */
6520                         if (wbms)
6521                                 free((char *)wbms);
6522                         fsp->wbmpx_ptr = NULL;
6523                         END_PROFILE(SMBwriteBs);
6524                         return(ERROR_DOS(ERRHRD,ERRdiskfull));
6525                 }
6526                 wbms->wr_errclass = ERRHRD;
6527                 wbms->wr_error = ERRdiskfull;
6528                 wbms->wr_status = NT_STATUS_DISK_FULL;
6529                 wbms->wr_discard = True;
6530                 END_PROFILE(SMBwriteBs);
6531                 return -1;
6532         }
6533
6534         /* Increment the total written, if this matches tcount
6535                 we can discard the auxiliary struct (hurrah !) and return a writeC */
6536         wbms->wr_total_written += nwritten;
6537         if(wbms->wr_total_written >= tcount) {
6538                 if (write_through) {
6539                         outsize = set_message(inbuf,outbuf,1,0,True);
6540                         SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);    
6541                         send_response = True;
6542                 }
6543
6544                 free((char *)wbms);
6545                 fsp->wbmpx_ptr = NULL;
6546         }
6547
6548         if(send_response) {
6549                 END_PROFILE(SMBwriteBs);
6550                 return(outsize);
6551         }
6552
6553         END_PROFILE(SMBwriteBs);
6554         return(-1);
6555 }
6556
6557 /****************************************************************************
6558  Reply to a SMBgetattrE.
6559 ****************************************************************************/
6560
6561 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
6562 {
6563         SMB_STRUCT_STAT sbuf;
6564         int outsize = 0;
6565         int mode;
6566         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6567         START_PROFILE(SMBgetattrE);
6568
6569         outsize = set_message(inbuf,outbuf,11,0,True);
6570
6571         if(!fsp || (fsp->conn != conn)) {
6572                 END_PROFILE(SMBgetattrE);
6573                 return ERROR_DOS(ERRDOS,ERRbadfid);
6574         }
6575
6576         /* Do an fstat on this file */
6577         if(fsp_stat(fsp, &sbuf)) {
6578                 END_PROFILE(SMBgetattrE);
6579                 return(UNIXERROR(ERRDOS,ERRnoaccess));
6580         }
6581   
6582         mode = dos_mode(conn,fsp->fsp_name,&sbuf);
6583   
6584         /*
6585          * Convert the times into dos times. Set create
6586          * date to be last modify date as UNIX doesn't save
6587          * this.
6588          */
6589
6590         srv_put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
6591         srv_put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
6592         /* Should we check pending modtime here ? JRA */
6593         srv_put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
6594
6595         if (mode & aDIR) {
6596                 SIVAL(outbuf,smb_vwv6,0);
6597                 SIVAL(outbuf,smb_vwv8,0);
6598         } else {
6599                 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
6600                 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
6601                 SIVAL(outbuf,smb_vwv8,allocation_size);
6602         }
6603         SSVAL(outbuf,smb_vwv10, mode);
6604   
6605         DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
6606   
6607         END_PROFILE(SMBgetattrE);
6608         return(outsize);
6609 }