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