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