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