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