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