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