s3: Remove smbd_server_fd from netbios_session_retarget
[samba.git] / source3 / smbd / reply.c
1 /*
2    Unix SMB/CIFS implementation.
3    Main SMB reply routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Andrew Bartlett      2001
6    Copyright (C) Jeremy Allison 1992-2007.
7    Copyright (C) Volker Lendecke 2007
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22 /*
23    This file handles most of the reply_ calls that the server
24    makes to handle specific protocols
25 */
26
27 #include "includes.h"
28 #include "printing.h"
29 #include "smbd/globals.h"
30 #include "../librpc/gen_ndr/cli_spoolss.h"
31 #include "rpc_client/cli_spoolss.h"
32 #include "rpc_client/init_spoolss.h"
33
34 /****************************************************************************
35  Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
36  path or anything including wildcards.
37  We're assuming here that '/' is not the second byte in any multibyte char
38  set (a safe assumption). '\\' *may* be the second byte in a multibyte char
39  set.
40 ****************************************************************************/
41
42 /* Custom version for processing POSIX paths. */
43 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
44
45 static NTSTATUS check_path_syntax_internal(char *path,
46                                            bool posix_path,
47                                            bool *p_last_component_contains_wcard)
48 {
49         char *d = path;
50         const char *s = path;
51         NTSTATUS ret = NT_STATUS_OK;
52         bool start_of_name_component = True;
53         bool stream_started = false;
54
55         *p_last_component_contains_wcard = False;
56
57         while (*s) {
58                 if (stream_started) {
59                         switch (*s) {
60                         case '/':
61                         case '\\':
62                                 return NT_STATUS_OBJECT_NAME_INVALID;
63                         case ':':
64                                 if (s[1] == '\0') {
65                                         return NT_STATUS_OBJECT_NAME_INVALID;
66                                 }
67                                 if (strchr_m(&s[1], ':')) {
68                                         return NT_STATUS_OBJECT_NAME_INVALID;
69                                 }
70                                 break;
71                         }
72                 }
73
74                 if ((*s == ':') && !posix_path && !stream_started) {
75                         if (*p_last_component_contains_wcard) {
76                                 return NT_STATUS_OBJECT_NAME_INVALID;
77                         }
78                         /* Stream names allow more characters than file names.
79                            We're overloading posix_path here to allow a wider
80                            range of characters. If stream_started is true this
81                            is still a Windows path even if posix_path is true.
82                            JRA.
83                         */
84                         stream_started = true;
85                         start_of_name_component = false;
86                         posix_path = true;
87
88                         if (s[1] == '\0') {
89                                 return NT_STATUS_OBJECT_NAME_INVALID;
90                         }
91                 }
92
93                 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
94                         /*
95                          * Safe to assume is not the second part of a mb char
96                          * as this is handled below.
97                          */
98                         /* Eat multiple '/' or '\\' */
99                         while (IS_PATH_SEP(*s,posix_path)) {
100                                 s++;
101                         }
102                         if ((d != path) && (*s != '\0')) {
103                                 /* We only care about non-leading or trailing '/' or '\\' */
104                                 *d++ = '/';
105                         }
106
107                         start_of_name_component = True;
108                         /* New component. */
109                         *p_last_component_contains_wcard = False;
110                         continue;
111                 }
112
113                 if (start_of_name_component) {
114                         if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
115                                 /* Uh oh - "/../" or "\\..\\"  or "/..\0" or "\\..\0" ! */
116
117                                 /*
118                                  * No mb char starts with '.' so we're safe checking the directory separator here.
119                                  */
120
121                                 /* If  we just added a '/' - delete it */
122                                 if ((d > path) && (*(d-1) == '/')) {
123                                         *(d-1) = '\0';
124                                         d--;
125                                 }
126
127                                 /* Are we at the start ? Can't go back further if so. */
128                                 if (d <= path) {
129                                         ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
130                                         break;
131                                 }
132                                 /* Go back one level... */
133                                 /* We know this is safe as '/' cannot be part of a mb sequence. */
134                                 /* NOTE - if this assumption is invalid we are not in good shape... */
135                                 /* Decrement d first as d points to the *next* char to write into. */
136                                 for (d--; d > path; d--) {
137                                         if (*d == '/')
138                                                 break;
139                                 }
140                                 s += 2; /* Else go past the .. */
141                                 /* We're still at the start of a name component, just the previous one. */
142                                 continue;
143
144                         } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
145                                 if (posix_path) {
146                                         /* Eat the '.' */
147                                         s++;
148                                         continue;
149                                 }
150                         }
151
152                 }
153
154                 if (!(*s & 0x80)) {
155                         if (!posix_path) {
156                                 if (*s <= 0x1f || *s == '|') {
157                                         return NT_STATUS_OBJECT_NAME_INVALID;
158                                 }
159                                 switch (*s) {
160                                         case '*':
161                                         case '?':
162                                         case '<':
163                                         case '>':
164                                         case '"':
165                                                 *p_last_component_contains_wcard = True;
166                                                 break;
167                                         default:
168                                                 break;
169                                 }
170                         }
171                         *d++ = *s++;
172                 } else {
173                         size_t siz;
174                         /* Get the size of the next MB character. */
175                         next_codepoint(s,&siz);
176                         switch(siz) {
177                                 case 5:
178                                         *d++ = *s++;
179                                         /*fall through*/
180                                 case 4:
181                                         *d++ = *s++;
182                                         /*fall through*/
183                                 case 3:
184                                         *d++ = *s++;
185                                         /*fall through*/
186                                 case 2:
187                                         *d++ = *s++;
188                                         /*fall through*/
189                                 case 1:
190                                         *d++ = *s++;
191                                         break;
192                                 default:
193                                         DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
194                                         *d = '\0';
195                                         return NT_STATUS_INVALID_PARAMETER;
196                         }
197                 }
198                 start_of_name_component = False;
199         }
200
201         *d = '\0';
202
203         return ret;
204 }
205
206 /****************************************************************************
207  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
208  No wildcards allowed.
209 ****************************************************************************/
210
211 NTSTATUS check_path_syntax(char *path)
212 {
213         bool ignore;
214         return check_path_syntax_internal(path, False, &ignore);
215 }
216
217 /****************************************************************************
218  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
219  Wildcards allowed - p_contains_wcard returns true if the last component contained
220  a wildcard.
221 ****************************************************************************/
222
223 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
224 {
225         return check_path_syntax_internal(path, False, p_contains_wcard);
226 }
227
228 /****************************************************************************
229  Check the path for a POSIX client.
230  We're assuming here that '/' is not the second byte in any multibyte char
231  set (a safe assumption).
232 ****************************************************************************/
233
234 NTSTATUS check_path_syntax_posix(char *path)
235 {
236         bool ignore;
237         return check_path_syntax_internal(path, True, &ignore);
238 }
239
240 /****************************************************************************
241  Pull a string and check the path allowing a wilcard - provide for error return.
242 ****************************************************************************/
243
244 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
245                         const char *base_ptr,
246                         uint16 smb_flags2,
247                         char **pp_dest,
248                         const char *src,
249                         size_t src_len,
250                         int flags,
251                         NTSTATUS *err,
252                         bool *contains_wcard)
253 {
254         size_t ret;
255
256         *pp_dest = NULL;
257
258         ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
259                                  src_len, flags);
260
261         if (!*pp_dest) {
262                 *err = NT_STATUS_INVALID_PARAMETER;
263                 return ret;
264         }
265
266         *contains_wcard = False;
267
268         if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
269                 /*
270                  * For a DFS path the function parse_dfs_path()
271                  * will do the path processing, just make a copy.
272                  */
273                 *err = NT_STATUS_OK;
274                 return ret;
275         }
276
277         if (lp_posix_pathnames()) {
278                 *err = check_path_syntax_posix(*pp_dest);
279         } else {
280                 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
281         }
282
283         return ret;
284 }
285
286 /****************************************************************************
287  Pull a string and check the path - provide for error return.
288 ****************************************************************************/
289
290 size_t srvstr_get_path(TALLOC_CTX *ctx,
291                         const char *base_ptr,
292                         uint16 smb_flags2,
293                         char **pp_dest,
294                         const char *src,
295                         size_t src_len,
296                         int flags,
297                         NTSTATUS *err)
298 {
299         bool ignore;
300         return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
301                                      src_len, flags, err, &ignore);
302 }
303
304 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
305                                  char **pp_dest, const char *src, int flags,
306                                  NTSTATUS *err, bool *contains_wcard)
307 {
308         return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
309                                      pp_dest, src, smbreq_bufrem(req, src),
310                                      flags, err, contains_wcard);
311 }
312
313 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
314                            char **pp_dest, const char *src, int flags,
315                            NTSTATUS *err)
316 {
317         bool ignore;
318         return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
319                                          flags, err, &ignore);
320 }
321
322 /****************************************************************************
323  Check if we have a correct fsp pointing to a file. Basic check for open fsp.
324 ****************************************************************************/
325
326 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
327                     files_struct *fsp)
328 {
329         if ((fsp == NULL) || (conn == NULL)) {
330                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
331                 return False;
332         }
333         if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
334                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
335                 return False;
336         }
337         return True;
338 }
339
340 /****************************************************************************
341  Check if we have a correct fsp pointing to a file.
342 ****************************************************************************/
343
344 bool check_fsp(connection_struct *conn, struct smb_request *req,
345                files_struct *fsp)
346 {
347         if (!check_fsp_open(conn, req, fsp)) {
348                 return False;
349         }
350         if (fsp->is_directory) {
351                 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
352                 return False;
353         }
354         if (fsp->fh->fd == -1) {
355                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
356                 return False;
357         }
358         fsp->num_smb_operations++;
359         return True;
360 }
361
362 /****************************************************************************
363  Check if we have a correct fsp pointing to a quota fake file. Replacement for
364  the CHECK_NTQUOTA_HANDLE_OK macro.
365 ****************************************************************************/
366
367 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
368                               files_struct *fsp)
369 {
370         if (!check_fsp_open(conn, req, fsp)) {
371                 return false;
372         }
373
374         if (fsp->is_directory) {
375                 return false;
376         }
377
378         if (fsp->fake_file_handle == NULL) {
379                 return false;
380         }
381
382         if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
383                 return false;
384         }
385
386         if (fsp->fake_file_handle->private_data == NULL) {
387                 return false;
388         }
389
390         return true;
391 }
392
393 static bool netbios_session_retarget(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(smbd_server_fd(),buf,cur_read) != cur_read) {
2814                         SAFE_FREE(buf);
2815                         return -1;
2816                 }
2817                 tosend -= cur_read;
2818                 startpos += cur_read;
2819         }
2820
2821         SAFE_FREE(buf);
2822         return (ssize_t)nread;
2823 }
2824
2825 #if defined(WITH_SENDFILE)
2826 /****************************************************************************
2827  Deal with the case of sendfile reading less bytes from the file than
2828  requested. Fill with zeros (all we can do).
2829 ****************************************************************************/
2830
2831 static void sendfile_short_send(files_struct *fsp,
2832                                 ssize_t nread,
2833                                 size_t headersize,
2834                                 size_t smb_maxcnt)
2835 {
2836 #define SHORT_SEND_BUFSIZE 1024
2837         if (nread < headersize) {
2838                 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2839                         "header for file %s (%s). Terminating\n",
2840                         fsp_str_dbg(fsp), strerror(errno)));
2841                 exit_server_cleanly("sendfile_short_send failed");
2842         }
2843
2844         nread -= headersize;
2845
2846         if (nread < smb_maxcnt) {
2847                 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2848                 if (!buf) {
2849                         exit_server_cleanly("sendfile_short_send: "
2850                                 "malloc failed");
2851                 }
2852
2853                 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2854                         "with zeros !\n", fsp_str_dbg(fsp)));
2855
2856                 while (nread < smb_maxcnt) {
2857                         /*
2858                          * We asked for the real file size and told sendfile
2859                          * to not go beyond the end of the file. But it can
2860                          * happen that in between our fstat call and the
2861                          * sendfile call the file was truncated. This is very
2862                          * bad because we have already announced the larger
2863                          * number of bytes to the client.
2864                          *
2865                          * The best we can do now is to send 0-bytes, just as
2866                          * a read from a hole in a sparse file would do.
2867                          *
2868                          * This should happen rarely enough that I don't care
2869                          * about efficiency here :-)
2870                          */
2871                         size_t to_write;
2872
2873                         to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2874                         if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2875                                 exit_server_cleanly("sendfile_short_send: "
2876                                         "write_data failed");
2877                         }
2878                         nread += to_write;
2879                 }
2880                 SAFE_FREE(buf);
2881         }
2882 }
2883 #endif /* defined WITH_SENDFILE */
2884
2885 /****************************************************************************
2886  Return a readbraw error (4 bytes of zero).
2887 ****************************************************************************/
2888
2889 static void reply_readbraw_error(struct smbd_server_connection *sconn)
2890 {
2891         char header[4];
2892
2893         SIVAL(header,0,0);
2894
2895         smbd_lock_socket(sconn);
2896         if (write_data(smbd_server_fd(),header,4) != 4) {
2897                 fail_readraw();
2898         }
2899         smbd_unlock_socket(sconn);
2900 }
2901
2902 /****************************************************************************
2903  Use sendfile in readbraw.
2904 ****************************************************************************/
2905
2906 static void send_file_readbraw(connection_struct *conn,
2907                                struct smb_request *req,
2908                                files_struct *fsp,
2909                                SMB_OFF_T startpos,
2910                                size_t nread,
2911                                ssize_t mincount)
2912 {
2913         struct smbd_server_connection *sconn = req->sconn;
2914         char *outbuf = NULL;
2915         ssize_t ret=0;
2916
2917 #if defined(WITH_SENDFILE)
2918         /*
2919          * We can only use sendfile on a non-chained packet 
2920          * but we can use on a non-oplocked file. tridge proved this
2921          * on a train in Germany :-). JRA.
2922          * reply_readbraw has already checked the length.
2923          */
2924
2925         if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2926             (fsp->wcp == NULL) &&
2927             lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
2928                 ssize_t sendfile_read = -1;
2929                 char header[4];
2930                 DATA_BLOB header_blob;
2931
2932                 _smb_setlen(header,nread);
2933                 header_blob = data_blob_const(header, 4);
2934
2935                 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2936                                 &header_blob, startpos, nread)) == -1) {
2937                         /* Returning ENOSYS means no data at all was sent.
2938                          * Do this as a normal read. */
2939                         if (errno == ENOSYS) {
2940                                 goto normal_readbraw;
2941                         }
2942
2943                         /*
2944                          * Special hack for broken Linux with no working sendfile. If we
2945                          * return EINTR we sent the header but not the rest of the data.
2946                          * Fake this up by doing read/write calls.
2947                          */
2948                         if (errno == EINTR) {
2949                                 /* Ensure we don't do this again. */
2950                                 set_use_sendfile(SNUM(conn), False);
2951                                 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2952
2953                                 if (fake_sendfile(fsp, startpos, nread) == -1) {
2954                                         DEBUG(0,("send_file_readbraw: "
2955                                                  "fake_sendfile failed for "
2956                                                  "file %s (%s).\n",
2957                                                  fsp_str_dbg(fsp),
2958                                                  strerror(errno)));
2959                                         exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2960                                 }
2961                                 return;
2962                         }
2963
2964                         DEBUG(0,("send_file_readbraw: sendfile failed for "
2965                                  "file %s (%s). Terminating\n",
2966                                  fsp_str_dbg(fsp), strerror(errno)));
2967                         exit_server_cleanly("send_file_readbraw sendfile failed");
2968                 } else if (sendfile_read == 0) {
2969                         /*
2970                          * Some sendfile implementations return 0 to indicate
2971                          * that there was a short read, but nothing was
2972                          * actually written to the socket.  In this case,
2973                          * fallback to the normal read path so the header gets
2974                          * the correct byte count.
2975                          */
2976                         DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2977                                   "bytes falling back to the normal read: "
2978                                   "%s\n", fsp_str_dbg(fsp)));
2979                         goto normal_readbraw;
2980                 }
2981
2982                 /* Deal with possible short send. */
2983                 if (sendfile_read != 4+nread) {
2984                         sendfile_short_send(fsp, sendfile_read, 4, nread);
2985                 }
2986                 return;
2987         }
2988
2989 normal_readbraw:
2990 #endif
2991
2992         outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2993         if (!outbuf) {
2994                 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2995                         (unsigned)(nread+4)));
2996                 reply_readbraw_error(sconn);
2997                 return;
2998         }
2999
3000         if (nread > 0) {
3001                 ret = read_file(fsp,outbuf+4,startpos,nread);
3002 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3003                 if (ret < mincount)
3004                         ret = 0;
3005 #else
3006                 if (ret < nread)
3007                         ret = 0;
3008 #endif
3009         }
3010
3011         _smb_setlen(outbuf,ret);
3012         if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
3013                 fail_readraw();
3014
3015         TALLOC_FREE(outbuf);
3016 }
3017
3018 /****************************************************************************
3019  Reply to a readbraw (core+ protocol).
3020 ****************************************************************************/
3021
3022 void reply_readbraw(struct smb_request *req)
3023 {
3024         connection_struct *conn = req->conn;
3025         struct smbd_server_connection *sconn = req->sconn;
3026         ssize_t maxcount,mincount;
3027         size_t nread = 0;
3028         SMB_OFF_T startpos;
3029         files_struct *fsp;
3030         struct lock_struct lock;
3031         SMB_OFF_T size = 0;
3032
3033         START_PROFILE(SMBreadbraw);
3034
3035         if (srv_is_signing_active(sconn) ||
3036             is_encrypted_packet(req->inbuf)) {
3037                 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3038                         "raw reads/writes are disallowed.");
3039         }
3040
3041         if (req->wct < 8) {
3042                 reply_readbraw_error(sconn);
3043                 END_PROFILE(SMBreadbraw);
3044                 return;
3045         }
3046
3047         if (sconn->smb1.echo_handler.trusted_fde) {
3048                 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3049                          "'async smb echo handler = yes'\n"));
3050                 reply_readbraw_error(sconn);
3051                 END_PROFILE(SMBreadbraw);
3052                 return;
3053         }
3054
3055         /*
3056          * Special check if an oplock break has been issued
3057          * and the readraw request croses on the wire, we must
3058          * return a zero length response here.
3059          */
3060
3061         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3062
3063         /*
3064          * We have to do a check_fsp by hand here, as
3065          * we must always return 4 zero bytes on error,
3066          * not a NTSTATUS.
3067          */
3068
3069         if (!fsp || !conn || conn != fsp->conn ||
3070                         req->vuid != fsp->vuid ||
3071                         fsp->is_directory || fsp->fh->fd == -1) {
3072                 /*
3073                  * fsp could be NULL here so use the value from the packet. JRA.
3074                  */
3075                 DEBUG(3,("reply_readbraw: fnum %d not valid "
3076                         "- cache prime?\n",
3077                         (int)SVAL(req->vwv+0, 0)));
3078                 reply_readbraw_error(sconn);
3079                 END_PROFILE(SMBreadbraw);
3080                 return;
3081         }
3082
3083         /* Do a "by hand" version of CHECK_READ. */
3084         if (!(fsp->can_read ||
3085                         ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3086                                 (fsp->access_mask & FILE_EXECUTE)))) {
3087                 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3088                                 (int)SVAL(req->vwv+0, 0)));
3089                 reply_readbraw_error(sconn);
3090                 END_PROFILE(SMBreadbraw);
3091                 return;
3092         }
3093
3094         flush_write_cache(fsp, READRAW_FLUSH);
3095
3096         startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3097         if(req->wct == 10) {
3098                 /*
3099                  * This is a large offset (64 bit) read.
3100                  */
3101 #ifdef LARGE_SMB_OFF_T
3102
3103                 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3104
3105 #else /* !LARGE_SMB_OFF_T */
3106
3107                 /*
3108                  * Ensure we haven't been sent a >32 bit offset.
3109                  */
3110
3111                 if(IVAL(req->vwv+8, 0) != 0) {
3112                         DEBUG(0,("reply_readbraw: large offset "
3113                                 "(%x << 32) used and we don't support "
3114                                 "64 bit offsets.\n",
3115                         (unsigned int)IVAL(req->vwv+8, 0) ));
3116                         reply_readbraw_error();
3117                         END_PROFILE(SMBreadbraw);
3118                         return;
3119                 }
3120
3121 #endif /* LARGE_SMB_OFF_T */
3122
3123                 if(startpos < 0) {
3124                         DEBUG(0,("reply_readbraw: negative 64 bit "
3125                                 "readraw offset (%.0f) !\n",
3126                                 (double)startpos ));
3127                         reply_readbraw_error(sconn);
3128                         END_PROFILE(SMBreadbraw);
3129                         return;
3130                 }
3131         }
3132
3133         maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3134         mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3135
3136         /* ensure we don't overrun the packet size */
3137         maxcount = MIN(65535,maxcount);
3138
3139         init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3140             (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3141             &lock);
3142
3143         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3144                 reply_readbraw_error(sconn);
3145                 END_PROFILE(SMBreadbraw);
3146                 return;
3147         }
3148
3149         if (fsp_stat(fsp) == 0) {
3150                 size = fsp->fsp_name->st.st_ex_size;
3151         }
3152
3153         if (startpos >= size) {
3154                 nread = 0;
3155         } else {
3156                 nread = MIN(maxcount,(size - startpos));
3157         }
3158
3159 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3160         if (nread < mincount)
3161                 nread = 0;
3162 #endif
3163
3164         DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3165                 "min=%lu nread=%lu\n",
3166                 fsp->fnum, (double)startpos,
3167                 (unsigned long)maxcount,
3168                 (unsigned long)mincount,
3169                 (unsigned long)nread ) );
3170
3171         send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3172
3173         DEBUG(5,("reply_readbraw finished\n"));
3174
3175         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3176
3177         END_PROFILE(SMBreadbraw);
3178         return;
3179 }
3180
3181 #undef DBGC_CLASS
3182 #define DBGC_CLASS DBGC_LOCKING
3183
3184 /****************************************************************************
3185  Reply to a lockread (core+ protocol).
3186 ****************************************************************************/
3187
3188 void reply_lockread(struct smb_request *req)
3189 {
3190         connection_struct *conn = req->conn;
3191         ssize_t nread = -1;
3192         char *data;
3193         SMB_OFF_T startpos;
3194         size_t numtoread;
3195         NTSTATUS status;
3196         files_struct *fsp;
3197         struct byte_range_lock *br_lck = NULL;
3198         char *p = NULL;
3199         struct smbd_server_connection *sconn = req->sconn;
3200
3201         START_PROFILE(SMBlockread);
3202
3203         if (req->wct < 5) {
3204                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3205                 END_PROFILE(SMBlockread);
3206                 return;
3207         }
3208
3209         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3210
3211         if (!check_fsp(conn, req, fsp)) {
3212                 END_PROFILE(SMBlockread);
3213                 return;
3214         }
3215
3216         if (!CHECK_READ(fsp,req)) {
3217                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3218                 END_PROFILE(SMBlockread);
3219                 return;
3220         }
3221
3222         numtoread = SVAL(req->vwv+1, 0);
3223         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3224
3225         numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3226
3227         reply_outbuf(req, 5, numtoread + 3);
3228
3229         data = smb_buf(req->outbuf) + 3;
3230
3231         /*
3232          * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3233          * protocol request that predates the read/write lock concept. 
3234          * Thus instead of asking for a read lock here we need to ask
3235          * for a write lock. JRA.
3236          * Note that the requested lock size is unaffected by max_recv.
3237          */
3238
3239         br_lck = do_lock(req->sconn->msg_ctx,
3240                         fsp,
3241                         (uint64_t)req->smbpid,
3242                         (uint64_t)numtoread,
3243                         (uint64_t)startpos,
3244                         WRITE_LOCK,
3245                         WINDOWS_LOCK,
3246                         False, /* Non-blocking lock. */
3247                         &status,
3248                         NULL,
3249                         NULL);
3250         TALLOC_FREE(br_lck);
3251
3252         if (NT_STATUS_V(status)) {
3253                 reply_nterror(req, status);
3254                 END_PROFILE(SMBlockread);
3255                 return;
3256         }
3257
3258         /*
3259          * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3260          */
3261
3262         if (numtoread > sconn->smb1.negprot.max_recv) {
3263                 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3264 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3265                         (unsigned int)numtoread,
3266                         (unsigned int)sconn->smb1.negprot.max_recv));
3267                 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3268         }
3269         nread = read_file(fsp,data,startpos,numtoread);
3270
3271         if (nread < 0) {
3272                 reply_nterror(req, map_nt_error_from_unix(errno));
3273                 END_PROFILE(SMBlockread);
3274                 return;
3275         }
3276
3277         srv_set_message((char *)req->outbuf, 5, nread+3, False);
3278
3279         SSVAL(req->outbuf,smb_vwv0,nread);
3280         SSVAL(req->outbuf,smb_vwv5,nread+3);
3281         p = smb_buf(req->outbuf);
3282         SCVAL(p,0,0); /* pad byte. */
3283         SSVAL(p,1,nread);
3284
3285         DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3286                  fsp->fnum, (int)numtoread, (int)nread));
3287
3288         END_PROFILE(SMBlockread);
3289         return;
3290 }
3291
3292 #undef DBGC_CLASS
3293 #define DBGC_CLASS DBGC_ALL
3294
3295 /****************************************************************************
3296  Reply to a read.
3297 ****************************************************************************/
3298
3299 void reply_read(struct smb_request *req)
3300 {
3301         connection_struct *conn = req->conn;
3302         size_t numtoread;
3303         ssize_t nread = 0;
3304         char *data;
3305         SMB_OFF_T startpos;
3306         int outsize = 0;
3307         files_struct *fsp;
3308         struct lock_struct lock;
3309         struct smbd_server_connection *sconn = req->sconn;
3310
3311         START_PROFILE(SMBread);
3312
3313         if (req->wct < 3) {
3314                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3315                 END_PROFILE(SMBread);
3316                 return;
3317         }
3318
3319         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3320
3321         if (!check_fsp(conn, req, fsp)) {
3322                 END_PROFILE(SMBread);
3323                 return;
3324         }
3325
3326         if (!CHECK_READ(fsp,req)) {
3327                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3328                 END_PROFILE(SMBread);
3329                 return;
3330         }
3331
3332         numtoread = SVAL(req->vwv+1, 0);
3333         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3334
3335         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3336
3337         /*
3338          * The requested read size cannot be greater than max_recv. JRA.
3339          */
3340         if (numtoread > sconn->smb1.negprot.max_recv) {
3341                 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3342 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3343                         (unsigned int)numtoread,
3344                         (unsigned int)sconn->smb1.negprot.max_recv));
3345                 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3346         }
3347
3348         reply_outbuf(req, 5, numtoread+3);
3349
3350         data = smb_buf(req->outbuf) + 3;
3351
3352         init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3353             (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3354             &lock);
3355
3356         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3357                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3358                 END_PROFILE(SMBread);
3359                 return;
3360         }
3361
3362         if (numtoread > 0)
3363                 nread = read_file(fsp,data,startpos,numtoread);
3364
3365         if (nread < 0) {
3366                 reply_nterror(req, map_nt_error_from_unix(errno));
3367                 goto strict_unlock;
3368         }
3369
3370         srv_set_message((char *)req->outbuf, 5, nread+3, False);
3371
3372         SSVAL(req->outbuf,smb_vwv0,nread);
3373         SSVAL(req->outbuf,smb_vwv5,nread+3);
3374         SCVAL(smb_buf(req->outbuf),0,1);
3375         SSVAL(smb_buf(req->outbuf),1,nread);
3376
3377         DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3378                 fsp->fnum, (int)numtoread, (int)nread ) );
3379
3380 strict_unlock:
3381         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3382
3383         END_PROFILE(SMBread);
3384         return;
3385 }
3386
3387 /****************************************************************************
3388  Setup readX header.
3389 ****************************************************************************/
3390
3391 static int setup_readX_header(struct smb_request *req, char *outbuf,
3392                               size_t smb_maxcnt)
3393 {
3394         int outsize;
3395         char *data;
3396
3397         outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3398         data = smb_buf(outbuf);
3399
3400         memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3401
3402         SCVAL(outbuf,smb_vwv0,0xFF);
3403         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3404         SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3405         SSVAL(outbuf,smb_vwv6,
3406               req_wct_ofs(req)
3407               + 1               /* the wct field */
3408               + 12 * sizeof(uint16_t) /* vwv */
3409               + 2);             /* the buflen field */
3410         SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3411         SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3412         /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3413         _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3414         return outsize;
3415 }
3416
3417 /****************************************************************************
3418  Reply to a read and X - possibly using sendfile.
3419 ****************************************************************************/
3420
3421 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3422                             files_struct *fsp, SMB_OFF_T startpos,
3423                             size_t smb_maxcnt)
3424 {
3425         ssize_t nread = -1;
3426         struct lock_struct lock;
3427         int saved_errno = 0;
3428
3429         if(fsp_stat(fsp) == -1) {
3430                 reply_nterror(req, map_nt_error_from_unix(errno));
3431                 return;
3432         }
3433
3434         init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3435             (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3436             &lock);
3437
3438         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3439                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3440                 return;
3441         }
3442
3443         if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3444                         (startpos > fsp->fsp_name->st.st_ex_size)
3445                         || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3446                 /*
3447                  * We already know that we would do a short read, so don't
3448                  * try the sendfile() path.
3449                  */
3450                 goto nosendfile_read;
3451         }
3452
3453 #if defined(WITH_SENDFILE)
3454         /*
3455          * We can only use sendfile on a non-chained packet
3456          * but we can use on a non-oplocked file. tridge proved this
3457          * on a train in Germany :-). JRA.
3458          */
3459
3460         if (!req_is_in_chain(req) &&
3461             !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3462             (fsp->wcp == NULL) &&
3463             lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3464                 uint8 headerbuf[smb_size + 12 * 2];
3465                 DATA_BLOB header;
3466
3467                 /*
3468                  * Set up the packet header before send. We
3469                  * assume here the sendfile will work (get the
3470                  * correct amount of data).
3471                  */
3472
3473                 header = data_blob_const(headerbuf, sizeof(headerbuf));
3474
3475                 construct_reply_common_req(req, (char *)headerbuf);
3476                 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3477
3478                 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3479                         /* Returning ENOSYS means no data at all was sent.
3480                            Do this as a normal read. */
3481                         if (errno == ENOSYS) {
3482                                 goto normal_read;
3483                         }
3484
3485                         /*
3486                          * Special hack for broken Linux with no working sendfile. If we
3487                          * return EINTR we sent the header but not the rest of the data.
3488                          * Fake this up by doing read/write calls.
3489                          */
3490
3491                         if (errno == EINTR) {
3492                                 /* Ensure we don't do this again. */
3493                                 set_use_sendfile(SNUM(conn), False);
3494                                 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3495                                 nread = fake_sendfile(fsp, startpos,
3496                                                       smb_maxcnt);
3497                                 if (nread == -1) {
3498                                         DEBUG(0,("send_file_readX: "
3499                                                  "fake_sendfile failed for "
3500                                                  "file %s (%s).\n",
3501                                                  fsp_str_dbg(fsp),
3502                                                  strerror(errno)));
3503                                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
3504                                 }
3505                                 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3506                                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3507                                 /* No outbuf here means successful sendfile. */
3508                                 goto strict_unlock;
3509                         }
3510
3511                         DEBUG(0,("send_file_readX: sendfile failed for file "
3512                                  "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3513                                  strerror(errno)));
3514                         exit_server_cleanly("send_file_readX sendfile failed");
3515                 } else if (nread == 0) {
3516                         /*
3517                          * Some sendfile implementations return 0 to indicate
3518                          * that there was a short read, but nothing was
3519                          * actually written to the socket.  In this case,
3520                          * fallback to the normal read path so the header gets
3521                          * the correct byte count.
3522                          */
3523                         DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3524                                   "falling back to the normal read: %s\n",
3525                                   fsp_str_dbg(fsp)));
3526                         goto normal_read;
3527                 }
3528
3529                 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3530                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3531
3532                 /* Deal with possible short send. */
3533                 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3534                         sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3535                 }
3536                 /* No outbuf here means successful sendfile. */
3537                 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3538                 SMB_PERFCOUNT_END(&req->pcd);
3539                 goto strict_unlock;
3540         }
3541
3542 normal_read:
3543
3544 #endif
3545
3546         if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3547                 uint8 headerbuf[smb_size + 2*12];
3548
3549                 construct_reply_common_req(req, (char *)headerbuf);
3550                 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3551
3552                 /* Send out the header. */
3553                 if (write_data(smbd_server_fd(), (char *)headerbuf,
3554                                sizeof(headerbuf)) != sizeof(headerbuf)) {
3555                         DEBUG(0,("send_file_readX: write_data failed for file "
3556                                  "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3557                                  strerror(errno)));
3558                         exit_server_cleanly("send_file_readX sendfile failed");
3559                 }
3560                 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3561                 if (nread == -1) {
3562                         DEBUG(0,("send_file_readX: fake_sendfile failed for "
3563                                  "file %s (%s).\n", fsp_str_dbg(fsp),
3564                                  strerror(errno)));
3565                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
3566                 }
3567                 goto strict_unlock;
3568         }
3569
3570 nosendfile_read:
3571
3572         reply_outbuf(req, 12, smb_maxcnt);
3573
3574         nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3575         saved_errno = errno;
3576
3577         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3578
3579         if (nread < 0) {
3580                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3581                 return;
3582         }
3583
3584         setup_readX_header(req, (char *)req->outbuf, nread);
3585
3586         DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3587                     fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3588
3589         chain_reply(req);
3590         return;
3591
3592  strict_unlock:
3593         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3594         TALLOC_FREE(req->outbuf);
3595         return;
3596 }
3597
3598 /****************************************************************************
3599  Reply to a read and X.
3600 ****************************************************************************/
3601
3602 void reply_read_and_X(struct smb_request *req)
3603 {
3604         connection_struct *conn = req->conn;
3605         files_struct *fsp;
3606         SMB_OFF_T startpos;
3607         size_t smb_maxcnt;
3608         bool big_readX = False;
3609 #if 0
3610         size_t smb_mincnt = SVAL(req->vwv+6, 0);
3611 #endif
3612
3613         START_PROFILE(SMBreadX);
3614
3615         if ((req->wct != 10) && (req->wct != 12)) {
3616                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3617                 return;
3618         }
3619
3620         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3621         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3622         smb_maxcnt = SVAL(req->vwv+5, 0);
3623
3624         /* If it's an IPC, pass off the pipe handler. */
3625         if (IS_IPC(conn)) {
3626                 reply_pipe_read_and_X(req);
3627                 END_PROFILE(SMBreadX);
3628                 return;
3629         }
3630
3631         if (!check_fsp(conn, req, fsp)) {
3632                 END_PROFILE(SMBreadX);
3633                 return;
3634         }
3635
3636         if (!CHECK_READ(fsp,req)) {
3637                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3638                 END_PROFILE(SMBreadX);
3639                 return;
3640         }
3641
3642         if (global_client_caps & CAP_LARGE_READX) {
3643                 size_t upper_size = SVAL(req->vwv+7, 0);
3644                 smb_maxcnt |= (upper_size<<16);
3645                 if (upper_size > 1) {
3646                         /* Can't do this on a chained packet. */
3647                         if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3648                                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3649                                 END_PROFILE(SMBreadX);
3650                                 return;
3651                         }
3652                         /* We currently don't do this on signed or sealed data. */
3653                         if (srv_is_signing_active(req->sconn) ||
3654                             is_encrypted_packet(req->inbuf)) {
3655                                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3656                                 END_PROFILE(SMBreadX);
3657                                 return;
3658                         }
3659                         /* Is there room in the reply for this data ? */
3660                         if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2)))  {
3661                                 reply_nterror(req,
3662                                               NT_STATUS_INVALID_PARAMETER);
3663                                 END_PROFILE(SMBreadX);
3664                                 return;
3665                         }
3666                         big_readX = True;
3667                 }
3668         }
3669
3670         if (req->wct == 12) {
3671 #ifdef LARGE_SMB_OFF_T
3672                 /*
3673                  * This is a large offset (64 bit) read.
3674                  */
3675                 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3676
3677 #else /* !LARGE_SMB_OFF_T */
3678
3679                 /*
3680                  * Ensure we haven't been sent a >32 bit offset.
3681                  */
3682
3683                 if(IVAL(req->vwv+10, 0) != 0) {
3684                         DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3685                                  "used and we don't support 64 bit offsets.\n",
3686                                  (unsigned int)IVAL(req->vwv+10, 0) ));
3687                         END_PROFILE(SMBreadX);
3688                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3689                         return;
3690                 }
3691
3692 #endif /* LARGE_SMB_OFF_T */
3693
3694         }
3695
3696         if (!big_readX) {
3697                 NTSTATUS status = schedule_aio_read_and_X(conn,
3698                                         req,
3699                                         fsp,
3700                                         startpos,
3701                                         smb_maxcnt);
3702                 if (NT_STATUS_IS_OK(status)) {
3703                         /* Read scheduled - we're done. */
3704                         goto out;
3705                 }
3706                 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3707                         /* Real error - report to client. */
3708                         END_PROFILE(SMBreadX);
3709                         reply_nterror(req, status);
3710                         return;
3711                 }
3712                 /* NT_STATUS_RETRY - fall back to sync read. */
3713         }
3714
3715         smbd_lock_socket(req->sconn);
3716         send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3717         smbd_unlock_socket(req->sconn);
3718
3719  out:
3720         END_PROFILE(SMBreadX);
3721         return;
3722 }
3723
3724 /****************************************************************************
3725  Error replies to writebraw must have smb_wct == 1. Fix this up.
3726 ****************************************************************************/
3727
3728 void error_to_writebrawerr(struct smb_request *req)
3729 {
3730         uint8 *old_outbuf = req->outbuf;
3731
3732         reply_outbuf(req, 1, 0);
3733
3734         memcpy(req->outbuf, old_outbuf, smb_size);
3735         TALLOC_FREE(old_outbuf);
3736 }
3737
3738 /****************************************************************************
3739  Reply to a writebraw (core+ or LANMAN1.0 protocol).
3740 ****************************************************************************/
3741
3742 void reply_writebraw(struct smb_request *req)
3743 {
3744         connection_struct *conn = req->conn;
3745         char *buf = NULL;
3746         ssize_t nwritten=0;
3747         ssize_t total_written=0;
3748         size_t numtowrite=0;
3749         size_t tcount;
3750         SMB_OFF_T startpos;
3751         char *data=NULL;
3752         bool write_through;
3753         files_struct *fsp;
3754         struct lock_struct lock;
3755         NTSTATUS status;
3756
3757         START_PROFILE(SMBwritebraw);
3758
3759         /*
3760          * If we ever reply with an error, it must have the SMB command
3761          * type of SMBwritec, not SMBwriteBraw, as this tells the client
3762          * we're finished.
3763          */
3764         SCVAL(req->inbuf,smb_com,SMBwritec);
3765
3766         if (srv_is_signing_active(req->sconn)) {
3767                 END_PROFILE(SMBwritebraw);
3768                 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3769                                 "raw reads/writes are disallowed.");
3770         }
3771
3772         if (req->wct < 12) {
3773                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3774                 error_to_writebrawerr(req);
3775                 END_PROFILE(SMBwritebraw);
3776                 return;
3777         }
3778
3779         if (req->sconn->smb1.echo_handler.trusted_fde) {
3780                 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3781                          "'async smb echo handler = yes'\n"));
3782                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3783                 error_to_writebrawerr(req);
3784                 END_PROFILE(SMBwritebraw);
3785                 return;
3786         }
3787
3788         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3789         if (!check_fsp(conn, req, fsp)) {
3790                 error_to_writebrawerr(req);
3791                 END_PROFILE(SMBwritebraw);
3792                 return;
3793         }
3794
3795         if (!CHECK_WRITE(fsp)) {
3796                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3797                 error_to_writebrawerr(req);
3798                 END_PROFILE(SMBwritebraw);
3799                 return;
3800         }
3801
3802         tcount = IVAL(req->vwv+1, 0);
3803         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3804         write_through = BITSETW(req->vwv+7,0);
3805
3806         /* We have to deal with slightly different formats depending
3807                 on whether we are using the core+ or lanman1.0 protocol */
3808
3809         if(get_Protocol() <= PROTOCOL_COREPLUS) {
3810                 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3811                 data = smb_buf(req->inbuf);
3812         } else {
3813                 numtowrite = SVAL(req->vwv+10, 0);
3814                 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3815         }
3816
3817         /* Ensure we don't write bytes past the end of this packet. */
3818         if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3819                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3820                 error_to_writebrawerr(req);
3821                 END_PROFILE(SMBwritebraw);
3822                 return;
3823         }
3824
3825         if (!fsp->print_file) {
3826                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3827                     (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3828                     &lock);
3829
3830                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3831                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3832                         error_to_writebrawerr(req);
3833                         END_PROFILE(SMBwritebraw);
3834                         return;
3835                 }
3836         }
3837
3838         if (numtowrite>0) {
3839                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3840         }
3841
3842         DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3843                         "wrote=%d sync=%d\n",
3844                 fsp->fnum, (double)startpos, (int)numtowrite,
3845                 (int)nwritten, (int)write_through));
3846
3847         if (nwritten < (ssize_t)numtowrite)  {
3848                 reply_nterror(req, NT_STATUS_DISK_FULL);
3849                 error_to_writebrawerr(req);
3850                 goto strict_unlock;
3851         }
3852
3853         total_written = nwritten;
3854
3855         /* Allocate a buffer of 64k + length. */
3856         buf = TALLOC_ARRAY(NULL, char, 65540);
3857         if (!buf) {
3858                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3859                 error_to_writebrawerr(req);
3860                 goto strict_unlock;
3861         }
3862
3863         /* Return a SMBwritebraw message to the redirector to tell
3864          * it to send more bytes */
3865
3866         memcpy(buf, req->inbuf, smb_size);
3867         srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
3868         SCVAL(buf,smb_com,SMBwritebraw);
3869         SSVALS(buf,smb_vwv0,0xFFFF);
3870         show_msg(buf);
3871         if (!srv_send_smb(smbd_server_fd(),
3872                           buf,
3873                           false, 0, /* no signing */
3874                           IS_CONN_ENCRYPTED(conn),
3875                           &req->pcd)) {
3876                 exit_server_cleanly("reply_writebraw: srv_send_smb "
3877                         "failed.");
3878         }
3879
3880         /* Now read the raw data into the buffer and write it */
3881         status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3882                                  &numtowrite);
3883         if (!NT_STATUS_IS_OK(status)) {
3884                 exit_server_cleanly("secondary writebraw failed");
3885         }
3886
3887         /* Set up outbuf to return the correct size */
3888         reply_outbuf(req, 1, 0);
3889
3890         if (numtowrite != 0) {
3891
3892                 if (numtowrite > 0xFFFF) {
3893                         DEBUG(0,("reply_writebraw: Oversize secondary write "
3894                                 "raw requested (%u). Terminating\n",
3895                                 (unsigned int)numtowrite ));
3896                         exit_server_cleanly("secondary writebraw failed");
3897                 }
3898
3899                 if (tcount > nwritten+numtowrite) {
3900                         DEBUG(3,("reply_writebraw: Client overestimated the "
3901                                 "write %d %d %d\n",
3902                                 (int)tcount,(int)nwritten,(int)numtowrite));
3903                 }
3904
3905                 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3906
3907                 if (!NT_STATUS_IS_OK(status)) {
3908                         DEBUG(0,("reply_writebraw: Oversize secondary write "
3909                                  "raw read failed (%s). Terminating\n",
3910                                  nt_errstr(status)));
3911                         exit_server_cleanly("secondary writebraw failed");
3912                 }
3913
3914                 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3915                 if (nwritten == -1) {
3916                         TALLOC_FREE(buf);
3917                         reply_nterror(req, map_nt_error_from_unix(errno));
3918                         error_to_writebrawerr(req);
3919                         goto strict_unlock;
3920                 }
3921
3922                 if (nwritten < (ssize_t)numtowrite) {
3923                         SCVAL(req->outbuf,smb_rcls,ERRHRD);
3924                         SSVAL(req->outbuf,smb_err,ERRdiskfull);
3925                 }
3926
3927                 if (nwritten > 0) {
3928                         total_written += nwritten;
3929                 }
3930         }
3931
3932         TALLOC_FREE(buf);
3933         SSVAL(req->outbuf,smb_vwv0,total_written);
3934
3935         status = sync_file(conn, fsp, write_through);
3936         if (!NT_STATUS_IS_OK(status)) {
3937                 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3938                          fsp_str_dbg(fsp), nt_errstr(status)));
3939                 reply_nterror(req, status);
3940                 error_to_writebrawerr(req);
3941                 goto strict_unlock;
3942         }
3943
3944         DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3945                 "wrote=%d\n",
3946                 fsp->fnum, (double)startpos, (int)numtowrite,
3947                 (int)total_written));
3948
3949         if (!fsp->print_file) {
3950                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3951         }
3952
3953         /* We won't return a status if write through is not selected - this
3954          * follows what WfWg does */
3955         END_PROFILE(SMBwritebraw);
3956
3957         if (!write_through && total_written==tcount) {
3958
3959 #if RABBIT_PELLET_FIX
3960                 /*
3961                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3962                  * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3963                  * JRA.
3964                  */
3965                 if (!send_keepalive(smbd_server_fd())) {
3966                         exit_server_cleanly("reply_writebraw: send of "
3967                                 "keepalive failed");
3968                 }
3969 #endif
3970                 TALLOC_FREE(req->outbuf);
3971         }
3972         return;
3973
3974 strict_unlock:
3975         if (!fsp->print_file) {
3976                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3977         }
3978
3979         END_PROFILE(SMBwritebraw);
3980         return;
3981 }
3982
3983 #undef DBGC_CLASS
3984 #define DBGC_CLASS DBGC_LOCKING
3985
3986 /****************************************************************************
3987  Reply to a writeunlock (core+).
3988 ****************************************************************************/
3989
3990 void reply_writeunlock(struct smb_request *req)
3991 {
3992         connection_struct *conn = req->conn;
3993         ssize_t nwritten = -1;
3994         size_t numtowrite;
3995         SMB_OFF_T startpos;
3996         const char *data;
3997         NTSTATUS status = NT_STATUS_OK;
3998         files_struct *fsp;
3999         struct lock_struct lock;
4000         int saved_errno = 0;
4001
4002         START_PROFILE(SMBwriteunlock);
4003
4004         if (req->wct < 5) {
4005                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4006                 END_PROFILE(SMBwriteunlock);
4007                 return;
4008         }
4009
4010         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4011
4012         if (!check_fsp(conn, req, fsp)) {
4013                 END_PROFILE(SMBwriteunlock);
4014                 return;
4015         }
4016
4017         if (!CHECK_WRITE(fsp)) {
4018                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4019                 END_PROFILE(SMBwriteunlock);
4020                 return;
4021         }
4022
4023         numtowrite = SVAL(req->vwv+1, 0);
4024         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4025         data = (const char *)req->buf + 3;
4026
4027         if (!fsp->print_file && numtowrite > 0) {
4028                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4029                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4030                     &lock);
4031
4032                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4033                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4034                         END_PROFILE(SMBwriteunlock);
4035                         return;
4036                 }
4037         }
4038
4039         /* The special X/Open SMB protocol handling of
4040            zero length writes is *NOT* done for
4041            this call */
4042         if(numtowrite == 0) {
4043                 nwritten = 0;
4044         } else {
4045                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4046                 saved_errno = errno;
4047         }
4048
4049         status = sync_file(conn, fsp, False /* write through */);
4050         if (!NT_STATUS_IS_OK(status)) {
4051                 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4052                          fsp_str_dbg(fsp), nt_errstr(status)));
4053                 reply_nterror(req, status);
4054                 goto strict_unlock;
4055         }
4056
4057         if(nwritten < 0) {
4058                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4059                 goto strict_unlock;
4060         }
4061
4062         if((nwritten < numtowrite) && (numtowrite != 0)) {
4063                 reply_nterror(req, NT_STATUS_DISK_FULL);
4064                 goto strict_unlock;
4065         }
4066
4067         if (numtowrite && !fsp->print_file) {
4068                 status = do_unlock(req->sconn->msg_ctx,
4069                                 fsp,
4070                                 (uint64_t)req->smbpid,
4071                                 (uint64_t)numtowrite, 
4072                                 (uint64_t)startpos,
4073                                 WINDOWS_LOCK);
4074
4075                 if (NT_STATUS_V(status)) {
4076                         reply_nterror(req, status);
4077                         goto strict_unlock;
4078                 }
4079         }
4080
4081         reply_outbuf(req, 1, 0);
4082
4083         SSVAL(req->outbuf,smb_vwv0,nwritten);
4084
4085         DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4086                  fsp->fnum, (int)numtowrite, (int)nwritten));
4087
4088 strict_unlock:
4089         if (numtowrite && !fsp->print_file) {
4090                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4091         }
4092
4093         END_PROFILE(SMBwriteunlock);
4094         return;
4095 }
4096
4097 #undef DBGC_CLASS
4098 #define DBGC_CLASS DBGC_ALL
4099
4100 /****************************************************************************
4101  Reply to a write.
4102 ****************************************************************************/
4103
4104 void reply_write(struct smb_request *req)
4105 {
4106         connection_struct *conn = req->conn;
4107         size_t numtowrite;
4108         ssize_t nwritten = -1;
4109         SMB_OFF_T startpos;
4110         const char *data;
4111         files_struct *fsp;
4112         struct lock_struct lock;
4113         NTSTATUS status;
4114         int saved_errno = 0;
4115
4116         START_PROFILE(SMBwrite);
4117
4118         if (req->wct < 5) {
4119                 END_PROFILE(SMBwrite);
4120                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4121                 return;
4122         }
4123
4124         /* If it's an IPC, pass off the pipe handler. */
4125         if (IS_IPC(conn)) {
4126                 reply_pipe_write(req);
4127                 END_PROFILE(SMBwrite);
4128                 return;
4129         }
4130
4131         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4132
4133         if (!check_fsp(conn, req, fsp)) {
4134                 END_PROFILE(SMBwrite);
4135                 return;
4136         }
4137
4138         if (!CHECK_WRITE(fsp)) {
4139                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4140                 END_PROFILE(SMBwrite);
4141                 return;
4142         }
4143
4144         numtowrite = SVAL(req->vwv+1, 0);
4145         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4146         data = (const char *)req->buf + 3;
4147
4148         if (!fsp->print_file) {
4149                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4150                         (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4151                         &lock);
4152
4153                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4154                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4155                         END_PROFILE(SMBwrite);
4156                         return;
4157                 }
4158         }
4159
4160         /*
4161          * X/Open SMB protocol says that if smb_vwv1 is
4162          * zero then the file size should be extended or
4163          * truncated to the size given in smb_vwv[2-3].
4164          */
4165
4166         if(numtowrite == 0) {
4167                 /*
4168                  * This is actually an allocate call, and set EOF. JRA.
4169                  */
4170                 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4171                 if (nwritten < 0) {
4172                         reply_nterror(req, NT_STATUS_DISK_FULL);
4173                         goto strict_unlock;
4174                 }
4175                 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4176                 if (nwritten < 0) {
4177                         reply_nterror(req, NT_STATUS_DISK_FULL);
4178                         goto strict_unlock;
4179                 }
4180                 trigger_write_time_update_immediate(fsp);
4181         } else {
4182                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4183         }
4184
4185         status = sync_file(conn, fsp, False);
4186         if (!NT_STATUS_IS_OK(status)) {
4187                 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4188                          fsp_str_dbg(fsp), nt_errstr(status)));
4189                 reply_nterror(req, status);
4190                 goto strict_unlock;
4191         }
4192
4193         if(nwritten < 0) {
4194                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4195                 goto strict_unlock;
4196         }
4197
4198         if((nwritten == 0) && (numtowrite != 0)) {
4199                 reply_nterror(req, NT_STATUS_DISK_FULL);
4200                 goto strict_unlock;
4201         }
4202
4203         reply_outbuf(req, 1, 0);
4204
4205         SSVAL(req->outbuf,smb_vwv0,nwritten);
4206
4207         if (nwritten < (ssize_t)numtowrite) {
4208                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4209                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4210         }
4211
4212         DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4213
4214 strict_unlock:
4215         if (!fsp->print_file) {
4216                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4217         }
4218
4219         END_PROFILE(SMBwrite);
4220         return;
4221 }
4222
4223 /****************************************************************************
4224  Ensure a buffer is a valid writeX for recvfile purposes.
4225 ****************************************************************************/
4226
4227 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4228                                                 (2*14) + /* word count (including bcc) */ \
4229                                                 1 /* pad byte */)
4230
4231 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4232                             const uint8_t *inbuf)
4233 {
4234         size_t numtowrite;
4235         connection_struct *conn = NULL;
4236         unsigned int doff = 0;
4237         size_t len = smb_len_large(inbuf);
4238
4239         if (is_encrypted_packet(inbuf)) {
4240                 /* Can't do this on encrypted
4241                  * connections. */
4242                 return false;
4243         }
4244
4245         if (CVAL(inbuf,smb_com) != SMBwriteX) {
4246                 return false;
4247         }
4248
4249         if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4250                         CVAL(inbuf,smb_wct) != 14) {
4251                 DEBUG(10,("is_valid_writeX_buffer: chained or "
4252                         "invalid word length.\n"));
4253                 return false;
4254         }
4255
4256         conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4257         if (conn == NULL) {
4258                 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4259                 return false;
4260         }
4261         if (IS_IPC(conn)) {
4262                 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4263                 return false;
4264         }
4265         if (IS_PRINT(conn)) {
4266                 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4267                 return false;
4268         }
4269         doff = SVAL(inbuf,smb_vwv11);
4270
4271         numtowrite = SVAL(inbuf,smb_vwv10);
4272
4273         if (len > doff && len - doff > 0xFFFF) {
4274                 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4275         }
4276
4277         if (numtowrite == 0) {
4278                 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4279                 return false;
4280         }
4281
4282         /* Ensure the sizes match up. */
4283         if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4284                 /* no pad byte...old smbclient :-( */
4285                 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4286                         (unsigned int)doff,
4287                         (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4288                 return false;
4289         }
4290
4291         if (len - doff != numtowrite) {
4292                 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4293                         "len = %u, doff = %u, numtowrite = %u\n",
4294                         (unsigned int)len,
4295                         (unsigned int)doff,
4296                         (unsigned int)numtowrite ));
4297                 return false;
4298         }
4299
4300         DEBUG(10,("is_valid_writeX_buffer: true "
4301                 "len = %u, doff = %u, numtowrite = %u\n",
4302                 (unsigned int)len,
4303                 (unsigned int)doff,
4304                 (unsigned int)numtowrite ));
4305
4306         return true;
4307 }
4308
4309 /****************************************************************************
4310  Reply to a write and X.
4311 ****************************************************************************/
4312
4313 void reply_write_and_X(struct smb_request *req)
4314 {
4315         connection_struct *conn = req->conn;
4316         files_struct *fsp;
4317         struct lock_struct lock;
4318         SMB_OFF_T startpos;
4319         size_t numtowrite;
4320         bool write_through;
4321         ssize_t nwritten;
4322         unsigned int smb_doff;
4323         unsigned int smblen;
4324         char *data;
4325         NTSTATUS status;
4326         int saved_errno = 0;
4327
4328         START_PROFILE(SMBwriteX);
4329
4330         if ((req->wct != 12) && (req->wct != 14)) {
4331                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4332                 END_PROFILE(SMBwriteX);
4333                 return;
4334         }
4335
4336         numtowrite = SVAL(req->vwv+10, 0);
4337         smb_doff = SVAL(req->vwv+11, 0);
4338         smblen = smb_len(req->inbuf);
4339
4340         if (req->unread_bytes > 0xFFFF ||
4341                         (smblen > smb_doff &&
4342                                 smblen - smb_doff > 0xFFFF)) {
4343                 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4344         }
4345
4346         if (req->unread_bytes) {
4347                 /* Can't do a recvfile write on IPC$ */
4348                 if (IS_IPC(conn)) {
4349                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4350                         END_PROFILE(SMBwriteX);
4351                         return;
4352                 }
4353                 if (numtowrite != req->unread_bytes) {
4354                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4355                         END_PROFILE(SMBwriteX);
4356                         return;
4357                 }
4358         } else {
4359                 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4360                                 smb_doff + numtowrite > smblen) {
4361                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4362                         END_PROFILE(SMBwriteX);
4363                         return;
4364                 }
4365         }
4366
4367         /* If it's an IPC, pass off the pipe handler. */
4368         if (IS_IPC(conn)) {
4369                 if (req->unread_bytes) {
4370                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4371                         END_PROFILE(SMBwriteX);
4372                         return;
4373                 }
4374                 reply_pipe_write_and_X(req);
4375                 END_PROFILE(SMBwriteX);
4376                 return;
4377         }
4378
4379         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4380         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4381         write_through = BITSETW(req->vwv+7,0);
4382
4383         if (!check_fsp(conn, req, fsp)) {
4384                 END_PROFILE(SMBwriteX);
4385                 return;
4386         }
4387
4388         if (!CHECK_WRITE(fsp)) {
4389                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4390                 END_PROFILE(SMBwriteX);
4391                 return;
4392         }
4393
4394         data = smb_base(req->inbuf) + smb_doff;
4395
4396         if(req->wct == 14) {
4397 #ifdef LARGE_SMB_OFF_T
4398                 /*
4399                  * This is a large offset (64 bit) write.
4400                  */
4401                 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4402
4403 #else /* !LARGE_SMB_OFF_T */
4404
4405                 /*
4406                  * Ensure we haven't been sent a >32 bit offset.
4407                  */
4408
4409                 if(IVAL(req->vwv+12, 0) != 0) {
4410                         DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4411                                  "used and we don't support 64 bit offsets.\n",
4412                                  (unsigned int)IVAL(req->vwv+12, 0) ));
4413                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4414                         END_PROFILE(SMBwriteX);
4415                         return;
4416                 }
4417
4418 #endif /* LARGE_SMB_OFF_T */
4419         }
4420
4421         /* X/Open SMB protocol says that, unlike SMBwrite
4422         if the length is zero then NO truncation is
4423         done, just a write of zero. To truncate a file,
4424         use SMBwrite. */
4425
4426         if(numtowrite == 0) {
4427                 nwritten = 0;
4428         } else {
4429                 if (req->unread_bytes == 0) {
4430                         status = schedule_aio_write_and_X(conn,
4431                                                 req,
4432                                                 fsp,
4433                                                 data,
4434                                                 startpos,
4435                                                 numtowrite);
4436
4437                         if (NT_STATUS_IS_OK(status)) {
4438                                 /* write scheduled - we're done. */
4439                                 goto out;
4440                         }
4441                         if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4442                                 /* Real error - report to client. */
4443                                 reply_nterror(req, status);
4444                                 goto out;
4445                         }
4446                         /* NT_STATUS_RETRY - fall through to sync write. */
4447                 }
4448
4449                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4450                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4451                     &lock);
4452
4453                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4454                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4455                         goto out;
4456                 }
4457
4458                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4459                 saved_errno = errno;
4460
4461                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4462         }
4463
4464         if(nwritten < 0) {
4465                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4466                 goto out;
4467         }
4468
4469         if((nwritten == 0) && (numtowrite != 0)) {
4470                 reply_nterror(req, NT_STATUS_DISK_FULL);
4471                 goto out;
4472         }
4473
4474         reply_outbuf(req, 6, 0);
4475         SSVAL(req->outbuf,smb_vwv2,nwritten);
4476         SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4477
4478         if (nwritten < (ssize_t)numtowrite) {
4479                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4480                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4481         }
4482
4483         DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4484                 fsp->fnum, (int)numtowrite, (int)nwritten));
4485
4486         status = sync_file(conn, fsp, write_through);
4487         if (!NT_STATUS_IS_OK(status)) {
4488                 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4489                          fsp_str_dbg(fsp), nt_errstr(status)));
4490                 reply_nterror(req, status);
4491                 goto out;
4492         }
4493
4494         END_PROFILE(SMBwriteX);
4495         chain_reply(req);
4496         return;
4497
4498 out:
4499         END_PROFILE(SMBwriteX);
4500         return;
4501 }
4502
4503 /****************************************************************************
4504  Reply to a lseek.
4505 ****************************************************************************/
4506
4507 void reply_lseek(struct smb_request *req)
4508 {
4509         connection_struct *conn = req->conn;
4510         SMB_OFF_T startpos;
4511         SMB_OFF_T res= -1;
4512         int mode,umode;
4513         files_struct *fsp;
4514
4515         START_PROFILE(SMBlseek);
4516
4517         if (req->wct < 4) {
4518                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4519                 END_PROFILE(SMBlseek);
4520                 return;
4521         }
4522
4523         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4524
4525         if (!check_fsp(conn, req, fsp)) {
4526                 return;
4527         }
4528
4529         flush_write_cache(fsp, SEEK_FLUSH);
4530
4531         mode = SVAL(req->vwv+1, 0) & 3;
4532         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4533         startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4534
4535         switch (mode) {
4536                 case 0:
4537                         umode = SEEK_SET;
4538                         res = startpos;
4539                         break;
4540                 case 1:
4541                         umode = SEEK_CUR;
4542                         res = fsp->fh->pos + startpos;
4543                         break;
4544                 case 2:
4545                         umode = SEEK_END;
4546                         break;
4547                 default:
4548                         umode = SEEK_SET;
4549                         res = startpos;
4550                         break;
4551         }
4552
4553         if (umode == SEEK_END) {
4554                 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4555                         if(errno == EINVAL) {
4556                                 SMB_OFF_T current_pos = startpos;
4557
4558                                 if(fsp_stat(fsp) == -1) {
4559                                         reply_nterror(req,
4560                                                 map_nt_error_from_unix(errno));
4561                                         END_PROFILE(SMBlseek);
4562                                         return;
4563                                 }
4564
4565                                 current_pos += fsp->fsp_name->st.st_ex_size;
4566                                 if(current_pos < 0)
4567                                         res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4568                         }
4569                 }
4570
4571                 if(res == -1) {
4572                         reply_nterror(req, map_nt_error_from_unix(errno));
4573                         END_PROFILE(SMBlseek);
4574                         return;
4575                 }
4576         }
4577
4578         fsp->fh->pos = res;
4579
4580         reply_outbuf(req, 2, 0);
4581         SIVAL(req->outbuf,smb_vwv0,res);
4582
4583         DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4584                 fsp->fnum, (double)startpos, (double)res, mode));
4585
4586         END_PROFILE(SMBlseek);
4587         return;
4588 }
4589
4590 /****************************************************************************
4591  Reply to a flush.
4592 ****************************************************************************/
4593
4594 void reply_flush(struct smb_request *req)
4595 {
4596         connection_struct *conn = req->conn;
4597         uint16 fnum;
4598         files_struct *fsp;
4599
4600         START_PROFILE(SMBflush);
4601
4602         if (req->wct < 1) {
4603                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4604                 return;
4605         }
4606
4607         fnum = SVAL(req->vwv+0, 0);
4608         fsp = file_fsp(req, fnum);
4609
4610         if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4611                 return;
4612         }
4613
4614         if (!fsp) {
4615                 file_sync_all(conn);
4616         } else {
4617                 NTSTATUS status = sync_file(conn, fsp, True);
4618                 if (!NT_STATUS_IS_OK(status)) {
4619                         DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4620                                 fsp_str_dbg(fsp), nt_errstr(status)));
4621                         reply_nterror(req, status);
4622                         END_PROFILE(SMBflush);
4623                         return;
4624                 }
4625         }
4626
4627         reply_outbuf(req, 0, 0);
4628
4629         DEBUG(3,("flush\n"));
4630         END_PROFILE(SMBflush);
4631         return;
4632 }
4633
4634 /****************************************************************************
4635  Reply to a exit.
4636  conn POINTER CAN BE NULL HERE !
4637 ****************************************************************************/
4638
4639 void reply_exit(struct smb_request *req)
4640 {
4641         START_PROFILE(SMBexit);
4642
4643         file_close_pid(req->smbpid, req->vuid);
4644
4645         reply_outbuf(req, 0, 0);
4646
4647         DEBUG(3,("exit\n"));
4648
4649         END_PROFILE(SMBexit);
4650         return;
4651 }
4652
4653 /****************************************************************************
4654  Reply to a close - has to deal with closing a directory opened by NT SMB's.
4655 ****************************************************************************/
4656
4657 void reply_close(struct smb_request *req)
4658 {
4659         connection_struct *conn = req->conn;
4660         NTSTATUS status = NT_STATUS_OK;
4661         files_struct *fsp = NULL;
4662         START_PROFILE(SMBclose);
4663
4664         if (req->wct < 3) {
4665                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4666                 END_PROFILE(SMBclose);
4667                 return;
4668         }
4669
4670         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4671
4672         /*
4673          * We can only use check_fsp if we know it's not a directory.
4674          */
4675
4676         if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4677                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4678                 END_PROFILE(SMBclose);
4679                 return;
4680         }
4681
4682         if(fsp->is_directory) {
4683                 /*
4684                  * Special case - close NT SMB directory handle.
4685                  */
4686                 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4687                 status = close_file(req, fsp, NORMAL_CLOSE);
4688         } else {
4689                 time_t t;
4690                 /*
4691                  * Close ordinary file.
4692                  */
4693
4694                 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4695                          fsp->fh->fd, fsp->fnum,
4696                          conn->num_files_open));
4697
4698                 /*
4699                  * Take care of any time sent in the close.
4700                  */
4701
4702                 t = srv_make_unix_date3(req->vwv+1);
4703                 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4704
4705                 /*
4706                  * close_file() returns the unix errno if an error
4707                  * was detected on close - normally this is due to
4708                  * a disk full error. If not then it was probably an I/O error.
4709                  */
4710
4711                 status = close_file(req, fsp, NORMAL_CLOSE);
4712         }  
4713
4714         if (!NT_STATUS_IS_OK(status)) {
4715                 reply_nterror(req, status);
4716                 END_PROFILE(SMBclose);
4717                 return;
4718         }
4719
4720         reply_outbuf(req, 0, 0);
4721         END_PROFILE(SMBclose);
4722         return;
4723 }
4724
4725 /****************************************************************************
4726  Reply to a writeclose (Core+ protocol).
4727 ****************************************************************************/
4728
4729 void reply_writeclose(struct smb_request *req)
4730 {
4731         connection_struct *conn = req->conn;
4732         size_t numtowrite;
4733         ssize_t nwritten = -1;
4734         NTSTATUS close_status = NT_STATUS_OK;
4735         SMB_OFF_T startpos;
4736         const char *data;
4737         struct timespec mtime;
4738         files_struct *fsp;
4739         struct lock_struct lock;
4740
4741         START_PROFILE(SMBwriteclose);
4742
4743         if (req->wct < 6) {
4744                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4745                 END_PROFILE(SMBwriteclose);
4746                 return;
4747         }
4748
4749         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4750
4751         if (!check_fsp(conn, req, fsp)) {
4752                 END_PROFILE(SMBwriteclose);
4753                 return;
4754         }
4755         if (!CHECK_WRITE(fsp)) {
4756                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4757                 END_PROFILE(SMBwriteclose);
4758                 return;
4759         }
4760
4761         numtowrite = SVAL(req->vwv+1, 0);
4762         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4763         mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4764         data = (const char *)req->buf + 1;
4765
4766         if (!fsp->print_file) {
4767                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4768                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4769                     &lock);
4770
4771                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4772                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4773                         END_PROFILE(SMBwriteclose);
4774                         return;
4775                 }
4776         }
4777
4778         nwritten = write_file(req,fsp,data,startpos,numtowrite);
4779
4780         set_close_write_time(fsp, mtime);
4781
4782         /*
4783          * More insanity. W2K only closes the file if writelen > 0.
4784          * JRA.
4785          */
4786
4787         if (numtowrite) {
4788                 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4789                          "file %s\n", fsp_str_dbg(fsp)));
4790                 close_status = close_file(req, fsp, NORMAL_CLOSE);
4791         }
4792
4793         DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4794                  fsp->fnum, (int)numtowrite, (int)nwritten,
4795                  conn->num_files_open));
4796
4797         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4798                 reply_nterror(req, NT_STATUS_DISK_FULL);
4799                 goto strict_unlock;
4800         }
4801
4802         if(!NT_STATUS_IS_OK(close_status)) {
4803                 reply_nterror(req, close_status);
4804                 goto strict_unlock;
4805         }
4806
4807         reply_outbuf(req, 1, 0);
4808
4809         SSVAL(req->outbuf,smb_vwv0,nwritten);
4810
4811 strict_unlock:
4812         if (numtowrite && !fsp->print_file) {
4813                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4814         }
4815
4816         END_PROFILE(SMBwriteclose);
4817         return;
4818 }
4819
4820 #undef DBGC_CLASS
4821 #define DBGC_CLASS DBGC_LOCKING
4822
4823 /****************************************************************************
4824  Reply to a lock.
4825 ****************************************************************************/
4826
4827 void reply_lock(struct smb_request *req)
4828 {
4829         connection_struct *conn = req->conn;
4830         uint64_t count,offset;
4831         NTSTATUS status;
4832         files_struct *fsp;
4833         struct byte_range_lock *br_lck = NULL;
4834
4835         START_PROFILE(SMBlock);
4836
4837         if (req->wct < 5) {
4838                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4839                 END_PROFILE(SMBlock);
4840                 return;
4841         }
4842
4843         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4844
4845         if (!check_fsp(conn, req, fsp)) {
4846                 END_PROFILE(SMBlock);
4847                 return;
4848         }
4849
4850         count = (uint64_t)IVAL(req->vwv+1, 0);
4851         offset = (uint64_t)IVAL(req->vwv+3, 0);
4852
4853         DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4854                  fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4855
4856         br_lck = do_lock(req->sconn->msg_ctx,
4857                         fsp,
4858                         (uint64_t)req->smbpid,
4859                         count,
4860                         offset,
4861                         WRITE_LOCK,
4862                         WINDOWS_LOCK,
4863                         False, /* Non-blocking lock. */
4864                         &status,
4865                         NULL,
4866                         NULL);
4867
4868         TALLOC_FREE(br_lck);
4869
4870         if (NT_STATUS_V(status)) {
4871                 reply_nterror(req, status);
4872                 END_PROFILE(SMBlock);
4873                 return;
4874         }
4875
4876         reply_outbuf(req, 0, 0);
4877
4878         END_PROFILE(SMBlock);
4879         return;
4880 }
4881
4882 /****************************************************************************
4883  Reply to a unlock.
4884 ****************************************************************************/
4885
4886 void reply_unlock(struct smb_request *req)
4887 {
4888         connection_struct *conn = req->conn;
4889         uint64_t count,offset;
4890         NTSTATUS status;
4891         files_struct *fsp;
4892
4893         START_PROFILE(SMBunlock);
4894
4895         if (req->wct < 5) {
4896                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4897                 END_PROFILE(SMBunlock);
4898                 return;
4899         }
4900
4901         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4902
4903         if (!check_fsp(conn, req, fsp)) {
4904                 END_PROFILE(SMBunlock);
4905                 return;
4906         }
4907
4908         count = (uint64_t)IVAL(req->vwv+1, 0);
4909         offset = (uint64_t)IVAL(req->vwv+3, 0);
4910
4911         status = do_unlock(req->sconn->msg_ctx,
4912                         fsp,
4913                         (uint64_t)req->smbpid,
4914                         count,
4915                         offset,
4916                         WINDOWS_LOCK);
4917
4918         if (NT_STATUS_V(status)) {
4919                 reply_nterror(req, status);
4920                 END_PROFILE(SMBunlock);
4921                 return;
4922         }
4923
4924         DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4925                     fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4926
4927         reply_outbuf(req, 0, 0);
4928
4929         END_PROFILE(SMBunlock);
4930         return;
4931 }
4932
4933 #undef DBGC_CLASS
4934 #define DBGC_CLASS DBGC_ALL
4935
4936 /****************************************************************************
4937  Reply to a tdis.
4938  conn POINTER CAN BE NULL HERE !
4939 ****************************************************************************/
4940
4941 void reply_tdis(struct smb_request *req)
4942 {
4943         connection_struct *conn = req->conn;
4944         START_PROFILE(SMBtdis);
4945
4946         if (!conn) {
4947                 DEBUG(4,("Invalid connection in tdis\n"));
4948                 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
4949                 END_PROFILE(SMBtdis);
4950                 return;
4951         }
4952
4953         conn->used = False;
4954
4955         close_cnum(conn,req->vuid);
4956         req->conn = NULL;
4957
4958         reply_outbuf(req, 0, 0);
4959         END_PROFILE(SMBtdis);
4960         return;
4961 }
4962
4963 /****************************************************************************
4964  Reply to a echo.
4965  conn POINTER CAN BE NULL HERE !
4966 ****************************************************************************/
4967
4968 void reply_echo(struct smb_request *req)
4969 {
4970         connection_struct *conn = req->conn;
4971         struct smb_perfcount_data local_pcd;
4972         struct smb_perfcount_data *cur_pcd;
4973         int smb_reverb;
4974         int seq_num;
4975
4976         START_PROFILE(SMBecho);
4977
4978         smb_init_perfcount_data(&local_pcd);
4979
4980         if (req->wct < 1) {
4981                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4982                 END_PROFILE(SMBecho);
4983                 return;
4984         }
4985
4986         smb_reverb = SVAL(req->vwv+0, 0);
4987
4988         reply_outbuf(req, 1, req->buflen);
4989
4990         /* copy any incoming data back out */
4991         if (req->buflen > 0) {
4992                 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4993         }
4994
4995         if (smb_reverb > 100) {
4996                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4997                 smb_reverb = 100;
4998         }
4999
5000         for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5001
5002                 /* this makes sure we catch the request pcd */
5003                 if (seq_num == smb_reverb) {
5004                         cur_pcd = &req->pcd;
5005                 } else {
5006                         SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5007                         cur_pcd = &local_pcd;
5008                 }
5009
5010                 SSVAL(req->outbuf,smb_vwv0,seq_num);
5011
5012                 show_msg((char *)req->outbuf);
5013                 if (!srv_send_smb(smbd_server_fd(),
5014                                 (char *)req->outbuf,
5015                                 true, req->seqnum+1,
5016                                 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5017                                 cur_pcd))
5018                         exit_server_cleanly("reply_echo: srv_send_smb failed.");
5019         }
5020
5021         DEBUG(3,("echo %d times\n", smb_reverb));
5022
5023         TALLOC_FREE(req->outbuf);
5024
5025         END_PROFILE(SMBecho);
5026         return;
5027 }
5028
5029 /****************************************************************************
5030  Reply to a printopen.
5031 ****************************************************************************/
5032
5033 void reply_printopen(struct smb_request *req)
5034 {
5035         connection_struct *conn = req->conn;
5036         files_struct *fsp;
5037         NTSTATUS status;
5038
5039         START_PROFILE(SMBsplopen);
5040
5041         if (req->wct < 2) {
5042                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5043                 END_PROFILE(SMBsplopen);
5044                 return;
5045         }
5046
5047         if (!CAN_PRINT(conn)) {
5048                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5049                 END_PROFILE(SMBsplopen);
5050                 return;
5051         }
5052
5053         status = file_new(req, conn, &fsp);
5054         if(!NT_STATUS_IS_OK(status)) {
5055                 reply_nterror(req, status);
5056                 END_PROFILE(SMBsplopen);
5057                 return;
5058         }
5059
5060         /* Open for exclusive use, write only. */
5061         status = print_spool_open(fsp, NULL, req->vuid);
5062
5063         if (!NT_STATUS_IS_OK(status)) {
5064                 file_free(req, fsp);
5065                 reply_nterror(req, status);
5066                 END_PROFILE(SMBsplopen);
5067                 return;
5068         }
5069
5070         reply_outbuf(req, 1, 0);
5071         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5072
5073         DEBUG(3,("openprint fd=%d fnum=%d\n",
5074                  fsp->fh->fd, fsp->fnum));
5075
5076         END_PROFILE(SMBsplopen);
5077         return;
5078 }
5079
5080 /****************************************************************************
5081  Reply to a printclose.
5082 ****************************************************************************/
5083
5084 void reply_printclose(struct smb_request *req)
5085 {
5086         connection_struct *conn = req->conn;
5087         files_struct *fsp;
5088         NTSTATUS status;
5089
5090         START_PROFILE(SMBsplclose);
5091
5092         if (req->wct < 1) {
5093                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5094                 END_PROFILE(SMBsplclose);
5095                 return;
5096         }
5097
5098         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5099
5100         if (!check_fsp(conn, req, fsp)) {
5101                 END_PROFILE(SMBsplclose);
5102                 return;
5103         }
5104
5105         if (!CAN_PRINT(conn)) {
5106                 reply_force_doserror(req, ERRSRV, ERRerror);
5107                 END_PROFILE(SMBsplclose);
5108                 return;
5109         }
5110
5111         DEBUG(3,("printclose fd=%d fnum=%d\n",
5112                  fsp->fh->fd,fsp->fnum));
5113
5114         status = close_file(req, fsp, NORMAL_CLOSE);
5115
5116         if(!NT_STATUS_IS_OK(status)) {
5117                 reply_nterror(req, status);
5118                 END_PROFILE(SMBsplclose);
5119                 return;
5120         }
5121
5122         reply_outbuf(req, 0, 0);
5123
5124         END_PROFILE(SMBsplclose);
5125         return;
5126 }
5127
5128 /****************************************************************************
5129  Reply to a printqueue.
5130 ****************************************************************************/
5131
5132 void reply_printqueue(struct smb_request *req)
5133 {
5134         connection_struct *conn = req->conn;
5135         int max_count;
5136         int start_index;
5137
5138         START_PROFILE(SMBsplretq);
5139
5140         if (req->wct < 2) {
5141                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5142                 END_PROFILE(SMBsplretq);
5143                 return;
5144         }
5145
5146         max_count = SVAL(req->vwv+0, 0);
5147         start_index = SVAL(req->vwv+1, 0);
5148
5149         /* we used to allow the client to get the cnum wrong, but that
5150            is really quite gross and only worked when there was only
5151            one printer - I think we should now only accept it if they
5152            get it right (tridge) */
5153         if (!CAN_PRINT(conn)) {
5154                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5155                 END_PROFILE(SMBsplretq);
5156                 return;
5157         }
5158
5159         reply_outbuf(req, 2, 3);
5160         SSVAL(req->outbuf,smb_vwv0,0);
5161         SSVAL(req->outbuf,smb_vwv1,0);
5162         SCVAL(smb_buf(req->outbuf),0,1);
5163         SSVAL(smb_buf(req->outbuf),1,0);
5164
5165         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5166                  start_index, max_count));
5167
5168         {
5169                 TALLOC_CTX *mem_ctx = talloc_tos();
5170                 NTSTATUS status;
5171                 WERROR werr;
5172                 const char *sharename = lp_servicename(SNUM(conn));
5173                 struct rpc_pipe_client *cli = NULL;
5174                 struct policy_handle handle;
5175                 struct spoolss_DevmodeContainer devmode_ctr;
5176                 union spoolss_JobInfo *info;
5177                 uint32_t count;
5178                 uint32_t num_to_get;
5179                 uint32_t first;
5180                 uint32_t i;
5181
5182                 ZERO_STRUCT(handle);
5183
5184                 status = rpc_connect_spoolss_pipe(conn, &cli);
5185                 if (!NT_STATUS_IS_OK(status)) {
5186                         DEBUG(0, ("reply_printqueue: "
5187                                   "could not connect to spoolss: %s\n",
5188                                   nt_errstr(status)));
5189                         reply_nterror(req, status);
5190                         goto out;
5191                 }
5192
5193                 ZERO_STRUCT(devmode_ctr);
5194
5195                 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
5196                                                 sharename,
5197                                                 NULL, devmode_ctr,
5198                                                 SEC_FLAG_MAXIMUM_ALLOWED,
5199                                                 &handle,
5200                                                 &werr);
5201                 if (!NT_STATUS_IS_OK(status)) {
5202                         reply_nterror(req, status);
5203                         goto out;
5204                 }
5205                 if (!W_ERROR_IS_OK(werr)) {
5206                         reply_nterror(req, werror_to_ntstatus(werr));
5207                         goto out;
5208                 }
5209
5210                 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5211                                                &handle,
5212                                                0, /* firstjob */
5213                                                0xff, /* numjobs */
5214                                                2, /* level */
5215                                                0, /* offered */
5216                                                &count,
5217                                                &info);
5218                 if (!W_ERROR_IS_OK(werr)) {
5219                         reply_nterror(req, werror_to_ntstatus(werr));
5220                         goto out;
5221                 }
5222
5223                 if (max_count > 0) {
5224                         first = start_index;
5225                 } else {
5226                         first = start_index + max_count + 1;
5227                 }
5228
5229                 if (first >= count) {
5230                         num_to_get = first;
5231                 } else {
5232                         num_to_get = first + MIN(ABS(max_count), count - first);
5233                 }
5234
5235                 for (i = first; i < num_to_get; i++) {
5236                         char blob[28];
5237                         char *p = blob;
5238                         time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5239                         int qstatus;
5240                         uint16_t qrapjobid = pjobid_to_rap(sharename,
5241                                                         info[i].info2.job_id);
5242
5243                         if (info[i].info2.status == JOB_STATUS_PRINTING) {
5244                                 qstatus = 2;
5245                         } else {
5246                                 qstatus = 3;
5247                         }
5248
5249                         srv_put_dos_date2(p, 0, qtime);
5250                         SCVAL(p, 4, qstatus);
5251                         SSVAL(p, 5, qrapjobid);
5252                         SIVAL(p, 7, info[i].info2.size);
5253                         SCVAL(p, 11, 0);
5254                         srvstr_push(blob, req->flags2, p+12,
5255                                     info[i].info2.notify_name, 16, STR_ASCII);
5256
5257                         if (message_push_blob(
5258                                     &req->outbuf,
5259                                     data_blob_const(
5260                                             blob, sizeof(blob))) == -1) {
5261                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
5262                                 goto out;
5263                         }
5264                 }
5265
5266                 if (count > 0) {
5267                         SSVAL(req->outbuf,smb_vwv0,count);
5268                         SSVAL(req->outbuf,smb_vwv1,
5269                               (max_count>0?first+count:first-1));
5270                         SCVAL(smb_buf(req->outbuf),0,1);
5271                         SSVAL(smb_buf(req->outbuf),1,28*count);
5272                 }
5273
5274
5275                 DEBUG(3, ("%u entries returned in queue\n",
5276                           (unsigned)count));
5277
5278 out:
5279                 if (cli && is_valid_policy_hnd(&handle)) {
5280                         rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
5281                 }
5282
5283         }
5284
5285         END_PROFILE(SMBsplretq);
5286         return;
5287 }
5288
5289 /****************************************************************************
5290  Reply to a printwrite.
5291 ****************************************************************************/
5292
5293 void reply_printwrite(struct smb_request *req)
5294 {
5295         connection_struct *conn = req->conn;
5296         int numtowrite;
5297         const char *data;
5298         files_struct *fsp;
5299
5300         START_PROFILE(SMBsplwr);
5301
5302         if (req->wct < 1) {
5303                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5304                 END_PROFILE(SMBsplwr);
5305                 return;
5306         }
5307
5308         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5309
5310         if (!check_fsp(conn, req, fsp)) {
5311                 END_PROFILE(SMBsplwr);
5312                 return;
5313         }
5314
5315         if (!fsp->print_file) {
5316                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5317                 END_PROFILE(SMBsplwr);
5318                 return;
5319         }
5320
5321         if (!CHECK_WRITE(fsp)) {
5322                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5323                 END_PROFILE(SMBsplwr);
5324                 return;
5325         }
5326
5327         numtowrite = SVAL(req->buf, 1);
5328
5329         if (req->buflen < numtowrite + 3) {
5330                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5331                 END_PROFILE(SMBsplwr);
5332                 return;
5333         }
5334
5335         data = (const char *)req->buf + 3;
5336
5337         if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5338                 reply_nterror(req, map_nt_error_from_unix(errno));
5339                 END_PROFILE(SMBsplwr);
5340                 return;
5341         }
5342
5343         DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5344
5345         END_PROFILE(SMBsplwr);
5346         return;
5347 }
5348
5349 /****************************************************************************
5350  Reply to a mkdir.
5351 ****************************************************************************/
5352
5353 void reply_mkdir(struct smb_request *req)
5354 {
5355         connection_struct *conn = req->conn;
5356         struct smb_filename *smb_dname = NULL;
5357         char *directory = NULL;
5358         NTSTATUS status;
5359         TALLOC_CTX *ctx = talloc_tos();
5360
5361         START_PROFILE(SMBmkdir);
5362
5363         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5364                             STR_TERMINATE, &status);
5365         if (!NT_STATUS_IS_OK(status)) {
5366                 reply_nterror(req, status);
5367                 goto out;
5368         }
5369
5370         status = filename_convert(ctx, conn,
5371                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
5372                                  directory,
5373                                  0,
5374                                  NULL,
5375                                  &smb_dname);
5376         if (!NT_STATUS_IS_OK(status)) {
5377                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5378                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5379                                         ERRSRV, ERRbadpath);
5380                         goto out;
5381                 }
5382                 reply_nterror(req, status);
5383                 goto out;
5384         }
5385
5386         status = create_directory(conn, req, smb_dname);
5387
5388         DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5389
5390         if (!NT_STATUS_IS_OK(status)) {
5391
5392                 if (!use_nt_status()
5393                     && NT_STATUS_EQUAL(status,
5394                                        NT_STATUS_OBJECT_NAME_COLLISION)) {
5395                         /*
5396                          * Yes, in the DOS error code case we get a
5397                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5398                          * samba4 torture test.
5399                          */
5400                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5401                 }
5402
5403                 reply_nterror(req, status);
5404                 goto out;
5405         }
5406
5407         reply_outbuf(req, 0, 0);
5408
5409         DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5410  out:
5411         TALLOC_FREE(smb_dname);
5412         END_PROFILE(SMBmkdir);
5413         return;
5414 }
5415
5416 /****************************************************************************
5417  Reply to a rmdir.
5418 ****************************************************************************/
5419
5420 void reply_rmdir(struct smb_request *req)
5421 {
5422         connection_struct *conn = req->conn;
5423         struct smb_filename *smb_dname = NULL;
5424         char *directory = NULL;
5425         NTSTATUS status;
5426         TALLOC_CTX *ctx = talloc_tos();
5427         files_struct *fsp = NULL;
5428         int info = 0;
5429         struct smbd_server_connection *sconn = req->sconn;
5430
5431         START_PROFILE(SMBrmdir);
5432
5433         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5434                             STR_TERMINATE, &status);
5435         if (!NT_STATUS_IS_OK(status)) {
5436                 reply_nterror(req, status);
5437                 goto out;
5438         }
5439
5440         status = filename_convert(ctx, conn,
5441                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
5442                                  directory,
5443                                  0,
5444                                  NULL,
5445                                  &smb_dname);
5446         if (!NT_STATUS_IS_OK(status)) {
5447                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5448                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5449                                         ERRSRV, ERRbadpath);
5450                         goto out;
5451                 }
5452                 reply_nterror(req, status);
5453                 goto out;
5454         }
5455
5456         if (is_ntfs_stream_smb_fname(smb_dname)) {
5457                 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5458                 goto out;
5459         }
5460
5461         status = SMB_VFS_CREATE_FILE(
5462                 conn,                                   /* conn */
5463                 req,                                    /* req */
5464                 0,                                      /* root_dir_fid */
5465                 smb_dname,                              /* fname */
5466                 DELETE_ACCESS,                          /* access_mask */
5467                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
5468                         FILE_SHARE_DELETE),
5469                 FILE_OPEN,                              /* create_disposition*/
5470                 FILE_DIRECTORY_FILE,                    /* create_options */
5471                 FILE_ATTRIBUTE_DIRECTORY,               /* file_attributes */
5472                 0,                                      /* oplock_request */
5473                 0,                                      /* allocation_size */
5474                 0,                                      /* private_flags */
5475                 NULL,                                   /* sd */
5476                 NULL,                                   /* ea_list */
5477                 &fsp,                                   /* result */
5478                 &info);                                 /* pinfo */
5479
5480         if (!NT_STATUS_IS_OK(status)) {
5481                 if (open_was_deferred(req->mid)) {
5482                         /* We have re-scheduled this call. */
5483                         goto out;
5484                 }
5485                 reply_nterror(req, status);
5486                 goto out;
5487         }
5488
5489         status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5490         if (!NT_STATUS_IS_OK(status)) {
5491                 close_file(req, fsp, ERROR_CLOSE);
5492                 reply_nterror(req, status);
5493                 goto out;
5494         }
5495
5496         if (!set_delete_on_close(fsp, true, &conn->server_info->utok)) {
5497                 close_file(req, fsp, ERROR_CLOSE);
5498                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5499                 goto out;
5500         }
5501
5502         status = close_file(req, fsp, NORMAL_CLOSE);
5503         if (!NT_STATUS_IS_OK(status)) {
5504                 reply_nterror(req, status);
5505         } else {
5506                 reply_outbuf(req, 0, 0);
5507         }
5508
5509         dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5510
5511         DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5512  out:
5513         TALLOC_FREE(smb_dname);
5514         END_PROFILE(SMBrmdir);
5515         return;
5516 }
5517
5518 /*******************************************************************
5519  Resolve wildcards in a filename rename.
5520 ********************************************************************/
5521
5522 static bool resolve_wildcards(TALLOC_CTX *ctx,
5523                                 const char *name1,
5524                                 const char *name2,
5525                                 char **pp_newname)
5526 {
5527         char *name2_copy = NULL;
5528         char *root1 = NULL;
5529         char *root2 = NULL;
5530         char *ext1 = NULL;
5531         char *ext2 = NULL;
5532         char *p,*p2, *pname1, *pname2;
5533
5534         name2_copy = talloc_strdup(ctx, name2);
5535         if (!name2_copy) {
5536                 return False;
5537         }
5538
5539         pname1 = strrchr_m(name1,'/');
5540         pname2 = strrchr_m(name2_copy,'/');
5541
5542         if (!pname1 || !pname2) {
5543                 return False;
5544         }
5545
5546         /* Truncate the copy of name2 at the last '/' */
5547         *pname2 = '\0';
5548
5549         /* Now go past the '/' */
5550         pname1++;
5551         pname2++;
5552
5553         root1 = talloc_strdup(ctx, pname1);
5554         root2 = talloc_strdup(ctx, pname2);
5555
5556         if (!root1 || !root2) {
5557                 return False;
5558         }
5559
5560         p = strrchr_m(root1,'.');
5561         if (p) {
5562                 *p = 0;
5563                 ext1 = talloc_strdup(ctx, p+1);
5564         } else {
5565                 ext1 = talloc_strdup(ctx, "");
5566         }
5567         p = strrchr_m(root2,'.');
5568         if (p) {
5569                 *p = 0;
5570                 ext2 = talloc_strdup(ctx, p+1);
5571         } else {
5572                 ext2 = talloc_strdup(ctx, "");
5573         }
5574
5575         if (!ext1 || !ext2) {
5576                 return False;
5577         }
5578
5579         p = root1;
5580         p2 = root2;
5581         while (*p2) {
5582                 if (*p2 == '?') {
5583                         /* Hmmm. Should this be mb-aware ? */
5584                         *p2 = *p;
5585                         p2++;
5586                 } else if (*p2 == '*') {
5587                         *p2 = '\0';
5588                         root2 = talloc_asprintf(ctx, "%s%s",
5589                                                 root2,
5590                                                 p);
5591                         if (!root2) {
5592                                 return False;
5593                         }
5594                         break;
5595                 } else {
5596                         p2++;
5597                 }
5598                 if (*p) {
5599                         p++;
5600                 }
5601         }
5602
5603         p = ext1;
5604         p2 = ext2;
5605         while (*p2) {
5606                 if (*p2 == '?') {
5607                         /* Hmmm. Should this be mb-aware ? */
5608                         *p2 = *p;
5609                         p2++;
5610                 } else if (*p2 == '*') {
5611                         *p2 = '\0';
5612                         ext2 = talloc_asprintf(ctx, "%s%s",
5613                                                 ext2,
5614                                                 p);
5615                         if (!ext2) {
5616                                 return False;
5617                         }
5618                         break;
5619                 } else {
5620                         p2++;
5621                 }
5622                 if (*p) {
5623                         p++;
5624                 }
5625         }
5626
5627         if (*ext2) {
5628                 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5629                                 name2_copy,
5630                                 root2,
5631                                 ext2);
5632         } else {
5633                 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5634                                 name2_copy,
5635                                 root2);
5636         }
5637
5638         if (!*pp_newname) {
5639                 return False;
5640         }
5641
5642         return True;
5643 }
5644
5645 /****************************************************************************
5646  Ensure open files have their names updated. Updated to notify other smbd's
5647  asynchronously.
5648 ****************************************************************************/
5649
5650 static void rename_open_files(connection_struct *conn,
5651                               struct share_mode_lock *lck,
5652                               const struct smb_filename *smb_fname_dst)
5653 {
5654         files_struct *fsp;
5655         bool did_rename = False;
5656         NTSTATUS status;
5657
5658         for(fsp = file_find_di_first(lck->id); fsp;
5659             fsp = file_find_di_next(fsp)) {
5660                 /* fsp_name is a relative path under the fsp. To change this for other
5661                    sharepaths we need to manipulate relative paths. */
5662                 /* TODO - create the absolute path and manipulate the newname
5663                    relative to the sharepath. */
5664                 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5665                         continue;
5666                 }
5667                 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5668                            "(file_id %s) from %s -> %s\n", fsp->fnum,
5669                            file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5670                            smb_fname_str_dbg(smb_fname_dst)));
5671
5672                 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5673                 if (NT_STATUS_IS_OK(status)) {
5674                         did_rename = True;
5675                 }
5676         }
5677
5678         if (!did_rename) {
5679                 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5680                            "for %s\n", file_id_string_tos(&lck->id),
5681                            smb_fname_str_dbg(smb_fname_dst)));
5682         }
5683
5684         /* Send messages to all smbd's (not ourself) that the name has changed. */
5685         rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5686                               smb_fname_dst);
5687
5688 }
5689
5690 /****************************************************************************
5691  We need to check if the source path is a parent directory of the destination
5692  (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5693  refuse the rename with a sharing violation. Under UNIX the above call can
5694  *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5695  probably need to check that the client is a Windows one before disallowing
5696  this as a UNIX client (one with UNIX extensions) can know the source is a
5697  symlink and make this decision intelligently. Found by an excellent bug
5698  report from <AndyLiebman@aol.com>.
5699 ****************************************************************************/
5700
5701 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5702                                      const struct smb_filename *smb_fname_dst)
5703 {
5704         const char *psrc = smb_fname_src->base_name;
5705         const char *pdst = smb_fname_dst->base_name;
5706         size_t slen;
5707
5708         if (psrc[0] == '.' && psrc[1] == '/') {
5709                 psrc += 2;
5710         }
5711         if (pdst[0] == '.' && pdst[1] == '/') {
5712                 pdst += 2;
5713         }
5714         if ((slen = strlen(psrc)) > strlen(pdst)) {
5715                 return False;
5716         }
5717         return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5718 }
5719
5720 /*
5721  * Do the notify calls from a rename
5722  */
5723
5724 static void notify_rename(connection_struct *conn, bool is_dir,
5725                           const struct smb_filename *smb_fname_src,
5726                           const struct smb_filename *smb_fname_dst)
5727 {
5728         char *parent_dir_src = NULL;
5729         char *parent_dir_dst = NULL;
5730         uint32 mask;
5731
5732         mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5733                 : FILE_NOTIFY_CHANGE_FILE_NAME;
5734
5735         if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5736                             &parent_dir_src, NULL) ||
5737             !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5738                             &parent_dir_dst, NULL)) {
5739                 goto out;
5740         }
5741
5742         if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5743                 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5744                              smb_fname_src->base_name);
5745                 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5746                              smb_fname_dst->base_name);
5747         }
5748         else {
5749                 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5750                              smb_fname_src->base_name);
5751                 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5752                              smb_fname_dst->base_name);
5753         }
5754
5755         /* this is a strange one. w2k3 gives an additional event for
5756            CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5757            files, but not directories */
5758         if (!is_dir) {
5759                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5760                              FILE_NOTIFY_CHANGE_ATTRIBUTES
5761                              |FILE_NOTIFY_CHANGE_CREATION,
5762                              smb_fname_dst->base_name);
5763         }
5764  out:
5765         TALLOC_FREE(parent_dir_src);
5766         TALLOC_FREE(parent_dir_dst);
5767 }
5768
5769 /****************************************************************************
5770  Rename an open file - given an fsp.
5771 ****************************************************************************/
5772
5773 NTSTATUS rename_internals_fsp(connection_struct *conn,
5774                         files_struct *fsp,
5775                         const struct smb_filename *smb_fname_dst_in,
5776                         uint32 attrs,
5777                         bool replace_if_exists)
5778 {
5779         TALLOC_CTX *ctx = talloc_tos();
5780         struct smb_filename *smb_fname_dst = NULL;
5781         NTSTATUS status = NT_STATUS_OK;
5782         struct share_mode_lock *lck = NULL;
5783         bool dst_exists, old_is_stream, new_is_stream;
5784
5785         status = check_name(conn, smb_fname_dst_in->base_name);
5786         if (!NT_STATUS_IS_OK(status)) {
5787                 return status;
5788         }
5789
5790         /* Make a copy of the dst smb_fname structs */
5791
5792         status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5793         if (!NT_STATUS_IS_OK(status)) {
5794                 goto out;
5795         }
5796
5797         /* Ensure the dst smb_fname contains a '/' */
5798         if(strrchr_m(smb_fname_dst->base_name,'/') == 0) {
5799                 char * tmp;
5800                 tmp = talloc_asprintf(smb_fname_dst, "./%s",
5801                                       smb_fname_dst->base_name);
5802                 if (!tmp) {
5803                         status = NT_STATUS_NO_MEMORY;
5804                         goto out;
5805                 }
5806                 TALLOC_FREE(smb_fname_dst->base_name);
5807                 smb_fname_dst->base_name = tmp;
5808         }
5809
5810         /*
5811          * Check for special case with case preserving and not
5812          * case sensitive. If the old last component differs from the original
5813          * last component only by case, then we should allow
5814          * the rename (user is trying to change the case of the
5815          * filename).
5816          */
5817         if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5818             strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5819             strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
5820                 char *last_slash;
5821                 char *fname_dst_lcomp_base_mod = NULL;
5822                 struct smb_filename *smb_fname_orig_lcomp = NULL;
5823
5824                 /*
5825                  * Get the last component of the destination name.  Note that
5826                  * we guarantee that destination name contains a '/' character
5827                  * above.
5828                  */
5829                 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5830                 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5831                 if (!fname_dst_lcomp_base_mod) {
5832                         status = NT_STATUS_NO_MEMORY;
5833                         goto out;
5834                 }
5835
5836                 /*
5837                  * Create an smb_filename struct using the original last
5838                  * component of the destination.
5839                  */
5840                 status = create_synthetic_smb_fname_split(ctx,
5841                     smb_fname_dst->original_lcomp, NULL,
5842                     &smb_fname_orig_lcomp);
5843                 if (!NT_STATUS_IS_OK(status)) {
5844                         TALLOC_FREE(fname_dst_lcomp_base_mod);
5845                         goto out;
5846                 }
5847
5848                 /* If the base names only differ by case, use original. */
5849                 if(!strcsequal(fname_dst_lcomp_base_mod,
5850                                smb_fname_orig_lcomp->base_name)) {
5851                         char *tmp;
5852                         /*
5853                          * Replace the modified last component with the
5854                          * original.
5855                          */
5856                         *last_slash = '\0'; /* Truncate at the '/' */
5857                         tmp = talloc_asprintf(smb_fname_dst,
5858                                         "%s/%s",
5859                                         smb_fname_dst->base_name,
5860                                         smb_fname_orig_lcomp->base_name);
5861                         if (tmp == NULL) {
5862                                 status = NT_STATUS_NO_MEMORY;
5863                                 TALLOC_FREE(fname_dst_lcomp_base_mod);
5864                                 TALLOC_FREE(smb_fname_orig_lcomp);
5865                                 goto out;
5866                         }
5867                         TALLOC_FREE(smb_fname_dst->base_name);
5868                         smb_fname_dst->base_name = tmp;
5869                 }
5870
5871                 /* If the stream_names only differ by case, use original. */
5872                 if(!strcsequal(smb_fname_dst->stream_name,
5873                                smb_fname_orig_lcomp->stream_name)) {
5874                         char *tmp = NULL;
5875                         /* Use the original stream. */
5876                         tmp = talloc_strdup(smb_fname_dst,
5877                                             smb_fname_orig_lcomp->stream_name);
5878                         if (tmp == NULL) {
5879                                 status = NT_STATUS_NO_MEMORY;
5880                                 TALLOC_FREE(fname_dst_lcomp_base_mod);
5881                                 TALLOC_FREE(smb_fname_orig_lcomp);
5882                                 goto out;
5883                         }
5884                         TALLOC_FREE(smb_fname_dst->stream_name);
5885                         smb_fname_dst->stream_name = tmp;
5886                 }
5887                 TALLOC_FREE(fname_dst_lcomp_base_mod);
5888                 TALLOC_FREE(smb_fname_orig_lcomp);
5889         }
5890
5891         /*
5892          * If the src and dest names are identical - including case,
5893          * don't do the rename, just return success.
5894          */
5895
5896         if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5897             strcsequal(fsp->fsp_name->stream_name,
5898                        smb_fname_dst->stream_name)) {
5899                 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
5900                           "- returning success\n",
5901                           smb_fname_str_dbg(smb_fname_dst)));
5902                 status = NT_STATUS_OK;
5903                 goto out;
5904         }
5905
5906         old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
5907         new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
5908
5909         /* Return the correct error code if both names aren't streams. */
5910         if (!old_is_stream && new_is_stream) {
5911                 status = NT_STATUS_OBJECT_NAME_INVALID;
5912                 goto out;
5913         }
5914
5915         if (old_is_stream && !new_is_stream) {
5916                 status = NT_STATUS_INVALID_PARAMETER;
5917                 goto out;
5918         }
5919
5920         dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
5921
5922         if(!replace_if_exists && dst_exists) {
5923                 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
5924                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
5925                           smb_fname_str_dbg(smb_fname_dst)));
5926                 status = NT_STATUS_OBJECT_NAME_COLLISION;
5927                 goto out;
5928         }
5929
5930         if (dst_exists) {
5931                 struct file_id fileid = vfs_file_id_from_sbuf(conn,
5932                     &smb_fname_dst->st);
5933                 files_struct *dst_fsp = file_find_di_first(fileid);
5934                 /* The file can be open when renaming a stream */
5935                 if (dst_fsp && !new_is_stream) {
5936                         DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5937                         status = NT_STATUS_ACCESS_DENIED;
5938                         goto out;
5939                 }
5940         }
5941
5942         /* Ensure we have a valid stat struct for the source. */
5943         status = vfs_stat_fsp(fsp);
5944         if (!NT_STATUS_IS_OK(status)) {
5945                 goto out;
5946         }
5947
5948         status = can_rename(conn, fsp, attrs);
5949
5950         if (!NT_STATUS_IS_OK(status)) {
5951                 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
5952                           nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
5953                           smb_fname_str_dbg(smb_fname_dst)));
5954                 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5955                         status = NT_STATUS_ACCESS_DENIED;
5956                 goto out;
5957         }
5958
5959         if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
5960                 status = NT_STATUS_ACCESS_DENIED;
5961         }
5962
5963         lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5964                                   NULL);
5965
5966         /*
5967          * We have the file open ourselves, so not being able to get the
5968          * corresponding share mode lock is a fatal error.
5969          */
5970
5971         SMB_ASSERT(lck != NULL);
5972
5973         if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
5974                 uint32 create_options = fsp->fh->private_options;
5975
5976                 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
5977                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
5978                           smb_fname_str_dbg(smb_fname_dst)));
5979
5980                 if (lp_map_archive(SNUM(conn)) ||
5981                     lp_store_dos_attributes(SNUM(conn))) {
5982                         /* We must set the archive bit on the newly
5983                            renamed file. */
5984                         if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
5985                                 uint32_t old_dosmode = dos_mode(conn,
5986                                                         smb_fname_dst);
5987                                 file_set_dosmode(conn,
5988                                         smb_fname_dst,
5989                                         old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
5990                                         NULL,
5991                                         true);
5992                         }
5993                 }
5994
5995                 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
5996                               smb_fname_dst);
5997
5998                 rename_open_files(conn, lck, smb_fname_dst);
5999
6000                 /*
6001                  * A rename acts as a new file create w.r.t. allowing an initial delete
6002                  * on close, probably because in Windows there is a new handle to the
6003                  * new file. If initial delete on close was requested but not
6004                  * originally set, we need to set it here. This is probably not 100% correct,
6005                  * but will work for the CIFSFS client which in non-posix mode
6006                  * depends on these semantics. JRA.
6007                  */
6008
6009                 if (create_options & FILE_DELETE_ON_CLOSE) {
6010                         status = can_set_delete_on_close(fsp, 0);
6011
6012                         if (NT_STATUS_IS_OK(status)) {
6013                                 /* Note that here we set the *inital* delete on close flag,
6014                                  * not the regular one. The magic gets handled in close. */
6015                                 fsp->initial_delete_on_close = True;
6016                         }
6017                 }
6018                 TALLOC_FREE(lck);
6019                 status = NT_STATUS_OK;
6020                 goto out;
6021         }
6022
6023         TALLOC_FREE(lck);
6024
6025         if (errno == ENOTDIR || errno == EISDIR) {
6026                 status = NT_STATUS_OBJECT_NAME_COLLISION;
6027         } else {
6028                 status = map_nt_error_from_unix(errno);
6029         }
6030
6031         DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6032                   nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6033                   smb_fname_str_dbg(smb_fname_dst)));
6034
6035  out:
6036         TALLOC_FREE(smb_fname_dst);
6037
6038         return status;
6039 }
6040
6041 /****************************************************************************
6042  The guts of the rename command, split out so it may be called by the NT SMB
6043  code.
6044 ****************************************************************************/
6045
6046 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6047                         connection_struct *conn,
6048                         struct smb_request *req,
6049                         struct smb_filename *smb_fname_src,
6050                         struct smb_filename *smb_fname_dst,
6051                         uint32 attrs,
6052                         bool replace_if_exists,
6053                         bool src_has_wild,
6054                         bool dest_has_wild,
6055                         uint32_t access_mask)
6056 {
6057         char *fname_src_dir = NULL;
6058         char *fname_src_mask = NULL;
6059         int count=0;
6060         NTSTATUS status = NT_STATUS_OK;
6061         struct smb_Dir *dir_hnd = NULL;
6062         const char *dname = NULL;
6063         char *talloced = NULL;
6064         long offset = 0;
6065         int create_options = 0;
6066         bool posix_pathnames = lp_posix_pathnames();
6067
6068         /*
6069          * Split the old name into directory and last component
6070          * strings. Note that unix_convert may have stripped off a
6071          * leading ./ from both name and newname if the rename is
6072          * at the root of the share. We need to make sure either both
6073          * name and newname contain a / character or neither of them do
6074          * as this is checked in resolve_wildcards().
6075          */
6076
6077         /* Split up the directory from the filename/mask. */
6078         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6079                                       &fname_src_dir, &fname_src_mask);
6080         if (!NT_STATUS_IS_OK(status)) {
6081                 status = NT_STATUS_NO_MEMORY;
6082                 goto out;
6083         }
6084
6085         /*
6086          * We should only check the mangled cache
6087          * here if unix_convert failed. This means
6088          * that the path in 'mask' doesn't exist
6089          * on the file system and so we need to look
6090          * for a possible mangle. This patch from
6091          * Tine Smukavec <valentin.smukavec@hermes.si>.
6092          */
6093
6094         if (!VALID_STAT(smb_fname_src->st) &&
6095             mangle_is_mangled(fname_src_mask, conn->params)) {
6096                 char *new_mask = NULL;
6097                 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6098                                             conn->params);
6099                 if (new_mask) {
6100                         TALLOC_FREE(fname_src_mask);
6101                         fname_src_mask = new_mask;
6102                 }
6103         }
6104
6105         if (!src_has_wild) {
6106                 files_struct *fsp;
6107
6108                 /*
6109                  * Only one file needs to be renamed. Append the mask back
6110                  * onto the directory.
6111                  */
6112                 TALLOC_FREE(smb_fname_src->base_name);
6113                 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6114                                                            "%s/%s",
6115                                                            fname_src_dir,
6116                                                            fname_src_mask);
6117                 if (!smb_fname_src->base_name) {
6118                         status = NT_STATUS_NO_MEMORY;
6119                         goto out;
6120                 }
6121
6122                 /* Ensure dst fname contains a '/' also */
6123                 if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
6124                         char *tmp;
6125                         tmp = talloc_asprintf(smb_fname_dst, "./%s",
6126                                               smb_fname_dst->base_name);
6127                         if (!tmp) {
6128                                 status = NT_STATUS_NO_MEMORY;
6129                                 goto out;
6130                         }
6131                         TALLOC_FREE(smb_fname_dst->base_name);
6132                         smb_fname_dst->base_name = tmp;
6133                 }
6134
6135                 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6136                           "case_preserve = %d, short case preserve = %d, "
6137                           "directory = %s, newname = %s, "
6138                           "last_component_dest = %s\n",
6139                           conn->case_sensitive, conn->case_preserve,
6140                           conn->short_case_preserve,
6141                           smb_fname_str_dbg(smb_fname_src),
6142                           smb_fname_str_dbg(smb_fname_dst),
6143                           smb_fname_dst->original_lcomp));
6144
6145                 /* The dest name still may have wildcards. */
6146                 if (dest_has_wild) {
6147                         char *fname_dst_mod = NULL;
6148                         if (!resolve_wildcards(smb_fname_dst,
6149                                                smb_fname_src->base_name,
6150                                                smb_fname_dst->base_name,
6151                                                &fname_dst_mod)) {
6152                                 DEBUG(6, ("rename_internals: resolve_wildcards "
6153                                           "%s %s failed\n",
6154                                           smb_fname_src->base_name,
6155                                           smb_fname_dst->base_name));
6156                                 status = NT_STATUS_NO_MEMORY;
6157                                 goto out;
6158                         }
6159                         TALLOC_FREE(smb_fname_dst->base_name);
6160                         smb_fname_dst->base_name = fname_dst_mod;
6161                 }
6162
6163                 ZERO_STRUCT(smb_fname_src->st);
6164                 if (posix_pathnames) {
6165                         SMB_VFS_LSTAT(conn, smb_fname_src);
6166                 } else {
6167                         SMB_VFS_STAT(conn, smb_fname_src);
6168                 }
6169
6170                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6171                         create_options |= FILE_DIRECTORY_FILE;
6172                 }
6173
6174                 status = SMB_VFS_CREATE_FILE(
6175                         conn,                           /* conn */
6176                         req,                            /* req */
6177                         0,                              /* root_dir_fid */
6178                         smb_fname_src,                  /* fname */
6179                         access_mask,                    /* access_mask */
6180                         (FILE_SHARE_READ |              /* share_access */
6181                             FILE_SHARE_WRITE),
6182                         FILE_OPEN,                      /* create_disposition*/
6183                         create_options,                 /* create_options */
6184                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6185                         0,                              /* oplock_request */
6186                         0,                              /* allocation_size */
6187                         0,                              /* private_flags */
6188                         NULL,                           /* sd */
6189                         NULL,                           /* ea_list */
6190                         &fsp,                           /* result */
6191                         NULL);                          /* pinfo */
6192
6193                 if (!NT_STATUS_IS_OK(status)) {
6194                         DEBUG(3, ("Could not open rename source %s: %s\n",
6195                                   smb_fname_str_dbg(smb_fname_src),
6196                                   nt_errstr(status)));
6197                         goto out;
6198                 }
6199
6200                 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6201                                               attrs, replace_if_exists);
6202
6203                 close_file(req, fsp, NORMAL_CLOSE);
6204
6205                 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6206                           nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6207                           smb_fname_str_dbg(smb_fname_dst)));
6208
6209                 goto out;
6210         }
6211
6212         /*
6213          * Wildcards - process each file that matches.
6214          */
6215         if (strequal(fname_src_mask, "????????.???")) {
6216                 TALLOC_FREE(fname_src_mask);
6217                 fname_src_mask = talloc_strdup(ctx, "*");
6218                 if (!fname_src_mask) {
6219                         status = NT_STATUS_NO_MEMORY;
6220                         goto out;
6221                 }
6222         }
6223
6224         status = check_name(conn, fname_src_dir);
6225         if (!NT_STATUS_IS_OK(status)) {
6226                 goto out;
6227         }
6228
6229         dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6230                           attrs);
6231         if (dir_hnd == NULL) {
6232                 status = map_nt_error_from_unix(errno);
6233                 goto out;
6234         }
6235
6236         status = NT_STATUS_NO_SUCH_FILE;
6237         /*
6238          * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6239          * - gentest fix. JRA
6240          */
6241
6242         while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6243                                     &talloced))) {
6244                 files_struct *fsp = NULL;
6245                 char *destname = NULL;
6246                 bool sysdir_entry = False;
6247
6248                 /* Quick check for "." and ".." */
6249                 if (ISDOT(dname) || ISDOTDOT(dname)) {
6250                         if (attrs & aDIR) {
6251                                 sysdir_entry = True;
6252                         } else {
6253                                 TALLOC_FREE(talloced);
6254                                 continue;
6255                         }
6256                 }
6257
6258                 if (!is_visible_file(conn, fname_src_dir, dname,
6259                                      &smb_fname_src->st, false)) {
6260                         TALLOC_FREE(talloced);
6261                         continue;
6262                 }
6263
6264                 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6265                         TALLOC_FREE(talloced);
6266                         continue;
6267                 }
6268
6269                 if (sysdir_entry) {
6270                         status = NT_STATUS_OBJECT_NAME_INVALID;
6271                         break;
6272                 }
6273
6274                 TALLOC_FREE(smb_fname_src->base_name);
6275                 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6276                                                            "%s/%s",
6277                                                            fname_src_dir,
6278                                                            dname);
6279                 if (!smb_fname_src->base_name) {
6280                         status = NT_STATUS_NO_MEMORY;
6281                         goto out;
6282                 }
6283
6284                 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6285                                        smb_fname_dst->base_name,
6286                                        &destname)) {
6287                         DEBUG(6, ("resolve_wildcards %s %s failed\n",
6288                                   smb_fname_src->base_name, destname));
6289                         TALLOC_FREE(talloced);
6290                         continue;
6291                 }
6292                 if (!destname) {
6293                         status = NT_STATUS_NO_MEMORY;
6294                         goto out;
6295                 }
6296
6297                 TALLOC_FREE(smb_fname_dst->base_name);
6298                 smb_fname_dst->base_name = destname;
6299
6300                 ZERO_STRUCT(smb_fname_src->st);
6301                 if (posix_pathnames) {
6302                         SMB_VFS_LSTAT(conn, smb_fname_src);
6303                 } else {
6304                         SMB_VFS_STAT(conn, smb_fname_src);
6305                 }
6306
6307                 create_options = 0;
6308
6309                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6310                         create_options |= FILE_DIRECTORY_FILE;
6311                 }
6312
6313                 status = SMB_VFS_CREATE_FILE(
6314                         conn,                           /* conn */
6315                         req,                            /* req */
6316                         0,                              /* root_dir_fid */
6317                         smb_fname_src,                  /* fname */
6318                         access_mask,                    /* access_mask */
6319                         (FILE_SHARE_READ |              /* share_access */
6320                             FILE_SHARE_WRITE),
6321                         FILE_OPEN,                      /* create_disposition*/
6322                         create_options,                 /* create_options */
6323                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6324                         0,                              /* oplock_request */
6325                         0,                              /* allocation_size */
6326                         0,                              /* private_flags */
6327                         NULL,                           /* sd */
6328                         NULL,                           /* ea_list */
6329                         &fsp,                           /* result */
6330                         NULL);                          /* pinfo */
6331
6332                 if (!NT_STATUS_IS_OK(status)) {
6333                         DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6334                                  "returned %s rename %s -> %s\n",
6335                                  nt_errstr(status),
6336                                  smb_fname_str_dbg(smb_fname_src),
6337                                  smb_fname_str_dbg(smb_fname_dst)));
6338                         break;
6339                 }
6340
6341                 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6342                                                               dname);
6343                 if (!smb_fname_dst->original_lcomp) {
6344                         status = NT_STATUS_NO_MEMORY;
6345                         goto out;
6346                 }
6347
6348                 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6349                                               attrs, replace_if_exists);
6350
6351                 close_file(req, fsp, NORMAL_CLOSE);
6352
6353                 if (!NT_STATUS_IS_OK(status)) {
6354                         DEBUG(3, ("rename_internals_fsp returned %s for "
6355                                   "rename %s -> %s\n", nt_errstr(status),
6356                                   smb_fname_str_dbg(smb_fname_src),
6357                                   smb_fname_str_dbg(smb_fname_dst)));
6358                         break;
6359                 }
6360
6361                 count++;
6362
6363                 DEBUG(3,("rename_internals: doing rename on %s -> "
6364                          "%s\n", smb_fname_str_dbg(smb_fname_src),
6365                          smb_fname_str_dbg(smb_fname_src)));
6366                 TALLOC_FREE(talloced);
6367         }
6368         TALLOC_FREE(dir_hnd);
6369
6370         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6371                 status = map_nt_error_from_unix(errno);
6372         }
6373
6374  out:
6375         TALLOC_FREE(talloced);
6376         TALLOC_FREE(fname_src_dir);
6377         TALLOC_FREE(fname_src_mask);
6378         return status;
6379 }
6380
6381 /****************************************************************************
6382  Reply to a mv.
6383 ****************************************************************************/
6384
6385 void reply_mv(struct smb_request *req)
6386 {
6387         connection_struct *conn = req->conn;
6388         char *name = NULL;
6389         char *newname = NULL;
6390         const char *p;
6391         uint32 attrs;
6392         NTSTATUS status;
6393         bool src_has_wcard = False;
6394         bool dest_has_wcard = False;
6395         TALLOC_CTX *ctx = talloc_tos();
6396         struct smb_filename *smb_fname_src = NULL;
6397         struct smb_filename *smb_fname_dst = NULL;
6398
6399         START_PROFILE(SMBmv);
6400
6401         if (req->wct < 1) {
6402                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6403                 goto out;
6404         }
6405
6406         attrs = SVAL(req->vwv+0, 0);
6407
6408         p = (const char *)req->buf + 1;
6409         p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6410                                        &status, &src_has_wcard);
6411         if (!NT_STATUS_IS_OK(status)) {
6412                 reply_nterror(req, status);
6413                 goto out;
6414         }
6415         p++;
6416         p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6417                                        &status, &dest_has_wcard);
6418         if (!NT_STATUS_IS_OK(status)) {
6419                 reply_nterror(req, status);
6420                 goto out;
6421         }
6422
6423         status = filename_convert(ctx,
6424                                   conn,
6425                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6426                                   name,
6427                                   UCF_COND_ALLOW_WCARD_LCOMP,
6428                                   &src_has_wcard,
6429                                   &smb_fname_src);
6430
6431         if (!NT_STATUS_IS_OK(status)) {
6432                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6433                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6434                                         ERRSRV, ERRbadpath);
6435                         goto out;
6436                 }
6437                 reply_nterror(req, status);
6438                 goto out;
6439         }
6440
6441         status = filename_convert(ctx,
6442                                   conn,
6443                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6444                                   newname,
6445                                   UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6446                                   &dest_has_wcard,
6447                                   &smb_fname_dst);
6448
6449         if (!NT_STATUS_IS_OK(status)) {
6450                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6451                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6452                                         ERRSRV, ERRbadpath);
6453                         goto out;
6454                 }
6455                 reply_nterror(req, status);
6456                 goto out;
6457         }
6458
6459         DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6460                  smb_fname_str_dbg(smb_fname_dst)));
6461
6462         status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6463                                   attrs, False, src_has_wcard, dest_has_wcard,
6464                                   DELETE_ACCESS);
6465         if (!NT_STATUS_IS_OK(status)) {
6466                 if (open_was_deferred(req->mid)) {
6467                         /* We have re-scheduled this call. */
6468                         goto out;
6469                 }
6470                 reply_nterror(req, status);
6471                 goto out;
6472         }
6473
6474         reply_outbuf(req, 0, 0);
6475  out:
6476         TALLOC_FREE(smb_fname_src);
6477         TALLOC_FREE(smb_fname_dst);
6478         END_PROFILE(SMBmv);
6479         return;
6480 }
6481
6482 /*******************************************************************
6483  Copy a file as part of a reply_copy.
6484 ******************************************************************/
6485
6486 /*
6487  * TODO: check error codes on all callers
6488  */
6489
6490 NTSTATUS copy_file(TALLOC_CTX *ctx,
6491                         connection_struct *conn,
6492                         struct smb_filename *smb_fname_src,
6493                         struct smb_filename *smb_fname_dst,
6494                         int ofun,
6495                         int count,
6496                         bool target_is_directory)
6497 {
6498         struct smb_filename *smb_fname_dst_tmp = NULL;
6499         SMB_OFF_T ret=-1;
6500         files_struct *fsp1,*fsp2;
6501         uint32 dosattrs;
6502         uint32 new_create_disposition;
6503         NTSTATUS status;
6504
6505
6506         status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6507         if (!NT_STATUS_IS_OK(status)) {
6508                 return status;
6509         }
6510
6511         /*
6512          * If the target is a directory, extract the last component from the
6513          * src filename and append it to the dst filename
6514          */
6515         if (target_is_directory) {
6516                 const char *p;
6517
6518                 /* dest/target can't be a stream if it's a directory. */
6519                 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6520
6521                 p = strrchr_m(smb_fname_src->base_name,'/');
6522                 if (p) {
6523                         p++;
6524                 } else {
6525                         p = smb_fname_src->base_name;
6526                 }
6527                 smb_fname_dst_tmp->base_name =
6528                     talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6529                                            p);
6530                 if (!smb_fname_dst_tmp->base_name) {
6531                         status = NT_STATUS_NO_MEMORY;
6532                         goto out;
6533                 }
6534         }
6535
6536         status = vfs_file_exist(conn, smb_fname_src);
6537         if (!NT_STATUS_IS_OK(status)) {
6538                 goto out;
6539         }
6540
6541         if (!target_is_directory && count) {
6542                 new_create_disposition = FILE_OPEN;
6543         } else {
6544                 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
6545                                                  NULL, NULL,
6546                                                  &new_create_disposition,
6547                                                  NULL,
6548                                                  NULL)) {
6549                         status = NT_STATUS_INVALID_PARAMETER;
6550                         goto out;
6551                 }
6552         }
6553
6554         /* Open the src file for reading. */
6555         status = SMB_VFS_CREATE_FILE(
6556                 conn,                                   /* conn */
6557                 NULL,                                   /* req */
6558                 0,                                      /* root_dir_fid */
6559                 smb_fname_src,                          /* fname */
6560                 FILE_GENERIC_READ,                      /* access_mask */
6561                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
6562                 FILE_OPEN,                              /* create_disposition*/
6563                 0,                                      /* create_options */
6564                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
6565                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
6566                 0,                                      /* allocation_size */
6567                 0,                                      /* private_flags */
6568                 NULL,                                   /* sd */
6569                 NULL,                                   /* ea_list */
6570                 &fsp1,                                  /* result */
6571                 NULL);                                  /* psbuf */
6572
6573         if (!NT_STATUS_IS_OK(status)) {
6574                 goto out;
6575         }
6576
6577         dosattrs = dos_mode(conn, smb_fname_src);
6578
6579         if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6580                 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6581         }
6582
6583         /* Open the dst file for writing. */
6584         status = SMB_VFS_CREATE_FILE(
6585                 conn,                                   /* conn */
6586                 NULL,                                   /* req */
6587                 0,                                      /* root_dir_fid */
6588                 smb_fname_dst,                          /* fname */
6589                 FILE_GENERIC_WRITE,                     /* access_mask */
6590                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
6591                 new_create_disposition,                 /* create_disposition*/
6592                 0,                                      /* create_options */
6593                 dosattrs,                               /* file_attributes */
6594                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
6595                 0,                                      /* allocation_size */
6596                 0,                                      /* private_flags */
6597                 NULL,                                   /* sd */
6598                 NULL,                                   /* ea_list */
6599                 &fsp2,                                  /* result */
6600                 NULL);                                  /* psbuf */
6601
6602         if (!NT_STATUS_IS_OK(status)) {
6603                 close_file(NULL, fsp1, ERROR_CLOSE);
6604                 goto out;
6605         }
6606
6607         if ((ofun&3) == 1) {
6608                 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6609                         DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6610                         /*
6611                          * Stop the copy from occurring.
6612                          */
6613                         ret = -1;
6614                         smb_fname_src->st.st_ex_size = 0;
6615                 }
6616         }
6617
6618         /* Do the actual copy. */
6619         if (smb_fname_src->st.st_ex_size) {
6620                 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6621         }
6622
6623         close_file(NULL, fsp1, NORMAL_CLOSE);
6624
6625         /* Ensure the modtime is set correctly on the destination file. */
6626         set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6627
6628         /*
6629          * As we are opening fsp1 read-only we only expect
6630          * an error on close on fsp2 if we are out of space.
6631          * Thus we don't look at the error return from the
6632          * close of fsp1.
6633          */
6634         status = close_file(NULL, fsp2, NORMAL_CLOSE);
6635
6636         if (!NT_STATUS_IS_OK(status)) {
6637                 goto out;
6638         }
6639
6640         if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6641                 status = NT_STATUS_DISK_FULL;
6642                 goto out;
6643         }
6644
6645         status = NT_STATUS_OK;
6646
6647  out:
6648         TALLOC_FREE(smb_fname_dst_tmp);
6649         return status;
6650 }
6651
6652 /****************************************************************************
6653  Reply to a file copy.
6654 ****************************************************************************/
6655
6656 void reply_copy(struct smb_request *req)
6657 {
6658         connection_struct *conn = req->conn;
6659         struct smb_filename *smb_fname_src = NULL;
6660         struct smb_filename *smb_fname_dst = NULL;
6661         char *fname_src = NULL;
6662         char *fname_dst = NULL;
6663         char *fname_src_mask = NULL;
6664         char *fname_src_dir = NULL;
6665         const char *p;
6666         int count=0;
6667         int error = ERRnoaccess;
6668         int tid2;
6669         int ofun;
6670         int flags;
6671         bool target_is_directory=False;
6672         bool source_has_wild = False;
6673         bool dest_has_wild = False;
6674         NTSTATUS status;
6675         TALLOC_CTX *ctx = talloc_tos();
6676
6677         START_PROFILE(SMBcopy);
6678
6679         if (req->wct < 3) {
6680                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6681                 goto out;
6682         }
6683
6684         tid2 = SVAL(req->vwv+0, 0);
6685         ofun = SVAL(req->vwv+1, 0);
6686         flags = SVAL(req->vwv+2, 0);
6687
6688         p = (const char *)req->buf;
6689         p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6690                                        &status, &source_has_wild);
6691         if (!NT_STATUS_IS_OK(status)) {
6692                 reply_nterror(req, status);
6693                 goto out;
6694         }
6695         p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6696                                        &status, &dest_has_wild);
6697         if (!NT_STATUS_IS_OK(status)) {
6698                 reply_nterror(req, status);
6699                 goto out;
6700         }
6701
6702         DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6703
6704         if (tid2 != conn->cnum) {
6705                 /* can't currently handle inter share copies XXXX */
6706                 DEBUG(3,("Rejecting inter-share copy\n"));
6707                 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6708                 goto out;
6709         }
6710
6711         status = filename_convert(ctx, conn,
6712                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6713                                   fname_src,
6714                                   UCF_COND_ALLOW_WCARD_LCOMP,
6715                                   &source_has_wild,
6716                                   &smb_fname_src);
6717         if (!NT_STATUS_IS_OK(status)) {
6718                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6719                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6720                                         ERRSRV, ERRbadpath);
6721                         goto out;
6722                 }
6723                 reply_nterror(req, status);
6724                 goto out;
6725         }
6726
6727         status = filename_convert(ctx, conn,
6728                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6729                                   fname_dst,
6730                                   UCF_COND_ALLOW_WCARD_LCOMP,
6731                                   &dest_has_wild,
6732                                   &smb_fname_dst);
6733         if (!NT_STATUS_IS_OK(status)) {
6734                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6735                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6736                                         ERRSRV, ERRbadpath);
6737                         goto out;
6738                 }
6739                 reply_nterror(req, status);
6740                 goto out;
6741         }
6742
6743         target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6744
6745         if ((flags&1) && target_is_directory) {
6746                 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6747                 goto out;
6748         }
6749
6750         if ((flags&2) && !target_is_directory) {
6751                 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
6752                 goto out;
6753         }
6754
6755         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6756                 /* wants a tree copy! XXXX */
6757                 DEBUG(3,("Rejecting tree copy\n"));
6758                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6759                 goto out;
6760         }
6761
6762         /* Split up the directory from the filename/mask. */
6763         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6764                                       &fname_src_dir, &fname_src_mask);
6765         if (!NT_STATUS_IS_OK(status)) {
6766                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6767                 goto out;
6768         }
6769
6770         /*
6771          * We should only check the mangled cache
6772          * here if unix_convert failed. This means
6773          * that the path in 'mask' doesn't exist
6774          * on the file system and so we need to look
6775          * for a possible mangle. This patch from
6776          * Tine Smukavec <valentin.smukavec@hermes.si>.
6777          */
6778         if (!VALID_STAT(smb_fname_src->st) &&
6779             mangle_is_mangled(fname_src_mask, conn->params)) {
6780                 char *new_mask = NULL;
6781                 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6782                                             &new_mask, conn->params);
6783
6784                 /* Use demangled name if one was successfully found. */
6785                 if (new_mask) {
6786                         TALLOC_FREE(fname_src_mask);
6787                         fname_src_mask = new_mask;
6788                 }
6789         }
6790
6791         if (!source_has_wild) {
6792
6793                 /*
6794                  * Only one file needs to be copied. Append the mask back onto
6795                  * the directory.
6796                  */
6797                 TALLOC_FREE(smb_fname_src->base_name);
6798                 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6799                                                            "%s/%s",
6800                                                            fname_src_dir,
6801                                                            fname_src_mask);
6802                 if (!smb_fname_src->base_name) {
6803                         reply_nterror(req, NT_STATUS_NO_MEMORY);
6804                         goto out;
6805                 }
6806
6807                 if (dest_has_wild) {
6808                         char *fname_dst_mod = NULL;
6809                         if (!resolve_wildcards(smb_fname_dst,
6810                                                smb_fname_src->base_name,
6811                                                smb_fname_dst->base_name,
6812                                                &fname_dst_mod)) {
6813                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6814                                 goto out;
6815                         }
6816                         TALLOC_FREE(smb_fname_dst->base_name);
6817                         smb_fname_dst->base_name = fname_dst_mod;
6818                 }
6819
6820                 status = check_name(conn, smb_fname_src->base_name);
6821                 if (!NT_STATUS_IS_OK(status)) {
6822                         reply_nterror(req, status);
6823                         goto out;
6824                 }
6825
6826                 status = check_name(conn, smb_fname_dst->base_name);
6827                 if (!NT_STATUS_IS_OK(status)) {
6828                         reply_nterror(req, status);
6829                         goto out;
6830                 }
6831
6832                 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
6833                                    ofun, count, target_is_directory);
6834
6835                 if(!NT_STATUS_IS_OK(status)) {
6836                         reply_nterror(req, status);
6837                         goto out;
6838                 } else {
6839                         count++;
6840                 }
6841         } else {
6842                 struct smb_Dir *dir_hnd = NULL;
6843                 const char *dname = NULL;
6844                 char *talloced = NULL;
6845                 long offset = 0;
6846
6847                 /*
6848                  * There is a wildcard that requires us to actually read the
6849                  * src dir and copy each file matching the mask to the dst.
6850                  * Right now streams won't be copied, but this could
6851                  * presumably be added with a nested loop for reach dir entry.
6852                  */
6853                 SMB_ASSERT(!smb_fname_src->stream_name);
6854                 SMB_ASSERT(!smb_fname_dst->stream_name);
6855
6856                 smb_fname_src->stream_name = NULL;
6857                 smb_fname_dst->stream_name = NULL;
6858
6859                 if (strequal(fname_src_mask,"????????.???")) {
6860                         TALLOC_FREE(fname_src_mask);
6861                         fname_src_mask = talloc_strdup(ctx, "*");
6862                         if (!fname_src_mask) {
6863                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6864                                 goto out;
6865                         }
6866                 }
6867
6868                 status = check_name(conn, fname_src_dir);
6869                 if (!NT_STATUS_IS_OK(status)) {
6870                         reply_nterror(req, status);
6871                         goto out;
6872                 }
6873
6874                 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
6875                 if (dir_hnd == NULL) {
6876                         status = map_nt_error_from_unix(errno);
6877                         reply_nterror(req, status);
6878                         goto out;
6879                 }
6880
6881                 error = ERRbadfile;
6882
6883                 /* Iterate over the src dir copying each entry to the dst. */
6884                 while ((dname = ReadDirName(dir_hnd, &offset,
6885                                             &smb_fname_src->st, &talloced))) {
6886                         char *destname = NULL;
6887
6888                         if (ISDOT(dname) || ISDOTDOT(dname)) {
6889                                 TALLOC_FREE(talloced);
6890                                 continue;
6891                         }
6892
6893                         if (!is_visible_file(conn, fname_src_dir, dname,
6894                                              &smb_fname_src->st, false)) {
6895                                 TALLOC_FREE(talloced);
6896                                 continue;
6897                         }
6898
6899                         if(!mask_match(dname, fname_src_mask,
6900                                        conn->case_sensitive)) {
6901                                 TALLOC_FREE(talloced);
6902                                 continue;
6903                         }
6904
6905                         error = ERRnoaccess;
6906
6907                         /* Get the src smb_fname struct setup. */
6908                         TALLOC_FREE(smb_fname_src->base_name);
6909                         smb_fname_src->base_name =
6910                             talloc_asprintf(smb_fname_src, "%s/%s",
6911                                             fname_src_dir, dname);
6912
6913                         if (!smb_fname_src->base_name) {
6914                                 TALLOC_FREE(dir_hnd);
6915                                 TALLOC_FREE(talloced);
6916                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6917                                 goto out;
6918                         }
6919
6920                         if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6921                                                smb_fname_dst->base_name,
6922                                                &destname)) {
6923                                 TALLOC_FREE(talloced);
6924                                 continue;
6925                         }
6926                         if (!destname) {
6927                                 TALLOC_FREE(dir_hnd);
6928                                 TALLOC_FREE(talloced);
6929                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6930                                 goto out;
6931                         }
6932
6933                         TALLOC_FREE(smb_fname_dst->base_name);
6934                         smb_fname_dst->base_name = destname;
6935
6936                         status = check_name(conn, smb_fname_src->base_name);
6937                         if (!NT_STATUS_IS_OK(status)) {
6938                                 TALLOC_FREE(dir_hnd);
6939                                 TALLOC_FREE(talloced);
6940                                 reply_nterror(req, status);
6941                                 goto out;
6942                         }
6943
6944                         status = check_name(conn, smb_fname_dst->base_name);
6945                         if (!NT_STATUS_IS_OK(status)) {
6946                                 TALLOC_FREE(dir_hnd);
6947                                 TALLOC_FREE(talloced);
6948                                 reply_nterror(req, status);
6949                                 goto out;
6950                         }
6951
6952                         DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
6953                                 smb_fname_src->base_name,
6954                                 smb_fname_dst->base_name));
6955
6956                         status = copy_file(ctx, conn, smb_fname_src,
6957                                            smb_fname_dst, ofun, count,
6958                                            target_is_directory);
6959                         if (NT_STATUS_IS_OK(status)) {
6960                                 count++;
6961                         }
6962
6963                         TALLOC_FREE(talloced);
6964                 }
6965                 TALLOC_FREE(dir_hnd);
6966         }
6967
6968         if (count == 0) {
6969                 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
6970                 goto out;
6971         }
6972
6973         reply_outbuf(req, 1, 0);
6974         SSVAL(req->outbuf,smb_vwv0,count);
6975  out:
6976         TALLOC_FREE(smb_fname_src);
6977         TALLOC_FREE(smb_fname_dst);
6978         TALLOC_FREE(fname_src);
6979         TALLOC_FREE(fname_dst);
6980         TALLOC_FREE(fname_src_mask);
6981         TALLOC_FREE(fname_src_dir);
6982
6983         END_PROFILE(SMBcopy);
6984         return;
6985 }
6986
6987 #undef DBGC_CLASS
6988 #define DBGC_CLASS DBGC_LOCKING
6989
6990 /****************************************************************************
6991  Get a lock pid, dealing with large count requests.
6992 ****************************************************************************/
6993
6994 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
6995                     bool large_file_format)
6996 {
6997         if(!large_file_format)
6998                 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
6999         else
7000                 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7001 }
7002
7003 /****************************************************************************
7004  Get a lock count, dealing with large count requests.
7005 ****************************************************************************/
7006
7007 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7008                         bool large_file_format)
7009 {
7010         uint64_t count = 0;
7011
7012         if(!large_file_format) {
7013                 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7014         } else {
7015
7016 #if defined(HAVE_LONGLONG)
7017                 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7018                         ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7019 #else /* HAVE_LONGLONG */
7020
7021                 /*
7022                  * NT4.x seems to be broken in that it sends large file (64 bit)
7023                  * lockingX calls even if the CAP_LARGE_FILES was *not*
7024                  * negotiated. For boxes without large unsigned ints truncate the
7025                  * lock count by dropping the top 32 bits.
7026                  */
7027
7028                 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7029                         DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7030                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7031                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7032                                 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7033                 }
7034
7035                 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7036 #endif /* HAVE_LONGLONG */
7037         }
7038
7039         return count;
7040 }
7041
7042 #if !defined(HAVE_LONGLONG)
7043 /****************************************************************************
7044  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7045 ****************************************************************************/
7046
7047 static uint32 map_lock_offset(uint32 high, uint32 low)
7048 {
7049         unsigned int i;
7050         uint32 mask = 0;
7051         uint32 highcopy = high;
7052
7053         /*
7054          * Try and find out how many significant bits there are in high.
7055          */
7056
7057         for(i = 0; highcopy; i++)
7058                 highcopy >>= 1;
7059
7060         /*
7061          * We use 31 bits not 32 here as POSIX
7062          * lock offsets may not be negative.
7063          */
7064
7065         mask = (~0) << (31 - i);
7066
7067         if(low & mask)
7068                 return 0; /* Fail. */
7069
7070         high <<= (31 - i);
7071
7072         return (high|low);
7073 }
7074 #endif /* !defined(HAVE_LONGLONG) */
7075
7076 /****************************************************************************
7077  Get a lock offset, dealing with large offset requests.
7078 ****************************************************************************/
7079
7080 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7081                          bool large_file_format, bool *err)
7082 {
7083         uint64_t offset = 0;
7084
7085         *err = False;
7086
7087         if(!large_file_format) {
7088                 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7089         } else {
7090
7091 #if defined(HAVE_LONGLONG)
7092                 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7093                                 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7094 #else /* HAVE_LONGLONG */
7095
7096                 /*
7097                  * NT4.x seems to be broken in that it sends large file (64 bit)
7098                  * lockingX calls even if the CAP_LARGE_FILES was *not*
7099                  * negotiated. For boxes without large unsigned ints mangle the
7100                  * lock offset by mapping the top 32 bits onto the lower 32.
7101                  */
7102
7103                 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7104                         uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7105                         uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7106                         uint32 new_low = 0;
7107
7108                         if((new_low = map_lock_offset(high, low)) == 0) {
7109                                 *err = True;
7110                                 return (uint64_t)-1;
7111                         }
7112
7113                         DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7114                                 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7115                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7116                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7117                 }
7118
7119                 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7120 #endif /* HAVE_LONGLONG */
7121         }
7122
7123         return offset;
7124 }
7125
7126 NTSTATUS smbd_do_locking(struct smb_request *req,
7127                          files_struct *fsp,
7128                          uint8_t type,
7129                          int32_t timeout,
7130                          uint16_t num_ulocks,
7131                          struct smbd_lock_element *ulocks,
7132                          uint16_t num_locks,
7133                          struct smbd_lock_element *locks,
7134                          bool *async)
7135 {
7136         connection_struct *conn = req->conn;
7137         int i;
7138         NTSTATUS status = NT_STATUS_OK;
7139
7140         *async = false;
7141
7142         /* Data now points at the beginning of the list
7143            of smb_unlkrng structs */
7144         for(i = 0; i < (int)num_ulocks; i++) {
7145                 struct smbd_lock_element *e = &ulocks[i];
7146
7147                 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7148                           "pid %u, file %s\n",
7149                           (double)e->offset,
7150                           (double)e->count,
7151                           (unsigned int)e->smblctx,
7152                           fsp_str_dbg(fsp)));
7153
7154                 if (e->brltype != UNLOCK_LOCK) {
7155                         /* this can only happen with SMB2 */
7156                         return NT_STATUS_INVALID_PARAMETER;
7157                 }
7158
7159                 status = do_unlock(req->sconn->msg_ctx,
7160                                 fsp,
7161                                 e->smblctx,
7162                                 e->count,
7163                                 e->offset,
7164                                 WINDOWS_LOCK);
7165
7166                 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7167                     nt_errstr(status)));
7168
7169                 if (!NT_STATUS_IS_OK(status)) {
7170                         return status;
7171                 }
7172         }
7173
7174         /* Setup the timeout in seconds. */
7175
7176         if (!lp_blocking_locks(SNUM(conn))) {
7177                 timeout = 0;
7178         }
7179
7180         /* Data now points at the beginning of the list
7181            of smb_lkrng structs */
7182
7183         for(i = 0; i < (int)num_locks; i++) {
7184                 struct smbd_lock_element *e = &locks[i];
7185
7186                 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7187                           "%llu, file %s timeout = %d\n",
7188                           (double)e->offset,
7189                           (double)e->count,
7190                           (unsigned long long)e->smblctx,
7191                           fsp_str_dbg(fsp),
7192                           (int)timeout));
7193
7194                 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7195                         struct blocking_lock_record *blr = NULL;
7196
7197                         if (num_locks > 1) {
7198                                 /*
7199                                  * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7200                                  * if the lock vector contains one entry. When given mutliple cancel
7201                                  * requests in a single PDU we expect the server to return an
7202                                  * error. Windows servers seem to accept the request but only
7203                                  * cancel the first lock.
7204                                  * JRA - Do what Windows does (tm) :-).
7205                                  */
7206
7207 #if 0
7208                                 /* MS-CIFS (2.2.4.32.1) behavior. */
7209                                 return NT_STATUS_DOS(ERRDOS,
7210                                                 ERRcancelviolation);
7211 #else
7212                                 /* Windows behavior. */
7213                                 if (i != 0) {
7214                                         DEBUG(10,("smbd_do_locking: ignoring subsequent "
7215                                                 "cancel request\n"));
7216                                         continue;
7217                                 }
7218 #endif
7219                         }
7220
7221                         if (lp_blocking_locks(SNUM(conn))) {
7222
7223                                 /* Schedule a message to ourselves to
7224                                    remove the blocking lock record and
7225                                    return the right error. */
7226
7227                                 blr = blocking_lock_cancel_smb1(fsp,
7228                                                 e->smblctx,
7229                                                 e->offset,
7230                                                 e->count,
7231                                                 WINDOWS_LOCK,
7232                                                 type,
7233                                                 NT_STATUS_FILE_LOCK_CONFLICT);
7234                                 if (blr == NULL) {
7235                                         return NT_STATUS_DOS(
7236                                                         ERRDOS,
7237                                                         ERRcancelviolation);
7238                                 }
7239                         }
7240                         /* Remove a matching pending lock. */
7241                         status = do_lock_cancel(fsp,
7242                                                 e->smblctx,
7243                                                 e->count,
7244                                                 e->offset,
7245                                                 WINDOWS_LOCK,
7246                                                 blr);
7247                 } else {
7248                         bool blocking_lock = timeout ? true : false;
7249                         bool defer_lock = false;
7250                         struct byte_range_lock *br_lck;
7251                         uint64_t block_smblctx;
7252
7253                         br_lck = do_lock(req->sconn->msg_ctx,
7254                                         fsp,
7255                                         e->smblctx,
7256                                         e->count,
7257                                         e->offset, 
7258                                         e->brltype,
7259                                         WINDOWS_LOCK,
7260                                         blocking_lock,
7261                                         &status,
7262                                         &block_smblctx,
7263                                         NULL);
7264
7265                         if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7266                                 /* Windows internal resolution for blocking locks seems
7267                                    to be about 200ms... Don't wait for less than that. JRA. */
7268                                 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7269                                         timeout = lp_lock_spin_time();
7270                                 }
7271                                 defer_lock = true;
7272                         }
7273
7274                         /* If a lock sent with timeout of zero would fail, and
7275                          * this lock has been requested multiple times,
7276                          * according to brl_lock_failed() we convert this
7277                          * request to a blocking lock with a timeout of between
7278                          * 150 - 300 milliseconds.
7279                          *
7280                          * If lp_lock_spin_time() has been set to 0, we skip
7281                          * this blocking retry and fail immediately.
7282                          *
7283                          * Replacement for do_lock_spin(). JRA. */
7284
7285                         if (!req->sconn->using_smb2 &&
7286                             br_lck && lp_blocking_locks(SNUM(conn)) &&
7287                             lp_lock_spin_time() && !blocking_lock &&
7288                             NT_STATUS_EQUAL((status),
7289                                 NT_STATUS_FILE_LOCK_CONFLICT))
7290                         {
7291                                 defer_lock = true;
7292                                 timeout = lp_lock_spin_time();
7293                         }
7294
7295                         if (br_lck && defer_lock) {
7296                                 /*
7297                                  * A blocking lock was requested. Package up
7298                                  * this smb into a queued request and push it
7299                                  * onto the blocking lock queue.
7300                                  */
7301                                 if(push_blocking_lock_request(br_lck,
7302                                                         req,
7303                                                         fsp,
7304                                                         timeout,
7305                                                         i,
7306                                                         e->smblctx,
7307                                                         e->brltype,
7308                                                         WINDOWS_LOCK,
7309                                                         e->offset,
7310                                                         e->count,
7311                                                         block_smblctx)) {
7312                                         TALLOC_FREE(br_lck);
7313                                         *async = true;
7314                                         return NT_STATUS_OK;
7315                                 }
7316                         }
7317
7318                         TALLOC_FREE(br_lck);
7319                 }
7320
7321                 if (!NT_STATUS_IS_OK(status)) {
7322                         break;
7323                 }
7324         }
7325
7326         /* If any of the above locks failed, then we must unlock
7327            all of the previous locks (X/Open spec). */
7328
7329         if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7330
7331                 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7332                         i = -1; /* we want to skip the for loop */
7333                 }
7334
7335                 /*
7336                  * Ensure we don't do a remove on the lock that just failed,
7337                  * as under POSIX rules, if we have a lock already there, we
7338                  * will delete it (and we shouldn't) .....
7339                  */
7340                 for(i--; i >= 0; i--) {
7341                         struct smbd_lock_element *e = &locks[i];
7342
7343                         do_unlock(req->sconn->msg_ctx,
7344                                 fsp,
7345                                 e->smblctx,
7346                                 e->count,
7347                                 e->offset,
7348                                 WINDOWS_LOCK);
7349                 }
7350                 return status;
7351         }
7352
7353         DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7354                   fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7355
7356         return NT_STATUS_OK;
7357 }
7358
7359 /****************************************************************************
7360  Reply to a lockingX request.
7361 ****************************************************************************/
7362
7363 void reply_lockingX(struct smb_request *req)
7364 {
7365         connection_struct *conn = req->conn;
7366         files_struct *fsp;
7367         unsigned char locktype;
7368         unsigned char oplocklevel;
7369         uint16 num_ulocks;
7370         uint16 num_locks;
7371         int32 lock_timeout;
7372         int i;
7373         const uint8_t *data;
7374         bool large_file_format;
7375         bool err;
7376         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7377         struct smbd_lock_element *ulocks;
7378         struct smbd_lock_element *locks;
7379         bool async = false;
7380
7381         START_PROFILE(SMBlockingX);
7382
7383         if (req->wct < 8) {
7384                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7385                 END_PROFILE(SMBlockingX);
7386                 return;
7387         }
7388
7389         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7390         locktype = CVAL(req->vwv+3, 0);
7391         oplocklevel = CVAL(req->vwv+3, 1);
7392         num_ulocks = SVAL(req->vwv+6, 0);
7393         num_locks = SVAL(req->vwv+7, 0);
7394         lock_timeout = IVAL(req->vwv+4, 0);
7395         large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7396
7397         if (!check_fsp(conn, req, fsp)) {
7398                 END_PROFILE(SMBlockingX);
7399                 return;
7400         }
7401
7402         data = req->buf;
7403
7404         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7405                 /* we don't support these - and CANCEL_LOCK makes w2k
7406                    and XP reboot so I don't really want to be
7407                    compatible! (tridge) */
7408                 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7409                 END_PROFILE(SMBlockingX);
7410                 return;
7411         }
7412
7413         /* Check if this is an oplock break on a file
7414            we have granted an oplock on.
7415         */
7416         if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7417                 /* Client can insist on breaking to none. */
7418                 bool break_to_none = (oplocklevel == 0);
7419                 bool result;
7420
7421                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7422                          "for fnum = %d\n", (unsigned int)oplocklevel,
7423                          fsp->fnum ));
7424
7425                 /*
7426                  * Make sure we have granted an exclusive or batch oplock on
7427                  * this file.
7428                  */
7429
7430                 if (fsp->oplock_type == 0) {
7431
7432                         /* The Samba4 nbench simulator doesn't understand
7433                            the difference between break to level2 and break
7434                            to none from level2 - it sends oplock break
7435                            replies in both cases. Don't keep logging an error
7436                            message here - just ignore it. JRA. */
7437
7438                         DEBUG(5,("reply_lockingX: Error : oplock break from "
7439                                  "client for fnum = %d (oplock=%d) and no "
7440                                  "oplock granted on this file (%s).\n",
7441                                  fsp->fnum, fsp->oplock_type,
7442                                  fsp_str_dbg(fsp)));
7443
7444                         /* if this is a pure oplock break request then don't
7445                          * send a reply */
7446                         if (num_locks == 0 && num_ulocks == 0) {
7447                                 END_PROFILE(SMBlockingX);
7448                                 return;
7449                         } else {
7450                                 END_PROFILE(SMBlockingX);
7451                                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7452                                 return;
7453                         }
7454                 }
7455
7456                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7457                     (break_to_none)) {
7458                         result = remove_oplock(fsp);
7459                 } else {
7460                         result = downgrade_oplock(fsp);
7461                 }
7462
7463                 if (!result) {
7464                         DEBUG(0, ("reply_lockingX: error in removing "
7465                                   "oplock on file %s\n", fsp_str_dbg(fsp)));
7466                         /* Hmmm. Is this panic justified? */
7467                         smb_panic("internal tdb error");
7468                 }
7469
7470                 reply_to_oplock_break_requests(fsp);
7471
7472                 /* if this is a pure oplock break request then don't send a
7473                  * reply */
7474                 if (num_locks == 0 && num_ulocks == 0) {
7475                         /* Sanity check - ensure a pure oplock break is not a
7476                            chained request. */
7477                         if(CVAL(req->vwv+0, 0) != 0xff)
7478                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
7479                                          "break is a chained %d request !\n",
7480                                          (unsigned int)CVAL(req->vwv+0, 0)));
7481                         END_PROFILE(SMBlockingX);
7482                         return;
7483                 }
7484         }
7485
7486         if (req->buflen <
7487             (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7488                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7489                 END_PROFILE(SMBlockingX);
7490                 return;
7491         }
7492
7493         ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7494         if (ulocks == NULL) {
7495                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7496                 END_PROFILE(SMBlockingX);
7497                 return;
7498         }
7499
7500         locks = talloc_array(req, struct smbd_lock_element, num_locks);
7501         if (locks == NULL) {
7502                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7503                 END_PROFILE(SMBlockingX);
7504                 return;
7505         }
7506
7507         /* Data now points at the beginning of the list
7508            of smb_unlkrng structs */
7509         for(i = 0; i < (int)num_ulocks; i++) {
7510                 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7511                 ulocks[i].count = get_lock_count(data, i, large_file_format);
7512                 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7513                 ulocks[i].brltype = UNLOCK_LOCK;
7514
7515                 /*
7516                  * There is no error code marked "stupid client bug".... :-).
7517                  */
7518                 if(err) {
7519                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7520                         END_PROFILE(SMBlockingX);
7521                         return;
7522                 }
7523         }
7524
7525         /* Now do any requested locks */
7526         data += ((large_file_format ? 20 : 10)*num_ulocks);
7527
7528         /* Data now points at the beginning of the list
7529            of smb_lkrng structs */
7530
7531         for(i = 0; i < (int)num_locks; i++) {
7532                 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7533                 locks[i].count = get_lock_count(data, i, large_file_format);
7534                 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7535
7536                 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7537                         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7538                                 locks[i].brltype = PENDING_READ_LOCK;
7539                         } else {
7540                                 locks[i].brltype = READ_LOCK;
7541                         }
7542                 } else {
7543                         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7544                                 locks[i].brltype = PENDING_WRITE_LOCK;
7545                         } else {
7546                                 locks[i].brltype = WRITE_LOCK;
7547                         }
7548                 }
7549
7550                 /*
7551                  * There is no error code marked "stupid client bug".... :-).
7552                  */
7553                 if(err) {
7554                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7555                         END_PROFILE(SMBlockingX);
7556                         return;
7557                 }
7558         }
7559
7560         status = smbd_do_locking(req, fsp,
7561                                  locktype, lock_timeout,
7562                                  num_ulocks, ulocks,
7563                                  num_locks, locks,
7564                                  &async);
7565         if (!NT_STATUS_IS_OK(status)) {
7566                 END_PROFILE(SMBlockingX);
7567                 reply_nterror(req, status);
7568                 return;
7569         }
7570         if (async) {
7571                 END_PROFILE(SMBlockingX);
7572                 return;
7573         }
7574
7575         reply_outbuf(req, 2, 0);
7576
7577         DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7578                   fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7579
7580         END_PROFILE(SMBlockingX);
7581         chain_reply(req);
7582 }
7583
7584 #undef DBGC_CLASS
7585 #define DBGC_CLASS DBGC_ALL
7586
7587 /****************************************************************************
7588  Reply to a SMBreadbmpx (read block multiplex) request.
7589  Always reply with an error, if someone has a platform really needs this,
7590  please contact vl@samba.org
7591 ****************************************************************************/
7592
7593 void reply_readbmpx(struct smb_request *req)
7594 {
7595         START_PROFILE(SMBreadBmpx);
7596         reply_force_doserror(req, ERRSRV, ERRuseSTD);
7597         END_PROFILE(SMBreadBmpx);
7598         return;
7599 }
7600
7601 /****************************************************************************
7602  Reply to a SMBreadbs (read block multiplex secondary) request.
7603  Always reply with an error, if someone has a platform really needs this,
7604  please contact vl@samba.org
7605 ****************************************************************************/
7606
7607 void reply_readbs(struct smb_request *req)
7608 {
7609         START_PROFILE(SMBreadBs);
7610         reply_force_doserror(req, ERRSRV, ERRuseSTD);
7611         END_PROFILE(SMBreadBs);
7612         return;
7613 }
7614
7615 /****************************************************************************
7616  Reply to a SMBsetattrE.
7617 ****************************************************************************/
7618
7619 void reply_setattrE(struct smb_request *req)
7620 {
7621         connection_struct *conn = req->conn;
7622         struct smb_file_time ft;
7623         files_struct *fsp;
7624         NTSTATUS status;
7625
7626         START_PROFILE(SMBsetattrE);
7627         ZERO_STRUCT(ft);
7628
7629         if (req->wct < 7) {
7630                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7631                 goto out;
7632         }
7633
7634         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7635
7636         if(!fsp || (fsp->conn != conn)) {
7637                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7638                 goto out;
7639         }
7640
7641         /*
7642          * Convert the DOS times into unix times.
7643          */
7644
7645         ft.atime = convert_time_t_to_timespec(
7646             srv_make_unix_date2(req->vwv+3));
7647         ft.mtime = convert_time_t_to_timespec(
7648             srv_make_unix_date2(req->vwv+5));
7649         ft.create_time = convert_time_t_to_timespec(
7650             srv_make_unix_date2(req->vwv+1));
7651
7652         reply_outbuf(req, 0, 0);
7653
7654         /* 
7655          * Patch from Ray Frush <frush@engr.colostate.edu>
7656          * Sometimes times are sent as zero - ignore them.
7657          */
7658
7659         /* Ensure we have a valid stat struct for the source. */
7660         status = vfs_stat_fsp(fsp);
7661         if (!NT_STATUS_IS_OK(status)) {
7662                 reply_nterror(req, status);
7663                 goto out;
7664         }
7665
7666         status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7667         if (!NT_STATUS_IS_OK(status)) {
7668                 reply_nterror(req, status);
7669                 goto out;
7670         }
7671
7672         DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7673                " createtime=%u\n",
7674                 fsp->fnum,
7675                 (unsigned int)ft.atime.tv_sec,
7676                 (unsigned int)ft.mtime.tv_sec,
7677                 (unsigned int)ft.create_time.tv_sec
7678                 ));
7679  out:
7680         END_PROFILE(SMBsetattrE);
7681         return;
7682 }
7683
7684
7685 /* Back from the dead for OS/2..... JRA. */
7686
7687 /****************************************************************************
7688  Reply to a SMBwritebmpx (write block multiplex primary) request.
7689  Always reply with an error, if someone has a platform really needs this,
7690  please contact vl@samba.org
7691 ****************************************************************************/
7692
7693 void reply_writebmpx(struct smb_request *req)
7694 {
7695         START_PROFILE(SMBwriteBmpx);
7696         reply_force_doserror(req, ERRSRV, ERRuseSTD);
7697         END_PROFILE(SMBwriteBmpx);
7698         return;
7699 }
7700
7701 /****************************************************************************
7702  Reply to a SMBwritebs (write block multiplex secondary) request.
7703  Always reply with an error, if someone has a platform really needs this,
7704  please contact vl@samba.org
7705 ****************************************************************************/
7706
7707 void reply_writebs(struct smb_request *req)
7708 {
7709         START_PROFILE(SMBwriteBs);
7710         reply_force_doserror(req, ERRSRV, ERRuseSTD);
7711         END_PROFILE(SMBwriteBs);
7712         return;
7713 }
7714
7715 /****************************************************************************
7716  Reply to a SMBgetattrE.
7717 ****************************************************************************/
7718
7719 void reply_getattrE(struct smb_request *req)
7720 {
7721         connection_struct *conn = req->conn;
7722         int mode;
7723         files_struct *fsp;
7724         struct timespec create_ts;
7725
7726         START_PROFILE(SMBgetattrE);
7727
7728         if (req->wct < 1) {
7729                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7730                 END_PROFILE(SMBgetattrE);
7731                 return;
7732         }
7733
7734         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7735
7736         if(!fsp || (fsp->conn != conn)) {
7737                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7738                 END_PROFILE(SMBgetattrE);
7739                 return;
7740         }
7741
7742         /* Do an fstat on this file */
7743         if(fsp_stat(fsp)) {
7744                 reply_nterror(req, map_nt_error_from_unix(errno));
7745                 END_PROFILE(SMBgetattrE);
7746                 return;
7747         }
7748
7749         mode = dos_mode(conn, fsp->fsp_name);
7750
7751         /*
7752          * Convert the times into dos times. Set create
7753          * date to be last modify date as UNIX doesn't save
7754          * this.
7755          */
7756
7757         reply_outbuf(req, 11, 0);
7758
7759         create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7760         srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7761         srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7762                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7763         /* Should we check pending modtime here ? JRA */
7764         srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7765                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7766
7767         if (mode & aDIR) {
7768                 SIVAL(req->outbuf, smb_vwv6, 0);
7769                 SIVAL(req->outbuf, smb_vwv8, 0);
7770         } else {
7771                 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7772                 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
7773                 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7774         }
7775         SSVAL(req->outbuf,smb_vwv10, mode);
7776
7777         DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7778
7779         END_PROFILE(SMBgetattrE);
7780         return;
7781 }