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