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