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