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