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
29 #include "smbd/globals.h"
31 /****************************************************************************
32 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
33 path or anything including wildcards.
34 We're assuming here that '/' is not the second byte in any multibyte char
35 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
37 ****************************************************************************/
39 /* Custom version for processing POSIX paths. */
40 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
42 static NTSTATUS check_path_syntax_internal(char *path,
44 bool *p_last_component_contains_wcard)
48 NTSTATUS ret = NT_STATUS_OK;
49 bool start_of_name_component = True;
50 bool stream_started = false;
52 *p_last_component_contains_wcard = False;
59 return NT_STATUS_OBJECT_NAME_INVALID;
62 return NT_STATUS_OBJECT_NAME_INVALID;
64 if (strchr_m(&s[1], ':')) {
65 return NT_STATUS_OBJECT_NAME_INVALID;
71 if ((*s == ':') && !posix_path && !stream_started) {
72 if (*p_last_component_contains_wcard) {
73 return NT_STATUS_OBJECT_NAME_INVALID;
75 /* Stream names allow more characters than file names.
76 We're overloading posix_path here to allow a wider
77 range of characters. If stream_started is true this
78 is still a Windows path even if posix_path is true.
81 stream_started = true;
82 start_of_name_component = false;
86 return NT_STATUS_OBJECT_NAME_INVALID;
90 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
92 * Safe to assume is not the second part of a mb char
93 * as this is handled below.
95 /* Eat multiple '/' or '\\' */
96 while (IS_PATH_SEP(*s,posix_path)) {
99 if ((d != path) && (*s != '\0')) {
100 /* We only care about non-leading or trailing '/' or '\\' */
104 start_of_name_component = True;
106 *p_last_component_contains_wcard = False;
110 if (start_of_name_component) {
111 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
112 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
115 * No mb char starts with '.' so we're safe checking the directory separator here.
118 /* If we just added a '/' - delete it */
119 if ((d > path) && (*(d-1) == '/')) {
124 /* Are we at the start ? Can't go back further if so. */
126 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
129 /* Go back one level... */
130 /* We know this is safe as '/' cannot be part of a mb sequence. */
131 /* NOTE - if this assumption is invalid we are not in good shape... */
132 /* Decrement d first as d points to the *next* char to write into. */
133 for (d--; d > path; d--) {
137 s += 2; /* Else go past the .. */
138 /* We're still at the start of a name component, just the previous one. */
141 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
153 if (*s <= 0x1f || *s == '|') {
154 return NT_STATUS_OBJECT_NAME_INVALID;
162 *p_last_component_contains_wcard = True;
171 /* Get the size of the next MB character. */
172 next_codepoint(s,&siz);
190 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
192 return NT_STATUS_INVALID_PARAMETER;
195 start_of_name_component = False;
203 /****************************************************************************
204 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
205 No wildcards allowed.
206 ****************************************************************************/
208 NTSTATUS check_path_syntax(char *path)
211 return check_path_syntax_internal(path, False, &ignore);
214 /****************************************************************************
215 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
216 Wildcards allowed - p_contains_wcard returns true if the last component contained
218 ****************************************************************************/
220 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
222 return check_path_syntax_internal(path, False, p_contains_wcard);
225 /****************************************************************************
226 Check the path for a POSIX client.
227 We're assuming here that '/' is not the second byte in any multibyte char
228 set (a safe assumption).
229 ****************************************************************************/
231 NTSTATUS check_path_syntax_posix(char *path)
234 return check_path_syntax_internal(path, True, &ignore);
237 /****************************************************************************
238 Pull a string and check the path allowing a wilcard - provide for error return.
239 ****************************************************************************/
241 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
242 const char *base_ptr,
249 bool *contains_wcard)
255 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
259 *err = NT_STATUS_INVALID_PARAMETER;
263 *contains_wcard = False;
265 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
267 * For a DFS path the function parse_dfs_path()
268 * will do the path processing, just make a copy.
274 if (lp_posix_pathnames()) {
275 *err = check_path_syntax_posix(*pp_dest);
277 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
283 /****************************************************************************
284 Pull a string and check the path - provide for error return.
285 ****************************************************************************/
287 size_t srvstr_get_path(TALLOC_CTX *ctx,
288 const char *base_ptr,
297 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
298 src_len, flags, err, &ignore);
301 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
302 char **pp_dest, const char *src, int flags,
303 NTSTATUS *err, bool *contains_wcard)
305 return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
306 pp_dest, src, smbreq_bufrem(req, src),
307 flags, err, contains_wcard);
310 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
311 char **pp_dest, const char *src, int flags,
315 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
316 flags, err, &ignore);
319 /****************************************************************************
320 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
321 ****************************************************************************/
323 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
326 if ((fsp == NULL) || (conn == NULL)) {
327 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
330 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
331 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
337 /****************************************************************************
338 Check if we have a correct fsp pointing to a file.
339 ****************************************************************************/
341 bool check_fsp(connection_struct *conn, struct smb_request *req,
344 if (!check_fsp_open(conn, req, fsp)) {
347 if (fsp->is_directory) {
348 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
351 if (fsp->fh->fd == -1) {
352 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
355 fsp->num_smb_operations++;
359 /****************************************************************************
360 Check if we have a correct fsp pointing to a quota fake file. Replacement for
361 the CHECK_NTQUOTA_HANDLE_OK macro.
362 ****************************************************************************/
364 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
367 if (!check_fsp_open(conn, req, fsp)) {
371 if (fsp->is_directory) {
375 if (fsp->fake_file_handle == NULL) {
379 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
383 if (fsp->fake_file_handle->private_data == NULL) {
390 static bool netbios_session_retarget(const char *name, int name_type)
393 char *trim_name_type;
394 const char *retarget_parm;
397 int retarget_type = 0x20;
398 int retarget_port = 139;
399 struct sockaddr_storage retarget_addr;
400 struct sockaddr_in *in_addr;
404 if (get_socket_port(smbd_server_fd()) != 139) {
408 trim_name = talloc_strdup(talloc_tos(), name);
409 if (trim_name == NULL) {
412 trim_char(trim_name, ' ', ' ');
414 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
416 if (trim_name_type == NULL) {
420 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
421 trim_name_type, NULL);
422 if (retarget_parm == NULL) {
423 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
426 if (retarget_parm == NULL) {
430 retarget = talloc_strdup(trim_name, retarget_parm);
431 if (retarget == NULL) {
435 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
437 p = strchr(retarget, ':');
440 retarget_port = atoi(p);
443 p = strchr_m(retarget, '#');
446 sscanf(p, "%x", &retarget_type);
449 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
451 DEBUG(10, ("could not resolve %s\n", retarget));
455 if (retarget_addr.ss_family != AF_INET) {
456 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
460 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
462 _smb_setlen(outbuf, 6);
463 SCVAL(outbuf, 0, 0x84);
464 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
465 *(uint16_t *)(outbuf+8) = htons(retarget_port);
467 if (!srv_send_smb(smbd_server_fd(), (char *)outbuf, false, 0, false,
469 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
475 TALLOC_FREE(trim_name);
479 /****************************************************************************
480 Reply to a (netbios-level) special message.
481 ****************************************************************************/
483 void reply_special(struct smbd_server_connection *sconn, char *inbuf)
485 int msg_type = CVAL(inbuf,0);
486 int msg_flags = CVAL(inbuf,1);
488 char name_type1, name_type2;
491 * We only really use 4 bytes of the outbuf, but for the smb_setlen
492 * calculation & friends (srv_send_smb uses that) we need the full smb
495 char outbuf[smb_size];
499 memset(outbuf, '\0', sizeof(outbuf));
501 smb_setlen(outbuf,0);
504 case 0x81: /* session request */
506 if (sconn->nbt.got_session) {
507 exit_server_cleanly("multiple session request not permitted");
510 SCVAL(outbuf,0,0x82);
512 if (name_len(inbuf+4) > 50 ||
513 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
514 DEBUG(0,("Invalid name length in session request\n"));
517 name_type1 = name_extract(inbuf,4,name1);
518 name_type2 = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
519 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
520 name1, name_type1, name2, name_type2));
522 if (netbios_session_retarget(name1, name_type1)) {
523 exit_server_cleanly("retargeted client");
526 set_local_machine_name(name1, True);
527 set_remote_machine_name(name2, True);
529 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
530 get_local_machine_name(), get_remote_machine_name(),
533 if (name_type2 == 'R') {
534 /* We are being asked for a pathworks session ---
536 SCVAL(outbuf, 0,0x83);
540 /* only add the client's machine name to the list
541 of possibly valid usernames if we are operating
542 in share mode security */
543 if (lp_security() == SEC_SHARE) {
544 add_session_user(sconn, get_remote_machine_name());
547 reload_services(True);
550 sconn->nbt.got_session = true;
553 case 0x89: /* session keepalive request
554 (some old clients produce this?) */
555 SCVAL(outbuf,0,SMBkeepalive);
559 case 0x82: /* positive session response */
560 case 0x83: /* negative session response */
561 case 0x84: /* retarget session response */
562 DEBUG(0,("Unexpected session response\n"));
565 case SMBkeepalive: /* session keepalive */
570 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
571 msg_type, msg_flags));
573 srv_send_smb(smbd_server_fd(), outbuf, false, 0, false, NULL);
577 /****************************************************************************
579 conn POINTER CAN BE NULL HERE !
580 ****************************************************************************/
582 void reply_tcon(struct smb_request *req)
584 connection_struct *conn = req->conn;
586 char *service_buf = NULL;
587 char *password = NULL;
592 DATA_BLOB password_blob;
593 TALLOC_CTX *ctx = talloc_tos();
594 struct smbd_server_connection *sconn = req->sconn;
596 START_PROFILE(SMBtcon);
598 if (req->buflen < 4) {
599 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
600 END_PROFILE(SMBtcon);
604 p = (const char *)req->buf + 1;
605 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
607 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
609 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
612 if (service_buf == NULL || password == NULL || dev == NULL) {
613 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
614 END_PROFILE(SMBtcon);
617 p = strrchr_m(service_buf,'\\');
621 service = service_buf;
624 password_blob = data_blob(password, pwlen+1);
626 conn = make_connection(sconn,service,password_blob,dev,
627 req->vuid,&nt_status);
630 data_blob_clear_free(&password_blob);
633 reply_nterror(req, nt_status);
634 END_PROFILE(SMBtcon);
638 reply_outbuf(req, 2, 0);
639 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
640 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
641 SSVAL(req->outbuf,smb_tid,conn->cnum);
643 DEBUG(3,("tcon service=%s cnum=%d\n",
644 service, conn->cnum));
646 END_PROFILE(SMBtcon);
650 /****************************************************************************
651 Reply to a tcon and X.
652 conn POINTER CAN BE NULL HERE !
653 ****************************************************************************/
655 void reply_tcon_and_X(struct smb_request *req)
657 connection_struct *conn = req->conn;
658 const char *service = NULL;
660 TALLOC_CTX *ctx = talloc_tos();
661 /* what the cleint thinks the device is */
662 char *client_devicetype = NULL;
663 /* what the server tells the client the share represents */
664 const char *server_devicetype;
670 struct smbd_server_connection *sconn = req->sconn;
672 START_PROFILE(SMBtconX);
675 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
676 END_PROFILE(SMBtconX);
680 passlen = SVAL(req->vwv+3, 0);
681 tcon_flags = SVAL(req->vwv+2, 0);
683 /* we might have to close an old one */
684 if ((tcon_flags & 0x1) && conn) {
685 close_cnum(conn,req->vuid);
690 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
691 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
692 END_PROFILE(SMBtconX);
696 if (sconn->smb1.negprot.encrypted_passwords) {
697 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
698 if (lp_security() == SEC_SHARE) {
700 * Security = share always has a pad byte
701 * after the password.
703 p = (const char *)req->buf + passlen + 1;
705 p = (const char *)req->buf + passlen;
708 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
709 /* Ensure correct termination */
710 password.data[passlen]=0;
711 p = (const char *)req->buf + passlen + 1;
714 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
717 data_blob_clear_free(&password);
718 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
719 END_PROFILE(SMBtconX);
724 * the service name can be either: \\server\share
725 * or share directly like on the DELL PowerVault 705
728 q = strchr_m(path+2,'\\');
730 data_blob_clear_free(&password);
731 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
732 END_PROFILE(SMBtconX);
740 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
741 &client_devicetype, p,
742 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
744 if (client_devicetype == NULL) {
745 data_blob_clear_free(&password);
746 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
747 END_PROFILE(SMBtconX);
751 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
753 conn = make_connection(sconn, service, password, client_devicetype,
754 req->vuid, &nt_status);
757 data_blob_clear_free(&password);
760 reply_nterror(req, nt_status);
761 END_PROFILE(SMBtconX);
766 server_devicetype = "IPC";
767 else if ( IS_PRINT(conn) )
768 server_devicetype = "LPT1:";
770 server_devicetype = "A:";
772 if (get_Protocol() < PROTOCOL_NT1) {
773 reply_outbuf(req, 2, 0);
774 if (message_push_string(&req->outbuf, server_devicetype,
775 STR_TERMINATE|STR_ASCII) == -1) {
776 reply_nterror(req, NT_STATUS_NO_MEMORY);
777 END_PROFILE(SMBtconX);
781 /* NT sets the fstype of IPC$ to the null string */
782 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
784 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
785 /* Return permissions. */
789 reply_outbuf(req, 7, 0);
792 perm1 = FILE_ALL_ACCESS;
793 perm2 = FILE_ALL_ACCESS;
795 perm1 = CAN_WRITE(conn) ?
800 SIVAL(req->outbuf, smb_vwv3, perm1);
801 SIVAL(req->outbuf, smb_vwv5, perm2);
803 reply_outbuf(req, 3, 0);
806 if ((message_push_string(&req->outbuf, server_devicetype,
807 STR_TERMINATE|STR_ASCII) == -1)
808 || (message_push_string(&req->outbuf, fstype,
809 STR_TERMINATE) == -1)) {
810 reply_nterror(req, NT_STATUS_NO_MEMORY);
811 END_PROFILE(SMBtconX);
815 /* what does setting this bit do? It is set by NT4 and
816 may affect the ability to autorun mounted cdroms */
817 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
818 (lp_csc_policy(SNUM(conn)) << 2));
820 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
821 DEBUG(2,("Serving %s as a Dfs root\n",
822 lp_servicename(SNUM(conn)) ));
823 SSVAL(req->outbuf, smb_vwv2,
824 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
829 DEBUG(3,("tconX service=%s \n",
832 /* set the incoming and outgoing tid to the just created one */
833 SSVAL(req->inbuf,smb_tid,conn->cnum);
834 SSVAL(req->outbuf,smb_tid,conn->cnum);
836 END_PROFILE(SMBtconX);
838 req->tid = conn->cnum;
843 /****************************************************************************
844 Reply to an unknown type.
845 ****************************************************************************/
847 void reply_unknown_new(struct smb_request *req, uint8 type)
849 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
850 smb_fn_name(type), type, type));
851 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
855 /****************************************************************************
857 conn POINTER CAN BE NULL HERE !
858 ****************************************************************************/
860 void reply_ioctl(struct smb_request *req)
862 connection_struct *conn = req->conn;
869 START_PROFILE(SMBioctl);
872 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
873 END_PROFILE(SMBioctl);
877 device = SVAL(req->vwv+1, 0);
878 function = SVAL(req->vwv+2, 0);
879 ioctl_code = (device << 16) + function;
881 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
883 switch (ioctl_code) {
884 case IOCTL_QUERY_JOB_INFO:
888 reply_force_doserror(req, ERRSRV, ERRnosupport);
889 END_PROFILE(SMBioctl);
893 reply_outbuf(req, 8, replysize+1);
894 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
895 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
896 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
897 p = smb_buf(req->outbuf);
898 memset(p, '\0', replysize+1); /* valgrind-safe. */
899 p += 1; /* Allow for alignment */
901 switch (ioctl_code) {
902 case IOCTL_QUERY_JOB_INFO:
904 files_struct *fsp = file_fsp(
905 req, SVAL(req->vwv+0, 0));
907 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
908 END_PROFILE(SMBioctl);
912 if (fsp->print_file) {
913 SSVAL(p, 0, fsp->print_file->rap_jobid);
917 srvstr_push((char *)req->outbuf, req->flags2, p+2,
919 STR_TERMINATE|STR_ASCII);
921 srvstr_push((char *)req->outbuf, req->flags2,
922 p+18, lp_servicename(SNUM(conn)),
923 13, STR_TERMINATE|STR_ASCII);
931 END_PROFILE(SMBioctl);
935 /****************************************************************************
936 Strange checkpath NTSTATUS mapping.
937 ****************************************************************************/
939 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
941 /* Strange DOS error code semantics only for checkpath... */
942 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
943 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
944 /* We need to map to ERRbadpath */
945 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
951 /****************************************************************************
952 Reply to a checkpath.
953 ****************************************************************************/
955 void reply_checkpath(struct smb_request *req)
957 connection_struct *conn = req->conn;
958 struct smb_filename *smb_fname = NULL;
961 TALLOC_CTX *ctx = talloc_tos();
963 START_PROFILE(SMBcheckpath);
965 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
966 STR_TERMINATE, &status);
968 if (!NT_STATUS_IS_OK(status)) {
969 status = map_checkpath_error(req->flags2, status);
970 reply_nterror(req, status);
971 END_PROFILE(SMBcheckpath);
975 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
977 status = filename_convert(ctx,
979 req->flags2 & FLAGS2_DFS_PATHNAMES,
985 if (!NT_STATUS_IS_OK(status)) {
986 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
987 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
989 END_PROFILE(SMBcheckpath);
995 if (!VALID_STAT(smb_fname->st) &&
996 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
997 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
998 smb_fname_str_dbg(smb_fname), strerror(errno)));
999 status = map_nt_error_from_unix(errno);
1003 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1004 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1005 ERRDOS, ERRbadpath);
1009 reply_outbuf(req, 0, 0);
1012 /* We special case this - as when a Windows machine
1013 is parsing a path is steps through the components
1014 one at a time - if a component fails it expects
1015 ERRbadpath, not ERRbadfile.
1017 status = map_checkpath_error(req->flags2, status);
1018 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1020 * Windows returns different error codes if
1021 * the parent directory is valid but not the
1022 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1023 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1024 * if the path is invalid.
1026 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1027 ERRDOS, ERRbadpath);
1031 reply_nterror(req, status);
1034 TALLOC_FREE(smb_fname);
1035 END_PROFILE(SMBcheckpath);
1039 /****************************************************************************
1041 ****************************************************************************/
1043 void reply_getatr(struct smb_request *req)
1045 connection_struct *conn = req->conn;
1046 struct smb_filename *smb_fname = NULL;
1053 TALLOC_CTX *ctx = talloc_tos();
1054 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1056 START_PROFILE(SMBgetatr);
1058 p = (const char *)req->buf + 1;
1059 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1060 if (!NT_STATUS_IS_OK(status)) {
1061 reply_nterror(req, status);
1065 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1066 under WfWg - weird! */
1067 if (*fname == '\0') {
1068 mode = aHIDDEN | aDIR;
1069 if (!CAN_WRITE(conn)) {
1075 status = filename_convert(ctx,
1077 req->flags2 & FLAGS2_DFS_PATHNAMES,
1082 if (!NT_STATUS_IS_OK(status)) {
1083 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1084 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1085 ERRSRV, ERRbadpath);
1088 reply_nterror(req, status);
1091 if (!VALID_STAT(smb_fname->st) &&
1092 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1093 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1094 smb_fname_str_dbg(smb_fname),
1096 reply_nterror(req, map_nt_error_from_unix(errno));
1100 mode = dos_mode(conn, smb_fname);
1101 size = smb_fname->st.st_ex_size;
1103 if (ask_sharemode) {
1104 struct timespec write_time_ts;
1105 struct file_id fileid;
1107 ZERO_STRUCT(write_time_ts);
1108 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1109 get_file_infos(fileid, NULL, &write_time_ts);
1110 if (!null_timespec(write_time_ts)) {
1111 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1115 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
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);
1127 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1129 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1131 if (get_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",
1137 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1140 TALLOC_FREE(smb_fname);
1142 END_PROFILE(SMBgetatr);
1146 /****************************************************************************
1148 ****************************************************************************/
1150 void reply_setatr(struct smb_request *req)
1152 struct smb_file_time ft;
1153 connection_struct *conn = req->conn;
1154 struct smb_filename *smb_fname = NULL;
1160 TALLOC_CTX *ctx = talloc_tos();
1162 START_PROFILE(SMBsetatr);
1167 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1171 p = (const char *)req->buf + 1;
1172 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1173 if (!NT_STATUS_IS_OK(status)) {
1174 reply_nterror(req, status);
1178 status = filename_convert(ctx,
1180 req->flags2 & FLAGS2_DFS_PATHNAMES,
1185 if (!NT_STATUS_IS_OK(status)) {
1186 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1187 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1188 ERRSRV, ERRbadpath);
1191 reply_nterror(req, status);
1195 if (smb_fname->base_name[0] == '.' &&
1196 smb_fname->base_name[1] == '\0') {
1198 * Not sure here is the right place to catch this
1199 * condition. Might be moved to somewhere else later -- vl
1201 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1205 mode = SVAL(req->vwv+0, 0);
1206 mtime = srv_make_unix_date3(req->vwv+1);
1208 ft.mtime = convert_time_t_to_timespec(mtime);
1209 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1210 if (!NT_STATUS_IS_OK(status)) {
1211 reply_nterror(req, status);
1215 if (mode != FILE_ATTRIBUTE_NORMAL) {
1216 if (VALID_STAT_OF_DIR(smb_fname->st))
1221 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1223 reply_nterror(req, map_nt_error_from_unix(errno));
1228 reply_outbuf(req, 0, 0);
1230 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1233 TALLOC_FREE(smb_fname);
1234 END_PROFILE(SMBsetatr);
1238 /****************************************************************************
1240 ****************************************************************************/
1242 void reply_dskattr(struct smb_request *req)
1244 connection_struct *conn = req->conn;
1245 uint64_t dfree,dsize,bsize;
1246 START_PROFILE(SMBdskattr);
1248 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1249 reply_nterror(req, map_nt_error_from_unix(errno));
1250 END_PROFILE(SMBdskattr);
1254 reply_outbuf(req, 5, 0);
1256 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1257 double total_space, free_space;
1258 /* we need to scale this to a number that DOS6 can handle. We
1259 use floating point so we can handle large drives on systems
1260 that don't have 64 bit integers
1262 we end up displaying a maximum of 2G to DOS systems
1264 total_space = dsize * (double)bsize;
1265 free_space = dfree * (double)bsize;
1267 dsize = (uint64_t)((total_space+63*512) / (64*512));
1268 dfree = (uint64_t)((free_space+63*512) / (64*512));
1270 if (dsize > 0xFFFF) dsize = 0xFFFF;
1271 if (dfree > 0xFFFF) dfree = 0xFFFF;
1273 SSVAL(req->outbuf,smb_vwv0,dsize);
1274 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1275 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1276 SSVAL(req->outbuf,smb_vwv3,dfree);
1278 SSVAL(req->outbuf,smb_vwv0,dsize);
1279 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1280 SSVAL(req->outbuf,smb_vwv2,512);
1281 SSVAL(req->outbuf,smb_vwv3,dfree);
1284 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1286 END_PROFILE(SMBdskattr);
1291 * Utility function to split the filename from the directory.
1293 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1294 char **fname_dir_out,
1295 char **fname_mask_out)
1297 const char *p = NULL;
1298 char *fname_dir = NULL;
1299 char *fname_mask = NULL;
1301 p = strrchr_m(fname_in, '/');
1303 fname_dir = talloc_strdup(ctx, ".");
1304 fname_mask = talloc_strdup(ctx, fname_in);
1306 fname_dir = talloc_strndup(ctx, fname_in,
1307 PTR_DIFF(p, fname_in));
1308 fname_mask = talloc_strdup(ctx, p+1);
1311 if (!fname_dir || !fname_mask) {
1312 TALLOC_FREE(fname_dir);
1313 TALLOC_FREE(fname_mask);
1314 return NT_STATUS_NO_MEMORY;
1317 *fname_dir_out = fname_dir;
1318 *fname_mask_out = fname_mask;
1319 return NT_STATUS_OK;
1322 /****************************************************************************
1324 Can be called from SMBsearch, SMBffirst or SMBfunique.
1325 ****************************************************************************/
1327 void reply_search(struct smb_request *req)
1329 connection_struct *conn = req->conn;
1331 const char *mask = NULL;
1332 char *directory = NULL;
1333 struct smb_filename *smb_fname = NULL;
1337 struct timespec date;
1339 unsigned int numentries = 0;
1340 unsigned int maxentries = 0;
1341 bool finished = False;
1346 bool check_descend = False;
1347 bool expect_close = False;
1349 bool mask_contains_wcard = False;
1350 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1351 TALLOC_CTX *ctx = talloc_tos();
1352 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1353 struct dptr_struct *dirptr = NULL;
1354 struct smbd_server_connection *sconn = req->sconn;
1356 START_PROFILE(SMBsearch);
1359 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1363 if (lp_posix_pathnames()) {
1364 reply_unknown_new(req, req->cmd);
1368 /* If we were called as SMBffirst then we must expect close. */
1369 if(req->cmd == SMBffirst) {
1370 expect_close = True;
1373 reply_outbuf(req, 1, 3);
1374 maxentries = SVAL(req->vwv+0, 0);
1375 dirtype = SVAL(req->vwv+1, 0);
1376 p = (const char *)req->buf + 1;
1377 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1378 &nt_status, &mask_contains_wcard);
1379 if (!NT_STATUS_IS_OK(nt_status)) {
1380 reply_nterror(req, nt_status);
1385 status_len = SVAL(p, 0);
1388 /* dirtype &= ~aDIR; */
1390 if (status_len == 0) {
1391 nt_status = filename_convert(ctx, conn,
1392 req->flags2 & FLAGS2_DFS_PATHNAMES,
1394 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1395 &mask_contains_wcard,
1397 if (!NT_STATUS_IS_OK(nt_status)) {
1398 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1399 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1400 ERRSRV, ERRbadpath);
1403 reply_nterror(req, nt_status);
1407 directory = smb_fname->base_name;
1409 p = strrchr_m(directory,'/');
1410 if ((p != NULL) && (*directory != '/')) {
1412 directory = talloc_strndup(ctx, directory,
1413 PTR_DIFF(p, directory));
1416 directory = talloc_strdup(ctx,".");
1420 reply_nterror(req, NT_STATUS_NO_MEMORY);
1424 memset((char *)status,'\0',21);
1425 SCVAL(status,0,(dirtype & 0x1F));
1427 nt_status = dptr_create(conn,
1433 mask_contains_wcard,
1436 if (!NT_STATUS_IS_OK(nt_status)) {
1437 reply_nterror(req, nt_status);
1440 dptr_num = dptr_dnum(dirptr);
1443 const char *dirpath;
1445 memcpy(status,p,21);
1446 status_dirtype = CVAL(status,0) & 0x1F;
1447 if (status_dirtype != (dirtype & 0x1F)) {
1448 dirtype = status_dirtype;
1451 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1455 dirpath = dptr_path(sconn, dptr_num);
1456 directory = talloc_strdup(ctx, dirpath);
1458 reply_nterror(req, NT_STATUS_NO_MEMORY);
1462 mask = dptr_wcard(sconn, dptr_num);
1467 * For a 'continue' search we have no string. So
1468 * check from the initial saved string.
1470 mask_contains_wcard = ms_has_wild(mask);
1471 dirtype = dptr_attr(sconn, dptr_num);
1474 DEBUG(4,("dptr_num is %d\n",dptr_num));
1476 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1477 dptr_init_search_op(dirptr);
1479 if ((dirtype&0x1F) == aVOLID) {
1480 char buf[DIR_STRUCT_SIZE];
1481 memcpy(buf,status,21);
1482 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1483 0,aVOLID,0,!allow_long_path_components)) {
1484 reply_nterror(req, NT_STATUS_NO_MEMORY);
1487 dptr_fill(sconn, buf+12,dptr_num);
1488 if (dptr_zero(buf+12) && (status_len==0)) {
1493 if (message_push_blob(&req->outbuf,
1494 data_blob_const(buf, sizeof(buf)))
1496 reply_nterror(req, NT_STATUS_NO_MEMORY);
1504 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1507 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1508 directory,lp_dontdescend(SNUM(conn))));
1509 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1510 check_descend = True;
1513 for (i=numentries;(i<maxentries) && !finished;i++) {
1514 finished = !get_dir_entry(ctx,
1525 char buf[DIR_STRUCT_SIZE];
1526 memcpy(buf,status,21);
1527 if (!make_dir_struct(ctx,
1533 convert_timespec_to_time_t(date),
1534 !allow_long_path_components)) {
1535 reply_nterror(req, NT_STATUS_NO_MEMORY);
1538 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1541 if (message_push_blob(&req->outbuf,
1542 data_blob_const(buf, sizeof(buf)))
1544 reply_nterror(req, NT_STATUS_NO_MEMORY);
1554 /* If we were called as SMBffirst with smb_search_id == NULL
1555 and no entries were found then return error and close dirptr
1558 if (numentries == 0) {
1559 dptr_close(sconn, &dptr_num);
1560 } else if(expect_close && status_len == 0) {
1561 /* Close the dptr - we know it's gone */
1562 dptr_close(sconn, &dptr_num);
1565 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1566 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1567 dptr_close(sconn, &dptr_num);
1570 if ((numentries == 0) && !mask_contains_wcard) {
1571 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1575 SSVAL(req->outbuf,smb_vwv0,numentries);
1576 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1577 SCVAL(smb_buf(req->outbuf),0,5);
1578 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1580 /* The replies here are never long name. */
1581 SSVAL(req->outbuf, smb_flg2,
1582 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1583 if (!allow_long_path_components) {
1584 SSVAL(req->outbuf, smb_flg2,
1585 SVAL(req->outbuf, smb_flg2)
1586 & (~FLAGS2_LONG_PATH_COMPONENTS));
1589 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1590 SSVAL(req->outbuf, smb_flg2,
1591 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1593 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1594 smb_fn_name(req->cmd),
1601 TALLOC_FREE(directory);
1602 TALLOC_FREE(smb_fname);
1603 END_PROFILE(SMBsearch);
1607 /****************************************************************************
1608 Reply to a fclose (stop directory search).
1609 ****************************************************************************/
1611 void reply_fclose(struct smb_request *req)
1619 bool path_contains_wcard = False;
1620 TALLOC_CTX *ctx = talloc_tos();
1621 struct smbd_server_connection *sconn = req->sconn;
1623 START_PROFILE(SMBfclose);
1625 if (lp_posix_pathnames()) {
1626 reply_unknown_new(req, req->cmd);
1627 END_PROFILE(SMBfclose);
1631 p = (const char *)req->buf + 1;
1632 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1633 &err, &path_contains_wcard);
1634 if (!NT_STATUS_IS_OK(err)) {
1635 reply_nterror(req, err);
1636 END_PROFILE(SMBfclose);
1640 status_len = SVAL(p,0);
1643 if (status_len == 0) {
1644 reply_force_doserror(req, ERRSRV, ERRsrverror);
1645 END_PROFILE(SMBfclose);
1649 memcpy(status,p,21);
1651 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1652 /* Close the dptr - we know it's gone */
1653 dptr_close(sconn, &dptr_num);
1656 reply_outbuf(req, 1, 0);
1657 SSVAL(req->outbuf,smb_vwv0,0);
1659 DEBUG(3,("search close\n"));
1661 END_PROFILE(SMBfclose);
1665 /****************************************************************************
1667 ****************************************************************************/
1669 void reply_open(struct smb_request *req)
1671 connection_struct *conn = req->conn;
1672 struct smb_filename *smb_fname = NULL;
1684 uint32 create_disposition;
1685 uint32 create_options = 0;
1686 uint32_t private_flags = 0;
1688 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1689 TALLOC_CTX *ctx = talloc_tos();
1691 START_PROFILE(SMBopen);
1694 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1698 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1699 deny_mode = SVAL(req->vwv+0, 0);
1700 dos_attr = SVAL(req->vwv+1, 0);
1702 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1703 STR_TERMINATE, &status);
1704 if (!NT_STATUS_IS_OK(status)) {
1705 reply_nterror(req, status);
1709 status = filename_convert(ctx,
1711 req->flags2 & FLAGS2_DFS_PATHNAMES,
1716 if (!NT_STATUS_IS_OK(status)) {
1717 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1718 reply_botherror(req,
1719 NT_STATUS_PATH_NOT_COVERED,
1720 ERRSRV, ERRbadpath);
1723 reply_nterror(req, status);
1727 if (!map_open_params_to_ntcreate(smb_fname, deny_mode,
1728 OPENX_FILE_EXISTS_OPEN, &access_mask,
1729 &share_mode, &create_disposition,
1730 &create_options, &private_flags)) {
1731 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1735 status = SMB_VFS_CREATE_FILE(
1738 0, /* root_dir_fid */
1739 smb_fname, /* fname */
1740 access_mask, /* access_mask */
1741 share_mode, /* share_access */
1742 create_disposition, /* create_disposition*/
1743 create_options, /* create_options */
1744 dos_attr, /* file_attributes */
1745 oplock_request, /* oplock_request */
1746 0, /* allocation_size */
1753 if (!NT_STATUS_IS_OK(status)) {
1754 if (open_was_deferred(req->mid)) {
1755 /* We have re-scheduled this call. */
1758 reply_openerror(req, status);
1762 size = smb_fname->st.st_ex_size;
1763 fattr = dos_mode(conn, smb_fname);
1765 /* Deal with other possible opens having a modified
1767 if (ask_sharemode) {
1768 struct timespec write_time_ts;
1770 ZERO_STRUCT(write_time_ts);
1771 get_file_infos(fsp->file_id, NULL, &write_time_ts);
1772 if (!null_timespec(write_time_ts)) {
1773 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1777 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1780 DEBUG(3,("attempt to open a directory %s\n",
1782 close_file(req, fsp, ERROR_CLOSE);
1783 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1784 ERRDOS, ERRnoaccess);
1788 reply_outbuf(req, 7, 0);
1789 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1790 SSVAL(req->outbuf,smb_vwv1,fattr);
1791 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1792 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1794 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1796 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1797 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1799 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1800 SCVAL(req->outbuf,smb_flg,
1801 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1804 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1805 SCVAL(req->outbuf,smb_flg,
1806 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1809 TALLOC_FREE(smb_fname);
1810 END_PROFILE(SMBopen);
1814 /****************************************************************************
1815 Reply to an open and X.
1816 ****************************************************************************/
1818 void reply_open_and_X(struct smb_request *req)
1820 connection_struct *conn = req->conn;
1821 struct smb_filename *smb_fname = NULL;
1826 /* Breakout the oplock request bits so we can set the
1827 reply bits separately. */
1828 int ex_oplock_request;
1829 int core_oplock_request;
1832 int smb_sattr = SVAL(req->vwv+4, 0);
1833 uint32 smb_time = make_unix_date3(req->vwv+6);
1841 uint64_t allocation_size;
1842 ssize_t retval = -1;
1845 uint32 create_disposition;
1846 uint32 create_options = 0;
1847 uint32_t private_flags = 0;
1848 TALLOC_CTX *ctx = talloc_tos();
1850 START_PROFILE(SMBopenX);
1852 if (req->wct < 15) {
1853 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
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. */
1868 if (lp_nt_pipe_support()) {
1869 reply_open_pipe_and_X(conn, req);
1871 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
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);
1884 status = filename_convert(ctx,
1886 req->flags2 & FLAGS2_DFS_PATHNAMES,
1891 if (!NT_STATUS_IS_OK(status)) {
1892 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1893 reply_botherror(req,
1894 NT_STATUS_PATH_NOT_COVERED,
1895 ERRSRV, ERRbadpath);
1898 reply_nterror(req, status);
1902 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, smb_ofun,
1903 &access_mask, &share_mode,
1904 &create_disposition,
1907 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1911 status = SMB_VFS_CREATE_FILE(
1914 0, /* root_dir_fid */
1915 smb_fname, /* fname */
1916 access_mask, /* access_mask */
1917 share_mode, /* share_access */
1918 create_disposition, /* create_disposition*/
1919 create_options, /* create_options */
1920 smb_attr, /* file_attributes */
1921 oplock_request, /* oplock_request */
1922 0, /* allocation_size */
1927 &smb_action); /* pinfo */
1929 if (!NT_STATUS_IS_OK(status)) {
1930 if (open_was_deferred(req->mid)) {
1931 /* We have re-scheduled this call. */
1934 reply_openerror(req, status);
1938 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1939 if the file is truncated or created. */
1940 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1941 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1942 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1943 close_file(req, fsp, ERROR_CLOSE);
1944 reply_nterror(req, NT_STATUS_DISK_FULL);
1947 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1949 close_file(req, fsp, ERROR_CLOSE);
1950 reply_nterror(req, NT_STATUS_DISK_FULL);
1953 smb_fname->st.st_ex_size =
1954 SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
1957 fattr = dos_mode(conn, smb_fname);
1958 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1960 close_file(req, fsp, ERROR_CLOSE);
1961 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1965 /* If the caller set the extended oplock request bit
1966 and we granted one (by whatever means) - set the
1967 correct bit for extended oplock reply.
1970 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1971 smb_action |= EXTENDED_OPLOCK_GRANTED;
1974 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1975 smb_action |= EXTENDED_OPLOCK_GRANTED;
1978 /* If the caller set the core oplock request bit
1979 and we granted one (by whatever means) - set the
1980 correct bit for core oplock reply.
1983 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1984 reply_outbuf(req, 19, 0);
1986 reply_outbuf(req, 15, 0);
1989 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1990 SCVAL(req->outbuf, smb_flg,
1991 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1994 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1995 SCVAL(req->outbuf, smb_flg,
1996 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1999 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2000 SSVAL(req->outbuf,smb_vwv3,fattr);
2001 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2002 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2004 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2006 SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size);
2007 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2008 SSVAL(req->outbuf,smb_vwv11,smb_action);
2010 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2011 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2016 TALLOC_FREE(smb_fname);
2017 END_PROFILE(SMBopenX);
2021 /****************************************************************************
2022 Reply to a SMBulogoffX.
2023 ****************************************************************************/
2025 void reply_ulogoffX(struct smb_request *req)
2027 struct smbd_server_connection *sconn = req->sconn;
2030 START_PROFILE(SMBulogoffX);
2032 vuser = get_valid_user_struct(sconn, req->vuid);
2035 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2039 /* in user level security we are supposed to close any files
2040 open by this user */
2041 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2042 file_close_user(req->vuid);
2045 invalidate_vuid(sconn, req->vuid);
2047 reply_outbuf(req, 2, 0);
2049 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2051 END_PROFILE(SMBulogoffX);
2052 req->vuid = UID_FIELD_INVALID;
2056 /****************************************************************************
2057 Reply to a mknew or a create.
2058 ****************************************************************************/
2060 void reply_mknew(struct smb_request *req)
2062 connection_struct *conn = req->conn;
2063 struct smb_filename *smb_fname = NULL;
2066 struct smb_file_time ft;
2068 int oplock_request = 0;
2070 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2071 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2072 uint32 create_disposition;
2073 uint32 create_options = 0;
2074 TALLOC_CTX *ctx = talloc_tos();
2076 START_PROFILE(SMBcreate);
2080 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2084 fattr = SVAL(req->vwv+0, 0);
2085 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2088 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2090 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2091 STR_TERMINATE, &status);
2092 if (!NT_STATUS_IS_OK(status)) {
2093 reply_nterror(req, status);
2097 status = filename_convert(ctx,
2099 req->flags2 & FLAGS2_DFS_PATHNAMES,
2104 if (!NT_STATUS_IS_OK(status)) {
2105 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2106 reply_botherror(req,
2107 NT_STATUS_PATH_NOT_COVERED,
2108 ERRSRV, ERRbadpath);
2111 reply_nterror(req, status);
2115 if (fattr & aVOLID) {
2116 DEBUG(0,("Attempt to create file (%s) with volid set - "
2117 "please report this\n",
2118 smb_fname_str_dbg(smb_fname)));
2121 if(req->cmd == SMBmknew) {
2122 /* We should fail if file exists. */
2123 create_disposition = FILE_CREATE;
2125 /* Create if file doesn't exist, truncate if it does. */
2126 create_disposition = FILE_OVERWRITE_IF;
2129 status = SMB_VFS_CREATE_FILE(
2132 0, /* root_dir_fid */
2133 smb_fname, /* fname */
2134 access_mask, /* access_mask */
2135 share_mode, /* share_access */
2136 create_disposition, /* create_disposition*/
2137 create_options, /* create_options */
2138 fattr, /* file_attributes */
2139 oplock_request, /* oplock_request */
2140 0, /* allocation_size */
2141 0, /* private_flags */
2147 if (!NT_STATUS_IS_OK(status)) {
2148 if (open_was_deferred(req->mid)) {
2149 /* We have re-scheduled this call. */
2152 reply_openerror(req, status);
2156 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2157 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2158 if (!NT_STATUS_IS_OK(status)) {
2159 END_PROFILE(SMBcreate);
2163 reply_outbuf(req, 1, 0);
2164 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2166 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2167 SCVAL(req->outbuf,smb_flg,
2168 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2171 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2172 SCVAL(req->outbuf,smb_flg,
2173 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2176 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2177 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2178 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2179 (unsigned int)fattr));
2182 TALLOC_FREE(smb_fname);
2183 END_PROFILE(SMBcreate);
2187 /****************************************************************************
2188 Reply to a create temporary file.
2189 ****************************************************************************/
2191 void reply_ctemp(struct smb_request *req)
2193 connection_struct *conn = req->conn;
2194 struct smb_filename *smb_fname = NULL;
2202 TALLOC_CTX *ctx = talloc_tos();
2204 START_PROFILE(SMBctemp);
2207 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2211 fattr = SVAL(req->vwv+0, 0);
2212 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2214 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2215 STR_TERMINATE, &status);
2216 if (!NT_STATUS_IS_OK(status)) {
2217 reply_nterror(req, status);
2221 fname = talloc_asprintf(ctx,
2225 fname = talloc_strdup(ctx, "TMXXXXXX");
2229 reply_nterror(req, NT_STATUS_NO_MEMORY);
2233 status = filename_convert(ctx, conn,
2234 req->flags2 & FLAGS2_DFS_PATHNAMES,
2239 if (!NT_STATUS_IS_OK(status)) {
2240 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2241 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2242 ERRSRV, ERRbadpath);
2245 reply_nterror(req, status);
2249 tmpfd = mkstemp(smb_fname->base_name);
2251 reply_nterror(req, map_nt_error_from_unix(errno));
2255 SMB_VFS_STAT(conn, smb_fname);
2257 /* We should fail if file does not exist. */
2258 status = SMB_VFS_CREATE_FILE(
2261 0, /* root_dir_fid */
2262 smb_fname, /* fname */
2263 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2264 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2265 FILE_OPEN, /* create_disposition*/
2266 0, /* create_options */
2267 fattr, /* file_attributes */
2268 oplock_request, /* oplock_request */
2269 0, /* allocation_size */
2270 0, /* private_flags */
2276 /* close fd from mkstemp() */
2279 if (!NT_STATUS_IS_OK(status)) {
2280 if (open_was_deferred(req->mid)) {
2281 /* We have re-scheduled this call. */
2284 reply_openerror(req, status);
2288 reply_outbuf(req, 1, 0);
2289 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2291 /* the returned filename is relative to the directory */
2292 s = strrchr_m(fsp->fsp_name->base_name, '/');
2294 s = fsp->fsp_name->base_name;
2300 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2301 thing in the byte section. JRA */
2302 SSVALS(p, 0, -1); /* what is this? not in spec */
2304 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2306 reply_nterror(req, NT_STATUS_NO_MEMORY);
2310 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2311 SCVAL(req->outbuf, smb_flg,
2312 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2315 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2316 SCVAL(req->outbuf, smb_flg,
2317 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2320 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2321 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2322 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2324 TALLOC_FREE(smb_fname);
2325 END_PROFILE(SMBctemp);
2329 /*******************************************************************
2330 Check if a user is allowed to rename a file.
2331 ********************************************************************/
2333 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2338 if (!CAN_WRITE(conn)) {
2339 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2342 fmode = dos_mode(conn, fsp->fsp_name);
2343 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2344 return NT_STATUS_NO_SUCH_FILE;
2347 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2348 if (fsp->posix_open) {
2349 return NT_STATUS_OK;
2352 /* If no pathnames are open below this
2353 directory, allow the rename. */
2355 if (file_find_subpath(fsp)) {
2356 return NT_STATUS_ACCESS_DENIED;
2358 return NT_STATUS_OK;
2361 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2362 return NT_STATUS_OK;
2365 return NT_STATUS_ACCESS_DENIED;
2368 /*******************************************************************
2369 * unlink a file with all relevant access checks
2370 *******************************************************************/
2372 static NTSTATUS do_unlink(connection_struct *conn,
2373 struct smb_request *req,
2374 struct smb_filename *smb_fname,
2379 uint32 dirtype_orig = dirtype;
2382 bool posix_paths = lp_posix_pathnames();
2384 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2385 smb_fname_str_dbg(smb_fname),
2388 if (!CAN_WRITE(conn)) {
2389 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2393 ret = SMB_VFS_LSTAT(conn, smb_fname);
2395 ret = SMB_VFS_STAT(conn, smb_fname);
2398 return map_nt_error_from_unix(errno);
2401 fattr = dos_mode(conn, smb_fname);
2403 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2404 dirtype = aDIR|aARCH|aRONLY;
2407 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2409 return NT_STATUS_NO_SUCH_FILE;
2412 if (!dir_check_ftype(conn, fattr, dirtype)) {
2414 return NT_STATUS_FILE_IS_A_DIRECTORY;
2416 return NT_STATUS_NO_SUCH_FILE;
2419 if (dirtype_orig & 0x8000) {
2420 /* These will never be set for POSIX. */
2421 return NT_STATUS_NO_SUCH_FILE;
2425 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2426 return NT_STATUS_FILE_IS_A_DIRECTORY;
2429 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2430 return NT_STATUS_NO_SUCH_FILE;
2433 if (dirtype & 0xFF00) {
2434 /* These will never be set for POSIX. */
2435 return NT_STATUS_NO_SUCH_FILE;
2440 return NT_STATUS_NO_SUCH_FILE;
2443 /* Can't delete a directory. */
2445 return NT_STATUS_FILE_IS_A_DIRECTORY;
2450 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2451 return NT_STATUS_OBJECT_NAME_INVALID;
2452 #endif /* JRATEST */
2454 /* On open checks the open itself will check the share mode, so
2455 don't do it here as we'll get it wrong. */
2457 status = SMB_VFS_CREATE_FILE
2460 0, /* root_dir_fid */
2461 smb_fname, /* fname */
2462 DELETE_ACCESS, /* access_mask */
2463 FILE_SHARE_NONE, /* share_access */
2464 FILE_OPEN, /* create_disposition*/
2465 FILE_NON_DIRECTORY_FILE, /* create_options */
2466 /* file_attributes */
2467 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2468 FILE_ATTRIBUTE_NORMAL,
2469 0, /* oplock_request */
2470 0, /* allocation_size */
2471 0, /* private_flags */
2477 if (!NT_STATUS_IS_OK(status)) {
2478 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2479 nt_errstr(status)));
2483 status = can_set_delete_on_close(fsp, fattr);
2484 if (!NT_STATUS_IS_OK(status)) {
2485 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2487 smb_fname_str_dbg(smb_fname),
2488 nt_errstr(status)));
2489 close_file(req, fsp, NORMAL_CLOSE);
2493 /* The set is across all open files on this dev/inode pair. */
2494 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2495 close_file(req, fsp, NORMAL_CLOSE);
2496 return NT_STATUS_ACCESS_DENIED;
2499 return close_file(req, fsp, NORMAL_CLOSE);
2502 /****************************************************************************
2503 The guts of the unlink command, split out so it may be called by the NT SMB
2505 ****************************************************************************/
2507 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2508 uint32 dirtype, struct smb_filename *smb_fname,
2511 char *fname_dir = NULL;
2512 char *fname_mask = NULL;
2514 NTSTATUS status = NT_STATUS_OK;
2515 TALLOC_CTX *ctx = talloc_tos();
2517 /* Split up the directory from the filename/mask. */
2518 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2519 &fname_dir, &fname_mask);
2520 if (!NT_STATUS_IS_OK(status)) {
2525 * We should only check the mangled cache
2526 * here if unix_convert failed. This means
2527 * that the path in 'mask' doesn't exist
2528 * on the file system and so we need to look
2529 * for a possible mangle. This patch from
2530 * Tine Smukavec <valentin.smukavec@hermes.si>.
2533 if (!VALID_STAT(smb_fname->st) &&
2534 mangle_is_mangled(fname_mask, conn->params)) {
2535 char *new_mask = NULL;
2536 mangle_lookup_name_from_8_3(ctx, fname_mask,
2537 &new_mask, conn->params);
2539 TALLOC_FREE(fname_mask);
2540 fname_mask = new_mask;
2547 * Only one file needs to be unlinked. Append the mask back
2548 * onto the directory.
2550 TALLOC_FREE(smb_fname->base_name);
2551 smb_fname->base_name = talloc_asprintf(smb_fname,
2555 if (!smb_fname->base_name) {
2556 status = NT_STATUS_NO_MEMORY;
2560 dirtype = FILE_ATTRIBUTE_NORMAL;
2563 status = check_name(conn, smb_fname->base_name);
2564 if (!NT_STATUS_IS_OK(status)) {
2568 status = do_unlink(conn, req, smb_fname, dirtype);
2569 if (!NT_STATUS_IS_OK(status)) {
2575 struct smb_Dir *dir_hnd = NULL;
2577 const char *dname = NULL;
2578 char *talloced = NULL;
2580 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2581 status = NT_STATUS_OBJECT_NAME_INVALID;
2585 if (strequal(fname_mask,"????????.???")) {
2586 TALLOC_FREE(fname_mask);
2587 fname_mask = talloc_strdup(ctx, "*");
2589 status = NT_STATUS_NO_MEMORY;
2594 status = check_name(conn, fname_dir);
2595 if (!NT_STATUS_IS_OK(status)) {
2599 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2601 if (dir_hnd == NULL) {
2602 status = map_nt_error_from_unix(errno);
2606 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2607 the pattern matches against the long name, otherwise the short name
2608 We don't implement this yet XXXX
2611 status = NT_STATUS_NO_SUCH_FILE;
2613 while ((dname = ReadDirName(dir_hnd, &offset,
2614 &smb_fname->st, &talloced))) {
2615 TALLOC_CTX *frame = talloc_stackframe();
2617 if (!is_visible_file(conn, fname_dir, dname,
2618 &smb_fname->st, true)) {
2620 TALLOC_FREE(talloced);
2624 /* Quick check for "." and ".." */
2625 if (ISDOT(dname) || ISDOTDOT(dname)) {
2627 TALLOC_FREE(talloced);
2631 if(!mask_match(dname, fname_mask,
2632 conn->case_sensitive)) {
2634 TALLOC_FREE(talloced);
2638 TALLOC_FREE(smb_fname->base_name);
2639 smb_fname->base_name =
2640 talloc_asprintf(smb_fname, "%s/%s",
2643 if (!smb_fname->base_name) {
2644 TALLOC_FREE(dir_hnd);
2645 status = NT_STATUS_NO_MEMORY;
2647 TALLOC_FREE(talloced);
2651 status = check_name(conn, smb_fname->base_name);
2652 if (!NT_STATUS_IS_OK(status)) {
2653 TALLOC_FREE(dir_hnd);
2655 TALLOC_FREE(talloced);
2659 status = do_unlink(conn, req, smb_fname, dirtype);
2660 if (!NT_STATUS_IS_OK(status)) {
2662 TALLOC_FREE(talloced);
2667 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2668 smb_fname->base_name));
2671 TALLOC_FREE(talloced);
2673 TALLOC_FREE(dir_hnd);
2676 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2677 status = map_nt_error_from_unix(errno);
2681 TALLOC_FREE(fname_dir);
2682 TALLOC_FREE(fname_mask);
2686 /****************************************************************************
2688 ****************************************************************************/
2690 void reply_unlink(struct smb_request *req)
2692 connection_struct *conn = req->conn;
2694 struct smb_filename *smb_fname = NULL;
2697 bool path_contains_wcard = False;
2698 TALLOC_CTX *ctx = talloc_tos();
2700 START_PROFILE(SMBunlink);
2703 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2707 dirtype = SVAL(req->vwv+0, 0);
2709 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2710 STR_TERMINATE, &status,
2711 &path_contains_wcard);
2712 if (!NT_STATUS_IS_OK(status)) {
2713 reply_nterror(req, status);
2717 status = filename_convert(ctx, conn,
2718 req->flags2 & FLAGS2_DFS_PATHNAMES,
2720 UCF_COND_ALLOW_WCARD_LCOMP,
2721 &path_contains_wcard,
2723 if (!NT_STATUS_IS_OK(status)) {
2724 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2725 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2726 ERRSRV, ERRbadpath);
2729 reply_nterror(req, status);
2733 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2735 status = unlink_internals(conn, req, dirtype, smb_fname,
2736 path_contains_wcard);
2737 if (!NT_STATUS_IS_OK(status)) {
2738 if (open_was_deferred(req->mid)) {
2739 /* We have re-scheduled this call. */
2742 reply_nterror(req, status);
2746 reply_outbuf(req, 0, 0);
2748 TALLOC_FREE(smb_fname);
2749 END_PROFILE(SMBunlink);
2753 /****************************************************************************
2755 ****************************************************************************/
2757 static void fail_readraw(void)
2759 const char *errstr = talloc_asprintf(talloc_tos(),
2760 "FAIL ! reply_readbraw: socket write fail (%s)",
2765 exit_server_cleanly(errstr);
2768 /****************************************************************************
2769 Fake (read/write) sendfile. Returns -1 on read or write fail.
2770 ****************************************************************************/
2772 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2776 size_t tosend = nread;
2783 bufsize = MIN(nread, 65536);
2785 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2789 while (tosend > 0) {
2793 if (tosend > bufsize) {
2798 ret = read_file(fsp,buf,startpos,cur_read);
2804 /* If we had a short read, fill with zeros. */
2805 if (ret < cur_read) {
2806 memset(buf + ret, '\0', cur_read - ret);
2809 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2814 startpos += cur_read;
2818 return (ssize_t)nread;
2821 #if defined(WITH_SENDFILE)
2822 /****************************************************************************
2823 Deal with the case of sendfile reading less bytes from the file than
2824 requested. Fill with zeros (all we can do).
2825 ****************************************************************************/
2827 static void sendfile_short_send(files_struct *fsp,
2832 #define SHORT_SEND_BUFSIZE 1024
2833 if (nread < headersize) {
2834 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2835 "header for file %s (%s). Terminating\n",
2836 fsp_str_dbg(fsp), strerror(errno)));
2837 exit_server_cleanly("sendfile_short_send failed");
2840 nread -= headersize;
2842 if (nread < smb_maxcnt) {
2843 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2845 exit_server_cleanly("sendfile_short_send: "
2849 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2850 "with zeros !\n", fsp_str_dbg(fsp)));
2852 while (nread < smb_maxcnt) {
2854 * We asked for the real file size and told sendfile
2855 * to not go beyond the end of the file. But it can
2856 * happen that in between our fstat call and the
2857 * sendfile call the file was truncated. This is very
2858 * bad because we have already announced the larger
2859 * number of bytes to the client.
2861 * The best we can do now is to send 0-bytes, just as
2862 * a read from a hole in a sparse file would do.
2864 * This should happen rarely enough that I don't care
2865 * about efficiency here :-)
2869 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2870 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2871 exit_server_cleanly("sendfile_short_send: "
2872 "write_data failed");
2879 #endif /* defined WITH_SENDFILE */
2881 /****************************************************************************
2882 Return a readbraw error (4 bytes of zero).
2883 ****************************************************************************/
2885 static void reply_readbraw_error(struct smbd_server_connection *sconn)
2891 smbd_lock_socket(sconn);
2892 if (write_data(smbd_server_fd(),header,4) != 4) {
2895 smbd_unlock_socket(sconn);
2898 /****************************************************************************
2899 Use sendfile in readbraw.
2900 ****************************************************************************/
2902 static void send_file_readbraw(connection_struct *conn,
2903 struct smb_request *req,
2909 struct smbd_server_connection *sconn = req->sconn;
2910 char *outbuf = NULL;
2913 #if defined(WITH_SENDFILE)
2915 * We can only use sendfile on a non-chained packet
2916 * but we can use on a non-oplocked file. tridge proved this
2917 * on a train in Germany :-). JRA.
2918 * reply_readbraw has already checked the length.
2921 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2922 (fsp->wcp == NULL) &&
2923 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
2924 ssize_t sendfile_read = -1;
2926 DATA_BLOB header_blob;
2928 _smb_setlen(header,nread);
2929 header_blob = data_blob_const(header, 4);
2931 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2932 &header_blob, startpos, nread)) == -1) {
2933 /* Returning ENOSYS means no data at all was sent.
2934 * Do this as a normal read. */
2935 if (errno == ENOSYS) {
2936 goto normal_readbraw;
2940 * Special hack for broken Linux with no working sendfile. If we
2941 * return EINTR we sent the header but not the rest of the data.
2942 * Fake this up by doing read/write calls.
2944 if (errno == EINTR) {
2945 /* Ensure we don't do this again. */
2946 set_use_sendfile(SNUM(conn), False);
2947 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2949 if (fake_sendfile(fsp, startpos, nread) == -1) {
2950 DEBUG(0,("send_file_readbraw: "
2951 "fake_sendfile failed for "
2955 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2960 DEBUG(0,("send_file_readbraw: sendfile failed for "
2961 "file %s (%s). Terminating\n",
2962 fsp_str_dbg(fsp), strerror(errno)));
2963 exit_server_cleanly("send_file_readbraw sendfile failed");
2964 } else if (sendfile_read == 0) {
2966 * Some sendfile implementations return 0 to indicate
2967 * that there was a short read, but nothing was
2968 * actually written to the socket. In this case,
2969 * fallback to the normal read path so the header gets
2970 * the correct byte count.
2972 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2973 "bytes falling back to the normal read: "
2974 "%s\n", fsp_str_dbg(fsp)));
2975 goto normal_readbraw;
2978 /* Deal with possible short send. */
2979 if (sendfile_read != 4+nread) {
2980 sendfile_short_send(fsp, sendfile_read, 4, nread);
2988 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2990 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2991 (unsigned)(nread+4)));
2992 reply_readbraw_error(sconn);
2997 ret = read_file(fsp,outbuf+4,startpos,nread);
2998 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3007 _smb_setlen(outbuf,ret);
3008 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
3011 TALLOC_FREE(outbuf);
3014 /****************************************************************************
3015 Reply to a readbraw (core+ protocol).
3016 ****************************************************************************/
3018 void reply_readbraw(struct smb_request *req)
3020 connection_struct *conn = req->conn;
3021 struct smbd_server_connection *sconn = req->sconn;
3022 ssize_t maxcount,mincount;
3026 struct lock_struct lock;
3029 START_PROFILE(SMBreadbraw);
3031 if (srv_is_signing_active(sconn) ||
3032 is_encrypted_packet(req->inbuf)) {
3033 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3034 "raw reads/writes are disallowed.");
3038 reply_readbraw_error(sconn);
3039 END_PROFILE(SMBreadbraw);
3043 if (sconn->smb1.echo_handler.trusted_fde) {
3044 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3045 "'async smb echo handler = yes'\n"));
3046 reply_readbraw_error(sconn);
3047 END_PROFILE(SMBreadbraw);
3052 * Special check if an oplock break has been issued
3053 * and the readraw request croses on the wire, we must
3054 * return a zero length response here.
3057 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3060 * We have to do a check_fsp by hand here, as
3061 * we must always return 4 zero bytes on error,
3065 if (!fsp || !conn || conn != fsp->conn ||
3066 req->vuid != fsp->vuid ||
3067 fsp->is_directory || fsp->fh->fd == -1) {
3069 * fsp could be NULL here so use the value from the packet. JRA.
3071 DEBUG(3,("reply_readbraw: fnum %d not valid "
3073 (int)SVAL(req->vwv+0, 0)));
3074 reply_readbraw_error(sconn);
3075 END_PROFILE(SMBreadbraw);
3079 /* Do a "by hand" version of CHECK_READ. */
3080 if (!(fsp->can_read ||
3081 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3082 (fsp->access_mask & FILE_EXECUTE)))) {
3083 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3084 (int)SVAL(req->vwv+0, 0)));
3085 reply_readbraw_error(sconn);
3086 END_PROFILE(SMBreadbraw);
3090 flush_write_cache(fsp, READRAW_FLUSH);
3092 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3093 if(req->wct == 10) {
3095 * This is a large offset (64 bit) read.
3097 #ifdef LARGE_SMB_OFF_T
3099 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3101 #else /* !LARGE_SMB_OFF_T */
3104 * Ensure we haven't been sent a >32 bit offset.
3107 if(IVAL(req->vwv+8, 0) != 0) {
3108 DEBUG(0,("reply_readbraw: large offset "
3109 "(%x << 32) used and we don't support "
3110 "64 bit offsets.\n",
3111 (unsigned int)IVAL(req->vwv+8, 0) ));
3112 reply_readbraw_error();
3113 END_PROFILE(SMBreadbraw);
3117 #endif /* LARGE_SMB_OFF_T */
3120 DEBUG(0,("reply_readbraw: negative 64 bit "
3121 "readraw offset (%.0f) !\n",
3122 (double)startpos ));
3123 reply_readbraw_error(sconn);
3124 END_PROFILE(SMBreadbraw);
3129 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3130 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3132 /* ensure we don't overrun the packet size */
3133 maxcount = MIN(65535,maxcount);
3135 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3136 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3139 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3140 reply_readbraw_error(sconn);
3141 END_PROFILE(SMBreadbraw);
3145 if (fsp_stat(fsp) == 0) {
3146 size = fsp->fsp_name->st.st_ex_size;
3149 if (startpos >= size) {
3152 nread = MIN(maxcount,(size - startpos));
3155 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3156 if (nread < mincount)
3160 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3161 "min=%lu nread=%lu\n",
3162 fsp->fnum, (double)startpos,
3163 (unsigned long)maxcount,
3164 (unsigned long)mincount,
3165 (unsigned long)nread ) );
3167 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3169 DEBUG(5,("reply_readbraw finished\n"));
3171 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3173 END_PROFILE(SMBreadbraw);
3178 #define DBGC_CLASS DBGC_LOCKING
3180 /****************************************************************************
3181 Reply to a lockread (core+ protocol).
3182 ****************************************************************************/
3184 void reply_lockread(struct smb_request *req)
3186 connection_struct *conn = req->conn;
3193 struct byte_range_lock *br_lck = NULL;
3195 struct smbd_server_connection *sconn = req->sconn;
3197 START_PROFILE(SMBlockread);
3200 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3201 END_PROFILE(SMBlockread);
3205 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3207 if (!check_fsp(conn, req, fsp)) {
3208 END_PROFILE(SMBlockread);
3212 if (!CHECK_READ(fsp,req)) {
3213 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3214 END_PROFILE(SMBlockread);
3218 numtoread = SVAL(req->vwv+1, 0);
3219 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3221 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3223 reply_outbuf(req, 5, numtoread + 3);
3225 data = smb_buf(req->outbuf) + 3;
3228 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3229 * protocol request that predates the read/write lock concept.
3230 * Thus instead of asking for a read lock here we need to ask
3231 * for a write lock. JRA.
3232 * Note that the requested lock size is unaffected by max_recv.
3235 br_lck = do_lock(req->sconn->msg_ctx,
3237 (uint64_t)req->smbpid,
3238 (uint64_t)numtoread,
3242 False, /* Non-blocking lock. */
3246 TALLOC_FREE(br_lck);
3248 if (NT_STATUS_V(status)) {
3249 reply_nterror(req, status);
3250 END_PROFILE(SMBlockread);
3255 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3258 if (numtoread > sconn->smb1.negprot.max_recv) {
3259 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3260 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3261 (unsigned int)numtoread,
3262 (unsigned int)sconn->smb1.negprot.max_recv));
3263 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3265 nread = read_file(fsp,data,startpos,numtoread);
3268 reply_nterror(req, map_nt_error_from_unix(errno));
3269 END_PROFILE(SMBlockread);
3273 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3275 SSVAL(req->outbuf,smb_vwv0,nread);
3276 SSVAL(req->outbuf,smb_vwv5,nread+3);
3277 p = smb_buf(req->outbuf);
3278 SCVAL(p,0,0); /* pad byte. */
3281 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3282 fsp->fnum, (int)numtoread, (int)nread));
3284 END_PROFILE(SMBlockread);
3289 #define DBGC_CLASS DBGC_ALL
3291 /****************************************************************************
3293 ****************************************************************************/
3295 void reply_read(struct smb_request *req)
3297 connection_struct *conn = req->conn;
3304 struct lock_struct lock;
3305 struct smbd_server_connection *sconn = req->sconn;
3307 START_PROFILE(SMBread);
3310 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3311 END_PROFILE(SMBread);
3315 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3317 if (!check_fsp(conn, req, fsp)) {
3318 END_PROFILE(SMBread);
3322 if (!CHECK_READ(fsp,req)) {
3323 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3324 END_PROFILE(SMBread);
3328 numtoread = SVAL(req->vwv+1, 0);
3329 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3331 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3334 * The requested read size cannot be greater than max_recv. JRA.
3336 if (numtoread > sconn->smb1.negprot.max_recv) {
3337 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3338 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3339 (unsigned int)numtoread,
3340 (unsigned int)sconn->smb1.negprot.max_recv));
3341 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3344 reply_outbuf(req, 5, numtoread+3);
3346 data = smb_buf(req->outbuf) + 3;
3348 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3349 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3352 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3353 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3354 END_PROFILE(SMBread);
3359 nread = read_file(fsp,data,startpos,numtoread);
3362 reply_nterror(req, map_nt_error_from_unix(errno));
3366 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3368 SSVAL(req->outbuf,smb_vwv0,nread);
3369 SSVAL(req->outbuf,smb_vwv5,nread+3);
3370 SCVAL(smb_buf(req->outbuf),0,1);
3371 SSVAL(smb_buf(req->outbuf),1,nread);
3373 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3374 fsp->fnum, (int)numtoread, (int)nread ) );
3377 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3379 END_PROFILE(SMBread);
3383 /****************************************************************************
3385 ****************************************************************************/
3387 static int setup_readX_header(struct smb_request *req, char *outbuf,
3393 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3394 data = smb_buf(outbuf);
3396 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3398 SCVAL(outbuf,smb_vwv0,0xFF);
3399 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3400 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3401 SSVAL(outbuf,smb_vwv6,
3403 + 1 /* the wct field */
3404 + 12 * sizeof(uint16_t) /* vwv */
3405 + 2); /* the buflen field */
3406 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3407 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3408 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3409 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3413 /****************************************************************************
3414 Reply to a read and X - possibly using sendfile.
3415 ****************************************************************************/
3417 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3418 files_struct *fsp, SMB_OFF_T startpos,
3422 struct lock_struct lock;
3423 int saved_errno = 0;
3425 if(fsp_stat(fsp) == -1) {
3426 reply_nterror(req, map_nt_error_from_unix(errno));
3430 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3431 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3434 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3435 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3439 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3440 (startpos > fsp->fsp_name->st.st_ex_size)
3441 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3443 * We already know that we would do a short read, so don't
3444 * try the sendfile() path.
3446 goto nosendfile_read;
3449 #if defined(WITH_SENDFILE)
3451 * We can only use sendfile on a non-chained packet
3452 * but we can use on a non-oplocked file. tridge proved this
3453 * on a train in Germany :-). JRA.
3456 if (!req_is_in_chain(req) &&
3457 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3458 (fsp->wcp == NULL) &&
3459 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3460 uint8 headerbuf[smb_size + 12 * 2];
3464 * Set up the packet header before send. We
3465 * assume here the sendfile will work (get the
3466 * correct amount of data).
3469 header = data_blob_const(headerbuf, sizeof(headerbuf));
3471 construct_reply_common_req(req, (char *)headerbuf);
3472 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3474 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3475 /* Returning ENOSYS means no data at all was sent.
3476 Do this as a normal read. */
3477 if (errno == ENOSYS) {
3482 * Special hack for broken Linux with no working sendfile. If we
3483 * return EINTR we sent the header but not the rest of the data.
3484 * Fake this up by doing read/write calls.
3487 if (errno == EINTR) {
3488 /* Ensure we don't do this again. */
3489 set_use_sendfile(SNUM(conn), False);
3490 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3491 nread = fake_sendfile(fsp, startpos,
3494 DEBUG(0,("send_file_readX: "
3495 "fake_sendfile failed for "
3499 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3501 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3502 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3503 /* No outbuf here means successful sendfile. */
3507 DEBUG(0,("send_file_readX: sendfile failed for file "
3508 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3510 exit_server_cleanly("send_file_readX sendfile failed");
3511 } else if (nread == 0) {
3513 * Some sendfile implementations return 0 to indicate
3514 * that there was a short read, but nothing was
3515 * actually written to the socket. In this case,
3516 * fallback to the normal read path so the header gets
3517 * the correct byte count.
3519 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3520 "falling back to the normal read: %s\n",
3525 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3526 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3528 /* Deal with possible short send. */
3529 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3530 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3532 /* No outbuf here means successful sendfile. */
3533 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3534 SMB_PERFCOUNT_END(&req->pcd);
3542 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3543 uint8 headerbuf[smb_size + 2*12];
3545 construct_reply_common_req(req, (char *)headerbuf);
3546 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3548 /* Send out the header. */
3549 if (write_data(smbd_server_fd(), (char *)headerbuf,
3550 sizeof(headerbuf)) != sizeof(headerbuf)) {
3551 DEBUG(0,("send_file_readX: write_data failed for file "
3552 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3554 exit_server_cleanly("send_file_readX sendfile failed");
3556 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3558 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3559 "file %s (%s).\n", fsp_str_dbg(fsp),
3561 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3568 reply_outbuf(req, 12, smb_maxcnt);
3570 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3571 saved_errno = errno;
3573 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3576 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3580 setup_readX_header(req, (char *)req->outbuf, nread);
3582 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3583 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3589 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3590 TALLOC_FREE(req->outbuf);
3594 /****************************************************************************
3595 Reply to a read and X.
3596 ****************************************************************************/
3598 void reply_read_and_X(struct smb_request *req)
3600 connection_struct *conn = req->conn;
3604 bool big_readX = False;
3606 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3609 START_PROFILE(SMBreadX);
3611 if ((req->wct != 10) && (req->wct != 12)) {
3612 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3616 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3617 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3618 smb_maxcnt = SVAL(req->vwv+5, 0);
3620 /* If it's an IPC, pass off the pipe handler. */
3622 reply_pipe_read_and_X(req);
3623 END_PROFILE(SMBreadX);
3627 if (!check_fsp(conn, req, fsp)) {
3628 END_PROFILE(SMBreadX);
3632 if (!CHECK_READ(fsp,req)) {
3633 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3634 END_PROFILE(SMBreadX);
3638 if (global_client_caps & CAP_LARGE_READX) {
3639 size_t upper_size = SVAL(req->vwv+7, 0);
3640 smb_maxcnt |= (upper_size<<16);
3641 if (upper_size > 1) {
3642 /* Can't do this on a chained packet. */
3643 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3644 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3645 END_PROFILE(SMBreadX);
3648 /* We currently don't do this on signed or sealed data. */
3649 if (srv_is_signing_active(req->sconn) ||
3650 is_encrypted_packet(req->inbuf)) {
3651 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3652 END_PROFILE(SMBreadX);
3655 /* Is there room in the reply for this data ? */
3656 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3658 NT_STATUS_INVALID_PARAMETER);
3659 END_PROFILE(SMBreadX);
3666 if (req->wct == 12) {
3667 #ifdef LARGE_SMB_OFF_T
3669 * This is a large offset (64 bit) read.
3671 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3673 #else /* !LARGE_SMB_OFF_T */
3676 * Ensure we haven't been sent a >32 bit offset.
3679 if(IVAL(req->vwv+10, 0) != 0) {
3680 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3681 "used and we don't support 64 bit offsets.\n",
3682 (unsigned int)IVAL(req->vwv+10, 0) ));
3683 END_PROFILE(SMBreadX);
3684 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3688 #endif /* LARGE_SMB_OFF_T */
3693 NTSTATUS status = schedule_aio_read_and_X(conn,
3698 if (NT_STATUS_IS_OK(status)) {
3699 /* Read scheduled - we're done. */
3702 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3703 /* Real error - report to client. */
3704 END_PROFILE(SMBreadX);
3705 reply_nterror(req, status);
3708 /* NT_STATUS_RETRY - fall back to sync read. */
3711 smbd_lock_socket(req->sconn);
3712 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3713 smbd_unlock_socket(req->sconn);
3716 END_PROFILE(SMBreadX);
3720 /****************************************************************************
3721 Error replies to writebraw must have smb_wct == 1. Fix this up.
3722 ****************************************************************************/
3724 void error_to_writebrawerr(struct smb_request *req)
3726 uint8 *old_outbuf = req->outbuf;
3728 reply_outbuf(req, 1, 0);
3730 memcpy(req->outbuf, old_outbuf, smb_size);
3731 TALLOC_FREE(old_outbuf);
3734 /****************************************************************************
3735 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3736 ****************************************************************************/
3738 void reply_writebraw(struct smb_request *req)
3740 connection_struct *conn = req->conn;
3743 ssize_t total_written=0;
3744 size_t numtowrite=0;
3750 struct lock_struct lock;
3753 START_PROFILE(SMBwritebraw);
3756 * If we ever reply with an error, it must have the SMB command
3757 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3760 SCVAL(req->inbuf,smb_com,SMBwritec);
3762 if (srv_is_signing_active(req->sconn)) {
3763 END_PROFILE(SMBwritebraw);
3764 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3765 "raw reads/writes are disallowed.");
3768 if (req->wct < 12) {
3769 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3770 error_to_writebrawerr(req);
3771 END_PROFILE(SMBwritebraw);
3775 if (req->sconn->smb1.echo_handler.trusted_fde) {
3776 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3777 "'async smb echo handler = yes'\n"));
3778 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3779 error_to_writebrawerr(req);
3780 END_PROFILE(SMBwritebraw);
3784 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3785 if (!check_fsp(conn, req, fsp)) {
3786 error_to_writebrawerr(req);
3787 END_PROFILE(SMBwritebraw);
3791 if (!CHECK_WRITE(fsp)) {
3792 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3793 error_to_writebrawerr(req);
3794 END_PROFILE(SMBwritebraw);
3798 tcount = IVAL(req->vwv+1, 0);
3799 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3800 write_through = BITSETW(req->vwv+7,0);
3802 /* We have to deal with slightly different formats depending
3803 on whether we are using the core+ or lanman1.0 protocol */
3805 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3806 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3807 data = smb_buf(req->inbuf);
3809 numtowrite = SVAL(req->vwv+10, 0);
3810 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3813 /* Ensure we don't write bytes past the end of this packet. */
3814 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3815 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3816 error_to_writebrawerr(req);
3817 END_PROFILE(SMBwritebraw);
3821 if (!fsp->print_file) {
3822 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3823 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3826 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3827 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3828 error_to_writebrawerr(req);
3829 END_PROFILE(SMBwritebraw);
3835 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3838 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3839 "wrote=%d sync=%d\n",
3840 fsp->fnum, (double)startpos, (int)numtowrite,
3841 (int)nwritten, (int)write_through));
3843 if (nwritten < (ssize_t)numtowrite) {
3844 reply_nterror(req, NT_STATUS_DISK_FULL);
3845 error_to_writebrawerr(req);
3849 total_written = nwritten;
3851 /* Allocate a buffer of 64k + length. */
3852 buf = TALLOC_ARRAY(NULL, char, 65540);
3854 reply_nterror(req, NT_STATUS_NO_MEMORY);
3855 error_to_writebrawerr(req);
3859 /* Return a SMBwritebraw message to the redirector to tell
3860 * it to send more bytes */
3862 memcpy(buf, req->inbuf, smb_size);
3863 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
3864 SCVAL(buf,smb_com,SMBwritebraw);
3865 SSVALS(buf,smb_vwv0,0xFFFF);
3867 if (!srv_send_smb(smbd_server_fd(),
3869 false, 0, /* no signing */
3870 IS_CONN_ENCRYPTED(conn),
3872 exit_server_cleanly("reply_writebraw: srv_send_smb "
3876 /* Now read the raw data into the buffer and write it */
3877 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3879 if (!NT_STATUS_IS_OK(status)) {
3880 exit_server_cleanly("secondary writebraw failed");
3883 /* Set up outbuf to return the correct size */
3884 reply_outbuf(req, 1, 0);
3886 if (numtowrite != 0) {
3888 if (numtowrite > 0xFFFF) {
3889 DEBUG(0,("reply_writebraw: Oversize secondary write "
3890 "raw requested (%u). Terminating\n",
3891 (unsigned int)numtowrite ));
3892 exit_server_cleanly("secondary writebraw failed");
3895 if (tcount > nwritten+numtowrite) {
3896 DEBUG(3,("reply_writebraw: Client overestimated the "
3898 (int)tcount,(int)nwritten,(int)numtowrite));
3901 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3903 if (!NT_STATUS_IS_OK(status)) {
3904 DEBUG(0,("reply_writebraw: Oversize secondary write "
3905 "raw read failed (%s). Terminating\n",
3906 nt_errstr(status)));
3907 exit_server_cleanly("secondary writebraw failed");
3910 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3911 if (nwritten == -1) {
3913 reply_nterror(req, map_nt_error_from_unix(errno));
3914 error_to_writebrawerr(req);
3918 if (nwritten < (ssize_t)numtowrite) {
3919 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3920 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3924 total_written += nwritten;
3929 SSVAL(req->outbuf,smb_vwv0,total_written);
3931 status = sync_file(conn, fsp, write_through);
3932 if (!NT_STATUS_IS_OK(status)) {
3933 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3934 fsp_str_dbg(fsp), nt_errstr(status)));
3935 reply_nterror(req, status);
3936 error_to_writebrawerr(req);
3940 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3942 fsp->fnum, (double)startpos, (int)numtowrite,
3943 (int)total_written));
3945 if (!fsp->print_file) {
3946 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3949 /* We won't return a status if write through is not selected - this
3950 * follows what WfWg does */
3951 END_PROFILE(SMBwritebraw);
3953 if (!write_through && total_written==tcount) {
3955 #if RABBIT_PELLET_FIX
3957 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3958 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3961 if (!send_keepalive(smbd_server_fd())) {
3962 exit_server_cleanly("reply_writebraw: send of "
3963 "keepalive failed");
3966 TALLOC_FREE(req->outbuf);
3971 if (!fsp->print_file) {
3972 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3975 END_PROFILE(SMBwritebraw);
3980 #define DBGC_CLASS DBGC_LOCKING
3982 /****************************************************************************
3983 Reply to a writeunlock (core+).
3984 ****************************************************************************/
3986 void reply_writeunlock(struct smb_request *req)
3988 connection_struct *conn = req->conn;
3989 ssize_t nwritten = -1;
3993 NTSTATUS status = NT_STATUS_OK;
3995 struct lock_struct lock;
3996 int saved_errno = 0;
3998 START_PROFILE(SMBwriteunlock);
4001 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4002 END_PROFILE(SMBwriteunlock);
4006 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4008 if (!check_fsp(conn, req, fsp)) {
4009 END_PROFILE(SMBwriteunlock);
4013 if (!CHECK_WRITE(fsp)) {
4014 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4015 END_PROFILE(SMBwriteunlock);
4019 numtowrite = SVAL(req->vwv+1, 0);
4020 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4021 data = (const char *)req->buf + 3;
4023 if (!fsp->print_file && numtowrite > 0) {
4024 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4025 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4028 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4029 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4030 END_PROFILE(SMBwriteunlock);
4035 /* The special X/Open SMB protocol handling of
4036 zero length writes is *NOT* done for
4038 if(numtowrite == 0) {
4041 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4042 saved_errno = errno;
4045 status = sync_file(conn, fsp, False /* write through */);
4046 if (!NT_STATUS_IS_OK(status)) {
4047 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4048 fsp_str_dbg(fsp), nt_errstr(status)));
4049 reply_nterror(req, status);
4054 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4058 if((nwritten < numtowrite) && (numtowrite != 0)) {
4059 reply_nterror(req, NT_STATUS_DISK_FULL);
4063 if (numtowrite && !fsp->print_file) {
4064 status = do_unlock(req->sconn->msg_ctx,
4066 (uint64_t)req->smbpid,
4067 (uint64_t)numtowrite,
4071 if (NT_STATUS_V(status)) {
4072 reply_nterror(req, status);
4077 reply_outbuf(req, 1, 0);
4079 SSVAL(req->outbuf,smb_vwv0,nwritten);
4081 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4082 fsp->fnum, (int)numtowrite, (int)nwritten));
4085 if (numtowrite && !fsp->print_file) {
4086 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4089 END_PROFILE(SMBwriteunlock);
4094 #define DBGC_CLASS DBGC_ALL
4096 /****************************************************************************
4098 ****************************************************************************/
4100 void reply_write(struct smb_request *req)
4102 connection_struct *conn = req->conn;
4104 ssize_t nwritten = -1;
4108 struct lock_struct lock;
4110 int saved_errno = 0;
4112 START_PROFILE(SMBwrite);
4115 END_PROFILE(SMBwrite);
4116 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4120 /* If it's an IPC, pass off the pipe handler. */
4122 reply_pipe_write(req);
4123 END_PROFILE(SMBwrite);
4127 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4129 if (!check_fsp(conn, req, fsp)) {
4130 END_PROFILE(SMBwrite);
4134 if (!CHECK_WRITE(fsp)) {
4135 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4136 END_PROFILE(SMBwrite);
4140 numtowrite = SVAL(req->vwv+1, 0);
4141 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4142 data = (const char *)req->buf + 3;
4144 if (!fsp->print_file) {
4145 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4146 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4149 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4150 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4151 END_PROFILE(SMBwrite);
4157 * X/Open SMB protocol says that if smb_vwv1 is
4158 * zero then the file size should be extended or
4159 * truncated to the size given in smb_vwv[2-3].
4162 if(numtowrite == 0) {
4164 * This is actually an allocate call, and set EOF. JRA.
4166 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4168 reply_nterror(req, NT_STATUS_DISK_FULL);
4171 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4173 reply_nterror(req, NT_STATUS_DISK_FULL);
4176 trigger_write_time_update_immediate(fsp);
4178 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4181 status = sync_file(conn, fsp, False);
4182 if (!NT_STATUS_IS_OK(status)) {
4183 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4184 fsp_str_dbg(fsp), nt_errstr(status)));
4185 reply_nterror(req, status);
4190 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4194 if((nwritten == 0) && (numtowrite != 0)) {
4195 reply_nterror(req, NT_STATUS_DISK_FULL);
4199 reply_outbuf(req, 1, 0);
4201 SSVAL(req->outbuf,smb_vwv0,nwritten);
4203 if (nwritten < (ssize_t)numtowrite) {
4204 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4205 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4208 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4211 if (!fsp->print_file) {
4212 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4215 END_PROFILE(SMBwrite);
4219 /****************************************************************************
4220 Ensure a buffer is a valid writeX for recvfile purposes.
4221 ****************************************************************************/
4223 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4224 (2*14) + /* word count (including bcc) */ \
4227 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4228 const uint8_t *inbuf)
4231 connection_struct *conn = NULL;
4232 unsigned int doff = 0;
4233 size_t len = smb_len_large(inbuf);
4235 if (is_encrypted_packet(inbuf)) {
4236 /* Can't do this on encrypted
4241 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4245 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4246 CVAL(inbuf,smb_wct) != 14) {
4247 DEBUG(10,("is_valid_writeX_buffer: chained or "
4248 "invalid word length.\n"));
4252 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4254 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4258 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4261 if (IS_PRINT(conn)) {
4262 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4265 doff = SVAL(inbuf,smb_vwv11);
4267 numtowrite = SVAL(inbuf,smb_vwv10);
4269 if (len > doff && len - doff > 0xFFFF) {
4270 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4273 if (numtowrite == 0) {
4274 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4278 /* Ensure the sizes match up. */
4279 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4280 /* no pad byte...old smbclient :-( */
4281 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4283 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4287 if (len - doff != numtowrite) {
4288 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4289 "len = %u, doff = %u, numtowrite = %u\n",
4292 (unsigned int)numtowrite ));
4296 DEBUG(10,("is_valid_writeX_buffer: true "
4297 "len = %u, doff = %u, numtowrite = %u\n",
4300 (unsigned int)numtowrite ));
4305 /****************************************************************************
4306 Reply to a write and X.
4307 ****************************************************************************/
4309 void reply_write_and_X(struct smb_request *req)
4311 connection_struct *conn = req->conn;
4313 struct lock_struct lock;
4318 unsigned int smb_doff;
4319 unsigned int smblen;
4322 int saved_errno = 0;
4324 START_PROFILE(SMBwriteX);
4326 if ((req->wct != 12) && (req->wct != 14)) {
4327 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4328 END_PROFILE(SMBwriteX);
4332 numtowrite = SVAL(req->vwv+10, 0);
4333 smb_doff = SVAL(req->vwv+11, 0);
4334 smblen = smb_len(req->inbuf);
4336 if (req->unread_bytes > 0xFFFF ||
4337 (smblen > smb_doff &&
4338 smblen - smb_doff > 0xFFFF)) {
4339 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4342 if (req->unread_bytes) {
4343 /* Can't do a recvfile write on IPC$ */
4345 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4346 END_PROFILE(SMBwriteX);
4349 if (numtowrite != req->unread_bytes) {
4350 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4351 END_PROFILE(SMBwriteX);
4355 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4356 smb_doff + numtowrite > smblen) {
4357 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4358 END_PROFILE(SMBwriteX);
4363 /* If it's an IPC, pass off the pipe handler. */
4365 if (req->unread_bytes) {
4366 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4367 END_PROFILE(SMBwriteX);
4370 reply_pipe_write_and_X(req);
4371 END_PROFILE(SMBwriteX);
4375 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4376 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4377 write_through = BITSETW(req->vwv+7,0);
4379 if (!check_fsp(conn, req, fsp)) {
4380 END_PROFILE(SMBwriteX);
4384 if (!CHECK_WRITE(fsp)) {
4385 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4386 END_PROFILE(SMBwriteX);
4390 data = smb_base(req->inbuf) + smb_doff;
4392 if(req->wct == 14) {
4393 #ifdef LARGE_SMB_OFF_T
4395 * This is a large offset (64 bit) write.
4397 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4399 #else /* !LARGE_SMB_OFF_T */
4402 * Ensure we haven't been sent a >32 bit offset.
4405 if(IVAL(req->vwv+12, 0) != 0) {
4406 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4407 "used and we don't support 64 bit offsets.\n",
4408 (unsigned int)IVAL(req->vwv+12, 0) ));
4409 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4410 END_PROFILE(SMBwriteX);
4414 #endif /* LARGE_SMB_OFF_T */
4417 /* X/Open SMB protocol says that, unlike SMBwrite
4418 if the length is zero then NO truncation is
4419 done, just a write of zero. To truncate a file,
4422 if(numtowrite == 0) {
4425 if (req->unread_bytes == 0) {
4426 status = schedule_aio_write_and_X(conn,
4433 if (NT_STATUS_IS_OK(status)) {
4434 /* write scheduled - we're done. */
4437 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4438 /* Real error - report to client. */
4439 reply_nterror(req, status);
4442 /* NT_STATUS_RETRY - fall through to sync write. */
4445 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4446 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4449 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4450 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4454 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4455 saved_errno = errno;
4457 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4461 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4465 if((nwritten == 0) && (numtowrite != 0)) {
4466 reply_nterror(req, NT_STATUS_DISK_FULL);
4470 reply_outbuf(req, 6, 0);
4471 SSVAL(req->outbuf,smb_vwv2,nwritten);
4472 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4474 if (nwritten < (ssize_t)numtowrite) {
4475 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4476 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4479 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4480 fsp->fnum, (int)numtowrite, (int)nwritten));
4482 status = sync_file(conn, fsp, write_through);
4483 if (!NT_STATUS_IS_OK(status)) {
4484 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4485 fsp_str_dbg(fsp), nt_errstr(status)));
4486 reply_nterror(req, status);
4490 END_PROFILE(SMBwriteX);
4495 END_PROFILE(SMBwriteX);
4499 /****************************************************************************
4501 ****************************************************************************/
4503 void reply_lseek(struct smb_request *req)
4505 connection_struct *conn = req->conn;
4511 START_PROFILE(SMBlseek);
4514 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4515 END_PROFILE(SMBlseek);
4519 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4521 if (!check_fsp(conn, req, fsp)) {
4525 flush_write_cache(fsp, SEEK_FLUSH);
4527 mode = SVAL(req->vwv+1, 0) & 3;
4528 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4529 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4538 res = fsp->fh->pos + startpos;
4549 if (umode == SEEK_END) {
4550 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4551 if(errno == EINVAL) {
4552 SMB_OFF_T current_pos = startpos;
4554 if(fsp_stat(fsp) == -1) {
4556 map_nt_error_from_unix(errno));
4557 END_PROFILE(SMBlseek);
4561 current_pos += fsp->fsp_name->st.st_ex_size;
4563 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4568 reply_nterror(req, map_nt_error_from_unix(errno));
4569 END_PROFILE(SMBlseek);
4576 reply_outbuf(req, 2, 0);
4577 SIVAL(req->outbuf,smb_vwv0,res);
4579 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4580 fsp->fnum, (double)startpos, (double)res, mode));
4582 END_PROFILE(SMBlseek);
4586 /****************************************************************************
4588 ****************************************************************************/
4590 void reply_flush(struct smb_request *req)
4592 connection_struct *conn = req->conn;
4596 START_PROFILE(SMBflush);
4599 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4603 fnum = SVAL(req->vwv+0, 0);
4604 fsp = file_fsp(req, fnum);
4606 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4611 file_sync_all(conn);
4613 NTSTATUS status = sync_file(conn, fsp, True);
4614 if (!NT_STATUS_IS_OK(status)) {
4615 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4616 fsp_str_dbg(fsp), nt_errstr(status)));
4617 reply_nterror(req, status);
4618 END_PROFILE(SMBflush);
4623 reply_outbuf(req, 0, 0);
4625 DEBUG(3,("flush\n"));
4626 END_PROFILE(SMBflush);
4630 /****************************************************************************
4632 conn POINTER CAN BE NULL HERE !
4633 ****************************************************************************/
4635 void reply_exit(struct smb_request *req)
4637 START_PROFILE(SMBexit);
4639 file_close_pid(req->smbpid, req->vuid);
4641 reply_outbuf(req, 0, 0);
4643 DEBUG(3,("exit\n"));
4645 END_PROFILE(SMBexit);
4649 /****************************************************************************
4650 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4651 ****************************************************************************/
4653 void reply_close(struct smb_request *req)
4655 connection_struct *conn = req->conn;
4656 NTSTATUS status = NT_STATUS_OK;
4657 files_struct *fsp = NULL;
4658 START_PROFILE(SMBclose);
4661 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4662 END_PROFILE(SMBclose);
4666 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4669 * We can only use check_fsp if we know it's not a directory.
4672 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4673 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4674 END_PROFILE(SMBclose);
4678 if(fsp->is_directory) {
4680 * Special case - close NT SMB directory handle.
4682 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4683 status = close_file(req, fsp, NORMAL_CLOSE);
4687 * Close ordinary file.
4690 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4691 fsp->fh->fd, fsp->fnum,
4692 conn->num_files_open));
4695 * Take care of any time sent in the close.
4698 t = srv_make_unix_date3(req->vwv+1);
4699 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4702 * close_file() returns the unix errno if an error
4703 * was detected on close - normally this is due to
4704 * a disk full error. If not then it was probably an I/O error.
4707 status = close_file(req, fsp, NORMAL_CLOSE);
4710 if (!NT_STATUS_IS_OK(status)) {
4711 reply_nterror(req, status);
4712 END_PROFILE(SMBclose);
4716 reply_outbuf(req, 0, 0);
4717 END_PROFILE(SMBclose);
4721 /****************************************************************************
4722 Reply to a writeclose (Core+ protocol).
4723 ****************************************************************************/
4725 void reply_writeclose(struct smb_request *req)
4727 connection_struct *conn = req->conn;
4729 ssize_t nwritten = -1;
4730 NTSTATUS close_status = NT_STATUS_OK;
4733 struct timespec mtime;
4735 struct lock_struct lock;
4737 START_PROFILE(SMBwriteclose);
4740 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4741 END_PROFILE(SMBwriteclose);
4745 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4747 if (!check_fsp(conn, req, fsp)) {
4748 END_PROFILE(SMBwriteclose);
4751 if (!CHECK_WRITE(fsp)) {
4752 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4753 END_PROFILE(SMBwriteclose);
4757 numtowrite = SVAL(req->vwv+1, 0);
4758 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4759 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4760 data = (const char *)req->buf + 1;
4762 if (!fsp->print_file) {
4763 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4764 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4767 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4768 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4769 END_PROFILE(SMBwriteclose);
4774 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4776 set_close_write_time(fsp, mtime);
4779 * More insanity. W2K only closes the file if writelen > 0.
4784 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4785 "file %s\n", fsp_str_dbg(fsp)));
4786 close_status = close_file(req, fsp, NORMAL_CLOSE);
4789 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4790 fsp->fnum, (int)numtowrite, (int)nwritten,
4791 conn->num_files_open));
4793 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4794 reply_nterror(req, NT_STATUS_DISK_FULL);
4798 if(!NT_STATUS_IS_OK(close_status)) {
4799 reply_nterror(req, close_status);
4803 reply_outbuf(req, 1, 0);
4805 SSVAL(req->outbuf,smb_vwv0,nwritten);
4808 if (numtowrite && !fsp->print_file) {
4809 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4812 END_PROFILE(SMBwriteclose);
4817 #define DBGC_CLASS DBGC_LOCKING
4819 /****************************************************************************
4821 ****************************************************************************/
4823 void reply_lock(struct smb_request *req)
4825 connection_struct *conn = req->conn;
4826 uint64_t count,offset;
4829 struct byte_range_lock *br_lck = NULL;
4831 START_PROFILE(SMBlock);
4834 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4835 END_PROFILE(SMBlock);
4839 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4841 if (!check_fsp(conn, req, fsp)) {
4842 END_PROFILE(SMBlock);
4846 count = (uint64_t)IVAL(req->vwv+1, 0);
4847 offset = (uint64_t)IVAL(req->vwv+3, 0);
4849 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4850 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4852 br_lck = do_lock(req->sconn->msg_ctx,
4854 (uint64_t)req->smbpid,
4859 False, /* Non-blocking lock. */
4864 TALLOC_FREE(br_lck);
4866 if (NT_STATUS_V(status)) {
4867 reply_nterror(req, status);
4868 END_PROFILE(SMBlock);
4872 reply_outbuf(req, 0, 0);
4874 END_PROFILE(SMBlock);
4878 /****************************************************************************
4880 ****************************************************************************/
4882 void reply_unlock(struct smb_request *req)
4884 connection_struct *conn = req->conn;
4885 uint64_t count,offset;
4889 START_PROFILE(SMBunlock);
4892 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4893 END_PROFILE(SMBunlock);
4897 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4899 if (!check_fsp(conn, req, fsp)) {
4900 END_PROFILE(SMBunlock);
4904 count = (uint64_t)IVAL(req->vwv+1, 0);
4905 offset = (uint64_t)IVAL(req->vwv+3, 0);
4907 status = do_unlock(req->sconn->msg_ctx,
4909 (uint64_t)req->smbpid,
4914 if (NT_STATUS_V(status)) {
4915 reply_nterror(req, status);
4916 END_PROFILE(SMBunlock);
4920 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4921 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4923 reply_outbuf(req, 0, 0);
4925 END_PROFILE(SMBunlock);
4930 #define DBGC_CLASS DBGC_ALL
4932 /****************************************************************************
4934 conn POINTER CAN BE NULL HERE !
4935 ****************************************************************************/
4937 void reply_tdis(struct smb_request *req)
4939 connection_struct *conn = req->conn;
4940 START_PROFILE(SMBtdis);
4943 DEBUG(4,("Invalid connection in tdis\n"));
4944 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
4945 END_PROFILE(SMBtdis);
4951 close_cnum(conn,req->vuid);
4954 reply_outbuf(req, 0, 0);
4955 END_PROFILE(SMBtdis);
4959 /****************************************************************************
4961 conn POINTER CAN BE NULL HERE !
4962 ****************************************************************************/
4964 void reply_echo(struct smb_request *req)
4966 connection_struct *conn = req->conn;
4967 struct smb_perfcount_data local_pcd;
4968 struct smb_perfcount_data *cur_pcd;
4972 START_PROFILE(SMBecho);
4974 smb_init_perfcount_data(&local_pcd);
4977 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4978 END_PROFILE(SMBecho);
4982 smb_reverb = SVAL(req->vwv+0, 0);
4984 reply_outbuf(req, 1, req->buflen);
4986 /* copy any incoming data back out */
4987 if (req->buflen > 0) {
4988 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4991 if (smb_reverb > 100) {
4992 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4996 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
4998 /* this makes sure we catch the request pcd */
4999 if (seq_num == smb_reverb) {
5000 cur_pcd = &req->pcd;
5002 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5003 cur_pcd = &local_pcd;
5006 SSVAL(req->outbuf,smb_vwv0,seq_num);
5008 show_msg((char *)req->outbuf);
5009 if (!srv_send_smb(smbd_server_fd(),
5010 (char *)req->outbuf,
5011 true, req->seqnum+1,
5012 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5014 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5017 DEBUG(3,("echo %d times\n", smb_reverb));
5019 TALLOC_FREE(req->outbuf);
5021 END_PROFILE(SMBecho);
5025 /****************************************************************************
5026 Reply to a printopen.
5027 ****************************************************************************/
5029 void reply_printopen(struct smb_request *req)
5031 connection_struct *conn = req->conn;
5035 START_PROFILE(SMBsplopen);
5038 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5039 END_PROFILE(SMBsplopen);
5043 if (!CAN_PRINT(conn)) {
5044 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5045 END_PROFILE(SMBsplopen);
5049 status = file_new(req, conn, &fsp);
5050 if(!NT_STATUS_IS_OK(status)) {
5051 reply_nterror(req, status);
5052 END_PROFILE(SMBsplopen);
5056 /* Open for exclusive use, write only. */
5057 status = print_spool_open(fsp, NULL, req->vuid);
5059 if (!NT_STATUS_IS_OK(status)) {
5060 file_free(req, fsp);
5061 reply_nterror(req, status);
5062 END_PROFILE(SMBsplopen);
5066 reply_outbuf(req, 1, 0);
5067 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5069 DEBUG(3,("openprint fd=%d fnum=%d\n",
5070 fsp->fh->fd, fsp->fnum));
5072 END_PROFILE(SMBsplopen);
5076 /****************************************************************************
5077 Reply to a printclose.
5078 ****************************************************************************/
5080 void reply_printclose(struct smb_request *req)
5082 connection_struct *conn = req->conn;
5086 START_PROFILE(SMBsplclose);
5089 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5090 END_PROFILE(SMBsplclose);
5094 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5096 if (!check_fsp(conn, req, fsp)) {
5097 END_PROFILE(SMBsplclose);
5101 if (!CAN_PRINT(conn)) {
5102 reply_force_doserror(req, ERRSRV, ERRerror);
5103 END_PROFILE(SMBsplclose);
5107 DEBUG(3,("printclose fd=%d fnum=%d\n",
5108 fsp->fh->fd,fsp->fnum));
5110 status = close_file(req, fsp, NORMAL_CLOSE);
5112 if(!NT_STATUS_IS_OK(status)) {
5113 reply_nterror(req, status);
5114 END_PROFILE(SMBsplclose);
5118 reply_outbuf(req, 0, 0);
5120 END_PROFILE(SMBsplclose);
5124 /****************************************************************************
5125 Reply to a printqueue.
5126 ****************************************************************************/
5128 void reply_printqueue(struct smb_request *req)
5130 connection_struct *conn = req->conn;
5134 START_PROFILE(SMBsplretq);
5137 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5138 END_PROFILE(SMBsplretq);
5142 max_count = SVAL(req->vwv+0, 0);
5143 start_index = SVAL(req->vwv+1, 0);
5145 /* we used to allow the client to get the cnum wrong, but that
5146 is really quite gross and only worked when there was only
5147 one printer - I think we should now only accept it if they
5148 get it right (tridge) */
5149 if (!CAN_PRINT(conn)) {
5150 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5151 END_PROFILE(SMBsplretq);
5155 reply_outbuf(req, 2, 3);
5156 SSVAL(req->outbuf,smb_vwv0,0);
5157 SSVAL(req->outbuf,smb_vwv1,0);
5158 SCVAL(smb_buf(req->outbuf),0,1);
5159 SSVAL(smb_buf(req->outbuf),1,0);
5161 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5162 start_index, max_count));
5165 print_queue_struct *queue = NULL;
5166 print_status_struct status;
5167 int count = print_queue_status(SNUM(conn), &queue, &status);
5168 int num_to_get = ABS(max_count);
5169 int first = (max_count>0?start_index:start_index+max_count+1);
5175 num_to_get = MIN(num_to_get,count-first);
5178 for (i=first;i<first+num_to_get;i++) {
5182 srv_put_dos_date2(p,0,queue[i].time);
5183 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
5184 SSVAL(p,5, queue[i].job);
5185 SIVAL(p,7,queue[i].size);
5187 srvstr_push(blob, req->flags2, p+12,
5188 queue[i].fs_user, 16, STR_ASCII);
5190 if (message_push_blob(
5193 blob, sizeof(blob))) == -1) {
5194 reply_nterror(req, NT_STATUS_NO_MEMORY);
5195 END_PROFILE(SMBsplretq);
5201 SSVAL(req->outbuf,smb_vwv0,count);
5202 SSVAL(req->outbuf,smb_vwv1,
5203 (max_count>0?first+count:first-1));
5204 SCVAL(smb_buf(req->outbuf),0,1);
5205 SSVAL(smb_buf(req->outbuf),1,28*count);
5210 DEBUG(3,("%d entries returned in queue\n",count));
5213 END_PROFILE(SMBsplretq);
5217 /****************************************************************************
5218 Reply to a printwrite.
5219 ****************************************************************************/
5221 void reply_printwrite(struct smb_request *req)
5223 connection_struct *conn = req->conn;
5228 START_PROFILE(SMBsplwr);
5231 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5232 END_PROFILE(SMBsplwr);
5236 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5238 if (!check_fsp(conn, req, fsp)) {
5239 END_PROFILE(SMBsplwr);
5243 if (!CAN_PRINT(conn)) {
5244 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5245 END_PROFILE(SMBsplwr);
5249 if (!CHECK_WRITE(fsp)) {
5250 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5251 END_PROFILE(SMBsplwr);
5255 numtowrite = SVAL(req->buf, 1);
5257 if (req->buflen < numtowrite + 3) {
5258 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5259 END_PROFILE(SMBsplwr);
5263 data = (const char *)req->buf + 3;
5265 if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5266 reply_nterror(req, map_nt_error_from_unix(errno));
5267 END_PROFILE(SMBsplwr);
5271 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5273 END_PROFILE(SMBsplwr);
5277 /****************************************************************************
5279 ****************************************************************************/
5281 void reply_mkdir(struct smb_request *req)
5283 connection_struct *conn = req->conn;
5284 struct smb_filename *smb_dname = NULL;
5285 char *directory = NULL;
5287 TALLOC_CTX *ctx = talloc_tos();
5289 START_PROFILE(SMBmkdir);
5291 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5292 STR_TERMINATE, &status);
5293 if (!NT_STATUS_IS_OK(status)) {
5294 reply_nterror(req, status);
5298 status = filename_convert(ctx, conn,
5299 req->flags2 & FLAGS2_DFS_PATHNAMES,
5304 if (!NT_STATUS_IS_OK(status)) {
5305 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5306 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5307 ERRSRV, ERRbadpath);
5310 reply_nterror(req, status);
5314 status = create_directory(conn, req, smb_dname);
5316 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5318 if (!NT_STATUS_IS_OK(status)) {
5320 if (!use_nt_status()
5321 && NT_STATUS_EQUAL(status,
5322 NT_STATUS_OBJECT_NAME_COLLISION)) {
5324 * Yes, in the DOS error code case we get a
5325 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5326 * samba4 torture test.
5328 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5331 reply_nterror(req, status);
5335 reply_outbuf(req, 0, 0);
5337 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5339 TALLOC_FREE(smb_dname);
5340 END_PROFILE(SMBmkdir);
5344 /****************************************************************************
5346 ****************************************************************************/
5348 void reply_rmdir(struct smb_request *req)
5350 connection_struct *conn = req->conn;
5351 struct smb_filename *smb_dname = NULL;
5352 char *directory = NULL;
5354 TALLOC_CTX *ctx = talloc_tos();
5355 files_struct *fsp = NULL;
5357 struct smbd_server_connection *sconn = req->sconn;
5359 START_PROFILE(SMBrmdir);
5361 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5362 STR_TERMINATE, &status);
5363 if (!NT_STATUS_IS_OK(status)) {
5364 reply_nterror(req, status);
5368 status = filename_convert(ctx, conn,
5369 req->flags2 & FLAGS2_DFS_PATHNAMES,
5374 if (!NT_STATUS_IS_OK(status)) {
5375 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5376 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5377 ERRSRV, ERRbadpath);
5380 reply_nterror(req, status);
5384 if (is_ntfs_stream_smb_fname(smb_dname)) {
5385 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5389 status = SMB_VFS_CREATE_FILE(
5392 0, /* root_dir_fid */
5393 smb_dname, /* fname */
5394 DELETE_ACCESS, /* access_mask */
5395 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5397 FILE_OPEN, /* create_disposition*/
5398 FILE_DIRECTORY_FILE, /* create_options */
5399 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5400 0, /* oplock_request */
5401 0, /* allocation_size */
5402 0, /* private_flags */
5408 if (!NT_STATUS_IS_OK(status)) {
5409 if (open_was_deferred(req->mid)) {
5410 /* We have re-scheduled this call. */
5413 reply_nterror(req, status);
5417 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5418 if (!NT_STATUS_IS_OK(status)) {
5419 close_file(req, fsp, ERROR_CLOSE);
5420 reply_nterror(req, status);
5424 if (!set_delete_on_close(fsp, true, &conn->server_info->utok)) {
5425 close_file(req, fsp, ERROR_CLOSE);
5426 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5430 status = close_file(req, fsp, NORMAL_CLOSE);
5431 if (!NT_STATUS_IS_OK(status)) {
5432 reply_nterror(req, status);
5434 reply_outbuf(req, 0, 0);
5437 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5439 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5441 TALLOC_FREE(smb_dname);
5442 END_PROFILE(SMBrmdir);
5446 /*******************************************************************
5447 Resolve wildcards in a filename rename.
5448 ********************************************************************/
5450 static bool resolve_wildcards(TALLOC_CTX *ctx,
5455 char *name2_copy = NULL;
5460 char *p,*p2, *pname1, *pname2;
5462 name2_copy = talloc_strdup(ctx, name2);
5467 pname1 = strrchr_m(name1,'/');
5468 pname2 = strrchr_m(name2_copy,'/');
5470 if (!pname1 || !pname2) {
5474 /* Truncate the copy of name2 at the last '/' */
5477 /* Now go past the '/' */
5481 root1 = talloc_strdup(ctx, pname1);
5482 root2 = talloc_strdup(ctx, pname2);
5484 if (!root1 || !root2) {
5488 p = strrchr_m(root1,'.');
5491 ext1 = talloc_strdup(ctx, p+1);
5493 ext1 = talloc_strdup(ctx, "");
5495 p = strrchr_m(root2,'.');
5498 ext2 = talloc_strdup(ctx, p+1);
5500 ext2 = talloc_strdup(ctx, "");
5503 if (!ext1 || !ext2) {
5511 /* Hmmm. Should this be mb-aware ? */
5514 } else if (*p2 == '*') {
5516 root2 = talloc_asprintf(ctx, "%s%s",
5535 /* Hmmm. Should this be mb-aware ? */
5538 } else if (*p2 == '*') {
5540 ext2 = talloc_asprintf(ctx, "%s%s",
5556 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5561 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5573 /****************************************************************************
5574 Ensure open files have their names updated. Updated to notify other smbd's
5576 ****************************************************************************/
5578 static void rename_open_files(connection_struct *conn,
5579 struct share_mode_lock *lck,
5580 const struct smb_filename *smb_fname_dst)
5583 bool did_rename = False;
5586 for(fsp = file_find_di_first(lck->id); fsp;
5587 fsp = file_find_di_next(fsp)) {
5588 /* fsp_name is a relative path under the fsp. To change this for other
5589 sharepaths we need to manipulate relative paths. */
5590 /* TODO - create the absolute path and manipulate the newname
5591 relative to the sharepath. */
5592 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5595 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5596 "(file_id %s) from %s -> %s\n", fsp->fnum,
5597 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5598 smb_fname_str_dbg(smb_fname_dst)));
5600 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5601 if (NT_STATUS_IS_OK(status)) {
5607 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5608 "for %s\n", file_id_string_tos(&lck->id),
5609 smb_fname_str_dbg(smb_fname_dst)));
5612 /* Send messages to all smbd's (not ourself) that the name has changed. */
5613 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5618 /****************************************************************************
5619 We need to check if the source path is a parent directory of the destination
5620 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5621 refuse the rename with a sharing violation. Under UNIX the above call can
5622 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5623 probably need to check that the client is a Windows one before disallowing
5624 this as a UNIX client (one with UNIX extensions) can know the source is a
5625 symlink and make this decision intelligently. Found by an excellent bug
5626 report from <AndyLiebman@aol.com>.
5627 ****************************************************************************/
5629 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5630 const struct smb_filename *smb_fname_dst)
5632 const char *psrc = smb_fname_src->base_name;
5633 const char *pdst = smb_fname_dst->base_name;
5636 if (psrc[0] == '.' && psrc[1] == '/') {
5639 if (pdst[0] == '.' && pdst[1] == '/') {
5642 if ((slen = strlen(psrc)) > strlen(pdst)) {
5645 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5649 * Do the notify calls from a rename
5652 static void notify_rename(connection_struct *conn, bool is_dir,
5653 const struct smb_filename *smb_fname_src,
5654 const struct smb_filename *smb_fname_dst)
5656 char *parent_dir_src = NULL;
5657 char *parent_dir_dst = NULL;
5660 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5661 : FILE_NOTIFY_CHANGE_FILE_NAME;
5663 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5664 &parent_dir_src, NULL) ||
5665 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5666 &parent_dir_dst, NULL)) {
5670 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5671 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5672 smb_fname_src->base_name);
5673 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5674 smb_fname_dst->base_name);
5677 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5678 smb_fname_src->base_name);
5679 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5680 smb_fname_dst->base_name);
5683 /* this is a strange one. w2k3 gives an additional event for
5684 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5685 files, but not directories */
5687 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5688 FILE_NOTIFY_CHANGE_ATTRIBUTES
5689 |FILE_NOTIFY_CHANGE_CREATION,
5690 smb_fname_dst->base_name);
5693 TALLOC_FREE(parent_dir_src);
5694 TALLOC_FREE(parent_dir_dst);
5697 /****************************************************************************
5698 Rename an open file - given an fsp.
5699 ****************************************************************************/
5701 NTSTATUS rename_internals_fsp(connection_struct *conn,
5703 const struct smb_filename *smb_fname_dst_in,
5705 bool replace_if_exists)
5707 TALLOC_CTX *ctx = talloc_tos();
5708 struct smb_filename *smb_fname_dst = NULL;
5709 NTSTATUS status = NT_STATUS_OK;
5710 struct share_mode_lock *lck = NULL;
5711 bool dst_exists, old_is_stream, new_is_stream;
5713 status = check_name(conn, smb_fname_dst_in->base_name);
5714 if (!NT_STATUS_IS_OK(status)) {
5718 /* Make a copy of the dst smb_fname structs */
5720 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5721 if (!NT_STATUS_IS_OK(status)) {
5725 /* Ensure the dst smb_fname contains a '/' */
5726 if(strrchr_m(smb_fname_dst->base_name,'/') == 0) {
5728 tmp = talloc_asprintf(smb_fname_dst, "./%s",
5729 smb_fname_dst->base_name);
5731 status = NT_STATUS_NO_MEMORY;
5734 TALLOC_FREE(smb_fname_dst->base_name);
5735 smb_fname_dst->base_name = tmp;
5739 * Check for special case with case preserving and not
5740 * case sensitive. If the old last component differs from the original
5741 * last component only by case, then we should allow
5742 * the rename (user is trying to change the case of the
5745 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5746 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5747 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
5749 char *fname_dst_lcomp_base_mod = NULL;
5750 struct smb_filename *smb_fname_orig_lcomp = NULL;
5753 * Get the last component of the destination name. Note that
5754 * we guarantee that destination name contains a '/' character
5757 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5758 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5759 if (!fname_dst_lcomp_base_mod) {
5760 status = NT_STATUS_NO_MEMORY;
5765 * Create an smb_filename struct using the original last
5766 * component of the destination.
5768 status = create_synthetic_smb_fname_split(ctx,
5769 smb_fname_dst->original_lcomp, NULL,
5770 &smb_fname_orig_lcomp);
5771 if (!NT_STATUS_IS_OK(status)) {
5772 TALLOC_FREE(fname_dst_lcomp_base_mod);
5776 /* If the base names only differ by case, use original. */
5777 if(!strcsequal(fname_dst_lcomp_base_mod,
5778 smb_fname_orig_lcomp->base_name)) {
5781 * Replace the modified last component with the
5784 *last_slash = '\0'; /* Truncate at the '/' */
5785 tmp = talloc_asprintf(smb_fname_dst,
5787 smb_fname_dst->base_name,
5788 smb_fname_orig_lcomp->base_name);
5790 status = NT_STATUS_NO_MEMORY;
5791 TALLOC_FREE(fname_dst_lcomp_base_mod);
5792 TALLOC_FREE(smb_fname_orig_lcomp);
5795 TALLOC_FREE(smb_fname_dst->base_name);
5796 smb_fname_dst->base_name = tmp;
5799 /* If the stream_names only differ by case, use original. */
5800 if(!strcsequal(smb_fname_dst->stream_name,
5801 smb_fname_orig_lcomp->stream_name)) {
5803 /* Use the original stream. */
5804 tmp = talloc_strdup(smb_fname_dst,
5805 smb_fname_orig_lcomp->stream_name);
5807 status = NT_STATUS_NO_MEMORY;
5808 TALLOC_FREE(fname_dst_lcomp_base_mod);
5809 TALLOC_FREE(smb_fname_orig_lcomp);
5812 TALLOC_FREE(smb_fname_dst->stream_name);
5813 smb_fname_dst->stream_name = tmp;
5815 TALLOC_FREE(fname_dst_lcomp_base_mod);
5816 TALLOC_FREE(smb_fname_orig_lcomp);
5820 * If the src and dest names are identical - including case,
5821 * don't do the rename, just return success.
5824 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5825 strcsequal(fsp->fsp_name->stream_name,
5826 smb_fname_dst->stream_name)) {
5827 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
5828 "- returning success\n",
5829 smb_fname_str_dbg(smb_fname_dst)));
5830 status = NT_STATUS_OK;
5834 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
5835 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
5837 /* Return the correct error code if both names aren't streams. */
5838 if (!old_is_stream && new_is_stream) {
5839 status = NT_STATUS_OBJECT_NAME_INVALID;
5843 if (old_is_stream && !new_is_stream) {
5844 status = NT_STATUS_INVALID_PARAMETER;
5848 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
5850 if(!replace_if_exists && dst_exists) {
5851 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
5852 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
5853 smb_fname_str_dbg(smb_fname_dst)));
5854 status = NT_STATUS_OBJECT_NAME_COLLISION;
5859 struct file_id fileid = vfs_file_id_from_sbuf(conn,
5860 &smb_fname_dst->st);
5861 files_struct *dst_fsp = file_find_di_first(fileid);
5862 /* The file can be open when renaming a stream */
5863 if (dst_fsp && !new_is_stream) {
5864 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5865 status = NT_STATUS_ACCESS_DENIED;
5870 /* Ensure we have a valid stat struct for the source. */
5871 status = vfs_stat_fsp(fsp);
5872 if (!NT_STATUS_IS_OK(status)) {
5876 status = can_rename(conn, fsp, attrs);
5878 if (!NT_STATUS_IS_OK(status)) {
5879 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
5880 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
5881 smb_fname_str_dbg(smb_fname_dst)));
5882 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5883 status = NT_STATUS_ACCESS_DENIED;
5887 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
5888 status = NT_STATUS_ACCESS_DENIED;
5891 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5895 * We have the file open ourselves, so not being able to get the
5896 * corresponding share mode lock is a fatal error.
5899 SMB_ASSERT(lck != NULL);
5901 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
5902 uint32 create_options = fsp->fh->private_options;
5904 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
5905 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
5906 smb_fname_str_dbg(smb_fname_dst)));
5908 if (lp_map_archive(SNUM(conn)) ||
5909 lp_store_dos_attributes(SNUM(conn))) {
5910 /* We must set the archive bit on the newly
5912 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
5913 uint32_t old_dosmode = dos_mode(conn,
5915 file_set_dosmode(conn,
5917 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
5923 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
5926 rename_open_files(conn, lck, smb_fname_dst);
5929 * A rename acts as a new file create w.r.t. allowing an initial delete
5930 * on close, probably because in Windows there is a new handle to the
5931 * new file. If initial delete on close was requested but not
5932 * originally set, we need to set it here. This is probably not 100% correct,
5933 * but will work for the CIFSFS client which in non-posix mode
5934 * depends on these semantics. JRA.
5937 if (create_options & FILE_DELETE_ON_CLOSE) {
5938 status = can_set_delete_on_close(fsp, 0);
5940 if (NT_STATUS_IS_OK(status)) {
5941 /* Note that here we set the *inital* delete on close flag,
5942 * not the regular one. The magic gets handled in close. */
5943 fsp->initial_delete_on_close = True;
5947 status = NT_STATUS_OK;
5953 if (errno == ENOTDIR || errno == EISDIR) {
5954 status = NT_STATUS_OBJECT_NAME_COLLISION;
5956 status = map_nt_error_from_unix(errno);
5959 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
5960 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
5961 smb_fname_str_dbg(smb_fname_dst)));
5964 TALLOC_FREE(smb_fname_dst);
5969 /****************************************************************************
5970 The guts of the rename command, split out so it may be called by the NT SMB
5972 ****************************************************************************/
5974 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5975 connection_struct *conn,
5976 struct smb_request *req,
5977 struct smb_filename *smb_fname_src,
5978 struct smb_filename *smb_fname_dst,
5980 bool replace_if_exists,
5983 uint32_t access_mask)
5985 char *fname_src_dir = NULL;
5986 char *fname_src_mask = NULL;
5988 NTSTATUS status = NT_STATUS_OK;
5989 struct smb_Dir *dir_hnd = NULL;
5990 const char *dname = NULL;
5991 char *talloced = NULL;
5993 int create_options = 0;
5994 bool posix_pathnames = lp_posix_pathnames();
5997 * Split the old name into directory and last component
5998 * strings. Note that unix_convert may have stripped off a
5999 * leading ./ from both name and newname if the rename is
6000 * at the root of the share. We need to make sure either both
6001 * name and newname contain a / character or neither of them do
6002 * as this is checked in resolve_wildcards().
6005 /* Split up the directory from the filename/mask. */
6006 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6007 &fname_src_dir, &fname_src_mask);
6008 if (!NT_STATUS_IS_OK(status)) {
6009 status = NT_STATUS_NO_MEMORY;
6014 * We should only check the mangled cache
6015 * here if unix_convert failed. This means
6016 * that the path in 'mask' doesn't exist
6017 * on the file system and so we need to look
6018 * for a possible mangle. This patch from
6019 * Tine Smukavec <valentin.smukavec@hermes.si>.
6022 if (!VALID_STAT(smb_fname_src->st) &&
6023 mangle_is_mangled(fname_src_mask, conn->params)) {
6024 char *new_mask = NULL;
6025 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6028 TALLOC_FREE(fname_src_mask);
6029 fname_src_mask = new_mask;
6033 if (!src_has_wild) {
6037 * Only one file needs to be renamed. Append the mask back
6038 * onto the directory.
6040 TALLOC_FREE(smb_fname_src->base_name);
6041 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6045 if (!smb_fname_src->base_name) {
6046 status = NT_STATUS_NO_MEMORY;
6050 /* Ensure dst fname contains a '/' also */
6051 if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
6053 tmp = talloc_asprintf(smb_fname_dst, "./%s",
6054 smb_fname_dst->base_name);
6056 status = NT_STATUS_NO_MEMORY;
6059 TALLOC_FREE(smb_fname_dst->base_name);
6060 smb_fname_dst->base_name = tmp;
6063 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6064 "case_preserve = %d, short case preserve = %d, "
6065 "directory = %s, newname = %s, "
6066 "last_component_dest = %s\n",
6067 conn->case_sensitive, conn->case_preserve,
6068 conn->short_case_preserve,
6069 smb_fname_str_dbg(smb_fname_src),
6070 smb_fname_str_dbg(smb_fname_dst),
6071 smb_fname_dst->original_lcomp));
6073 /* The dest name still may have wildcards. */
6074 if (dest_has_wild) {
6075 char *fname_dst_mod = NULL;
6076 if (!resolve_wildcards(smb_fname_dst,
6077 smb_fname_src->base_name,
6078 smb_fname_dst->base_name,
6080 DEBUG(6, ("rename_internals: resolve_wildcards "
6082 smb_fname_src->base_name,
6083 smb_fname_dst->base_name));
6084 status = NT_STATUS_NO_MEMORY;
6087 TALLOC_FREE(smb_fname_dst->base_name);
6088 smb_fname_dst->base_name = fname_dst_mod;
6091 ZERO_STRUCT(smb_fname_src->st);
6092 if (posix_pathnames) {
6093 SMB_VFS_LSTAT(conn, smb_fname_src);
6095 SMB_VFS_STAT(conn, smb_fname_src);
6098 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6099 create_options |= FILE_DIRECTORY_FILE;
6102 status = SMB_VFS_CREATE_FILE(
6105 0, /* root_dir_fid */
6106 smb_fname_src, /* fname */
6107 access_mask, /* access_mask */
6108 (FILE_SHARE_READ | /* share_access */
6110 FILE_OPEN, /* create_disposition*/
6111 create_options, /* create_options */
6112 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6113 0, /* oplock_request */
6114 0, /* allocation_size */
6115 0, /* private_flags */
6121 if (!NT_STATUS_IS_OK(status)) {
6122 DEBUG(3, ("Could not open rename source %s: %s\n",
6123 smb_fname_str_dbg(smb_fname_src),
6124 nt_errstr(status)));
6128 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6129 attrs, replace_if_exists);
6131 close_file(req, fsp, NORMAL_CLOSE);
6133 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6134 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6135 smb_fname_str_dbg(smb_fname_dst)));
6141 * Wildcards - process each file that matches.
6143 if (strequal(fname_src_mask, "????????.???")) {
6144 TALLOC_FREE(fname_src_mask);
6145 fname_src_mask = talloc_strdup(ctx, "*");
6146 if (!fname_src_mask) {
6147 status = NT_STATUS_NO_MEMORY;
6152 status = check_name(conn, fname_src_dir);
6153 if (!NT_STATUS_IS_OK(status)) {
6157 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6159 if (dir_hnd == NULL) {
6160 status = map_nt_error_from_unix(errno);
6164 status = NT_STATUS_NO_SUCH_FILE;
6166 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6167 * - gentest fix. JRA
6170 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6172 files_struct *fsp = NULL;
6173 char *destname = NULL;
6174 bool sysdir_entry = False;
6176 /* Quick check for "." and ".." */
6177 if (ISDOT(dname) || ISDOTDOT(dname)) {
6179 sysdir_entry = True;
6181 TALLOC_FREE(talloced);
6186 if (!is_visible_file(conn, fname_src_dir, dname,
6187 &smb_fname_src->st, false)) {
6188 TALLOC_FREE(talloced);
6192 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6193 TALLOC_FREE(talloced);
6198 status = NT_STATUS_OBJECT_NAME_INVALID;
6202 TALLOC_FREE(smb_fname_src->base_name);
6203 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6207 if (!smb_fname_src->base_name) {
6208 status = NT_STATUS_NO_MEMORY;
6212 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6213 smb_fname_dst->base_name,
6215 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6216 smb_fname_src->base_name, destname));
6217 TALLOC_FREE(talloced);
6221 status = NT_STATUS_NO_MEMORY;
6225 TALLOC_FREE(smb_fname_dst->base_name);
6226 smb_fname_dst->base_name = destname;
6228 ZERO_STRUCT(smb_fname_src->st);
6229 if (posix_pathnames) {
6230 SMB_VFS_LSTAT(conn, smb_fname_src);
6232 SMB_VFS_STAT(conn, smb_fname_src);
6237 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6238 create_options |= FILE_DIRECTORY_FILE;
6241 status = SMB_VFS_CREATE_FILE(
6244 0, /* root_dir_fid */
6245 smb_fname_src, /* fname */
6246 access_mask, /* access_mask */
6247 (FILE_SHARE_READ | /* share_access */
6249 FILE_OPEN, /* create_disposition*/
6250 create_options, /* create_options */
6251 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6252 0, /* oplock_request */
6253 0, /* allocation_size */
6254 0, /* private_flags */
6260 if (!NT_STATUS_IS_OK(status)) {
6261 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6262 "returned %s rename %s -> %s\n",
6264 smb_fname_str_dbg(smb_fname_src),
6265 smb_fname_str_dbg(smb_fname_dst)));
6269 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6271 if (!smb_fname_dst->original_lcomp) {
6272 status = NT_STATUS_NO_MEMORY;
6276 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6277 attrs, replace_if_exists);
6279 close_file(req, fsp, NORMAL_CLOSE);
6281 if (!NT_STATUS_IS_OK(status)) {
6282 DEBUG(3, ("rename_internals_fsp returned %s for "
6283 "rename %s -> %s\n", nt_errstr(status),
6284 smb_fname_str_dbg(smb_fname_src),
6285 smb_fname_str_dbg(smb_fname_dst)));
6291 DEBUG(3,("rename_internals: doing rename on %s -> "
6292 "%s\n", smb_fname_str_dbg(smb_fname_src),
6293 smb_fname_str_dbg(smb_fname_src)));
6294 TALLOC_FREE(talloced);
6296 TALLOC_FREE(dir_hnd);
6298 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6299 status = map_nt_error_from_unix(errno);
6303 TALLOC_FREE(talloced);
6304 TALLOC_FREE(fname_src_dir);
6305 TALLOC_FREE(fname_src_mask);
6309 /****************************************************************************
6311 ****************************************************************************/
6313 void reply_mv(struct smb_request *req)
6315 connection_struct *conn = req->conn;
6317 char *newname = NULL;
6321 bool src_has_wcard = False;
6322 bool dest_has_wcard = False;
6323 TALLOC_CTX *ctx = talloc_tos();
6324 struct smb_filename *smb_fname_src = NULL;
6325 struct smb_filename *smb_fname_dst = NULL;
6327 START_PROFILE(SMBmv);
6330 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6334 attrs = SVAL(req->vwv+0, 0);
6336 p = (const char *)req->buf + 1;
6337 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6338 &status, &src_has_wcard);
6339 if (!NT_STATUS_IS_OK(status)) {
6340 reply_nterror(req, status);
6344 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6345 &status, &dest_has_wcard);
6346 if (!NT_STATUS_IS_OK(status)) {
6347 reply_nterror(req, status);
6351 status = filename_convert(ctx,
6353 req->flags2 & FLAGS2_DFS_PATHNAMES,
6355 UCF_COND_ALLOW_WCARD_LCOMP,
6359 if (!NT_STATUS_IS_OK(status)) {
6360 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6361 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6362 ERRSRV, ERRbadpath);
6365 reply_nterror(req, status);
6369 status = filename_convert(ctx,
6371 req->flags2 & FLAGS2_DFS_PATHNAMES,
6373 UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6377 if (!NT_STATUS_IS_OK(status)) {
6378 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6379 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6380 ERRSRV, ERRbadpath);
6383 reply_nterror(req, status);
6387 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6388 smb_fname_str_dbg(smb_fname_dst)));
6390 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6391 attrs, False, src_has_wcard, dest_has_wcard,
6393 if (!NT_STATUS_IS_OK(status)) {
6394 if (open_was_deferred(req->mid)) {
6395 /* We have re-scheduled this call. */
6398 reply_nterror(req, status);
6402 reply_outbuf(req, 0, 0);
6404 TALLOC_FREE(smb_fname_src);
6405 TALLOC_FREE(smb_fname_dst);
6410 /*******************************************************************
6411 Copy a file as part of a reply_copy.
6412 ******************************************************************/
6415 * TODO: check error codes on all callers
6418 NTSTATUS copy_file(TALLOC_CTX *ctx,
6419 connection_struct *conn,
6420 struct smb_filename *smb_fname_src,
6421 struct smb_filename *smb_fname_dst,
6424 bool target_is_directory)
6426 struct smb_filename *smb_fname_dst_tmp = NULL;
6428 files_struct *fsp1,*fsp2;
6430 uint32 new_create_disposition;
6434 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6435 if (!NT_STATUS_IS_OK(status)) {
6440 * If the target is a directory, extract the last component from the
6441 * src filename and append it to the dst filename
6443 if (target_is_directory) {
6446 /* dest/target can't be a stream if it's a directory. */
6447 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6449 p = strrchr_m(smb_fname_src->base_name,'/');
6453 p = smb_fname_src->base_name;
6455 smb_fname_dst_tmp->base_name =
6456 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6458 if (!smb_fname_dst_tmp->base_name) {
6459 status = NT_STATUS_NO_MEMORY;
6464 status = vfs_file_exist(conn, smb_fname_src);
6465 if (!NT_STATUS_IS_OK(status)) {
6469 if (!target_is_directory && count) {
6470 new_create_disposition = FILE_OPEN;
6472 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
6474 &new_create_disposition,
6477 status = NT_STATUS_INVALID_PARAMETER;
6482 /* Open the src file for reading. */
6483 status = SMB_VFS_CREATE_FILE(
6486 0, /* root_dir_fid */
6487 smb_fname_src, /* fname */
6488 FILE_GENERIC_READ, /* access_mask */
6489 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6490 FILE_OPEN, /* create_disposition*/
6491 0, /* create_options */
6492 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6493 INTERNAL_OPEN_ONLY, /* oplock_request */
6494 0, /* allocation_size */
6495 0, /* private_flags */
6501 if (!NT_STATUS_IS_OK(status)) {
6505 dosattrs = dos_mode(conn, smb_fname_src);
6507 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6508 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6511 /* Open the dst file for writing. */
6512 status = SMB_VFS_CREATE_FILE(
6515 0, /* root_dir_fid */
6516 smb_fname_dst, /* fname */
6517 FILE_GENERIC_WRITE, /* access_mask */
6518 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6519 new_create_disposition, /* create_disposition*/
6520 0, /* create_options */
6521 dosattrs, /* file_attributes */
6522 INTERNAL_OPEN_ONLY, /* oplock_request */
6523 0, /* allocation_size */
6524 0, /* private_flags */
6530 if (!NT_STATUS_IS_OK(status)) {
6531 close_file(NULL, fsp1, ERROR_CLOSE);
6535 if ((ofun&3) == 1) {
6536 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6537 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6539 * Stop the copy from occurring.
6542 smb_fname_src->st.st_ex_size = 0;
6546 /* Do the actual copy. */
6547 if (smb_fname_src->st.st_ex_size) {
6548 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6551 close_file(NULL, fsp1, NORMAL_CLOSE);
6553 /* Ensure the modtime is set correctly on the destination file. */
6554 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6557 * As we are opening fsp1 read-only we only expect
6558 * an error on close on fsp2 if we are out of space.
6559 * Thus we don't look at the error return from the
6562 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6564 if (!NT_STATUS_IS_OK(status)) {
6568 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6569 status = NT_STATUS_DISK_FULL;
6573 status = NT_STATUS_OK;
6576 TALLOC_FREE(smb_fname_dst_tmp);
6580 /****************************************************************************
6581 Reply to a file copy.
6582 ****************************************************************************/
6584 void reply_copy(struct smb_request *req)
6586 connection_struct *conn = req->conn;
6587 struct smb_filename *smb_fname_src = NULL;
6588 struct smb_filename *smb_fname_dst = NULL;
6589 char *fname_src = NULL;
6590 char *fname_dst = NULL;
6591 char *fname_src_mask = NULL;
6592 char *fname_src_dir = NULL;
6595 int error = ERRnoaccess;
6599 bool target_is_directory=False;
6600 bool source_has_wild = False;
6601 bool dest_has_wild = False;
6603 TALLOC_CTX *ctx = talloc_tos();
6605 START_PROFILE(SMBcopy);
6608 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6612 tid2 = SVAL(req->vwv+0, 0);
6613 ofun = SVAL(req->vwv+1, 0);
6614 flags = SVAL(req->vwv+2, 0);
6616 p = (const char *)req->buf;
6617 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6618 &status, &source_has_wild);
6619 if (!NT_STATUS_IS_OK(status)) {
6620 reply_nterror(req, status);
6623 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6624 &status, &dest_has_wild);
6625 if (!NT_STATUS_IS_OK(status)) {
6626 reply_nterror(req, status);
6630 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6632 if (tid2 != conn->cnum) {
6633 /* can't currently handle inter share copies XXXX */
6634 DEBUG(3,("Rejecting inter-share copy\n"));
6635 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6639 status = filename_convert(ctx, conn,
6640 req->flags2 & FLAGS2_DFS_PATHNAMES,
6642 UCF_COND_ALLOW_WCARD_LCOMP,
6645 if (!NT_STATUS_IS_OK(status)) {
6646 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6647 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6648 ERRSRV, ERRbadpath);
6651 reply_nterror(req, status);
6655 status = filename_convert(ctx, conn,
6656 req->flags2 & FLAGS2_DFS_PATHNAMES,
6658 UCF_COND_ALLOW_WCARD_LCOMP,
6661 if (!NT_STATUS_IS_OK(status)) {
6662 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6663 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6664 ERRSRV, ERRbadpath);
6667 reply_nterror(req, status);
6671 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6673 if ((flags&1) && target_is_directory) {
6674 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6678 if ((flags&2) && !target_is_directory) {
6679 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
6683 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6684 /* wants a tree copy! XXXX */
6685 DEBUG(3,("Rejecting tree copy\n"));
6686 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6690 /* Split up the directory from the filename/mask. */
6691 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6692 &fname_src_dir, &fname_src_mask);
6693 if (!NT_STATUS_IS_OK(status)) {
6694 reply_nterror(req, NT_STATUS_NO_MEMORY);
6699 * We should only check the mangled cache
6700 * here if unix_convert failed. This means
6701 * that the path in 'mask' doesn't exist
6702 * on the file system and so we need to look
6703 * for a possible mangle. This patch from
6704 * Tine Smukavec <valentin.smukavec@hermes.si>.
6706 if (!VALID_STAT(smb_fname_src->st) &&
6707 mangle_is_mangled(fname_src_mask, conn->params)) {
6708 char *new_mask = NULL;
6709 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6710 &new_mask, conn->params);
6712 /* Use demangled name if one was successfully found. */
6714 TALLOC_FREE(fname_src_mask);
6715 fname_src_mask = new_mask;
6719 if (!source_has_wild) {
6722 * Only one file needs to be copied. Append the mask back onto
6725 TALLOC_FREE(smb_fname_src->base_name);
6726 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6730 if (!smb_fname_src->base_name) {
6731 reply_nterror(req, NT_STATUS_NO_MEMORY);
6735 if (dest_has_wild) {
6736 char *fname_dst_mod = NULL;
6737 if (!resolve_wildcards(smb_fname_dst,
6738 smb_fname_src->base_name,
6739 smb_fname_dst->base_name,
6741 reply_nterror(req, NT_STATUS_NO_MEMORY);
6744 TALLOC_FREE(smb_fname_dst->base_name);
6745 smb_fname_dst->base_name = fname_dst_mod;
6748 status = check_name(conn, smb_fname_src->base_name);
6749 if (!NT_STATUS_IS_OK(status)) {
6750 reply_nterror(req, status);
6754 status = check_name(conn, smb_fname_dst->base_name);
6755 if (!NT_STATUS_IS_OK(status)) {
6756 reply_nterror(req, status);
6760 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
6761 ofun, count, target_is_directory);
6763 if(!NT_STATUS_IS_OK(status)) {
6764 reply_nterror(req, status);
6770 struct smb_Dir *dir_hnd = NULL;
6771 const char *dname = NULL;
6772 char *talloced = NULL;
6776 * There is a wildcard that requires us to actually read the
6777 * src dir and copy each file matching the mask to the dst.
6778 * Right now streams won't be copied, but this could
6779 * presumably be added with a nested loop for reach dir entry.
6781 SMB_ASSERT(!smb_fname_src->stream_name);
6782 SMB_ASSERT(!smb_fname_dst->stream_name);
6784 smb_fname_src->stream_name = NULL;
6785 smb_fname_dst->stream_name = NULL;
6787 if (strequal(fname_src_mask,"????????.???")) {
6788 TALLOC_FREE(fname_src_mask);
6789 fname_src_mask = talloc_strdup(ctx, "*");
6790 if (!fname_src_mask) {
6791 reply_nterror(req, NT_STATUS_NO_MEMORY);
6796 status = check_name(conn, fname_src_dir);
6797 if (!NT_STATUS_IS_OK(status)) {
6798 reply_nterror(req, status);
6802 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
6803 if (dir_hnd == NULL) {
6804 status = map_nt_error_from_unix(errno);
6805 reply_nterror(req, status);
6811 /* Iterate over the src dir copying each entry to the dst. */
6812 while ((dname = ReadDirName(dir_hnd, &offset,
6813 &smb_fname_src->st, &talloced))) {
6814 char *destname = NULL;
6816 if (ISDOT(dname) || ISDOTDOT(dname)) {
6817 TALLOC_FREE(talloced);
6821 if (!is_visible_file(conn, fname_src_dir, dname,
6822 &smb_fname_src->st, false)) {
6823 TALLOC_FREE(talloced);
6827 if(!mask_match(dname, fname_src_mask,
6828 conn->case_sensitive)) {
6829 TALLOC_FREE(talloced);
6833 error = ERRnoaccess;
6835 /* Get the src smb_fname struct setup. */
6836 TALLOC_FREE(smb_fname_src->base_name);
6837 smb_fname_src->base_name =
6838 talloc_asprintf(smb_fname_src, "%s/%s",
6839 fname_src_dir, dname);
6841 if (!smb_fname_src->base_name) {
6842 TALLOC_FREE(dir_hnd);
6843 TALLOC_FREE(talloced);
6844 reply_nterror(req, NT_STATUS_NO_MEMORY);
6848 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6849 smb_fname_dst->base_name,
6851 TALLOC_FREE(talloced);
6855 TALLOC_FREE(dir_hnd);
6856 TALLOC_FREE(talloced);
6857 reply_nterror(req, NT_STATUS_NO_MEMORY);
6861 TALLOC_FREE(smb_fname_dst->base_name);
6862 smb_fname_dst->base_name = destname;
6864 status = check_name(conn, smb_fname_src->base_name);
6865 if (!NT_STATUS_IS_OK(status)) {
6866 TALLOC_FREE(dir_hnd);
6867 TALLOC_FREE(talloced);
6868 reply_nterror(req, status);
6872 status = check_name(conn, smb_fname_dst->base_name);
6873 if (!NT_STATUS_IS_OK(status)) {
6874 TALLOC_FREE(dir_hnd);
6875 TALLOC_FREE(talloced);
6876 reply_nterror(req, status);
6880 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
6881 smb_fname_src->base_name,
6882 smb_fname_dst->base_name));
6884 status = copy_file(ctx, conn, smb_fname_src,
6885 smb_fname_dst, ofun, count,
6886 target_is_directory);
6887 if (NT_STATUS_IS_OK(status)) {
6891 TALLOC_FREE(talloced);
6893 TALLOC_FREE(dir_hnd);
6897 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
6901 reply_outbuf(req, 1, 0);
6902 SSVAL(req->outbuf,smb_vwv0,count);
6904 TALLOC_FREE(smb_fname_src);
6905 TALLOC_FREE(smb_fname_dst);
6906 TALLOC_FREE(fname_src);
6907 TALLOC_FREE(fname_dst);
6908 TALLOC_FREE(fname_src_mask);
6909 TALLOC_FREE(fname_src_dir);
6911 END_PROFILE(SMBcopy);
6916 #define DBGC_CLASS DBGC_LOCKING
6918 /****************************************************************************
6919 Get a lock pid, dealing with large count requests.
6920 ****************************************************************************/
6922 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
6923 bool large_file_format)
6925 if(!large_file_format)
6926 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
6928 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6931 /****************************************************************************
6932 Get a lock count, dealing with large count requests.
6933 ****************************************************************************/
6935 uint64_t get_lock_count(const uint8_t *data, int data_offset,
6936 bool large_file_format)
6940 if(!large_file_format) {
6941 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6944 #if defined(HAVE_LONGLONG)
6945 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6946 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6947 #else /* HAVE_LONGLONG */
6950 * NT4.x seems to be broken in that it sends large file (64 bit)
6951 * lockingX calls even if the CAP_LARGE_FILES was *not*
6952 * negotiated. For boxes without large unsigned ints truncate the
6953 * lock count by dropping the top 32 bits.
6956 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6957 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6958 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6959 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6960 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6963 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6964 #endif /* HAVE_LONGLONG */
6970 #if !defined(HAVE_LONGLONG)
6971 /****************************************************************************
6972 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6973 ****************************************************************************/
6975 static uint32 map_lock_offset(uint32 high, uint32 low)
6979 uint32 highcopy = high;
6982 * Try and find out how many significant bits there are in high.
6985 for(i = 0; highcopy; i++)
6989 * We use 31 bits not 32 here as POSIX
6990 * lock offsets may not be negative.
6993 mask = (~0) << (31 - i);
6996 return 0; /* Fail. */
7002 #endif /* !defined(HAVE_LONGLONG) */
7004 /****************************************************************************
7005 Get a lock offset, dealing with large offset requests.
7006 ****************************************************************************/
7008 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7009 bool large_file_format, bool *err)
7011 uint64_t offset = 0;
7015 if(!large_file_format) {
7016 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7019 #if defined(HAVE_LONGLONG)
7020 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7021 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7022 #else /* HAVE_LONGLONG */
7025 * NT4.x seems to be broken in that it sends large file (64 bit)
7026 * lockingX calls even if the CAP_LARGE_FILES was *not*
7027 * negotiated. For boxes without large unsigned ints mangle the
7028 * lock offset by mapping the top 32 bits onto the lower 32.
7031 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7032 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7033 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7036 if((new_low = map_lock_offset(high, low)) == 0) {
7038 return (uint64_t)-1;
7041 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7042 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7043 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7044 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7047 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7048 #endif /* HAVE_LONGLONG */
7054 NTSTATUS smbd_do_locking(struct smb_request *req,
7058 uint16_t num_ulocks,
7059 struct smbd_lock_element *ulocks,
7061 struct smbd_lock_element *locks,
7064 connection_struct *conn = req->conn;
7066 NTSTATUS status = NT_STATUS_OK;
7070 /* Data now points at the beginning of the list
7071 of smb_unlkrng structs */
7072 for(i = 0; i < (int)num_ulocks; i++) {
7073 struct smbd_lock_element *e = &ulocks[i];
7075 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7076 "pid %u, file %s\n",
7079 (unsigned int)e->smblctx,
7082 if (e->brltype != UNLOCK_LOCK) {
7083 /* this can only happen with SMB2 */
7084 return NT_STATUS_INVALID_PARAMETER;
7087 status = do_unlock(req->sconn->msg_ctx,
7094 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7095 nt_errstr(status)));
7097 if (!NT_STATUS_IS_OK(status)) {
7102 /* Setup the timeout in seconds. */
7104 if (!lp_blocking_locks(SNUM(conn))) {
7108 /* Data now points at the beginning of the list
7109 of smb_lkrng structs */
7111 for(i = 0; i < (int)num_locks; i++) {
7112 struct smbd_lock_element *e = &locks[i];
7114 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7115 "%llu, file %s timeout = %d\n",
7118 (unsigned long long)e->smblctx,
7122 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7123 struct blocking_lock_record *blr = NULL;
7125 if (num_locks > 1) {
7127 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7128 * if the lock vector contains one entry. When given mutliple cancel
7129 * requests in a single PDU we expect the server to return an
7130 * error. Windows servers seem to accept the request but only
7131 * cancel the first lock.
7132 * JRA - Do what Windows does (tm) :-).
7136 /* MS-CIFS (2.2.4.32.1) behavior. */
7137 return NT_STATUS_DOS(ERRDOS,
7138 ERRcancelviolation);
7140 /* Windows behavior. */
7142 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7143 "cancel request\n"));
7149 if (lp_blocking_locks(SNUM(conn))) {
7151 /* Schedule a message to ourselves to
7152 remove the blocking lock record and
7153 return the right error. */
7155 blr = blocking_lock_cancel_smb1(fsp,
7161 NT_STATUS_FILE_LOCK_CONFLICT);
7163 return NT_STATUS_DOS(
7165 ERRcancelviolation);
7168 /* Remove a matching pending lock. */
7169 status = do_lock_cancel(fsp,
7176 bool blocking_lock = timeout ? true : false;
7177 bool defer_lock = false;
7178 struct byte_range_lock *br_lck;
7179 uint64_t block_smblctx;
7181 br_lck = do_lock(req->sconn->msg_ctx,
7193 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7194 /* Windows internal resolution for blocking locks seems
7195 to be about 200ms... Don't wait for less than that. JRA. */
7196 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7197 timeout = lp_lock_spin_time();
7202 /* If a lock sent with timeout of zero would fail, and
7203 * this lock has been requested multiple times,
7204 * according to brl_lock_failed() we convert this
7205 * request to a blocking lock with a timeout of between
7206 * 150 - 300 milliseconds.
7208 * If lp_lock_spin_time() has been set to 0, we skip
7209 * this blocking retry and fail immediately.
7211 * Replacement for do_lock_spin(). JRA. */
7213 if (!req->sconn->using_smb2 &&
7214 br_lck && lp_blocking_locks(SNUM(conn)) &&
7215 lp_lock_spin_time() && !blocking_lock &&
7216 NT_STATUS_EQUAL((status),
7217 NT_STATUS_FILE_LOCK_CONFLICT))
7220 timeout = lp_lock_spin_time();
7223 if (br_lck && defer_lock) {
7225 * A blocking lock was requested. Package up
7226 * this smb into a queued request and push it
7227 * onto the blocking lock queue.
7229 if(push_blocking_lock_request(br_lck,
7240 TALLOC_FREE(br_lck);
7242 return NT_STATUS_OK;
7246 TALLOC_FREE(br_lck);
7249 if (!NT_STATUS_IS_OK(status)) {
7254 /* If any of the above locks failed, then we must unlock
7255 all of the previous locks (X/Open spec). */
7257 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7259 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7260 i = -1; /* we want to skip the for loop */
7264 * Ensure we don't do a remove on the lock that just failed,
7265 * as under POSIX rules, if we have a lock already there, we
7266 * will delete it (and we shouldn't) .....
7268 for(i--; i >= 0; i--) {
7269 struct smbd_lock_element *e = &locks[i];
7271 do_unlock(req->sconn->msg_ctx,
7281 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7282 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7284 return NT_STATUS_OK;
7287 /****************************************************************************
7288 Reply to a lockingX request.
7289 ****************************************************************************/
7291 void reply_lockingX(struct smb_request *req)
7293 connection_struct *conn = req->conn;
7295 unsigned char locktype;
7296 unsigned char oplocklevel;
7301 const uint8_t *data;
7302 bool large_file_format;
7304 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7305 struct smbd_lock_element *ulocks;
7306 struct smbd_lock_element *locks;
7309 START_PROFILE(SMBlockingX);
7312 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7313 END_PROFILE(SMBlockingX);
7317 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7318 locktype = CVAL(req->vwv+3, 0);
7319 oplocklevel = CVAL(req->vwv+3, 1);
7320 num_ulocks = SVAL(req->vwv+6, 0);
7321 num_locks = SVAL(req->vwv+7, 0);
7322 lock_timeout = IVAL(req->vwv+4, 0);
7323 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7325 if (!check_fsp(conn, req, fsp)) {
7326 END_PROFILE(SMBlockingX);
7332 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7333 /* we don't support these - and CANCEL_LOCK makes w2k
7334 and XP reboot so I don't really want to be
7335 compatible! (tridge) */
7336 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7337 END_PROFILE(SMBlockingX);
7341 /* Check if this is an oplock break on a file
7342 we have granted an oplock on.
7344 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7345 /* Client can insist on breaking to none. */
7346 bool break_to_none = (oplocklevel == 0);
7349 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7350 "for fnum = %d\n", (unsigned int)oplocklevel,
7354 * Make sure we have granted an exclusive or batch oplock on
7358 if (fsp->oplock_type == 0) {
7360 /* The Samba4 nbench simulator doesn't understand
7361 the difference between break to level2 and break
7362 to none from level2 - it sends oplock break
7363 replies in both cases. Don't keep logging an error
7364 message here - just ignore it. JRA. */
7366 DEBUG(5,("reply_lockingX: Error : oplock break from "
7367 "client for fnum = %d (oplock=%d) and no "
7368 "oplock granted on this file (%s).\n",
7369 fsp->fnum, fsp->oplock_type,
7372 /* if this is a pure oplock break request then don't
7374 if (num_locks == 0 && num_ulocks == 0) {
7375 END_PROFILE(SMBlockingX);
7378 END_PROFILE(SMBlockingX);
7379 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7384 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7386 result = remove_oplock(fsp);
7388 result = downgrade_oplock(fsp);
7392 DEBUG(0, ("reply_lockingX: error in removing "
7393 "oplock on file %s\n", fsp_str_dbg(fsp)));
7394 /* Hmmm. Is this panic justified? */
7395 smb_panic("internal tdb error");
7398 reply_to_oplock_break_requests(fsp);
7400 /* if this is a pure oplock break request then don't send a
7402 if (num_locks == 0 && num_ulocks == 0) {
7403 /* Sanity check - ensure a pure oplock break is not a
7405 if(CVAL(req->vwv+0, 0) != 0xff)
7406 DEBUG(0,("reply_lockingX: Error : pure oplock "
7407 "break is a chained %d request !\n",
7408 (unsigned int)CVAL(req->vwv+0, 0)));
7409 END_PROFILE(SMBlockingX);
7415 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7416 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7417 END_PROFILE(SMBlockingX);
7421 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7422 if (ulocks == NULL) {
7423 reply_nterror(req, NT_STATUS_NO_MEMORY);
7424 END_PROFILE(SMBlockingX);
7428 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7429 if (locks == NULL) {
7430 reply_nterror(req, NT_STATUS_NO_MEMORY);
7431 END_PROFILE(SMBlockingX);
7435 /* Data now points at the beginning of the list
7436 of smb_unlkrng structs */
7437 for(i = 0; i < (int)num_ulocks; i++) {
7438 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7439 ulocks[i].count = get_lock_count(data, i, large_file_format);
7440 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7441 ulocks[i].brltype = UNLOCK_LOCK;
7444 * There is no error code marked "stupid client bug".... :-).
7447 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7448 END_PROFILE(SMBlockingX);
7453 /* Now do any requested locks */
7454 data += ((large_file_format ? 20 : 10)*num_ulocks);
7456 /* Data now points at the beginning of the list
7457 of smb_lkrng structs */
7459 for(i = 0; i < (int)num_locks; i++) {
7460 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7461 locks[i].count = get_lock_count(data, i, large_file_format);
7462 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7464 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7465 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7466 locks[i].brltype = PENDING_READ_LOCK;
7468 locks[i].brltype = READ_LOCK;
7471 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7472 locks[i].brltype = PENDING_WRITE_LOCK;
7474 locks[i].brltype = WRITE_LOCK;
7479 * There is no error code marked "stupid client bug".... :-).
7482 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7483 END_PROFILE(SMBlockingX);
7488 status = smbd_do_locking(req, fsp,
7489 locktype, lock_timeout,
7493 if (!NT_STATUS_IS_OK(status)) {
7494 END_PROFILE(SMBlockingX);
7495 reply_nterror(req, status);
7499 END_PROFILE(SMBlockingX);
7503 reply_outbuf(req, 2, 0);
7505 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7506 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7508 END_PROFILE(SMBlockingX);
7513 #define DBGC_CLASS DBGC_ALL
7515 /****************************************************************************
7516 Reply to a SMBreadbmpx (read block multiplex) request.
7517 Always reply with an error, if someone has a platform really needs this,
7518 please contact vl@samba.org
7519 ****************************************************************************/
7521 void reply_readbmpx(struct smb_request *req)
7523 START_PROFILE(SMBreadBmpx);
7524 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7525 END_PROFILE(SMBreadBmpx);
7529 /****************************************************************************
7530 Reply to a SMBreadbs (read block multiplex secondary) request.
7531 Always reply with an error, if someone has a platform really needs this,
7532 please contact vl@samba.org
7533 ****************************************************************************/
7535 void reply_readbs(struct smb_request *req)
7537 START_PROFILE(SMBreadBs);
7538 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7539 END_PROFILE(SMBreadBs);
7543 /****************************************************************************
7544 Reply to a SMBsetattrE.
7545 ****************************************************************************/
7547 void reply_setattrE(struct smb_request *req)
7549 connection_struct *conn = req->conn;
7550 struct smb_file_time ft;
7554 START_PROFILE(SMBsetattrE);
7558 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7562 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7564 if(!fsp || (fsp->conn != conn)) {
7565 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7570 * Convert the DOS times into unix times.
7573 ft.atime = convert_time_t_to_timespec(
7574 srv_make_unix_date2(req->vwv+3));
7575 ft.mtime = convert_time_t_to_timespec(
7576 srv_make_unix_date2(req->vwv+5));
7577 ft.create_time = convert_time_t_to_timespec(
7578 srv_make_unix_date2(req->vwv+1));
7580 reply_outbuf(req, 0, 0);
7583 * Patch from Ray Frush <frush@engr.colostate.edu>
7584 * Sometimes times are sent as zero - ignore them.
7587 /* Ensure we have a valid stat struct for the source. */
7588 status = vfs_stat_fsp(fsp);
7589 if (!NT_STATUS_IS_OK(status)) {
7590 reply_nterror(req, status);
7594 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7595 if (!NT_STATUS_IS_OK(status)) {
7596 reply_nterror(req, status);
7600 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7603 (unsigned int)ft.atime.tv_sec,
7604 (unsigned int)ft.mtime.tv_sec,
7605 (unsigned int)ft.create_time.tv_sec
7608 END_PROFILE(SMBsetattrE);
7613 /* Back from the dead for OS/2..... JRA. */
7615 /****************************************************************************
7616 Reply to a SMBwritebmpx (write block multiplex primary) request.
7617 Always reply with an error, if someone has a platform really needs this,
7618 please contact vl@samba.org
7619 ****************************************************************************/
7621 void reply_writebmpx(struct smb_request *req)
7623 START_PROFILE(SMBwriteBmpx);
7624 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7625 END_PROFILE(SMBwriteBmpx);
7629 /****************************************************************************
7630 Reply to a SMBwritebs (write block multiplex secondary) request.
7631 Always reply with an error, if someone has a platform really needs this,
7632 please contact vl@samba.org
7633 ****************************************************************************/
7635 void reply_writebs(struct smb_request *req)
7637 START_PROFILE(SMBwriteBs);
7638 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7639 END_PROFILE(SMBwriteBs);
7643 /****************************************************************************
7644 Reply to a SMBgetattrE.
7645 ****************************************************************************/
7647 void reply_getattrE(struct smb_request *req)
7649 connection_struct *conn = req->conn;
7652 struct timespec create_ts;
7654 START_PROFILE(SMBgetattrE);
7657 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7658 END_PROFILE(SMBgetattrE);
7662 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7664 if(!fsp || (fsp->conn != conn)) {
7665 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7666 END_PROFILE(SMBgetattrE);
7670 /* Do an fstat on this file */
7672 reply_nterror(req, map_nt_error_from_unix(errno));
7673 END_PROFILE(SMBgetattrE);
7677 mode = dos_mode(conn, fsp->fsp_name);
7680 * Convert the times into dos times. Set create
7681 * date to be last modify date as UNIX doesn't save
7685 reply_outbuf(req, 11, 0);
7687 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7688 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7689 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7690 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7691 /* Should we check pending modtime here ? JRA */
7692 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7693 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7696 SIVAL(req->outbuf, smb_vwv6, 0);
7697 SIVAL(req->outbuf, smb_vwv8, 0);
7699 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7700 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
7701 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7703 SSVAL(req->outbuf,smb_vwv10, mode);
7705 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7707 END_PROFILE(SMBgetattrE);