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