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