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