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