Add tiny tldap test
[Samba/gebeck_regimport.git] / source3 / smbd / reply.c
blob9544b845da5b0998a4993a2b892484dd79b1b12a
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
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.
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.
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/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
27 #include "includes.h"
28 #include "smbd/globals.h"
30 extern enum protocol_types Protocol;
32 /****************************************************************************
33 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
34 path or anything including wildcards.
35 We're assuming here that '/' is not the second byte in any multibyte char
36 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
37 set.
38 ****************************************************************************/
40 /* Custom version for processing POSIX paths. */
41 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
43 static NTSTATUS check_path_syntax_internal(char *path,
44 bool posix_path,
45 bool *p_last_component_contains_wcard)
47 char *d = path;
48 const char *s = path;
49 NTSTATUS ret = NT_STATUS_OK;
50 bool start_of_name_component = True;
51 bool stream_started = false;
53 *p_last_component_contains_wcard = False;
55 while (*s) {
56 if (stream_started) {
57 switch (*s) {
58 case '/':
59 case '\\':
60 return NT_STATUS_OBJECT_NAME_INVALID;
61 case ':':
62 if (s[1] == '\0') {
63 return NT_STATUS_OBJECT_NAME_INVALID;
65 if (strchr_m(&s[1], ':')) {
66 return NT_STATUS_OBJECT_NAME_INVALID;
68 if (StrCaseCmp(s, ":$DATA") != 0) {
69 return NT_STATUS_INVALID_PARAMETER;
71 break;
75 if (!posix_path && !stream_started && *s == ':') {
76 if (*p_last_component_contains_wcard) {
77 return NT_STATUS_OBJECT_NAME_INVALID;
79 /* Stream names allow more characters than file names.
80 We're overloading posix_path here to allow a wider
81 range of characters. If stream_started is true this
82 is still a Windows path even if posix_path is true.
83 JRA.
85 stream_started = true;
86 start_of_name_component = false;
87 posix_path = true;
89 if (s[1] == '\0') {
90 return NT_STATUS_OBJECT_NAME_INVALID;
94 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
96 * Safe to assume is not the second part of a mb char
97 * as this is handled below.
99 /* Eat multiple '/' or '\\' */
100 while (IS_PATH_SEP(*s,posix_path)) {
101 s++;
103 if ((d != path) && (*s != '\0')) {
104 /* We only care about non-leading or trailing '/' or '\\' */
105 *d++ = '/';
108 start_of_name_component = True;
109 /* New component. */
110 *p_last_component_contains_wcard = False;
111 continue;
114 if (start_of_name_component) {
115 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
116 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
119 * No mb char starts with '.' so we're safe checking the directory separator here.
122 /* If we just added a '/' - delete it */
123 if ((d > path) && (*(d-1) == '/')) {
124 *(d-1) = '\0';
125 d--;
128 /* Are we at the start ? Can't go back further if so. */
129 if (d <= path) {
130 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
131 break;
133 /* Go back one level... */
134 /* We know this is safe as '/' cannot be part of a mb sequence. */
135 /* NOTE - if this assumption is invalid we are not in good shape... */
136 /* Decrement d first as d points to the *next* char to write into. */
137 for (d--; d > path; d--) {
138 if (*d == '/')
139 break;
141 s += 2; /* Else go past the .. */
142 /* We're still at the start of a name component, just the previous one. */
143 continue;
145 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
146 if (posix_path) {
147 /* Eat the '.' */
148 s++;
149 continue;
155 if (!(*s & 0x80)) {
156 if (!posix_path) {
157 if (*s <= 0x1f || *s == '|') {
158 return NT_STATUS_OBJECT_NAME_INVALID;
160 switch (*s) {
161 case '*':
162 case '?':
163 case '<':
164 case '>':
165 case '"':
166 *p_last_component_contains_wcard = True;
167 break;
168 default:
169 break;
172 *d++ = *s++;
173 } else {
174 size_t siz;
175 /* Get the size of the next MB character. */
176 next_codepoint(s,&siz);
177 switch(siz) {
178 case 5:
179 *d++ = *s++;
180 /*fall through*/
181 case 4:
182 *d++ = *s++;
183 /*fall through*/
184 case 3:
185 *d++ = *s++;
186 /*fall through*/
187 case 2:
188 *d++ = *s++;
189 /*fall through*/
190 case 1:
191 *d++ = *s++;
192 break;
193 default:
194 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
195 *d = '\0';
196 return NT_STATUS_INVALID_PARAMETER;
199 start_of_name_component = False;
202 *d = '\0';
204 return ret;
207 /****************************************************************************
208 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
209 No wildcards allowed.
210 ****************************************************************************/
212 NTSTATUS check_path_syntax(char *path)
214 bool ignore;
215 return check_path_syntax_internal(path, False, &ignore);
218 /****************************************************************************
219 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
220 Wildcards allowed - p_contains_wcard returns true if the last component contained
221 a wildcard.
222 ****************************************************************************/
224 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
226 return check_path_syntax_internal(path, False, p_contains_wcard);
229 /****************************************************************************
230 Check the path for a POSIX client.
231 We're assuming here that '/' is not the second byte in any multibyte char
232 set (a safe assumption).
233 ****************************************************************************/
235 NTSTATUS check_path_syntax_posix(char *path)
237 bool ignore;
238 return check_path_syntax_internal(path, True, &ignore);
241 /****************************************************************************
242 Pull a string and check the path allowing a wilcard - provide for error return.
243 ****************************************************************************/
245 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
246 const char *base_ptr,
247 uint16 smb_flags2,
248 char **pp_dest,
249 const char *src,
250 size_t src_len,
251 int flags,
252 NTSTATUS *err,
253 bool *contains_wcard)
255 size_t ret;
257 *pp_dest = NULL;
259 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
260 src_len, flags);
262 if (!*pp_dest) {
263 *err = NT_STATUS_INVALID_PARAMETER;
264 return ret;
267 *contains_wcard = False;
269 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
271 * For a DFS path the function parse_dfs_path()
272 * will do the path processing, just make a copy.
274 *err = NT_STATUS_OK;
275 return ret;
278 if (lp_posix_pathnames()) {
279 *err = check_path_syntax_posix(*pp_dest);
280 } else {
281 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
284 return ret;
287 /****************************************************************************
288 Pull a string and check the path - provide for error return.
289 ****************************************************************************/
291 size_t srvstr_get_path(TALLOC_CTX *ctx,
292 const char *base_ptr,
293 uint16 smb_flags2,
294 char **pp_dest,
295 const char *src,
296 size_t src_len,
297 int flags,
298 NTSTATUS *err)
300 bool ignore;
301 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
302 src_len, flags, err, &ignore);
305 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
306 char **pp_dest, const char *src, int flags,
307 NTSTATUS *err, bool *contains_wcard)
309 return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
310 pp_dest, src, smbreq_bufrem(req, src),
311 flags, err, contains_wcard);
314 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
315 char **pp_dest, const char *src, int flags,
316 NTSTATUS *err)
318 bool ignore;
319 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
320 flags, err, &ignore);
323 /****************************************************************************
324 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
325 ****************************************************************************/
327 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
328 files_struct *fsp)
330 if (!(fsp) || !(conn)) {
331 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
332 return False;
334 if (((conn) != (fsp)->conn) || req->vuid != (fsp)->vuid) {
335 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
336 return False;
338 return True;
341 /****************************************************************************
342 Check if we have a correct fsp pointing to a file.
343 ****************************************************************************/
345 bool check_fsp(connection_struct *conn, struct smb_request *req,
346 files_struct *fsp)
348 if (!check_fsp_open(conn, req, fsp)) {
349 return False;
351 if ((fsp)->is_directory) {
352 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
353 return False;
355 if ((fsp)->fh->fd == -1) {
356 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
357 return False;
359 (fsp)->num_smb_operations++;
360 return True;
363 /****************************************************************************
364 Check if we have a correct fsp pointing to a quota fake file. Replacement for
365 the CHECK_NTQUOTA_HANDLE_OK macro.
366 ****************************************************************************/
368 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
369 files_struct *fsp)
371 if (!check_fsp_open(conn, req, fsp)) {
372 return false;
375 if (fsp->is_directory) {
376 return false;
379 if (fsp->fake_file_handle == NULL) {
380 return false;
383 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
384 return false;
387 if (fsp->fake_file_handle->private_data == NULL) {
388 return false;
391 return true;
394 /****************************************************************************
395 Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
396 ****************************************************************************/
398 bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
399 files_struct *fsp)
401 if ((fsp) && (conn) && ((conn)==(fsp)->conn)
402 && (req->vuid == (fsp)->vuid)) {
403 return True;
406 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
407 return False;
410 static bool netbios_session_retarget(const char *name, int name_type)
412 char *trim_name;
413 char *trim_name_type;
414 const char *retarget_parm;
415 char *retarget;
416 char *p;
417 int retarget_type = 0x20;
418 int retarget_port = 139;
419 struct sockaddr_storage retarget_addr;
420 struct sockaddr_in *in_addr;
421 bool ret = false;
422 uint8_t outbuf[10];
424 if (get_socket_port(smbd_server_fd()) != 139) {
425 return false;
428 trim_name = talloc_strdup(talloc_tos(), name);
429 if (trim_name == NULL) {
430 goto fail;
432 trim_char(trim_name, ' ', ' ');
434 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
435 name_type);
436 if (trim_name_type == NULL) {
437 goto fail;
440 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
441 trim_name_type, NULL);
442 if (retarget_parm == NULL) {
443 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
444 trim_name, NULL);
446 if (retarget_parm == NULL) {
447 goto fail;
450 retarget = talloc_strdup(trim_name, retarget_parm);
451 if (retarget == NULL) {
452 goto fail;
455 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
457 p = strchr(retarget, ':');
458 if (p != NULL) {
459 *p++ = '\0';
460 retarget_port = atoi(p);
463 p = strchr_m(retarget, '#');
464 if (p != NULL) {
465 *p++ = '\0';
466 sscanf(p, "%x", &retarget_type);
469 ret = resolve_name(retarget, &retarget_addr, retarget_type);
470 if (!ret) {
471 DEBUG(10, ("could not resolve %s\n", retarget));
472 goto fail;
475 if (retarget_addr.ss_family != AF_INET) {
476 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
477 goto fail;
480 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
482 _smb_setlen(outbuf, 6);
483 SCVAL(outbuf, 0, 0x84);
484 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
485 *(uint16_t *)(outbuf+8) = htons(retarget_port);
487 if (!srv_send_smb(smbd_server_fd(), (char *)outbuf, false, 0, false,
488 NULL)) {
489 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
490 "failed.");
493 ret = true;
494 fail:
495 TALLOC_FREE(trim_name);
496 return ret;
499 /****************************************************************************
500 Reply to a (netbios-level) special message.
501 ****************************************************************************/
503 void reply_special(char *inbuf)
505 int msg_type = CVAL(inbuf,0);
506 int msg_flags = CVAL(inbuf,1);
507 fstring name1,name2;
508 char name_type1, name_type2;
509 struct smbd_server_connection *sconn = smbd_server_conn;
512 * We only really use 4 bytes of the outbuf, but for the smb_setlen
513 * calculation & friends (srv_send_smb uses that) we need the full smb
514 * header.
516 char outbuf[smb_size];
518 *name1 = *name2 = 0;
520 memset(outbuf, '\0', sizeof(outbuf));
522 smb_setlen(outbuf,0);
524 switch (msg_type) {
525 case 0x81: /* session request */
527 if (sconn->nbt.got_session) {
528 exit_server_cleanly("multiple session request not permitted");
531 SCVAL(outbuf,0,0x82);
532 SCVAL(outbuf,3,0);
533 if (name_len(inbuf+4) > 50 ||
534 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
535 DEBUG(0,("Invalid name length in session request\n"));
536 return;
538 name_type1 = name_extract(inbuf,4,name1);
539 name_type2 = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
540 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
541 name1, name_type1, name2, name_type2));
543 if (netbios_session_retarget(name1, name_type1)) {
544 exit_server_cleanly("retargeted client");
547 set_local_machine_name(name1, True);
548 set_remote_machine_name(name2, True);
550 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
551 get_local_machine_name(), get_remote_machine_name(),
552 name_type2));
554 if (name_type2 == 'R') {
555 /* We are being asked for a pathworks session ---
556 no thanks! */
557 SCVAL(outbuf, 0,0x83);
558 break;
561 /* only add the client's machine name to the list
562 of possibly valid usernames if we are operating
563 in share mode security */
564 if (lp_security() == SEC_SHARE) {
565 add_session_user(sconn, get_remote_machine_name());
568 reload_services(True);
569 reopen_logs();
571 sconn->nbt.got_session = true;
572 break;
574 case 0x89: /* session keepalive request
575 (some old clients produce this?) */
576 SCVAL(outbuf,0,SMBkeepalive);
577 SCVAL(outbuf,3,0);
578 break;
580 case 0x82: /* positive session response */
581 case 0x83: /* negative session response */
582 case 0x84: /* retarget session response */
583 DEBUG(0,("Unexpected session response\n"));
584 break;
586 case SMBkeepalive: /* session keepalive */
587 default:
588 return;
591 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
592 msg_type, msg_flags));
594 srv_send_smb(smbd_server_fd(), outbuf, false, 0, false, NULL);
595 return;
598 /****************************************************************************
599 Reply to a tcon.
600 conn POINTER CAN BE NULL HERE !
601 ****************************************************************************/
603 void reply_tcon(struct smb_request *req)
605 connection_struct *conn = req->conn;
606 const char *service;
607 char *service_buf = NULL;
608 char *password = NULL;
609 char *dev = NULL;
610 int pwlen=0;
611 NTSTATUS nt_status;
612 const char *p;
613 DATA_BLOB password_blob;
614 TALLOC_CTX *ctx = talloc_tos();
615 struct smbd_server_connection *sconn = smbd_server_conn;
617 START_PROFILE(SMBtcon);
619 if (req->buflen < 4) {
620 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
621 END_PROFILE(SMBtcon);
622 return;
625 p = (const char *)req->buf + 1;
626 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
627 p += 1;
628 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
629 p += pwlen+1;
630 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
631 p += 1;
633 if (service_buf == NULL || password == NULL || dev == NULL) {
634 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
635 END_PROFILE(SMBtcon);
636 return;
638 p = strrchr_m(service_buf,'\\');
639 if (p) {
640 service = p+1;
641 } else {
642 service = service_buf;
645 password_blob = data_blob(password, pwlen+1);
647 conn = make_connection(sconn,service,password_blob,dev,
648 req->vuid,&nt_status);
649 req->conn = conn;
651 data_blob_clear_free(&password_blob);
653 if (!conn) {
654 reply_nterror(req, nt_status);
655 END_PROFILE(SMBtcon);
656 return;
659 reply_outbuf(req, 2, 0);
660 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
661 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
662 SSVAL(req->outbuf,smb_tid,conn->cnum);
664 DEBUG(3,("tcon service=%s cnum=%d\n",
665 service, conn->cnum));
667 END_PROFILE(SMBtcon);
668 return;
671 /****************************************************************************
672 Reply to a tcon and X.
673 conn POINTER CAN BE NULL HERE !
674 ****************************************************************************/
676 void reply_tcon_and_X(struct smb_request *req)
678 connection_struct *conn = req->conn;
679 const char *service = NULL;
680 DATA_BLOB password;
681 TALLOC_CTX *ctx = talloc_tos();
682 /* what the cleint thinks the device is */
683 char *client_devicetype = NULL;
684 /* what the server tells the client the share represents */
685 const char *server_devicetype;
686 NTSTATUS nt_status;
687 int passlen;
688 char *path = NULL;
689 const char *p, *q;
690 uint16 tcon_flags;
691 struct smbd_server_connection *sconn = smbd_server_conn;
693 START_PROFILE(SMBtconX);
695 if (req->wct < 4) {
696 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
697 END_PROFILE(SMBtconX);
698 return;
701 passlen = SVAL(req->vwv+3, 0);
702 tcon_flags = SVAL(req->vwv+2, 0);
704 /* we might have to close an old one */
705 if ((tcon_flags & 0x1) && conn) {
706 close_cnum(sconn, conn,req->vuid);
707 req->conn = NULL;
708 conn = NULL;
711 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
712 reply_doserror(req, ERRDOS, ERRbuftoosmall);
713 END_PROFILE(SMBtconX);
714 return;
717 if (sconn->smb1.negprot.encrypted_passwords) {
718 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
719 if (lp_security() == SEC_SHARE) {
721 * Security = share always has a pad byte
722 * after the password.
724 p = (const char *)req->buf + passlen + 1;
725 } else {
726 p = (const char *)req->buf + passlen;
728 } else {
729 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
730 /* Ensure correct termination */
731 password.data[passlen]=0;
732 p = (const char *)req->buf + passlen + 1;
735 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
737 if (path == NULL) {
738 data_blob_clear_free(&password);
739 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
740 END_PROFILE(SMBtconX);
741 return;
745 * the service name can be either: \\server\share
746 * or share directly like on the DELL PowerVault 705
748 if (*path=='\\') {
749 q = strchr_m(path+2,'\\');
750 if (!q) {
751 data_blob_clear_free(&password);
752 reply_doserror(req, ERRDOS, ERRnosuchshare);
753 END_PROFILE(SMBtconX);
754 return;
756 service = q+1;
757 } else {
758 service = path;
761 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
762 &client_devicetype, p,
763 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
765 if (client_devicetype == NULL) {
766 data_blob_clear_free(&password);
767 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
768 END_PROFILE(SMBtconX);
769 return;
772 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
774 conn = make_connection(sconn, service, password, client_devicetype,
775 req->vuid, &nt_status);
776 req->conn =conn;
778 data_blob_clear_free(&password);
780 if (!conn) {
781 reply_nterror(req, nt_status);
782 END_PROFILE(SMBtconX);
783 return;
786 if ( IS_IPC(conn) )
787 server_devicetype = "IPC";
788 else if ( IS_PRINT(conn) )
789 server_devicetype = "LPT1:";
790 else
791 server_devicetype = "A:";
793 if (Protocol < PROTOCOL_NT1) {
794 reply_outbuf(req, 2, 0);
795 if (message_push_string(&req->outbuf, server_devicetype,
796 STR_TERMINATE|STR_ASCII) == -1) {
797 reply_nterror(req, NT_STATUS_NO_MEMORY);
798 END_PROFILE(SMBtconX);
799 return;
801 } else {
802 /* NT sets the fstype of IPC$ to the null string */
803 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
805 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
806 /* Return permissions. */
807 uint32 perm1 = 0;
808 uint32 perm2 = 0;
810 reply_outbuf(req, 7, 0);
812 if (IS_IPC(conn)) {
813 perm1 = FILE_ALL_ACCESS;
814 perm2 = FILE_ALL_ACCESS;
815 } else {
816 perm1 = CAN_WRITE(conn) ?
817 SHARE_ALL_ACCESS :
818 SHARE_READ_ONLY;
821 SIVAL(req->outbuf, smb_vwv3, perm1);
822 SIVAL(req->outbuf, smb_vwv5, perm2);
823 } else {
824 reply_outbuf(req, 3, 0);
827 if ((message_push_string(&req->outbuf, server_devicetype,
828 STR_TERMINATE|STR_ASCII) == -1)
829 || (message_push_string(&req->outbuf, fstype,
830 STR_TERMINATE) == -1)) {
831 reply_nterror(req, NT_STATUS_NO_MEMORY);
832 END_PROFILE(SMBtconX);
833 return;
836 /* what does setting this bit do? It is set by NT4 and
837 may affect the ability to autorun mounted cdroms */
838 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
839 (lp_csc_policy(SNUM(conn)) << 2));
841 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
842 DEBUG(2,("Serving %s as a Dfs root\n",
843 lp_servicename(SNUM(conn)) ));
844 SSVAL(req->outbuf, smb_vwv2,
845 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
850 DEBUG(3,("tconX service=%s \n",
851 service));
853 /* set the incoming and outgoing tid to the just created one */
854 SSVAL(req->inbuf,smb_tid,conn->cnum);
855 SSVAL(req->outbuf,smb_tid,conn->cnum);
857 END_PROFILE(SMBtconX);
859 chain_reply(req);
860 return;
863 /****************************************************************************
864 Reply to an unknown type.
865 ****************************************************************************/
867 void reply_unknown_new(struct smb_request *req, uint8 type)
869 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
870 smb_fn_name(type), type, type));
871 reply_doserror(req, ERRSRV, ERRunknownsmb);
872 return;
875 /****************************************************************************
876 Reply to an ioctl.
877 conn POINTER CAN BE NULL HERE !
878 ****************************************************************************/
880 void reply_ioctl(struct smb_request *req)
882 connection_struct *conn = req->conn;
883 uint16 device;
884 uint16 function;
885 uint32 ioctl_code;
886 int replysize;
887 char *p;
889 START_PROFILE(SMBioctl);
891 if (req->wct < 3) {
892 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
893 END_PROFILE(SMBioctl);
894 return;
897 device = SVAL(req->vwv+1, 0);
898 function = SVAL(req->vwv+2, 0);
899 ioctl_code = (device << 16) + function;
901 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
903 switch (ioctl_code) {
904 case IOCTL_QUERY_JOB_INFO:
905 replysize = 32;
906 break;
907 default:
908 reply_doserror(req, ERRSRV, ERRnosupport);
909 END_PROFILE(SMBioctl);
910 return;
913 reply_outbuf(req, 8, replysize+1);
914 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
915 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
916 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
917 p = smb_buf(req->outbuf);
918 memset(p, '\0', replysize+1); /* valgrind-safe. */
919 p += 1; /* Allow for alignment */
921 switch (ioctl_code) {
922 case IOCTL_QUERY_JOB_INFO:
924 files_struct *fsp = file_fsp(
925 req, SVAL(req->vwv+0, 0));
926 if (!fsp) {
927 reply_doserror(req, ERRDOS, ERRbadfid);
928 END_PROFILE(SMBioctl);
929 return;
931 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
932 srvstr_push((char *)req->outbuf, req->flags2, p+2,
933 global_myname(), 15,
934 STR_TERMINATE|STR_ASCII);
935 if (conn) {
936 srvstr_push((char *)req->outbuf, req->flags2,
937 p+18, lp_servicename(SNUM(conn)),
938 13, STR_TERMINATE|STR_ASCII);
939 } else {
940 memset(p+18, 0, 13);
942 break;
946 END_PROFILE(SMBioctl);
947 return;
950 /****************************************************************************
951 Strange checkpath NTSTATUS mapping.
952 ****************************************************************************/
954 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
956 /* Strange DOS error code semantics only for checkpath... */
957 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
958 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
959 /* We need to map to ERRbadpath */
960 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
963 return status;
966 /****************************************************************************
967 Reply to a checkpath.
968 ****************************************************************************/
970 void reply_checkpath(struct smb_request *req)
972 connection_struct *conn = req->conn;
973 struct smb_filename *smb_fname = NULL;
974 char *name = NULL;
975 NTSTATUS status;
976 TALLOC_CTX *ctx = talloc_tos();
978 START_PROFILE(SMBcheckpath);
980 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
981 STR_TERMINATE, &status);
983 if (!NT_STATUS_IS_OK(status)) {
984 status = map_checkpath_error(req->flags2, status);
985 reply_nterror(req, status);
986 END_PROFILE(SMBcheckpath);
987 return;
990 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
992 status = filename_convert(ctx,
993 conn,
994 req->flags2 & FLAGS2_DFS_PATHNAMES,
995 name,
996 &smb_fname,
997 &name);
999 if (!NT_STATUS_IS_OK(status)) {
1000 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1001 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1002 ERRSRV, ERRbadpath);
1003 END_PROFILE(SMBcheckpath);
1004 return;
1006 goto path_err;
1009 if (!VALID_STAT(smb_fname->st) &&
1010 (SMB_VFS_STAT(conn, name, &smb_fname->st) != 0)) {
1011 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
1012 status = map_nt_error_from_unix(errno);
1013 goto path_err;
1016 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1017 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1018 ERRDOS, ERRbadpath);
1019 goto out;
1022 reply_outbuf(req, 0, 0);
1023 out:
1024 TALLOC_FREE(smb_fname);
1025 END_PROFILE(SMBcheckpath);
1026 return;
1028 path_err:
1030 TALLOC_FREE(smb_fname);
1032 END_PROFILE(SMBcheckpath);
1034 /* We special case this - as when a Windows machine
1035 is parsing a path is steps through the components
1036 one at a time - if a component fails it expects
1037 ERRbadpath, not ERRbadfile.
1039 status = map_checkpath_error(req->flags2, status);
1040 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1042 * Windows returns different error codes if
1043 * the parent directory is valid but not the
1044 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1045 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1046 * if the path is invalid.
1048 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1049 ERRDOS, ERRbadpath);
1050 return;
1053 reply_nterror(req, status);
1056 /****************************************************************************
1057 Reply to a getatr.
1058 ****************************************************************************/
1060 void reply_getatr(struct smb_request *req)
1062 connection_struct *conn = req->conn;
1063 struct smb_filename *smb_fname = NULL;
1064 char *fname = NULL;
1065 int mode=0;
1066 SMB_OFF_T size=0;
1067 time_t mtime=0;
1068 const char *p;
1069 NTSTATUS status;
1070 TALLOC_CTX *ctx = talloc_tos();
1072 START_PROFILE(SMBgetatr);
1074 p = (const char *)req->buf + 1;
1075 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1076 if (!NT_STATUS_IS_OK(status)) {
1077 reply_nterror(req, status);
1078 goto out;
1081 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1082 under WfWg - weird! */
1083 if (*fname == '\0') {
1084 mode = aHIDDEN | aDIR;
1085 if (!CAN_WRITE(conn)) {
1086 mode |= aRONLY;
1088 size = 0;
1089 mtime = 0;
1090 } else {
1091 status = filename_convert(ctx,
1092 conn,
1093 req->flags2 & FLAGS2_DFS_PATHNAMES,
1094 fname,
1095 &smb_fname,
1096 &fname);
1097 if (!NT_STATUS_IS_OK(status)) {
1098 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1099 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1100 ERRSRV, ERRbadpath);
1101 goto out;
1103 reply_nterror(req, status);
1104 goto out;
1106 if (!VALID_STAT(smb_fname->st) &&
1107 (SMB_VFS_STAT(conn, fname, &smb_fname->st) != 0)) {
1108 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
1109 reply_unixerror(req, ERRDOS,ERRbadfile);
1110 goto out;
1113 mode = dos_mode(conn, fname, &smb_fname->st);
1114 size = smb_fname->st.st_ex_size;
1115 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1116 if (mode & aDIR) {
1117 size = 0;
1121 reply_outbuf(req, 10, 0);
1123 SSVAL(req->outbuf,smb_vwv0,mode);
1124 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1125 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1126 } else {
1127 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1129 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1131 if (Protocol >= PROTOCOL_NT1) {
1132 SSVAL(req->outbuf, smb_flg2,
1133 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1136 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
1138 out:
1139 TALLOC_FREE(smb_fname);
1140 END_PROFILE(SMBgetatr);
1141 return;
1144 /****************************************************************************
1145 Reply to a setatr.
1146 ****************************************************************************/
1148 void reply_setatr(struct smb_request *req)
1150 struct smb_file_time ft;
1151 connection_struct *conn = req->conn;
1152 struct smb_filename *smb_fname = NULL;
1153 char *fname = NULL;
1154 int mode;
1155 time_t mtime;
1156 const char *p;
1157 NTSTATUS status;
1158 TALLOC_CTX *ctx = talloc_tos();
1160 START_PROFILE(SMBsetatr);
1162 ZERO_STRUCT(ft);
1164 if (req->wct < 2) {
1165 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1166 goto out;
1169 p = (const char *)req->buf + 1;
1170 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1171 if (!NT_STATUS_IS_OK(status)) {
1172 reply_nterror(req, status);
1173 goto out;
1176 status = filename_convert(ctx,
1177 conn,
1178 req->flags2 & FLAGS2_DFS_PATHNAMES,
1179 fname,
1180 &smb_fname,
1181 &fname);
1182 if (!NT_STATUS_IS_OK(status)) {
1183 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1184 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1185 ERRSRV, ERRbadpath);
1186 goto out;
1188 reply_nterror(req, status);
1189 goto out;
1192 if (fname[0] == '.' && fname[1] == '\0') {
1194 * Not sure here is the right place to catch this
1195 * condition. Might be moved to somewhere else later -- vl
1197 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1198 goto out;
1201 mode = SVAL(req->vwv+0, 0);
1202 mtime = srv_make_unix_date3(req->vwv+1);
1204 ft.mtime = convert_time_t_to_timespec(mtime);
1205 status = smb_set_file_time(conn, NULL, fname,
1206 &smb_fname->st, &ft, true);
1207 if (!NT_STATUS_IS_OK(status)) {
1208 reply_unixerror(req, ERRDOS, ERRnoaccess);
1209 goto out;
1212 if (mode != FILE_ATTRIBUTE_NORMAL) {
1213 if (VALID_STAT_OF_DIR(smb_fname->st))
1214 mode |= aDIR;
1215 else
1216 mode &= ~aDIR;
1218 if (file_set_dosmode(conn, fname, mode, &smb_fname->st, NULL,
1219 false) != 0) {
1220 reply_unixerror(req, ERRDOS, ERRnoaccess);
1221 goto out;
1225 reply_outbuf(req, 0, 0);
1227 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1228 out:
1229 TALLOC_FREE(smb_fname);
1230 END_PROFILE(SMBsetatr);
1231 return;
1234 /****************************************************************************
1235 Reply to a dskattr.
1236 ****************************************************************************/
1238 void reply_dskattr(struct smb_request *req)
1240 connection_struct *conn = req->conn;
1241 uint64_t dfree,dsize,bsize;
1242 START_PROFILE(SMBdskattr);
1244 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1245 reply_unixerror(req, ERRHRD, ERRgeneral);
1246 END_PROFILE(SMBdskattr);
1247 return;
1250 reply_outbuf(req, 5, 0);
1252 if (Protocol <= PROTOCOL_LANMAN2) {
1253 double total_space, free_space;
1254 /* we need to scale this to a number that DOS6 can handle. We
1255 use floating point so we can handle large drives on systems
1256 that don't have 64 bit integers
1258 we end up displaying a maximum of 2G to DOS systems
1260 total_space = dsize * (double)bsize;
1261 free_space = dfree * (double)bsize;
1263 dsize = (uint64_t)((total_space+63*512) / (64*512));
1264 dfree = (uint64_t)((free_space+63*512) / (64*512));
1266 if (dsize > 0xFFFF) dsize = 0xFFFF;
1267 if (dfree > 0xFFFF) dfree = 0xFFFF;
1269 SSVAL(req->outbuf,smb_vwv0,dsize);
1270 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1271 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1272 SSVAL(req->outbuf,smb_vwv3,dfree);
1273 } else {
1274 SSVAL(req->outbuf,smb_vwv0,dsize);
1275 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1276 SSVAL(req->outbuf,smb_vwv2,512);
1277 SSVAL(req->outbuf,smb_vwv3,dfree);
1280 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1282 END_PROFILE(SMBdskattr);
1283 return;
1287 * Utility function to split the filename from the directory.
1289 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1290 char **fname_dir_out,
1291 char **fname_mask_out)
1293 const char *p = NULL;
1294 char *fname_dir = NULL;
1295 char *fname_mask = NULL;
1297 p = strrchr_m(fname_in, '/');
1298 if (!p) {
1299 fname_dir = talloc_strdup(ctx, ".");
1300 fname_mask = talloc_strdup(ctx, fname_in);
1301 } else {
1302 fname_dir = talloc_strndup(ctx, fname_in,
1303 PTR_DIFF(p, fname_in));
1304 fname_mask = talloc_strdup(ctx, p+1);
1307 if (!fname_dir || !fname_mask) {
1308 TALLOC_FREE(fname_dir);
1309 TALLOC_FREE(fname_mask);
1310 return NT_STATUS_NO_MEMORY;
1313 *fname_dir_out = fname_dir;
1314 *fname_mask_out = fname_mask;
1315 return NT_STATUS_OK;
1318 /****************************************************************************
1319 Reply to a search.
1320 Can be called from SMBsearch, SMBffirst or SMBfunique.
1321 ****************************************************************************/
1323 void reply_search(struct smb_request *req)
1325 connection_struct *conn = req->conn;
1326 char *path = NULL;
1327 const char *mask = NULL;
1328 char *directory = NULL;
1329 char *fname = NULL;
1330 SMB_OFF_T size;
1331 uint32 mode;
1332 struct timespec date;
1333 uint32 dirtype;
1334 unsigned int numentries = 0;
1335 unsigned int maxentries = 0;
1336 bool finished = False;
1337 const char *p;
1338 int status_len;
1339 char status[21];
1340 int dptr_num= -1;
1341 bool check_descend = False;
1342 bool expect_close = False;
1343 NTSTATUS nt_status;
1344 bool mask_contains_wcard = False;
1345 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1346 TALLOC_CTX *ctx = talloc_tos();
1347 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1349 START_PROFILE(SMBsearch);
1351 if (req->wct < 2) {
1352 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1353 END_PROFILE(SMBsearch);
1354 return;
1357 if (lp_posix_pathnames()) {
1358 reply_unknown_new(req, req->cmd);
1359 END_PROFILE(SMBsearch);
1360 return;
1363 /* If we were called as SMBffirst then we must expect close. */
1364 if(req->cmd == SMBffirst) {
1365 expect_close = True;
1368 reply_outbuf(req, 1, 3);
1369 maxentries = SVAL(req->vwv+0, 0);
1370 dirtype = SVAL(req->vwv+1, 0);
1371 p = (const char *)req->buf + 1;
1372 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1373 &nt_status, &mask_contains_wcard);
1374 if (!NT_STATUS_IS_OK(nt_status)) {
1375 reply_nterror(req, nt_status);
1376 END_PROFILE(SMBsearch);
1377 return;
1380 p++;
1381 status_len = SVAL(p, 0);
1382 p += 2;
1384 /* dirtype &= ~aDIR; */
1386 if (status_len == 0) {
1387 struct smb_filename *smb_fname = NULL;
1389 nt_status = resolve_dfspath_wcard(ctx, conn,
1390 req->flags2 & FLAGS2_DFS_PATHNAMES,
1391 path,
1392 &path,
1393 &mask_contains_wcard);
1394 if (!NT_STATUS_IS_OK(nt_status)) {
1395 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1396 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1397 ERRSRV, ERRbadpath);
1398 END_PROFILE(SMBsearch);
1399 return;
1401 reply_nterror(req, nt_status);
1402 END_PROFILE(SMBsearch);
1403 return;
1406 nt_status = unix_convert(ctx, conn, path, &smb_fname,
1407 UCF_ALLOW_WCARD_LCOMP);
1408 if (!NT_STATUS_IS_OK(nt_status)) {
1409 reply_nterror(req, nt_status);
1410 END_PROFILE(SMBsearch);
1411 return;
1414 nt_status = get_full_smb_filename(ctx, smb_fname, &directory);
1415 TALLOC_FREE(smb_fname);
1416 if (!NT_STATUS_IS_OK(nt_status)) {
1417 reply_nterror(req, nt_status);
1418 END_PROFILE(SMBsearch);
1419 return;
1422 nt_status = check_name(conn, directory);
1423 if (!NT_STATUS_IS_OK(nt_status)) {
1424 reply_nterror(req, nt_status);
1425 END_PROFILE(SMBsearch);
1426 return;
1429 p = strrchr_m(directory,'/');
1430 if ((p != NULL) && (*directory != '/')) {
1431 mask = p + 1;
1432 directory = talloc_strndup(ctx, directory,
1433 PTR_DIFF(p, directory));
1434 } else {
1435 mask = directory;
1436 directory = talloc_strdup(ctx,".");
1439 if (!directory) {
1440 reply_nterror(req, NT_STATUS_NO_MEMORY);
1441 END_PROFILE(SMBsearch);
1442 return;
1445 memset((char *)status,'\0',21);
1446 SCVAL(status,0,(dirtype & 0x1F));
1448 nt_status = dptr_create(conn,
1449 directory,
1450 True,
1451 expect_close,
1452 req->smbpid,
1453 mask,
1454 mask_contains_wcard,
1455 dirtype,
1456 &conn->dirptr);
1457 if (!NT_STATUS_IS_OK(nt_status)) {
1458 reply_nterror(req, nt_status);
1459 END_PROFILE(SMBsearch);
1460 return;
1462 dptr_num = dptr_dnum(conn->dirptr);
1463 } else {
1464 int status_dirtype;
1466 memcpy(status,p,21);
1467 status_dirtype = CVAL(status,0) & 0x1F;
1468 if (status_dirtype != (dirtype & 0x1F)) {
1469 dirtype = status_dirtype;
1472 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1473 if (!conn->dirptr) {
1474 goto SearchEmpty;
1476 string_set(&conn->dirpath,dptr_path(dptr_num));
1477 mask = dptr_wcard(dptr_num);
1478 if (!mask) {
1479 goto SearchEmpty;
1482 * For a 'continue' search we have no string. So
1483 * check from the initial saved string.
1485 mask_contains_wcard = ms_has_wild(mask);
1486 dirtype = dptr_attr(dptr_num);
1489 DEBUG(4,("dptr_num is %d\n",dptr_num));
1491 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1492 dptr_init_search_op(conn->dirptr);
1494 if ((dirtype&0x1F) == aVOLID) {
1495 char buf[DIR_STRUCT_SIZE];
1496 memcpy(buf,status,21);
1497 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1498 0,aVOLID,0,!allow_long_path_components)) {
1499 reply_nterror(req, NT_STATUS_NO_MEMORY);
1500 END_PROFILE(SMBsearch);
1501 return;
1503 dptr_fill(buf+12,dptr_num);
1504 if (dptr_zero(buf+12) && (status_len==0)) {
1505 numentries = 1;
1506 } else {
1507 numentries = 0;
1509 if (message_push_blob(&req->outbuf,
1510 data_blob_const(buf, sizeof(buf)))
1511 == -1) {
1512 reply_nterror(req, NT_STATUS_NO_MEMORY);
1513 END_PROFILE(SMBsearch);
1514 return;
1516 } else {
1517 unsigned int i;
1518 maxentries = MIN(
1519 maxentries,
1520 ((BUFFER_SIZE -
1521 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1522 /DIR_STRUCT_SIZE));
1524 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1525 conn->dirpath,lp_dontdescend(SNUM(conn))));
1526 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1527 check_descend = True;
1530 for (i=numentries;(i<maxentries) && !finished;i++) {
1531 finished = !get_dir_entry(ctx,
1532 conn,
1533 mask,
1534 dirtype,
1535 &fname,
1536 &size,
1537 &mode,
1538 &date,
1539 check_descend,
1540 ask_sharemode);
1541 if (!finished) {
1542 char buf[DIR_STRUCT_SIZE];
1543 memcpy(buf,status,21);
1544 if (!make_dir_struct(ctx,
1545 buf,
1546 mask,
1547 fname,
1548 size,
1549 mode,
1550 convert_timespec_to_time_t(date),
1551 !allow_long_path_components)) {
1552 reply_nterror(req, NT_STATUS_NO_MEMORY);
1553 END_PROFILE(SMBsearch);
1554 return;
1556 if (!dptr_fill(buf+12,dptr_num)) {
1557 break;
1559 if (message_push_blob(&req->outbuf,
1560 data_blob_const(buf, sizeof(buf)))
1561 == -1) {
1562 reply_nterror(req, NT_STATUS_NO_MEMORY);
1563 END_PROFILE(SMBsearch);
1564 return;
1566 numentries++;
1571 SearchEmpty:
1573 /* If we were called as SMBffirst with smb_search_id == NULL
1574 and no entries were found then return error and close dirptr
1575 (X/Open spec) */
1577 if (numentries == 0) {
1578 dptr_close(&dptr_num);
1579 } else if(expect_close && status_len == 0) {
1580 /* Close the dptr - we know it's gone */
1581 dptr_close(&dptr_num);
1584 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1585 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1586 dptr_close(&dptr_num);
1589 if ((numentries == 0) && !mask_contains_wcard) {
1590 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1591 END_PROFILE(SMBsearch);
1592 return;
1595 SSVAL(req->outbuf,smb_vwv0,numentries);
1596 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1597 SCVAL(smb_buf(req->outbuf),0,5);
1598 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1600 /* The replies here are never long name. */
1601 SSVAL(req->outbuf, smb_flg2,
1602 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1603 if (!allow_long_path_components) {
1604 SSVAL(req->outbuf, smb_flg2,
1605 SVAL(req->outbuf, smb_flg2)
1606 & (~FLAGS2_LONG_PATH_COMPONENTS));
1609 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1610 SSVAL(req->outbuf, smb_flg2,
1611 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1613 if (!directory) {
1614 directory = dptr_path(dptr_num);
1617 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1618 smb_fn_name(req->cmd),
1619 mask,
1620 directory ? directory : "./",
1621 dirtype,
1622 numentries,
1623 maxentries ));
1625 END_PROFILE(SMBsearch);
1626 return;
1629 /****************************************************************************
1630 Reply to a fclose (stop directory search).
1631 ****************************************************************************/
1633 void reply_fclose(struct smb_request *req)
1635 int status_len;
1636 char status[21];
1637 int dptr_num= -2;
1638 const char *p;
1639 char *path = NULL;
1640 NTSTATUS err;
1641 bool path_contains_wcard = False;
1642 TALLOC_CTX *ctx = talloc_tos();
1644 START_PROFILE(SMBfclose);
1646 if (lp_posix_pathnames()) {
1647 reply_unknown_new(req, req->cmd);
1648 END_PROFILE(SMBfclose);
1649 return;
1652 p = (const char *)req->buf + 1;
1653 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1654 &err, &path_contains_wcard);
1655 if (!NT_STATUS_IS_OK(err)) {
1656 reply_nterror(req, err);
1657 END_PROFILE(SMBfclose);
1658 return;
1660 p++;
1661 status_len = SVAL(p,0);
1662 p += 2;
1664 if (status_len == 0) {
1665 reply_doserror(req, ERRSRV, ERRsrverror);
1666 END_PROFILE(SMBfclose);
1667 return;
1670 memcpy(status,p,21);
1672 if(dptr_fetch(status+12,&dptr_num)) {
1673 /* Close the dptr - we know it's gone */
1674 dptr_close(&dptr_num);
1677 reply_outbuf(req, 1, 0);
1678 SSVAL(req->outbuf,smb_vwv0,0);
1680 DEBUG(3,("search close\n"));
1682 END_PROFILE(SMBfclose);
1683 return;
1686 /****************************************************************************
1687 Reply to an open.
1688 ****************************************************************************/
1690 void reply_open(struct smb_request *req)
1692 connection_struct *conn = req->conn;
1693 struct smb_filename *smb_fname = NULL;
1694 char *fname = NULL;
1695 uint32 fattr=0;
1696 SMB_OFF_T size = 0;
1697 time_t mtime=0;
1698 int info;
1699 files_struct *fsp;
1700 int oplock_request;
1701 int deny_mode;
1702 uint32 dos_attr;
1703 uint32 access_mask;
1704 uint32 share_mode;
1705 uint32 create_disposition;
1706 uint32 create_options = 0;
1707 NTSTATUS status;
1708 TALLOC_CTX *ctx = talloc_tos();
1710 START_PROFILE(SMBopen);
1712 if (req->wct < 2) {
1713 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1714 goto out;
1717 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1718 deny_mode = SVAL(req->vwv+0, 0);
1719 dos_attr = SVAL(req->vwv+1, 0);
1721 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1722 STR_TERMINATE, &status);
1723 if (!NT_STATUS_IS_OK(status)) {
1724 reply_nterror(req, status);
1725 goto out;
1728 status = filename_convert(ctx,
1729 conn,
1730 req->flags2 & FLAGS2_DFS_PATHNAMES,
1731 fname,
1732 &smb_fname,
1733 &fname);
1734 if (!NT_STATUS_IS_OK(status)) {
1735 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1736 reply_botherror(req,
1737 NT_STATUS_PATH_NOT_COVERED,
1738 ERRSRV, ERRbadpath);
1739 goto out;
1741 reply_nterror(req, status);
1742 goto out;
1745 if (!map_open_params_to_ntcreate(
1746 fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
1747 &share_mode, &create_disposition, &create_options)) {
1748 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1749 goto out;
1752 status = SMB_VFS_CREATE_FILE(
1753 conn, /* conn */
1754 req, /* req */
1755 0, /* root_dir_fid */
1756 smb_fname, /* fname */
1757 access_mask, /* access_mask */
1758 share_mode, /* share_access */
1759 create_disposition, /* create_disposition*/
1760 create_options, /* create_options */
1761 dos_attr, /* file_attributes */
1762 oplock_request, /* oplock_request */
1763 0, /* allocation_size */
1764 NULL, /* sd */
1765 NULL, /* ea_list */
1766 &fsp, /* result */
1767 &info); /* pinfo */
1769 if (!NT_STATUS_IS_OK(status)) {
1770 if (open_was_deferred(req->mid)) {
1771 /* We have re-scheduled this call. */
1772 goto out;
1774 reply_openerror(req, status);
1775 goto out;
1778 size = smb_fname->st.st_ex_size;
1779 fattr = dos_mode(conn,fsp->fsp_name,&smb_fname->st);
1780 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1782 if (fattr & aDIR) {
1783 DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
1784 close_file(req, fsp, ERROR_CLOSE);
1785 reply_doserror(req, ERRDOS,ERRnoaccess);
1786 goto out;
1789 reply_outbuf(req, 7, 0);
1790 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1791 SSVAL(req->outbuf,smb_vwv1,fattr);
1792 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1793 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1794 } else {
1795 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1797 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1798 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1800 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1801 SCVAL(req->outbuf,smb_flg,
1802 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1805 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1806 SCVAL(req->outbuf,smb_flg,
1807 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1809 out:
1810 TALLOC_FREE(smb_fname);
1811 END_PROFILE(SMBopen);
1812 return;
1815 /****************************************************************************
1816 Reply to an open and X.
1817 ****************************************************************************/
1819 void reply_open_and_X(struct smb_request *req)
1821 connection_struct *conn = req->conn;
1822 struct smb_filename *smb_fname = NULL;
1823 char *fname = NULL;
1824 uint16 open_flags;
1825 int deny_mode;
1826 uint32 smb_attr;
1827 /* Breakout the oplock request bits so we can set the
1828 reply bits separately. */
1829 int ex_oplock_request;
1830 int core_oplock_request;
1831 int oplock_request;
1832 #if 0
1833 int smb_sattr = SVAL(req->vwv+4, 0);
1834 uint32 smb_time = make_unix_date3(req->vwv+6);
1835 #endif
1836 int smb_ofun;
1837 uint32 fattr=0;
1838 int mtime=0;
1839 int smb_action = 0;
1840 files_struct *fsp;
1841 NTSTATUS status;
1842 uint64_t allocation_size;
1843 ssize_t retval = -1;
1844 uint32 access_mask;
1845 uint32 share_mode;
1846 uint32 create_disposition;
1847 uint32 create_options = 0;
1848 TALLOC_CTX *ctx = talloc_tos();
1850 START_PROFILE(SMBopenX);
1852 if (req->wct < 15) {
1853 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1854 goto out;
1857 open_flags = SVAL(req->vwv+2, 0);
1858 deny_mode = SVAL(req->vwv+3, 0);
1859 smb_attr = SVAL(req->vwv+5, 0);
1860 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1861 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1862 oplock_request = ex_oplock_request | core_oplock_request;
1863 smb_ofun = SVAL(req->vwv+8, 0);
1864 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1866 /* If it's an IPC, pass off the pipe handler. */
1867 if (IS_IPC(conn)) {
1868 if (lp_nt_pipe_support()) {
1869 reply_open_pipe_and_X(conn, req);
1870 } else {
1871 reply_doserror(req, ERRSRV, ERRaccess);
1873 goto out;
1876 /* XXXX we need to handle passed times, sattr and flags */
1877 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1878 STR_TERMINATE, &status);
1879 if (!NT_STATUS_IS_OK(status)) {
1880 reply_nterror(req, status);
1881 goto out;
1884 status = filename_convert(ctx,
1885 conn,
1886 req->flags2 & FLAGS2_DFS_PATHNAMES,
1887 fname,
1888 &smb_fname,
1889 &fname);
1890 if (!NT_STATUS_IS_OK(status)) {
1891 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1892 reply_botherror(req,
1893 NT_STATUS_PATH_NOT_COVERED,
1894 ERRSRV, ERRbadpath);
1895 goto out;
1897 reply_nterror(req, status);
1898 goto out;
1901 if (!map_open_params_to_ntcreate(
1902 fname, deny_mode, smb_ofun, &access_mask,
1903 &share_mode, &create_disposition, &create_options)) {
1904 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1905 goto out;
1908 status = SMB_VFS_CREATE_FILE(
1909 conn, /* conn */
1910 req, /* req */
1911 0, /* root_dir_fid */
1912 smb_fname, /* fname */
1913 access_mask, /* access_mask */
1914 share_mode, /* share_access */
1915 create_disposition, /* create_disposition*/
1916 create_options, /* create_options */
1917 smb_attr, /* file_attributes */
1918 oplock_request, /* oplock_request */
1919 0, /* allocation_size */
1920 NULL, /* sd */
1921 NULL, /* ea_list */
1922 &fsp, /* result */
1923 &smb_action); /* pinfo */
1925 if (!NT_STATUS_IS_OK(status)) {
1926 if (open_was_deferred(req->mid)) {
1927 /* We have re-scheduled this call. */
1928 goto out;
1930 reply_openerror(req, status);
1931 goto out;
1934 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1935 if the file is truncated or created. */
1936 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1937 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1938 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1939 close_file(req, fsp, ERROR_CLOSE);
1940 reply_nterror(req, NT_STATUS_DISK_FULL);
1941 goto out;
1943 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1944 if (retval < 0) {
1945 close_file(req, fsp, ERROR_CLOSE);
1946 reply_nterror(req, NT_STATUS_DISK_FULL);
1947 goto out;
1949 smb_fname->st.st_ex_size =
1950 SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
1953 fattr = dos_mode(conn,fsp->fsp_name,&smb_fname->st);
1954 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1955 if (fattr & aDIR) {
1956 close_file(req, fsp, ERROR_CLOSE);
1957 reply_doserror(req, ERRDOS, ERRnoaccess);
1958 goto out;
1961 /* If the caller set the extended oplock request bit
1962 and we granted one (by whatever means) - set the
1963 correct bit for extended oplock reply.
1966 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1967 smb_action |= EXTENDED_OPLOCK_GRANTED;
1970 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1971 smb_action |= EXTENDED_OPLOCK_GRANTED;
1974 /* If the caller set the core oplock request bit
1975 and we granted one (by whatever means) - set the
1976 correct bit for core oplock reply.
1979 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1980 reply_outbuf(req, 19, 0);
1981 } else {
1982 reply_outbuf(req, 15, 0);
1985 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1986 SCVAL(req->outbuf, smb_flg,
1987 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1990 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1991 SCVAL(req->outbuf, smb_flg,
1992 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1995 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1996 SSVAL(req->outbuf,smb_vwv3,fattr);
1997 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1998 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1999 } else {
2000 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2002 SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size);
2003 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2004 SSVAL(req->outbuf,smb_vwv11,smb_action);
2006 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2007 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
2010 chain_reply(req);
2011 out:
2012 TALLOC_FREE(smb_fname);
2013 END_PROFILE(SMBopenX);
2014 return;
2017 /****************************************************************************
2018 Reply to a SMBulogoffX.
2019 ****************************************************************************/
2021 void reply_ulogoffX(struct smb_request *req)
2023 struct smbd_server_connection *sconn = smbd_server_conn;
2024 user_struct *vuser;
2026 START_PROFILE(SMBulogoffX);
2028 vuser = get_valid_user_struct(sconn, req->vuid);
2030 if(vuser == NULL) {
2031 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2032 req->vuid));
2035 /* in user level security we are supposed to close any files
2036 open by this user */
2037 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2038 file_close_user(req->vuid);
2041 invalidate_vuid(sconn, req->vuid);
2043 reply_outbuf(req, 2, 0);
2045 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2047 END_PROFILE(SMBulogoffX);
2048 chain_reply(req);
2051 /****************************************************************************
2052 Reply to a mknew or a create.
2053 ****************************************************************************/
2055 void reply_mknew(struct smb_request *req)
2057 connection_struct *conn = req->conn;
2058 struct smb_filename *smb_fname = NULL;
2059 char *fname = NULL;
2060 uint32 fattr = 0;
2061 struct smb_file_time ft;
2062 files_struct *fsp;
2063 int oplock_request = 0;
2064 NTSTATUS status;
2065 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2066 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2067 uint32 create_disposition;
2068 uint32 create_options = 0;
2069 TALLOC_CTX *ctx = talloc_tos();
2071 START_PROFILE(SMBcreate);
2072 ZERO_STRUCT(ft);
2074 if (req->wct < 3) {
2075 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2076 goto out;
2079 fattr = SVAL(req->vwv+0, 0);
2080 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2082 /* mtime. */
2083 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2085 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2086 STR_TERMINATE, &status);
2087 if (!NT_STATUS_IS_OK(status)) {
2088 reply_nterror(req, status);
2089 goto out;
2092 status = filename_convert(ctx,
2093 conn,
2094 req->flags2 & FLAGS2_DFS_PATHNAMES,
2095 fname,
2096 &smb_fname,
2097 &fname);
2098 if (!NT_STATUS_IS_OK(status)) {
2099 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2100 reply_botherror(req,
2101 NT_STATUS_PATH_NOT_COVERED,
2102 ERRSRV, ERRbadpath);
2103 goto out;
2105 reply_nterror(req, status);
2106 goto out;
2109 if (fattr & aVOLID) {
2110 DEBUG(0,("Attempt to create file (%s) with volid set - "
2111 "please report this\n", fname));
2114 if(req->cmd == SMBmknew) {
2115 /* We should fail if file exists. */
2116 create_disposition = FILE_CREATE;
2117 } else {
2118 /* Create if file doesn't exist, truncate if it does. */
2119 create_disposition = FILE_OVERWRITE_IF;
2122 status = SMB_VFS_CREATE_FILE(
2123 conn, /* conn */
2124 req, /* req */
2125 0, /* root_dir_fid */
2126 smb_fname, /* fname */
2127 access_mask, /* access_mask */
2128 share_mode, /* share_access */
2129 create_disposition, /* create_disposition*/
2130 create_options, /* create_options */
2131 fattr, /* file_attributes */
2132 oplock_request, /* oplock_request */
2133 0, /* allocation_size */
2134 NULL, /* sd */
2135 NULL, /* ea_list */
2136 &fsp, /* result */
2137 NULL); /* pinfo */
2139 if (!NT_STATUS_IS_OK(status)) {
2140 if (open_was_deferred(req->mid)) {
2141 /* We have re-scheduled this call. */
2142 goto out;
2144 reply_openerror(req, status);
2145 goto out;
2148 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2149 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &smb_fname->st,
2150 &ft, true);
2151 if (!NT_STATUS_IS_OK(status)) {
2152 END_PROFILE(SMBcreate);
2153 goto out;
2156 reply_outbuf(req, 1, 0);
2157 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2159 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2160 SCVAL(req->outbuf,smb_flg,
2161 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2164 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2165 SCVAL(req->outbuf,smb_flg,
2166 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2169 DEBUG( 2, ( "reply_mknew: file %s\n", fsp->fsp_name ) );
2170 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2171 fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) );
2173 out:
2174 TALLOC_FREE(smb_fname);
2175 END_PROFILE(SMBcreate);
2176 return;
2179 /****************************************************************************
2180 Reply to a create temporary file.
2181 ****************************************************************************/
2183 void reply_ctemp(struct smb_request *req)
2185 connection_struct *conn = req->conn;
2186 struct smb_filename *smb_fname = NULL;
2187 char *fname = NULL;
2188 uint32 fattr;
2189 files_struct *fsp;
2190 int oplock_request;
2191 int tmpfd;
2192 char *s;
2193 NTSTATUS status;
2194 TALLOC_CTX *ctx = talloc_tos();
2196 START_PROFILE(SMBctemp);
2198 if (req->wct < 3) {
2199 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2200 goto out;
2203 fattr = SVAL(req->vwv+0, 0);
2204 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2206 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2207 STR_TERMINATE, &status);
2208 if (!NT_STATUS_IS_OK(status)) {
2209 reply_nterror(req, status);
2210 goto out;
2212 if (*fname) {
2213 fname = talloc_asprintf(ctx,
2214 "%s/TMXXXXXX",
2215 fname);
2216 } else {
2217 fname = talloc_strdup(ctx, "TMXXXXXX");
2220 if (!fname) {
2221 reply_nterror(req, NT_STATUS_NO_MEMORY);
2222 goto out;
2225 status = filename_convert(ctx, conn,
2226 req->flags2 & FLAGS2_DFS_PATHNAMES,
2227 fname,
2228 &smb_fname,
2229 &fname);
2230 if (!NT_STATUS_IS_OK(status)) {
2231 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2232 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2233 ERRSRV, ERRbadpath);
2234 goto out;
2236 reply_nterror(req, status);
2237 goto out;
2240 tmpfd = mkstemp(smb_fname->base_name);
2241 if (tmpfd == -1) {
2242 reply_unixerror(req, ERRDOS, ERRnoaccess);
2243 goto out;
2246 SET_STAT_INVALID(smb_fname->st);
2247 SMB_VFS_STAT(conn, smb_fname->base_name, &smb_fname->st);
2249 /* We should fail if file does not exist. */
2250 status = SMB_VFS_CREATE_FILE(
2251 conn, /* conn */
2252 req, /* req */
2253 0, /* root_dir_fid */
2254 smb_fname, /* fname */
2255 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2256 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2257 FILE_OPEN, /* create_disposition*/
2258 0, /* create_options */
2259 fattr, /* file_attributes */
2260 oplock_request, /* oplock_request */
2261 0, /* allocation_size */
2262 NULL, /* sd */
2263 NULL, /* ea_list */
2264 &fsp, /* result */
2265 NULL); /* pinfo */
2267 /* close fd from mkstemp() */
2268 close(tmpfd);
2270 if (!NT_STATUS_IS_OK(status)) {
2271 if (open_was_deferred(req->mid)) {
2272 /* We have re-scheduled this call. */
2273 goto out;
2275 reply_openerror(req, status);
2276 goto out;
2279 reply_outbuf(req, 1, 0);
2280 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2282 /* the returned filename is relative to the directory */
2283 s = strrchr_m(fsp->fsp_name, '/');
2284 if (!s) {
2285 s = fsp->fsp_name;
2286 } else {
2287 s++;
2290 #if 0
2291 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2292 thing in the byte section. JRA */
2293 SSVALS(p, 0, -1); /* what is this? not in spec */
2294 #endif
2295 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2296 == -1) {
2297 reply_nterror(req, NT_STATUS_NO_MEMORY);
2298 goto out;
2301 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2302 SCVAL(req->outbuf, smb_flg,
2303 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2306 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2307 SCVAL(req->outbuf, smb_flg,
2308 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2311 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
2312 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
2313 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2314 out:
2315 TALLOC_FREE(smb_fname);
2316 END_PROFILE(SMBctemp);
2317 return;
2320 /*******************************************************************
2321 Check if a user is allowed to rename a file.
2322 ********************************************************************/
2324 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2325 uint16 dirtype, SMB_STRUCT_STAT *pst)
2327 uint32 fmode;
2329 if (!CAN_WRITE(conn)) {
2330 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2333 fmode = dos_mode(conn, fsp->fsp_name, pst);
2334 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2335 return NT_STATUS_NO_SUCH_FILE;
2338 if (S_ISDIR(pst->st_ex_mode)) {
2339 if (fsp->posix_open) {
2340 return NT_STATUS_OK;
2343 /* If no pathnames are open below this
2344 directory, allow the rename. */
2346 if (file_find_subpath(fsp)) {
2347 return NT_STATUS_ACCESS_DENIED;
2349 return NT_STATUS_OK;
2352 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2353 return NT_STATUS_OK;
2356 return NT_STATUS_ACCESS_DENIED;
2359 /*******************************************************************
2360 * unlink a file with all relevant access checks
2361 *******************************************************************/
2363 static NTSTATUS do_unlink(connection_struct *conn,
2364 struct smb_request *req,
2365 struct smb_filename *smb_fname,
2366 uint32 dirtype)
2368 char *fname = NULL;
2369 uint32 fattr;
2370 files_struct *fsp;
2371 uint32 dirtype_orig = dirtype;
2372 NTSTATUS status;
2374 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2376 if (!CAN_WRITE(conn)) {
2377 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2380 status = get_full_smb_filename(smb_fname, smb_fname, &fname);
2381 if (!NT_STATUS_IS_OK(status)) {
2382 return status;
2385 if (SMB_VFS_LSTAT(conn, fname, &smb_fname->st) != 0) {
2386 return map_nt_error_from_unix(errno);
2389 fattr = dos_mode(conn, fname, &smb_fname->st);
2391 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2392 dirtype = aDIR|aARCH|aRONLY;
2395 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2396 if (!dirtype) {
2397 return NT_STATUS_NO_SUCH_FILE;
2400 if (!dir_check_ftype(conn, fattr, dirtype)) {
2401 if (fattr & aDIR) {
2402 return NT_STATUS_FILE_IS_A_DIRECTORY;
2404 return NT_STATUS_NO_SUCH_FILE;
2407 if (dirtype_orig & 0x8000) {
2408 /* These will never be set for POSIX. */
2409 return NT_STATUS_NO_SUCH_FILE;
2412 #if 0
2413 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2414 return NT_STATUS_FILE_IS_A_DIRECTORY;
2417 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2418 return NT_STATUS_NO_SUCH_FILE;
2421 if (dirtype & 0xFF00) {
2422 /* These will never be set for POSIX. */
2423 return NT_STATUS_NO_SUCH_FILE;
2426 dirtype &= 0xFF;
2427 if (!dirtype) {
2428 return NT_STATUS_NO_SUCH_FILE;
2431 /* Can't delete a directory. */
2432 if (fattr & aDIR) {
2433 return NT_STATUS_FILE_IS_A_DIRECTORY;
2435 #endif
2437 #if 0 /* JRATEST */
2438 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2439 return NT_STATUS_OBJECT_NAME_INVALID;
2440 #endif /* JRATEST */
2442 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2444 On a Windows share, a file with read-only dosmode can be opened with
2445 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2446 fails with NT_STATUS_CANNOT_DELETE error.
2448 This semantic causes a problem that a user can not
2449 rename a file with read-only dosmode on a Samba share
2450 from a Windows command prompt (i.e. cmd.exe, but can rename
2451 from Windows Explorer).
2454 if (!lp_delete_readonly(SNUM(conn))) {
2455 if (fattr & aRONLY) {
2456 return NT_STATUS_CANNOT_DELETE;
2460 /* On open checks the open itself will check the share mode, so
2461 don't do it here as we'll get it wrong. */
2463 status = SMB_VFS_CREATE_FILE
2464 (conn, /* conn */
2465 req, /* req */
2466 0, /* root_dir_fid */
2467 smb_fname, /* fname */
2468 DELETE_ACCESS, /* access_mask */
2469 FILE_SHARE_NONE, /* share_access */
2470 FILE_OPEN, /* create_disposition*/
2471 FILE_NON_DIRECTORY_FILE, /* create_options */
2472 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2473 0, /* oplock_request */
2474 0, /* allocation_size */
2475 NULL, /* sd */
2476 NULL, /* ea_list */
2477 &fsp, /* result */
2478 NULL); /* pinfo */
2480 if (!NT_STATUS_IS_OK(status)) {
2481 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2482 nt_errstr(status)));
2483 return status;
2486 /* The set is across all open files on this dev/inode pair. */
2487 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2488 close_file(req, fsp, NORMAL_CLOSE);
2489 return NT_STATUS_ACCESS_DENIED;
2492 return close_file(req, fsp, NORMAL_CLOSE);
2495 /****************************************************************************
2496 The guts of the unlink command, split out so it may be called by the NT SMB
2497 code.
2498 ****************************************************************************/
2500 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2501 uint32 dirtype, const char *name_in, bool has_wild)
2503 struct smb_filename *smb_fname = NULL;
2504 char *fname_dir = NULL;
2505 char *fname_mask = NULL;
2506 int count=0;
2507 NTSTATUS status = NT_STATUS_OK;
2508 TALLOC_CTX *ctx = talloc_tos();
2510 status = unix_convert(ctx, conn, name_in, &smb_fname,
2511 has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
2512 if (!NT_STATUS_IS_OK(status)) {
2513 goto out;
2516 /* Split up the directory from the filename/mask. */
2517 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2518 &fname_dir, &fname_mask);
2519 if (!NT_STATUS_IS_OK(status)) {
2520 goto out;
2524 * We should only check the mangled cache
2525 * here if unix_convert failed. This means
2526 * that the path in 'mask' doesn't exist
2527 * on the file system and so we need to look
2528 * for a possible mangle. This patch from
2529 * Tine Smukavec <valentin.smukavec@hermes.si>.
2532 if (!VALID_STAT(smb_fname->st) &&
2533 mangle_is_mangled(fname_mask, conn->params)) {
2534 char *new_mask = NULL;
2535 mangle_lookup_name_from_8_3(ctx, fname_mask,
2536 &new_mask, conn->params);
2537 if (new_mask) {
2538 TALLOC_FREE(fname_mask);
2539 fname_mask = new_mask;
2543 if (!has_wild) {
2546 * Only one file needs to be unlinked. Append the mask back
2547 * onto the directory.
2549 TALLOC_FREE(smb_fname->base_name);
2550 smb_fname->base_name = talloc_asprintf(smb_fname,
2551 "%s/%s",
2552 fname_dir,
2553 fname_mask);
2554 if (!smb_fname->base_name) {
2555 status = NT_STATUS_NO_MEMORY;
2556 goto out;
2558 if (dirtype == 0) {
2559 dirtype = FILE_ATTRIBUTE_NORMAL;
2562 status = check_name(conn, smb_fname->base_name);
2563 if (!NT_STATUS_IS_OK(status)) {
2564 goto out;
2567 status = do_unlink(conn, req, smb_fname, dirtype);
2568 if (!NT_STATUS_IS_OK(status)) {
2569 goto out;
2572 count++;
2573 } else {
2574 struct smb_Dir *dir_hnd = NULL;
2575 long offset = 0;
2576 const char *dname;
2578 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2579 status = NT_STATUS_OBJECT_NAME_INVALID;
2580 goto out;
2583 if (strequal(fname_mask,"????????.???")) {
2584 TALLOC_FREE(fname_mask);
2585 fname_mask = talloc_strdup(ctx, "*");
2586 if (!fname_mask) {
2587 status = NT_STATUS_NO_MEMORY;
2588 goto out;
2592 status = check_name(conn, fname_dir);
2593 if (!NT_STATUS_IS_OK(status)) {
2594 goto out;
2597 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2598 dirtype);
2599 if (dir_hnd == NULL) {
2600 status = map_nt_error_from_unix(errno);
2601 goto out;
2604 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2605 the pattern matches against the long name, otherwise the short name
2606 We don't implement this yet XXXX
2609 status = NT_STATUS_NO_SUCH_FILE;
2611 while ((dname = ReadDirName(dir_hnd, &offset,
2612 &smb_fname->st))) {
2613 if (!is_visible_file(conn, fname_dir, dname,
2614 &smb_fname->st, true)) {
2615 continue;
2618 /* Quick check for "." and ".." */
2619 if (ISDOT(dname) || ISDOTDOT(dname)) {
2620 continue;
2623 if(!mask_match(dname, fname_mask,
2624 conn->case_sensitive)) {
2625 continue;
2628 TALLOC_FREE(smb_fname->base_name);
2629 smb_fname->base_name =
2630 talloc_asprintf(smb_fname, "%s/%s",
2631 fname_dir, dname);
2633 if (!smb_fname->base_name) {
2634 TALLOC_FREE(dir_hnd);
2635 status = NT_STATUS_NO_MEMORY;
2636 goto out;
2639 status = check_name(conn, smb_fname->base_name);
2640 if (!NT_STATUS_IS_OK(status)) {
2641 TALLOC_FREE(dir_hnd);
2642 goto out;
2645 status = do_unlink(conn, req, smb_fname, dirtype);
2646 if (!NT_STATUS_IS_OK(status)) {
2647 continue;
2650 count++;
2651 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2652 smb_fname->base_name));
2654 TALLOC_FREE(dir_hnd);
2657 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2658 status = map_nt_error_from_unix(errno);
2661 out:
2662 TALLOC_FREE(smb_fname);
2663 TALLOC_FREE(fname_dir);
2664 TALLOC_FREE(fname_mask);
2665 return status;
2668 /****************************************************************************
2669 Reply to a unlink
2670 ****************************************************************************/
2672 void reply_unlink(struct smb_request *req)
2674 connection_struct *conn = req->conn;
2675 char *name = NULL;
2676 uint32 dirtype;
2677 NTSTATUS status;
2678 bool path_contains_wcard = False;
2679 TALLOC_CTX *ctx = talloc_tos();
2681 START_PROFILE(SMBunlink);
2683 if (req->wct < 1) {
2684 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2685 END_PROFILE(SMBunlink);
2686 return;
2689 dirtype = SVAL(req->vwv+0, 0);
2691 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2692 STR_TERMINATE, &status,
2693 &path_contains_wcard);
2694 if (!NT_STATUS_IS_OK(status)) {
2695 reply_nterror(req, status);
2696 END_PROFILE(SMBunlink);
2697 return;
2700 status = resolve_dfspath_wcard(ctx, conn,
2701 req->flags2 & FLAGS2_DFS_PATHNAMES,
2702 name,
2703 &name,
2704 &path_contains_wcard);
2705 if (!NT_STATUS_IS_OK(status)) {
2706 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2707 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2708 ERRSRV, ERRbadpath);
2709 END_PROFILE(SMBunlink);
2710 return;
2712 reply_nterror(req, status);
2713 END_PROFILE(SMBunlink);
2714 return;
2717 DEBUG(3,("reply_unlink : %s\n",name));
2719 status = unlink_internals(conn, req, dirtype, name,
2720 path_contains_wcard);
2721 if (!NT_STATUS_IS_OK(status)) {
2722 if (open_was_deferred(req->mid)) {
2723 /* We have re-scheduled this call. */
2724 END_PROFILE(SMBunlink);
2725 return;
2727 reply_nterror(req, status);
2728 END_PROFILE(SMBunlink);
2729 return;
2732 reply_outbuf(req, 0, 0);
2733 END_PROFILE(SMBunlink);
2735 return;
2738 /****************************************************************************
2739 Fail for readbraw.
2740 ****************************************************************************/
2742 static void fail_readraw(void)
2744 const char *errstr = talloc_asprintf(talloc_tos(),
2745 "FAIL ! reply_readbraw: socket write fail (%s)",
2746 strerror(errno));
2747 if (!errstr) {
2748 errstr = "";
2750 exit_server_cleanly(errstr);
2753 /****************************************************************************
2754 Fake (read/write) sendfile. Returns -1 on read or write fail.
2755 ****************************************************************************/
2757 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2758 size_t nread)
2760 size_t bufsize;
2761 size_t tosend = nread;
2762 char *buf;
2764 if (nread == 0) {
2765 return 0;
2768 bufsize = MIN(nread, 65536);
2770 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2771 return -1;
2774 while (tosend > 0) {
2775 ssize_t ret;
2776 size_t cur_read;
2778 if (tosend > bufsize) {
2779 cur_read = bufsize;
2780 } else {
2781 cur_read = tosend;
2783 ret = read_file(fsp,buf,startpos,cur_read);
2784 if (ret == -1) {
2785 SAFE_FREE(buf);
2786 return -1;
2789 /* If we had a short read, fill with zeros. */
2790 if (ret < cur_read) {
2791 memset(buf + ret, '\0', cur_read - ret);
2794 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2795 SAFE_FREE(buf);
2796 return -1;
2798 tosend -= cur_read;
2799 startpos += cur_read;
2802 SAFE_FREE(buf);
2803 return (ssize_t)nread;
2806 #if defined(WITH_SENDFILE)
2807 /****************************************************************************
2808 Deal with the case of sendfile reading less bytes from the file than
2809 requested. Fill with zeros (all we can do).
2810 ****************************************************************************/
2812 static void sendfile_short_send(files_struct *fsp,
2813 ssize_t nread,
2814 size_t headersize,
2815 size_t smb_maxcnt)
2817 #define SHORT_SEND_BUFSIZE 1024
2818 if (nread < headersize) {
2819 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2820 "header for file %s (%s). Terminating\n",
2821 fsp->fsp_name, strerror(errno) ));
2822 exit_server_cleanly("sendfile_short_send failed");
2825 nread -= headersize;
2827 if (nread < smb_maxcnt) {
2828 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2829 if (!buf) {
2830 exit_server_cleanly("sendfile_short_send: "
2831 "malloc failed");
2834 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2835 "with zeros !\n", fsp->fsp_name));
2837 while (nread < smb_maxcnt) {
2839 * We asked for the real file size and told sendfile
2840 * to not go beyond the end of the file. But it can
2841 * happen that in between our fstat call and the
2842 * sendfile call the file was truncated. This is very
2843 * bad because we have already announced the larger
2844 * number of bytes to the client.
2846 * The best we can do now is to send 0-bytes, just as
2847 * a read from a hole in a sparse file would do.
2849 * This should happen rarely enough that I don't care
2850 * about efficiency here :-)
2852 size_t to_write;
2854 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2855 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2856 exit_server_cleanly("sendfile_short_send: "
2857 "write_data failed");
2859 nread += to_write;
2861 SAFE_FREE(buf);
2864 #endif /* defined WITH_SENDFILE */
2866 /****************************************************************************
2867 Return a readbraw error (4 bytes of zero).
2868 ****************************************************************************/
2870 static void reply_readbraw_error(void)
2872 char header[4];
2873 SIVAL(header,0,0);
2874 if (write_data(smbd_server_fd(),header,4) != 4) {
2875 fail_readraw();
2879 /****************************************************************************
2880 Use sendfile in readbraw.
2881 ****************************************************************************/
2883 static void send_file_readbraw(connection_struct *conn,
2884 struct smb_request *req,
2885 files_struct *fsp,
2886 SMB_OFF_T startpos,
2887 size_t nread,
2888 ssize_t mincount)
2890 char *outbuf = NULL;
2891 ssize_t ret=0;
2893 #if defined(WITH_SENDFILE)
2895 * We can only use sendfile on a non-chained packet
2896 * but we can use on a non-oplocked file. tridge proved this
2897 * on a train in Germany :-). JRA.
2898 * reply_readbraw has already checked the length.
2901 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2902 (fsp->wcp == NULL) &&
2903 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
2904 ssize_t sendfile_read = -1;
2905 char header[4];
2906 DATA_BLOB header_blob;
2908 _smb_setlen(header,nread);
2909 header_blob = data_blob_const(header, 4);
2911 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2912 &header_blob, startpos, nread)) == -1) {
2913 /* Returning ENOSYS means no data at all was sent.
2914 * Do this as a normal read. */
2915 if (errno == ENOSYS) {
2916 goto normal_readbraw;
2920 * Special hack for broken Linux with no working sendfile. If we
2921 * return EINTR we sent the header but not the rest of the data.
2922 * Fake this up by doing read/write calls.
2924 if (errno == EINTR) {
2925 /* Ensure we don't do this again. */
2926 set_use_sendfile(SNUM(conn), False);
2927 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2929 if (fake_sendfile(fsp, startpos, nread) == -1) {
2930 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2931 fsp->fsp_name, strerror(errno) ));
2932 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2934 return;
2937 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2938 fsp->fsp_name, strerror(errno) ));
2939 exit_server_cleanly("send_file_readbraw sendfile failed");
2940 } else if (sendfile_read == 0) {
2942 * Some sendfile implementations return 0 to indicate
2943 * that there was a short read, but nothing was
2944 * actually written to the socket. In this case,
2945 * fallback to the normal read path so the header gets
2946 * the correct byte count.
2948 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2949 "bytes falling back to the normal read: "
2950 "%s\n", fsp->fsp_name));
2951 goto normal_readbraw;
2954 /* Deal with possible short send. */
2955 if (sendfile_read != 4+nread) {
2956 sendfile_short_send(fsp, sendfile_read, 4, nread);
2958 return;
2961 normal_readbraw:
2962 #endif
2964 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2965 if (!outbuf) {
2966 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2967 (unsigned)(nread+4)));
2968 reply_readbraw_error();
2969 return;
2972 if (nread > 0) {
2973 ret = read_file(fsp,outbuf+4,startpos,nread);
2974 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2975 if (ret < mincount)
2976 ret = 0;
2977 #else
2978 if (ret < nread)
2979 ret = 0;
2980 #endif
2983 _smb_setlen(outbuf,ret);
2984 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2985 fail_readraw();
2987 TALLOC_FREE(outbuf);
2990 /****************************************************************************
2991 Reply to a readbraw (core+ protocol).
2992 ****************************************************************************/
2994 void reply_readbraw(struct smb_request *req)
2996 connection_struct *conn = req->conn;
2997 ssize_t maxcount,mincount;
2998 size_t nread = 0;
2999 SMB_OFF_T startpos;
3000 files_struct *fsp;
3001 struct lock_struct lock;
3002 SMB_STRUCT_STAT st;
3003 SMB_OFF_T size = 0;
3005 START_PROFILE(SMBreadbraw);
3007 if (srv_is_signing_active(smbd_server_conn) ||
3008 is_encrypted_packet(req->inbuf)) {
3009 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3010 "raw reads/writes are disallowed.");
3013 if (req->wct < 8) {
3014 reply_readbraw_error();
3015 END_PROFILE(SMBreadbraw);
3016 return;
3020 * Special check if an oplock break has been issued
3021 * and the readraw request croses on the wire, we must
3022 * return a zero length response here.
3025 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3028 * We have to do a check_fsp by hand here, as
3029 * we must always return 4 zero bytes on error,
3030 * not a NTSTATUS.
3033 if (!fsp || !conn || conn != fsp->conn ||
3034 req->vuid != fsp->vuid ||
3035 fsp->is_directory || fsp->fh->fd == -1) {
3037 * fsp could be NULL here so use the value from the packet. JRA.
3039 DEBUG(3,("reply_readbraw: fnum %d not valid "
3040 "- cache prime?\n",
3041 (int)SVAL(req->vwv+0, 0)));
3042 reply_readbraw_error();
3043 END_PROFILE(SMBreadbraw);
3044 return;
3047 /* Do a "by hand" version of CHECK_READ. */
3048 if (!(fsp->can_read ||
3049 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3050 (fsp->access_mask & FILE_EXECUTE)))) {
3051 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3052 (int)SVAL(req->vwv+0, 0)));
3053 reply_readbraw_error();
3054 END_PROFILE(SMBreadbraw);
3055 return;
3058 flush_write_cache(fsp, READRAW_FLUSH);
3060 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3061 if(req->wct == 10) {
3063 * This is a large offset (64 bit) read.
3065 #ifdef LARGE_SMB_OFF_T
3067 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3069 #else /* !LARGE_SMB_OFF_T */
3072 * Ensure we haven't been sent a >32 bit offset.
3075 if(IVAL(req->vwv+8, 0) != 0) {
3076 DEBUG(0,("reply_readbraw: large offset "
3077 "(%x << 32) used and we don't support "
3078 "64 bit offsets.\n",
3079 (unsigned int)IVAL(req->vwv+8, 0) ));
3080 reply_readbraw_error();
3081 END_PROFILE(SMBreadbraw);
3082 return;
3085 #endif /* LARGE_SMB_OFF_T */
3087 if(startpos < 0) {
3088 DEBUG(0,("reply_readbraw: negative 64 bit "
3089 "readraw offset (%.0f) !\n",
3090 (double)startpos ));
3091 reply_readbraw_error();
3092 END_PROFILE(SMBreadbraw);
3093 return;
3097 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3098 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3100 /* ensure we don't overrun the packet size */
3101 maxcount = MIN(65535,maxcount);
3103 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3104 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3105 &lock);
3107 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3108 reply_readbraw_error();
3109 END_PROFILE(SMBreadbraw);
3110 return;
3113 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
3114 size = st.st_ex_size;
3117 if (startpos >= size) {
3118 nread = 0;
3119 } else {
3120 nread = MIN(maxcount,(size - startpos));
3123 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3124 if (nread < mincount)
3125 nread = 0;
3126 #endif
3128 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3129 "min=%lu nread=%lu\n",
3130 fsp->fnum, (double)startpos,
3131 (unsigned long)maxcount,
3132 (unsigned long)mincount,
3133 (unsigned long)nread ) );
3135 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3137 DEBUG(5,("reply_readbraw finished\n"));
3139 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3141 END_PROFILE(SMBreadbraw);
3142 return;
3145 #undef DBGC_CLASS
3146 #define DBGC_CLASS DBGC_LOCKING
3148 /****************************************************************************
3149 Reply to a lockread (core+ protocol).
3150 ****************************************************************************/
3152 void reply_lockread(struct smb_request *req)
3154 connection_struct *conn = req->conn;
3155 ssize_t nread = -1;
3156 char *data;
3157 SMB_OFF_T startpos;
3158 size_t numtoread;
3159 NTSTATUS status;
3160 files_struct *fsp;
3161 struct byte_range_lock *br_lck = NULL;
3162 char *p = NULL;
3163 struct smbd_server_connection *sconn = smbd_server_conn;
3165 START_PROFILE(SMBlockread);
3167 if (req->wct < 5) {
3168 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3169 END_PROFILE(SMBlockread);
3170 return;
3173 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3175 if (!check_fsp(conn, req, fsp)) {
3176 END_PROFILE(SMBlockread);
3177 return;
3180 if (!CHECK_READ(fsp,req)) {
3181 reply_doserror(req, ERRDOS, ERRbadaccess);
3182 END_PROFILE(SMBlockread);
3183 return;
3186 numtoread = SVAL(req->vwv+1, 0);
3187 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3189 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3191 reply_outbuf(req, 5, numtoread + 3);
3193 data = smb_buf(req->outbuf) + 3;
3196 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3197 * protocol request that predates the read/write lock concept.
3198 * Thus instead of asking for a read lock here we need to ask
3199 * for a write lock. JRA.
3200 * Note that the requested lock size is unaffected by max_recv.
3203 br_lck = do_lock(smbd_messaging_context(),
3204 fsp,
3205 req->smbpid,
3206 (uint64_t)numtoread,
3207 (uint64_t)startpos,
3208 WRITE_LOCK,
3209 WINDOWS_LOCK,
3210 False, /* Non-blocking lock. */
3211 &status,
3212 NULL,
3213 NULL);
3214 TALLOC_FREE(br_lck);
3216 if (NT_STATUS_V(status)) {
3217 reply_nterror(req, status);
3218 END_PROFILE(SMBlockread);
3219 return;
3223 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3226 if (numtoread > sconn->smb1.negprot.max_recv) {
3227 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3228 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3229 (unsigned int)numtoread,
3230 (unsigned int)sconn->smb1.negprot.max_recv));
3231 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3233 nread = read_file(fsp,data,startpos,numtoread);
3235 if (nread < 0) {
3236 reply_unixerror(req, ERRDOS, ERRnoaccess);
3237 END_PROFILE(SMBlockread);
3238 return;
3241 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3243 SSVAL(req->outbuf,smb_vwv0,nread);
3244 SSVAL(req->outbuf,smb_vwv5,nread+3);
3245 p = smb_buf(req->outbuf);
3246 SCVAL(p,0,0); /* pad byte. */
3247 SSVAL(p,1,nread);
3249 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3250 fsp->fnum, (int)numtoread, (int)nread));
3252 END_PROFILE(SMBlockread);
3253 return;
3256 #undef DBGC_CLASS
3257 #define DBGC_CLASS DBGC_ALL
3259 /****************************************************************************
3260 Reply to a read.
3261 ****************************************************************************/
3263 void reply_read(struct smb_request *req)
3265 connection_struct *conn = req->conn;
3266 size_t numtoread;
3267 ssize_t nread = 0;
3268 char *data;
3269 SMB_OFF_T startpos;
3270 int outsize = 0;
3271 files_struct *fsp;
3272 struct lock_struct lock;
3273 struct smbd_server_connection *sconn = smbd_server_conn;
3275 START_PROFILE(SMBread);
3277 if (req->wct < 3) {
3278 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3279 END_PROFILE(SMBread);
3280 return;
3283 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3285 if (!check_fsp(conn, req, fsp)) {
3286 END_PROFILE(SMBread);
3287 return;
3290 if (!CHECK_READ(fsp,req)) {
3291 reply_doserror(req, ERRDOS, ERRbadaccess);
3292 END_PROFILE(SMBread);
3293 return;
3296 numtoread = SVAL(req->vwv+1, 0);
3297 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3299 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3302 * The requested read size cannot be greater than max_recv. JRA.
3304 if (numtoread > sconn->smb1.negprot.max_recv) {
3305 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3306 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3307 (unsigned int)numtoread,
3308 (unsigned int)sconn->smb1.negprot.max_recv));
3309 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3312 reply_outbuf(req, 5, numtoread+3);
3314 data = smb_buf(req->outbuf) + 3;
3316 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3317 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3318 &lock);
3320 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3321 reply_doserror(req, ERRDOS,ERRlock);
3322 END_PROFILE(SMBread);
3323 return;
3326 if (numtoread > 0)
3327 nread = read_file(fsp,data,startpos,numtoread);
3329 if (nread < 0) {
3330 reply_unixerror(req, ERRDOS,ERRnoaccess);
3331 goto strict_unlock;
3334 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3336 SSVAL(req->outbuf,smb_vwv0,nread);
3337 SSVAL(req->outbuf,smb_vwv5,nread+3);
3338 SCVAL(smb_buf(req->outbuf),0,1);
3339 SSVAL(smb_buf(req->outbuf),1,nread);
3341 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3342 fsp->fnum, (int)numtoread, (int)nread ) );
3344 strict_unlock:
3345 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3347 END_PROFILE(SMBread);
3348 return;
3351 /****************************************************************************
3352 Setup readX header.
3353 ****************************************************************************/
3355 static int setup_readX_header(struct smb_request *req, char *outbuf,
3356 size_t smb_maxcnt)
3358 int outsize;
3359 char *data;
3361 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3362 data = smb_buf(outbuf);
3364 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3366 SCVAL(outbuf,smb_vwv0,0xFF);
3367 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3368 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3369 SSVAL(outbuf,smb_vwv6,
3370 req_wct_ofs(req)
3371 + 1 /* the wct field */
3372 + 12 * sizeof(uint16_t) /* vwv */
3373 + 2); /* the buflen field */
3374 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3375 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3376 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3377 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3378 return outsize;
3381 /****************************************************************************
3382 Reply to a read and X - possibly using sendfile.
3383 ****************************************************************************/
3385 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3386 files_struct *fsp, SMB_OFF_T startpos,
3387 size_t smb_maxcnt)
3389 SMB_STRUCT_STAT sbuf;
3390 ssize_t nread = -1;
3391 struct lock_struct lock;
3393 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3394 reply_unixerror(req, ERRDOS, ERRnoaccess);
3395 return;
3398 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3399 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3400 &lock);
3402 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3403 reply_doserror(req, ERRDOS, ERRlock);
3404 return;
3407 if (!S_ISREG(sbuf.st_ex_mode) || (startpos > sbuf.st_ex_size)
3408 || (smb_maxcnt > (sbuf.st_ex_size - startpos))) {
3410 * We already know that we would do a short read, so don't
3411 * try the sendfile() path.
3413 goto nosendfile_read;
3416 #if defined(WITH_SENDFILE)
3418 * We can only use sendfile on a non-chained packet
3419 * but we can use on a non-oplocked file. tridge proved this
3420 * on a train in Germany :-). JRA.
3423 if (!req_is_in_chain(req) &&
3424 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3425 (fsp->wcp == NULL) &&
3426 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
3427 uint8 headerbuf[smb_size + 12 * 2];
3428 DATA_BLOB header;
3431 * Set up the packet header before send. We
3432 * assume here the sendfile will work (get the
3433 * correct amount of data).
3436 header = data_blob_const(headerbuf, sizeof(headerbuf));
3438 construct_reply_common_req(req, (char *)headerbuf);
3439 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3441 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3442 /* Returning ENOSYS means no data at all was sent.
3443 Do this as a normal read. */
3444 if (errno == ENOSYS) {
3445 goto normal_read;
3449 * Special hack for broken Linux with no working sendfile. If we
3450 * return EINTR we sent the header but not the rest of the data.
3451 * Fake this up by doing read/write calls.
3454 if (errno == EINTR) {
3455 /* Ensure we don't do this again. */
3456 set_use_sendfile(SNUM(conn), False);
3457 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3458 nread = fake_sendfile(fsp, startpos,
3459 smb_maxcnt);
3460 if (nread == -1) {
3461 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3462 fsp->fsp_name, strerror(errno) ));
3463 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3465 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3466 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3467 /* No outbuf here means successful sendfile. */
3468 goto strict_unlock;
3471 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3472 fsp->fsp_name, strerror(errno) ));
3473 exit_server_cleanly("send_file_readX sendfile failed");
3474 } else if (nread == 0) {
3476 * Some sendfile implementations return 0 to indicate
3477 * that there was a short read, but nothing was
3478 * actually written to the socket. In this case,
3479 * fallback to the normal read path so the header gets
3480 * the correct byte count.
3482 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3483 "falling back to the normal read: %s\n",
3484 fsp->fsp_name));
3485 goto normal_read;
3488 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3489 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3491 /* Deal with possible short send. */
3492 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3493 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3495 /* No outbuf here means successful sendfile. */
3496 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3497 SMB_PERFCOUNT_END(&req->pcd);
3498 goto strict_unlock;
3501 normal_read:
3503 #endif
3505 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3506 uint8 headerbuf[smb_size + 2*12];
3508 construct_reply_common_req(req, (char *)headerbuf);
3509 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3511 /* Send out the header. */
3512 if (write_data(smbd_server_fd(), (char *)headerbuf,
3513 sizeof(headerbuf)) != sizeof(headerbuf)) {
3514 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3515 fsp->fsp_name, strerror(errno) ));
3516 exit_server_cleanly("send_file_readX sendfile failed");
3518 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3519 if (nread == -1) {
3520 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3521 fsp->fsp_name, strerror(errno) ));
3522 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3524 goto strict_unlock;
3527 nosendfile_read:
3529 reply_outbuf(req, 12, smb_maxcnt);
3531 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3533 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3535 if (nread < 0) {
3536 reply_unixerror(req, ERRDOS, ERRnoaccess);
3537 return;
3540 setup_readX_header(req, (char *)req->outbuf, nread);
3542 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3543 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3545 chain_reply(req);
3546 return;
3548 strict_unlock:
3549 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3550 TALLOC_FREE(req->outbuf);
3551 return;
3554 /****************************************************************************
3555 Reply to a read and X.
3556 ****************************************************************************/
3558 void reply_read_and_X(struct smb_request *req)
3560 connection_struct *conn = req->conn;
3561 files_struct *fsp;
3562 SMB_OFF_T startpos;
3563 size_t smb_maxcnt;
3564 bool big_readX = False;
3565 #if 0
3566 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3567 #endif
3569 START_PROFILE(SMBreadX);
3571 if ((req->wct != 10) && (req->wct != 12)) {
3572 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3573 return;
3576 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3577 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3578 smb_maxcnt = SVAL(req->vwv+5, 0);
3580 /* If it's an IPC, pass off the pipe handler. */
3581 if (IS_IPC(conn)) {
3582 reply_pipe_read_and_X(req);
3583 END_PROFILE(SMBreadX);
3584 return;
3587 if (!check_fsp(conn, req, fsp)) {
3588 END_PROFILE(SMBreadX);
3589 return;
3592 if (!CHECK_READ(fsp,req)) {
3593 reply_doserror(req, ERRDOS,ERRbadaccess);
3594 END_PROFILE(SMBreadX);
3595 return;
3598 if (global_client_caps & CAP_LARGE_READX) {
3599 size_t upper_size = SVAL(req->vwv+7, 0);
3600 smb_maxcnt |= (upper_size<<16);
3601 if (upper_size > 1) {
3602 /* Can't do this on a chained packet. */
3603 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3604 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3605 END_PROFILE(SMBreadX);
3606 return;
3608 /* We currently don't do this on signed or sealed data. */
3609 if (srv_is_signing_active(smbd_server_conn) ||
3610 is_encrypted_packet(req->inbuf)) {
3611 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3612 END_PROFILE(SMBreadX);
3613 return;
3615 /* Is there room in the reply for this data ? */
3616 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3617 reply_nterror(req,
3618 NT_STATUS_INVALID_PARAMETER);
3619 END_PROFILE(SMBreadX);
3620 return;
3622 big_readX = True;
3626 if (req->wct == 12) {
3627 #ifdef LARGE_SMB_OFF_T
3629 * This is a large offset (64 bit) read.
3631 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3633 #else /* !LARGE_SMB_OFF_T */
3636 * Ensure we haven't been sent a >32 bit offset.
3639 if(IVAL(req->vwv+10, 0) != 0) {
3640 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3641 "used and we don't support 64 bit offsets.\n",
3642 (unsigned int)IVAL(req->vwv+10, 0) ));
3643 END_PROFILE(SMBreadX);
3644 reply_doserror(req, ERRDOS, ERRbadaccess);
3645 return;
3648 #endif /* LARGE_SMB_OFF_T */
3652 if (!big_readX &&
3653 schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3654 goto out;
3657 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3659 out:
3660 END_PROFILE(SMBreadX);
3661 return;
3664 /****************************************************************************
3665 Error replies to writebraw must have smb_wct == 1. Fix this up.
3666 ****************************************************************************/
3668 void error_to_writebrawerr(struct smb_request *req)
3670 uint8 *old_outbuf = req->outbuf;
3672 reply_outbuf(req, 1, 0);
3674 memcpy(req->outbuf, old_outbuf, smb_size);
3675 TALLOC_FREE(old_outbuf);
3678 /****************************************************************************
3679 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3680 ****************************************************************************/
3682 void reply_writebraw(struct smb_request *req)
3684 connection_struct *conn = req->conn;
3685 char *buf = NULL;
3686 ssize_t nwritten=0;
3687 ssize_t total_written=0;
3688 size_t numtowrite=0;
3689 size_t tcount;
3690 SMB_OFF_T startpos;
3691 char *data=NULL;
3692 bool write_through;
3693 files_struct *fsp;
3694 struct lock_struct lock;
3695 NTSTATUS status;
3697 START_PROFILE(SMBwritebraw);
3700 * If we ever reply with an error, it must have the SMB command
3701 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3702 * we're finished.
3704 SCVAL(req->inbuf,smb_com,SMBwritec);
3706 if (srv_is_signing_active(smbd_server_conn)) {
3707 END_PROFILE(SMBwritebraw);
3708 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3709 "raw reads/writes are disallowed.");
3712 if (req->wct < 12) {
3713 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3714 error_to_writebrawerr(req);
3715 END_PROFILE(SMBwritebraw);
3716 return;
3719 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3720 if (!check_fsp(conn, req, fsp)) {
3721 error_to_writebrawerr(req);
3722 END_PROFILE(SMBwritebraw);
3723 return;
3726 if (!CHECK_WRITE(fsp)) {
3727 reply_doserror(req, ERRDOS, ERRbadaccess);
3728 error_to_writebrawerr(req);
3729 END_PROFILE(SMBwritebraw);
3730 return;
3733 tcount = IVAL(req->vwv+1, 0);
3734 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3735 write_through = BITSETW(req->vwv+7,0);
3737 /* We have to deal with slightly different formats depending
3738 on whether we are using the core+ or lanman1.0 protocol */
3740 if(Protocol <= PROTOCOL_COREPLUS) {
3741 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3742 data = smb_buf(req->inbuf);
3743 } else {
3744 numtowrite = SVAL(req->vwv+10, 0);
3745 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3748 /* Ensure we don't write bytes past the end of this packet. */
3749 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3750 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3751 error_to_writebrawerr(req);
3752 END_PROFILE(SMBwritebraw);
3753 return;
3756 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3757 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3758 &lock);
3760 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3761 reply_doserror(req, ERRDOS, ERRlock);
3762 error_to_writebrawerr(req);
3763 END_PROFILE(SMBwritebraw);
3764 return;
3767 if (numtowrite>0) {
3768 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3771 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3772 "wrote=%d sync=%d\n",
3773 fsp->fnum, (double)startpos, (int)numtowrite,
3774 (int)nwritten, (int)write_through));
3776 if (nwritten < (ssize_t)numtowrite) {
3777 reply_unixerror(req, ERRHRD, ERRdiskfull);
3778 error_to_writebrawerr(req);
3779 goto strict_unlock;
3782 total_written = nwritten;
3784 /* Allocate a buffer of 64k + length. */
3785 buf = TALLOC_ARRAY(NULL, char, 65540);
3786 if (!buf) {
3787 reply_doserror(req, ERRDOS, ERRnomem);
3788 error_to_writebrawerr(req);
3789 goto strict_unlock;
3792 /* Return a SMBwritebraw message to the redirector to tell
3793 * it to send more bytes */
3795 memcpy(buf, req->inbuf, smb_size);
3796 srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3797 SCVAL(buf,smb_com,SMBwritebraw);
3798 SSVALS(buf,smb_vwv0,0xFFFF);
3799 show_msg(buf);
3800 if (!srv_send_smb(smbd_server_fd(),
3801 buf,
3802 false, 0, /* no signing */
3803 IS_CONN_ENCRYPTED(conn),
3804 &req->pcd)) {
3805 exit_server_cleanly("reply_writebraw: srv_send_smb "
3806 "failed.");
3809 /* Now read the raw data into the buffer and write it */
3810 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3811 &numtowrite);
3812 if (!NT_STATUS_IS_OK(status)) {
3813 exit_server_cleanly("secondary writebraw failed");
3816 /* Set up outbuf to return the correct size */
3817 reply_outbuf(req, 1, 0);
3819 if (numtowrite != 0) {
3821 if (numtowrite > 0xFFFF) {
3822 DEBUG(0,("reply_writebraw: Oversize secondary write "
3823 "raw requested (%u). Terminating\n",
3824 (unsigned int)numtowrite ));
3825 exit_server_cleanly("secondary writebraw failed");
3828 if (tcount > nwritten+numtowrite) {
3829 DEBUG(3,("reply_writebraw: Client overestimated the "
3830 "write %d %d %d\n",
3831 (int)tcount,(int)nwritten,(int)numtowrite));
3834 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3836 if (!NT_STATUS_IS_OK(status)) {
3837 DEBUG(0,("reply_writebraw: Oversize secondary write "
3838 "raw read failed (%s). Terminating\n",
3839 nt_errstr(status)));
3840 exit_server_cleanly("secondary writebraw failed");
3843 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3844 if (nwritten == -1) {
3845 TALLOC_FREE(buf);
3846 reply_unixerror(req, ERRHRD, ERRdiskfull);
3847 error_to_writebrawerr(req);
3848 goto strict_unlock;
3851 if (nwritten < (ssize_t)numtowrite) {
3852 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3853 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3856 if (nwritten > 0) {
3857 total_written += nwritten;
3861 TALLOC_FREE(buf);
3862 SSVAL(req->outbuf,smb_vwv0,total_written);
3864 status = sync_file(conn, fsp, write_through);
3865 if (!NT_STATUS_IS_OK(status)) {
3866 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3867 fsp->fsp_name, nt_errstr(status) ));
3868 reply_nterror(req, status);
3869 error_to_writebrawerr(req);
3870 goto strict_unlock;
3873 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3874 "wrote=%d\n",
3875 fsp->fnum, (double)startpos, (int)numtowrite,
3876 (int)total_written));
3878 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3880 /* We won't return a status if write through is not selected - this
3881 * follows what WfWg does */
3882 END_PROFILE(SMBwritebraw);
3884 if (!write_through && total_written==tcount) {
3886 #if RABBIT_PELLET_FIX
3888 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3889 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3890 * JRA.
3892 if (!send_keepalive(smbd_server_fd())) {
3893 exit_server_cleanly("reply_writebraw: send of "
3894 "keepalive failed");
3896 #endif
3897 TALLOC_FREE(req->outbuf);
3899 return;
3901 strict_unlock:
3902 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3904 END_PROFILE(SMBwritebraw);
3905 return;
3908 #undef DBGC_CLASS
3909 #define DBGC_CLASS DBGC_LOCKING
3911 /****************************************************************************
3912 Reply to a writeunlock (core+).
3913 ****************************************************************************/
3915 void reply_writeunlock(struct smb_request *req)
3917 connection_struct *conn = req->conn;
3918 ssize_t nwritten = -1;
3919 size_t numtowrite;
3920 SMB_OFF_T startpos;
3921 const char *data;
3922 NTSTATUS status = NT_STATUS_OK;
3923 files_struct *fsp;
3924 struct lock_struct lock;
3926 START_PROFILE(SMBwriteunlock);
3928 if (req->wct < 5) {
3929 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3930 END_PROFILE(SMBwriteunlock);
3931 return;
3934 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3936 if (!check_fsp(conn, req, fsp)) {
3937 END_PROFILE(SMBwriteunlock);
3938 return;
3941 if (!CHECK_WRITE(fsp)) {
3942 reply_doserror(req, ERRDOS,ERRbadaccess);
3943 END_PROFILE(SMBwriteunlock);
3944 return;
3947 numtowrite = SVAL(req->vwv+1, 0);
3948 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3949 data = (const char *)req->buf + 3;
3951 if (numtowrite) {
3952 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3953 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
3954 &lock);
3956 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3957 reply_doserror(req, ERRDOS, ERRlock);
3958 END_PROFILE(SMBwriteunlock);
3959 return;
3963 /* The special X/Open SMB protocol handling of
3964 zero length writes is *NOT* done for
3965 this call */
3966 if(numtowrite == 0) {
3967 nwritten = 0;
3968 } else {
3969 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3972 status = sync_file(conn, fsp, False /* write through */);
3973 if (!NT_STATUS_IS_OK(status)) {
3974 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3975 fsp->fsp_name, nt_errstr(status) ));
3976 reply_nterror(req, status);
3977 goto strict_unlock;
3980 if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
3981 reply_unixerror(req, ERRHRD, ERRdiskfull);
3982 goto strict_unlock;
3985 if (numtowrite) {
3986 status = do_unlock(smbd_messaging_context(),
3987 fsp,
3988 req->smbpid,
3989 (uint64_t)numtowrite,
3990 (uint64_t)startpos,
3991 WINDOWS_LOCK);
3993 if (NT_STATUS_V(status)) {
3994 reply_nterror(req, status);
3995 goto strict_unlock;
3999 reply_outbuf(req, 1, 0);
4001 SSVAL(req->outbuf,smb_vwv0,nwritten);
4003 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4004 fsp->fnum, (int)numtowrite, (int)nwritten));
4006 strict_unlock:
4007 if (numtowrite) {
4008 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4011 END_PROFILE(SMBwriteunlock);
4012 return;
4015 #undef DBGC_CLASS
4016 #define DBGC_CLASS DBGC_ALL
4018 /****************************************************************************
4019 Reply to a write.
4020 ****************************************************************************/
4022 void reply_write(struct smb_request *req)
4024 connection_struct *conn = req->conn;
4025 size_t numtowrite;
4026 ssize_t nwritten = -1;
4027 SMB_OFF_T startpos;
4028 const char *data;
4029 files_struct *fsp;
4030 struct lock_struct lock;
4031 NTSTATUS status;
4033 START_PROFILE(SMBwrite);
4035 if (req->wct < 5) {
4036 END_PROFILE(SMBwrite);
4037 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4038 return;
4041 /* If it's an IPC, pass off the pipe handler. */
4042 if (IS_IPC(conn)) {
4043 reply_pipe_write(req);
4044 END_PROFILE(SMBwrite);
4045 return;
4048 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4050 if (!check_fsp(conn, req, fsp)) {
4051 END_PROFILE(SMBwrite);
4052 return;
4055 if (!CHECK_WRITE(fsp)) {
4056 reply_doserror(req, ERRDOS, ERRbadaccess);
4057 END_PROFILE(SMBwrite);
4058 return;
4061 numtowrite = SVAL(req->vwv+1, 0);
4062 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4063 data = (const char *)req->buf + 3;
4065 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4066 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4067 &lock);
4069 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4070 reply_doserror(req, ERRDOS, ERRlock);
4071 END_PROFILE(SMBwrite);
4072 return;
4076 * X/Open SMB protocol says that if smb_vwv1 is
4077 * zero then the file size should be extended or
4078 * truncated to the size given in smb_vwv[2-3].
4081 if(numtowrite == 0) {
4083 * This is actually an allocate call, and set EOF. JRA.
4085 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4086 if (nwritten < 0) {
4087 reply_nterror(req, NT_STATUS_DISK_FULL);
4088 goto strict_unlock;
4090 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4091 if (nwritten < 0) {
4092 reply_nterror(req, NT_STATUS_DISK_FULL);
4093 goto strict_unlock;
4095 trigger_write_time_update_immediate(fsp);
4096 } else {
4097 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4100 status = sync_file(conn, fsp, False);
4101 if (!NT_STATUS_IS_OK(status)) {
4102 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4103 fsp->fsp_name, nt_errstr(status) ));
4104 reply_nterror(req, status);
4105 goto strict_unlock;
4108 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4109 reply_unixerror(req, ERRHRD, ERRdiskfull);
4110 goto strict_unlock;
4113 reply_outbuf(req, 1, 0);
4115 SSVAL(req->outbuf,smb_vwv0,nwritten);
4117 if (nwritten < (ssize_t)numtowrite) {
4118 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4119 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4122 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4124 strict_unlock:
4125 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4127 END_PROFILE(SMBwrite);
4128 return;
4131 /****************************************************************************
4132 Ensure a buffer is a valid writeX for recvfile purposes.
4133 ****************************************************************************/
4135 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4136 (2*14) + /* word count (including bcc) */ \
4137 1 /* pad byte */)
4139 bool is_valid_writeX_buffer(const uint8_t *inbuf)
4141 size_t numtowrite;
4142 connection_struct *conn = NULL;
4143 unsigned int doff = 0;
4144 size_t len = smb_len_large(inbuf);
4145 struct smbd_server_connection *sconn = smbd_server_conn;
4147 if (is_encrypted_packet(inbuf)) {
4148 /* Can't do this on encrypted
4149 * connections. */
4150 return false;
4153 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4154 return false;
4157 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4158 CVAL(inbuf,smb_wct) != 14) {
4159 DEBUG(10,("is_valid_writeX_buffer: chained or "
4160 "invalid word length.\n"));
4161 return false;
4164 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4165 if (conn == NULL) {
4166 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4167 return false;
4169 if (IS_IPC(conn)) {
4170 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4171 return false;
4173 if (IS_PRINT(conn)) {
4174 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4175 return false;
4177 doff = SVAL(inbuf,smb_vwv11);
4179 numtowrite = SVAL(inbuf,smb_vwv10);
4181 if (len > doff && len - doff > 0xFFFF) {
4182 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4185 if (numtowrite == 0) {
4186 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4187 return false;
4190 /* Ensure the sizes match up. */
4191 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4192 /* no pad byte...old smbclient :-( */
4193 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4194 (unsigned int)doff,
4195 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4196 return false;
4199 if (len - doff != numtowrite) {
4200 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4201 "len = %u, doff = %u, numtowrite = %u\n",
4202 (unsigned int)len,
4203 (unsigned int)doff,
4204 (unsigned int)numtowrite ));
4205 return false;
4208 DEBUG(10,("is_valid_writeX_buffer: true "
4209 "len = %u, doff = %u, numtowrite = %u\n",
4210 (unsigned int)len,
4211 (unsigned int)doff,
4212 (unsigned int)numtowrite ));
4214 return true;
4217 /****************************************************************************
4218 Reply to a write and X.
4219 ****************************************************************************/
4221 void reply_write_and_X(struct smb_request *req)
4223 connection_struct *conn = req->conn;
4224 files_struct *fsp;
4225 struct lock_struct lock;
4226 SMB_OFF_T startpos;
4227 size_t numtowrite;
4228 bool write_through;
4229 ssize_t nwritten;
4230 unsigned int smb_doff;
4231 unsigned int smblen;
4232 char *data;
4233 NTSTATUS status;
4235 START_PROFILE(SMBwriteX);
4237 if ((req->wct != 12) && (req->wct != 14)) {
4238 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4239 END_PROFILE(SMBwriteX);
4240 return;
4243 numtowrite = SVAL(req->vwv+10, 0);
4244 smb_doff = SVAL(req->vwv+11, 0);
4245 smblen = smb_len(req->inbuf);
4247 if (req->unread_bytes > 0xFFFF ||
4248 (smblen > smb_doff &&
4249 smblen - smb_doff > 0xFFFF)) {
4250 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4253 if (req->unread_bytes) {
4254 /* Can't do a recvfile write on IPC$ */
4255 if (IS_IPC(conn)) {
4256 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4257 END_PROFILE(SMBwriteX);
4258 return;
4260 if (numtowrite != req->unread_bytes) {
4261 reply_doserror(req, ERRDOS, ERRbadmem);
4262 END_PROFILE(SMBwriteX);
4263 return;
4265 } else {
4266 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4267 smb_doff + numtowrite > smblen) {
4268 reply_doserror(req, ERRDOS, ERRbadmem);
4269 END_PROFILE(SMBwriteX);
4270 return;
4274 /* If it's an IPC, pass off the pipe handler. */
4275 if (IS_IPC(conn)) {
4276 if (req->unread_bytes) {
4277 reply_doserror(req, ERRDOS, ERRbadmem);
4278 END_PROFILE(SMBwriteX);
4279 return;
4281 reply_pipe_write_and_X(req);
4282 END_PROFILE(SMBwriteX);
4283 return;
4286 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4287 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4288 write_through = BITSETW(req->vwv+7,0);
4290 if (!check_fsp(conn, req, fsp)) {
4291 END_PROFILE(SMBwriteX);
4292 return;
4295 if (!CHECK_WRITE(fsp)) {
4296 reply_doserror(req, ERRDOS, ERRbadaccess);
4297 END_PROFILE(SMBwriteX);
4298 return;
4301 data = smb_base(req->inbuf) + smb_doff;
4303 if(req->wct == 14) {
4304 #ifdef LARGE_SMB_OFF_T
4306 * This is a large offset (64 bit) write.
4308 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4310 #else /* !LARGE_SMB_OFF_T */
4313 * Ensure we haven't been sent a >32 bit offset.
4316 if(IVAL(req->vwv+12, 0) != 0) {
4317 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4318 "used and we don't support 64 bit offsets.\n",
4319 (unsigned int)IVAL(req->vwv+12, 0) ));
4320 reply_doserror(req, ERRDOS, ERRbadaccess);
4321 END_PROFILE(SMBwriteX);
4322 return;
4325 #endif /* LARGE_SMB_OFF_T */
4328 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4329 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4330 &lock);
4332 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4333 reply_doserror(req, ERRDOS, ERRlock);
4334 END_PROFILE(SMBwriteX);
4335 return;
4338 /* X/Open SMB protocol says that, unlike SMBwrite
4339 if the length is zero then NO truncation is
4340 done, just a write of zero. To truncate a file,
4341 use SMBwrite. */
4343 if(numtowrite == 0) {
4344 nwritten = 0;
4345 } else {
4347 if ((req->unread_bytes == 0) &&
4348 schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4349 numtowrite)) {
4350 goto strict_unlock;
4353 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4356 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4357 reply_unixerror(req, ERRHRD, ERRdiskfull);
4358 goto strict_unlock;
4361 reply_outbuf(req, 6, 0);
4362 SSVAL(req->outbuf,smb_vwv2,nwritten);
4363 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4365 if (nwritten < (ssize_t)numtowrite) {
4366 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4367 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4370 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4371 fsp->fnum, (int)numtowrite, (int)nwritten));
4373 status = sync_file(conn, fsp, write_through);
4374 if (!NT_STATUS_IS_OK(status)) {
4375 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4376 fsp->fsp_name, nt_errstr(status) ));
4377 reply_nterror(req, status);
4378 goto strict_unlock;
4381 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4383 END_PROFILE(SMBwriteX);
4384 chain_reply(req);
4385 return;
4387 strict_unlock:
4388 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4390 END_PROFILE(SMBwriteX);
4391 return;
4394 /****************************************************************************
4395 Reply to a lseek.
4396 ****************************************************************************/
4398 void reply_lseek(struct smb_request *req)
4400 connection_struct *conn = req->conn;
4401 SMB_OFF_T startpos;
4402 SMB_OFF_T res= -1;
4403 int mode,umode;
4404 files_struct *fsp;
4406 START_PROFILE(SMBlseek);
4408 if (req->wct < 4) {
4409 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4410 END_PROFILE(SMBlseek);
4411 return;
4414 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4416 if (!check_fsp(conn, req, fsp)) {
4417 return;
4420 flush_write_cache(fsp, SEEK_FLUSH);
4422 mode = SVAL(req->vwv+1, 0) & 3;
4423 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4424 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4426 switch (mode) {
4427 case 0:
4428 umode = SEEK_SET;
4429 res = startpos;
4430 break;
4431 case 1:
4432 umode = SEEK_CUR;
4433 res = fsp->fh->pos + startpos;
4434 break;
4435 case 2:
4436 umode = SEEK_END;
4437 break;
4438 default:
4439 umode = SEEK_SET;
4440 res = startpos;
4441 break;
4444 if (umode == SEEK_END) {
4445 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4446 if(errno == EINVAL) {
4447 SMB_OFF_T current_pos = startpos;
4448 SMB_STRUCT_STAT sbuf;
4450 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4451 reply_unixerror(req, ERRDOS,
4452 ERRnoaccess);
4453 END_PROFILE(SMBlseek);
4454 return;
4457 current_pos += sbuf.st_ex_size;
4458 if(current_pos < 0)
4459 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4463 if(res == -1) {
4464 reply_unixerror(req, ERRDOS, ERRnoaccess);
4465 END_PROFILE(SMBlseek);
4466 return;
4470 fsp->fh->pos = res;
4472 reply_outbuf(req, 2, 0);
4473 SIVAL(req->outbuf,smb_vwv0,res);
4475 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4476 fsp->fnum, (double)startpos, (double)res, mode));
4478 END_PROFILE(SMBlseek);
4479 return;
4482 /****************************************************************************
4483 Reply to a flush.
4484 ****************************************************************************/
4486 void reply_flush(struct smb_request *req)
4488 connection_struct *conn = req->conn;
4489 uint16 fnum;
4490 files_struct *fsp;
4492 START_PROFILE(SMBflush);
4494 if (req->wct < 1) {
4495 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4496 return;
4499 fnum = SVAL(req->vwv+0, 0);
4500 fsp = file_fsp(req, fnum);
4502 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4503 return;
4506 if (!fsp) {
4507 file_sync_all(conn);
4508 } else {
4509 NTSTATUS status = sync_file(conn, fsp, True);
4510 if (!NT_STATUS_IS_OK(status)) {
4511 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4512 fsp->fsp_name, nt_errstr(status) ));
4513 reply_nterror(req, status);
4514 END_PROFILE(SMBflush);
4515 return;
4519 reply_outbuf(req, 0, 0);
4521 DEBUG(3,("flush\n"));
4522 END_PROFILE(SMBflush);
4523 return;
4526 /****************************************************************************
4527 Reply to a exit.
4528 conn POINTER CAN BE NULL HERE !
4529 ****************************************************************************/
4531 void reply_exit(struct smb_request *req)
4533 START_PROFILE(SMBexit);
4535 file_close_pid(req->smbpid, req->vuid);
4537 reply_outbuf(req, 0, 0);
4539 DEBUG(3,("exit\n"));
4541 END_PROFILE(SMBexit);
4542 return;
4545 /****************************************************************************
4546 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4547 ****************************************************************************/
4549 void reply_close(struct smb_request *req)
4551 connection_struct *conn = req->conn;
4552 NTSTATUS status = NT_STATUS_OK;
4553 files_struct *fsp = NULL;
4554 START_PROFILE(SMBclose);
4556 if (req->wct < 3) {
4557 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4558 END_PROFILE(SMBclose);
4559 return;
4562 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4565 * We can only use check_fsp if we know it's not a directory.
4568 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4569 reply_doserror(req, ERRDOS, ERRbadfid);
4570 END_PROFILE(SMBclose);
4571 return;
4574 if(fsp->is_directory) {
4576 * Special case - close NT SMB directory handle.
4578 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4579 status = close_file(req, fsp, NORMAL_CLOSE);
4580 } else {
4581 time_t t;
4583 * Close ordinary file.
4586 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4587 fsp->fh->fd, fsp->fnum,
4588 conn->num_files_open));
4591 * Take care of any time sent in the close.
4594 t = srv_make_unix_date3(req->vwv+1);
4595 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4598 * close_file() returns the unix errno if an error
4599 * was detected on close - normally this is due to
4600 * a disk full error. If not then it was probably an I/O error.
4603 status = close_file(req, fsp, NORMAL_CLOSE);
4606 if (!NT_STATUS_IS_OK(status)) {
4607 reply_nterror(req, status);
4608 END_PROFILE(SMBclose);
4609 return;
4612 reply_outbuf(req, 0, 0);
4613 END_PROFILE(SMBclose);
4614 return;
4617 /****************************************************************************
4618 Reply to a writeclose (Core+ protocol).
4619 ****************************************************************************/
4621 void reply_writeclose(struct smb_request *req)
4623 connection_struct *conn = req->conn;
4624 size_t numtowrite;
4625 ssize_t nwritten = -1;
4626 NTSTATUS close_status = NT_STATUS_OK;
4627 SMB_OFF_T startpos;
4628 const char *data;
4629 struct timespec mtime;
4630 files_struct *fsp;
4631 struct lock_struct lock;
4633 START_PROFILE(SMBwriteclose);
4635 if (req->wct < 6) {
4636 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4637 END_PROFILE(SMBwriteclose);
4638 return;
4641 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4643 if (!check_fsp(conn, req, fsp)) {
4644 END_PROFILE(SMBwriteclose);
4645 return;
4647 if (!CHECK_WRITE(fsp)) {
4648 reply_doserror(req, ERRDOS,ERRbadaccess);
4649 END_PROFILE(SMBwriteclose);
4650 return;
4653 numtowrite = SVAL(req->vwv+1, 0);
4654 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4655 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4656 data = (const char *)req->buf + 1;
4658 if (numtowrite) {
4659 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4660 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4661 &lock);
4663 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4664 reply_doserror(req, ERRDOS,ERRlock);
4665 END_PROFILE(SMBwriteclose);
4666 return;
4670 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4672 set_close_write_time(fsp, mtime);
4675 * More insanity. W2K only closes the file if writelen > 0.
4676 * JRA.
4679 if (numtowrite) {
4680 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4681 fsp->fsp_name ));
4682 close_status = close_file(req, fsp, NORMAL_CLOSE);
4685 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4686 fsp->fnum, (int)numtowrite, (int)nwritten,
4687 conn->num_files_open));
4689 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4690 reply_doserror(req, ERRHRD, ERRdiskfull);
4691 goto strict_unlock;
4694 if(!NT_STATUS_IS_OK(close_status)) {
4695 reply_nterror(req, close_status);
4696 goto strict_unlock;
4699 reply_outbuf(req, 1, 0);
4701 SSVAL(req->outbuf,smb_vwv0,nwritten);
4703 strict_unlock:
4704 if (numtowrite) {
4705 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4708 END_PROFILE(SMBwriteclose);
4709 return;
4712 #undef DBGC_CLASS
4713 #define DBGC_CLASS DBGC_LOCKING
4715 /****************************************************************************
4716 Reply to a lock.
4717 ****************************************************************************/
4719 void reply_lock(struct smb_request *req)
4721 connection_struct *conn = req->conn;
4722 uint64_t count,offset;
4723 NTSTATUS status;
4724 files_struct *fsp;
4725 struct byte_range_lock *br_lck = NULL;
4727 START_PROFILE(SMBlock);
4729 if (req->wct < 5) {
4730 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4731 END_PROFILE(SMBlock);
4732 return;
4735 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4737 if (!check_fsp(conn, req, fsp)) {
4738 END_PROFILE(SMBlock);
4739 return;
4742 count = (uint64_t)IVAL(req->vwv+1, 0);
4743 offset = (uint64_t)IVAL(req->vwv+3, 0);
4745 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4746 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4748 br_lck = do_lock(smbd_messaging_context(),
4749 fsp,
4750 req->smbpid,
4751 count,
4752 offset,
4753 WRITE_LOCK,
4754 WINDOWS_LOCK,
4755 False, /* Non-blocking lock. */
4756 &status,
4757 NULL,
4758 NULL);
4760 TALLOC_FREE(br_lck);
4762 if (NT_STATUS_V(status)) {
4763 reply_nterror(req, status);
4764 END_PROFILE(SMBlock);
4765 return;
4768 reply_outbuf(req, 0, 0);
4770 END_PROFILE(SMBlock);
4771 return;
4774 /****************************************************************************
4775 Reply to a unlock.
4776 ****************************************************************************/
4778 void reply_unlock(struct smb_request *req)
4780 connection_struct *conn = req->conn;
4781 uint64_t count,offset;
4782 NTSTATUS status;
4783 files_struct *fsp;
4785 START_PROFILE(SMBunlock);
4787 if (req->wct < 5) {
4788 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4789 END_PROFILE(SMBunlock);
4790 return;
4793 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4795 if (!check_fsp(conn, req, fsp)) {
4796 END_PROFILE(SMBunlock);
4797 return;
4800 count = (uint64_t)IVAL(req->vwv+1, 0);
4801 offset = (uint64_t)IVAL(req->vwv+3, 0);
4803 status = do_unlock(smbd_messaging_context(),
4804 fsp,
4805 req->smbpid,
4806 count,
4807 offset,
4808 WINDOWS_LOCK);
4810 if (NT_STATUS_V(status)) {
4811 reply_nterror(req, status);
4812 END_PROFILE(SMBunlock);
4813 return;
4816 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4817 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4819 reply_outbuf(req, 0, 0);
4821 END_PROFILE(SMBunlock);
4822 return;
4825 #undef DBGC_CLASS
4826 #define DBGC_CLASS DBGC_ALL
4828 /****************************************************************************
4829 Reply to a tdis.
4830 conn POINTER CAN BE NULL HERE !
4831 ****************************************************************************/
4833 void reply_tdis(struct smb_request *req)
4835 struct smbd_server_connection *sconn = smbd_server_conn;
4836 connection_struct *conn = req->conn;
4837 START_PROFILE(SMBtdis);
4839 if (!conn) {
4840 DEBUG(4,("Invalid connection in tdis\n"));
4841 reply_doserror(req, ERRSRV, ERRinvnid);
4842 END_PROFILE(SMBtdis);
4843 return;
4846 conn->used = False;
4848 close_cnum(sconn, conn,req->vuid);
4849 req->conn = NULL;
4851 reply_outbuf(req, 0, 0);
4852 END_PROFILE(SMBtdis);
4853 return;
4856 /****************************************************************************
4857 Reply to a echo.
4858 conn POINTER CAN BE NULL HERE !
4859 ****************************************************************************/
4861 void reply_echo(struct smb_request *req)
4863 connection_struct *conn = req->conn;
4864 struct smb_perfcount_data local_pcd;
4865 struct smb_perfcount_data *cur_pcd;
4866 int smb_reverb;
4867 int seq_num;
4869 START_PROFILE(SMBecho);
4871 smb_init_perfcount_data(&local_pcd);
4873 if (req->wct < 1) {
4874 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4875 END_PROFILE(SMBecho);
4876 return;
4879 smb_reverb = SVAL(req->vwv+0, 0);
4881 reply_outbuf(req, 1, req->buflen);
4883 /* copy any incoming data back out */
4884 if (req->buflen > 0) {
4885 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4888 if (smb_reverb > 100) {
4889 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4890 smb_reverb = 100;
4893 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
4895 /* this makes sure we catch the request pcd */
4896 if (seq_num == smb_reverb) {
4897 cur_pcd = &req->pcd;
4898 } else {
4899 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
4900 cur_pcd = &local_pcd;
4903 SSVAL(req->outbuf,smb_vwv0,seq_num);
4905 show_msg((char *)req->outbuf);
4906 if (!srv_send_smb(smbd_server_fd(),
4907 (char *)req->outbuf,
4908 true, req->seqnum+1,
4909 IS_CONN_ENCRYPTED(conn)||req->encrypted,
4910 cur_pcd))
4911 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4914 DEBUG(3,("echo %d times\n", smb_reverb));
4916 TALLOC_FREE(req->outbuf);
4918 END_PROFILE(SMBecho);
4919 return;
4922 /****************************************************************************
4923 Reply to a printopen.
4924 ****************************************************************************/
4926 void reply_printopen(struct smb_request *req)
4928 connection_struct *conn = req->conn;
4929 files_struct *fsp;
4930 SMB_STRUCT_STAT sbuf;
4931 NTSTATUS status;
4933 START_PROFILE(SMBsplopen);
4935 if (req->wct < 2) {
4936 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4937 END_PROFILE(SMBsplopen);
4938 return;
4941 if (!CAN_PRINT(conn)) {
4942 reply_doserror(req, ERRDOS, ERRnoaccess);
4943 END_PROFILE(SMBsplopen);
4944 return;
4947 status = file_new(req, conn, &fsp);
4948 if(!NT_STATUS_IS_OK(status)) {
4949 reply_nterror(req, status);
4950 END_PROFILE(SMBsplopen);
4951 return;
4954 /* Open for exclusive use, write only. */
4955 status = print_fsp_open(req, conn, NULL, req->vuid, fsp, &sbuf);
4957 if (!NT_STATUS_IS_OK(status)) {
4958 file_free(req, fsp);
4959 reply_nterror(req, status);
4960 END_PROFILE(SMBsplopen);
4961 return;
4964 reply_outbuf(req, 1, 0);
4965 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4967 DEBUG(3,("openprint fd=%d fnum=%d\n",
4968 fsp->fh->fd, fsp->fnum));
4970 END_PROFILE(SMBsplopen);
4971 return;
4974 /****************************************************************************
4975 Reply to a printclose.
4976 ****************************************************************************/
4978 void reply_printclose(struct smb_request *req)
4980 connection_struct *conn = req->conn;
4981 files_struct *fsp;
4982 NTSTATUS status;
4984 START_PROFILE(SMBsplclose);
4986 if (req->wct < 1) {
4987 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4988 END_PROFILE(SMBsplclose);
4989 return;
4992 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4994 if (!check_fsp(conn, req, fsp)) {
4995 END_PROFILE(SMBsplclose);
4996 return;
4999 if (!CAN_PRINT(conn)) {
5000 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
5001 END_PROFILE(SMBsplclose);
5002 return;
5005 DEBUG(3,("printclose fd=%d fnum=%d\n",
5006 fsp->fh->fd,fsp->fnum));
5008 status = close_file(req, fsp, NORMAL_CLOSE);
5010 if(!NT_STATUS_IS_OK(status)) {
5011 reply_nterror(req, status);
5012 END_PROFILE(SMBsplclose);
5013 return;
5016 reply_outbuf(req, 0, 0);
5018 END_PROFILE(SMBsplclose);
5019 return;
5022 /****************************************************************************
5023 Reply to a printqueue.
5024 ****************************************************************************/
5026 void reply_printqueue(struct smb_request *req)
5028 connection_struct *conn = req->conn;
5029 int max_count;
5030 int start_index;
5032 START_PROFILE(SMBsplretq);
5034 if (req->wct < 2) {
5035 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5036 END_PROFILE(SMBsplretq);
5037 return;
5040 max_count = SVAL(req->vwv+0, 0);
5041 start_index = SVAL(req->vwv+1, 0);
5043 /* we used to allow the client to get the cnum wrong, but that
5044 is really quite gross and only worked when there was only
5045 one printer - I think we should now only accept it if they
5046 get it right (tridge) */
5047 if (!CAN_PRINT(conn)) {
5048 reply_doserror(req, ERRDOS, ERRnoaccess);
5049 END_PROFILE(SMBsplretq);
5050 return;
5053 reply_outbuf(req, 2, 3);
5054 SSVAL(req->outbuf,smb_vwv0,0);
5055 SSVAL(req->outbuf,smb_vwv1,0);
5056 SCVAL(smb_buf(req->outbuf),0,1);
5057 SSVAL(smb_buf(req->outbuf),1,0);
5059 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5060 start_index, max_count));
5063 print_queue_struct *queue = NULL;
5064 print_status_struct status;
5065 int count = print_queue_status(SNUM(conn), &queue, &status);
5066 int num_to_get = ABS(max_count);
5067 int first = (max_count>0?start_index:start_index+max_count+1);
5068 int i;
5070 if (first >= count)
5071 num_to_get = 0;
5072 else
5073 num_to_get = MIN(num_to_get,count-first);
5076 for (i=first;i<first+num_to_get;i++) {
5077 char blob[28];
5078 char *p = blob;
5080 srv_put_dos_date2(p,0,queue[i].time);
5081 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
5082 SSVAL(p,5, queue[i].job);
5083 SIVAL(p,7,queue[i].size);
5084 SCVAL(p,11,0);
5085 srvstr_push(blob, req->flags2, p+12,
5086 queue[i].fs_user, 16, STR_ASCII);
5088 if (message_push_blob(
5089 &req->outbuf,
5090 data_blob_const(
5091 blob, sizeof(blob))) == -1) {
5092 reply_nterror(req, NT_STATUS_NO_MEMORY);
5093 END_PROFILE(SMBsplretq);
5094 return;
5098 if (count > 0) {
5099 SSVAL(req->outbuf,smb_vwv0,count);
5100 SSVAL(req->outbuf,smb_vwv1,
5101 (max_count>0?first+count:first-1));
5102 SCVAL(smb_buf(req->outbuf),0,1);
5103 SSVAL(smb_buf(req->outbuf),1,28*count);
5106 SAFE_FREE(queue);
5108 DEBUG(3,("%d entries returned in queue\n",count));
5111 END_PROFILE(SMBsplretq);
5112 return;
5115 /****************************************************************************
5116 Reply to a printwrite.
5117 ****************************************************************************/
5119 void reply_printwrite(struct smb_request *req)
5121 connection_struct *conn = req->conn;
5122 int numtowrite;
5123 const char *data;
5124 files_struct *fsp;
5126 START_PROFILE(SMBsplwr);
5128 if (req->wct < 1) {
5129 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5130 END_PROFILE(SMBsplwr);
5131 return;
5134 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5136 if (!check_fsp(conn, req, fsp)) {
5137 END_PROFILE(SMBsplwr);
5138 return;
5141 if (!CAN_PRINT(conn)) {
5142 reply_doserror(req, ERRDOS, ERRnoaccess);
5143 END_PROFILE(SMBsplwr);
5144 return;
5147 if (!CHECK_WRITE(fsp)) {
5148 reply_doserror(req, ERRDOS, ERRbadaccess);
5149 END_PROFILE(SMBsplwr);
5150 return;
5153 numtowrite = SVAL(req->buf, 1);
5155 if (req->buflen < numtowrite + 3) {
5156 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5157 END_PROFILE(SMBsplwr);
5158 return;
5161 data = (const char *)req->buf + 3;
5163 if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
5164 reply_unixerror(req, ERRHRD, ERRdiskfull);
5165 END_PROFILE(SMBsplwr);
5166 return;
5169 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5171 END_PROFILE(SMBsplwr);
5172 return;
5175 /****************************************************************************
5176 Reply to a mkdir.
5177 ****************************************************************************/
5179 void reply_mkdir(struct smb_request *req)
5181 connection_struct *conn = req->conn;
5182 struct smb_filename *smb_dname = NULL;
5183 char *directory = NULL;
5184 NTSTATUS status;
5185 TALLOC_CTX *ctx = talloc_tos();
5187 START_PROFILE(SMBmkdir);
5189 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5190 STR_TERMINATE, &status);
5191 if (!NT_STATUS_IS_OK(status)) {
5192 reply_nterror(req, status);
5193 goto out;
5196 status = filename_convert(ctx, conn,
5197 req->flags2 & FLAGS2_DFS_PATHNAMES,
5198 directory,
5199 &smb_dname,
5200 &directory);
5201 if (!NT_STATUS_IS_OK(status)) {
5202 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5203 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5204 ERRSRV, ERRbadpath);
5205 goto out;
5207 reply_nterror(req, status);
5208 goto out;
5211 status = create_directory(conn, req, smb_dname);
5213 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5215 if (!NT_STATUS_IS_OK(status)) {
5217 if (!use_nt_status()
5218 && NT_STATUS_EQUAL(status,
5219 NT_STATUS_OBJECT_NAME_COLLISION)) {
5221 * Yes, in the DOS error code case we get a
5222 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5223 * samba4 torture test.
5225 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5228 reply_nterror(req, status);
5229 goto out;
5232 reply_outbuf(req, 0, 0);
5234 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5235 out:
5236 TALLOC_FREE(smb_dname);
5237 END_PROFILE(SMBmkdir);
5238 return;
5241 /****************************************************************************
5242 Static function used by reply_rmdir to delete an entire directory
5243 tree recursively. Return True on ok, False on fail.
5244 ****************************************************************************/
5246 static bool recursive_rmdir(TALLOC_CTX *ctx,
5247 connection_struct *conn,
5248 char *directory)
5250 const char *dname = NULL;
5251 bool ret = True;
5252 long offset = 0;
5253 SMB_STRUCT_STAT st;
5254 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, directory,
5255 NULL, 0);
5257 if(dir_hnd == NULL)
5258 return False;
5260 while((dname = ReadDirName(dir_hnd, &offset, &st))) {
5261 char *fullname = NULL;
5263 if (ISDOT(dname) || ISDOTDOT(dname)) {
5264 continue;
5267 if (!is_visible_file(conn, directory, dname, &st, False)) {
5268 continue;
5271 /* Construct the full name. */
5272 fullname = talloc_asprintf(ctx,
5273 "%s/%s",
5274 directory,
5275 dname);
5276 if (!fullname) {
5277 errno = ENOMEM;
5278 ret = False;
5279 break;
5282 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5283 ret = False;
5284 break;
5287 if(st.st_ex_mode & S_IFDIR) {
5288 if(!recursive_rmdir(ctx, conn, fullname)) {
5289 ret = False;
5290 break;
5292 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5293 ret = False;
5294 break;
5296 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5297 ret = False;
5298 break;
5300 TALLOC_FREE(fullname);
5302 TALLOC_FREE(dir_hnd);
5303 return ret;
5306 /****************************************************************************
5307 The internals of the rmdir code - called elsewhere.
5308 ****************************************************************************/
5310 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
5311 connection_struct *conn,
5312 const char *directory)
5314 int ret;
5315 SMB_STRUCT_STAT st;
5317 /* Might be a symlink. */
5318 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
5319 return map_nt_error_from_unix(errno);
5322 if (S_ISLNK(st.st_ex_mode)) {
5323 /* Is what it points to a directory ? */
5324 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
5325 return map_nt_error_from_unix(errno);
5327 if (!(S_ISDIR(st.st_ex_mode))) {
5328 return NT_STATUS_NOT_A_DIRECTORY;
5330 ret = SMB_VFS_UNLINK(conn,directory);
5331 } else {
5332 ret = SMB_VFS_RMDIR(conn,directory);
5334 if (ret == 0) {
5335 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5336 FILE_NOTIFY_CHANGE_DIR_NAME,
5337 directory);
5338 return NT_STATUS_OK;
5341 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5343 * Check to see if the only thing in this directory are
5344 * vetoed files/directories. If so then delete them and
5345 * retry. If we fail to delete any of them (and we *don't*
5346 * do a recursive delete) then fail the rmdir.
5348 const char *dname;
5349 long dirpos = 0;
5350 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5351 directory, NULL, 0);
5353 if(dir_hnd == NULL) {
5354 errno = ENOTEMPTY;
5355 goto err;
5358 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5359 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5360 continue;
5361 if (!is_visible_file(conn, directory, dname, &st, False))
5362 continue;
5363 if(!IS_VETO_PATH(conn, dname)) {
5364 TALLOC_FREE(dir_hnd);
5365 errno = ENOTEMPTY;
5366 goto err;
5370 /* We only have veto files/directories.
5371 * Are we allowed to delete them ? */
5373 if(!lp_recursive_veto_delete(SNUM(conn))) {
5374 TALLOC_FREE(dir_hnd);
5375 errno = ENOTEMPTY;
5376 goto err;
5379 /* Do a recursive delete. */
5380 RewindDir(dir_hnd,&dirpos);
5381 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5382 char *fullname = NULL;
5384 if (ISDOT(dname) || ISDOTDOT(dname)) {
5385 continue;
5387 if (!is_visible_file(conn, directory, dname, &st, False)) {
5388 continue;
5391 fullname = talloc_asprintf(ctx,
5392 "%s/%s",
5393 directory,
5394 dname);
5396 if(!fullname) {
5397 errno = ENOMEM;
5398 break;
5401 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5402 break;
5404 if(st.st_ex_mode & S_IFDIR) {
5405 if(!recursive_rmdir(ctx, conn, fullname)) {
5406 break;
5408 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5409 break;
5411 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5412 break;
5414 TALLOC_FREE(fullname);
5416 TALLOC_FREE(dir_hnd);
5417 /* Retry the rmdir */
5418 ret = SMB_VFS_RMDIR(conn,directory);
5421 err:
5423 if (ret != 0) {
5424 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5425 "%s\n", directory,strerror(errno)));
5426 return map_nt_error_from_unix(errno);
5429 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5430 FILE_NOTIFY_CHANGE_DIR_NAME,
5431 directory);
5433 return NT_STATUS_OK;
5436 /****************************************************************************
5437 Reply to a rmdir.
5438 ****************************************************************************/
5440 void reply_rmdir(struct smb_request *req)
5442 connection_struct *conn = req->conn;
5443 struct smb_filename *smb_dname = NULL;
5444 char *directory = NULL;
5445 NTSTATUS status;
5446 TALLOC_CTX *ctx = talloc_tos();
5448 START_PROFILE(SMBrmdir);
5450 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5451 STR_TERMINATE, &status);
5452 if (!NT_STATUS_IS_OK(status)) {
5453 reply_nterror(req, status);
5454 goto out;
5457 status = filename_convert(ctx, conn,
5458 req->flags2 & FLAGS2_DFS_PATHNAMES,
5459 directory,
5460 &smb_dname,
5461 &directory);
5462 if (!NT_STATUS_IS_OK(status)) {
5463 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5464 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5465 ERRSRV, ERRbadpath);
5466 goto out;
5468 reply_nterror(req, status);
5469 goto out;
5472 dptr_closepath(directory, req->smbpid);
5473 status = rmdir_internals(ctx, conn, directory);
5474 if (!NT_STATUS_IS_OK(status)) {
5475 reply_nterror(req, status);
5476 goto out;
5479 reply_outbuf(req, 0, 0);
5481 DEBUG( 3, ( "rmdir %s\n", directory ) );
5482 out:
5483 TALLOC_FREE(smb_dname);
5484 END_PROFILE(SMBrmdir);
5485 return;
5488 /*******************************************************************
5489 Resolve wildcards in a filename rename.
5490 ********************************************************************/
5492 static bool resolve_wildcards(TALLOC_CTX *ctx,
5493 const char *name1,
5494 const char *name2,
5495 char **pp_newname)
5497 char *name2_copy = NULL;
5498 char *root1 = NULL;
5499 char *root2 = NULL;
5500 char *ext1 = NULL;
5501 char *ext2 = NULL;
5502 char *p,*p2, *pname1, *pname2;
5504 name2_copy = talloc_strdup(ctx, name2);
5505 if (!name2_copy) {
5506 return False;
5509 pname1 = strrchr_m(name1,'/');
5510 pname2 = strrchr_m(name2_copy,'/');
5512 if (!pname1 || !pname2) {
5513 return False;
5516 /* Truncate the copy of name2 at the last '/' */
5517 *pname2 = '\0';
5519 /* Now go past the '/' */
5520 pname1++;
5521 pname2++;
5523 root1 = talloc_strdup(ctx, pname1);
5524 root2 = talloc_strdup(ctx, pname2);
5526 if (!root1 || !root2) {
5527 return False;
5530 p = strrchr_m(root1,'.');
5531 if (p) {
5532 *p = 0;
5533 ext1 = talloc_strdup(ctx, p+1);
5534 } else {
5535 ext1 = talloc_strdup(ctx, "");
5537 p = strrchr_m(root2,'.');
5538 if (p) {
5539 *p = 0;
5540 ext2 = talloc_strdup(ctx, p+1);
5541 } else {
5542 ext2 = talloc_strdup(ctx, "");
5545 if (!ext1 || !ext2) {
5546 return False;
5549 p = root1;
5550 p2 = root2;
5551 while (*p2) {
5552 if (*p2 == '?') {
5553 /* Hmmm. Should this be mb-aware ? */
5554 *p2 = *p;
5555 p2++;
5556 } else if (*p2 == '*') {
5557 *p2 = '\0';
5558 root2 = talloc_asprintf(ctx, "%s%s",
5559 root2,
5561 if (!root2) {
5562 return False;
5564 break;
5565 } else {
5566 p2++;
5568 if (*p) {
5569 p++;
5573 p = ext1;
5574 p2 = ext2;
5575 while (*p2) {
5576 if (*p2 == '?') {
5577 /* Hmmm. Should this be mb-aware ? */
5578 *p2 = *p;
5579 p2++;
5580 } else if (*p2 == '*') {
5581 *p2 = '\0';
5582 ext2 = talloc_asprintf(ctx, "%s%s",
5583 ext2,
5585 if (!ext2) {
5586 return False;
5588 break;
5589 } else {
5590 p2++;
5592 if (*p) {
5593 p++;
5597 if (*ext2) {
5598 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5599 name2_copy,
5600 root2,
5601 ext2);
5602 } else {
5603 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5604 name2_copy,
5605 root2);
5608 if (!*pp_newname) {
5609 return False;
5612 return True;
5615 /****************************************************************************
5616 Ensure open files have their names updated. Updated to notify other smbd's
5617 asynchronously.
5618 ****************************************************************************/
5620 static void rename_open_files(connection_struct *conn,
5621 struct share_mode_lock *lck,
5622 const char *newname)
5624 files_struct *fsp;
5625 bool did_rename = False;
5627 for(fsp = file_find_di_first(lck->id); fsp;
5628 fsp = file_find_di_next(fsp)) {
5629 /* fsp_name is a relative path under the fsp. To change this for other
5630 sharepaths we need to manipulate relative paths. */
5631 /* TODO - create the absolute path and manipulate the newname
5632 relative to the sharepath. */
5633 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5634 continue;
5636 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5637 fsp->fnum, file_id_string_tos(&fsp->file_id),
5638 fsp->fsp_name, newname ));
5639 string_set(&fsp->fsp_name, newname);
5640 did_rename = True;
5643 if (!did_rename) {
5644 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5645 file_id_string_tos(&lck->id), newname ));
5648 /* Send messages to all smbd's (not ourself) that the name has changed. */
5649 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5650 newname);
5653 /****************************************************************************
5654 We need to check if the source path is a parent directory of the destination
5655 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5656 refuse the rename with a sharing violation. Under UNIX the above call can
5657 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5658 probably need to check that the client is a Windows one before disallowing
5659 this as a UNIX client (one with UNIX extensions) can know the source is a
5660 symlink and make this decision intelligently. Found by an excellent bug
5661 report from <AndyLiebman@aol.com>.
5662 ****************************************************************************/
5664 static bool rename_path_prefix_equal(const char *src, const char *dest)
5666 const char *psrc = src;
5667 const char *pdst = dest;
5668 size_t slen;
5670 if (psrc[0] == '.' && psrc[1] == '/') {
5671 psrc += 2;
5673 if (pdst[0] == '.' && pdst[1] == '/') {
5674 pdst += 2;
5676 if ((slen = strlen(psrc)) > strlen(pdst)) {
5677 return False;
5679 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5683 * Do the notify calls from a rename
5686 static void notify_rename(connection_struct *conn, bool is_dir,
5687 const char *oldpath, const char *newpath)
5689 char *olddir, *newdir;
5690 const char *oldname, *newname;
5691 uint32 mask;
5693 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5694 : FILE_NOTIFY_CHANGE_FILE_NAME;
5696 if (!parent_dirname(talloc_tos(), oldpath, &olddir, &oldname)
5697 || !parent_dirname(talloc_tos(), newpath, &newdir, &newname)) {
5698 TALLOC_FREE(olddir);
5699 return;
5702 if (strcmp(olddir, newdir) == 0) {
5703 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
5704 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
5706 else {
5707 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
5708 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
5710 TALLOC_FREE(olddir);
5711 TALLOC_FREE(newdir);
5713 /* this is a strange one. w2k3 gives an additional event for
5714 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5715 files, but not directories */
5716 if (!is_dir) {
5717 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5718 FILE_NOTIFY_CHANGE_ATTRIBUTES
5719 |FILE_NOTIFY_CHANGE_CREATION,
5720 newpath);
5724 /****************************************************************************
5725 Rename an open file - given an fsp.
5726 ****************************************************************************/
5728 NTSTATUS rename_internals_fsp(connection_struct *conn,
5729 files_struct *fsp,
5730 char *newname,
5731 const char *newname_last_component,
5732 uint32 attrs,
5733 bool replace_if_exists)
5735 TALLOC_CTX *ctx = talloc_tos();
5736 SMB_STRUCT_STAT sbuf, sbuf1;
5737 NTSTATUS status = NT_STATUS_OK;
5738 struct share_mode_lock *lck = NULL;
5739 bool dst_exists, old_is_stream, new_is_stream;
5741 ZERO_STRUCT(sbuf);
5743 status = check_name(conn, newname);
5744 if (!NT_STATUS_IS_OK(status)) {
5745 return status;
5748 /* Ensure newname contains a '/' */
5749 if(strrchr_m(newname,'/') == 0) {
5750 newname = talloc_asprintf(ctx,
5751 "./%s",
5752 newname);
5753 if (!newname) {
5754 return NT_STATUS_NO_MEMORY;
5759 * Check for special case with case preserving and not
5760 * case sensitive. If the old last component differs from the original
5761 * last component only by case, then we should allow
5762 * the rename (user is trying to change the case of the
5763 * filename).
5766 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5767 strequal(newname, fsp->fsp_name)) {
5768 char *p;
5769 char *newname_modified_last_component = NULL;
5772 * Get the last component of the modified name.
5773 * Note that we guarantee that newname contains a '/'
5774 * character above.
5776 p = strrchr_m(newname,'/');
5777 newname_modified_last_component = talloc_strdup(ctx,
5778 p+1);
5779 if (!newname_modified_last_component) {
5780 return NT_STATUS_NO_MEMORY;
5783 if(strcsequal(newname_modified_last_component,
5784 newname_last_component) == False) {
5786 * Replace the modified last component with
5787 * the original.
5789 *p = '\0'; /* Truncate at the '/' */
5790 newname = talloc_asprintf(ctx,
5791 "%s/%s",
5792 newname,
5793 newname_last_component);
5798 * If the src and dest names are identical - including case,
5799 * don't do the rename, just return success.
5802 if (strcsequal(fsp->fsp_name, newname)) {
5803 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5804 newname));
5805 return NT_STATUS_OK;
5808 old_is_stream = is_ntfs_stream_name(fsp->fsp_name);
5809 new_is_stream = is_ntfs_stream_name(newname);
5811 /* Return the correct error code if both names aren't streams. */
5812 if (!old_is_stream && new_is_stream) {
5813 return NT_STATUS_OBJECT_NAME_INVALID;
5816 if (old_is_stream && !new_is_stream) {
5817 return NT_STATUS_INVALID_PARAMETER;
5821 * Have vfs_object_exist also fill sbuf1
5823 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
5825 if(!replace_if_exists && dst_exists) {
5826 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5827 fsp->fsp_name,newname));
5828 return NT_STATUS_OBJECT_NAME_COLLISION;
5831 if (dst_exists) {
5832 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5833 files_struct *dst_fsp = file_find_di_first(fileid);
5834 /* The file can be open when renaming a stream */
5835 if (dst_fsp && !new_is_stream) {
5836 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5837 return NT_STATUS_ACCESS_DENIED;
5841 /* Ensure we have a valid stat struct for the source. */
5842 if (fsp->fh->fd != -1) {
5843 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
5844 return map_nt_error_from_unix(errno);
5846 } else {
5847 int ret = -1;
5848 if (fsp->posix_open) {
5849 ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf);
5850 } else {
5851 ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf);
5853 if (ret == -1) {
5854 return map_nt_error_from_unix(errno);
5858 status = can_rename(conn, fsp, attrs, &sbuf);
5860 if (!NT_STATUS_IS_OK(status)) {
5861 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5862 nt_errstr(status), fsp->fsp_name,newname));
5863 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5864 status = NT_STATUS_ACCESS_DENIED;
5865 return status;
5868 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5869 return NT_STATUS_ACCESS_DENIED;
5872 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5873 NULL);
5876 * We have the file open ourselves, so not being able to get the
5877 * corresponding share mode lock is a fatal error.
5880 SMB_ASSERT(lck != NULL);
5882 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5883 uint32 create_options = fsp->fh->private_options;
5885 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5886 fsp->fsp_name,newname));
5888 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5890 rename_open_files(conn, lck, newname);
5893 * A rename acts as a new file create w.r.t. allowing an initial delete
5894 * on close, probably because in Windows there is a new handle to the
5895 * new file. If initial delete on close was requested but not
5896 * originally set, we need to set it here. This is probably not 100% correct,
5897 * but will work for the CIFSFS client which in non-posix mode
5898 * depends on these semantics. JRA.
5901 if (create_options & FILE_DELETE_ON_CLOSE) {
5902 status = can_set_delete_on_close(fsp, True, 0);
5904 if (NT_STATUS_IS_OK(status)) {
5905 /* Note that here we set the *inital* delete on close flag,
5906 * not the regular one. The magic gets handled in close. */
5907 fsp->initial_delete_on_close = True;
5910 TALLOC_FREE(lck);
5911 return NT_STATUS_OK;
5914 TALLOC_FREE(lck);
5916 if (errno == ENOTDIR || errno == EISDIR) {
5917 status = NT_STATUS_OBJECT_NAME_COLLISION;
5918 } else {
5919 status = map_nt_error_from_unix(errno);
5922 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5923 nt_errstr(status), fsp->fsp_name,newname));
5925 return status;
5928 /****************************************************************************
5929 The guts of the rename command, split out so it may be called by the NT SMB
5930 code.
5931 ****************************************************************************/
5933 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5934 connection_struct *conn,
5935 struct smb_request *req,
5936 const char *name_in,
5937 const char *newname_in,
5938 uint32 attrs,
5939 bool replace_if_exists,
5940 bool src_has_wild,
5941 bool dest_has_wild,
5942 uint32_t access_mask)
5944 struct smb_filename *smb_fname_src = NULL;
5945 struct smb_filename *smb_fname_dst = NULL;
5946 char *fname_src_dir = NULL;
5947 char *fname_src_mask = NULL;
5948 int count=0;
5949 NTSTATUS status = NT_STATUS_OK;
5950 struct smb_Dir *dir_hnd = NULL;
5951 const char *dname;
5952 long offset = 0;
5953 int create_options = 0;
5954 bool posix_pathnames = lp_posix_pathnames();
5956 status = unix_convert(ctx, conn, name_in, &smb_fname_src,
5957 src_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
5958 if (!NT_STATUS_IS_OK(status)) {
5959 goto out;
5962 status = unix_convert(ctx, conn, newname_in, &smb_fname_dst,
5963 (UCF_SAVE_LCOMP |
5964 (dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0)));
5965 if (!NT_STATUS_IS_OK(status)) {
5966 goto out;
5970 * Split the old name into directory and last component
5971 * strings. Note that unix_convert may have stripped off a
5972 * leading ./ from both name and newname if the rename is
5973 * at the root of the share. We need to make sure either both
5974 * name and newname contain a / character or neither of them do
5975 * as this is checked in resolve_wildcards().
5978 /* Split up the directory from the filename/mask. */
5979 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
5980 &fname_src_dir, &fname_src_mask);
5981 if (!NT_STATUS_IS_OK(status)) {
5982 status = NT_STATUS_NO_MEMORY;
5983 goto out;
5987 * We should only check the mangled cache
5988 * here if unix_convert failed. This means
5989 * that the path in 'mask' doesn't exist
5990 * on the file system and so we need to look
5991 * for a possible mangle. This patch from
5992 * Tine Smukavec <valentin.smukavec@hermes.si>.
5995 if (!VALID_STAT(smb_fname_src->st) &&
5996 mangle_is_mangled(fname_src_mask, conn->params)) {
5997 char *new_mask = NULL;
5998 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
5999 conn->params);
6000 if (new_mask) {
6001 TALLOC_FREE(fname_src_mask);
6002 fname_src_mask = new_mask;
6006 if (!src_has_wild) {
6007 files_struct *fsp;
6008 char *fname_src = NULL;
6009 char *fname_dst = NULL;
6012 * Only one file needs to be renamied. Append the mask back
6013 * onto the directory.
6015 TALLOC_FREE(smb_fname_src->base_name);
6016 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6017 "%s/%s",
6018 fname_src_dir,
6019 fname_src_mask);
6020 if (!smb_fname_src->base_name) {
6021 status = NT_STATUS_NO_MEMORY;
6022 goto out;
6025 /* Ensure dst fname contains a '/' also */
6026 if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
6027 char *tmp;
6028 tmp = talloc_asprintf(smb_fname_dst, "./%s",
6029 smb_fname_dst->base_name);
6030 if (!tmp) {
6031 status = NT_STATUS_NO_MEMORY;
6032 goto out;
6034 TALLOC_FREE(smb_fname_dst->base_name);
6035 smb_fname_dst->base_name = tmp;
6038 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6039 "case_preserve = %d, short case preserve = %d, "
6040 "directory = %s, newname = %s, "
6041 "last_component_dest = %s\n",
6042 conn->case_sensitive, conn->case_preserve,
6043 conn->short_case_preserve,
6044 smb_fname_str_dbg(smb_fname_src),
6045 smb_fname_str_dbg(smb_fname_dst),
6046 smb_fname_dst->original_lcomp));
6048 /* The dest name still may have wildcards. */
6049 if (dest_has_wild) {
6050 char *fname_dst_mod = NULL;
6051 if (!resolve_wildcards(smb_fname_dst,
6052 smb_fname_src->base_name,
6053 smb_fname_dst->base_name,
6054 &fname_dst_mod)) {
6055 DEBUG(6, ("rename_internals: resolve_wildcards "
6056 "%s %s failed\n",
6057 smb_fname_src->base_name,
6058 smb_fname_dst->base_name));
6059 status = NT_STATUS_NO_MEMORY;
6060 goto out;
6062 TALLOC_FREE(smb_fname_dst->base_name);
6063 smb_fname_dst->base_name = fname_dst_mod;
6066 status = get_full_smb_filename(ctx, smb_fname_src, &fname_src);
6067 if (!NT_STATUS_IS_OK(status)) {
6068 goto out;
6071 ZERO_STRUCT(smb_fname_src->st);
6072 if (posix_pathnames) {
6073 SMB_VFS_LSTAT(conn, fname_src, &smb_fname_src->st);
6074 } else {
6075 SMB_VFS_STAT(conn, fname_src, &smb_fname_src->st);
6078 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6079 create_options |= FILE_DIRECTORY_FILE;
6082 TALLOC_FREE(fname_src);
6084 status = SMB_VFS_CREATE_FILE(
6085 conn, /* conn */
6086 req, /* req */
6087 0, /* root_dir_fid */
6088 smb_fname_src, /* fname */
6089 access_mask, /* access_mask */
6090 (FILE_SHARE_READ | /* share_access */
6091 FILE_SHARE_WRITE),
6092 FILE_OPEN, /* create_disposition*/
6093 create_options, /* create_options */
6094 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6095 0, /* oplock_request */
6096 0, /* allocation_size */
6097 NULL, /* sd */
6098 NULL, /* ea_list */
6099 &fsp, /* result */
6100 NULL); /* pinfo */
6102 if (!NT_STATUS_IS_OK(status)) {
6103 DEBUG(3, ("Could not open rename source %s: %s\n",
6104 smb_fname_str_dbg(smb_fname_src),
6105 nt_errstr(status)));
6106 goto out;
6109 status = get_full_smb_filename(ctx, smb_fname_dst, &fname_dst);
6110 if (!NT_STATUS_IS_OK(status)) {
6111 TALLOC_FREE(fname_src);
6112 goto out;
6115 status = rename_internals_fsp(conn, fsp, fname_dst,
6116 smb_fname_dst->original_lcomp,
6117 attrs, replace_if_exists);
6119 TALLOC_FREE(fname_dst);
6121 close_file(req, fsp, NORMAL_CLOSE);
6123 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6124 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6125 smb_fname_str_dbg(smb_fname_dst)));
6127 goto out;
6131 * Wildcards - process each file that matches.
6133 if (strequal(fname_src_mask, "????????.???")) {
6134 TALLOC_FREE(fname_src_mask);
6135 fname_src_mask = talloc_strdup(ctx, "*");
6136 if (!fname_src_mask) {
6137 status = NT_STATUS_NO_MEMORY;
6138 goto out;
6142 status = check_name(conn, fname_src_dir);
6143 if (!NT_STATUS_IS_OK(status)) {
6144 goto out;
6147 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6148 attrs);
6149 if (dir_hnd == NULL) {
6150 status = map_nt_error_from_unix(errno);
6151 goto out;
6154 status = NT_STATUS_NO_SUCH_FILE;
6156 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6157 * - gentest fix. JRA
6160 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st))) {
6161 files_struct *fsp = NULL;
6162 char *fname_src = NULL;
6163 char *fname_dst = NULL;
6164 char *destname = NULL;
6165 bool sysdir_entry = False;
6167 /* Quick check for "." and ".." */
6168 if (ISDOT(dname) || ISDOTDOT(dname)) {
6169 if (attrs & aDIR) {
6170 sysdir_entry = True;
6171 } else {
6172 continue;
6176 if (!is_visible_file(conn, fname_src_dir, dname,
6177 &smb_fname_src->st, false)) {
6178 continue;
6181 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6182 continue;
6185 if (sysdir_entry) {
6186 status = NT_STATUS_OBJECT_NAME_INVALID;
6187 break;
6190 TALLOC_FREE(smb_fname_src->base_name);
6191 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6192 "%s/%s",
6193 fname_src_dir,
6194 dname);
6195 if (!smb_fname_src->base_name) {
6196 status = NT_STATUS_NO_MEMORY;
6197 goto out;
6200 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6201 smb_fname_dst->base_name,
6202 &destname)) {
6203 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6204 smb_fname_src->base_name, destname));
6205 continue;
6207 if (!destname) {
6208 status = NT_STATUS_NO_MEMORY;
6209 goto out;
6212 TALLOC_FREE(smb_fname_dst->base_name);
6213 smb_fname_dst->base_name = destname;
6215 status = get_full_smb_filename(ctx, smb_fname_src, &fname_src);
6216 if (!NT_STATUS_IS_OK(status)) {
6217 goto out;
6220 ZERO_STRUCT(smb_fname_src->st);
6221 if (posix_pathnames) {
6222 SMB_VFS_LSTAT(conn, fname_src, &smb_fname_src->st);
6223 } else {
6224 SMB_VFS_STAT(conn, fname_src, &smb_fname_src->st);
6227 TALLOC_FREE(fname_src);
6229 create_options = 0;
6231 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6232 create_options |= FILE_DIRECTORY_FILE;
6235 status = SMB_VFS_CREATE_FILE(
6236 conn, /* conn */
6237 req, /* req */
6238 0, /* root_dir_fid */
6239 smb_fname_src, /* fname */
6240 access_mask, /* access_mask */
6241 (FILE_SHARE_READ | /* share_access */
6242 FILE_SHARE_WRITE),
6243 FILE_OPEN, /* create_disposition*/
6244 create_options, /* create_options */
6245 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6246 0, /* oplock_request */
6247 0, /* allocation_size */
6248 NULL, /* sd */
6249 NULL, /* ea_list */
6250 &fsp, /* result */
6251 NULL); /* pinfo */
6253 if (!NT_STATUS_IS_OK(status)) {
6254 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6255 "returned %s rename %s -> %s\n",
6256 nt_errstr(status),
6257 smb_fname_str_dbg(smb_fname_src),
6258 smb_fname_str_dbg(smb_fname_dst)));
6259 break;
6262 status = get_full_smb_filename(ctx, smb_fname_dst, &fname_dst);
6263 if (!NT_STATUS_IS_OK(status)) {
6264 goto out;
6267 status = rename_internals_fsp(conn, fsp, fname_dst, dname,
6268 attrs, replace_if_exists);
6270 TALLOC_FREE(fname_dst);
6272 close_file(req, fsp, NORMAL_CLOSE);
6274 if (!NT_STATUS_IS_OK(status)) {
6275 DEBUG(3, ("rename_internals_fsp returned %s for "
6276 "rename %s -> %s\n", nt_errstr(status),
6277 smb_fname_str_dbg(smb_fname_src),
6278 smb_fname_str_dbg(smb_fname_dst)));
6279 break;
6282 count++;
6284 DEBUG(3,("rename_internals: doing rename on %s -> "
6285 "%s\n", smb_fname_str_dbg(smb_fname_src),
6286 smb_fname_str_dbg(smb_fname_src)));
6289 TALLOC_FREE(dir_hnd);
6291 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6292 status = map_nt_error_from_unix(errno);
6295 out:
6296 TALLOC_FREE(smb_fname_src);
6297 TALLOC_FREE(smb_fname_dst);
6298 TALLOC_FREE(fname_src_dir);
6299 TALLOC_FREE(fname_src_mask);
6300 return status;
6303 /****************************************************************************
6304 Reply to a mv.
6305 ****************************************************************************/
6307 void reply_mv(struct smb_request *req)
6309 connection_struct *conn = req->conn;
6310 char *name = NULL;
6311 char *newname = NULL;
6312 const char *p;
6313 uint32 attrs;
6314 NTSTATUS status;
6315 bool src_has_wcard = False;
6316 bool dest_has_wcard = False;
6317 TALLOC_CTX *ctx = talloc_tos();
6319 START_PROFILE(SMBmv);
6321 if (req->wct < 1) {
6322 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6323 END_PROFILE(SMBmv);
6324 return;
6327 attrs = SVAL(req->vwv+0, 0);
6329 p = (const char *)req->buf + 1;
6330 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6331 &status, &src_has_wcard);
6332 if (!NT_STATUS_IS_OK(status)) {
6333 reply_nterror(req, status);
6334 END_PROFILE(SMBmv);
6335 return;
6337 p++;
6338 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6339 &status, &dest_has_wcard);
6340 if (!NT_STATUS_IS_OK(status)) {
6341 reply_nterror(req, status);
6342 END_PROFILE(SMBmv);
6343 return;
6346 status = resolve_dfspath_wcard(ctx, conn,
6347 req->flags2 & FLAGS2_DFS_PATHNAMES,
6348 name,
6349 &name,
6350 &src_has_wcard);
6351 if (!NT_STATUS_IS_OK(status)) {
6352 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6353 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6354 ERRSRV, ERRbadpath);
6355 END_PROFILE(SMBmv);
6356 return;
6358 reply_nterror(req, status);
6359 END_PROFILE(SMBmv);
6360 return;
6363 status = resolve_dfspath_wcard(ctx, conn,
6364 req->flags2 & FLAGS2_DFS_PATHNAMES,
6365 newname,
6366 &newname,
6367 &dest_has_wcard);
6368 if (!NT_STATUS_IS_OK(status)) {
6369 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6370 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6371 ERRSRV, ERRbadpath);
6372 END_PROFILE(SMBmv);
6373 return;
6375 reply_nterror(req, status);
6376 END_PROFILE(SMBmv);
6377 return;
6380 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
6382 status = rename_internals(ctx, conn, req, name, newname, attrs, False,
6383 src_has_wcard, dest_has_wcard, DELETE_ACCESS);
6384 if (!NT_STATUS_IS_OK(status)) {
6385 if (open_was_deferred(req->mid)) {
6386 /* We have re-scheduled this call. */
6387 END_PROFILE(SMBmv);
6388 return;
6390 reply_nterror(req, status);
6391 END_PROFILE(SMBmv);
6392 return;
6395 reply_outbuf(req, 0, 0);
6397 END_PROFILE(SMBmv);
6398 return;
6401 /*******************************************************************
6402 Copy a file as part of a reply_copy.
6403 ******************************************************************/
6406 * TODO: check error codes on all callers
6409 NTSTATUS copy_file(TALLOC_CTX *ctx,
6410 connection_struct *conn,
6411 struct smb_filename *smb_fname_src,
6412 struct smb_filename *smb_fname_dst,
6413 int ofun,
6414 int count,
6415 bool target_is_directory)
6417 struct smb_filename *smb_fname_dst_tmp = NULL;
6418 char *fname_src = NULL;
6419 char *fname_dst = NULL;
6420 SMB_OFF_T ret=-1;
6421 files_struct *fsp1,*fsp2;
6422 uint32 dosattrs;
6423 uint32 new_create_disposition;
6424 NTSTATUS status;
6427 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6428 if (!NT_STATUS_IS_OK(status)) {
6429 return status;
6433 * If the target is a directory, extract the last component from the
6434 * src filename and append it to the dst filename
6436 if (target_is_directory) {
6437 const char *p;
6439 /* dest/target can't be a stream if it's a directory. */
6440 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6442 p = strrchr_m(smb_fname_src->base_name,'/');
6443 if (p) {
6444 p++;
6445 } else {
6446 p = smb_fname_src->base_name;
6448 smb_fname_dst_tmp->base_name =
6449 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6451 if (!smb_fname_dst_tmp->base_name) {
6452 status = NT_STATUS_NO_MEMORY;
6453 goto out;
6457 status = vfs_file_exist(conn, smb_fname_src);
6458 if (!NT_STATUS_IS_OK(status)) {
6459 goto out;
6462 if (!target_is_directory && count) {
6463 new_create_disposition = FILE_OPEN;
6464 } else {
6465 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
6466 0, ofun, NULL, NULL,
6467 &new_create_disposition,
6468 NULL)) {
6469 status = NT_STATUS_INVALID_PARAMETER;
6470 goto out;
6474 /* Open the src file for reading. */
6475 status = SMB_VFS_CREATE_FILE(
6476 conn, /* conn */
6477 NULL, /* req */
6478 0, /* root_dir_fid */
6479 smb_fname_src, /* fname */
6480 FILE_GENERIC_READ, /* access_mask */
6481 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6482 FILE_OPEN, /* create_disposition*/
6483 0, /* create_options */
6484 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6485 INTERNAL_OPEN_ONLY, /* oplock_request */
6486 0, /* allocation_size */
6487 NULL, /* sd */
6488 NULL, /* ea_list */
6489 &fsp1, /* result */
6490 NULL); /* psbuf */
6492 if (!NT_STATUS_IS_OK(status)) {
6493 goto out;
6496 status = get_full_smb_filename(talloc_tos(), smb_fname_src, &fname_src);
6497 if (!NT_STATUS_IS_OK(status)) {
6498 goto out;
6501 dosattrs = dos_mode(conn, fname_src, &smb_fname_src->st);
6503 TALLOC_FREE(fname_src);
6505 status = get_full_smb_filename(talloc_tos(), smb_fname_dst_tmp, &fname_dst);
6506 if (!NT_STATUS_IS_OK(status)) {
6507 goto out;
6510 if (SMB_VFS_STAT(conn, fname_dst, &smb_fname_dst_tmp->st) == -1) {
6511 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6514 TALLOC_FREE(fname_dst);
6516 /* Open the dst file for writing. */
6517 status = SMB_VFS_CREATE_FILE(
6518 conn, /* conn */
6519 NULL, /* req */
6520 0, /* root_dir_fid */
6521 smb_fname_dst, /* fname */
6522 FILE_GENERIC_WRITE, /* access_mask */
6523 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6524 new_create_disposition, /* create_disposition*/
6525 0, /* create_options */
6526 dosattrs, /* file_attributes */
6527 INTERNAL_OPEN_ONLY, /* oplock_request */
6528 0, /* allocation_size */
6529 NULL, /* sd */
6530 NULL, /* ea_list */
6531 &fsp2, /* result */
6532 NULL); /* psbuf */
6534 if (!NT_STATUS_IS_OK(status)) {
6535 close_file(NULL, fsp1, ERROR_CLOSE);
6536 goto out;
6539 if ((ofun&3) == 1) {
6540 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6541 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6543 * Stop the copy from occurring.
6545 ret = -1;
6546 smb_fname_src->st.st_ex_size = 0;
6550 /* Do the actual copy. */
6551 if (smb_fname_src->st.st_ex_size) {
6552 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6555 close_file(NULL, fsp1, NORMAL_CLOSE);
6557 /* Ensure the modtime is set correctly on the destination file. */
6558 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6561 * As we are opening fsp1 read-only we only expect
6562 * an error on close on fsp2 if we are out of space.
6563 * Thus we don't look at the error return from the
6564 * close of fsp1.
6566 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6568 if (!NT_STATUS_IS_OK(status)) {
6569 goto out;
6572 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6573 status = NT_STATUS_DISK_FULL;
6574 goto out;
6577 status = NT_STATUS_OK;
6579 out:
6580 TALLOC_FREE(smb_fname_dst_tmp);
6581 return status;
6584 /****************************************************************************
6585 Reply to a file copy.
6586 ****************************************************************************/
6588 void reply_copy(struct smb_request *req)
6590 connection_struct *conn = req->conn;
6591 struct smb_filename *smb_fname_src = NULL;
6592 struct smb_filename *smb_fname_dst = NULL;
6593 char *fname_src = NULL;
6594 char *fname_dst = NULL;
6595 char *fname_src_mask = NULL;
6596 char *fname_src_dir = NULL;
6597 const char *p;
6598 int count=0;
6599 int error = ERRnoaccess;
6600 int err = 0;
6601 int tid2;
6602 int ofun;
6603 int flags;
6604 bool target_is_directory=False;
6605 bool source_has_wild = False;
6606 bool dest_has_wild = False;
6607 NTSTATUS status;
6608 TALLOC_CTX *ctx = talloc_tos();
6610 START_PROFILE(SMBcopy);
6612 if (req->wct < 3) {
6613 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6614 goto out;
6617 tid2 = SVAL(req->vwv+0, 0);
6618 ofun = SVAL(req->vwv+1, 0);
6619 flags = SVAL(req->vwv+2, 0);
6621 p = (const char *)req->buf;
6622 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6623 &status, &source_has_wild);
6624 if (!NT_STATUS_IS_OK(status)) {
6625 reply_nterror(req, status);
6626 goto out;
6628 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6629 &status, &dest_has_wild);
6630 if (!NT_STATUS_IS_OK(status)) {
6631 reply_nterror(req, status);
6632 goto out;
6635 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6637 if (tid2 != conn->cnum) {
6638 /* can't currently handle inter share copies XXXX */
6639 DEBUG(3,("Rejecting inter-share copy\n"));
6640 reply_doserror(req, ERRSRV, ERRinvdevice);
6641 goto out;
6644 status = resolve_dfspath_wcard(ctx, conn,
6645 req->flags2 & FLAGS2_DFS_PATHNAMES,
6646 fname_src,
6647 &fname_src,
6648 &source_has_wild);
6649 if (!NT_STATUS_IS_OK(status)) {
6650 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6651 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6652 ERRSRV, ERRbadpath);
6653 goto out;
6655 reply_nterror(req, status);
6656 goto out;
6659 status = resolve_dfspath_wcard(ctx, conn,
6660 req->flags2 & FLAGS2_DFS_PATHNAMES,
6661 fname_dst,
6662 &fname_dst,
6663 &dest_has_wild);
6664 if (!NT_STATUS_IS_OK(status)) {
6665 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6666 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6667 ERRSRV, ERRbadpath);
6668 goto out;
6670 reply_nterror(req, status);
6671 goto out;
6674 status = unix_convert(ctx, conn, fname_src, &smb_fname_src,
6675 source_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
6676 if (!NT_STATUS_IS_OK(status)) {
6677 reply_nterror(req, status);
6678 goto out;
6681 status = unix_convert(ctx, conn, fname_dst, &smb_fname_dst,
6682 dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
6683 if (!NT_STATUS_IS_OK(status)) {
6684 reply_nterror(req, status);
6685 goto out;
6688 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6690 if ((flags&1) && target_is_directory) {
6691 reply_doserror(req, ERRDOS, ERRbadfile);
6692 goto out;
6695 if ((flags&2) && !target_is_directory) {
6696 reply_doserror(req, ERRDOS, ERRbadpath);
6697 goto out;
6700 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6701 /* wants a tree copy! XXXX */
6702 DEBUG(3,("Rejecting tree copy\n"));
6703 reply_doserror(req, ERRSRV, ERRerror);
6704 goto out;
6707 /* Split up the directory from the filename/mask. */
6708 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6709 &fname_src_dir, &fname_src_mask);
6710 if (!NT_STATUS_IS_OK(status)) {
6711 reply_nterror(req, NT_STATUS_NO_MEMORY);
6712 goto out;
6716 * We should only check the mangled cache
6717 * here if unix_convert failed. This means
6718 * that the path in 'mask' doesn't exist
6719 * on the file system and so we need to look
6720 * for a possible mangle. This patch from
6721 * Tine Smukavec <valentin.smukavec@hermes.si>.
6723 if (!VALID_STAT(smb_fname_src->st) &&
6724 mangle_is_mangled(fname_src_mask, conn->params)) {
6725 char *new_mask = NULL;
6726 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6727 &new_mask, conn->params);
6729 /* Use demangled name if one was successfully found. */
6730 if (new_mask) {
6731 TALLOC_FREE(fname_src_mask);
6732 fname_src_mask = new_mask;
6736 if (!source_has_wild) {
6739 * Only one file needs to be copied. Append the mask back onto
6740 * the directory.
6742 TALLOC_FREE(smb_fname_src->base_name);
6743 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6744 "%s/%s",
6745 fname_src_dir,
6746 fname_src_mask);
6747 if (!smb_fname_src->base_name) {
6748 reply_nterror(req, NT_STATUS_NO_MEMORY);
6749 goto out;
6752 if (dest_has_wild) {
6753 char *fname_dst_mod = NULL;
6754 if (!resolve_wildcards(smb_fname_dst,
6755 smb_fname_src->base_name,
6756 smb_fname_dst->base_name,
6757 &fname_dst_mod)) {
6758 reply_nterror(req, NT_STATUS_NO_MEMORY);
6759 goto out;
6761 TALLOC_FREE(smb_fname_dst->base_name);
6762 smb_fname_dst->base_name = fname_dst_mod;
6765 status = check_name(conn, smb_fname_src->base_name);
6766 if (!NT_STATUS_IS_OK(status)) {
6767 reply_nterror(req, status);
6768 goto out;
6771 status = check_name(conn, smb_fname_dst->base_name);
6772 if (!NT_STATUS_IS_OK(status)) {
6773 reply_nterror(req, status);
6774 goto out;
6777 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
6778 ofun, count, target_is_directory);
6780 if(!NT_STATUS_IS_OK(status)) {
6781 reply_nterror(req, status);
6782 goto out;
6783 } else {
6784 count++;
6786 } else {
6787 struct smb_Dir *dir_hnd = NULL;
6788 const char *dname = NULL;
6789 long offset = 0;
6792 * There is a wildcard that requires us to actually read the
6793 * src dir and copy each file matching the mask to the dst.
6794 * Right now streams won't be copied, but this could
6795 * presumably be added with a nested loop for reach dir entry.
6797 SMB_ASSERT(!smb_fname_src->stream_name);
6798 SMB_ASSERT(!smb_fname_dst->stream_name);
6800 smb_fname_src->stream_name = NULL;
6801 smb_fname_dst->stream_name = NULL;
6803 if (strequal(fname_src_mask,"????????.???")) {
6804 TALLOC_FREE(fname_src_mask);
6805 fname_src_mask = talloc_strdup(ctx, "*");
6806 if (!fname_src_mask) {
6807 reply_nterror(req, NT_STATUS_NO_MEMORY);
6808 goto out;
6812 status = check_name(conn, fname_src_dir);
6813 if (!NT_STATUS_IS_OK(status)) {
6814 reply_nterror(req, status);
6815 goto out;
6818 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
6819 if (dir_hnd == NULL) {
6820 status = map_nt_error_from_unix(errno);
6821 reply_nterror(req, status);
6822 goto out;
6825 error = ERRbadfile;
6827 /* Iterate over the src dir copying each entry to the dst. */
6828 while ((dname = ReadDirName(dir_hnd, &offset,
6829 &smb_fname_src->st))) {
6830 char *destname = NULL;
6832 if (ISDOT(dname) || ISDOTDOT(dname)) {
6833 continue;
6836 if (!is_visible_file(conn, fname_src_dir, dname,
6837 &smb_fname_src->st, false)) {
6838 continue;
6841 if(!mask_match(dname, fname_src_mask,
6842 conn->case_sensitive)) {
6843 continue;
6846 error = ERRnoaccess;
6848 /* Get the src smb_fname struct setup. */
6849 TALLOC_FREE(smb_fname_src->base_name);
6850 smb_fname_src->base_name =
6851 talloc_asprintf(smb_fname_src, "%s/%s",
6852 fname_src_dir, dname);
6854 if (!smb_fname_src->base_name) {
6855 TALLOC_FREE(dir_hnd);
6856 reply_nterror(req, NT_STATUS_NO_MEMORY);
6857 goto out;
6860 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6861 smb_fname_dst->base_name,
6862 &destname)) {
6863 continue;
6865 if (!destname) {
6866 TALLOC_FREE(dir_hnd);
6867 reply_nterror(req, NT_STATUS_NO_MEMORY);
6868 goto out;
6871 TALLOC_FREE(smb_fname_dst->base_name);
6872 smb_fname_dst->base_name = destname;
6874 status = check_name(conn, smb_fname_src->base_name);
6875 if (!NT_STATUS_IS_OK(status)) {
6876 TALLOC_FREE(dir_hnd);
6877 reply_nterror(req, status);
6878 goto out;
6881 status = check_name(conn, smb_fname_dst->base_name);
6882 if (!NT_STATUS_IS_OK(status)) {
6883 TALLOC_FREE(dir_hnd);
6884 reply_nterror(req, status);
6885 goto out;
6888 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
6889 smb_fname_src->base_name,
6890 smb_fname_dst->base_name));
6892 status = copy_file(ctx, conn, smb_fname_src,
6893 smb_fname_dst, ofun, count,
6894 target_is_directory);
6895 if (NT_STATUS_IS_OK(status)) {
6896 count++;
6899 TALLOC_FREE(dir_hnd);
6902 if (count == 0) {
6903 if(err) {
6904 /* Error on close... */
6905 errno = err;
6906 reply_unixerror(req, ERRHRD, ERRgeneral);
6907 goto out;
6910 reply_doserror(req, ERRDOS, error);
6911 goto out;
6914 reply_outbuf(req, 1, 0);
6915 SSVAL(req->outbuf,smb_vwv0,count);
6916 out:
6917 TALLOC_FREE(smb_fname_src);
6918 TALLOC_FREE(smb_fname_dst);
6919 TALLOC_FREE(fname_src);
6920 TALLOC_FREE(fname_dst);
6921 TALLOC_FREE(fname_src_mask);
6922 TALLOC_FREE(fname_src_dir);
6924 END_PROFILE(SMBcopy);
6925 return;
6928 #undef DBGC_CLASS
6929 #define DBGC_CLASS DBGC_LOCKING
6931 /****************************************************************************
6932 Get a lock pid, dealing with large count requests.
6933 ****************************************************************************/
6935 uint32 get_lock_pid(const uint8_t *data, int data_offset,
6936 bool large_file_format)
6938 if(!large_file_format)
6939 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
6940 else
6941 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6944 /****************************************************************************
6945 Get a lock count, dealing with large count requests.
6946 ****************************************************************************/
6948 uint64_t get_lock_count(const uint8_t *data, int data_offset,
6949 bool large_file_format)
6951 uint64_t count = 0;
6953 if(!large_file_format) {
6954 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6955 } else {
6957 #if defined(HAVE_LONGLONG)
6958 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6959 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6960 #else /* HAVE_LONGLONG */
6963 * NT4.x seems to be broken in that it sends large file (64 bit)
6964 * lockingX calls even if the CAP_LARGE_FILES was *not*
6965 * negotiated. For boxes without large unsigned ints truncate the
6966 * lock count by dropping the top 32 bits.
6969 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6970 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6971 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6972 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6973 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6976 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6977 #endif /* HAVE_LONGLONG */
6980 return count;
6983 #if !defined(HAVE_LONGLONG)
6984 /****************************************************************************
6985 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6986 ****************************************************************************/
6988 static uint32 map_lock_offset(uint32 high, uint32 low)
6990 unsigned int i;
6991 uint32 mask = 0;
6992 uint32 highcopy = high;
6995 * Try and find out how many significant bits there are in high.
6998 for(i = 0; highcopy; i++)
6999 highcopy >>= 1;
7002 * We use 31 bits not 32 here as POSIX
7003 * lock offsets may not be negative.
7006 mask = (~0) << (31 - i);
7008 if(low & mask)
7009 return 0; /* Fail. */
7011 high <<= (31 - i);
7013 return (high|low);
7015 #endif /* !defined(HAVE_LONGLONG) */
7017 /****************************************************************************
7018 Get a lock offset, dealing with large offset requests.
7019 ****************************************************************************/
7021 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7022 bool large_file_format, bool *err)
7024 uint64_t offset = 0;
7026 *err = False;
7028 if(!large_file_format) {
7029 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7030 } else {
7032 #if defined(HAVE_LONGLONG)
7033 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7034 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7035 #else /* HAVE_LONGLONG */
7038 * NT4.x seems to be broken in that it sends large file (64 bit)
7039 * lockingX calls even if the CAP_LARGE_FILES was *not*
7040 * negotiated. For boxes without large unsigned ints mangle the
7041 * lock offset by mapping the top 32 bits onto the lower 32.
7044 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7045 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7046 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7047 uint32 new_low = 0;
7049 if((new_low = map_lock_offset(high, low)) == 0) {
7050 *err = True;
7051 return (uint64_t)-1;
7054 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7055 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7056 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7057 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7060 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7061 #endif /* HAVE_LONGLONG */
7064 return offset;
7067 /****************************************************************************
7068 Reply to a lockingX request.
7069 ****************************************************************************/
7071 void reply_lockingX(struct smb_request *req)
7073 connection_struct *conn = req->conn;
7074 files_struct *fsp;
7075 unsigned char locktype;
7076 unsigned char oplocklevel;
7077 uint16 num_ulocks;
7078 uint16 num_locks;
7079 uint64_t count = 0, offset = 0;
7080 uint32 lock_pid;
7081 int32 lock_timeout;
7082 int i;
7083 const uint8_t *data;
7084 bool large_file_format;
7085 bool err;
7086 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7088 START_PROFILE(SMBlockingX);
7090 if (req->wct < 8) {
7091 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7092 END_PROFILE(SMBlockingX);
7093 return;
7096 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7097 locktype = CVAL(req->vwv+3, 0);
7098 oplocklevel = CVAL(req->vwv+3, 1);
7099 num_ulocks = SVAL(req->vwv+6, 0);
7100 num_locks = SVAL(req->vwv+7, 0);
7101 lock_timeout = IVAL(req->vwv+4, 0);
7102 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7104 if (!check_fsp(conn, req, fsp)) {
7105 END_PROFILE(SMBlockingX);
7106 return;
7109 data = req->buf;
7111 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7112 /* we don't support these - and CANCEL_LOCK makes w2k
7113 and XP reboot so I don't really want to be
7114 compatible! (tridge) */
7115 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
7116 END_PROFILE(SMBlockingX);
7117 return;
7120 /* Check if this is an oplock break on a file
7121 we have granted an oplock on.
7123 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7124 /* Client can insist on breaking to none. */
7125 bool break_to_none = (oplocklevel == 0);
7126 bool result;
7128 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7129 "for fnum = %d\n", (unsigned int)oplocklevel,
7130 fsp->fnum ));
7133 * Make sure we have granted an exclusive or batch oplock on
7134 * this file.
7137 if (fsp->oplock_type == 0) {
7139 /* The Samba4 nbench simulator doesn't understand
7140 the difference between break to level2 and break
7141 to none from level2 - it sends oplock break
7142 replies in both cases. Don't keep logging an error
7143 message here - just ignore it. JRA. */
7145 DEBUG(5,("reply_lockingX: Error : oplock break from "
7146 "client for fnum = %d (oplock=%d) and no "
7147 "oplock granted on this file (%s).\n",
7148 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
7150 /* if this is a pure oplock break request then don't
7151 * send a reply */
7152 if (num_locks == 0 && num_ulocks == 0) {
7153 END_PROFILE(SMBlockingX);
7154 return;
7155 } else {
7156 END_PROFILE(SMBlockingX);
7157 reply_doserror(req, ERRDOS, ERRlock);
7158 return;
7162 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7163 (break_to_none)) {
7164 result = remove_oplock(fsp);
7165 } else {
7166 result = downgrade_oplock(fsp);
7169 if (!result) {
7170 DEBUG(0, ("reply_lockingX: error in removing "
7171 "oplock on file %s\n", fsp->fsp_name));
7172 /* Hmmm. Is this panic justified? */
7173 smb_panic("internal tdb error");
7176 reply_to_oplock_break_requests(fsp);
7178 /* if this is a pure oplock break request then don't send a
7179 * reply */
7180 if (num_locks == 0 && num_ulocks == 0) {
7181 /* Sanity check - ensure a pure oplock break is not a
7182 chained request. */
7183 if(CVAL(req->vwv+0, 0) != 0xff)
7184 DEBUG(0,("reply_lockingX: Error : pure oplock "
7185 "break is a chained %d request !\n",
7186 (unsigned int)CVAL(req->vwv+0, 0)));
7187 END_PROFILE(SMBlockingX);
7188 return;
7192 if (req->buflen <
7193 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7194 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7195 END_PROFILE(SMBlockingX);
7196 return;
7199 /* Data now points at the beginning of the list
7200 of smb_unlkrng structs */
7201 for(i = 0; i < (int)num_ulocks; i++) {
7202 lock_pid = get_lock_pid( data, i, large_file_format);
7203 count = get_lock_count( data, i, large_file_format);
7204 offset = get_lock_offset( data, i, large_file_format, &err);
7207 * There is no error code marked "stupid client bug".... :-).
7209 if(err) {
7210 END_PROFILE(SMBlockingX);
7211 reply_doserror(req, ERRDOS, ERRnoaccess);
7212 return;
7215 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
7216 "pid %u, file %s\n", (double)offset, (double)count,
7217 (unsigned int)lock_pid, fsp->fsp_name ));
7219 status = do_unlock(smbd_messaging_context(),
7220 fsp,
7221 lock_pid,
7222 count,
7223 offset,
7224 WINDOWS_LOCK);
7226 DEBUG(10, ("reply_lockingX: unlock returned %s\n",
7227 nt_errstr(status)));
7229 if (NT_STATUS_V(status)) {
7230 END_PROFILE(SMBlockingX);
7231 reply_nterror(req, status);
7232 return;
7236 /* Setup the timeout in seconds. */
7238 if (!lp_blocking_locks(SNUM(conn))) {
7239 lock_timeout = 0;
7242 /* Now do any requested locks */
7243 data += ((large_file_format ? 20 : 10)*num_ulocks);
7245 /* Data now points at the beginning of the list
7246 of smb_lkrng structs */
7248 for(i = 0; i < (int)num_locks; i++) {
7249 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
7250 READ_LOCK:WRITE_LOCK);
7251 lock_pid = get_lock_pid( data, i, large_file_format);
7252 count = get_lock_count( data, i, large_file_format);
7253 offset = get_lock_offset( data, i, large_file_format, &err);
7256 * There is no error code marked "stupid client bug".... :-).
7258 if(err) {
7259 END_PROFILE(SMBlockingX);
7260 reply_doserror(req, ERRDOS, ERRnoaccess);
7261 return;
7264 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
7265 "%u, file %s timeout = %d\n", (double)offset,
7266 (double)count, (unsigned int)lock_pid,
7267 fsp->fsp_name, (int)lock_timeout ));
7269 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7270 struct blocking_lock_record *blr = NULL;
7272 if (lp_blocking_locks(SNUM(conn))) {
7274 /* Schedule a message to ourselves to
7275 remove the blocking lock record and
7276 return the right error. */
7278 blr = blocking_lock_cancel(fsp,
7279 lock_pid,
7280 offset,
7281 count,
7282 WINDOWS_LOCK,
7283 locktype,
7284 NT_STATUS_FILE_LOCK_CONFLICT);
7285 if (blr == NULL) {
7286 END_PROFILE(SMBlockingX);
7287 reply_nterror(
7288 req,
7289 NT_STATUS_DOS(
7290 ERRDOS,
7291 ERRcancelviolation));
7292 return;
7295 /* Remove a matching pending lock. */
7296 status = do_lock_cancel(fsp,
7297 lock_pid,
7298 count,
7299 offset,
7300 WINDOWS_LOCK,
7301 blr);
7302 } else {
7303 bool blocking_lock = lock_timeout ? True : False;
7304 bool defer_lock = False;
7305 struct byte_range_lock *br_lck;
7306 uint32 block_smbpid;
7308 br_lck = do_lock(smbd_messaging_context(),
7309 fsp,
7310 lock_pid,
7311 count,
7312 offset,
7313 lock_type,
7314 WINDOWS_LOCK,
7315 blocking_lock,
7316 &status,
7317 &block_smbpid,
7318 NULL);
7320 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7321 /* Windows internal resolution for blocking locks seems
7322 to be about 200ms... Don't wait for less than that. JRA. */
7323 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
7324 lock_timeout = lp_lock_spin_time();
7326 defer_lock = True;
7329 /* This heuristic seems to match W2K3 very well. If a
7330 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7331 it pretends we asked for a timeout of between 150 - 300 milliseconds as
7332 far as I can tell. Replacement for do_lock_spin(). JRA. */
7334 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
7335 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
7336 defer_lock = True;
7337 lock_timeout = lp_lock_spin_time();
7340 if (br_lck && defer_lock) {
7342 * A blocking lock was requested. Package up
7343 * this smb into a queued request and push it
7344 * onto the blocking lock queue.
7346 if(push_blocking_lock_request(br_lck,
7347 req,
7348 fsp,
7349 lock_timeout,
7351 lock_pid,
7352 lock_type,
7353 WINDOWS_LOCK,
7354 offset,
7355 count,
7356 block_smbpid)) {
7357 TALLOC_FREE(br_lck);
7358 END_PROFILE(SMBlockingX);
7359 return;
7363 TALLOC_FREE(br_lck);
7366 if (NT_STATUS_V(status)) {
7367 END_PROFILE(SMBlockingX);
7368 reply_nterror(req, status);
7369 return;
7373 /* If any of the above locks failed, then we must unlock
7374 all of the previous locks (X/Open spec). */
7376 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
7377 (i != num_locks) &&
7378 (num_locks != 0)) {
7380 * Ensure we don't do a remove on the lock that just failed,
7381 * as under POSIX rules, if we have a lock already there, we
7382 * will delete it (and we shouldn't) .....
7384 for(i--; i >= 0; i--) {
7385 lock_pid = get_lock_pid( data, i, large_file_format);
7386 count = get_lock_count( data, i, large_file_format);
7387 offset = get_lock_offset( data, i, large_file_format,
7388 &err);
7391 * There is no error code marked "stupid client
7392 * bug".... :-).
7394 if(err) {
7395 END_PROFILE(SMBlockingX);
7396 reply_doserror(req, ERRDOS, ERRnoaccess);
7397 return;
7400 do_unlock(smbd_messaging_context(),
7401 fsp,
7402 lock_pid,
7403 count,
7404 offset,
7405 WINDOWS_LOCK);
7407 END_PROFILE(SMBlockingX);
7408 reply_nterror(req, status);
7409 return;
7412 reply_outbuf(req, 2, 0);
7414 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7415 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7417 END_PROFILE(SMBlockingX);
7418 chain_reply(req);
7421 #undef DBGC_CLASS
7422 #define DBGC_CLASS DBGC_ALL
7424 /****************************************************************************
7425 Reply to a SMBreadbmpx (read block multiplex) request.
7426 Always reply with an error, if someone has a platform really needs this,
7427 please contact vl@samba.org
7428 ****************************************************************************/
7430 void reply_readbmpx(struct smb_request *req)
7432 START_PROFILE(SMBreadBmpx);
7433 reply_doserror(req, ERRSRV, ERRuseSTD);
7434 END_PROFILE(SMBreadBmpx);
7435 return;
7438 /****************************************************************************
7439 Reply to a SMBreadbs (read block multiplex secondary) request.
7440 Always reply with an error, if someone has a platform really needs this,
7441 please contact vl@samba.org
7442 ****************************************************************************/
7444 void reply_readbs(struct smb_request *req)
7446 START_PROFILE(SMBreadBs);
7447 reply_doserror(req, ERRSRV, ERRuseSTD);
7448 END_PROFILE(SMBreadBs);
7449 return;
7452 /****************************************************************************
7453 Reply to a SMBsetattrE.
7454 ****************************************************************************/
7456 void reply_setattrE(struct smb_request *req)
7458 connection_struct *conn = req->conn;
7459 struct smb_file_time ft;
7460 files_struct *fsp;
7461 SMB_STRUCT_STAT sbuf;
7462 NTSTATUS status;
7464 START_PROFILE(SMBsetattrE);
7465 ZERO_STRUCT(ft);
7467 if (req->wct < 7) {
7468 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7469 END_PROFILE(SMBsetattrE);
7470 return;
7473 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7475 if(!fsp || (fsp->conn != conn)) {
7476 reply_doserror(req, ERRDOS, ERRbadfid);
7477 END_PROFILE(SMBsetattrE);
7478 return;
7483 * Convert the DOS times into unix times.
7486 ft.atime = convert_time_t_to_timespec(
7487 srv_make_unix_date2(req->vwv+3));
7488 ft.mtime = convert_time_t_to_timespec(
7489 srv_make_unix_date2(req->vwv+5));
7490 ft.create_time = convert_time_t_to_timespec(
7491 srv_make_unix_date2(req->vwv+1));
7493 reply_outbuf(req, 0, 0);
7496 * Patch from Ray Frush <frush@engr.colostate.edu>
7497 * Sometimes times are sent as zero - ignore them.
7500 /* Ensure we have a valid stat struct for the source. */
7501 if (fsp->fh->fd != -1) {
7502 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
7503 status = map_nt_error_from_unix(errno);
7504 reply_nterror(req, status);
7505 END_PROFILE(SMBsetattrE);
7506 return;
7508 } else {
7509 int ret = -1;
7511 if (fsp->posix_open) {
7512 ret = SMB_VFS_LSTAT(conn, fsp->fsp_name, &sbuf);
7513 } else {
7514 ret = SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf);
7516 if (ret == -1) {
7517 status = map_nt_error_from_unix(errno);
7518 reply_nterror(req, status);
7519 END_PROFILE(SMBsetattrE);
7520 return;
7524 status = smb_set_file_time(conn, fsp, fsp->fsp_name,
7525 &sbuf, &ft, true);
7526 if (!NT_STATUS_IS_OK(status)) {
7527 reply_doserror(req, ERRDOS, ERRnoaccess);
7528 END_PROFILE(SMBsetattrE);
7529 return;
7532 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7533 " createtime=%u\n",
7534 fsp->fnum,
7535 (unsigned int)ft.atime.tv_sec,
7536 (unsigned int)ft.mtime.tv_sec,
7537 (unsigned int)ft.create_time.tv_sec
7540 END_PROFILE(SMBsetattrE);
7541 return;
7545 /* Back from the dead for OS/2..... JRA. */
7547 /****************************************************************************
7548 Reply to a SMBwritebmpx (write block multiplex primary) request.
7549 Always reply with an error, if someone has a platform really needs this,
7550 please contact vl@samba.org
7551 ****************************************************************************/
7553 void reply_writebmpx(struct smb_request *req)
7555 START_PROFILE(SMBwriteBmpx);
7556 reply_doserror(req, ERRSRV, ERRuseSTD);
7557 END_PROFILE(SMBwriteBmpx);
7558 return;
7561 /****************************************************************************
7562 Reply to a SMBwritebs (write block multiplex secondary) request.
7563 Always reply with an error, if someone has a platform really needs this,
7564 please contact vl@samba.org
7565 ****************************************************************************/
7567 void reply_writebs(struct smb_request *req)
7569 START_PROFILE(SMBwriteBs);
7570 reply_doserror(req, ERRSRV, ERRuseSTD);
7571 END_PROFILE(SMBwriteBs);
7572 return;
7575 /****************************************************************************
7576 Reply to a SMBgetattrE.
7577 ****************************************************************************/
7579 void reply_getattrE(struct smb_request *req)
7581 connection_struct *conn = req->conn;
7582 SMB_STRUCT_STAT sbuf;
7583 int mode;
7584 files_struct *fsp;
7585 struct timespec create_ts;
7587 START_PROFILE(SMBgetattrE);
7589 if (req->wct < 1) {
7590 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7591 END_PROFILE(SMBgetattrE);
7592 return;
7595 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7597 if(!fsp || (fsp->conn != conn)) {
7598 reply_doserror(req, ERRDOS, ERRbadfid);
7599 END_PROFILE(SMBgetattrE);
7600 return;
7603 /* Do an fstat on this file */
7604 if(fsp_stat(fsp, &sbuf)) {
7605 reply_unixerror(req, ERRDOS, ERRnoaccess);
7606 END_PROFILE(SMBgetattrE);
7607 return;
7610 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7613 * Convert the times into dos times. Set create
7614 * date to be last modify date as UNIX doesn't save
7615 * this.
7618 reply_outbuf(req, 11, 0);
7620 create_ts = sbuf.st_ex_btime;
7621 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7622 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7623 convert_timespec_to_time_t(sbuf.st_ex_atime));
7624 /* Should we check pending modtime here ? JRA */
7625 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7626 convert_timespec_to_time_t(sbuf.st_ex_mtime));
7628 if (mode & aDIR) {
7629 SIVAL(req->outbuf, smb_vwv6, 0);
7630 SIVAL(req->outbuf, smb_vwv8, 0);
7631 } else {
7632 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &sbuf);
7633 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_ex_size);
7634 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7636 SSVAL(req->outbuf,smb_vwv10, mode);
7638 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7640 END_PROFILE(SMBgetattrE);
7641 return;