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