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