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