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