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