Constrain "min receivefile size" to max of BUFFER_SIZE
[samba.git] / source / smbd / reply.c
1 /*
2    Unix SMB/CIFS implementation.
3    Main SMB reply routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Andrew Bartlett      2001
6    Copyright (C) Jeremy Allison 1992-2007.
7    Copyright (C) Volker Lendecke 2007
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22 /*
23    This file handles most of the reply_ calls that the server
24    makes to handle specific protocols
25 */
26
27 #include "includes.h"
28
29 /* look in server.c for some explanation of these variables */
30 extern enum protocol_types Protocol;
31 extern int max_recv;
32 unsigned int smb_echo_count = 0;
33 extern uint32 global_client_caps;
34
35 extern struct current_user current_user;
36 extern bool global_encrypted_passwords_negotiated;
37
38 /****************************************************************************
39  Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
40  path or anything including wildcards.
41  We're assuming here that '/' is not the second byte in any multibyte char
42  set (a safe assumption). '\\' *may* be the second byte in a multibyte char
43  set.
44 ****************************************************************************/
45
46 /* Custom version for processing POSIX paths. */
47 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
48
49 static NTSTATUS check_path_syntax_internal(char *path,
50                                            bool posix_path,
51                                            bool *p_last_component_contains_wcard)
52 {
53         char *d = path;
54         const char *s = path;
55         NTSTATUS ret = NT_STATUS_OK;
56         bool start_of_name_component = True;
57
58         *p_last_component_contains_wcard = False;
59
60         while (*s) {
61                 if (IS_PATH_SEP(*s,posix_path)) {
62                         /*
63                          * Safe to assume is not the second part of a mb char
64                          * as this is handled below.
65                          */
66                         /* Eat multiple '/' or '\\' */
67                         while (IS_PATH_SEP(*s,posix_path)) {
68                                 s++;
69                         }
70                         if ((d != path) && (*s != '\0')) {
71                                 /* We only care about non-leading or trailing '/' or '\\' */
72                                 *d++ = '/';
73                         }
74
75                         start_of_name_component = True;
76                         /* New component. */
77                         *p_last_component_contains_wcard = False;
78                         continue;
79                 }
80
81                 if (start_of_name_component) {
82                         if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
83                                 /* Uh oh - "/../" or "\\..\\"  or "/..\0" or "\\..\0" ! */
84
85                                 /*
86                                  * No mb char starts with '.' so we're safe checking the directory separator here.
87                                  */
88
89                                 /* If  we just added a '/' - delete it */
90                                 if ((d > path) && (*(d-1) == '/')) {
91                                         *(d-1) = '\0';
92                                         d--;
93                                 }
94
95                                 /* Are we at the start ? Can't go back further if so. */
96                                 if (d <= path) {
97                                         ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
98                                         break;
99                                 }
100                                 /* Go back one level... */
101                                 /* We know this is safe as '/' cannot be part of a mb sequence. */
102                                 /* NOTE - if this assumption is invalid we are not in good shape... */
103                                 /* Decrement d first as d points to the *next* char to write into. */
104                                 for (d--; d > path; d--) {
105                                         if (*d == '/')
106                                                 break;
107                                 }
108                                 s += 2; /* Else go past the .. */
109                                 /* We're still at the start of a name component, just the previous one. */
110                                 continue;
111
112                         } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
113                                 if (posix_path) {
114                                         /* Eat the '.' */
115                                         s++;
116                                         continue;
117                                 }
118                         }
119
120                 }
121
122                 if (!(*s & 0x80)) {
123                         if (!posix_path) {
124                                 if (*s <= 0x1f) {
125                                         return NT_STATUS_OBJECT_NAME_INVALID;
126                                 }
127                                 switch (*s) {
128                                         case '*':
129                                         case '?':
130                                         case '<':
131                                         case '>':
132                                         case '"':
133                                                 *p_last_component_contains_wcard = True;
134                                                 break;
135                                         default:
136                                                 break;
137                                 }
138                         }
139                         *d++ = *s++;
140                 } else {
141                         size_t siz;
142                         /* Get the size of the next MB character. */
143                         next_codepoint(s,&siz);
144                         switch(siz) {
145                                 case 5:
146                                         *d++ = *s++;
147                                         /*fall through*/
148                                 case 4:
149                                         *d++ = *s++;
150                                         /*fall through*/
151                                 case 3:
152                                         *d++ = *s++;
153                                         /*fall through*/
154                                 case 2:
155                                         *d++ = *s++;
156                                         /*fall through*/
157                                 case 1:
158                                         *d++ = *s++;
159                                         break;
160                                 default:
161                                         DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
162                                         *d = '\0';
163                                         return NT_STATUS_INVALID_PARAMETER;
164                         }
165                 }
166                 start_of_name_component = False;
167         }
168
169         *d = '\0';
170         return ret;
171 }
172
173 /****************************************************************************
174  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
175  No wildcards allowed.
176 ****************************************************************************/
177
178 NTSTATUS check_path_syntax(char *path)
179 {
180         bool ignore;
181         return check_path_syntax_internal(path, False, &ignore);
182 }
183
184 /****************************************************************************
185  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
186  Wildcards allowed - p_contains_wcard returns true if the last component contained
187  a wildcard.
188 ****************************************************************************/
189
190 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
191 {
192         return check_path_syntax_internal(path, False, p_contains_wcard);
193 }
194
195 /****************************************************************************
196  Check the path for a POSIX client.
197  We're assuming here that '/' is not the second byte in any multibyte char
198  set (a safe assumption).
199 ****************************************************************************/
200
201 NTSTATUS check_path_syntax_posix(char *path)
202 {
203         bool ignore;
204         return check_path_syntax_internal(path, True, &ignore);
205 }
206
207 /****************************************************************************
208  Pull a string and check the path allowing a wilcard - provide for error return.
209 ****************************************************************************/
210
211 size_t srvstr_get_path_wcard(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,NULL,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(req,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,
3539                         SMB_SECONDARY_WAIT, get_srv_read_error()) == -1) {
3540                 exit_server_cleanly("secondary writebraw failed");
3541         }
3542
3543         /*
3544          * Even though this is not an smb message,
3545          * smb_len returns the generic length of a packet.
3546          */
3547
3548         numtowrite = smb_len(buf);
3549
3550         /* Set up outbuf to return the correct size */
3551         reply_outbuf(req, 1, 0);
3552
3553         if (numtowrite != 0) {
3554
3555                 if (numtowrite > 0xFFFF) {
3556                         DEBUG(0,("reply_writebraw: Oversize secondary write "
3557                                 "raw requested (%u). Terminating\n",
3558                                 (unsigned int)numtowrite ));
3559                         exit_server_cleanly("secondary writebraw failed");
3560                 }
3561
3562                 if (tcount > nwritten+numtowrite) {
3563                         DEBUG(3,("reply_writebraw: Client overestimated the "
3564                                 "write %d %d %d\n",
3565                                 (int)tcount,(int)nwritten,(int)numtowrite));
3566                 }
3567
3568                 if (read_data(smbd_server_fd(), buf+4, numtowrite,get_srv_read_error())
3569                                         != numtowrite ) {
3570                         DEBUG(0,("reply_writebraw: Oversize secondary write "
3571                                 "raw read failed (%s). Terminating\n",
3572                                 strerror(errno) ));
3573                         exit_server_cleanly("secondary writebraw failed");
3574                 }
3575
3576                 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3577                 if (nwritten == -1) {
3578                         TALLOC_FREE(buf);
3579                         reply_unixerror(req, ERRHRD, ERRdiskfull);
3580                         error_to_writebrawerr(req);
3581                         END_PROFILE(SMBwritebraw);
3582                         return;
3583                 }
3584
3585                 if (nwritten < (ssize_t)numtowrite) {
3586                         SCVAL(req->outbuf,smb_rcls,ERRHRD);
3587                         SSVAL(req->outbuf,smb_err,ERRdiskfull);
3588                 }
3589
3590                 if (nwritten > 0) {
3591                         total_written += nwritten;
3592                 }
3593         }
3594
3595         TALLOC_FREE(buf);
3596         SSVAL(req->outbuf,smb_vwv0,total_written);
3597
3598         status = sync_file(conn, fsp, write_through);
3599         if (!NT_STATUS_IS_OK(status)) {
3600                 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3601                         fsp->fsp_name, nt_errstr(status) ));
3602                 reply_nterror(req, status);
3603                 error_to_writebrawerr(req);
3604                 END_PROFILE(SMBwritebraw);
3605                 return;
3606         }
3607
3608         DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3609                 "wrote=%d\n",
3610                 fsp->fnum, (double)startpos, (int)numtowrite,
3611                 (int)total_written));
3612
3613         /* We won't return a status if write through is not selected - this
3614          * follows what WfWg does */
3615         END_PROFILE(SMBwritebraw);
3616
3617         if (!write_through && total_written==tcount) {
3618
3619 #if RABBIT_PELLET_FIX
3620                 /*
3621                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3622                  * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3623                  * JRA.
3624                  */
3625                 if (!send_keepalive(smbd_server_fd())) {
3626                         exit_server_cleanly("reply_writebraw: send of "
3627                                 "keepalive failed");
3628                 }
3629 #endif
3630                 TALLOC_FREE(req->outbuf);
3631         }
3632         return;
3633 }
3634
3635 #undef DBGC_CLASS
3636 #define DBGC_CLASS DBGC_LOCKING
3637
3638 /****************************************************************************
3639  Reply to a writeunlock (core+).
3640 ****************************************************************************/
3641
3642 void reply_writeunlock(connection_struct *conn, struct smb_request *req)
3643 {
3644         ssize_t nwritten = -1;
3645         size_t numtowrite;
3646         SMB_OFF_T startpos;
3647         char *data;
3648         NTSTATUS status = NT_STATUS_OK;
3649         files_struct *fsp;
3650
3651         START_PROFILE(SMBwriteunlock);
3652
3653         if (req->wct < 5) {
3654                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3655                 END_PROFILE(SMBwriteunlock);
3656                 return;
3657         }
3658         
3659         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3660
3661         if (!check_fsp(conn, req, fsp, &current_user)) {
3662                 END_PROFILE(SMBwriteunlock);
3663                 return;
3664         }
3665
3666         if (!CHECK_WRITE(fsp)) {
3667                 reply_doserror(req, ERRDOS,ERRbadaccess);
3668                 END_PROFILE(SMBwriteunlock);
3669                 return;
3670         }
3671
3672         numtowrite = SVAL(req->inbuf,smb_vwv1);
3673         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
3674         data = smb_buf(req->inbuf) + 3;
3675   
3676         if (numtowrite
3677             && is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
3678                          (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3679                 reply_doserror(req, ERRDOS, ERRlock);
3680                 END_PROFILE(SMBwriteunlock);
3681                 return;
3682         }
3683
3684         /* The special X/Open SMB protocol handling of
3685            zero length writes is *NOT* done for
3686            this call */
3687         if(numtowrite == 0) {
3688                 nwritten = 0;
3689         } else {
3690                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3691         }
3692   
3693         status = sync_file(conn, fsp, False /* write through */);
3694         if (!NT_STATUS_IS_OK(status)) {
3695                 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3696                         fsp->fsp_name, nt_errstr(status) ));
3697                 reply_nterror(req, status);
3698                 END_PROFILE(SMBwriteunlock);
3699                 return;
3700         }
3701
3702         if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
3703                 reply_unixerror(req, ERRHRD, ERRdiskfull);
3704                 END_PROFILE(SMBwriteunlock);
3705                 return;
3706         }
3707
3708         if (numtowrite) {
3709                 status = do_unlock(smbd_messaging_context(),
3710                                 fsp,
3711                                 req->smbpid,
3712                                 (SMB_BIG_UINT)numtowrite, 
3713                                 (SMB_BIG_UINT)startpos,
3714                                 WINDOWS_LOCK);
3715
3716                 if (NT_STATUS_V(status)) {
3717                         reply_nterror(req, status);
3718                         END_PROFILE(SMBwriteunlock);
3719                         return;
3720                 }
3721         }
3722
3723         reply_outbuf(req, 1, 0);
3724         
3725         SSVAL(req->outbuf,smb_vwv0,nwritten);
3726         
3727         DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3728                  fsp->fnum, (int)numtowrite, (int)nwritten));
3729         
3730         END_PROFILE(SMBwriteunlock);
3731         return;
3732 }
3733
3734 #undef DBGC_CLASS
3735 #define DBGC_CLASS DBGC_ALL
3736
3737 /****************************************************************************
3738  Reply to a write.
3739 ****************************************************************************/
3740
3741 void reply_write(connection_struct *conn, struct smb_request *req)
3742 {
3743         size_t numtowrite;
3744         ssize_t nwritten = -1;
3745         SMB_OFF_T startpos;
3746         char *data;
3747         files_struct *fsp;
3748         NTSTATUS status;
3749
3750         START_PROFILE(SMBwrite);
3751
3752         if (req->wct < 5) {
3753                 END_PROFILE(SMBwrite);
3754                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3755                 return;
3756         }
3757
3758         /* If it's an IPC, pass off the pipe handler. */
3759         if (IS_IPC(conn)) {
3760                 reply_pipe_write(req);
3761                 END_PROFILE(SMBwrite);
3762                 return;
3763         }
3764
3765         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3766
3767         if (!check_fsp(conn, req, fsp, &current_user)) {
3768                 END_PROFILE(SMBwrite);
3769                 return;
3770         }
3771
3772         if (!CHECK_WRITE(fsp)) {
3773                 reply_doserror(req, ERRDOS, ERRbadaccess);
3774                 END_PROFILE(SMBwrite);
3775                 return;
3776         }
3777
3778         numtowrite = SVAL(req->inbuf,smb_vwv1);
3779         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
3780         data = smb_buf(req->inbuf) + 3;
3781   
3782         if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
3783                       (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3784                 reply_doserror(req, ERRDOS, ERRlock);
3785                 END_PROFILE(SMBwrite);
3786                 return;
3787         }
3788
3789         /*
3790          * X/Open SMB protocol says that if smb_vwv1 is
3791          * zero then the file size should be extended or
3792          * truncated to the size given in smb_vwv[2-3].
3793          */
3794
3795         if(numtowrite == 0) {
3796                 /*
3797                  * This is actually an allocate call, and set EOF. JRA.
3798                  */
3799                 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3800                 if (nwritten < 0) {
3801                         reply_nterror(req, NT_STATUS_DISK_FULL);
3802                         END_PROFILE(SMBwrite);
3803                         return;
3804                 }
3805                 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3806                 if (nwritten < 0) {
3807                         reply_nterror(req, NT_STATUS_DISK_FULL);
3808                         END_PROFILE(SMBwrite);
3809                         return;
3810                 }
3811         } else
3812                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3813   
3814         status = sync_file(conn, fsp, False);
3815         if (!NT_STATUS_IS_OK(status)) {
3816                 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3817                         fsp->fsp_name, nt_errstr(status) ));
3818                 reply_nterror(req, status);
3819                 END_PROFILE(SMBwrite);
3820                 return;
3821         }
3822
3823         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3824                 reply_unixerror(req, ERRHRD, ERRdiskfull);
3825                 END_PROFILE(SMBwrite);
3826                 return;
3827         }
3828
3829         reply_outbuf(req, 1, 0);
3830   
3831         SSVAL(req->outbuf,smb_vwv0,nwritten);
3832
3833         if (nwritten < (ssize_t)numtowrite) {
3834                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3835                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3836         }
3837   
3838         DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3839
3840         END_PROFILE(SMBwrite);
3841         return;
3842 }
3843
3844 /****************************************************************************
3845  Ensure a buffer is a valid writeX for recvfile purposes.
3846 ****************************************************************************/
3847
3848 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
3849                                                 (2*14) + /* word count (including bcc) */ \
3850                                                 1 /* pad byte */)
3851
3852 bool is_valid_writeX_buffer(const char *inbuf)
3853 {
3854         size_t numtowrite;
3855         connection_struct *conn = NULL;
3856         unsigned int doff = 0;
3857         size_t len = smb_len_large(inbuf);
3858
3859         if (CVAL(inbuf,smb_com) != SMBwriteX) {
3860                 return false;
3861         }
3862
3863         if (CVAL(inbuf,smb_vwv0) != 0xFF ||
3864                         CVAL(inbuf,smb_wct) != 14) {
3865                 DEBUG(10,("is_valid_writeX_buffer: chained or "
3866                         "invalid word length.\n"));
3867                 return false;
3868         }
3869
3870         conn = conn_find(SVAL(inbuf, smb_tid));
3871         if (conn == NULL) {
3872                 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
3873                 return false;
3874         }
3875         if (IS_IPC(conn)) {
3876                 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
3877                 return false;
3878         }
3879         doff = SVAL(inbuf,smb_vwv11);
3880
3881         numtowrite = SVAL(inbuf,smb_vwv10);
3882
3883         if (len > doff && len - doff > 0xFFFF) {
3884                 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
3885         }
3886
3887         if (numtowrite == 0) {
3888                 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
3889                 return false;
3890         }
3891
3892         /* Ensure the sizes match up. */
3893         if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
3894                 /* no pad byte...old smbclient :-( */
3895                 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
3896                         (unsigned int)doff,
3897                         (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
3898                 return false;
3899         }
3900
3901         if (len - doff != numtowrite) {
3902                 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
3903                         "len = %u, doff = %u, numtowrite = %u\n",
3904                         (unsigned int)len,
3905                         (unsigned int)doff,
3906                         (unsigned int)numtowrite ));
3907                 return false;
3908         }
3909
3910         DEBUG(10,("is_valid_writeX_buffer: true "
3911                 "len = %u, doff = %u, numtowrite = %u\n",
3912                 (unsigned int)len,
3913                 (unsigned int)doff,
3914                 (unsigned int)numtowrite ));
3915
3916         return true;
3917 }
3918
3919 /****************************************************************************
3920  Reply to a write and X.
3921 ****************************************************************************/
3922
3923 void reply_write_and_X(connection_struct *conn, struct smb_request *req)
3924 {
3925         files_struct *fsp;
3926         SMB_OFF_T startpos;
3927         size_t numtowrite;
3928         bool write_through;
3929         ssize_t nwritten;
3930         unsigned int smb_doff;
3931         unsigned int smblen;
3932         char *data;
3933         NTSTATUS status;
3934
3935         START_PROFILE(SMBwriteX);
3936
3937         if ((req->wct != 12) && (req->wct != 14)) {
3938                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3939                 END_PROFILE(SMBwriteX);
3940                 return;
3941         }
3942
3943         numtowrite = SVAL(req->inbuf,smb_vwv10);
3944         smb_doff = SVAL(req->inbuf,smb_vwv11);
3945         smblen = smb_len(req->inbuf);
3946
3947         if (req->unread_bytes > 0xFFFF ||
3948                         (smblen > smb_doff &&
3949                                 smblen - smb_doff > 0xFFFF)) {
3950                 numtowrite |= (((size_t)SVAL(req->inbuf,smb_vwv9))<<16);
3951         }
3952
3953         if (req->unread_bytes) {
3954                 /* Can't do a recvfile write on IPC$ */
3955                 if (IS_IPC(conn)) {
3956                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3957                         END_PROFILE(SMBwriteX);
3958                         return;
3959                 }
3960                 if (numtowrite != req->unread_bytes) {
3961                         reply_doserror(req, ERRDOS, ERRbadmem);
3962                         END_PROFILE(SMBwriteX);
3963                         return;
3964                 }
3965         } else {
3966                 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
3967                                 smb_doff + numtowrite > smblen) {
3968                         reply_doserror(req, ERRDOS, ERRbadmem);
3969                         END_PROFILE(SMBwriteX);
3970                         return;
3971                 }
3972         }
3973
3974         /* If it's an IPC, pass off the pipe handler. */
3975         if (IS_IPC(conn)) {
3976                 if (req->unread_bytes) {
3977                         reply_doserror(req, ERRDOS, ERRbadmem);
3978                         END_PROFILE(SMBwriteX);
3979                         return;
3980                 }
3981                 reply_pipe_write_and_X(req);
3982                 END_PROFILE(SMBwriteX);
3983                 return;
3984         }
3985
3986         fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
3987         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
3988         write_through = BITSETW(req->inbuf+smb_vwv7,0);
3989
3990         if (!check_fsp(conn, req, fsp, &current_user)) {
3991                 END_PROFILE(SMBwriteX);
3992                 return;
3993         }
3994
3995         if (!CHECK_WRITE(fsp)) {
3996                 reply_doserror(req, ERRDOS, ERRbadaccess);
3997                 END_PROFILE(SMBwriteX);
3998                 return;
3999         }
4000
4001         data = smb_base(req->inbuf) + smb_doff;
4002
4003         if(req->wct == 14) {
4004 #ifdef LARGE_SMB_OFF_T
4005                 /*
4006                  * This is a large offset (64 bit) write.
4007                  */
4008                 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv12)) << 32);
4009
4010 #else /* !LARGE_SMB_OFF_T */
4011
4012                 /*
4013                  * Ensure we haven't been sent a >32 bit offset.
4014                  */
4015
4016                 if(IVAL(req->inbuf,smb_vwv12) != 0) {
4017                         DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4018                                  "used and we don't support 64 bit offsets.\n",
4019                                  (unsigned int)IVAL(req->inbuf,smb_vwv12) ));
4020                         reply_doserror(req, ERRDOS, ERRbadaccess);
4021                         END_PROFILE(SMBwriteX);
4022                         return;
4023                 }
4024
4025 #endif /* LARGE_SMB_OFF_T */
4026         }
4027
4028         if (is_locked(fsp,(uint32)req->smbpid,
4029                       (SMB_BIG_UINT)numtowrite,
4030                       (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
4031                 reply_doserror(req, ERRDOS, ERRlock);
4032                 END_PROFILE(SMBwriteX);
4033                 return;
4034         }
4035
4036         /* X/Open SMB protocol says that, unlike SMBwrite
4037         if the length is zero then NO truncation is
4038         done, just a write of zero. To truncate a file,
4039         use SMBwrite. */
4040
4041         if(numtowrite == 0) {
4042                 nwritten = 0;
4043         } else {
4044
4045                 if (req->unread_bytes == 0 &&
4046                                 schedule_aio_write_and_X(conn, req, fsp, data,
4047                                                         startpos, numtowrite)) {
4048                         END_PROFILE(SMBwriteX);
4049                         return;
4050                 }
4051
4052                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4053         }
4054
4055         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4056                 reply_unixerror(req, ERRHRD, ERRdiskfull);
4057                 END_PROFILE(SMBwriteX);
4058                 return;
4059         }
4060
4061         reply_outbuf(req, 6, 0);
4062         SSVAL(req->outbuf,smb_vwv2,nwritten);
4063         SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4064
4065         if (nwritten < (ssize_t)numtowrite) {
4066                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4067                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4068         }
4069
4070         DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4071                 fsp->fnum, (int)numtowrite, (int)nwritten));
4072
4073         status = sync_file(conn, fsp, write_through);
4074         if (!NT_STATUS_IS_OK(status)) {
4075                 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4076                         fsp->fsp_name, nt_errstr(status) ));
4077                 reply_nterror(req, status);
4078                 END_PROFILE(SMBwriteX);
4079                 return;
4080         }
4081
4082         END_PROFILE(SMBwriteX);
4083         chain_reply(req);
4084         return;
4085 }
4086
4087 /****************************************************************************
4088  Reply to a lseek.
4089 ****************************************************************************/
4090
4091 void reply_lseek(connection_struct *conn, struct smb_request *req)
4092 {
4093         SMB_OFF_T startpos;
4094         SMB_OFF_T res= -1;
4095         int mode,umode;
4096         files_struct *fsp;
4097
4098         START_PROFILE(SMBlseek);
4099
4100         if (req->wct < 4) {
4101                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4102                 END_PROFILE(SMBlseek);
4103                 return;
4104         }
4105
4106         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4107
4108         if (!check_fsp(conn, req, fsp, &current_user)) {
4109                 return;
4110         }
4111
4112         flush_write_cache(fsp, SEEK_FLUSH);
4113
4114         mode = SVAL(req->inbuf,smb_vwv1) & 3;
4115         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4116         startpos = (SMB_OFF_T)IVALS(req->inbuf,smb_vwv2);
4117
4118         switch (mode) {
4119                 case 0:
4120                         umode = SEEK_SET;
4121                         res = startpos;
4122                         break;
4123                 case 1:
4124                         umode = SEEK_CUR;
4125                         res = fsp->fh->pos + startpos;
4126                         break;
4127                 case 2:
4128                         umode = SEEK_END;
4129                         break;
4130                 default:
4131                         umode = SEEK_SET;
4132                         res = startpos;
4133                         break;
4134         }
4135
4136         if (umode == SEEK_END) {
4137                 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
4138                         if(errno == EINVAL) {
4139                                 SMB_OFF_T current_pos = startpos;
4140                                 SMB_STRUCT_STAT sbuf;
4141
4142                                 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
4143                                         reply_unixerror(req, ERRDOS,
4144                                                         ERRnoaccess);
4145                                         END_PROFILE(SMBlseek);
4146                                         return;
4147                                 }
4148
4149                                 current_pos += sbuf.st_size;
4150                                 if(current_pos < 0)
4151                                         res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
4152                         }
4153                 }
4154
4155                 if(res == -1) {
4156                         reply_unixerror(req, ERRDOS, ERRnoaccess);
4157                         END_PROFILE(SMBlseek);
4158                         return;
4159                 }
4160         }
4161
4162         fsp->fh->pos = res;
4163
4164         reply_outbuf(req, 2, 0);
4165         SIVAL(req->outbuf,smb_vwv0,res);
4166   
4167         DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4168                 fsp->fnum, (double)startpos, (double)res, mode));
4169
4170         END_PROFILE(SMBlseek);
4171         return;
4172 }
4173
4174 /****************************************************************************
4175  Reply to a flush.
4176 ****************************************************************************/
4177
4178 void reply_flush(connection_struct *conn, struct smb_request *req)
4179 {
4180         uint16 fnum;
4181         files_struct *fsp;
4182
4183         START_PROFILE(SMBflush);
4184
4185         if (req->wct < 1) {
4186                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4187                 return;
4188         }
4189
4190         fnum = SVAL(req->inbuf,smb_vwv0);
4191         fsp = file_fsp(fnum);
4192
4193         if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp, &current_user)) {
4194                 return;
4195         }
4196         
4197         if (!fsp) {
4198                 file_sync_all(conn);
4199         } else {
4200                 NTSTATUS status = sync_file(conn, fsp, True);
4201                 if (!NT_STATUS_IS_OK(status)) {
4202                         DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4203                                 fsp->fsp_name, nt_errstr(status) ));
4204                         reply_nterror(req, status);
4205                         END_PROFILE(SMBflush);
4206                         return;
4207                 }
4208         }
4209         
4210         reply_outbuf(req, 0, 0);
4211
4212         DEBUG(3,("flush\n"));
4213         END_PROFILE(SMBflush);
4214         return;
4215 }
4216
4217 /****************************************************************************
4218  Reply to a exit.
4219  conn POINTER CAN BE NULL HERE !
4220 ****************************************************************************/
4221
4222 void reply_exit(connection_struct *conn, struct smb_request *req)
4223 {
4224         START_PROFILE(SMBexit);
4225
4226         file_close_pid(req->smbpid, req->vuid);
4227
4228         reply_outbuf(req, 0, 0);
4229
4230         DEBUG(3,("exit\n"));
4231
4232         END_PROFILE(SMBexit);
4233         return;
4234 }
4235
4236 /****************************************************************************
4237  Reply to a close - has to deal with closing a directory opened by NT SMB's.
4238 ****************************************************************************/
4239
4240 void reply_close(connection_struct *conn, struct smb_request *req)
4241 {
4242         NTSTATUS status = NT_STATUS_OK;
4243         files_struct *fsp = NULL;
4244         START_PROFILE(SMBclose);
4245
4246         if (req->wct < 3) {
4247                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4248                 END_PROFILE(SMBclose);
4249                 return;
4250         }
4251
4252         /* If it's an IPC, pass off to the pipe handler. */
4253         if (IS_IPC(conn)) {
4254                 reply_pipe_close(conn, req);
4255                 END_PROFILE(SMBclose);
4256                 return;
4257         }
4258
4259         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4260
4261         /*
4262          * We can only use CHECK_FSP if we know it's not a directory.
4263          */
4264
4265         if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
4266                 reply_doserror(req, ERRDOS, ERRbadfid);
4267                 END_PROFILE(SMBclose);
4268                 return;
4269         }
4270
4271         if(fsp->is_directory) {
4272                 /*
4273                  * Special case - close NT SMB directory handle.
4274                  */
4275                 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4276                 status = close_file(fsp,NORMAL_CLOSE);
4277         } else {
4278                 /*
4279                  * Close ordinary file.
4280                  */
4281
4282                 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4283                          fsp->fh->fd, fsp->fnum,
4284                          conn->num_files_open));
4285  
4286                 /*
4287                  * Take care of any time sent in the close.
4288                  */
4289
4290                 fsp_set_pending_modtime(fsp, convert_time_t_to_timespec(
4291                                                 srv_make_unix_date3(
4292                                                         req->inbuf+smb_vwv1)));
4293
4294                 /*
4295                  * close_file() returns the unix errno if an error
4296                  * was detected on close - normally this is due to
4297                  * a disk full error. If not then it was probably an I/O error.
4298                  */
4299  
4300                 status = close_file(fsp,NORMAL_CLOSE);
4301         }  
4302
4303         if (!NT_STATUS_IS_OK(status)) {
4304                 reply_nterror(req, status);
4305                 END_PROFILE(SMBclose);
4306                 return;
4307         }
4308
4309         reply_outbuf(req, 0, 0);
4310         END_PROFILE(SMBclose);
4311         return;
4312 }
4313
4314 /****************************************************************************
4315  Reply to a writeclose (Core+ protocol).
4316 ****************************************************************************/
4317
4318 void reply_writeclose(connection_struct *conn, struct smb_request *req)
4319 {
4320         size_t numtowrite;
4321         ssize_t nwritten = -1;
4322         NTSTATUS close_status = NT_STATUS_OK;
4323         SMB_OFF_T startpos;
4324         char *data;
4325         struct timespec mtime;
4326         files_struct *fsp;
4327
4328         START_PROFILE(SMBwriteclose);
4329
4330         if (req->wct < 6) {
4331                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4332                 END_PROFILE(SMBwriteclose);
4333                 return;
4334         }
4335
4336         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4337
4338         if (!check_fsp(conn, req, fsp, &current_user)) {
4339                 END_PROFILE(SMBwriteclose);
4340                 return;
4341         }
4342         if (!CHECK_WRITE(fsp)) {
4343                 reply_doserror(req, ERRDOS,ERRbadaccess);
4344                 END_PROFILE(SMBwriteclose);
4345                 return;
4346         }
4347
4348         numtowrite = SVAL(req->inbuf,smb_vwv1);
4349         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
4350         mtime = convert_time_t_to_timespec(srv_make_unix_date3(
4351                                                    req->inbuf+smb_vwv4));
4352         data = smb_buf(req->inbuf) + 1;
4353   
4354         if (numtowrite
4355             && is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
4356                          (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
4357                 reply_doserror(req, ERRDOS,ERRlock);
4358                 END_PROFILE(SMBwriteclose);
4359                 return;
4360         }
4361   
4362         nwritten = write_file(req,fsp,data,startpos,numtowrite);
4363
4364         set_filetime(conn, fsp->fsp_name, mtime);
4365   
4366         /*
4367          * More insanity. W2K only closes the file if writelen > 0.
4368          * JRA.
4369          */
4370
4371         if (numtowrite) {
4372                 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4373                         fsp->fsp_name ));
4374                 close_status = close_file(fsp,NORMAL_CLOSE);
4375         }
4376
4377         DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4378                  fsp->fnum, (int)numtowrite, (int)nwritten,
4379                  conn->num_files_open));
4380   
4381         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4382                 reply_doserror(req, ERRHRD, ERRdiskfull);
4383                 END_PROFILE(SMBwriteclose);
4384                 return;
4385         }
4386  
4387         if(!NT_STATUS_IS_OK(close_status)) {
4388                 reply_nterror(req, close_status);
4389                 END_PROFILE(SMBwriteclose);
4390                 return;
4391         }
4392
4393         reply_outbuf(req, 1, 0);
4394   
4395         SSVAL(req->outbuf,smb_vwv0,nwritten);
4396         END_PROFILE(SMBwriteclose);
4397         return;
4398 }
4399
4400 #undef DBGC_CLASS
4401 #define DBGC_CLASS DBGC_LOCKING
4402
4403 /****************************************************************************
4404  Reply to a lock.
4405 ****************************************************************************/
4406
4407 void reply_lock(connection_struct *conn, struct smb_request *req)
4408 {
4409         SMB_BIG_UINT count,offset;
4410         NTSTATUS status;
4411         files_struct *fsp;
4412         struct byte_range_lock *br_lck = NULL;
4413
4414         START_PROFILE(SMBlock);
4415
4416         if (req->wct < 5) {
4417                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4418                 END_PROFILE(SMBlock);
4419                 return;
4420         }
4421
4422         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4423
4424         if (!check_fsp(conn, req, fsp, &current_user)) {
4425                 END_PROFILE(SMBlock);
4426                 return;
4427         }
4428
4429         release_level_2_oplocks_on_change(fsp);
4430
4431         count = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv1);
4432         offset = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv3);
4433
4434         DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4435                  fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4436
4437         br_lck = do_lock(smbd_messaging_context(),
4438                         fsp,
4439                         req->smbpid,
4440                         count,
4441                         offset,
4442                         WRITE_LOCK,
4443                         WINDOWS_LOCK,
4444                         False, /* Non-blocking lock. */
4445                         &status,
4446                         NULL);
4447
4448         TALLOC_FREE(br_lck);
4449
4450         if (NT_STATUS_V(status)) {
4451                 reply_nterror(req, status);
4452                 END_PROFILE(SMBlock);
4453                 return;
4454         }
4455
4456         reply_outbuf(req, 0, 0);
4457
4458         END_PROFILE(SMBlock);
4459         return;
4460 }
4461
4462 /****************************************************************************
4463  Reply to a unlock.
4464 ****************************************************************************/
4465
4466 void reply_unlock(connection_struct *conn, struct smb_request *req)
4467 {
4468         SMB_BIG_UINT count,offset;
4469         NTSTATUS status;
4470         files_struct *fsp;
4471
4472         START_PROFILE(SMBunlock);
4473
4474         if (req->wct < 5) {
4475                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4476                 END_PROFILE(SMBunlock);
4477                 return;
4478         }
4479
4480         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4481
4482         if (!check_fsp(conn, req, fsp, &current_user)) {
4483                 END_PROFILE(SMBunlock);
4484                 return;
4485         }
4486         
4487         count = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv1);
4488         offset = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv3);
4489         
4490         status = do_unlock(smbd_messaging_context(),
4491                         fsp,
4492                         req->smbpid,
4493                         count,
4494                         offset,
4495                         WINDOWS_LOCK);
4496
4497         if (NT_STATUS_V(status)) {
4498                 reply_nterror(req, status);
4499                 END_PROFILE(SMBunlock);
4500                 return;
4501         }
4502
4503         DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4504                     fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4505
4506         reply_outbuf(req, 0, 0);
4507
4508         END_PROFILE(SMBunlock);
4509         return;
4510 }
4511
4512 #undef DBGC_CLASS
4513 #define DBGC_CLASS DBGC_ALL
4514
4515 /****************************************************************************
4516  Reply to a tdis.
4517  conn POINTER CAN BE NULL HERE !
4518 ****************************************************************************/
4519
4520 void reply_tdis(connection_struct *conn, struct smb_request *req)
4521 {
4522         START_PROFILE(SMBtdis);
4523
4524         if (!conn) {
4525                 DEBUG(4,("Invalid connection in tdis\n"));
4526                 reply_doserror(req, ERRSRV, ERRinvnid);
4527                 END_PROFILE(SMBtdis);
4528                 return;
4529         }
4530
4531         conn->used = False;
4532
4533         close_cnum(conn,req->vuid);
4534
4535         reply_outbuf(req, 0, 0);
4536         END_PROFILE(SMBtdis);
4537         return;
4538 }
4539
4540 /****************************************************************************
4541  Reply to a echo.
4542  conn POINTER CAN BE NULL HERE !
4543 ****************************************************************************/
4544
4545 void reply_echo(connection_struct *conn, struct smb_request *req)
4546 {
4547         int smb_reverb;
4548         int seq_num;
4549         unsigned int data_len = smb_buflen(req->inbuf);
4550
4551         START_PROFILE(SMBecho);
4552
4553         if (req->wct < 1) {
4554                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4555                 END_PROFILE(SMBecho);
4556                 return;
4557         }
4558
4559         if (data_len > BUFFER_SIZE) {
4560                 DEBUG(0,("reply_echo: data_len too large.\n"));
4561                 reply_nterror(req, NT_STATUS_INSUFFICIENT_RESOURCES);
4562                 END_PROFILE(SMBecho);
4563                 return;
4564         }
4565
4566         smb_reverb = SVAL(req->inbuf,smb_vwv0);
4567
4568         reply_outbuf(req, 1, data_len);
4569
4570         /* copy any incoming data back out */
4571         if (data_len > 0) {
4572                 memcpy(smb_buf(req->outbuf),smb_buf(req->inbuf),data_len);
4573         }
4574
4575         if (smb_reverb > 100) {
4576                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4577                 smb_reverb = 100;
4578         }
4579
4580         for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
4581                 SSVAL(req->outbuf,smb_vwv0,seq_num);
4582
4583                 show_msg((char *)req->outbuf);
4584                 if (!send_smb(smbd_server_fd(),(char *)req->outbuf))
4585                         exit_server_cleanly("reply_echo: send_smb failed.");
4586         }
4587
4588         DEBUG(3,("echo %d times\n", smb_reverb));
4589
4590         TALLOC_FREE(req->outbuf);
4591
4592         smb_echo_count++;
4593
4594         END_PROFILE(SMBecho);
4595         return;
4596 }
4597
4598 /****************************************************************************
4599  Reply to a printopen.
4600 ****************************************************************************/
4601
4602 void reply_printopen(connection_struct *conn, struct smb_request *req)
4603 {
4604         files_struct *fsp;
4605         NTSTATUS status;
4606         
4607         START_PROFILE(SMBsplopen);
4608
4609         if (req->wct < 2) {
4610                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4611                 END_PROFILE(SMBsplopen);
4612                 return;
4613         }
4614
4615         if (!CAN_PRINT(conn)) {
4616                 reply_doserror(req, ERRDOS, ERRnoaccess);
4617                 END_PROFILE(SMBsplopen);
4618                 return;
4619         }
4620
4621         /* Open for exclusive use, write only. */
4622         status = print_fsp_open(conn, NULL, &fsp);
4623
4624         if (!NT_STATUS_IS_OK(status)) {
4625                 reply_nterror(req, status);
4626                 END_PROFILE(SMBsplopen);
4627                 return;
4628         }
4629
4630         reply_outbuf(req, 1, 0);
4631         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4632   
4633         DEBUG(3,("openprint fd=%d fnum=%d\n",
4634                  fsp->fh->fd, fsp->fnum));
4635
4636         END_PROFILE(SMBsplopen);
4637         return;
4638 }
4639
4640 /****************************************************************************
4641  Reply to a printclose.
4642 ****************************************************************************/
4643
4644 void reply_printclose(connection_struct *conn, struct smb_request *req)
4645 {
4646         files_struct *fsp;
4647         NTSTATUS status;
4648
4649         START_PROFILE(SMBsplclose);
4650
4651         if (req->wct < 3) {
4652                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4653                 END_PROFILE(SMBsplclose);
4654                 return;
4655         }
4656
4657         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4658
4659         if (!check_fsp(conn, req, fsp, &current_user)) {
4660                 END_PROFILE(SMBsplclose);
4661                 return;
4662         }
4663
4664         if (!CAN_PRINT(conn)) {
4665                 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
4666                 END_PROFILE(SMBsplclose);
4667                 return;
4668         }
4669   
4670         DEBUG(3,("printclose fd=%d fnum=%d\n",
4671                  fsp->fh->fd,fsp->fnum));
4672   
4673         status = close_file(fsp,NORMAL_CLOSE);
4674
4675         if(!NT_STATUS_IS_OK(status)) {
4676                 reply_nterror(req, status);
4677                 END_PROFILE(SMBsplclose);
4678                 return;
4679         }
4680
4681         END_PROFILE(SMBsplclose);
4682         return;
4683 }
4684
4685 /****************************************************************************
4686  Reply to a printqueue.
4687 ****************************************************************************/
4688
4689 void reply_printqueue(connection_struct *conn, struct smb_request *req)
4690 {
4691         int max_count;
4692         int start_index;
4693
4694         START_PROFILE(SMBsplretq);
4695
4696         if (req->wct < 2) {
4697                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4698                 END_PROFILE(SMBsplretq);
4699                 return;
4700         }
4701
4702         max_count = SVAL(req->inbuf,smb_vwv0);
4703         start_index = SVAL(req->inbuf,smb_vwv1);
4704
4705         /* we used to allow the client to get the cnum wrong, but that
4706            is really quite gross and only worked when there was only
4707            one printer - I think we should now only accept it if they
4708            get it right (tridge) */
4709         if (!CAN_PRINT(conn)) {
4710                 reply_doserror(req, ERRDOS, ERRnoaccess);
4711                 END_PROFILE(SMBsplretq);
4712                 return;
4713         }
4714
4715         reply_outbuf(req, 2, 3);
4716         SSVAL(req->outbuf,smb_vwv0,0);
4717         SSVAL(req->outbuf,smb_vwv1,0);
4718         SCVAL(smb_buf(req->outbuf),0,1);
4719         SSVAL(smb_buf(req->outbuf),1,0);
4720   
4721         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
4722                  start_index, max_count));
4723
4724         {
4725                 print_queue_struct *queue = NULL;
4726                 print_status_struct status;
4727                 int count = print_queue_status(SNUM(conn), &queue, &status);
4728                 int num_to_get = ABS(max_count);
4729                 int first = (max_count>0?start_index:start_index+max_count+1);
4730                 int i;
4731
4732                 if (first >= count)
4733                         num_to_get = 0;
4734                 else
4735                         num_to_get = MIN(num_to_get,count-first);
4736     
4737
4738                 for (i=first;i<first+num_to_get;i++) {
4739                         char blob[28];
4740                         char *p = blob;
4741
4742                         srv_put_dos_date2(p,0,queue[i].time);
4743                         SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
4744                         SSVAL(p,5, queue[i].job);
4745                         SIVAL(p,7,queue[i].size);
4746                         SCVAL(p,11,0);
4747                         srvstr_push(blob, req->flags2, p+12,
4748                                     queue[i].fs_user, 16, STR_ASCII);
4749
4750                         if (message_push_blob(
4751                                     &req->outbuf,
4752                                     data_blob_const(
4753                                             blob, sizeof(blob))) == -1) {
4754                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4755                                 END_PROFILE(SMBsplretq);
4756                                 return;
4757                         }
4758                 }
4759
4760                 if (count > 0) {
4761                         SSVAL(req->outbuf,smb_vwv0,count);
4762                         SSVAL(req->outbuf,smb_vwv1,
4763                               (max_count>0?first+count:first-1));
4764                         SCVAL(smb_buf(req->outbuf),0,1);
4765                         SSVAL(smb_buf(req->outbuf),1,28*count);
4766                 }
4767
4768                 SAFE_FREE(queue);
4769           
4770                 DEBUG(3,("%d entries returned in queue\n",count));
4771         }
4772   
4773         END_PROFILE(SMBsplretq);
4774         return;
4775 }
4776
4777 /****************************************************************************
4778  Reply to a printwrite.
4779 ****************************************************************************/
4780
4781 void reply_printwrite(connection_struct *conn, struct smb_request *req)
4782 {
4783         int numtowrite;
4784         char *data;
4785         files_struct *fsp;
4786
4787         START_PROFILE(SMBsplwr);
4788
4789         if (req->wct < 1) {
4790                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4791                 END_PROFILE(SMBsplwr);
4792                 return;
4793         }
4794   
4795         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4796
4797         if (!check_fsp(conn, req, fsp, &current_user)) {
4798                 END_PROFILE(SMBsplwr);
4799                 return;
4800         }
4801
4802         if (!CAN_PRINT(conn)) {
4803                 reply_doserror(req, ERRDOS, ERRnoaccess);
4804                 END_PROFILE(SMBsplwr);
4805                 return;
4806         }
4807
4808         if (!CHECK_WRITE(fsp)) {
4809                 reply_doserror(req, ERRDOS, ERRbadaccess);
4810                 END_PROFILE(SMBsplwr);
4811                 return;
4812         }
4813
4814         numtowrite = SVAL(smb_buf(req->inbuf),1);
4815
4816         if (smb_buflen(req->inbuf) < numtowrite + 3) {
4817                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4818                 END_PROFILE(SMBsplwr);
4819                 return;
4820         }
4821
4822         data = smb_buf(req->inbuf) + 3;
4823
4824         if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
4825                 reply_unixerror(req, ERRHRD, ERRdiskfull);
4826                 END_PROFILE(SMBsplwr);
4827                 return;
4828         }
4829
4830         DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
4831
4832         END_PROFILE(SMBsplwr);
4833         return;
4834 }
4835
4836 /****************************************************************************
4837  Reply to a mkdir.
4838 ****************************************************************************/
4839
4840 void reply_mkdir(connection_struct *conn, struct smb_request *req)
4841 {
4842         char *directory = NULL;
4843         NTSTATUS status;
4844         SMB_STRUCT_STAT sbuf;
4845         TALLOC_CTX *ctx = talloc_tos();
4846
4847         START_PROFILE(SMBmkdir);
4848
4849         srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &directory,
4850                         smb_buf(req->inbuf) + 1, 0,
4851                         STR_TERMINATE, &status);
4852         if (!NT_STATUS_IS_OK(status)) {
4853                 reply_nterror(req, status);
4854                 END_PROFILE(SMBmkdir);
4855                 return;
4856         }
4857
4858         status = resolve_dfspath(ctx, conn,
4859                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
4860                                  directory,
4861                                  &directory);
4862         if (!NT_STATUS_IS_OK(status)) {
4863                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4864                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
4865                                         ERRSRV, ERRbadpath);
4866                         END_PROFILE(SMBmkdir);
4867                         return;
4868                 }
4869                 reply_nterror(req, status);
4870                 END_PROFILE(SMBmkdir);
4871                 return;
4872         }
4873
4874         status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
4875         if (!NT_STATUS_IS_OK(status)) {
4876                 reply_nterror(req, status);
4877                 END_PROFILE(SMBmkdir);
4878                 return;
4879         }
4880
4881         status = check_name(conn, directory);
4882         if (!NT_STATUS_IS_OK(status)) {
4883                 reply_nterror(req, status);
4884                 END_PROFILE(SMBmkdir);
4885                 return;
4886         }
4887
4888         status = create_directory(conn, directory);
4889
4890         DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
4891
4892         if (!NT_STATUS_IS_OK(status)) {
4893
4894                 if (!use_nt_status()
4895                     && NT_STATUS_EQUAL(status,
4896                                        NT_STATUS_OBJECT_NAME_COLLISION)) {
4897                         /*
4898                          * Yes, in the DOS error code case we get a
4899                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
4900                          * samba4 torture test.
4901                          */
4902                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
4903                 }
4904
4905                 reply_nterror(req, status);
4906                 END_PROFILE(SMBmkdir);
4907                 return;
4908         }
4909
4910         reply_outbuf(req, 0, 0);
4911
4912         DEBUG( 3, ( "mkdir %s\n", directory ) );
4913
4914         END_PROFILE(SMBmkdir);
4915         return;
4916 }
4917
4918 /****************************************************************************
4919  Static function used by reply_rmdir to delete an entire directory
4920  tree recursively. Return True on ok, False on fail.
4921 ****************************************************************************/
4922
4923 static bool recursive_rmdir(TALLOC_CTX *ctx,
4924                         connection_struct *conn,
4925                         char *directory)
4926 {
4927         const char *dname = NULL;
4928         bool ret = True;
4929         long offset = 0;
4930         struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
4931
4932         if(dir_hnd == NULL)
4933                 return False;
4934
4935         while((dname = ReadDirName(dir_hnd, &offset))) {
4936                 char *fullname = NULL;
4937                 SMB_STRUCT_STAT st;
4938
4939                 if (ISDOT(dname) || ISDOTDOT(dname)) {
4940                         continue;
4941                 }
4942
4943                 if (!is_visible_file(conn, directory, dname, &st, False)) {
4944                         continue;
4945                 }
4946
4947                 /* Construct the full name. */
4948                 fullname = talloc_asprintf(ctx,
4949                                 "%s/%s",
4950                                 directory,
4951                                 dname);
4952                 if (!fullname) {
4953                         errno = ENOMEM;
4954                         ret = False;
4955                         break;
4956                 }
4957
4958                 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
4959                         ret = False;
4960                         break;
4961                 }
4962
4963                 if(st.st_mode & S_IFDIR) {
4964                         if(!recursive_rmdir(ctx, conn, fullname)) {
4965                                 ret = False;
4966                                 break;
4967                         }
4968                         if(SMB_VFS_RMDIR(conn,fullname) != 0) {
4969                                 ret = False;
4970                                 break;
4971                         }
4972                 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
4973                         ret = False;
4974                         break;
4975                 }
4976                 TALLOC_FREE(fullname);
4977         }
4978         CloseDir(dir_hnd);
4979         return ret;
4980 }
4981
4982 /****************************************************************************
4983  The internals of the rmdir code - called elsewhere.
4984 ****************************************************************************/
4985
4986 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
4987                         connection_struct *conn,
4988                         const char *directory)
4989 {
4990         int ret;
4991         SMB_STRUCT_STAT st;
4992
4993         /* Might be a symlink. */
4994         if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
4995                 return map_nt_error_from_unix(errno);
4996         }
4997
4998         if (S_ISLNK(st.st_mode)) {
4999                 /* Is what it points to a directory ? */
5000                 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
5001                         return map_nt_error_from_unix(errno);
5002                 }
5003                 if (!(S_ISDIR(st.st_mode))) {
5004                         return NT_STATUS_NOT_A_DIRECTORY;
5005                 }
5006                 ret = SMB_VFS_UNLINK(conn,directory);
5007         } else {
5008                 ret = SMB_VFS_RMDIR(conn,directory);
5009         }
5010         if (ret == 0) {
5011                 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5012                              FILE_NOTIFY_CHANGE_DIR_NAME,
5013                              directory);
5014                 return NT_STATUS_OK;
5015         }
5016
5017         if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5018                 /*
5019                  * Check to see if the only thing in this directory are
5020                  * vetoed files/directories. If so then delete them and
5021                  * retry. If we fail to delete any of them (and we *don't*
5022                  * do a recursive delete) then fail the rmdir.
5023                  */
5024                 const char *dname;
5025                 long dirpos = 0;
5026                 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
5027
5028                 if(dir_hnd == NULL) {
5029                         errno = ENOTEMPTY;
5030                         goto err;
5031                 }
5032
5033                 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
5034                         if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5035                                 continue;
5036                         if (!is_visible_file(conn, directory, dname, &st, False))
5037                                 continue;
5038                         if(!IS_VETO_PATH(conn, dname)) {
5039                                 CloseDir(dir_hnd);
5040                                 errno = ENOTEMPTY;
5041                                 goto err;
5042                         }
5043                 }
5044
5045                 /* We only have veto files/directories. Recursive delete. */
5046
5047                 RewindDir(dir_hnd,&dirpos);
5048                 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
5049                         char *fullname = NULL;
5050
5051                         if (ISDOT(dname) || ISDOTDOT(dname)) {
5052                                 continue;
5053                         }
5054                         if (!is_visible_file(conn, directory, dname, &st, False)) {
5055                                 continue;
5056                         }
5057
5058                         fullname = talloc_asprintf(ctx,
5059                                         "%s/%s",
5060                                         directory,
5061                                         dname);
5062
5063                         if(!fullname) {
5064                                 errno = ENOMEM;
5065                                 break;
5066                         }
5067
5068                         if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5069                                 break;
5070                         }
5071                         if(st.st_mode & S_IFDIR) {
5072                                 if(lp_recursive_veto_delete(SNUM(conn))) {
5073                                         if(!recursive_rmdir(ctx, conn, fullname))
5074                                                 break;
5075                                 }
5076                                 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5077                                         break;
5078                                 }
5079                         } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5080                                 break;
5081                         }
5082                         TALLOC_FREE(fullname);
5083                 }
5084                 CloseDir(dir_hnd);
5085                 /* Retry the rmdir */
5086                 ret = SMB_VFS_RMDIR(conn,directory);
5087         }
5088
5089   err:
5090
5091         if (ret != 0) {
5092                 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5093                          "%s\n", directory,strerror(errno)));
5094                 return map_nt_error_from_unix(errno);
5095         }
5096
5097         notify_fname(conn, NOTIFY_ACTION_REMOVED,
5098                      FILE_NOTIFY_CHANGE_DIR_NAME,
5099                      directory);
5100
5101         return NT_STATUS_OK;
5102 }
5103
5104 /****************************************************************************
5105  Reply to a rmdir.
5106 ****************************************************************************/
5107
5108 void reply_rmdir(connection_struct *conn, struct smb_request *req)
5109 {
5110         char *directory = NULL;
5111         SMB_STRUCT_STAT sbuf;
5112         NTSTATUS status;
5113         TALLOC_CTX *ctx = talloc_tos();
5114
5115         START_PROFILE(SMBrmdir);
5116
5117         srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &directory,
5118                         smb_buf(req->inbuf) + 1, 0,
5119                         STR_TERMINATE, &status);
5120         if (!NT_STATUS_IS_OK(status)) {
5121                 reply_nterror(req, status);
5122                 END_PROFILE(SMBrmdir);
5123                 return;
5124         }
5125
5126         status = resolve_dfspath(ctx, conn,
5127                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
5128                                  directory,
5129                                  &directory);
5130         if (!NT_STATUS_IS_OK(status)) {
5131                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5132                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5133                                         ERRSRV, ERRbadpath);
5134                         END_PROFILE(SMBrmdir);
5135                         return;
5136                 }
5137                 reply_nterror(req, status);
5138                 END_PROFILE(SMBrmdir);
5139                 return;
5140         }
5141
5142         status = unix_convert(ctx, conn, directory, False, &directory,
5143                         NULL, &sbuf);
5144         if (!NT_STATUS_IS_OK(status)) {
5145                 reply_nterror(req, status);
5146                 END_PROFILE(SMBrmdir);
5147                 return;
5148         }
5149
5150         status = check_name(conn, directory);
5151         if (!NT_STATUS_IS_OK(status)) {
5152                 reply_nterror(req, status);
5153                 END_PROFILE(SMBrmdir);
5154                 return;
5155         }
5156
5157         dptr_closepath(directory, req->smbpid);
5158         status = rmdir_internals(ctx, conn, directory);
5159         if (!NT_STATUS_IS_OK(status)) {
5160                 reply_nterror(req, status);
5161                 END_PROFILE(SMBrmdir);
5162                 return;
5163         }
5164
5165         reply_outbuf(req, 0, 0);
5166
5167         DEBUG( 3, ( "rmdir %s\n", directory ) );
5168
5169         END_PROFILE(SMBrmdir);
5170         return;
5171 }
5172
5173 /*******************************************************************
5174  Resolve wildcards in a filename rename.
5175 ********************************************************************/
5176
5177 static bool resolve_wildcards(TALLOC_CTX *ctx,
5178                                 const char *name1,
5179                                 const char *name2,
5180                                 char **pp_newname)
5181 {
5182         char *name2_copy = NULL;
5183         char *root1 = NULL;
5184         char *root2 = NULL;
5185         char *ext1 = NULL;
5186         char *ext2 = NULL;
5187         char *p,*p2, *pname1, *pname2;
5188         
5189         name2_copy = talloc_strdup(ctx, name2);
5190         if (!name2_copy) {
5191                 return False;
5192         }
5193
5194         pname1 = strrchr_m(name1,'/');
5195         pname2 = strrchr_m(name2_copy,'/');
5196
5197         if (!pname1 || !pname2) {
5198                 return False;
5199         }
5200   
5201         /* Truncate the copy of name2 at the last '/' */
5202         *pname2 = '\0';
5203
5204         /* Now go past the '/' */
5205         pname1++;
5206         pname2++;
5207
5208         root1 = talloc_strdup(ctx, pname1);
5209         root2 = talloc_strdup(ctx, pname2);
5210
5211         if (!root1 || !root2) {
5212                 return False;
5213         }
5214
5215         p = strrchr_m(root1,'.');
5216         if (p) {
5217                 *p = 0;
5218                 ext1 = talloc_strdup(ctx, p+1);
5219         } else {
5220                 ext1 = talloc_strdup(ctx, "");
5221         }
5222         p = strrchr_m(root2,'.');
5223         if (p) {
5224                 *p = 0;
5225                 ext2 = talloc_strdup(ctx, p+1);
5226         } else {
5227                 ext2 = talloc_strdup(ctx, "");
5228         }
5229
5230         if (!ext1 || !ext2) {
5231                 return False;
5232         }
5233
5234         p = root1;
5235         p2 = root2;
5236         while (*p2) {
5237                 if (*p2 == '?') {
5238                         /* Hmmm. Should this be mb-aware ? */
5239                         *p2 = *p;
5240                         p2++;
5241                 } else if (*p2 == '*') {
5242                         *p2 = '\0';
5243                         root2 = talloc_asprintf(ctx, "%s%s",
5244                                                 root2,
5245                                                 p);
5246                         if (!root2) {
5247                                 return False;
5248                         }
5249                         break;
5250                 } else {
5251                         p2++;
5252                 }
5253                 if (*p) {
5254                         p++;
5255                 }
5256         }
5257
5258         p = ext1;
5259         p2 = ext2;
5260         while (*p2) {
5261                 if (*p2 == '?') {
5262                         /* Hmmm. Should this be mb-aware ? */
5263                         *p2 = *p;
5264                         p2++;
5265                 } else if (*p2 == '*') {
5266                         *p2 = '\0';
5267                         ext2 = talloc_asprintf(ctx, "%s%s",
5268                                                 ext2,
5269                                                 p);
5270                         if (!ext2) {
5271                                 return False;
5272                         }
5273                         break;
5274                 } else {
5275                         p2++;
5276                 }
5277                 if (*p) {
5278                         p++;
5279                 }
5280         }
5281
5282         if (*ext2) {
5283                 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5284                                 name2_copy,
5285                                 root2,
5286                                 ext2);
5287         } else {
5288                 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5289                                 name2_copy,
5290                                 root2);
5291         }
5292
5293         if (!*pp_newname) {
5294                 return False;
5295         }
5296
5297         return True;
5298 }
5299
5300 /****************************************************************************
5301  Ensure open files have their names updated. Updated to notify other smbd's
5302  asynchronously.
5303 ****************************************************************************/
5304
5305 static void rename_open_files(connection_struct *conn,
5306                               struct share_mode_lock *lck,
5307                               const char *newname)
5308 {
5309         files_struct *fsp;
5310         bool did_rename = False;
5311
5312         for(fsp = file_find_di_first(lck->id); fsp;
5313             fsp = file_find_di_next(fsp)) {
5314                 /* fsp_name is a relative path under the fsp. To change this for other
5315                    sharepaths we need to manipulate relative paths. */
5316                 /* TODO - create the absolute path and manipulate the newname
5317                    relative to the sharepath. */
5318                 if (fsp->conn != conn) {
5319                         continue;
5320                 }
5321                 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5322                           fsp->fnum, file_id_string_tos(&fsp->file_id),
5323                         fsp->fsp_name, newname ));
5324                 string_set(&fsp->fsp_name, newname);
5325                 did_rename = True;
5326         }
5327
5328         if (!did_rename) {
5329                 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5330                           file_id_string_tos(&lck->id), newname ));
5331         }
5332
5333         /* Send messages to all smbd's (not ourself) that the name has changed. */
5334         rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5335                               newname);
5336 }
5337
5338 /****************************************************************************
5339  We need to check if the source path is a parent directory of the destination
5340  (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5341  refuse the rename with a sharing violation. Under UNIX the above call can
5342  *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5343  probably need to check that the client is a Windows one before disallowing
5344  this as a UNIX client (one with UNIX extensions) can know the source is a
5345  symlink and make this decision intelligently. Found by an excellent bug
5346  report from <AndyLiebman@aol.com>.
5347 ****************************************************************************/
5348
5349 static bool rename_path_prefix_equal(const char *src, const char *dest)
5350 {
5351         const char *psrc = src;
5352         const char *pdst = dest;
5353         size_t slen;
5354
5355         if (psrc[0] == '.' && psrc[1] == '/') {
5356                 psrc += 2;
5357         }
5358         if (pdst[0] == '.' && pdst[1] == '/') {
5359                 pdst += 2;
5360         }
5361         if ((slen = strlen(psrc)) > strlen(pdst)) {
5362                 return False;
5363         }
5364         return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5365 }
5366
5367 /*
5368  * Do the notify calls from a rename
5369  */
5370
5371 static void notify_rename(connection_struct *conn, bool is_dir,
5372                           const char *oldpath, const char *newpath)
5373 {
5374         char *olddir, *newdir;
5375         const char *oldname, *newname;
5376         uint32 mask;
5377
5378         mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5379                 : FILE_NOTIFY_CHANGE_FILE_NAME;
5380
5381         if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
5382             || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
5383                 TALLOC_FREE(olddir);
5384                 return;
5385         }
5386
5387         if (strcmp(olddir, newdir) == 0) {
5388                 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
5389                 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
5390         }
5391         else {
5392                 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
5393                 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
5394         }
5395         TALLOC_FREE(olddir);
5396         TALLOC_FREE(newdir);
5397
5398         /* this is a strange one. w2k3 gives an additional event for
5399            CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5400            files, but not directories */
5401         if (!is_dir) {
5402                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5403                              FILE_NOTIFY_CHANGE_ATTRIBUTES
5404                              |FILE_NOTIFY_CHANGE_CREATION,
5405                              newpath);
5406         }
5407 }
5408
5409 /****************************************************************************
5410  Rename an open file - given an fsp.
5411 ****************************************************************************/
5412
5413 NTSTATUS rename_internals_fsp(connection_struct *conn,
5414                         files_struct *fsp,
5415                         char *newname,
5416                         const char *newname_last_component,
5417                         uint32 attrs,
5418                         bool replace_if_exists)
5419 {
5420         TALLOC_CTX *ctx = talloc_tos();
5421         SMB_STRUCT_STAT sbuf, sbuf1;
5422         NTSTATUS status = NT_STATUS_OK;
5423         struct share_mode_lock *lck = NULL;
5424         bool dst_exists;
5425
5426         ZERO_STRUCT(sbuf);
5427
5428         status = check_name(conn, newname);
5429         if (!NT_STATUS_IS_OK(status)) {
5430                 return status;
5431         }
5432
5433         /* Ensure newname contains a '/' */
5434         if(strrchr_m(newname,'/') == 0) {
5435                 newname = talloc_asprintf(ctx,
5436                                         "./%s",
5437                                         newname);
5438                 if (!newname) {
5439                         return NT_STATUS_NO_MEMORY;
5440                 }
5441         }
5442
5443         /*
5444          * Check for special case with case preserving and not
5445          * case sensitive. If the old last component differs from the original
5446          * last component only by case, then we should allow
5447          * the rename (user is trying to change the case of the
5448          * filename).
5449          */
5450
5451         if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5452                         strequal(newname, fsp->fsp_name)) {
5453                 char *p;
5454                 char *newname_modified_last_component = NULL;
5455
5456                 /*
5457                  * Get the last component of the modified name.
5458                  * Note that we guarantee that newname contains a '/'
5459                  * character above.
5460                  */
5461                 p = strrchr_m(newname,'/');
5462                 newname_modified_last_component = talloc_strdup(ctx,
5463                                                 p+1);
5464                 if (!newname_modified_last_component) {
5465                         return NT_STATUS_NO_MEMORY;
5466                 }
5467
5468                 if(strcsequal(newname_modified_last_component,
5469                               newname_last_component) == False) {
5470                         /*
5471                          * Replace the modified last component with
5472                          * the original.
5473                          */
5474                         *p = '\0'; /* Truncate at the '/' */
5475                         newname = talloc_asprintf(ctx,
5476                                         "%s/%s",
5477                                         newname,
5478                                         newname_last_component);
5479                 }
5480         }
5481
5482         /*
5483          * If the src and dest names are identical - including case,
5484          * don't do the rename, just return success.
5485          */
5486
5487         if (strcsequal(fsp->fsp_name, newname)) {
5488                 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5489                         newname));
5490                 return NT_STATUS_OK;
5491         }
5492
5493         /*
5494          * Have vfs_object_exist also fill sbuf1
5495          */
5496         dst_exists = vfs_object_exist(conn, newname, &sbuf1);
5497
5498         if(!replace_if_exists && dst_exists) {
5499                 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5500                         fsp->fsp_name,newname));
5501                 return NT_STATUS_OBJECT_NAME_COLLISION;
5502         }
5503
5504         if (dst_exists) {
5505                 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5506                 files_struct *dst_fsp = file_find_di_first(fileid);
5507                 if (dst_fsp) {
5508                         DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5509                         return NT_STATUS_ACCESS_DENIED;
5510                 }
5511         }
5512
5513         /* Ensure we have a valid stat struct for the source. */
5514         if (fsp->fh->fd != -1) {
5515                 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) == -1) {
5516                         return map_nt_error_from_unix(errno);
5517                 }
5518         } else {
5519                 if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
5520                         return map_nt_error_from_unix(errno);
5521                 }
5522         }
5523
5524         status = can_rename(conn, fsp, attrs, &sbuf);
5525
5526         if (!NT_STATUS_IS_OK(status)) {
5527                 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5528                         nt_errstr(status), fsp->fsp_name,newname));
5529                 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5530                         status = NT_STATUS_ACCESS_DENIED;
5531                 return status;
5532         }
5533
5534         if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5535                 return NT_STATUS_ACCESS_DENIED;
5536         }
5537
5538         lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
5539
5540         /*
5541          * We have the file open ourselves, so not being able to get the
5542          * corresponding share mode lock is a fatal error.
5543          */
5544
5545         SMB_ASSERT(lck != NULL);
5546
5547         if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5548                 uint32 create_options = fsp->fh->private_options;
5549
5550                 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5551                         fsp->fsp_name,newname));
5552
5553                 rename_open_files(conn, lck, newname);
5554
5555                 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5556
5557                 /*
5558                  * A rename acts as a new file create w.r.t. allowing an initial delete
5559                  * on close, probably because in Windows there is a new handle to the
5560                  * new file. If initial delete on close was requested but not
5561                  * originally set, we need to set it here. This is probably not 100% correct,
5562                  * but will work for the CIFSFS client which in non-posix mode
5563                  * depends on these semantics. JRA.
5564                  */
5565
5566                 set_allow_initial_delete_on_close(lck, fsp, True);
5567
5568                 if (create_options & FILE_DELETE_ON_CLOSE) {
5569                         status = can_set_delete_on_close(fsp, True, 0);
5570
5571                         if (NT_STATUS_IS_OK(status)) {
5572                                 /* Note that here we set the *inital* delete on close flag,
5573                                  * not the regular one. The magic gets handled in close. */
5574                                 fsp->initial_delete_on_close = True;
5575                         }
5576                 }
5577                 TALLOC_FREE(lck);
5578                 return NT_STATUS_OK;
5579         }
5580
5581         TALLOC_FREE(lck);
5582
5583         if (errno == ENOTDIR || errno == EISDIR) {
5584                 status = NT_STATUS_OBJECT_NAME_COLLISION;
5585         } else {
5586                 status = map_nt_error_from_unix(errno);
5587         }
5588
5589         DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5590                 nt_errstr(status), fsp->fsp_name,newname));
5591
5592         return status;
5593 }
5594
5595 /****************************************************************************
5596  The guts of the rename command, split out so it may be called by the NT SMB
5597  code.
5598 ****************************************************************************/
5599
5600 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5601                         connection_struct *conn,
5602                         struct smb_request *req,
5603                         const char *name_in,
5604                         const char *newname_in,
5605                         uint32 attrs,
5606                         bool replace_if_exists,
5607                         bool src_has_wild,
5608                         bool dest_has_wild)
5609 {
5610         char *directory = NULL;
5611         char *mask = NULL;
5612         char *last_component_src = NULL;
5613         char *last_component_dest = NULL;
5614         char *name = NULL;
5615         char *newname = NULL;
5616         char *p;
5617         int count=0;
5618         NTSTATUS status = NT_STATUS_OK;
5619         SMB_STRUCT_STAT sbuf1, sbuf2;
5620         struct smb_Dir *dir_hnd = NULL;
5621         const char *dname;
5622         long offset = 0;
5623
5624         ZERO_STRUCT(sbuf1);
5625         ZERO_STRUCT(sbuf2);
5626
5627         status = unix_convert(ctx, conn, name_in, src_has_wild, &name,
5628                         &last_component_src, &sbuf1);
5629         if (!NT_STATUS_IS_OK(status)) {
5630                 return status;
5631         }
5632
5633         status = unix_convert(ctx, conn, newname_in, dest_has_wild, &newname,
5634                         &last_component_dest, &sbuf2);
5635         if (!NT_STATUS_IS_OK(status)) {
5636                 return status;
5637         }
5638
5639         /*
5640          * Split the old name into directory and last component
5641          * strings. Note that unix_convert may have stripped off a
5642          * leading ./ from both name and newname if the rename is
5643          * at the root of the share. We need to make sure either both
5644          * name and newname contain a / character or neither of them do
5645          * as this is checked in resolve_wildcards().
5646          */
5647
5648         p = strrchr_m(name,'/');
5649         if (!p) {
5650                 directory = talloc_strdup(ctx, ".");
5651                 if (!directory) {
5652                         return NT_STATUS_NO_MEMORY;
5653                 }
5654                 mask = name;
5655         } else {
5656                 *p = 0;
5657                 directory = talloc_strdup(ctx, name);
5658                 if (!directory) {
5659                         return NT_STATUS_NO_MEMORY;
5660                 }
5661                 mask = p+1;
5662                 *p = '/'; /* Replace needed for exceptional test below. */
5663         }
5664
5665         /*
5666          * We should only check the mangled cache
5667          * here if unix_convert failed. This means
5668          * that the path in 'mask' doesn't exist
5669          * on the file system and so we need to look
5670          * for a possible mangle. This patch from
5671          * Tine Smukavec <valentin.smukavec@hermes.si>.
5672          */
5673
5674         if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5675                 char *new_mask = NULL;
5676                 mangle_lookup_name_from_8_3(ctx,
5677                                         mask,
5678                                         &new_mask,
5679                                         conn->params );
5680                 if (new_mask) {
5681                         mask = new_mask;
5682                 }
5683         }
5684
5685         if (!src_has_wild) {
5686                 files_struct *fsp;
5687
5688                 /*
5689                  * No wildcards - just process the one file.
5690                  */
5691                 bool is_short_name = mangle_is_8_3(name, True, conn->params);
5692
5693                 /* Add a terminating '/' to the directory name. */
5694                 directory = talloc_asprintf_append(directory,
5695                                 "/%s",
5696                                 mask);
5697                 if (!directory) {
5698                         return NT_STATUS_NO_MEMORY;
5699                 }
5700
5701                 /* Ensure newname contains a '/' also */
5702                 if(strrchr_m(newname,'/') == 0) {
5703                         newname = talloc_asprintf(ctx,
5704                                                 "./%s",
5705                                                 newname);
5706                         if (!newname) {
5707                                 return NT_STATUS_NO_MEMORY;
5708                         }
5709                 }
5710
5711                 DEBUG(3, ("rename_internals: case_sensitive = %d, "
5712                           "case_preserve = %d, short case preserve = %d, "
5713                           "directory = %s, newname = %s, "
5714                           "last_component_dest = %s, is_8_3 = %d\n",
5715                           conn->case_sensitive, conn->case_preserve,
5716                           conn->short_case_preserve, directory,
5717                           newname, last_component_dest, is_short_name));
5718
5719                 /* The dest name still may have wildcards. */
5720                 if (dest_has_wild) {
5721                         char *mod_newname = NULL;
5722                         if (!resolve_wildcards(ctx,
5723                                         directory,newname,&mod_newname)) {
5724                                 DEBUG(6, ("rename_internals: resolve_wildcards "
5725                                         "%s %s failed\n",
5726                                         directory,
5727                                         newname));
5728                                 return NT_STATUS_NO_MEMORY;
5729                         }
5730                         newname = mod_newname;
5731                 }
5732
5733                 ZERO_STRUCT(sbuf1);
5734                 SMB_VFS_STAT(conn, directory, &sbuf1);
5735
5736                 status = S_ISDIR(sbuf1.st_mode) ?
5737                         open_directory(conn, req, directory, &sbuf1,
5738                                        DELETE_ACCESS,
5739                                        FILE_SHARE_READ|FILE_SHARE_WRITE,
5740                                        FILE_OPEN, 0, 0, NULL,
5741                                        &fsp)
5742                         : open_file_ntcreate(conn, req, directory, &sbuf1,
5743                                              DELETE_ACCESS,
5744                                              FILE_SHARE_READ|FILE_SHARE_WRITE,
5745                                              FILE_OPEN, 0, 0, 0, NULL,
5746                                              &fsp);
5747
5748                 if (!NT_STATUS_IS_OK(status)) {
5749                         DEBUG(3, ("Could not open rename source %s: %s\n",
5750                                   directory, nt_errstr(status)));
5751                         return status;
5752                 }
5753
5754                 status = rename_internals_fsp(conn, fsp, newname,
5755                                               last_component_dest,
5756                                               attrs, replace_if_exists);
5757
5758                 close_file(fsp, NORMAL_CLOSE);
5759
5760                 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
5761                           nt_errstr(status), directory,newname));
5762
5763                 return status;
5764         }
5765
5766         /*
5767          * Wildcards - process each file that matches.
5768          */
5769         if (strequal(mask,"????????.???")) {
5770                 mask[0] = '*';
5771                 mask[1] = '\0';
5772         }
5773
5774         status = check_name(conn, directory);
5775         if (!NT_STATUS_IS_OK(status)) {
5776                 return status;
5777         }
5778
5779         dir_hnd = OpenDir(conn, directory, mask, attrs);
5780         if (dir_hnd == NULL) {
5781                 return map_nt_error_from_unix(errno);
5782         }
5783
5784         status = NT_STATUS_NO_SUCH_FILE;
5785         /*
5786          * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
5787          * - gentest fix. JRA
5788          */
5789
5790         while ((dname = ReadDirName(dir_hnd, &offset))) {
5791                 files_struct *fsp = NULL;
5792                 char *fname = NULL;
5793                 char *destname = NULL;
5794                 bool sysdir_entry = False;
5795
5796                 /* Quick check for "." and ".." */
5797                 if (ISDOT(dname) || ISDOTDOT(dname)) {
5798                         if (attrs & aDIR) {
5799                                 sysdir_entry = True;
5800                         } else {
5801                                 continue;
5802                         }
5803                 }
5804
5805                 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5806                         continue;
5807                 }
5808
5809                 if(!mask_match(dname, mask, conn->case_sensitive)) {
5810                         continue;
5811                 }
5812
5813                 if (sysdir_entry) {
5814                         status = NT_STATUS_OBJECT_NAME_INVALID;
5815                         break;
5816                 }
5817
5818                 fname = talloc_asprintf(ctx,
5819                                 "%s/%s",
5820                                 directory,
5821                                 dname);
5822                 if (!fname) {
5823                         return NT_STATUS_NO_MEMORY;
5824                 }
5825
5826                 if (!resolve_wildcards(ctx,
5827                                 fname,newname,&destname)) {
5828                         DEBUG(6, ("resolve_wildcards %s %s failed\n",
5829                                   fname, destname));
5830                         TALLOC_FREE(fname);
5831                         continue;
5832                 }
5833                 if (!destname) {
5834                         return NT_STATUS_NO_MEMORY;
5835                 }
5836
5837                 ZERO_STRUCT(sbuf1);
5838                 SMB_VFS_STAT(conn, fname, &sbuf1);
5839
5840                 status = S_ISDIR(sbuf1.st_mode) ?
5841                         open_directory(conn, req, fname, &sbuf1,
5842                                        DELETE_ACCESS,
5843                                        FILE_SHARE_READ|FILE_SHARE_WRITE,
5844                                        FILE_OPEN, 0, 0, NULL,
5845                                        &fsp)
5846                         : open_file_ntcreate(conn, req, fname, &sbuf1,
5847                                              DELETE_ACCESS,
5848                                              FILE_SHARE_READ|FILE_SHARE_WRITE,
5849                                              FILE_OPEN, 0, 0, 0, NULL,
5850                                              &fsp);
5851
5852                 if (!NT_STATUS_IS_OK(status)) {
5853                         DEBUG(3,("rename_internals: open_file_ntcreate "
5854                                  "returned %s rename %s -> %s\n",
5855                                  nt_errstr(status), directory, newname));
5856                         break;
5857                 }
5858
5859                 status = rename_internals_fsp(conn, fsp, destname, dname,
5860                                               attrs, replace_if_exists);
5861
5862                 close_file(fsp, NORMAL_CLOSE);
5863
5864                 if (!NT_STATUS_IS_OK(status)) {
5865                         DEBUG(3, ("rename_internals_fsp returned %s for "
5866                                   "rename %s -> %s\n", nt_errstr(status),
5867                                   directory, newname));
5868                         break;
5869                 }
5870
5871                 count++;
5872
5873                 DEBUG(3,("rename_internals: doing rename on %s -> "
5874                          "%s\n",fname,destname));
5875
5876                 TALLOC_FREE(fname);
5877                 TALLOC_FREE(destname);
5878         }
5879         CloseDir(dir_hnd);
5880
5881         if (count == 0 && NT_STATUS_IS_OK(status)) {
5882                 status = map_nt_error_from_unix(errno);
5883         }
5884
5885         return status;
5886 }
5887
5888 /****************************************************************************
5889  Reply to a mv.
5890 ****************************************************************************/
5891
5892 void reply_mv(connection_struct *conn, struct smb_request *req)
5893 {
5894         char *name = NULL;
5895         char *newname = NULL;
5896         char *p;
5897         uint32 attrs;
5898         NTSTATUS status;
5899         bool src_has_wcard = False;
5900         bool dest_has_wcard = False;
5901         TALLOC_CTX *ctx = talloc_tos();
5902
5903         START_PROFILE(SMBmv);
5904
5905         if (req->wct < 1) {
5906                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5907                 END_PROFILE(SMBmv);
5908                 return;
5909         }
5910
5911         attrs = SVAL(req->inbuf,smb_vwv0);
5912
5913         p = smb_buf(req->inbuf) + 1;
5914         p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name, p,
5915                                    0, STR_TERMINATE, &status,
5916                                    &src_has_wcard);
5917         if (!NT_STATUS_IS_OK(status)) {
5918                 reply_nterror(req, status);
5919                 END_PROFILE(SMBmv);
5920                 return;
5921         }
5922         p++;
5923         p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &newname, p,
5924                                    0, STR_TERMINATE, &status,
5925                                    &dest_has_wcard);
5926         if (!NT_STATUS_IS_OK(status)) {
5927                 reply_nterror(req, status);
5928                 END_PROFILE(SMBmv);
5929                 return;
5930         }
5931
5932         status = resolve_dfspath_wcard(ctx, conn,
5933                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
5934                                        name,
5935                                        &name,
5936                                        &src_has_wcard);
5937         if (!NT_STATUS_IS_OK(status)) {
5938                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5939                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5940                                         ERRSRV, ERRbadpath);
5941                         END_PROFILE(SMBmv);
5942                         return;
5943                 }
5944                 reply_nterror(req, status);
5945                 END_PROFILE(SMBmv);
5946                 return;
5947         }
5948
5949         status = resolve_dfspath_wcard(ctx, conn,
5950                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
5951                                        newname,
5952                                        &newname,
5953                                        &dest_has_wcard);
5954         if (!NT_STATUS_IS_OK(status)) {
5955                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5956                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5957                                         ERRSRV, ERRbadpath);
5958                         END_PROFILE(SMBmv);
5959                         return;
5960                 }
5961                 reply_nterror(req, status);
5962                 END_PROFILE(SMBmv);
5963                 return;
5964         }
5965
5966         DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
5967
5968         status = rename_internals(ctx, conn, req, name, newname, attrs, False,
5969                                   src_has_wcard, dest_has_wcard);
5970         if (!NT_STATUS_IS_OK(status)) {
5971                 if (open_was_deferred(req->mid)) {
5972                         /* We have re-scheduled this call. */
5973                         END_PROFILE(SMBmv);
5974                         return;
5975                 }
5976                 reply_nterror(req, status);
5977                 END_PROFILE(SMBmv);
5978                 return;
5979         }
5980
5981         reply_outbuf(req, 0, 0);
5982
5983         END_PROFILE(SMBmv);
5984         return;
5985 }
5986
5987 /*******************************************************************
5988  Copy a file as part of a reply_copy.
5989 ******************************************************************/
5990
5991 /*
5992  * TODO: check error codes on all callers
5993  */
5994
5995 NTSTATUS copy_file(TALLOC_CTX *ctx,
5996                         connection_struct *conn,
5997                         const char *src,
5998                         const char *dest1,
5999                         int ofun,
6000                         int count,
6001                         bool target_is_directory)
6002 {
6003         SMB_STRUCT_STAT src_sbuf, sbuf2;
6004         SMB_OFF_T ret=-1;
6005         files_struct *fsp1,*fsp2;
6006         char *dest = NULL;
6007         uint32 dosattrs;
6008         uint32 new_create_disposition;
6009         NTSTATUS status;
6010
6011         dest = talloc_strdup(ctx, dest1);
6012         if (!dest) {
6013                 return NT_STATUS_NO_MEMORY;
6014         }
6015         if (target_is_directory) {
6016                 const char *p = strrchr_m(src,'/');
6017                 if (p) {
6018                         p++;
6019                 } else {
6020                         p = src;
6021                 }
6022                 dest = talloc_asprintf_append(dest,
6023                                 "/%s",
6024                                 p);
6025                 if (!dest) {
6026                         return NT_STATUS_NO_MEMORY;
6027                 }
6028         }
6029
6030         if (!vfs_file_exist(conn,src,&src_sbuf)) {
6031                 TALLOC_FREE(dest);
6032                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6033         }
6034
6035         if (!target_is_directory && count) {
6036                 new_create_disposition = FILE_OPEN;
6037         } else {
6038                 if (!map_open_params_to_ntcreate(dest1,0,ofun,
6039                                 NULL, NULL, &new_create_disposition, NULL)) {
6040                         TALLOC_FREE(dest);
6041                         return NT_STATUS_INVALID_PARAMETER;
6042                 }
6043         }
6044
6045         status = open_file_ntcreate(conn, NULL, src, &src_sbuf,
6046                         FILE_GENERIC_READ,
6047                         FILE_SHARE_READ|FILE_SHARE_WRITE,
6048                         FILE_OPEN,
6049                         0,
6050                         FILE_ATTRIBUTE_NORMAL,
6051                         INTERNAL_OPEN_ONLY,
6052                         NULL, &fsp1);
6053
6054         if (!NT_STATUS_IS_OK(status)) {
6055                 TALLOC_FREE(dest);
6056                 return status;
6057         }
6058
6059         dosattrs = dos_mode(conn, src, &src_sbuf);
6060         if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
6061                 ZERO_STRUCTP(&sbuf2);
6062         }
6063
6064         status = open_file_ntcreate(conn, NULL, dest, &sbuf2,
6065                         FILE_GENERIC_WRITE,
6066                         FILE_SHARE_READ|FILE_SHARE_WRITE,
6067                         new_create_disposition,
6068                         0,
6069                         dosattrs,
6070                         INTERNAL_OPEN_ONLY,
6071                         NULL, &fsp2);
6072
6073         TALLOC_FREE(dest);
6074
6075         if (!NT_STATUS_IS_OK(status)) {
6076                 close_file(fsp1,ERROR_CLOSE);
6077                 return status;
6078         }
6079
6080         if ((ofun&3) == 1) {
6081                 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
6082                         DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6083                         /*
6084                          * Stop the copy from occurring.
6085                          */
6086                         ret = -1;
6087                         src_sbuf.st_size = 0;
6088                 }
6089         }
6090
6091         if (src_sbuf.st_size) {
6092                 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
6093         }
6094
6095         close_file(fsp1,NORMAL_CLOSE);
6096
6097         /* Ensure the modtime is set correctly on the destination file. */
6098         fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
6099
6100         /*
6101          * As we are opening fsp1 read-only we only expect
6102          * an error on close on fsp2 if we are out of space.
6103          * Thus we don't look at the error return from the
6104          * close of fsp1.
6105          */
6106         status = close_file(fsp2,NORMAL_CLOSE);
6107
6108         if (!NT_STATUS_IS_OK(status)) {
6109                 return status;
6110         }
6111
6112         if (ret != (SMB_OFF_T)src_sbuf.st_size) {
6113                 return NT_STATUS_DISK_FULL;
6114         }
6115
6116         return NT_STATUS_OK;
6117 }
6118
6119 /****************************************************************************
6120  Reply to a file copy.
6121 ****************************************************************************/
6122
6123 void reply_copy(connection_struct *conn, struct smb_request *req)
6124 {
6125         char *name = NULL;
6126         char *newname = NULL;
6127         char *directory = NULL;
6128         char *mask = NULL;
6129         char *p;
6130         int count=0;
6131         int error = ERRnoaccess;
6132         int err = 0;
6133         int tid2;
6134         int ofun;
6135         int flags;
6136         bool target_is_directory=False;
6137         bool source_has_wild = False;
6138         bool dest_has_wild = False;
6139         SMB_STRUCT_STAT sbuf1, sbuf2;
6140         NTSTATUS status;
6141         TALLOC_CTX *ctx = talloc_tos();
6142
6143         START_PROFILE(SMBcopy);
6144
6145         if (req->wct < 3) {
6146                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6147                 END_PROFILE(SMBcopy);
6148                 return;
6149         }
6150
6151         tid2 = SVAL(req->inbuf,smb_vwv0);
6152         ofun = SVAL(req->inbuf,smb_vwv1);
6153         flags = SVAL(req->inbuf,smb_vwv2);
6154
6155         p = smb_buf(req->inbuf);
6156         p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name, p,
6157                                    0, STR_TERMINATE, &status,
6158                                    &source_has_wild);
6159         if (!NT_STATUS_IS_OK(status)) {
6160                 reply_nterror(req, status);
6161                 END_PROFILE(SMBcopy);
6162                 return;
6163         }
6164         p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &newname, p,
6165                                    0, STR_TERMINATE, &status,
6166                                    &dest_has_wild);
6167         if (!NT_STATUS_IS_OK(status)) {
6168                 reply_nterror(req, status);
6169                 END_PROFILE(SMBcopy);
6170                 return;
6171         }
6172
6173         DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
6174
6175         if (tid2 != conn->cnum) {
6176                 /* can't currently handle inter share copies XXXX */
6177                 DEBUG(3,("Rejecting inter-share copy\n"));
6178                 reply_doserror(req, ERRSRV, ERRinvdevice);
6179                 END_PROFILE(SMBcopy);
6180                 return;
6181         }
6182
6183         status = resolve_dfspath_wcard(ctx, conn,
6184                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
6185                                        name,
6186                                        &name,
6187                                        &source_has_wild);
6188         if (!NT_STATUS_IS_OK(status)) {
6189                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6190                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6191                                         ERRSRV, ERRbadpath);
6192                         END_PROFILE(SMBcopy);
6193                         return;
6194                 }
6195                 reply_nterror(req, status);
6196                 END_PROFILE(SMBcopy);
6197                 return;
6198         }
6199
6200         status = resolve_dfspath_wcard(ctx, conn,
6201                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
6202                                        newname,
6203                                        &newname,
6204                                        &dest_has_wild);
6205         if (!NT_STATUS_IS_OK(status)) {
6206                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6207                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6208                                         ERRSRV, ERRbadpath);
6209                         END_PROFILE(SMBcopy);
6210                         return;
6211                 }
6212                 reply_nterror(req, status);
6213                 END_PROFILE(SMBcopy);
6214                 return;
6215         }
6216
6217         status = unix_convert(ctx, conn, name, source_has_wild,
6218                         &name, NULL, &sbuf1);
6219         if (!NT_STATUS_IS_OK(status)) {
6220                 reply_nterror(req, status);
6221                 END_PROFILE(SMBcopy);
6222                 return;
6223         }
6224
6225         status = unix_convert(ctx, conn, newname, dest_has_wild,
6226                         &newname, NULL, &sbuf2);
6227         if (!NT_STATUS_IS_OK(status)) {
6228                 reply_nterror(req, status);
6229                 END_PROFILE(SMBcopy);
6230                 return;
6231         }
6232
6233         target_is_directory = VALID_STAT_OF_DIR(sbuf2);
6234
6235         if ((flags&1) && target_is_directory) {
6236                 reply_doserror(req, ERRDOS, ERRbadfile);
6237                 END_PROFILE(SMBcopy);
6238                 return;
6239         }
6240
6241         if ((flags&2) && !target_is_directory) {
6242                 reply_doserror(req, ERRDOS, ERRbadpath);
6243                 END_PROFILE(SMBcopy);
6244                 return;
6245         }
6246
6247         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
6248                 /* wants a tree copy! XXXX */
6249                 DEBUG(3,("Rejecting tree copy\n"));
6250                 reply_doserror(req, ERRSRV, ERRerror);
6251                 END_PROFILE(SMBcopy);
6252                 return;
6253         }
6254
6255         p = strrchr_m(name,'/');
6256         if (!p) {
6257                 directory = talloc_strdup(ctx, "./");
6258                 if (!directory) {
6259                         reply_nterror(req, NT_STATUS_NO_MEMORY);
6260                         END_PROFILE(SMBcopy);
6261                         return;
6262                 }
6263                 mask = name;
6264         } else {
6265                 *p = 0;
6266                 directory = talloc_strdup(ctx, name);
6267                 if (!directory) {
6268                         reply_nterror(req, NT_STATUS_NO_MEMORY);
6269                         END_PROFILE(SMBcopy);
6270                         return;
6271                 }
6272                 mask = p+1;
6273         }
6274
6275         /*
6276          * We should only check the mangled cache
6277          * here if unix_convert failed. This means
6278          * that the path in 'mask' doesn't exist
6279          * on the file system and so we need to look
6280          * for a possible mangle. This patch from
6281          * Tine Smukavec <valentin.smukavec@hermes.si>.
6282          */
6283
6284         if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
6285                 char *new_mask = NULL;
6286                 mangle_lookup_name_from_8_3(ctx,
6287                                         mask,
6288                                         &new_mask,
6289                                         conn->params );
6290                 if (new_mask) {
6291                         mask = new_mask;
6292                 }
6293         }
6294
6295         if (!source_has_wild) {
6296                 directory = talloc_asprintf_append(directory,
6297                                 "/%s",
6298                                 mask);
6299                 if (dest_has_wild) {
6300                         char *mod_newname = NULL;
6301                         if (!resolve_wildcards(ctx,
6302                                         directory,newname,&mod_newname)) {
6303                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6304                                 END_PROFILE(SMBcopy);
6305                                 return;
6306                         }
6307                         newname = mod_newname;
6308                 }
6309
6310                 status = check_name(conn, directory);
6311                 if (!NT_STATUS_IS_OK(status)) {
6312                         reply_nterror(req, status);
6313                         END_PROFILE(SMBcopy);
6314                         return;
6315                 }
6316
6317                 status = check_name(conn, newname);
6318                 if (!NT_STATUS_IS_OK(status)) {
6319                         reply_nterror(req, status);
6320                         END_PROFILE(SMBcopy);
6321                         return;
6322                 }
6323
6324                 status = copy_file(ctx,conn,directory,newname,ofun,
6325                                 count,target_is_directory);
6326
6327                 if(!NT_STATUS_IS_OK(status)) {
6328                         reply_nterror(req, status);
6329                         END_PROFILE(SMBcopy);
6330                         return;
6331                 } else {
6332                         count++;
6333                 }
6334         } else {
6335                 struct smb_Dir *dir_hnd = NULL;
6336                 const char *dname = NULL;
6337                 long offset = 0;
6338
6339                 if (strequal(mask,"????????.???")) {
6340                         mask[0] = '*';
6341                         mask[1] = '\0';
6342                 }
6343
6344                 status = check_name(conn, directory);
6345                 if (!NT_STATUS_IS_OK(status)) {
6346                         reply_nterror(req, status);
6347                         END_PROFILE(SMBcopy);
6348                         return;
6349                 }
6350
6351                 dir_hnd = OpenDir(conn, directory, mask, 0);
6352                 if (dir_hnd == NULL) {
6353                         status = map_nt_error_from_unix(errno);
6354                         reply_nterror(req, status);
6355                         END_PROFILE(SMBcopy);
6356                         return;
6357                 }
6358
6359                 error = ERRbadfile;
6360
6361                 while ((dname = ReadDirName(dir_hnd, &offset))) {
6362                         char *destname = NULL;
6363                         char *fname = NULL;
6364
6365                         if (ISDOT(dname) || ISDOTDOT(dname)) {
6366                                 continue;
6367                         }
6368
6369                         if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
6370                                 continue;
6371                         }
6372
6373                         if(!mask_match(dname, mask, conn->case_sensitive)) {
6374                                 continue;
6375                         }
6376
6377                         error = ERRnoaccess;
6378                         fname = talloc_asprintf(ctx,
6379                                         "%s/%s",
6380                                         directory,
6381                                         dname);
6382                         if (!fname) {
6383                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6384                                 END_PROFILE(SMBcopy);
6385                                 return;
6386                         }
6387
6388                         if (!resolve_wildcards(ctx,
6389                                         fname,newname,&destname)) {
6390                                 continue;
6391                         }
6392                         if (!destname) {
6393                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6394                                 END_PROFILE(SMBcopy);
6395                                 return;
6396                         }
6397
6398                         status = check_name(conn, fname);
6399                         if (!NT_STATUS_IS_OK(status)) {
6400                                 reply_nterror(req, status);
6401                                 END_PROFILE(SMBcopy);
6402                                 return;
6403                         }
6404
6405                         status = check_name(conn, destname);
6406                         if (!NT_STATUS_IS_OK(status)) {
6407                                 reply_nterror(req, status);
6408                                 END_PROFILE(SMBcopy);
6409                                 return;
6410                         }
6411
6412                         DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
6413
6414                         status = copy_file(ctx,conn,fname,destname,ofun,
6415                                         count,target_is_directory);
6416                         if (NT_STATUS_IS_OK(status)) {
6417                                 count++;
6418                         }
6419                         TALLOC_FREE(fname);
6420                         TALLOC_FREE(destname);
6421                 }
6422                 CloseDir(dir_hnd);
6423         }
6424
6425         if (count == 0) {
6426                 if(err) {
6427                         /* Error on close... */
6428                         errno = err;
6429                         reply_unixerror(req, ERRHRD, ERRgeneral);
6430                         END_PROFILE(SMBcopy);
6431                         return;
6432                 }
6433
6434                 reply_doserror(req, ERRDOS, error);
6435                 END_PROFILE(SMBcopy);
6436                 return;
6437         }
6438
6439         reply_outbuf(req, 1, 0);
6440         SSVAL(req->outbuf,smb_vwv0,count);
6441
6442         END_PROFILE(SMBcopy);
6443         return;
6444 }
6445
6446 #undef DBGC_CLASS
6447 #define DBGC_CLASS DBGC_LOCKING
6448
6449 /****************************************************************************
6450  Get a lock pid, dealing with large count requests.
6451 ****************************************************************************/
6452
6453 uint32 get_lock_pid( char *data, int data_offset, bool large_file_format)
6454 {
6455         if(!large_file_format)
6456                 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
6457         else
6458                 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6459 }
6460
6461 /****************************************************************************
6462  Get a lock count, dealing with large count requests.
6463 ****************************************************************************/
6464
6465 SMB_BIG_UINT get_lock_count( char *data, int data_offset, bool large_file_format)
6466 {
6467         SMB_BIG_UINT count = 0;
6468
6469         if(!large_file_format) {
6470                 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6471         } else {
6472
6473 #if defined(HAVE_LONGLONG)
6474                 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6475                         ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6476 #else /* HAVE_LONGLONG */
6477
6478                 /*
6479                  * NT4.x seems to be broken in that it sends large file (64 bit)
6480                  * lockingX calls even if the CAP_LARGE_FILES was *not*
6481                  * negotiated. For boxes without large unsigned ints truncate the
6482                  * lock count by dropping the top 32 bits.
6483                  */
6484
6485                 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6486                         DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6487                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6488                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6489                                 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6490                 }
6491
6492                 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6493 #endif /* HAVE_LONGLONG */
6494         }
6495
6496         return count;
6497 }
6498
6499 #if !defined(HAVE_LONGLONG)
6500 /****************************************************************************
6501  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6502 ****************************************************************************/
6503
6504 static uint32 map_lock_offset(uint32 high, uint32 low)
6505 {
6506         unsigned int i;
6507         uint32 mask = 0;
6508         uint32 highcopy = high;
6509  
6510         /*
6511          * Try and find out how many significant bits there are in high.
6512          */
6513  
6514         for(i = 0; highcopy; i++)
6515                 highcopy >>= 1;
6516  
6517         /*
6518          * We use 31 bits not 32 here as POSIX
6519          * lock offsets may not be negative.
6520          */
6521  
6522         mask = (~0) << (31 - i);
6523  
6524         if(low & mask)
6525                 return 0; /* Fail. */
6526  
6527         high <<= (31 - i);
6528  
6529         return (high|low);
6530 }
6531 #endif /* !defined(HAVE_LONGLONG) */
6532
6533 /****************************************************************************
6534  Get a lock offset, dealing with large offset requests.
6535 ****************************************************************************/
6536
6537 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, bool large_file_format, bool *err)
6538 {
6539         SMB_BIG_UINT offset = 0;
6540
6541         *err = False;
6542
6543         if(!large_file_format) {
6544                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
6545         } else {
6546
6547 #if defined(HAVE_LONGLONG)
6548                 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
6549                                 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
6550 #else /* HAVE_LONGLONG */
6551
6552                 /*
6553                  * NT4.x seems to be broken in that it sends large file (64 bit)
6554                  * lockingX calls even if the CAP_LARGE_FILES was *not*
6555                  * negotiated. For boxes without large unsigned ints mangle the
6556                  * lock offset by mapping the top 32 bits onto the lower 32.
6557                  */
6558       
6559                 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
6560                         uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6561                         uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
6562                         uint32 new_low = 0;
6563
6564                         if((new_low = map_lock_offset(high, low)) == 0) {
6565                                 *err = True;
6566                                 return (SMB_BIG_UINT)-1;
6567                         }
6568
6569                         DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
6570                                 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
6571                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
6572                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
6573                 }
6574
6575                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6576 #endif /* HAVE_LONGLONG */
6577         }
6578
6579         return offset;
6580 }
6581
6582 /****************************************************************************
6583  Reply to a lockingX request.
6584 ****************************************************************************/
6585
6586 void reply_lockingX(connection_struct *conn, struct smb_request *req)
6587 {
6588         files_struct *fsp;
6589         unsigned char locktype;
6590         unsigned char oplocklevel;
6591         uint16 num_ulocks;
6592         uint16 num_locks;
6593         SMB_BIG_UINT count = 0, offset = 0;
6594         uint32 lock_pid;
6595         int32 lock_timeout;
6596         int i;
6597         char *data;
6598         bool large_file_format;
6599         bool err;
6600         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
6601
6602         START_PROFILE(SMBlockingX);
6603
6604         if (req->wct < 8) {
6605                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6606                 END_PROFILE(SMBlockingX);
6607                 return;
6608         }
6609         
6610         fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
6611         locktype = CVAL(req->inbuf,smb_vwv3);
6612         oplocklevel = CVAL(req->inbuf,smb_vwv3+1);
6613         num_ulocks = SVAL(req->inbuf,smb_vwv6);
6614         num_locks = SVAL(req->inbuf,smb_vwv7);
6615         lock_timeout = IVAL(req->inbuf,smb_vwv4);
6616         large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
6617
6618         if (!check_fsp(conn, req, fsp, &current_user)) {
6619                 END_PROFILE(SMBlockingX);
6620                 return;
6621         }
6622         
6623         data = smb_buf(req->inbuf);
6624
6625         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
6626                 /* we don't support these - and CANCEL_LOCK makes w2k
6627                    and XP reboot so I don't really want to be
6628                    compatible! (tridge) */
6629                 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
6630                 END_PROFILE(SMBlockingX);
6631                 return;
6632         }
6633         
6634         /* Check if this is an oplock break on a file
6635            we have granted an oplock on.
6636         */
6637         if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
6638                 /* Client can insist on breaking to none. */
6639                 bool break_to_none = (oplocklevel == 0);
6640                 bool result;
6641
6642                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6643                          "for fnum = %d\n", (unsigned int)oplocklevel,
6644                          fsp->fnum ));
6645
6646                 /*
6647                  * Make sure we have granted an exclusive or batch oplock on
6648                  * this file.
6649                  */
6650                 
6651                 if (fsp->oplock_type == 0) {
6652
6653                         /* The Samba4 nbench simulator doesn't understand
6654                            the difference between break to level2 and break
6655                            to none from level2 - it sends oplock break
6656                            replies in both cases. Don't keep logging an error
6657                            message here - just ignore it. JRA. */
6658
6659                         DEBUG(5,("reply_lockingX: Error : oplock break from "
6660                                  "client for fnum = %d (oplock=%d) and no "
6661                                  "oplock granted on this file (%s).\n",
6662                                  fsp->fnum, fsp->oplock_type, fsp->fsp_name));
6663
6664                         /* if this is a pure oplock break request then don't
6665                          * send a reply */
6666                         if (num_locks == 0 && num_ulocks == 0) {
6667                                 END_PROFILE(SMBlockingX);
6668                                 return;
6669                         } else {
6670                                 END_PROFILE(SMBlockingX);
6671                                 reply_doserror(req, ERRDOS, ERRlock);
6672                                 return;
6673                         }
6674                 }
6675
6676                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
6677                     (break_to_none)) {
6678                         result = remove_oplock(fsp);
6679                 } else {
6680                         result = downgrade_oplock(fsp);
6681                 }
6682                 
6683                 if (!result) {
6684                         DEBUG(0, ("reply_lockingX: error in removing "
6685                                   "oplock on file %s\n", fsp->fsp_name));
6686                         /* Hmmm. Is this panic justified? */
6687                         smb_panic("internal tdb error");
6688                 }
6689
6690                 reply_to_oplock_break_requests(fsp);
6691
6692                 /* if this is a pure oplock break request then don't send a
6693                  * reply */
6694                 if (num_locks == 0 && num_ulocks == 0) {
6695                         /* Sanity check - ensure a pure oplock break is not a
6696                            chained request. */
6697                         if(CVAL(req->inbuf,smb_vwv0) != 0xff)
6698                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
6699                                          "break is a chained %d request !\n",
6700                                          (unsigned int)CVAL(req->inbuf,
6701                                                             smb_vwv0) ));
6702                         END_PROFILE(SMBlockingX);
6703                         return;
6704                 }
6705         }
6706
6707         /*
6708          * We do this check *after* we have checked this is not a oplock break
6709          * response message. JRA.
6710          */
6711         
6712         release_level_2_oplocks_on_change(fsp);
6713
6714         if (smb_buflen(req->inbuf) <
6715             (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
6716                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6717                 END_PROFILE(SMBlockingX);
6718                 return;
6719         }
6720         
6721         /* Data now points at the beginning of the list
6722            of smb_unlkrng structs */
6723         for(i = 0; i < (int)num_ulocks; i++) {
6724                 lock_pid = get_lock_pid( data, i, large_file_format);
6725                 count = get_lock_count( data, i, large_file_format);
6726                 offset = get_lock_offset( data, i, large_file_format, &err);
6727                 
6728                 /*
6729                  * There is no error code marked "stupid client bug".... :-).
6730                  */
6731                 if(err) {
6732                         END_PROFILE(SMBlockingX);
6733                         reply_doserror(req, ERRDOS, ERRnoaccess);
6734                         return;
6735                 }
6736
6737                 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
6738                           "pid %u, file %s\n", (double)offset, (double)count,
6739                           (unsigned int)lock_pid, fsp->fsp_name ));
6740                 
6741                 status = do_unlock(smbd_messaging_context(),
6742                                 fsp,
6743                                 lock_pid,
6744                                 count,
6745                                 offset,
6746                                 WINDOWS_LOCK);
6747
6748                 if (NT_STATUS_V(status)) {
6749                         END_PROFILE(SMBlockingX);
6750                         reply_nterror(req, status);
6751                         return;
6752                 }
6753         }
6754
6755         /* Setup the timeout in seconds. */
6756
6757         if (!lp_blocking_locks(SNUM(conn))) {
6758                 lock_timeout = 0;
6759         }
6760         
6761         /* Now do any requested locks */
6762         data += ((large_file_format ? 20 : 10)*num_ulocks);
6763         
6764         /* Data now points at the beginning of the list
6765            of smb_lkrng structs */
6766         
6767         for(i = 0; i < (int)num_locks; i++) {
6768                 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
6769                                 READ_LOCK:WRITE_LOCK);
6770                 lock_pid = get_lock_pid( data, i, large_file_format);
6771                 count = get_lock_count( data, i, large_file_format);
6772                 offset = get_lock_offset( data, i, large_file_format, &err);
6773                 
6774                 /*
6775                  * There is no error code marked "stupid client bug".... :-).
6776                  */
6777                 if(err) {
6778                         END_PROFILE(SMBlockingX);
6779                         reply_doserror(req, ERRDOS, ERRnoaccess);
6780                         return;
6781                 }
6782                 
6783                 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
6784                           "%u, file %s timeout = %d\n", (double)offset,
6785                           (double)count, (unsigned int)lock_pid,
6786                           fsp->fsp_name, (int)lock_timeout ));
6787                 
6788                 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
6789                         if (lp_blocking_locks(SNUM(conn))) {
6790
6791                                 /* Schedule a message to ourselves to
6792                                    remove the blocking lock record and
6793                                    return the right error. */
6794
6795                                 if (!blocking_lock_cancel(fsp,
6796                                                 lock_pid,
6797                                                 offset,
6798                                                 count,
6799                                                 WINDOWS_LOCK,
6800                                                 locktype,
6801                                                 NT_STATUS_FILE_LOCK_CONFLICT)) {
6802                                         END_PROFILE(SMBlockingX);
6803                                         reply_nterror(
6804                                                 req,
6805                                                 NT_STATUS_DOS(
6806                                                         ERRDOS,
6807                                                         ERRcancelviolation));
6808                                         return;
6809                                 }
6810                         }
6811                         /* Remove a matching pending lock. */
6812                         status = do_lock_cancel(fsp,
6813                                                 lock_pid,
6814                                                 count,
6815                                                 offset,
6816                                                 WINDOWS_LOCK);
6817                 } else {
6818                         bool blocking_lock = lock_timeout ? True : False;
6819                         bool defer_lock = False;
6820                         struct byte_range_lock *br_lck;
6821                         uint32 block_smbpid;
6822
6823                         br_lck = do_lock(smbd_messaging_context(),
6824                                         fsp,
6825                                         lock_pid,
6826                                         count,
6827                                         offset, 
6828                                         lock_type,
6829                                         WINDOWS_LOCK,
6830                                         blocking_lock,
6831                                         &status,
6832                                         &block_smbpid);
6833
6834                         if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6835                                 /* Windows internal resolution for blocking locks seems
6836                                    to be about 200ms... Don't wait for less than that. JRA. */
6837                                 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
6838                                         lock_timeout = lp_lock_spin_time();
6839                                 }
6840                                 defer_lock = True;
6841                         }
6842
6843                         /* This heuristic seems to match W2K3 very well. If a
6844                            lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
6845                            it pretends we asked for a timeout of between 150 - 300 milliseconds as
6846                            far as I can tell. Replacement for do_lock_spin(). JRA. */
6847
6848                         if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
6849                                         NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
6850                                 defer_lock = True;
6851                                 lock_timeout = lp_lock_spin_time();
6852                         }
6853
6854                         if (br_lck && defer_lock) {
6855                                 /*
6856                                  * A blocking lock was requested. Package up
6857                                  * this smb into a queued request and push it
6858                                  * onto the blocking lock queue.
6859                                  */
6860                                 if(push_blocking_lock_request(br_lck,
6861                                                         (char *)req->inbuf,
6862                                                         smb_len(req->inbuf)+4,
6863                                                         fsp,
6864                                                         lock_timeout,
6865                                                         i,
6866                                                         lock_pid,
6867                                                         lock_type,
6868                                                         WINDOWS_LOCK,
6869                                                         offset,
6870                                                         count,
6871                                                         block_smbpid)) {
6872                                         TALLOC_FREE(br_lck);
6873                                         END_PROFILE(SMBlockingX);
6874                                         return;
6875                                 }
6876                         }
6877
6878                         TALLOC_FREE(br_lck);
6879                 }
6880
6881                 if (NT_STATUS_V(status)) {
6882                         END_PROFILE(SMBlockingX);
6883                         reply_nterror(req, status);
6884                         return;
6885                 }
6886         }
6887         
6888         /* If any of the above locks failed, then we must unlock
6889            all of the previous locks (X/Open spec). */
6890
6891         if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
6892                         (i != num_locks) &&
6893                         (num_locks != 0)) {
6894                 /*
6895                  * Ensure we don't do a remove on the lock that just failed,
6896                  * as under POSIX rules, if we have a lock already there, we
6897                  * will delete it (and we shouldn't) .....
6898                  */
6899                 for(i--; i >= 0; i--) {
6900                         lock_pid = get_lock_pid( data, i, large_file_format);
6901                         count = get_lock_count( data, i, large_file_format);
6902                         offset = get_lock_offset( data, i, large_file_format,
6903                                                   &err);
6904                         
6905                         /*
6906                          * There is no error code marked "stupid client
6907                          * bug".... :-).
6908                          */
6909                         if(err) {
6910                                 END_PROFILE(SMBlockingX);
6911                                 reply_doserror(req, ERRDOS, ERRnoaccess);
6912                                 return;
6913                         }
6914                         
6915                         do_unlock(smbd_messaging_context(),
6916                                 fsp,
6917                                 lock_pid,
6918                                 count,
6919                                 offset,
6920                                 WINDOWS_LOCK);
6921                 }
6922                 END_PROFILE(SMBlockingX);
6923                 reply_nterror(req, status);
6924                 return;
6925         }
6926
6927         reply_outbuf(req, 2, 0);
6928         
6929         DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
6930                   fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
6931         
6932         END_PROFILE(SMBlockingX);
6933         chain_reply(req);
6934 }
6935
6936 #undef DBGC_CLASS
6937 #define DBGC_CLASS DBGC_ALL
6938
6939 /****************************************************************************
6940  Reply to a SMBreadbmpx (read block multiplex) request.
6941  Always reply with an error, if someone has a platform really needs this,
6942  please contact vl@samba.org
6943 ****************************************************************************/
6944
6945 void reply_readbmpx(connection_struct *conn, struct smb_request *req)
6946 {
6947         START_PROFILE(SMBreadBmpx);
6948         reply_doserror(req, ERRSRV, ERRuseSTD);
6949         END_PROFILE(SMBreadBmpx);
6950         return;
6951 }
6952
6953 /****************************************************************************
6954  Reply to a SMBreadbs (read block multiplex secondary) request.
6955  Always reply with an error, if someone has a platform really needs this,
6956  please contact vl@samba.org
6957 ****************************************************************************/
6958
6959 void reply_readbs(connection_struct *conn, struct smb_request *req)
6960 {
6961         START_PROFILE(SMBreadBs);
6962         reply_doserror(req, ERRSRV, ERRuseSTD);
6963         END_PROFILE(SMBreadBs);
6964         return;
6965 }
6966
6967 /****************************************************************************
6968  Reply to a SMBsetattrE.
6969 ****************************************************************************/
6970
6971 void reply_setattrE(connection_struct *conn, struct smb_request *req)
6972 {
6973         struct timespec ts[2];
6974         files_struct *fsp;
6975
6976         START_PROFILE(SMBsetattrE);
6977
6978         if (req->wct < 7) {
6979                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6980                 END_PROFILE(SMBsetattrE);
6981                 return;
6982         }
6983
6984         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
6985
6986         if(!fsp || (fsp->conn != conn)) {
6987                 reply_doserror(req, ERRDOS, ERRbadfid);
6988                 END_PROFILE(SMBsetattrE);
6989                 return;
6990         }
6991
6992
6993         /*
6994          * Convert the DOS times into unix times. Ignore create
6995          * time as UNIX can't set this.
6996          */
6997
6998         ts[0] = convert_time_t_to_timespec(
6999                 srv_make_unix_date2(req->inbuf+smb_vwv3)); /* atime. */
7000         ts[1] = convert_time_t_to_timespec(
7001                 srv_make_unix_date2(req->inbuf+smb_vwv5)); /* mtime. */
7002   
7003         reply_outbuf(req, 0, 0);
7004
7005         /* 
7006          * Patch from Ray Frush <frush@engr.colostate.edu>
7007          * Sometimes times are sent as zero - ignore them.
7008          */
7009
7010         if (null_timespec(ts[0]) && null_timespec(ts[1])) {
7011                 /* Ignore request */
7012                 if( DEBUGLVL( 3 ) ) {
7013                         dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
7014                         dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
7015                 }
7016                 END_PROFILE(SMBsetattrE);
7017                 return;
7018         } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
7019                 /* set modify time = to access time if modify time was unset */
7020                 ts[1] = ts[0];
7021         }
7022
7023         /* Set the date on this file */
7024         /* Should we set pending modtime here ? JRA */
7025         if(file_ntimes(conn, fsp->fsp_name, ts)) {
7026                 reply_doserror(req, ERRDOS, ERRnoaccess);
7027                 END_PROFILE(SMBsetattrE);
7028                 return;
7029         }
7030   
7031         DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
7032                 fsp->fnum,
7033                 (unsigned int)ts[0].tv_sec,
7034                 (unsigned int)ts[1].tv_sec));
7035
7036         END_PROFILE(SMBsetattrE);
7037         return;
7038 }
7039
7040
7041 /* Back from the dead for OS/2..... JRA. */
7042
7043 /****************************************************************************
7044  Reply to a SMBwritebmpx (write block multiplex primary) request.
7045  Always reply with an error, if someone has a platform really needs this,
7046  please contact vl@samba.org
7047 ****************************************************************************/
7048
7049 void reply_writebmpx(connection_struct *conn, struct smb_request *req)
7050 {
7051         START_PROFILE(SMBwriteBmpx);
7052         reply_doserror(req, ERRSRV, ERRuseSTD);
7053         END_PROFILE(SMBwriteBmpx);
7054         return;
7055 }
7056
7057 /****************************************************************************
7058  Reply to a SMBwritebs (write block multiplex secondary) request.
7059  Always reply with an error, if someone has a platform really needs this,
7060  please contact vl@samba.org
7061 ****************************************************************************/
7062
7063 void reply_writebs(connection_struct *conn, struct smb_request *req)
7064 {
7065         START_PROFILE(SMBwriteBs);
7066         reply_doserror(req, ERRSRV, ERRuseSTD);
7067         END_PROFILE(SMBwriteBs);
7068         return;
7069 }
7070
7071 /****************************************************************************
7072  Reply to a SMBgetattrE.
7073 ****************************************************************************/
7074
7075 void reply_getattrE(connection_struct *conn, struct smb_request *req)
7076 {
7077         SMB_STRUCT_STAT sbuf;
7078         int mode;
7079         files_struct *fsp;
7080
7081         START_PROFILE(SMBgetattrE);
7082
7083         if (req->wct < 1) {
7084                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7085                 END_PROFILE(SMBgetattrE);
7086                 return;
7087         }
7088
7089         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
7090
7091         if(!fsp || (fsp->conn != conn)) {
7092                 reply_doserror(req, ERRDOS, ERRbadfid);
7093                 END_PROFILE(SMBgetattrE);
7094                 return;
7095         }
7096
7097         /* Do an fstat on this file */
7098         if(fsp_stat(fsp, &sbuf)) {
7099                 reply_unixerror(req, ERRDOS, ERRnoaccess);
7100                 END_PROFILE(SMBgetattrE);
7101                 return;
7102         }
7103   
7104         mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7105   
7106         /*
7107          * Convert the times into dos times. Set create
7108          * date to be last modify date as UNIX doesn't save
7109          * this.
7110          */
7111
7112         reply_outbuf(req, 11, 0);
7113
7114         srv_put_dos_date2((char *)req->outbuf, smb_vwv0,
7115                           get_create_time(&sbuf,
7116                                           lp_fake_dir_create_times(SNUM(conn))));
7117         srv_put_dos_date2((char *)req->outbuf, smb_vwv2, sbuf.st_atime);
7118         /* Should we check pending modtime here ? JRA */
7119         srv_put_dos_date2((char *)req->outbuf, smb_vwv4, sbuf.st_mtime);
7120
7121         if (mode & aDIR) {
7122                 SIVAL(req->outbuf, smb_vwv6, 0);
7123                 SIVAL(req->outbuf, smb_vwv8, 0);
7124         } else {
7125                 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
7126                 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_size);
7127                 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7128         }
7129         SSVAL(req->outbuf,smb_vwv10, mode);
7130   
7131         DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7132   
7133         END_PROFILE(SMBgetattrE);
7134         return;
7135 }