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