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"
30 #include "../librpc/gen_ndr/cli_spoolss.h"
32 /****************************************************************************
33 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
34 path or anything including wildcards.
35 We're assuming here that '/' is not the second byte in any multibyte char
36 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
38 ****************************************************************************/
40 /* Custom version for processing POSIX paths. */
41 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
43 static NTSTATUS check_path_syntax_internal(char *path,
45 bool *p_last_component_contains_wcard)
49 NTSTATUS ret = NT_STATUS_OK;
50 bool start_of_name_component = True;
51 bool stream_started = false;
53 *p_last_component_contains_wcard = False;
60 return NT_STATUS_OBJECT_NAME_INVALID;
63 return NT_STATUS_OBJECT_NAME_INVALID;
65 if (strchr_m(&s[1], ':')) {
66 return NT_STATUS_OBJECT_NAME_INVALID;
72 if ((*s == ':') && !posix_path && !stream_started) {
73 if (*p_last_component_contains_wcard) {
74 return NT_STATUS_OBJECT_NAME_INVALID;
76 /* Stream names allow more characters than file names.
77 We're overloading posix_path here to allow a wider
78 range of characters. If stream_started is true this
79 is still a Windows path even if posix_path is true.
82 stream_started = true;
83 start_of_name_component = false;
87 return NT_STATUS_OBJECT_NAME_INVALID;
91 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
93 * Safe to assume is not the second part of a mb char
94 * as this is handled below.
96 /* Eat multiple '/' or '\\' */
97 while (IS_PATH_SEP(*s,posix_path)) {
100 if ((d != path) && (*s != '\0')) {
101 /* We only care about non-leading or trailing '/' or '\\' */
105 start_of_name_component = True;
107 *p_last_component_contains_wcard = False;
111 if (start_of_name_component) {
112 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
113 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
116 * No mb char starts with '.' so we're safe checking the directory separator here.
119 /* If we just added a '/' - delete it */
120 if ((d > path) && (*(d-1) == '/')) {
125 /* Are we at the start ? Can't go back further if so. */
127 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
130 /* Go back one level... */
131 /* We know this is safe as '/' cannot be part of a mb sequence. */
132 /* NOTE - if this assumption is invalid we are not in good shape... */
133 /* Decrement d first as d points to the *next* char to write into. */
134 for (d--; d > path; d--) {
138 s += 2; /* Else go past the .. */
139 /* We're still at the start of a name component, just the previous one. */
142 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
154 if (*s <= 0x1f || *s == '|') {
155 return NT_STATUS_OBJECT_NAME_INVALID;
163 *p_last_component_contains_wcard = True;
172 /* Get the size of the next MB character. */
173 next_codepoint(s,&siz);
191 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
193 return NT_STATUS_INVALID_PARAMETER;
196 start_of_name_component = False;
204 /****************************************************************************
205 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
206 No wildcards allowed.
207 ****************************************************************************/
209 NTSTATUS check_path_syntax(char *path)
212 return check_path_syntax_internal(path, False, &ignore);
215 /****************************************************************************
216 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
217 Wildcards allowed - p_contains_wcard returns true if the last component contained
219 ****************************************************************************/
221 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
223 return check_path_syntax_internal(path, False, p_contains_wcard);
226 /****************************************************************************
227 Check the path for a POSIX client.
228 We're assuming here that '/' is not the second byte in any multibyte char
229 set (a safe assumption).
230 ****************************************************************************/
232 NTSTATUS check_path_syntax_posix(char *path)
235 return check_path_syntax_internal(path, True, &ignore);
238 /****************************************************************************
239 Pull a string and check the path allowing a wilcard - provide for error return.
240 ****************************************************************************/
242 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
243 const char *base_ptr,
250 bool *contains_wcard)
256 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
260 *err = NT_STATUS_INVALID_PARAMETER;
264 *contains_wcard = False;
266 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
268 * For a DFS path the function parse_dfs_path()
269 * will do the path processing, just make a copy.
275 if (lp_posix_pathnames()) {
276 *err = check_path_syntax_posix(*pp_dest);
278 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
284 /****************************************************************************
285 Pull a string and check the path - provide for error return.
286 ****************************************************************************/
288 size_t srvstr_get_path(TALLOC_CTX *ctx,
289 const char *base_ptr,
298 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
299 src_len, flags, err, &ignore);
302 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
303 char **pp_dest, const char *src, int flags,
304 NTSTATUS *err, bool *contains_wcard)
306 return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
307 pp_dest, src, smbreq_bufrem(req, src),
308 flags, err, contains_wcard);
311 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
312 char **pp_dest, const char *src, int flags,
316 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
317 flags, err, &ignore);
320 /****************************************************************************
321 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
322 ****************************************************************************/
324 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
327 if ((fsp == NULL) || (conn == NULL)) {
328 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
331 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
332 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
338 /****************************************************************************
339 Check if we have a correct fsp pointing to a file.
340 ****************************************************************************/
342 bool check_fsp(connection_struct *conn, struct smb_request *req,
345 if (!check_fsp_open(conn, req, fsp)) {
348 if (fsp->is_directory) {
349 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
352 if (fsp->fh->fd == -1) {
353 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
356 fsp->num_smb_operations++;
360 /****************************************************************************
361 Check if we have a correct fsp pointing to a quota fake file. Replacement for
362 the CHECK_NTQUOTA_HANDLE_OK macro.
363 ****************************************************************************/
365 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
368 if (!check_fsp_open(conn, req, fsp)) {
372 if (fsp->is_directory) {
376 if (fsp->fake_file_handle == NULL) {
380 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
384 if (fsp->fake_file_handle->private_data == NULL) {
391 static bool netbios_session_retarget(const char *name, int name_type)
394 char *trim_name_type;
395 const char *retarget_parm;
398 int retarget_type = 0x20;
399 int retarget_port = 139;
400 struct sockaddr_storage retarget_addr;
401 struct sockaddr_in *in_addr;
405 if (get_socket_port(smbd_server_fd()) != 139) {
409 trim_name = talloc_strdup(talloc_tos(), name);
410 if (trim_name == NULL) {
413 trim_char(trim_name, ' ', ' ');
415 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
417 if (trim_name_type == NULL) {
421 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
422 trim_name_type, NULL);
423 if (retarget_parm == NULL) {
424 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
427 if (retarget_parm == NULL) {
431 retarget = talloc_strdup(trim_name, retarget_parm);
432 if (retarget == NULL) {
436 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
438 p = strchr(retarget, ':');
441 retarget_port = atoi(p);
444 p = strchr_m(retarget, '#');
447 sscanf(p, "%x", &retarget_type);
450 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
452 DEBUG(10, ("could not resolve %s\n", retarget));
456 if (retarget_addr.ss_family != AF_INET) {
457 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
461 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
463 _smb_setlen(outbuf, 6);
464 SCVAL(outbuf, 0, 0x84);
465 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
466 *(uint16_t *)(outbuf+8) = htons(retarget_port);
468 if (!srv_send_smb(smbd_server_fd(), (char *)outbuf, false, 0, false,
470 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
476 TALLOC_FREE(trim_name);
480 /****************************************************************************
481 Reply to a (netbios-level) special message.
482 ****************************************************************************/
484 void reply_special(struct smbd_server_connection *sconn, char *inbuf)
486 int msg_type = CVAL(inbuf,0);
487 int msg_flags = CVAL(inbuf,1);
489 char name_type1, name_type2;
492 * We only really use 4 bytes of the outbuf, but for the smb_setlen
493 * calculation & friends (srv_send_smb uses that) we need the full smb
496 char outbuf[smb_size];
500 memset(outbuf, '\0', sizeof(outbuf));
502 smb_setlen(outbuf,0);
505 case 0x81: /* session request */
507 if (sconn->nbt.got_session) {
508 exit_server_cleanly("multiple session request not permitted");
511 SCVAL(outbuf,0,0x82);
513 if (name_len(inbuf+4) > 50 ||
514 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
515 DEBUG(0,("Invalid name length in session request\n"));
518 name_type1 = name_extract(inbuf,4,name1);
519 name_type2 = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
520 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
521 name1, name_type1, name2, name_type2));
523 if (netbios_session_retarget(name1, name_type1)) {
524 exit_server_cleanly("retargeted client");
527 set_local_machine_name(name1, True);
528 set_remote_machine_name(name2, True);
530 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
531 get_local_machine_name(), get_remote_machine_name(),
534 if (name_type2 == 'R') {
535 /* We are being asked for a pathworks session ---
537 SCVAL(outbuf, 0,0x83);
541 /* only add the client's machine name to the list
542 of possibly valid usernames if we are operating
543 in share mode security */
544 if (lp_security() == SEC_SHARE) {
545 add_session_user(sconn, get_remote_machine_name());
548 reload_services(True);
551 sconn->nbt.got_session = true;
554 case 0x89: /* session keepalive request
555 (some old clients produce this?) */
556 SCVAL(outbuf,0,SMBkeepalive);
560 case 0x82: /* positive session response */
561 case 0x83: /* negative session response */
562 case 0x84: /* retarget session response */
563 DEBUG(0,("Unexpected session response\n"));
566 case SMBkeepalive: /* session keepalive */
571 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
572 msg_type, msg_flags));
574 srv_send_smb(smbd_server_fd(), outbuf, false, 0, false, NULL);
578 /****************************************************************************
580 conn POINTER CAN BE NULL HERE !
581 ****************************************************************************/
583 void reply_tcon(struct smb_request *req)
585 connection_struct *conn = req->conn;
587 char *service_buf = NULL;
588 char *password = NULL;
593 DATA_BLOB password_blob;
594 TALLOC_CTX *ctx = talloc_tos();
595 struct smbd_server_connection *sconn = req->sconn;
597 START_PROFILE(SMBtcon);
599 if (req->buflen < 4) {
600 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
601 END_PROFILE(SMBtcon);
605 p = (const char *)req->buf + 1;
606 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
608 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
610 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
613 if (service_buf == NULL || password == NULL || dev == NULL) {
614 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
615 END_PROFILE(SMBtcon);
618 p = strrchr_m(service_buf,'\\');
622 service = service_buf;
625 password_blob = data_blob(password, pwlen+1);
627 conn = make_connection(sconn,service,password_blob,dev,
628 req->vuid,&nt_status);
631 data_blob_clear_free(&password_blob);
634 reply_nterror(req, nt_status);
635 END_PROFILE(SMBtcon);
639 reply_outbuf(req, 2, 0);
640 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
641 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
642 SSVAL(req->outbuf,smb_tid,conn->cnum);
644 DEBUG(3,("tcon service=%s cnum=%d\n",
645 service, conn->cnum));
647 END_PROFILE(SMBtcon);
651 /****************************************************************************
652 Reply to a tcon and X.
653 conn POINTER CAN BE NULL HERE !
654 ****************************************************************************/
656 void reply_tcon_and_X(struct smb_request *req)
658 connection_struct *conn = req->conn;
659 const char *service = NULL;
661 TALLOC_CTX *ctx = talloc_tos();
662 /* what the cleint thinks the device is */
663 char *client_devicetype = NULL;
664 /* what the server tells the client the share represents */
665 const char *server_devicetype;
671 struct smbd_server_connection *sconn = req->sconn;
673 START_PROFILE(SMBtconX);
676 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
677 END_PROFILE(SMBtconX);
681 passlen = SVAL(req->vwv+3, 0);
682 tcon_flags = SVAL(req->vwv+2, 0);
684 /* we might have to close an old one */
685 if ((tcon_flags & 0x1) && conn) {
686 close_cnum(conn,req->vuid);
691 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
692 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
693 END_PROFILE(SMBtconX);
697 if (sconn->smb1.negprot.encrypted_passwords) {
698 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
699 if (lp_security() == SEC_SHARE) {
701 * Security = share always has a pad byte
702 * after the password.
704 p = (const char *)req->buf + passlen + 1;
706 p = (const char *)req->buf + passlen;
709 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
710 /* Ensure correct termination */
711 password.data[passlen]=0;
712 p = (const char *)req->buf + passlen + 1;
715 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
718 data_blob_clear_free(&password);
719 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
720 END_PROFILE(SMBtconX);
725 * the service name can be either: \\server\share
726 * or share directly like on the DELL PowerVault 705
729 q = strchr_m(path+2,'\\');
731 data_blob_clear_free(&password);
732 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
733 END_PROFILE(SMBtconX);
741 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
742 &client_devicetype, p,
743 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
745 if (client_devicetype == NULL) {
746 data_blob_clear_free(&password);
747 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
748 END_PROFILE(SMBtconX);
752 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
754 conn = make_connection(sconn, service, password, client_devicetype,
755 req->vuid, &nt_status);
758 data_blob_clear_free(&password);
761 reply_nterror(req, nt_status);
762 END_PROFILE(SMBtconX);
767 server_devicetype = "IPC";
768 else if ( IS_PRINT(conn) )
769 server_devicetype = "LPT1:";
771 server_devicetype = "A:";
773 if (get_Protocol() < PROTOCOL_NT1) {
774 reply_outbuf(req, 2, 0);
775 if (message_push_string(&req->outbuf, server_devicetype,
776 STR_TERMINATE|STR_ASCII) == -1) {
777 reply_nterror(req, NT_STATUS_NO_MEMORY);
778 END_PROFILE(SMBtconX);
782 /* NT sets the fstype of IPC$ to the null string */
783 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
785 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
786 /* Return permissions. */
790 reply_outbuf(req, 7, 0);
793 perm1 = FILE_ALL_ACCESS;
794 perm2 = FILE_ALL_ACCESS;
796 perm1 = CAN_WRITE(conn) ?
801 SIVAL(req->outbuf, smb_vwv3, perm1);
802 SIVAL(req->outbuf, smb_vwv5, perm2);
804 reply_outbuf(req, 3, 0);
807 if ((message_push_string(&req->outbuf, server_devicetype,
808 STR_TERMINATE|STR_ASCII) == -1)
809 || (message_push_string(&req->outbuf, fstype,
810 STR_TERMINATE) == -1)) {
811 reply_nterror(req, NT_STATUS_NO_MEMORY);
812 END_PROFILE(SMBtconX);
816 /* what does setting this bit do? It is set by NT4 and
817 may affect the ability to autorun mounted cdroms */
818 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
819 (lp_csc_policy(SNUM(conn)) << 2));
821 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
822 DEBUG(2,("Serving %s as a Dfs root\n",
823 lp_servicename(SNUM(conn)) ));
824 SSVAL(req->outbuf, smb_vwv2,
825 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
830 DEBUG(3,("tconX service=%s \n",
833 /* set the incoming and outgoing tid to the just created one */
834 SSVAL(req->inbuf,smb_tid,conn->cnum);
835 SSVAL(req->outbuf,smb_tid,conn->cnum);
837 END_PROFILE(SMBtconX);
839 req->tid = conn->cnum;
844 /****************************************************************************
845 Reply to an unknown type.
846 ****************************************************************************/
848 void reply_unknown_new(struct smb_request *req, uint8 type)
850 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
851 smb_fn_name(type), type, type));
852 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
856 /****************************************************************************
858 conn POINTER CAN BE NULL HERE !
859 ****************************************************************************/
861 void reply_ioctl(struct smb_request *req)
863 connection_struct *conn = req->conn;
870 START_PROFILE(SMBioctl);
873 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
874 END_PROFILE(SMBioctl);
878 device = SVAL(req->vwv+1, 0);
879 function = SVAL(req->vwv+2, 0);
880 ioctl_code = (device << 16) + function;
882 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
884 switch (ioctl_code) {
885 case IOCTL_QUERY_JOB_INFO:
889 reply_force_doserror(req, ERRSRV, ERRnosupport);
890 END_PROFILE(SMBioctl);
894 reply_outbuf(req, 8, replysize+1);
895 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
896 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
897 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
898 p = smb_buf(req->outbuf);
899 memset(p, '\0', replysize+1); /* valgrind-safe. */
900 p += 1; /* Allow for alignment */
902 switch (ioctl_code) {
903 case IOCTL_QUERY_JOB_INFO:
905 files_struct *fsp = file_fsp(
906 req, SVAL(req->vwv+0, 0));
908 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
909 END_PROFILE(SMBioctl);
913 if (fsp->print_file) {
914 SSVAL(p, 0, fsp->print_file->rap_jobid);
918 srvstr_push((char *)req->outbuf, req->flags2, p+2,
920 STR_TERMINATE|STR_ASCII);
922 srvstr_push((char *)req->outbuf, req->flags2,
923 p+18, lp_servicename(SNUM(conn)),
924 13, STR_TERMINATE|STR_ASCII);
932 END_PROFILE(SMBioctl);
936 /****************************************************************************
937 Strange checkpath NTSTATUS mapping.
938 ****************************************************************************/
940 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
942 /* Strange DOS error code semantics only for checkpath... */
943 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
944 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
945 /* We need to map to ERRbadpath */
946 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
952 /****************************************************************************
953 Reply to a checkpath.
954 ****************************************************************************/
956 void reply_checkpath(struct smb_request *req)
958 connection_struct *conn = req->conn;
959 struct smb_filename *smb_fname = NULL;
962 TALLOC_CTX *ctx = talloc_tos();
964 START_PROFILE(SMBcheckpath);
966 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
967 STR_TERMINATE, &status);
969 if (!NT_STATUS_IS_OK(status)) {
970 status = map_checkpath_error(req->flags2, status);
971 reply_nterror(req, status);
972 END_PROFILE(SMBcheckpath);
976 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
978 status = filename_convert(ctx,
980 req->flags2 & FLAGS2_DFS_PATHNAMES,
986 if (!NT_STATUS_IS_OK(status)) {
987 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
988 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
990 END_PROFILE(SMBcheckpath);
996 if (!VALID_STAT(smb_fname->st) &&
997 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
998 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
999 smb_fname_str_dbg(smb_fname), strerror(errno)));
1000 status = map_nt_error_from_unix(errno);
1004 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1005 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1006 ERRDOS, ERRbadpath);
1010 reply_outbuf(req, 0, 0);
1013 /* We special case this - as when a Windows machine
1014 is parsing a path is steps through the components
1015 one at a time - if a component fails it expects
1016 ERRbadpath, not ERRbadfile.
1018 status = map_checkpath_error(req->flags2, status);
1019 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1021 * Windows returns different error codes if
1022 * the parent directory is valid but not the
1023 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1024 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1025 * if the path is invalid.
1027 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1028 ERRDOS, ERRbadpath);
1032 reply_nterror(req, status);
1035 TALLOC_FREE(smb_fname);
1036 END_PROFILE(SMBcheckpath);
1040 /****************************************************************************
1042 ****************************************************************************/
1044 void reply_getatr(struct smb_request *req)
1046 connection_struct *conn = req->conn;
1047 struct smb_filename *smb_fname = NULL;
1054 TALLOC_CTX *ctx = talloc_tos();
1055 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1057 START_PROFILE(SMBgetatr);
1059 p = (const char *)req->buf + 1;
1060 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1061 if (!NT_STATUS_IS_OK(status)) {
1062 reply_nterror(req, status);
1066 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1067 under WfWg - weird! */
1068 if (*fname == '\0') {
1069 mode = aHIDDEN | aDIR;
1070 if (!CAN_WRITE(conn)) {
1076 status = filename_convert(ctx,
1078 req->flags2 & FLAGS2_DFS_PATHNAMES,
1083 if (!NT_STATUS_IS_OK(status)) {
1084 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1085 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1086 ERRSRV, ERRbadpath);
1089 reply_nterror(req, status);
1092 if (!VALID_STAT(smb_fname->st) &&
1093 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1094 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1095 smb_fname_str_dbg(smb_fname),
1097 reply_nterror(req, map_nt_error_from_unix(errno));
1101 mode = dos_mode(conn, smb_fname);
1102 size = smb_fname->st.st_ex_size;
1104 if (ask_sharemode) {
1105 struct timespec write_time_ts;
1106 struct file_id fileid;
1108 ZERO_STRUCT(write_time_ts);
1109 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1110 get_file_infos(fileid, NULL, &write_time_ts);
1111 if (!null_timespec(write_time_ts)) {
1112 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1116 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1122 reply_outbuf(req, 10, 0);
1124 SSVAL(req->outbuf,smb_vwv0,mode);
1125 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1126 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1128 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1130 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1132 if (get_Protocol() >= PROTOCOL_NT1) {
1133 SSVAL(req->outbuf, smb_flg2,
1134 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1137 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1138 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1141 TALLOC_FREE(smb_fname);
1143 END_PROFILE(SMBgetatr);
1147 /****************************************************************************
1149 ****************************************************************************/
1151 void reply_setatr(struct smb_request *req)
1153 struct smb_file_time ft;
1154 connection_struct *conn = req->conn;
1155 struct smb_filename *smb_fname = NULL;
1161 TALLOC_CTX *ctx = talloc_tos();
1163 START_PROFILE(SMBsetatr);
1168 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1172 p = (const char *)req->buf + 1;
1173 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1174 if (!NT_STATUS_IS_OK(status)) {
1175 reply_nterror(req, status);
1179 status = filename_convert(ctx,
1181 req->flags2 & FLAGS2_DFS_PATHNAMES,
1186 if (!NT_STATUS_IS_OK(status)) {
1187 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1188 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1189 ERRSRV, ERRbadpath);
1192 reply_nterror(req, status);
1196 if (smb_fname->base_name[0] == '.' &&
1197 smb_fname->base_name[1] == '\0') {
1199 * Not sure here is the right place to catch this
1200 * condition. Might be moved to somewhere else later -- vl
1202 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1206 mode = SVAL(req->vwv+0, 0);
1207 mtime = srv_make_unix_date3(req->vwv+1);
1209 ft.mtime = convert_time_t_to_timespec(mtime);
1210 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1211 if (!NT_STATUS_IS_OK(status)) {
1212 reply_nterror(req, status);
1216 if (mode != FILE_ATTRIBUTE_NORMAL) {
1217 if (VALID_STAT_OF_DIR(smb_fname->st))
1222 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1224 reply_nterror(req, map_nt_error_from_unix(errno));
1229 reply_outbuf(req, 0, 0);
1231 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1234 TALLOC_FREE(smb_fname);
1235 END_PROFILE(SMBsetatr);
1239 /****************************************************************************
1241 ****************************************************************************/
1243 void reply_dskattr(struct smb_request *req)
1245 connection_struct *conn = req->conn;
1246 uint64_t dfree,dsize,bsize;
1247 START_PROFILE(SMBdskattr);
1249 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1250 reply_nterror(req, map_nt_error_from_unix(errno));
1251 END_PROFILE(SMBdskattr);
1255 reply_outbuf(req, 5, 0);
1257 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1258 double total_space, free_space;
1259 /* we need to scale this to a number that DOS6 can handle. We
1260 use floating point so we can handle large drives on systems
1261 that don't have 64 bit integers
1263 we end up displaying a maximum of 2G to DOS systems
1265 total_space = dsize * (double)bsize;
1266 free_space = dfree * (double)bsize;
1268 dsize = (uint64_t)((total_space+63*512) / (64*512));
1269 dfree = (uint64_t)((free_space+63*512) / (64*512));
1271 if (dsize > 0xFFFF) dsize = 0xFFFF;
1272 if (dfree > 0xFFFF) dfree = 0xFFFF;
1274 SSVAL(req->outbuf,smb_vwv0,dsize);
1275 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1276 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1277 SSVAL(req->outbuf,smb_vwv3,dfree);
1279 SSVAL(req->outbuf,smb_vwv0,dsize);
1280 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1281 SSVAL(req->outbuf,smb_vwv2,512);
1282 SSVAL(req->outbuf,smb_vwv3,dfree);
1285 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1287 END_PROFILE(SMBdskattr);
1292 * Utility function to split the filename from the directory.
1294 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1295 char **fname_dir_out,
1296 char **fname_mask_out)
1298 const char *p = NULL;
1299 char *fname_dir = NULL;
1300 char *fname_mask = NULL;
1302 p = strrchr_m(fname_in, '/');
1304 fname_dir = talloc_strdup(ctx, ".");
1305 fname_mask = talloc_strdup(ctx, fname_in);
1307 fname_dir = talloc_strndup(ctx, fname_in,
1308 PTR_DIFF(p, fname_in));
1309 fname_mask = talloc_strdup(ctx, p+1);
1312 if (!fname_dir || !fname_mask) {
1313 TALLOC_FREE(fname_dir);
1314 TALLOC_FREE(fname_mask);
1315 return NT_STATUS_NO_MEMORY;
1318 *fname_dir_out = fname_dir;
1319 *fname_mask_out = fname_mask;
1320 return NT_STATUS_OK;
1323 /****************************************************************************
1325 Can be called from SMBsearch, SMBffirst or SMBfunique.
1326 ****************************************************************************/
1328 void reply_search(struct smb_request *req)
1330 connection_struct *conn = req->conn;
1332 const char *mask = NULL;
1333 char *directory = NULL;
1334 struct smb_filename *smb_fname = NULL;
1338 struct timespec date;
1340 unsigned int numentries = 0;
1341 unsigned int maxentries = 0;
1342 bool finished = False;
1347 bool check_descend = False;
1348 bool expect_close = False;
1350 bool mask_contains_wcard = False;
1351 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1352 TALLOC_CTX *ctx = talloc_tos();
1353 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1354 struct dptr_struct *dirptr = NULL;
1355 struct smbd_server_connection *sconn = req->sconn;
1357 START_PROFILE(SMBsearch);
1360 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1364 if (lp_posix_pathnames()) {
1365 reply_unknown_new(req, req->cmd);
1369 /* If we were called as SMBffirst then we must expect close. */
1370 if(req->cmd == SMBffirst) {
1371 expect_close = True;
1374 reply_outbuf(req, 1, 3);
1375 maxentries = SVAL(req->vwv+0, 0);
1376 dirtype = SVAL(req->vwv+1, 0);
1377 p = (const char *)req->buf + 1;
1378 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1379 &nt_status, &mask_contains_wcard);
1380 if (!NT_STATUS_IS_OK(nt_status)) {
1381 reply_nterror(req, nt_status);
1386 status_len = SVAL(p, 0);
1389 /* dirtype &= ~aDIR; */
1391 if (status_len == 0) {
1392 nt_status = filename_convert(ctx, conn,
1393 req->flags2 & FLAGS2_DFS_PATHNAMES,
1395 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1396 &mask_contains_wcard,
1398 if (!NT_STATUS_IS_OK(nt_status)) {
1399 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1400 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1401 ERRSRV, ERRbadpath);
1404 reply_nterror(req, nt_status);
1408 directory = smb_fname->base_name;
1410 p = strrchr_m(directory,'/');
1411 if ((p != NULL) && (*directory != '/')) {
1413 directory = talloc_strndup(ctx, directory,
1414 PTR_DIFF(p, directory));
1417 directory = talloc_strdup(ctx,".");
1421 reply_nterror(req, NT_STATUS_NO_MEMORY);
1425 memset((char *)status,'\0',21);
1426 SCVAL(status,0,(dirtype & 0x1F));
1428 nt_status = dptr_create(conn,
1434 mask_contains_wcard,
1437 if (!NT_STATUS_IS_OK(nt_status)) {
1438 reply_nterror(req, nt_status);
1441 dptr_num = dptr_dnum(dirptr);
1444 const char *dirpath;
1446 memcpy(status,p,21);
1447 status_dirtype = CVAL(status,0) & 0x1F;
1448 if (status_dirtype != (dirtype & 0x1F)) {
1449 dirtype = status_dirtype;
1452 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1456 dirpath = dptr_path(sconn, dptr_num);
1457 directory = talloc_strdup(ctx, dirpath);
1459 reply_nterror(req, NT_STATUS_NO_MEMORY);
1463 mask = dptr_wcard(sconn, dptr_num);
1468 * For a 'continue' search we have no string. So
1469 * check from the initial saved string.
1471 mask_contains_wcard = ms_has_wild(mask);
1472 dirtype = dptr_attr(sconn, dptr_num);
1475 DEBUG(4,("dptr_num is %d\n",dptr_num));
1477 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1478 dptr_init_search_op(dirptr);
1480 if ((dirtype&0x1F) == aVOLID) {
1481 char buf[DIR_STRUCT_SIZE];
1482 memcpy(buf,status,21);
1483 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1484 0,aVOLID,0,!allow_long_path_components)) {
1485 reply_nterror(req, NT_STATUS_NO_MEMORY);
1488 dptr_fill(sconn, buf+12,dptr_num);
1489 if (dptr_zero(buf+12) && (status_len==0)) {
1494 if (message_push_blob(&req->outbuf,
1495 data_blob_const(buf, sizeof(buf)))
1497 reply_nterror(req, NT_STATUS_NO_MEMORY);
1505 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1508 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1509 directory,lp_dontdescend(SNUM(conn))));
1510 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1511 check_descend = True;
1514 for (i=numentries;(i<maxentries) && !finished;i++) {
1515 finished = !get_dir_entry(ctx,
1526 char buf[DIR_STRUCT_SIZE];
1527 memcpy(buf,status,21);
1528 if (!make_dir_struct(ctx,
1534 convert_timespec_to_time_t(date),
1535 !allow_long_path_components)) {
1536 reply_nterror(req, NT_STATUS_NO_MEMORY);
1539 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1542 if (message_push_blob(&req->outbuf,
1543 data_blob_const(buf, sizeof(buf)))
1545 reply_nterror(req, NT_STATUS_NO_MEMORY);
1555 /* If we were called as SMBffirst with smb_search_id == NULL
1556 and no entries were found then return error and close dirptr
1559 if (numentries == 0) {
1560 dptr_close(sconn, &dptr_num);
1561 } else if(expect_close && status_len == 0) {
1562 /* Close the dptr - we know it's gone */
1563 dptr_close(sconn, &dptr_num);
1566 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1567 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1568 dptr_close(sconn, &dptr_num);
1571 if ((numentries == 0) && !mask_contains_wcard) {
1572 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1576 SSVAL(req->outbuf,smb_vwv0,numentries);
1577 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1578 SCVAL(smb_buf(req->outbuf),0,5);
1579 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1581 /* The replies here are never long name. */
1582 SSVAL(req->outbuf, smb_flg2,
1583 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1584 if (!allow_long_path_components) {
1585 SSVAL(req->outbuf, smb_flg2,
1586 SVAL(req->outbuf, smb_flg2)
1587 & (~FLAGS2_LONG_PATH_COMPONENTS));
1590 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1591 SSVAL(req->outbuf, smb_flg2,
1592 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1594 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1595 smb_fn_name(req->cmd),
1602 TALLOC_FREE(directory);
1603 TALLOC_FREE(smb_fname);
1604 END_PROFILE(SMBsearch);
1608 /****************************************************************************
1609 Reply to a fclose (stop directory search).
1610 ****************************************************************************/
1612 void reply_fclose(struct smb_request *req)
1620 bool path_contains_wcard = False;
1621 TALLOC_CTX *ctx = talloc_tos();
1622 struct smbd_server_connection *sconn = req->sconn;
1624 START_PROFILE(SMBfclose);
1626 if (lp_posix_pathnames()) {
1627 reply_unknown_new(req, req->cmd);
1628 END_PROFILE(SMBfclose);
1632 p = (const char *)req->buf + 1;
1633 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1634 &err, &path_contains_wcard);
1635 if (!NT_STATUS_IS_OK(err)) {
1636 reply_nterror(req, err);
1637 END_PROFILE(SMBfclose);
1641 status_len = SVAL(p,0);
1644 if (status_len == 0) {
1645 reply_force_doserror(req, ERRSRV, ERRsrverror);
1646 END_PROFILE(SMBfclose);
1650 memcpy(status,p,21);
1652 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1653 /* Close the dptr - we know it's gone */
1654 dptr_close(sconn, &dptr_num);
1657 reply_outbuf(req, 1, 0);
1658 SSVAL(req->outbuf,smb_vwv0,0);
1660 DEBUG(3,("search close\n"));
1662 END_PROFILE(SMBfclose);
1666 /****************************************************************************
1668 ****************************************************************************/
1670 void reply_open(struct smb_request *req)
1672 connection_struct *conn = req->conn;
1673 struct smb_filename *smb_fname = NULL;
1685 uint32 create_disposition;
1686 uint32 create_options = 0;
1687 uint32_t private_flags = 0;
1689 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1690 TALLOC_CTX *ctx = talloc_tos();
1692 START_PROFILE(SMBopen);
1695 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1699 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1700 deny_mode = SVAL(req->vwv+0, 0);
1701 dos_attr = SVAL(req->vwv+1, 0);
1703 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1704 STR_TERMINATE, &status);
1705 if (!NT_STATUS_IS_OK(status)) {
1706 reply_nterror(req, status);
1710 status = filename_convert(ctx,
1712 req->flags2 & FLAGS2_DFS_PATHNAMES,
1717 if (!NT_STATUS_IS_OK(status)) {
1718 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1719 reply_botherror(req,
1720 NT_STATUS_PATH_NOT_COVERED,
1721 ERRSRV, ERRbadpath);
1724 reply_nterror(req, status);
1728 if (!map_open_params_to_ntcreate(smb_fname, deny_mode,
1729 OPENX_FILE_EXISTS_OPEN, &access_mask,
1730 &share_mode, &create_disposition,
1731 &create_options, &private_flags)) {
1732 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1736 status = SMB_VFS_CREATE_FILE(
1739 0, /* root_dir_fid */
1740 smb_fname, /* fname */
1741 access_mask, /* access_mask */
1742 share_mode, /* share_access */
1743 create_disposition, /* create_disposition*/
1744 create_options, /* create_options */
1745 dos_attr, /* file_attributes */
1746 oplock_request, /* oplock_request */
1747 0, /* allocation_size */
1754 if (!NT_STATUS_IS_OK(status)) {
1755 if (open_was_deferred(req->mid)) {
1756 /* We have re-scheduled this call. */
1759 reply_openerror(req, status);
1763 size = smb_fname->st.st_ex_size;
1764 fattr = dos_mode(conn, smb_fname);
1766 /* Deal with other possible opens having a modified
1768 if (ask_sharemode) {
1769 struct timespec write_time_ts;
1771 ZERO_STRUCT(write_time_ts);
1772 get_file_infos(fsp->file_id, NULL, &write_time_ts);
1773 if (!null_timespec(write_time_ts)) {
1774 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1778 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1781 DEBUG(3,("attempt to open a directory %s\n",
1783 close_file(req, fsp, ERROR_CLOSE);
1784 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1785 ERRDOS, ERRnoaccess);
1789 reply_outbuf(req, 7, 0);
1790 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1791 SSVAL(req->outbuf,smb_vwv1,fattr);
1792 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1793 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1795 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1797 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1798 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1800 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1801 SCVAL(req->outbuf,smb_flg,
1802 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1805 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1806 SCVAL(req->outbuf,smb_flg,
1807 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1810 TALLOC_FREE(smb_fname);
1811 END_PROFILE(SMBopen);
1815 /****************************************************************************
1816 Reply to an open and X.
1817 ****************************************************************************/
1819 void reply_open_and_X(struct smb_request *req)
1821 connection_struct *conn = req->conn;
1822 struct smb_filename *smb_fname = NULL;
1827 /* Breakout the oplock request bits so we can set the
1828 reply bits separately. */
1829 int ex_oplock_request;
1830 int core_oplock_request;
1833 int smb_sattr = SVAL(req->vwv+4, 0);
1834 uint32 smb_time = make_unix_date3(req->vwv+6);
1842 uint64_t allocation_size;
1843 ssize_t retval = -1;
1846 uint32 create_disposition;
1847 uint32 create_options = 0;
1848 uint32_t private_flags = 0;
1849 TALLOC_CTX *ctx = talloc_tos();
1851 START_PROFILE(SMBopenX);
1853 if (req->wct < 15) {
1854 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1858 open_flags = SVAL(req->vwv+2, 0);
1859 deny_mode = SVAL(req->vwv+3, 0);
1860 smb_attr = SVAL(req->vwv+5, 0);
1861 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1862 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1863 oplock_request = ex_oplock_request | core_oplock_request;
1864 smb_ofun = SVAL(req->vwv+8, 0);
1865 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1867 /* If it's an IPC, pass off the pipe handler. */
1869 if (lp_nt_pipe_support()) {
1870 reply_open_pipe_and_X(conn, req);
1872 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1877 /* XXXX we need to handle passed times, sattr and flags */
1878 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1879 STR_TERMINATE, &status);
1880 if (!NT_STATUS_IS_OK(status)) {
1881 reply_nterror(req, status);
1885 status = filename_convert(ctx,
1887 req->flags2 & FLAGS2_DFS_PATHNAMES,
1892 if (!NT_STATUS_IS_OK(status)) {
1893 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1894 reply_botherror(req,
1895 NT_STATUS_PATH_NOT_COVERED,
1896 ERRSRV, ERRbadpath);
1899 reply_nterror(req, status);
1903 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, smb_ofun,
1904 &access_mask, &share_mode,
1905 &create_disposition,
1908 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1912 status = SMB_VFS_CREATE_FILE(
1915 0, /* root_dir_fid */
1916 smb_fname, /* fname */
1917 access_mask, /* access_mask */
1918 share_mode, /* share_access */
1919 create_disposition, /* create_disposition*/
1920 create_options, /* create_options */
1921 smb_attr, /* file_attributes */
1922 oplock_request, /* oplock_request */
1923 0, /* allocation_size */
1928 &smb_action); /* pinfo */
1930 if (!NT_STATUS_IS_OK(status)) {
1931 if (open_was_deferred(req->mid)) {
1932 /* We have re-scheduled this call. */
1935 reply_openerror(req, status);
1939 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1940 if the file is truncated or created. */
1941 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1942 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1943 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1944 close_file(req, fsp, ERROR_CLOSE);
1945 reply_nterror(req, NT_STATUS_DISK_FULL);
1948 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1950 close_file(req, fsp, ERROR_CLOSE);
1951 reply_nterror(req, NT_STATUS_DISK_FULL);
1954 smb_fname->st.st_ex_size =
1955 SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
1958 fattr = dos_mode(conn, smb_fname);
1959 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1961 close_file(req, fsp, ERROR_CLOSE);
1962 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1966 /* If the caller set the extended oplock request bit
1967 and we granted one (by whatever means) - set the
1968 correct bit for extended oplock reply.
1971 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1972 smb_action |= EXTENDED_OPLOCK_GRANTED;
1975 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1976 smb_action |= EXTENDED_OPLOCK_GRANTED;
1979 /* If the caller set the core oplock request bit
1980 and we granted one (by whatever means) - set the
1981 correct bit for core oplock reply.
1984 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1985 reply_outbuf(req, 19, 0);
1987 reply_outbuf(req, 15, 0);
1990 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1991 SCVAL(req->outbuf, smb_flg,
1992 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1995 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1996 SCVAL(req->outbuf, smb_flg,
1997 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2000 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2001 SSVAL(req->outbuf,smb_vwv3,fattr);
2002 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2003 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2005 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2007 SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size);
2008 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2009 SSVAL(req->outbuf,smb_vwv11,smb_action);
2011 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2012 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2017 TALLOC_FREE(smb_fname);
2018 END_PROFILE(SMBopenX);
2022 /****************************************************************************
2023 Reply to a SMBulogoffX.
2024 ****************************************************************************/
2026 void reply_ulogoffX(struct smb_request *req)
2028 struct smbd_server_connection *sconn = req->sconn;
2031 START_PROFILE(SMBulogoffX);
2033 vuser = get_valid_user_struct(sconn, req->vuid);
2036 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2040 /* in user level security we are supposed to close any files
2041 open by this user */
2042 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2043 file_close_user(req->vuid);
2046 invalidate_vuid(sconn, req->vuid);
2048 reply_outbuf(req, 2, 0);
2050 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2052 END_PROFILE(SMBulogoffX);
2053 req->vuid = UID_FIELD_INVALID;
2057 /****************************************************************************
2058 Reply to a mknew or a create.
2059 ****************************************************************************/
2061 void reply_mknew(struct smb_request *req)
2063 connection_struct *conn = req->conn;
2064 struct smb_filename *smb_fname = NULL;
2067 struct smb_file_time ft;
2069 int oplock_request = 0;
2071 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2072 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2073 uint32 create_disposition;
2074 uint32 create_options = 0;
2075 TALLOC_CTX *ctx = talloc_tos();
2077 START_PROFILE(SMBcreate);
2081 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2085 fattr = SVAL(req->vwv+0, 0);
2086 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2089 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2091 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2092 STR_TERMINATE, &status);
2093 if (!NT_STATUS_IS_OK(status)) {
2094 reply_nterror(req, status);
2098 status = filename_convert(ctx,
2100 req->flags2 & FLAGS2_DFS_PATHNAMES,
2105 if (!NT_STATUS_IS_OK(status)) {
2106 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2107 reply_botherror(req,
2108 NT_STATUS_PATH_NOT_COVERED,
2109 ERRSRV, ERRbadpath);
2112 reply_nterror(req, status);
2116 if (fattr & aVOLID) {
2117 DEBUG(0,("Attempt to create file (%s) with volid set - "
2118 "please report this\n",
2119 smb_fname_str_dbg(smb_fname)));
2122 if(req->cmd == SMBmknew) {
2123 /* We should fail if file exists. */
2124 create_disposition = FILE_CREATE;
2126 /* Create if file doesn't exist, truncate if it does. */
2127 create_disposition = FILE_OVERWRITE_IF;
2130 status = SMB_VFS_CREATE_FILE(
2133 0, /* root_dir_fid */
2134 smb_fname, /* fname */
2135 access_mask, /* access_mask */
2136 share_mode, /* share_access */
2137 create_disposition, /* create_disposition*/
2138 create_options, /* create_options */
2139 fattr, /* file_attributes */
2140 oplock_request, /* oplock_request */
2141 0, /* allocation_size */
2142 0, /* private_flags */
2148 if (!NT_STATUS_IS_OK(status)) {
2149 if (open_was_deferred(req->mid)) {
2150 /* We have re-scheduled this call. */
2153 reply_openerror(req, status);
2157 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2158 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2159 if (!NT_STATUS_IS_OK(status)) {
2160 END_PROFILE(SMBcreate);
2164 reply_outbuf(req, 1, 0);
2165 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2167 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2168 SCVAL(req->outbuf,smb_flg,
2169 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2172 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2173 SCVAL(req->outbuf,smb_flg,
2174 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2177 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2178 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2179 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2180 (unsigned int)fattr));
2183 TALLOC_FREE(smb_fname);
2184 END_PROFILE(SMBcreate);
2188 /****************************************************************************
2189 Reply to a create temporary file.
2190 ****************************************************************************/
2192 void reply_ctemp(struct smb_request *req)
2194 connection_struct *conn = req->conn;
2195 struct smb_filename *smb_fname = NULL;
2203 TALLOC_CTX *ctx = talloc_tos();
2205 START_PROFILE(SMBctemp);
2208 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2212 fattr = SVAL(req->vwv+0, 0);
2213 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2215 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2216 STR_TERMINATE, &status);
2217 if (!NT_STATUS_IS_OK(status)) {
2218 reply_nterror(req, status);
2222 fname = talloc_asprintf(ctx,
2226 fname = talloc_strdup(ctx, "TMXXXXXX");
2230 reply_nterror(req, NT_STATUS_NO_MEMORY);
2234 status = filename_convert(ctx, conn,
2235 req->flags2 & FLAGS2_DFS_PATHNAMES,
2240 if (!NT_STATUS_IS_OK(status)) {
2241 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2242 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2243 ERRSRV, ERRbadpath);
2246 reply_nterror(req, status);
2250 tmpfd = mkstemp(smb_fname->base_name);
2252 reply_nterror(req, map_nt_error_from_unix(errno));
2256 SMB_VFS_STAT(conn, smb_fname);
2258 /* We should fail if file does not exist. */
2259 status = SMB_VFS_CREATE_FILE(
2262 0, /* root_dir_fid */
2263 smb_fname, /* fname */
2264 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2265 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2266 FILE_OPEN, /* create_disposition*/
2267 0, /* create_options */
2268 fattr, /* file_attributes */
2269 oplock_request, /* oplock_request */
2270 0, /* allocation_size */
2271 0, /* private_flags */
2277 /* close fd from mkstemp() */
2280 if (!NT_STATUS_IS_OK(status)) {
2281 if (open_was_deferred(req->mid)) {
2282 /* We have re-scheduled this call. */
2285 reply_openerror(req, status);
2289 reply_outbuf(req, 1, 0);
2290 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2292 /* the returned filename is relative to the directory */
2293 s = strrchr_m(fsp->fsp_name->base_name, '/');
2295 s = fsp->fsp_name->base_name;
2301 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2302 thing in the byte section. JRA */
2303 SSVALS(p, 0, -1); /* what is this? not in spec */
2305 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2307 reply_nterror(req, NT_STATUS_NO_MEMORY);
2311 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2312 SCVAL(req->outbuf, smb_flg,
2313 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2316 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2317 SCVAL(req->outbuf, smb_flg,
2318 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2321 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2322 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2323 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2325 TALLOC_FREE(smb_fname);
2326 END_PROFILE(SMBctemp);
2330 /*******************************************************************
2331 Check if a user is allowed to rename a file.
2332 ********************************************************************/
2334 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2339 if (!CAN_WRITE(conn)) {
2340 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2343 fmode = dos_mode(conn, fsp->fsp_name);
2344 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2345 return NT_STATUS_NO_SUCH_FILE;
2348 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2349 if (fsp->posix_open) {
2350 return NT_STATUS_OK;
2353 /* If no pathnames are open below this
2354 directory, allow the rename. */
2356 if (file_find_subpath(fsp)) {
2357 return NT_STATUS_ACCESS_DENIED;
2359 return NT_STATUS_OK;
2362 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2363 return NT_STATUS_OK;
2366 return NT_STATUS_ACCESS_DENIED;
2369 /*******************************************************************
2370 * unlink a file with all relevant access checks
2371 *******************************************************************/
2373 static NTSTATUS do_unlink(connection_struct *conn,
2374 struct smb_request *req,
2375 struct smb_filename *smb_fname,
2380 uint32 dirtype_orig = dirtype;
2383 bool posix_paths = lp_posix_pathnames();
2385 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2386 smb_fname_str_dbg(smb_fname),
2389 if (!CAN_WRITE(conn)) {
2390 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2394 ret = SMB_VFS_LSTAT(conn, smb_fname);
2396 ret = SMB_VFS_STAT(conn, smb_fname);
2399 return map_nt_error_from_unix(errno);
2402 fattr = dos_mode(conn, smb_fname);
2404 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2405 dirtype = aDIR|aARCH|aRONLY;
2408 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2410 return NT_STATUS_NO_SUCH_FILE;
2413 if (!dir_check_ftype(conn, fattr, dirtype)) {
2415 return NT_STATUS_FILE_IS_A_DIRECTORY;
2417 return NT_STATUS_NO_SUCH_FILE;
2420 if (dirtype_orig & 0x8000) {
2421 /* These will never be set for POSIX. */
2422 return NT_STATUS_NO_SUCH_FILE;
2426 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2427 return NT_STATUS_FILE_IS_A_DIRECTORY;
2430 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2431 return NT_STATUS_NO_SUCH_FILE;
2434 if (dirtype & 0xFF00) {
2435 /* These will never be set for POSIX. */
2436 return NT_STATUS_NO_SUCH_FILE;
2441 return NT_STATUS_NO_SUCH_FILE;
2444 /* Can't delete a directory. */
2446 return NT_STATUS_FILE_IS_A_DIRECTORY;
2451 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2452 return NT_STATUS_OBJECT_NAME_INVALID;
2453 #endif /* JRATEST */
2455 /* On open checks the open itself will check the share mode, so
2456 don't do it here as we'll get it wrong. */
2458 status = SMB_VFS_CREATE_FILE
2461 0, /* root_dir_fid */
2462 smb_fname, /* fname */
2463 DELETE_ACCESS, /* access_mask */
2464 FILE_SHARE_NONE, /* share_access */
2465 FILE_OPEN, /* create_disposition*/
2466 FILE_NON_DIRECTORY_FILE, /* create_options */
2467 /* file_attributes */
2468 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2469 FILE_ATTRIBUTE_NORMAL,
2470 0, /* oplock_request */
2471 0, /* allocation_size */
2472 0, /* private_flags */
2478 if (!NT_STATUS_IS_OK(status)) {
2479 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2480 nt_errstr(status)));
2484 status = can_set_delete_on_close(fsp, fattr);
2485 if (!NT_STATUS_IS_OK(status)) {
2486 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2488 smb_fname_str_dbg(smb_fname),
2489 nt_errstr(status)));
2490 close_file(req, fsp, NORMAL_CLOSE);
2494 /* The set is across all open files on this dev/inode pair. */
2495 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2496 close_file(req, fsp, NORMAL_CLOSE);
2497 return NT_STATUS_ACCESS_DENIED;
2500 return close_file(req, fsp, NORMAL_CLOSE);
2503 /****************************************************************************
2504 The guts of the unlink command, split out so it may be called by the NT SMB
2506 ****************************************************************************/
2508 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2509 uint32 dirtype, struct smb_filename *smb_fname,
2512 char *fname_dir = NULL;
2513 char *fname_mask = NULL;
2515 NTSTATUS status = NT_STATUS_OK;
2516 TALLOC_CTX *ctx = talloc_tos();
2518 /* Split up the directory from the filename/mask. */
2519 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2520 &fname_dir, &fname_mask);
2521 if (!NT_STATUS_IS_OK(status)) {
2526 * We should only check the mangled cache
2527 * here if unix_convert failed. This means
2528 * that the path in 'mask' doesn't exist
2529 * on the file system and so we need to look
2530 * for a possible mangle. This patch from
2531 * Tine Smukavec <valentin.smukavec@hermes.si>.
2534 if (!VALID_STAT(smb_fname->st) &&
2535 mangle_is_mangled(fname_mask, conn->params)) {
2536 char *new_mask = NULL;
2537 mangle_lookup_name_from_8_3(ctx, fname_mask,
2538 &new_mask, conn->params);
2540 TALLOC_FREE(fname_mask);
2541 fname_mask = new_mask;
2548 * Only one file needs to be unlinked. Append the mask back
2549 * onto the directory.
2551 TALLOC_FREE(smb_fname->base_name);
2552 smb_fname->base_name = talloc_asprintf(smb_fname,
2556 if (!smb_fname->base_name) {
2557 status = NT_STATUS_NO_MEMORY;
2561 dirtype = FILE_ATTRIBUTE_NORMAL;
2564 status = check_name(conn, smb_fname->base_name);
2565 if (!NT_STATUS_IS_OK(status)) {
2569 status = do_unlink(conn, req, smb_fname, dirtype);
2570 if (!NT_STATUS_IS_OK(status)) {
2576 struct smb_Dir *dir_hnd = NULL;
2578 const char *dname = NULL;
2579 char *talloced = NULL;
2581 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2582 status = NT_STATUS_OBJECT_NAME_INVALID;
2586 if (strequal(fname_mask,"????????.???")) {
2587 TALLOC_FREE(fname_mask);
2588 fname_mask = talloc_strdup(ctx, "*");
2590 status = NT_STATUS_NO_MEMORY;
2595 status = check_name(conn, fname_dir);
2596 if (!NT_STATUS_IS_OK(status)) {
2600 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2602 if (dir_hnd == NULL) {
2603 status = map_nt_error_from_unix(errno);
2607 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2608 the pattern matches against the long name, otherwise the short name
2609 We don't implement this yet XXXX
2612 status = NT_STATUS_NO_SUCH_FILE;
2614 while ((dname = ReadDirName(dir_hnd, &offset,
2615 &smb_fname->st, &talloced))) {
2616 TALLOC_CTX *frame = talloc_stackframe();
2618 if (!is_visible_file(conn, fname_dir, dname,
2619 &smb_fname->st, true)) {
2621 TALLOC_FREE(talloced);
2625 /* Quick check for "." and ".." */
2626 if (ISDOT(dname) || ISDOTDOT(dname)) {
2628 TALLOC_FREE(talloced);
2632 if(!mask_match(dname, fname_mask,
2633 conn->case_sensitive)) {
2635 TALLOC_FREE(talloced);
2639 TALLOC_FREE(smb_fname->base_name);
2640 smb_fname->base_name =
2641 talloc_asprintf(smb_fname, "%s/%s",
2644 if (!smb_fname->base_name) {
2645 TALLOC_FREE(dir_hnd);
2646 status = NT_STATUS_NO_MEMORY;
2648 TALLOC_FREE(talloced);
2652 status = check_name(conn, smb_fname->base_name);
2653 if (!NT_STATUS_IS_OK(status)) {
2654 TALLOC_FREE(dir_hnd);
2656 TALLOC_FREE(talloced);
2660 status = do_unlink(conn, req, smb_fname, dirtype);
2661 if (!NT_STATUS_IS_OK(status)) {
2663 TALLOC_FREE(talloced);
2668 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2669 smb_fname->base_name));
2672 TALLOC_FREE(talloced);
2674 TALLOC_FREE(dir_hnd);
2677 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2678 status = map_nt_error_from_unix(errno);
2682 TALLOC_FREE(fname_dir);
2683 TALLOC_FREE(fname_mask);
2687 /****************************************************************************
2689 ****************************************************************************/
2691 void reply_unlink(struct smb_request *req)
2693 connection_struct *conn = req->conn;
2695 struct smb_filename *smb_fname = NULL;
2698 bool path_contains_wcard = False;
2699 TALLOC_CTX *ctx = talloc_tos();
2701 START_PROFILE(SMBunlink);
2704 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2708 dirtype = SVAL(req->vwv+0, 0);
2710 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2711 STR_TERMINATE, &status,
2712 &path_contains_wcard);
2713 if (!NT_STATUS_IS_OK(status)) {
2714 reply_nterror(req, status);
2718 status = filename_convert(ctx, conn,
2719 req->flags2 & FLAGS2_DFS_PATHNAMES,
2721 UCF_COND_ALLOW_WCARD_LCOMP,
2722 &path_contains_wcard,
2724 if (!NT_STATUS_IS_OK(status)) {
2725 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2726 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2727 ERRSRV, ERRbadpath);
2730 reply_nterror(req, status);
2734 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2736 status = unlink_internals(conn, req, dirtype, smb_fname,
2737 path_contains_wcard);
2738 if (!NT_STATUS_IS_OK(status)) {
2739 if (open_was_deferred(req->mid)) {
2740 /* We have re-scheduled this call. */
2743 reply_nterror(req, status);
2747 reply_outbuf(req, 0, 0);
2749 TALLOC_FREE(smb_fname);
2750 END_PROFILE(SMBunlink);
2754 /****************************************************************************
2756 ****************************************************************************/
2758 static void fail_readraw(void)
2760 const char *errstr = talloc_asprintf(talloc_tos(),
2761 "FAIL ! reply_readbraw: socket write fail (%s)",
2766 exit_server_cleanly(errstr);
2769 /****************************************************************************
2770 Fake (read/write) sendfile. Returns -1 on read or write fail.
2771 ****************************************************************************/
2773 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2777 size_t tosend = nread;
2784 bufsize = MIN(nread, 65536);
2786 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2790 while (tosend > 0) {
2794 if (tosend > bufsize) {
2799 ret = read_file(fsp,buf,startpos,cur_read);
2805 /* If we had a short read, fill with zeros. */
2806 if (ret < cur_read) {
2807 memset(buf + ret, '\0', cur_read - ret);
2810 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2815 startpos += cur_read;
2819 return (ssize_t)nread;
2822 #if defined(WITH_SENDFILE)
2823 /****************************************************************************
2824 Deal with the case of sendfile reading less bytes from the file than
2825 requested. Fill with zeros (all we can do).
2826 ****************************************************************************/
2828 static void sendfile_short_send(files_struct *fsp,
2833 #define SHORT_SEND_BUFSIZE 1024
2834 if (nread < headersize) {
2835 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2836 "header for file %s (%s). Terminating\n",
2837 fsp_str_dbg(fsp), strerror(errno)));
2838 exit_server_cleanly("sendfile_short_send failed");
2841 nread -= headersize;
2843 if (nread < smb_maxcnt) {
2844 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2846 exit_server_cleanly("sendfile_short_send: "
2850 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2851 "with zeros !\n", fsp_str_dbg(fsp)));
2853 while (nread < smb_maxcnt) {
2855 * We asked for the real file size and told sendfile
2856 * to not go beyond the end of the file. But it can
2857 * happen that in between our fstat call and the
2858 * sendfile call the file was truncated. This is very
2859 * bad because we have already announced the larger
2860 * number of bytes to the client.
2862 * The best we can do now is to send 0-bytes, just as
2863 * a read from a hole in a sparse file would do.
2865 * This should happen rarely enough that I don't care
2866 * about efficiency here :-)
2870 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2871 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2872 exit_server_cleanly("sendfile_short_send: "
2873 "write_data failed");
2880 #endif /* defined WITH_SENDFILE */
2882 /****************************************************************************
2883 Return a readbraw error (4 bytes of zero).
2884 ****************************************************************************/
2886 static void reply_readbraw_error(struct smbd_server_connection *sconn)
2892 smbd_lock_socket(sconn);
2893 if (write_data(smbd_server_fd(),header,4) != 4) {
2896 smbd_unlock_socket(sconn);
2899 /****************************************************************************
2900 Use sendfile in readbraw.
2901 ****************************************************************************/
2903 static void send_file_readbraw(connection_struct *conn,
2904 struct smb_request *req,
2910 struct smbd_server_connection *sconn = req->sconn;
2911 char *outbuf = NULL;
2914 #if defined(WITH_SENDFILE)
2916 * We can only use sendfile on a non-chained packet
2917 * but we can use on a non-oplocked file. tridge proved this
2918 * on a train in Germany :-). JRA.
2919 * reply_readbraw has already checked the length.
2922 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2923 (fsp->wcp == NULL) &&
2924 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
2925 ssize_t sendfile_read = -1;
2927 DATA_BLOB header_blob;
2929 _smb_setlen(header,nread);
2930 header_blob = data_blob_const(header, 4);
2932 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2933 &header_blob, startpos, nread)) == -1) {
2934 /* Returning ENOSYS means no data at all was sent.
2935 * Do this as a normal read. */
2936 if (errno == ENOSYS) {
2937 goto normal_readbraw;
2941 * Special hack for broken Linux with no working sendfile. If we
2942 * return EINTR we sent the header but not the rest of the data.
2943 * Fake this up by doing read/write calls.
2945 if (errno == EINTR) {
2946 /* Ensure we don't do this again. */
2947 set_use_sendfile(SNUM(conn), False);
2948 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2950 if (fake_sendfile(fsp, startpos, nread) == -1) {
2951 DEBUG(0,("send_file_readbraw: "
2952 "fake_sendfile failed for "
2956 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2961 DEBUG(0,("send_file_readbraw: sendfile failed for "
2962 "file %s (%s). Terminating\n",
2963 fsp_str_dbg(fsp), strerror(errno)));
2964 exit_server_cleanly("send_file_readbraw sendfile failed");
2965 } else if (sendfile_read == 0) {
2967 * Some sendfile implementations return 0 to indicate
2968 * that there was a short read, but nothing was
2969 * actually written to the socket. In this case,
2970 * fallback to the normal read path so the header gets
2971 * the correct byte count.
2973 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2974 "bytes falling back to the normal read: "
2975 "%s\n", fsp_str_dbg(fsp)));
2976 goto normal_readbraw;
2979 /* Deal with possible short send. */
2980 if (sendfile_read != 4+nread) {
2981 sendfile_short_send(fsp, sendfile_read, 4, nread);
2989 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2991 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2992 (unsigned)(nread+4)));
2993 reply_readbraw_error(sconn);
2998 ret = read_file(fsp,outbuf+4,startpos,nread);
2999 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3008 _smb_setlen(outbuf,ret);
3009 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
3012 TALLOC_FREE(outbuf);
3015 /****************************************************************************
3016 Reply to a readbraw (core+ protocol).
3017 ****************************************************************************/
3019 void reply_readbraw(struct smb_request *req)
3021 connection_struct *conn = req->conn;
3022 struct smbd_server_connection *sconn = req->sconn;
3023 ssize_t maxcount,mincount;
3027 struct lock_struct lock;
3030 START_PROFILE(SMBreadbraw);
3032 if (srv_is_signing_active(sconn) ||
3033 is_encrypted_packet(req->inbuf)) {
3034 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3035 "raw reads/writes are disallowed.");
3039 reply_readbraw_error(sconn);
3040 END_PROFILE(SMBreadbraw);
3044 if (sconn->smb1.echo_handler.trusted_fde) {
3045 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3046 "'async smb echo handler = yes'\n"));
3047 reply_readbraw_error(sconn);
3048 END_PROFILE(SMBreadbraw);
3053 * Special check if an oplock break has been issued
3054 * and the readraw request croses on the wire, we must
3055 * return a zero length response here.
3058 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3061 * We have to do a check_fsp by hand here, as
3062 * we must always return 4 zero bytes on error,
3066 if (!fsp || !conn || conn != fsp->conn ||
3067 req->vuid != fsp->vuid ||
3068 fsp->is_directory || fsp->fh->fd == -1) {
3070 * fsp could be NULL here so use the value from the packet. JRA.
3072 DEBUG(3,("reply_readbraw: fnum %d not valid "
3074 (int)SVAL(req->vwv+0, 0)));
3075 reply_readbraw_error(sconn);
3076 END_PROFILE(SMBreadbraw);
3080 /* Do a "by hand" version of CHECK_READ. */
3081 if (!(fsp->can_read ||
3082 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3083 (fsp->access_mask & FILE_EXECUTE)))) {
3084 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3085 (int)SVAL(req->vwv+0, 0)));
3086 reply_readbraw_error(sconn);
3087 END_PROFILE(SMBreadbraw);
3091 flush_write_cache(fsp, READRAW_FLUSH);
3093 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3094 if(req->wct == 10) {
3096 * This is a large offset (64 bit) read.
3098 #ifdef LARGE_SMB_OFF_T
3100 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3102 #else /* !LARGE_SMB_OFF_T */
3105 * Ensure we haven't been sent a >32 bit offset.
3108 if(IVAL(req->vwv+8, 0) != 0) {
3109 DEBUG(0,("reply_readbraw: large offset "
3110 "(%x << 32) used and we don't support "
3111 "64 bit offsets.\n",
3112 (unsigned int)IVAL(req->vwv+8, 0) ));
3113 reply_readbraw_error();
3114 END_PROFILE(SMBreadbraw);
3118 #endif /* LARGE_SMB_OFF_T */
3121 DEBUG(0,("reply_readbraw: negative 64 bit "
3122 "readraw offset (%.0f) !\n",
3123 (double)startpos ));
3124 reply_readbraw_error(sconn);
3125 END_PROFILE(SMBreadbraw);
3130 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3131 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3133 /* ensure we don't overrun the packet size */
3134 maxcount = MIN(65535,maxcount);
3136 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3137 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3140 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3141 reply_readbraw_error(sconn);
3142 END_PROFILE(SMBreadbraw);
3146 if (fsp_stat(fsp) == 0) {
3147 size = fsp->fsp_name->st.st_ex_size;
3150 if (startpos >= size) {
3153 nread = MIN(maxcount,(size - startpos));
3156 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3157 if (nread < mincount)
3161 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3162 "min=%lu nread=%lu\n",
3163 fsp->fnum, (double)startpos,
3164 (unsigned long)maxcount,
3165 (unsigned long)mincount,
3166 (unsigned long)nread ) );
3168 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3170 DEBUG(5,("reply_readbraw finished\n"));
3172 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3174 END_PROFILE(SMBreadbraw);
3179 #define DBGC_CLASS DBGC_LOCKING
3181 /****************************************************************************
3182 Reply to a lockread (core+ protocol).
3183 ****************************************************************************/
3185 void reply_lockread(struct smb_request *req)
3187 connection_struct *conn = req->conn;
3194 struct byte_range_lock *br_lck = NULL;
3196 struct smbd_server_connection *sconn = req->sconn;
3198 START_PROFILE(SMBlockread);
3201 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3202 END_PROFILE(SMBlockread);
3206 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3208 if (!check_fsp(conn, req, fsp)) {
3209 END_PROFILE(SMBlockread);
3213 if (!CHECK_READ(fsp,req)) {
3214 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3215 END_PROFILE(SMBlockread);
3219 numtoread = SVAL(req->vwv+1, 0);
3220 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3222 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3224 reply_outbuf(req, 5, numtoread + 3);
3226 data = smb_buf(req->outbuf) + 3;
3229 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3230 * protocol request that predates the read/write lock concept.
3231 * Thus instead of asking for a read lock here we need to ask
3232 * for a write lock. JRA.
3233 * Note that the requested lock size is unaffected by max_recv.
3236 br_lck = do_lock(req->sconn->msg_ctx,
3238 (uint64_t)req->smbpid,
3239 (uint64_t)numtoread,
3243 False, /* Non-blocking lock. */
3247 TALLOC_FREE(br_lck);
3249 if (NT_STATUS_V(status)) {
3250 reply_nterror(req, status);
3251 END_PROFILE(SMBlockread);
3256 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3259 if (numtoread > sconn->smb1.negprot.max_recv) {
3260 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3261 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3262 (unsigned int)numtoread,
3263 (unsigned int)sconn->smb1.negprot.max_recv));
3264 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3266 nread = read_file(fsp,data,startpos,numtoread);
3269 reply_nterror(req, map_nt_error_from_unix(errno));
3270 END_PROFILE(SMBlockread);
3274 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3276 SSVAL(req->outbuf,smb_vwv0,nread);
3277 SSVAL(req->outbuf,smb_vwv5,nread+3);
3278 p = smb_buf(req->outbuf);
3279 SCVAL(p,0,0); /* pad byte. */
3282 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3283 fsp->fnum, (int)numtoread, (int)nread));
3285 END_PROFILE(SMBlockread);
3290 #define DBGC_CLASS DBGC_ALL
3292 /****************************************************************************
3294 ****************************************************************************/
3296 void reply_read(struct smb_request *req)
3298 connection_struct *conn = req->conn;
3305 struct lock_struct lock;
3306 struct smbd_server_connection *sconn = req->sconn;
3308 START_PROFILE(SMBread);
3311 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3312 END_PROFILE(SMBread);
3316 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3318 if (!check_fsp(conn, req, fsp)) {
3319 END_PROFILE(SMBread);
3323 if (!CHECK_READ(fsp,req)) {
3324 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3325 END_PROFILE(SMBread);
3329 numtoread = SVAL(req->vwv+1, 0);
3330 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3332 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3335 * The requested read size cannot be greater than max_recv. JRA.
3337 if (numtoread > sconn->smb1.negprot.max_recv) {
3338 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3339 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3340 (unsigned int)numtoread,
3341 (unsigned int)sconn->smb1.negprot.max_recv));
3342 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3345 reply_outbuf(req, 5, numtoread+3);
3347 data = smb_buf(req->outbuf) + 3;
3349 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3350 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3353 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3354 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3355 END_PROFILE(SMBread);
3360 nread = read_file(fsp,data,startpos,numtoread);
3363 reply_nterror(req, map_nt_error_from_unix(errno));
3367 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3369 SSVAL(req->outbuf,smb_vwv0,nread);
3370 SSVAL(req->outbuf,smb_vwv5,nread+3);
3371 SCVAL(smb_buf(req->outbuf),0,1);
3372 SSVAL(smb_buf(req->outbuf),1,nread);
3374 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3375 fsp->fnum, (int)numtoread, (int)nread ) );
3378 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3380 END_PROFILE(SMBread);
3384 /****************************************************************************
3386 ****************************************************************************/
3388 static int setup_readX_header(struct smb_request *req, char *outbuf,
3394 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3395 data = smb_buf(outbuf);
3397 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3399 SCVAL(outbuf,smb_vwv0,0xFF);
3400 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3401 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3402 SSVAL(outbuf,smb_vwv6,
3404 + 1 /* the wct field */
3405 + 12 * sizeof(uint16_t) /* vwv */
3406 + 2); /* the buflen field */
3407 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3408 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3409 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3410 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3414 /****************************************************************************
3415 Reply to a read and X - possibly using sendfile.
3416 ****************************************************************************/
3418 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3419 files_struct *fsp, SMB_OFF_T startpos,
3423 struct lock_struct lock;
3424 int saved_errno = 0;
3426 if(fsp_stat(fsp) == -1) {
3427 reply_nterror(req, map_nt_error_from_unix(errno));
3431 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3432 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3435 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3436 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3440 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3441 (startpos > fsp->fsp_name->st.st_ex_size)
3442 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3444 * We already know that we would do a short read, so don't
3445 * try the sendfile() path.
3447 goto nosendfile_read;
3450 #if defined(WITH_SENDFILE)
3452 * We can only use sendfile on a non-chained packet
3453 * but we can use on a non-oplocked file. tridge proved this
3454 * on a train in Germany :-). JRA.
3457 if (!req_is_in_chain(req) &&
3458 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3459 (fsp->wcp == NULL) &&
3460 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3461 uint8 headerbuf[smb_size + 12 * 2];
3465 * Set up the packet header before send. We
3466 * assume here the sendfile will work (get the
3467 * correct amount of data).
3470 header = data_blob_const(headerbuf, sizeof(headerbuf));
3472 construct_reply_common_req(req, (char *)headerbuf);
3473 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3475 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3476 /* Returning ENOSYS means no data at all was sent.
3477 Do this as a normal read. */
3478 if (errno == ENOSYS) {
3483 * Special hack for broken Linux with no working sendfile. If we
3484 * return EINTR we sent the header but not the rest of the data.
3485 * Fake this up by doing read/write calls.
3488 if (errno == EINTR) {
3489 /* Ensure we don't do this again. */
3490 set_use_sendfile(SNUM(conn), False);
3491 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3492 nread = fake_sendfile(fsp, startpos,
3495 DEBUG(0,("send_file_readX: "
3496 "fake_sendfile failed for "
3500 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3502 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3503 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3504 /* No outbuf here means successful sendfile. */
3508 DEBUG(0,("send_file_readX: sendfile failed for file "
3509 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3511 exit_server_cleanly("send_file_readX sendfile failed");
3512 } else if (nread == 0) {
3514 * Some sendfile implementations return 0 to indicate
3515 * that there was a short read, but nothing was
3516 * actually written to the socket. In this case,
3517 * fallback to the normal read path so the header gets
3518 * the correct byte count.
3520 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3521 "falling back to the normal read: %s\n",
3526 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3527 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3529 /* Deal with possible short send. */
3530 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3531 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3533 /* No outbuf here means successful sendfile. */
3534 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3535 SMB_PERFCOUNT_END(&req->pcd);
3543 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3544 uint8 headerbuf[smb_size + 2*12];
3546 construct_reply_common_req(req, (char *)headerbuf);
3547 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3549 /* Send out the header. */
3550 if (write_data(smbd_server_fd(), (char *)headerbuf,
3551 sizeof(headerbuf)) != sizeof(headerbuf)) {
3552 DEBUG(0,("send_file_readX: write_data failed for file "
3553 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3555 exit_server_cleanly("send_file_readX sendfile failed");
3557 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3559 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3560 "file %s (%s).\n", fsp_str_dbg(fsp),
3562 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3569 reply_outbuf(req, 12, smb_maxcnt);
3571 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3572 saved_errno = errno;
3574 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3577 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3581 setup_readX_header(req, (char *)req->outbuf, nread);
3583 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3584 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3590 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3591 TALLOC_FREE(req->outbuf);
3595 /****************************************************************************
3596 Reply to a read and X.
3597 ****************************************************************************/
3599 void reply_read_and_X(struct smb_request *req)
3601 connection_struct *conn = req->conn;
3605 bool big_readX = False;
3607 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3610 START_PROFILE(SMBreadX);
3612 if ((req->wct != 10) && (req->wct != 12)) {
3613 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3617 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3618 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3619 smb_maxcnt = SVAL(req->vwv+5, 0);
3621 /* If it's an IPC, pass off the pipe handler. */
3623 reply_pipe_read_and_X(req);
3624 END_PROFILE(SMBreadX);
3628 if (!check_fsp(conn, req, fsp)) {
3629 END_PROFILE(SMBreadX);
3633 if (!CHECK_READ(fsp,req)) {
3634 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3635 END_PROFILE(SMBreadX);
3639 if (global_client_caps & CAP_LARGE_READX) {
3640 size_t upper_size = SVAL(req->vwv+7, 0);
3641 smb_maxcnt |= (upper_size<<16);
3642 if (upper_size > 1) {
3643 /* Can't do this on a chained packet. */
3644 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3645 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3646 END_PROFILE(SMBreadX);
3649 /* We currently don't do this on signed or sealed data. */
3650 if (srv_is_signing_active(req->sconn) ||
3651 is_encrypted_packet(req->inbuf)) {
3652 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3653 END_PROFILE(SMBreadX);
3656 /* Is there room in the reply for this data ? */
3657 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3659 NT_STATUS_INVALID_PARAMETER);
3660 END_PROFILE(SMBreadX);
3667 if (req->wct == 12) {
3668 #ifdef LARGE_SMB_OFF_T
3670 * This is a large offset (64 bit) read.
3672 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3674 #else /* !LARGE_SMB_OFF_T */
3677 * Ensure we haven't been sent a >32 bit offset.
3680 if(IVAL(req->vwv+10, 0) != 0) {
3681 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3682 "used and we don't support 64 bit offsets.\n",
3683 (unsigned int)IVAL(req->vwv+10, 0) ));
3684 END_PROFILE(SMBreadX);
3685 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3689 #endif /* LARGE_SMB_OFF_T */
3694 NTSTATUS status = schedule_aio_read_and_X(conn,
3699 if (NT_STATUS_IS_OK(status)) {
3700 /* Read scheduled - we're done. */
3703 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3704 /* Real error - report to client. */
3705 END_PROFILE(SMBreadX);
3706 reply_nterror(req, status);
3709 /* NT_STATUS_RETRY - fall back to sync read. */
3712 smbd_lock_socket(req->sconn);
3713 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3714 smbd_unlock_socket(req->sconn);
3717 END_PROFILE(SMBreadX);
3721 /****************************************************************************
3722 Error replies to writebraw must have smb_wct == 1. Fix this up.
3723 ****************************************************************************/
3725 void error_to_writebrawerr(struct smb_request *req)
3727 uint8 *old_outbuf = req->outbuf;
3729 reply_outbuf(req, 1, 0);
3731 memcpy(req->outbuf, old_outbuf, smb_size);
3732 TALLOC_FREE(old_outbuf);
3735 /****************************************************************************
3736 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3737 ****************************************************************************/
3739 void reply_writebraw(struct smb_request *req)
3741 connection_struct *conn = req->conn;
3744 ssize_t total_written=0;
3745 size_t numtowrite=0;
3751 struct lock_struct lock;
3754 START_PROFILE(SMBwritebraw);
3757 * If we ever reply with an error, it must have the SMB command
3758 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3761 SCVAL(req->inbuf,smb_com,SMBwritec);
3763 if (srv_is_signing_active(req->sconn)) {
3764 END_PROFILE(SMBwritebraw);
3765 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3766 "raw reads/writes are disallowed.");
3769 if (req->wct < 12) {
3770 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3771 error_to_writebrawerr(req);
3772 END_PROFILE(SMBwritebraw);
3776 if (req->sconn->smb1.echo_handler.trusted_fde) {
3777 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3778 "'async smb echo handler = yes'\n"));
3779 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3780 error_to_writebrawerr(req);
3781 END_PROFILE(SMBwritebraw);
3785 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3786 if (!check_fsp(conn, req, fsp)) {
3787 error_to_writebrawerr(req);
3788 END_PROFILE(SMBwritebraw);
3792 if (!CHECK_WRITE(fsp)) {
3793 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3794 error_to_writebrawerr(req);
3795 END_PROFILE(SMBwritebraw);
3799 tcount = IVAL(req->vwv+1, 0);
3800 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3801 write_through = BITSETW(req->vwv+7,0);
3803 /* We have to deal with slightly different formats depending
3804 on whether we are using the core+ or lanman1.0 protocol */
3806 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3807 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3808 data = smb_buf(req->inbuf);
3810 numtowrite = SVAL(req->vwv+10, 0);
3811 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3814 /* Ensure we don't write bytes past the end of this packet. */
3815 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3816 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3817 error_to_writebrawerr(req);
3818 END_PROFILE(SMBwritebraw);
3822 if (!fsp->print_file) {
3823 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3824 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3827 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3828 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3829 error_to_writebrawerr(req);
3830 END_PROFILE(SMBwritebraw);
3836 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3839 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3840 "wrote=%d sync=%d\n",
3841 fsp->fnum, (double)startpos, (int)numtowrite,
3842 (int)nwritten, (int)write_through));
3844 if (nwritten < (ssize_t)numtowrite) {
3845 reply_nterror(req, NT_STATUS_DISK_FULL);
3846 error_to_writebrawerr(req);
3850 total_written = nwritten;
3852 /* Allocate a buffer of 64k + length. */
3853 buf = TALLOC_ARRAY(NULL, char, 65540);
3855 reply_nterror(req, NT_STATUS_NO_MEMORY);
3856 error_to_writebrawerr(req);
3860 /* Return a SMBwritebraw message to the redirector to tell
3861 * it to send more bytes */
3863 memcpy(buf, req->inbuf, smb_size);
3864 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
3865 SCVAL(buf,smb_com,SMBwritebraw);
3866 SSVALS(buf,smb_vwv0,0xFFFF);
3868 if (!srv_send_smb(smbd_server_fd(),
3870 false, 0, /* no signing */
3871 IS_CONN_ENCRYPTED(conn),
3873 exit_server_cleanly("reply_writebraw: srv_send_smb "
3877 /* Now read the raw data into the buffer and write it */
3878 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3880 if (!NT_STATUS_IS_OK(status)) {
3881 exit_server_cleanly("secondary writebraw failed");
3884 /* Set up outbuf to return the correct size */
3885 reply_outbuf(req, 1, 0);
3887 if (numtowrite != 0) {
3889 if (numtowrite > 0xFFFF) {
3890 DEBUG(0,("reply_writebraw: Oversize secondary write "
3891 "raw requested (%u). Terminating\n",
3892 (unsigned int)numtowrite ));
3893 exit_server_cleanly("secondary writebraw failed");
3896 if (tcount > nwritten+numtowrite) {
3897 DEBUG(3,("reply_writebraw: Client overestimated the "
3899 (int)tcount,(int)nwritten,(int)numtowrite));
3902 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3904 if (!NT_STATUS_IS_OK(status)) {
3905 DEBUG(0,("reply_writebraw: Oversize secondary write "
3906 "raw read failed (%s). Terminating\n",
3907 nt_errstr(status)));
3908 exit_server_cleanly("secondary writebraw failed");
3911 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3912 if (nwritten == -1) {
3914 reply_nterror(req, map_nt_error_from_unix(errno));
3915 error_to_writebrawerr(req);
3919 if (nwritten < (ssize_t)numtowrite) {
3920 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3921 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3925 total_written += nwritten;
3930 SSVAL(req->outbuf,smb_vwv0,total_written);
3932 status = sync_file(conn, fsp, write_through);
3933 if (!NT_STATUS_IS_OK(status)) {
3934 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3935 fsp_str_dbg(fsp), nt_errstr(status)));
3936 reply_nterror(req, status);
3937 error_to_writebrawerr(req);
3941 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3943 fsp->fnum, (double)startpos, (int)numtowrite,
3944 (int)total_written));
3946 if (!fsp->print_file) {
3947 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3950 /* We won't return a status if write through is not selected - this
3951 * follows what WfWg does */
3952 END_PROFILE(SMBwritebraw);
3954 if (!write_through && total_written==tcount) {
3956 #if RABBIT_PELLET_FIX
3958 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3959 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3962 if (!send_keepalive(smbd_server_fd())) {
3963 exit_server_cleanly("reply_writebraw: send of "
3964 "keepalive failed");
3967 TALLOC_FREE(req->outbuf);
3972 if (!fsp->print_file) {
3973 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3976 END_PROFILE(SMBwritebraw);
3981 #define DBGC_CLASS DBGC_LOCKING
3983 /****************************************************************************
3984 Reply to a writeunlock (core+).
3985 ****************************************************************************/
3987 void reply_writeunlock(struct smb_request *req)
3989 connection_struct *conn = req->conn;
3990 ssize_t nwritten = -1;
3994 NTSTATUS status = NT_STATUS_OK;
3996 struct lock_struct lock;
3997 int saved_errno = 0;
3999 START_PROFILE(SMBwriteunlock);
4002 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4003 END_PROFILE(SMBwriteunlock);
4007 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4009 if (!check_fsp(conn, req, fsp)) {
4010 END_PROFILE(SMBwriteunlock);
4014 if (!CHECK_WRITE(fsp)) {
4015 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4016 END_PROFILE(SMBwriteunlock);
4020 numtowrite = SVAL(req->vwv+1, 0);
4021 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4022 data = (const char *)req->buf + 3;
4024 if (!fsp->print_file && numtowrite > 0) {
4025 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4026 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4029 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4030 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4031 END_PROFILE(SMBwriteunlock);
4036 /* The special X/Open SMB protocol handling of
4037 zero length writes is *NOT* done for
4039 if(numtowrite == 0) {
4042 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4043 saved_errno = errno;
4046 status = sync_file(conn, fsp, False /* write through */);
4047 if (!NT_STATUS_IS_OK(status)) {
4048 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4049 fsp_str_dbg(fsp), nt_errstr(status)));
4050 reply_nterror(req, status);
4055 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4059 if((nwritten < numtowrite) && (numtowrite != 0)) {
4060 reply_nterror(req, NT_STATUS_DISK_FULL);
4064 if (numtowrite && !fsp->print_file) {
4065 status = do_unlock(req->sconn->msg_ctx,
4067 (uint64_t)req->smbpid,
4068 (uint64_t)numtowrite,
4072 if (NT_STATUS_V(status)) {
4073 reply_nterror(req, status);
4078 reply_outbuf(req, 1, 0);
4080 SSVAL(req->outbuf,smb_vwv0,nwritten);
4082 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4083 fsp->fnum, (int)numtowrite, (int)nwritten));
4086 if (numtowrite && !fsp->print_file) {
4087 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4090 END_PROFILE(SMBwriteunlock);
4095 #define DBGC_CLASS DBGC_ALL
4097 /****************************************************************************
4099 ****************************************************************************/
4101 void reply_write(struct smb_request *req)
4103 connection_struct *conn = req->conn;
4105 ssize_t nwritten = -1;
4109 struct lock_struct lock;
4111 int saved_errno = 0;
4113 START_PROFILE(SMBwrite);
4116 END_PROFILE(SMBwrite);
4117 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4121 /* If it's an IPC, pass off the pipe handler. */
4123 reply_pipe_write(req);
4124 END_PROFILE(SMBwrite);
4128 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4130 if (!check_fsp(conn, req, fsp)) {
4131 END_PROFILE(SMBwrite);
4135 if (!CHECK_WRITE(fsp)) {
4136 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4137 END_PROFILE(SMBwrite);
4141 numtowrite = SVAL(req->vwv+1, 0);
4142 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4143 data = (const char *)req->buf + 3;
4145 if (!fsp->print_file) {
4146 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4147 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4150 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4151 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4152 END_PROFILE(SMBwrite);
4158 * X/Open SMB protocol says that if smb_vwv1 is
4159 * zero then the file size should be extended or
4160 * truncated to the size given in smb_vwv[2-3].
4163 if(numtowrite == 0) {
4165 * This is actually an allocate call, and set EOF. JRA.
4167 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4169 reply_nterror(req, NT_STATUS_DISK_FULL);
4172 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4174 reply_nterror(req, NT_STATUS_DISK_FULL);
4177 trigger_write_time_update_immediate(fsp);
4179 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4182 status = sync_file(conn, fsp, False);
4183 if (!NT_STATUS_IS_OK(status)) {
4184 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4185 fsp_str_dbg(fsp), nt_errstr(status)));
4186 reply_nterror(req, status);
4191 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4195 if((nwritten == 0) && (numtowrite != 0)) {
4196 reply_nterror(req, NT_STATUS_DISK_FULL);
4200 reply_outbuf(req, 1, 0);
4202 SSVAL(req->outbuf,smb_vwv0,nwritten);
4204 if (nwritten < (ssize_t)numtowrite) {
4205 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4206 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4209 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4212 if (!fsp->print_file) {
4213 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4216 END_PROFILE(SMBwrite);
4220 /****************************************************************************
4221 Ensure a buffer is a valid writeX for recvfile purposes.
4222 ****************************************************************************/
4224 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4225 (2*14) + /* word count (including bcc) */ \
4228 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4229 const uint8_t *inbuf)
4232 connection_struct *conn = NULL;
4233 unsigned int doff = 0;
4234 size_t len = smb_len_large(inbuf);
4236 if (is_encrypted_packet(inbuf)) {
4237 /* Can't do this on encrypted
4242 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4246 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4247 CVAL(inbuf,smb_wct) != 14) {
4248 DEBUG(10,("is_valid_writeX_buffer: chained or "
4249 "invalid word length.\n"));
4253 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4255 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4259 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4262 if (IS_PRINT(conn)) {
4263 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4266 doff = SVAL(inbuf,smb_vwv11);
4268 numtowrite = SVAL(inbuf,smb_vwv10);
4270 if (len > doff && len - doff > 0xFFFF) {
4271 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4274 if (numtowrite == 0) {
4275 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4279 /* Ensure the sizes match up. */
4280 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4281 /* no pad byte...old smbclient :-( */
4282 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4284 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4288 if (len - doff != numtowrite) {
4289 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4290 "len = %u, doff = %u, numtowrite = %u\n",
4293 (unsigned int)numtowrite ));
4297 DEBUG(10,("is_valid_writeX_buffer: true "
4298 "len = %u, doff = %u, numtowrite = %u\n",
4301 (unsigned int)numtowrite ));
4306 /****************************************************************************
4307 Reply to a write and X.
4308 ****************************************************************************/
4310 void reply_write_and_X(struct smb_request *req)
4312 connection_struct *conn = req->conn;
4314 struct lock_struct lock;
4319 unsigned int smb_doff;
4320 unsigned int smblen;
4323 int saved_errno = 0;
4325 START_PROFILE(SMBwriteX);
4327 if ((req->wct != 12) && (req->wct != 14)) {
4328 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4329 END_PROFILE(SMBwriteX);
4333 numtowrite = SVAL(req->vwv+10, 0);
4334 smb_doff = SVAL(req->vwv+11, 0);
4335 smblen = smb_len(req->inbuf);
4337 if (req->unread_bytes > 0xFFFF ||
4338 (smblen > smb_doff &&
4339 smblen - smb_doff > 0xFFFF)) {
4340 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4343 if (req->unread_bytes) {
4344 /* Can't do a recvfile write on IPC$ */
4346 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4347 END_PROFILE(SMBwriteX);
4350 if (numtowrite != req->unread_bytes) {
4351 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4352 END_PROFILE(SMBwriteX);
4356 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4357 smb_doff + numtowrite > smblen) {
4358 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4359 END_PROFILE(SMBwriteX);
4364 /* If it's an IPC, pass off the pipe handler. */
4366 if (req->unread_bytes) {
4367 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4368 END_PROFILE(SMBwriteX);
4371 reply_pipe_write_and_X(req);
4372 END_PROFILE(SMBwriteX);
4376 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4377 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4378 write_through = BITSETW(req->vwv+7,0);
4380 if (!check_fsp(conn, req, fsp)) {
4381 END_PROFILE(SMBwriteX);
4385 if (!CHECK_WRITE(fsp)) {
4386 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4387 END_PROFILE(SMBwriteX);
4391 data = smb_base(req->inbuf) + smb_doff;
4393 if(req->wct == 14) {
4394 #ifdef LARGE_SMB_OFF_T
4396 * This is a large offset (64 bit) write.
4398 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4400 #else /* !LARGE_SMB_OFF_T */
4403 * Ensure we haven't been sent a >32 bit offset.
4406 if(IVAL(req->vwv+12, 0) != 0) {
4407 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4408 "used and we don't support 64 bit offsets.\n",
4409 (unsigned int)IVAL(req->vwv+12, 0) ));
4410 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4411 END_PROFILE(SMBwriteX);
4415 #endif /* LARGE_SMB_OFF_T */
4418 /* X/Open SMB protocol says that, unlike SMBwrite
4419 if the length is zero then NO truncation is
4420 done, just a write of zero. To truncate a file,
4423 if(numtowrite == 0) {
4426 if (req->unread_bytes == 0) {
4427 status = schedule_aio_write_and_X(conn,
4434 if (NT_STATUS_IS_OK(status)) {
4435 /* write scheduled - we're done. */
4438 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4439 /* Real error - report to client. */
4440 reply_nterror(req, status);
4443 /* NT_STATUS_RETRY - fall through to sync write. */
4446 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4447 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4450 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4451 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4455 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4456 saved_errno = errno;
4458 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4462 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4466 if((nwritten == 0) && (numtowrite != 0)) {
4467 reply_nterror(req, NT_STATUS_DISK_FULL);
4471 reply_outbuf(req, 6, 0);
4472 SSVAL(req->outbuf,smb_vwv2,nwritten);
4473 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4475 if (nwritten < (ssize_t)numtowrite) {
4476 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4477 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4480 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4481 fsp->fnum, (int)numtowrite, (int)nwritten));
4483 status = sync_file(conn, fsp, write_through);
4484 if (!NT_STATUS_IS_OK(status)) {
4485 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4486 fsp_str_dbg(fsp), nt_errstr(status)));
4487 reply_nterror(req, status);
4491 END_PROFILE(SMBwriteX);
4496 END_PROFILE(SMBwriteX);
4500 /****************************************************************************
4502 ****************************************************************************/
4504 void reply_lseek(struct smb_request *req)
4506 connection_struct *conn = req->conn;
4512 START_PROFILE(SMBlseek);
4515 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4516 END_PROFILE(SMBlseek);
4520 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4522 if (!check_fsp(conn, req, fsp)) {
4526 flush_write_cache(fsp, SEEK_FLUSH);
4528 mode = SVAL(req->vwv+1, 0) & 3;
4529 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4530 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4539 res = fsp->fh->pos + startpos;
4550 if (umode == SEEK_END) {
4551 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4552 if(errno == EINVAL) {
4553 SMB_OFF_T current_pos = startpos;
4555 if(fsp_stat(fsp) == -1) {
4557 map_nt_error_from_unix(errno));
4558 END_PROFILE(SMBlseek);
4562 current_pos += fsp->fsp_name->st.st_ex_size;
4564 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4569 reply_nterror(req, map_nt_error_from_unix(errno));
4570 END_PROFILE(SMBlseek);
4577 reply_outbuf(req, 2, 0);
4578 SIVAL(req->outbuf,smb_vwv0,res);
4580 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4581 fsp->fnum, (double)startpos, (double)res, mode));
4583 END_PROFILE(SMBlseek);
4587 /****************************************************************************
4589 ****************************************************************************/
4591 void reply_flush(struct smb_request *req)
4593 connection_struct *conn = req->conn;
4597 START_PROFILE(SMBflush);
4600 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4604 fnum = SVAL(req->vwv+0, 0);
4605 fsp = file_fsp(req, fnum);
4607 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4612 file_sync_all(conn);
4614 NTSTATUS status = sync_file(conn, fsp, True);
4615 if (!NT_STATUS_IS_OK(status)) {
4616 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4617 fsp_str_dbg(fsp), nt_errstr(status)));
4618 reply_nterror(req, status);
4619 END_PROFILE(SMBflush);
4624 reply_outbuf(req, 0, 0);
4626 DEBUG(3,("flush\n"));
4627 END_PROFILE(SMBflush);
4631 /****************************************************************************
4633 conn POINTER CAN BE NULL HERE !
4634 ****************************************************************************/
4636 void reply_exit(struct smb_request *req)
4638 START_PROFILE(SMBexit);
4640 file_close_pid(req->smbpid, req->vuid);
4642 reply_outbuf(req, 0, 0);
4644 DEBUG(3,("exit\n"));
4646 END_PROFILE(SMBexit);
4650 /****************************************************************************
4651 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4652 ****************************************************************************/
4654 void reply_close(struct smb_request *req)
4656 connection_struct *conn = req->conn;
4657 NTSTATUS status = NT_STATUS_OK;
4658 files_struct *fsp = NULL;
4659 START_PROFILE(SMBclose);
4662 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4663 END_PROFILE(SMBclose);
4667 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4670 * We can only use check_fsp if we know it's not a directory.
4673 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4674 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4675 END_PROFILE(SMBclose);
4679 if(fsp->is_directory) {
4681 * Special case - close NT SMB directory handle.
4683 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4684 status = close_file(req, fsp, NORMAL_CLOSE);
4688 * Close ordinary file.
4691 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4692 fsp->fh->fd, fsp->fnum,
4693 conn->num_files_open));
4696 * Take care of any time sent in the close.
4699 t = srv_make_unix_date3(req->vwv+1);
4700 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4703 * close_file() returns the unix errno if an error
4704 * was detected on close - normally this is due to
4705 * a disk full error. If not then it was probably an I/O error.
4708 status = close_file(req, fsp, NORMAL_CLOSE);
4711 if (!NT_STATUS_IS_OK(status)) {
4712 reply_nterror(req, status);
4713 END_PROFILE(SMBclose);
4717 reply_outbuf(req, 0, 0);
4718 END_PROFILE(SMBclose);
4722 /****************************************************************************
4723 Reply to a writeclose (Core+ protocol).
4724 ****************************************************************************/
4726 void reply_writeclose(struct smb_request *req)
4728 connection_struct *conn = req->conn;
4730 ssize_t nwritten = -1;
4731 NTSTATUS close_status = NT_STATUS_OK;
4734 struct timespec mtime;
4736 struct lock_struct lock;
4738 START_PROFILE(SMBwriteclose);
4741 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4742 END_PROFILE(SMBwriteclose);
4746 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4748 if (!check_fsp(conn, req, fsp)) {
4749 END_PROFILE(SMBwriteclose);
4752 if (!CHECK_WRITE(fsp)) {
4753 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4754 END_PROFILE(SMBwriteclose);
4758 numtowrite = SVAL(req->vwv+1, 0);
4759 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4760 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4761 data = (const char *)req->buf + 1;
4763 if (!fsp->print_file) {
4764 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4765 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4768 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4769 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4770 END_PROFILE(SMBwriteclose);
4775 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4777 set_close_write_time(fsp, mtime);
4780 * More insanity. W2K only closes the file if writelen > 0.
4785 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4786 "file %s\n", fsp_str_dbg(fsp)));
4787 close_status = close_file(req, fsp, NORMAL_CLOSE);
4790 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4791 fsp->fnum, (int)numtowrite, (int)nwritten,
4792 conn->num_files_open));
4794 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4795 reply_nterror(req, NT_STATUS_DISK_FULL);
4799 if(!NT_STATUS_IS_OK(close_status)) {
4800 reply_nterror(req, close_status);
4804 reply_outbuf(req, 1, 0);
4806 SSVAL(req->outbuf,smb_vwv0,nwritten);
4809 if (numtowrite && !fsp->print_file) {
4810 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4813 END_PROFILE(SMBwriteclose);
4818 #define DBGC_CLASS DBGC_LOCKING
4820 /****************************************************************************
4822 ****************************************************************************/
4824 void reply_lock(struct smb_request *req)
4826 connection_struct *conn = req->conn;
4827 uint64_t count,offset;
4830 struct byte_range_lock *br_lck = NULL;
4832 START_PROFILE(SMBlock);
4835 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4836 END_PROFILE(SMBlock);
4840 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4842 if (!check_fsp(conn, req, fsp)) {
4843 END_PROFILE(SMBlock);
4847 count = (uint64_t)IVAL(req->vwv+1, 0);
4848 offset = (uint64_t)IVAL(req->vwv+3, 0);
4850 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4851 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4853 br_lck = do_lock(req->sconn->msg_ctx,
4855 (uint64_t)req->smbpid,
4860 False, /* Non-blocking lock. */
4865 TALLOC_FREE(br_lck);
4867 if (NT_STATUS_V(status)) {
4868 reply_nterror(req, status);
4869 END_PROFILE(SMBlock);
4873 reply_outbuf(req, 0, 0);
4875 END_PROFILE(SMBlock);
4879 /****************************************************************************
4881 ****************************************************************************/
4883 void reply_unlock(struct smb_request *req)
4885 connection_struct *conn = req->conn;
4886 uint64_t count,offset;
4890 START_PROFILE(SMBunlock);
4893 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4894 END_PROFILE(SMBunlock);
4898 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4900 if (!check_fsp(conn, req, fsp)) {
4901 END_PROFILE(SMBunlock);
4905 count = (uint64_t)IVAL(req->vwv+1, 0);
4906 offset = (uint64_t)IVAL(req->vwv+3, 0);
4908 status = do_unlock(req->sconn->msg_ctx,
4910 (uint64_t)req->smbpid,
4915 if (NT_STATUS_V(status)) {
4916 reply_nterror(req, status);
4917 END_PROFILE(SMBunlock);
4921 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4922 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4924 reply_outbuf(req, 0, 0);
4926 END_PROFILE(SMBunlock);
4931 #define DBGC_CLASS DBGC_ALL
4933 /****************************************************************************
4935 conn POINTER CAN BE NULL HERE !
4936 ****************************************************************************/
4938 void reply_tdis(struct smb_request *req)
4940 connection_struct *conn = req->conn;
4941 START_PROFILE(SMBtdis);
4944 DEBUG(4,("Invalid connection in tdis\n"));
4945 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
4946 END_PROFILE(SMBtdis);
4952 close_cnum(conn,req->vuid);
4955 reply_outbuf(req, 0, 0);
4956 END_PROFILE(SMBtdis);
4960 /****************************************************************************
4962 conn POINTER CAN BE NULL HERE !
4963 ****************************************************************************/
4965 void reply_echo(struct smb_request *req)
4967 connection_struct *conn = req->conn;
4968 struct smb_perfcount_data local_pcd;
4969 struct smb_perfcount_data *cur_pcd;
4973 START_PROFILE(SMBecho);
4975 smb_init_perfcount_data(&local_pcd);
4978 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4979 END_PROFILE(SMBecho);
4983 smb_reverb = SVAL(req->vwv+0, 0);
4985 reply_outbuf(req, 1, req->buflen);
4987 /* copy any incoming data back out */
4988 if (req->buflen > 0) {
4989 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4992 if (smb_reverb > 100) {
4993 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4997 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
4999 /* this makes sure we catch the request pcd */
5000 if (seq_num == smb_reverb) {
5001 cur_pcd = &req->pcd;
5003 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5004 cur_pcd = &local_pcd;
5007 SSVAL(req->outbuf,smb_vwv0,seq_num);
5009 show_msg((char *)req->outbuf);
5010 if (!srv_send_smb(smbd_server_fd(),
5011 (char *)req->outbuf,
5012 true, req->seqnum+1,
5013 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5015 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5018 DEBUG(3,("echo %d times\n", smb_reverb));
5020 TALLOC_FREE(req->outbuf);
5022 END_PROFILE(SMBecho);
5026 /****************************************************************************
5027 Reply to a printopen.
5028 ****************************************************************************/
5030 void reply_printopen(struct smb_request *req)
5032 connection_struct *conn = req->conn;
5036 START_PROFILE(SMBsplopen);
5039 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5040 END_PROFILE(SMBsplopen);
5044 if (!CAN_PRINT(conn)) {
5045 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5046 END_PROFILE(SMBsplopen);
5050 status = file_new(req, conn, &fsp);
5051 if(!NT_STATUS_IS_OK(status)) {
5052 reply_nterror(req, status);
5053 END_PROFILE(SMBsplopen);
5057 /* Open for exclusive use, write only. */
5058 status = print_spool_open(fsp, NULL, req->vuid);
5060 if (!NT_STATUS_IS_OK(status)) {
5061 file_free(req, fsp);
5062 reply_nterror(req, status);
5063 END_PROFILE(SMBsplopen);
5067 reply_outbuf(req, 1, 0);
5068 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5070 DEBUG(3,("openprint fd=%d fnum=%d\n",
5071 fsp->fh->fd, fsp->fnum));
5073 END_PROFILE(SMBsplopen);
5077 /****************************************************************************
5078 Reply to a printclose.
5079 ****************************************************************************/
5081 void reply_printclose(struct smb_request *req)
5083 connection_struct *conn = req->conn;
5087 START_PROFILE(SMBsplclose);
5090 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5091 END_PROFILE(SMBsplclose);
5095 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5097 if (!check_fsp(conn, req, fsp)) {
5098 END_PROFILE(SMBsplclose);
5102 if (!CAN_PRINT(conn)) {
5103 reply_force_doserror(req, ERRSRV, ERRerror);
5104 END_PROFILE(SMBsplclose);
5108 DEBUG(3,("printclose fd=%d fnum=%d\n",
5109 fsp->fh->fd,fsp->fnum));
5111 status = close_file(req, fsp, NORMAL_CLOSE);
5113 if(!NT_STATUS_IS_OK(status)) {
5114 reply_nterror(req, status);
5115 END_PROFILE(SMBsplclose);
5119 reply_outbuf(req, 0, 0);
5121 END_PROFILE(SMBsplclose);
5125 /****************************************************************************
5126 Reply to a printqueue.
5127 ****************************************************************************/
5129 void reply_printqueue(struct smb_request *req)
5131 connection_struct *conn = req->conn;
5135 START_PROFILE(SMBsplretq);
5138 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5139 END_PROFILE(SMBsplretq);
5143 max_count = SVAL(req->vwv+0, 0);
5144 start_index = SVAL(req->vwv+1, 0);
5146 /* we used to allow the client to get the cnum wrong, but that
5147 is really quite gross and only worked when there was only
5148 one printer - I think we should now only accept it if they
5149 get it right (tridge) */
5150 if (!CAN_PRINT(conn)) {
5151 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5152 END_PROFILE(SMBsplretq);
5156 reply_outbuf(req, 2, 3);
5157 SSVAL(req->outbuf,smb_vwv0,0);
5158 SSVAL(req->outbuf,smb_vwv1,0);
5159 SCVAL(smb_buf(req->outbuf),0,1);
5160 SSVAL(smb_buf(req->outbuf),1,0);
5162 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5163 start_index, max_count));
5166 print_queue_struct *queue = NULL;
5167 print_status_struct status;
5168 int count = print_queue_status(SNUM(conn), &queue, &status);
5169 int num_to_get = ABS(max_count);
5170 int first = (max_count>0?start_index:start_index+max_count+1);
5176 num_to_get = MIN(num_to_get,count-first);
5179 for (i=first;i<first+num_to_get;i++) {
5183 srv_put_dos_date2(p,0,queue[i].time);
5184 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
5185 SSVAL(p,5, queue[i].job);
5186 SIVAL(p,7,queue[i].size);
5188 srvstr_push(blob, req->flags2, p+12,
5189 queue[i].fs_user, 16, STR_ASCII);
5191 if (message_push_blob(
5194 blob, sizeof(blob))) == -1) {
5195 reply_nterror(req, NT_STATUS_NO_MEMORY);
5196 END_PROFILE(SMBsplretq);
5202 SSVAL(req->outbuf,smb_vwv0,count);
5203 SSVAL(req->outbuf,smb_vwv1,
5204 (max_count>0?first+count:first-1));
5205 SCVAL(smb_buf(req->outbuf),0,1);
5206 SSVAL(smb_buf(req->outbuf),1,28*count);
5211 DEBUG(3,("%d entries returned in queue\n",count));
5214 END_PROFILE(SMBsplretq);
5218 /****************************************************************************
5219 Reply to a printwrite.
5220 ****************************************************************************/
5222 void reply_printwrite(struct smb_request *req)
5224 connection_struct *conn = req->conn;
5229 START_PROFILE(SMBsplwr);
5232 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5233 END_PROFILE(SMBsplwr);
5237 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5239 if (!check_fsp(conn, req, fsp)) {
5240 END_PROFILE(SMBsplwr);
5244 if (!fsp->print_file) {
5245 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5246 END_PROFILE(SMBsplwr);
5250 if (!CHECK_WRITE(fsp)) {
5251 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5252 END_PROFILE(SMBsplwr);
5256 numtowrite = SVAL(req->buf, 1);
5258 if (req->buflen < numtowrite + 3) {
5259 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5260 END_PROFILE(SMBsplwr);
5264 data = (const char *)req->buf + 3;
5266 if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5267 reply_nterror(req, map_nt_error_from_unix(errno));
5268 END_PROFILE(SMBsplwr);
5272 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5274 END_PROFILE(SMBsplwr);
5278 /****************************************************************************
5280 ****************************************************************************/
5282 void reply_mkdir(struct smb_request *req)
5284 connection_struct *conn = req->conn;
5285 struct smb_filename *smb_dname = NULL;
5286 char *directory = NULL;
5288 TALLOC_CTX *ctx = talloc_tos();
5290 START_PROFILE(SMBmkdir);
5292 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5293 STR_TERMINATE, &status);
5294 if (!NT_STATUS_IS_OK(status)) {
5295 reply_nterror(req, status);
5299 status = filename_convert(ctx, conn,
5300 req->flags2 & FLAGS2_DFS_PATHNAMES,
5305 if (!NT_STATUS_IS_OK(status)) {
5306 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5307 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5308 ERRSRV, ERRbadpath);
5311 reply_nterror(req, status);
5315 status = create_directory(conn, req, smb_dname);
5317 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5319 if (!NT_STATUS_IS_OK(status)) {
5321 if (!use_nt_status()
5322 && NT_STATUS_EQUAL(status,
5323 NT_STATUS_OBJECT_NAME_COLLISION)) {
5325 * Yes, in the DOS error code case we get a
5326 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5327 * samba4 torture test.
5329 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5332 reply_nterror(req, status);
5336 reply_outbuf(req, 0, 0);
5338 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5340 TALLOC_FREE(smb_dname);
5341 END_PROFILE(SMBmkdir);
5345 /****************************************************************************
5347 ****************************************************************************/
5349 void reply_rmdir(struct smb_request *req)
5351 connection_struct *conn = req->conn;
5352 struct smb_filename *smb_dname = NULL;
5353 char *directory = NULL;
5355 TALLOC_CTX *ctx = talloc_tos();
5356 files_struct *fsp = NULL;
5358 struct smbd_server_connection *sconn = req->sconn;
5360 START_PROFILE(SMBrmdir);
5362 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5363 STR_TERMINATE, &status);
5364 if (!NT_STATUS_IS_OK(status)) {
5365 reply_nterror(req, status);
5369 status = filename_convert(ctx, conn,
5370 req->flags2 & FLAGS2_DFS_PATHNAMES,
5375 if (!NT_STATUS_IS_OK(status)) {
5376 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5377 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5378 ERRSRV, ERRbadpath);
5381 reply_nterror(req, status);
5385 if (is_ntfs_stream_smb_fname(smb_dname)) {
5386 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5390 status = SMB_VFS_CREATE_FILE(
5393 0, /* root_dir_fid */
5394 smb_dname, /* fname */
5395 DELETE_ACCESS, /* access_mask */
5396 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5398 FILE_OPEN, /* create_disposition*/
5399 FILE_DIRECTORY_FILE, /* create_options */
5400 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5401 0, /* oplock_request */
5402 0, /* allocation_size */
5403 0, /* private_flags */
5409 if (!NT_STATUS_IS_OK(status)) {
5410 if (open_was_deferred(req->mid)) {
5411 /* We have re-scheduled this call. */
5414 reply_nterror(req, status);
5418 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5419 if (!NT_STATUS_IS_OK(status)) {
5420 close_file(req, fsp, ERROR_CLOSE);
5421 reply_nterror(req, status);
5425 if (!set_delete_on_close(fsp, true, &conn->server_info->utok)) {
5426 close_file(req, fsp, ERROR_CLOSE);
5427 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5431 status = close_file(req, fsp, NORMAL_CLOSE);
5432 if (!NT_STATUS_IS_OK(status)) {
5433 reply_nterror(req, status);
5435 reply_outbuf(req, 0, 0);
5438 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5440 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5442 TALLOC_FREE(smb_dname);
5443 END_PROFILE(SMBrmdir);
5447 /*******************************************************************
5448 Resolve wildcards in a filename rename.
5449 ********************************************************************/
5451 static bool resolve_wildcards(TALLOC_CTX *ctx,
5456 char *name2_copy = NULL;
5461 char *p,*p2, *pname1, *pname2;
5463 name2_copy = talloc_strdup(ctx, name2);
5468 pname1 = strrchr_m(name1,'/');
5469 pname2 = strrchr_m(name2_copy,'/');
5471 if (!pname1 || !pname2) {
5475 /* Truncate the copy of name2 at the last '/' */
5478 /* Now go past the '/' */
5482 root1 = talloc_strdup(ctx, pname1);
5483 root2 = talloc_strdup(ctx, pname2);
5485 if (!root1 || !root2) {
5489 p = strrchr_m(root1,'.');
5492 ext1 = talloc_strdup(ctx, p+1);
5494 ext1 = talloc_strdup(ctx, "");
5496 p = strrchr_m(root2,'.');
5499 ext2 = talloc_strdup(ctx, p+1);
5501 ext2 = talloc_strdup(ctx, "");
5504 if (!ext1 || !ext2) {
5512 /* Hmmm. Should this be mb-aware ? */
5515 } else if (*p2 == '*') {
5517 root2 = talloc_asprintf(ctx, "%s%s",
5536 /* Hmmm. Should this be mb-aware ? */
5539 } else if (*p2 == '*') {
5541 ext2 = talloc_asprintf(ctx, "%s%s",
5557 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5562 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5574 /****************************************************************************
5575 Ensure open files have their names updated. Updated to notify other smbd's
5577 ****************************************************************************/
5579 static void rename_open_files(connection_struct *conn,
5580 struct share_mode_lock *lck,
5581 const struct smb_filename *smb_fname_dst)
5584 bool did_rename = False;
5587 for(fsp = file_find_di_first(lck->id); fsp;
5588 fsp = file_find_di_next(fsp)) {
5589 /* fsp_name is a relative path under the fsp. To change this for other
5590 sharepaths we need to manipulate relative paths. */
5591 /* TODO - create the absolute path and manipulate the newname
5592 relative to the sharepath. */
5593 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5596 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5597 "(file_id %s) from %s -> %s\n", fsp->fnum,
5598 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5599 smb_fname_str_dbg(smb_fname_dst)));
5601 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5602 if (NT_STATUS_IS_OK(status)) {
5608 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5609 "for %s\n", file_id_string_tos(&lck->id),
5610 smb_fname_str_dbg(smb_fname_dst)));
5613 /* Send messages to all smbd's (not ourself) that the name has changed. */
5614 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5619 /****************************************************************************
5620 We need to check if the source path is a parent directory of the destination
5621 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5622 refuse the rename with a sharing violation. Under UNIX the above call can
5623 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5624 probably need to check that the client is a Windows one before disallowing
5625 this as a UNIX client (one with UNIX extensions) can know the source is a
5626 symlink and make this decision intelligently. Found by an excellent bug
5627 report from <AndyLiebman@aol.com>.
5628 ****************************************************************************/
5630 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5631 const struct smb_filename *smb_fname_dst)
5633 const char *psrc = smb_fname_src->base_name;
5634 const char *pdst = smb_fname_dst->base_name;
5637 if (psrc[0] == '.' && psrc[1] == '/') {
5640 if (pdst[0] == '.' && pdst[1] == '/') {
5643 if ((slen = strlen(psrc)) > strlen(pdst)) {
5646 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5650 * Do the notify calls from a rename
5653 static void notify_rename(connection_struct *conn, bool is_dir,
5654 const struct smb_filename *smb_fname_src,
5655 const struct smb_filename *smb_fname_dst)
5657 char *parent_dir_src = NULL;
5658 char *parent_dir_dst = NULL;
5661 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5662 : FILE_NOTIFY_CHANGE_FILE_NAME;
5664 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5665 &parent_dir_src, NULL) ||
5666 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5667 &parent_dir_dst, NULL)) {
5671 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5672 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5673 smb_fname_src->base_name);
5674 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5675 smb_fname_dst->base_name);
5678 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5679 smb_fname_src->base_name);
5680 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5681 smb_fname_dst->base_name);
5684 /* this is a strange one. w2k3 gives an additional event for
5685 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5686 files, but not directories */
5688 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5689 FILE_NOTIFY_CHANGE_ATTRIBUTES
5690 |FILE_NOTIFY_CHANGE_CREATION,
5691 smb_fname_dst->base_name);
5694 TALLOC_FREE(parent_dir_src);
5695 TALLOC_FREE(parent_dir_dst);
5698 /****************************************************************************
5699 Rename an open file - given an fsp.
5700 ****************************************************************************/
5702 NTSTATUS rename_internals_fsp(connection_struct *conn,
5704 const struct smb_filename *smb_fname_dst_in,
5706 bool replace_if_exists)
5708 TALLOC_CTX *ctx = talloc_tos();
5709 struct smb_filename *smb_fname_dst = NULL;
5710 NTSTATUS status = NT_STATUS_OK;
5711 struct share_mode_lock *lck = NULL;
5712 bool dst_exists, old_is_stream, new_is_stream;
5714 status = check_name(conn, smb_fname_dst_in->base_name);
5715 if (!NT_STATUS_IS_OK(status)) {
5719 /* Make a copy of the dst smb_fname structs */
5721 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5722 if (!NT_STATUS_IS_OK(status)) {
5726 /* Ensure the dst smb_fname contains a '/' */
5727 if(strrchr_m(smb_fname_dst->base_name,'/') == 0) {
5729 tmp = talloc_asprintf(smb_fname_dst, "./%s",
5730 smb_fname_dst->base_name);
5732 status = NT_STATUS_NO_MEMORY;
5735 TALLOC_FREE(smb_fname_dst->base_name);
5736 smb_fname_dst->base_name = tmp;
5740 * Check for special case with case preserving and not
5741 * case sensitive. If the old last component differs from the original
5742 * last component only by case, then we should allow
5743 * the rename (user is trying to change the case of the
5746 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5747 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5748 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
5750 char *fname_dst_lcomp_base_mod = NULL;
5751 struct smb_filename *smb_fname_orig_lcomp = NULL;
5754 * Get the last component of the destination name. Note that
5755 * we guarantee that destination name contains a '/' character
5758 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5759 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5760 if (!fname_dst_lcomp_base_mod) {
5761 status = NT_STATUS_NO_MEMORY;
5766 * Create an smb_filename struct using the original last
5767 * component of the destination.
5769 status = create_synthetic_smb_fname_split(ctx,
5770 smb_fname_dst->original_lcomp, NULL,
5771 &smb_fname_orig_lcomp);
5772 if (!NT_STATUS_IS_OK(status)) {
5773 TALLOC_FREE(fname_dst_lcomp_base_mod);
5777 /* If the base names only differ by case, use original. */
5778 if(!strcsequal(fname_dst_lcomp_base_mod,
5779 smb_fname_orig_lcomp->base_name)) {
5782 * Replace the modified last component with the
5785 *last_slash = '\0'; /* Truncate at the '/' */
5786 tmp = talloc_asprintf(smb_fname_dst,
5788 smb_fname_dst->base_name,
5789 smb_fname_orig_lcomp->base_name);
5791 status = NT_STATUS_NO_MEMORY;
5792 TALLOC_FREE(fname_dst_lcomp_base_mod);
5793 TALLOC_FREE(smb_fname_orig_lcomp);
5796 TALLOC_FREE(smb_fname_dst->base_name);
5797 smb_fname_dst->base_name = tmp;
5800 /* If the stream_names only differ by case, use original. */
5801 if(!strcsequal(smb_fname_dst->stream_name,
5802 smb_fname_orig_lcomp->stream_name)) {
5804 /* Use the original stream. */
5805 tmp = talloc_strdup(smb_fname_dst,
5806 smb_fname_orig_lcomp->stream_name);
5808 status = NT_STATUS_NO_MEMORY;
5809 TALLOC_FREE(fname_dst_lcomp_base_mod);
5810 TALLOC_FREE(smb_fname_orig_lcomp);
5813 TALLOC_FREE(smb_fname_dst->stream_name);
5814 smb_fname_dst->stream_name = tmp;
5816 TALLOC_FREE(fname_dst_lcomp_base_mod);
5817 TALLOC_FREE(smb_fname_orig_lcomp);
5821 * If the src and dest names are identical - including case,
5822 * don't do the rename, just return success.
5825 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5826 strcsequal(fsp->fsp_name->stream_name,
5827 smb_fname_dst->stream_name)) {
5828 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
5829 "- returning success\n",
5830 smb_fname_str_dbg(smb_fname_dst)));
5831 status = NT_STATUS_OK;
5835 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
5836 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
5838 /* Return the correct error code if both names aren't streams. */
5839 if (!old_is_stream && new_is_stream) {
5840 status = NT_STATUS_OBJECT_NAME_INVALID;
5844 if (old_is_stream && !new_is_stream) {
5845 status = NT_STATUS_INVALID_PARAMETER;
5849 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
5851 if(!replace_if_exists && dst_exists) {
5852 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
5853 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
5854 smb_fname_str_dbg(smb_fname_dst)));
5855 status = NT_STATUS_OBJECT_NAME_COLLISION;
5860 struct file_id fileid = vfs_file_id_from_sbuf(conn,
5861 &smb_fname_dst->st);
5862 files_struct *dst_fsp = file_find_di_first(fileid);
5863 /* The file can be open when renaming a stream */
5864 if (dst_fsp && !new_is_stream) {
5865 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5866 status = NT_STATUS_ACCESS_DENIED;
5871 /* Ensure we have a valid stat struct for the source. */
5872 status = vfs_stat_fsp(fsp);
5873 if (!NT_STATUS_IS_OK(status)) {
5877 status = can_rename(conn, fsp, attrs);
5879 if (!NT_STATUS_IS_OK(status)) {
5880 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
5881 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
5882 smb_fname_str_dbg(smb_fname_dst)));
5883 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5884 status = NT_STATUS_ACCESS_DENIED;
5888 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
5889 status = NT_STATUS_ACCESS_DENIED;
5892 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5896 * We have the file open ourselves, so not being able to get the
5897 * corresponding share mode lock is a fatal error.
5900 SMB_ASSERT(lck != NULL);
5902 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
5903 uint32 create_options = fsp->fh->private_options;
5905 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
5906 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
5907 smb_fname_str_dbg(smb_fname_dst)));
5909 if (lp_map_archive(SNUM(conn)) ||
5910 lp_store_dos_attributes(SNUM(conn))) {
5911 /* We must set the archive bit on the newly
5913 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
5914 uint32_t old_dosmode = dos_mode(conn,
5916 file_set_dosmode(conn,
5918 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
5924 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
5927 rename_open_files(conn, lck, smb_fname_dst);
5930 * A rename acts as a new file create w.r.t. allowing an initial delete
5931 * on close, probably because in Windows there is a new handle to the
5932 * new file. If initial delete on close was requested but not
5933 * originally set, we need to set it here. This is probably not 100% correct,
5934 * but will work for the CIFSFS client which in non-posix mode
5935 * depends on these semantics. JRA.
5938 if (create_options & FILE_DELETE_ON_CLOSE) {
5939 status = can_set_delete_on_close(fsp, 0);
5941 if (NT_STATUS_IS_OK(status)) {
5942 /* Note that here we set the *inital* delete on close flag,
5943 * not the regular one. The magic gets handled in close. */
5944 fsp->initial_delete_on_close = True;
5948 status = NT_STATUS_OK;
5954 if (errno == ENOTDIR || errno == EISDIR) {
5955 status = NT_STATUS_OBJECT_NAME_COLLISION;
5957 status = map_nt_error_from_unix(errno);
5960 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
5961 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
5962 smb_fname_str_dbg(smb_fname_dst)));
5965 TALLOC_FREE(smb_fname_dst);
5970 /****************************************************************************
5971 The guts of the rename command, split out so it may be called by the NT SMB
5973 ****************************************************************************/
5975 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5976 connection_struct *conn,
5977 struct smb_request *req,
5978 struct smb_filename *smb_fname_src,
5979 struct smb_filename *smb_fname_dst,
5981 bool replace_if_exists,
5984 uint32_t access_mask)
5986 char *fname_src_dir = NULL;
5987 char *fname_src_mask = NULL;
5989 NTSTATUS status = NT_STATUS_OK;
5990 struct smb_Dir *dir_hnd = NULL;
5991 const char *dname = NULL;
5992 char *talloced = NULL;
5994 int create_options = 0;
5995 bool posix_pathnames = lp_posix_pathnames();
5998 * Split the old name into directory and last component
5999 * strings. Note that unix_convert may have stripped off a
6000 * leading ./ from both name and newname if the rename is
6001 * at the root of the share. We need to make sure either both
6002 * name and newname contain a / character or neither of them do
6003 * as this is checked in resolve_wildcards().
6006 /* Split up the directory from the filename/mask. */
6007 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6008 &fname_src_dir, &fname_src_mask);
6009 if (!NT_STATUS_IS_OK(status)) {
6010 status = NT_STATUS_NO_MEMORY;
6015 * We should only check the mangled cache
6016 * here if unix_convert failed. This means
6017 * that the path in 'mask' doesn't exist
6018 * on the file system and so we need to look
6019 * for a possible mangle. This patch from
6020 * Tine Smukavec <valentin.smukavec@hermes.si>.
6023 if (!VALID_STAT(smb_fname_src->st) &&
6024 mangle_is_mangled(fname_src_mask, conn->params)) {
6025 char *new_mask = NULL;
6026 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6029 TALLOC_FREE(fname_src_mask);
6030 fname_src_mask = new_mask;
6034 if (!src_has_wild) {
6038 * Only one file needs to be renamed. Append the mask back
6039 * onto the directory.
6041 TALLOC_FREE(smb_fname_src->base_name);
6042 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6046 if (!smb_fname_src->base_name) {
6047 status = NT_STATUS_NO_MEMORY;
6051 /* Ensure dst fname contains a '/' also */
6052 if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
6054 tmp = talloc_asprintf(smb_fname_dst, "./%s",
6055 smb_fname_dst->base_name);
6057 status = NT_STATUS_NO_MEMORY;
6060 TALLOC_FREE(smb_fname_dst->base_name);
6061 smb_fname_dst->base_name = tmp;
6064 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6065 "case_preserve = %d, short case preserve = %d, "
6066 "directory = %s, newname = %s, "
6067 "last_component_dest = %s\n",
6068 conn->case_sensitive, conn->case_preserve,
6069 conn->short_case_preserve,
6070 smb_fname_str_dbg(smb_fname_src),
6071 smb_fname_str_dbg(smb_fname_dst),
6072 smb_fname_dst->original_lcomp));
6074 /* The dest name still may have wildcards. */
6075 if (dest_has_wild) {
6076 char *fname_dst_mod = NULL;
6077 if (!resolve_wildcards(smb_fname_dst,
6078 smb_fname_src->base_name,
6079 smb_fname_dst->base_name,
6081 DEBUG(6, ("rename_internals: resolve_wildcards "
6083 smb_fname_src->base_name,
6084 smb_fname_dst->base_name));
6085 status = NT_STATUS_NO_MEMORY;
6088 TALLOC_FREE(smb_fname_dst->base_name);
6089 smb_fname_dst->base_name = fname_dst_mod;
6092 ZERO_STRUCT(smb_fname_src->st);
6093 if (posix_pathnames) {
6094 SMB_VFS_LSTAT(conn, smb_fname_src);
6096 SMB_VFS_STAT(conn, smb_fname_src);
6099 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6100 create_options |= FILE_DIRECTORY_FILE;
6103 status = SMB_VFS_CREATE_FILE(
6106 0, /* root_dir_fid */
6107 smb_fname_src, /* fname */
6108 access_mask, /* access_mask */
6109 (FILE_SHARE_READ | /* share_access */
6111 FILE_OPEN, /* create_disposition*/
6112 create_options, /* create_options */
6113 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6114 0, /* oplock_request */
6115 0, /* allocation_size */
6116 0, /* private_flags */
6122 if (!NT_STATUS_IS_OK(status)) {
6123 DEBUG(3, ("Could not open rename source %s: %s\n",
6124 smb_fname_str_dbg(smb_fname_src),
6125 nt_errstr(status)));
6129 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6130 attrs, replace_if_exists);
6132 close_file(req, fsp, NORMAL_CLOSE);
6134 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6135 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6136 smb_fname_str_dbg(smb_fname_dst)));
6142 * Wildcards - process each file that matches.
6144 if (strequal(fname_src_mask, "????????.???")) {
6145 TALLOC_FREE(fname_src_mask);
6146 fname_src_mask = talloc_strdup(ctx, "*");
6147 if (!fname_src_mask) {
6148 status = NT_STATUS_NO_MEMORY;
6153 status = check_name(conn, fname_src_dir);
6154 if (!NT_STATUS_IS_OK(status)) {
6158 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6160 if (dir_hnd == NULL) {
6161 status = map_nt_error_from_unix(errno);
6165 status = NT_STATUS_NO_SUCH_FILE;
6167 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6168 * - gentest fix. JRA
6171 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6173 files_struct *fsp = NULL;
6174 char *destname = NULL;
6175 bool sysdir_entry = False;
6177 /* Quick check for "." and ".." */
6178 if (ISDOT(dname) || ISDOTDOT(dname)) {
6180 sysdir_entry = True;
6182 TALLOC_FREE(talloced);
6187 if (!is_visible_file(conn, fname_src_dir, dname,
6188 &smb_fname_src->st, false)) {
6189 TALLOC_FREE(talloced);
6193 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6194 TALLOC_FREE(talloced);
6199 status = NT_STATUS_OBJECT_NAME_INVALID;
6203 TALLOC_FREE(smb_fname_src->base_name);
6204 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6208 if (!smb_fname_src->base_name) {
6209 status = NT_STATUS_NO_MEMORY;
6213 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6214 smb_fname_dst->base_name,
6216 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6217 smb_fname_src->base_name, destname));
6218 TALLOC_FREE(talloced);
6222 status = NT_STATUS_NO_MEMORY;
6226 TALLOC_FREE(smb_fname_dst->base_name);
6227 smb_fname_dst->base_name = destname;
6229 ZERO_STRUCT(smb_fname_src->st);
6230 if (posix_pathnames) {
6231 SMB_VFS_LSTAT(conn, smb_fname_src);
6233 SMB_VFS_STAT(conn, smb_fname_src);
6238 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6239 create_options |= FILE_DIRECTORY_FILE;
6242 status = SMB_VFS_CREATE_FILE(
6245 0, /* root_dir_fid */
6246 smb_fname_src, /* fname */
6247 access_mask, /* access_mask */
6248 (FILE_SHARE_READ | /* share_access */
6250 FILE_OPEN, /* create_disposition*/
6251 create_options, /* create_options */
6252 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6253 0, /* oplock_request */
6254 0, /* allocation_size */
6255 0, /* private_flags */
6261 if (!NT_STATUS_IS_OK(status)) {
6262 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6263 "returned %s rename %s -> %s\n",
6265 smb_fname_str_dbg(smb_fname_src),
6266 smb_fname_str_dbg(smb_fname_dst)));
6270 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6272 if (!smb_fname_dst->original_lcomp) {
6273 status = NT_STATUS_NO_MEMORY;
6277 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6278 attrs, replace_if_exists);
6280 close_file(req, fsp, NORMAL_CLOSE);
6282 if (!NT_STATUS_IS_OK(status)) {
6283 DEBUG(3, ("rename_internals_fsp returned %s for "
6284 "rename %s -> %s\n", nt_errstr(status),
6285 smb_fname_str_dbg(smb_fname_src),
6286 smb_fname_str_dbg(smb_fname_dst)));
6292 DEBUG(3,("rename_internals: doing rename on %s -> "
6293 "%s\n", smb_fname_str_dbg(smb_fname_src),
6294 smb_fname_str_dbg(smb_fname_src)));
6295 TALLOC_FREE(talloced);
6297 TALLOC_FREE(dir_hnd);
6299 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6300 status = map_nt_error_from_unix(errno);
6304 TALLOC_FREE(talloced);
6305 TALLOC_FREE(fname_src_dir);
6306 TALLOC_FREE(fname_src_mask);
6310 /****************************************************************************
6312 ****************************************************************************/
6314 void reply_mv(struct smb_request *req)
6316 connection_struct *conn = req->conn;
6318 char *newname = NULL;
6322 bool src_has_wcard = False;
6323 bool dest_has_wcard = False;
6324 TALLOC_CTX *ctx = talloc_tos();
6325 struct smb_filename *smb_fname_src = NULL;
6326 struct smb_filename *smb_fname_dst = NULL;
6328 START_PROFILE(SMBmv);
6331 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6335 attrs = SVAL(req->vwv+0, 0);
6337 p = (const char *)req->buf + 1;
6338 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6339 &status, &src_has_wcard);
6340 if (!NT_STATUS_IS_OK(status)) {
6341 reply_nterror(req, status);
6345 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6346 &status, &dest_has_wcard);
6347 if (!NT_STATUS_IS_OK(status)) {
6348 reply_nterror(req, status);
6352 status = filename_convert(ctx,
6354 req->flags2 & FLAGS2_DFS_PATHNAMES,
6356 UCF_COND_ALLOW_WCARD_LCOMP,
6360 if (!NT_STATUS_IS_OK(status)) {
6361 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6362 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6363 ERRSRV, ERRbadpath);
6366 reply_nterror(req, status);
6370 status = filename_convert(ctx,
6372 req->flags2 & FLAGS2_DFS_PATHNAMES,
6374 UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6378 if (!NT_STATUS_IS_OK(status)) {
6379 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6380 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6381 ERRSRV, ERRbadpath);
6384 reply_nterror(req, status);
6388 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6389 smb_fname_str_dbg(smb_fname_dst)));
6391 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6392 attrs, False, src_has_wcard, dest_has_wcard,
6394 if (!NT_STATUS_IS_OK(status)) {
6395 if (open_was_deferred(req->mid)) {
6396 /* We have re-scheduled this call. */
6399 reply_nterror(req, status);
6403 reply_outbuf(req, 0, 0);
6405 TALLOC_FREE(smb_fname_src);
6406 TALLOC_FREE(smb_fname_dst);
6411 /*******************************************************************
6412 Copy a file as part of a reply_copy.
6413 ******************************************************************/
6416 * TODO: check error codes on all callers
6419 NTSTATUS copy_file(TALLOC_CTX *ctx,
6420 connection_struct *conn,
6421 struct smb_filename *smb_fname_src,
6422 struct smb_filename *smb_fname_dst,
6425 bool target_is_directory)
6427 struct smb_filename *smb_fname_dst_tmp = NULL;
6429 files_struct *fsp1,*fsp2;
6431 uint32 new_create_disposition;
6435 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6436 if (!NT_STATUS_IS_OK(status)) {
6441 * If the target is a directory, extract the last component from the
6442 * src filename and append it to the dst filename
6444 if (target_is_directory) {
6447 /* dest/target can't be a stream if it's a directory. */
6448 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6450 p = strrchr_m(smb_fname_src->base_name,'/');
6454 p = smb_fname_src->base_name;
6456 smb_fname_dst_tmp->base_name =
6457 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6459 if (!smb_fname_dst_tmp->base_name) {
6460 status = NT_STATUS_NO_MEMORY;
6465 status = vfs_file_exist(conn, smb_fname_src);
6466 if (!NT_STATUS_IS_OK(status)) {
6470 if (!target_is_directory && count) {
6471 new_create_disposition = FILE_OPEN;
6473 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
6475 &new_create_disposition,
6478 status = NT_STATUS_INVALID_PARAMETER;
6483 /* Open the src file for reading. */
6484 status = SMB_VFS_CREATE_FILE(
6487 0, /* root_dir_fid */
6488 smb_fname_src, /* fname */
6489 FILE_GENERIC_READ, /* access_mask */
6490 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6491 FILE_OPEN, /* create_disposition*/
6492 0, /* create_options */
6493 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6494 INTERNAL_OPEN_ONLY, /* oplock_request */
6495 0, /* allocation_size */
6496 0, /* private_flags */
6502 if (!NT_STATUS_IS_OK(status)) {
6506 dosattrs = dos_mode(conn, smb_fname_src);
6508 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6509 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6512 /* Open the dst file for writing. */
6513 status = SMB_VFS_CREATE_FILE(
6516 0, /* root_dir_fid */
6517 smb_fname_dst, /* fname */
6518 FILE_GENERIC_WRITE, /* access_mask */
6519 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6520 new_create_disposition, /* create_disposition*/
6521 0, /* create_options */
6522 dosattrs, /* file_attributes */
6523 INTERNAL_OPEN_ONLY, /* oplock_request */
6524 0, /* allocation_size */
6525 0, /* private_flags */
6531 if (!NT_STATUS_IS_OK(status)) {
6532 close_file(NULL, fsp1, ERROR_CLOSE);
6536 if ((ofun&3) == 1) {
6537 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6538 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6540 * Stop the copy from occurring.
6543 smb_fname_src->st.st_ex_size = 0;
6547 /* Do the actual copy. */
6548 if (smb_fname_src->st.st_ex_size) {
6549 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6552 close_file(NULL, fsp1, NORMAL_CLOSE);
6554 /* Ensure the modtime is set correctly on the destination file. */
6555 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6558 * As we are opening fsp1 read-only we only expect
6559 * an error on close on fsp2 if we are out of space.
6560 * Thus we don't look at the error return from the
6563 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6565 if (!NT_STATUS_IS_OK(status)) {
6569 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6570 status = NT_STATUS_DISK_FULL;
6574 status = NT_STATUS_OK;
6577 TALLOC_FREE(smb_fname_dst_tmp);
6581 /****************************************************************************
6582 Reply to a file copy.
6583 ****************************************************************************/
6585 void reply_copy(struct smb_request *req)
6587 connection_struct *conn = req->conn;
6588 struct smb_filename *smb_fname_src = NULL;
6589 struct smb_filename *smb_fname_dst = NULL;
6590 char *fname_src = NULL;
6591 char *fname_dst = NULL;
6592 char *fname_src_mask = NULL;
6593 char *fname_src_dir = NULL;
6596 int error = ERRnoaccess;
6600 bool target_is_directory=False;
6601 bool source_has_wild = False;
6602 bool dest_has_wild = False;
6604 TALLOC_CTX *ctx = talloc_tos();
6606 START_PROFILE(SMBcopy);
6609 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6613 tid2 = SVAL(req->vwv+0, 0);
6614 ofun = SVAL(req->vwv+1, 0);
6615 flags = SVAL(req->vwv+2, 0);
6617 p = (const char *)req->buf;
6618 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6619 &status, &source_has_wild);
6620 if (!NT_STATUS_IS_OK(status)) {
6621 reply_nterror(req, status);
6624 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6625 &status, &dest_has_wild);
6626 if (!NT_STATUS_IS_OK(status)) {
6627 reply_nterror(req, status);
6631 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6633 if (tid2 != conn->cnum) {
6634 /* can't currently handle inter share copies XXXX */
6635 DEBUG(3,("Rejecting inter-share copy\n"));
6636 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6640 status = filename_convert(ctx, conn,
6641 req->flags2 & FLAGS2_DFS_PATHNAMES,
6643 UCF_COND_ALLOW_WCARD_LCOMP,
6646 if (!NT_STATUS_IS_OK(status)) {
6647 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6648 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6649 ERRSRV, ERRbadpath);
6652 reply_nterror(req, status);
6656 status = filename_convert(ctx, conn,
6657 req->flags2 & FLAGS2_DFS_PATHNAMES,
6659 UCF_COND_ALLOW_WCARD_LCOMP,
6662 if (!NT_STATUS_IS_OK(status)) {
6663 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6664 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6665 ERRSRV, ERRbadpath);
6668 reply_nterror(req, status);
6672 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6674 if ((flags&1) && target_is_directory) {
6675 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6679 if ((flags&2) && !target_is_directory) {
6680 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
6684 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6685 /* wants a tree copy! XXXX */
6686 DEBUG(3,("Rejecting tree copy\n"));
6687 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6691 /* Split up the directory from the filename/mask. */
6692 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6693 &fname_src_dir, &fname_src_mask);
6694 if (!NT_STATUS_IS_OK(status)) {
6695 reply_nterror(req, NT_STATUS_NO_MEMORY);
6700 * We should only check the mangled cache
6701 * here if unix_convert failed. This means
6702 * that the path in 'mask' doesn't exist
6703 * on the file system and so we need to look
6704 * for a possible mangle. This patch from
6705 * Tine Smukavec <valentin.smukavec@hermes.si>.
6707 if (!VALID_STAT(smb_fname_src->st) &&
6708 mangle_is_mangled(fname_src_mask, conn->params)) {
6709 char *new_mask = NULL;
6710 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6711 &new_mask, conn->params);
6713 /* Use demangled name if one was successfully found. */
6715 TALLOC_FREE(fname_src_mask);
6716 fname_src_mask = new_mask;
6720 if (!source_has_wild) {
6723 * Only one file needs to be copied. Append the mask back onto
6726 TALLOC_FREE(smb_fname_src->base_name);
6727 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6731 if (!smb_fname_src->base_name) {
6732 reply_nterror(req, NT_STATUS_NO_MEMORY);
6736 if (dest_has_wild) {
6737 char *fname_dst_mod = NULL;
6738 if (!resolve_wildcards(smb_fname_dst,
6739 smb_fname_src->base_name,
6740 smb_fname_dst->base_name,
6742 reply_nterror(req, NT_STATUS_NO_MEMORY);
6745 TALLOC_FREE(smb_fname_dst->base_name);
6746 smb_fname_dst->base_name = fname_dst_mod;
6749 status = check_name(conn, smb_fname_src->base_name);
6750 if (!NT_STATUS_IS_OK(status)) {
6751 reply_nterror(req, status);
6755 status = check_name(conn, smb_fname_dst->base_name);
6756 if (!NT_STATUS_IS_OK(status)) {
6757 reply_nterror(req, status);
6761 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
6762 ofun, count, target_is_directory);
6764 if(!NT_STATUS_IS_OK(status)) {
6765 reply_nterror(req, status);
6771 struct smb_Dir *dir_hnd = NULL;
6772 const char *dname = NULL;
6773 char *talloced = NULL;
6777 * There is a wildcard that requires us to actually read the
6778 * src dir and copy each file matching the mask to the dst.
6779 * Right now streams won't be copied, but this could
6780 * presumably be added with a nested loop for reach dir entry.
6782 SMB_ASSERT(!smb_fname_src->stream_name);
6783 SMB_ASSERT(!smb_fname_dst->stream_name);
6785 smb_fname_src->stream_name = NULL;
6786 smb_fname_dst->stream_name = NULL;
6788 if (strequal(fname_src_mask,"????????.???")) {
6789 TALLOC_FREE(fname_src_mask);
6790 fname_src_mask = talloc_strdup(ctx, "*");
6791 if (!fname_src_mask) {
6792 reply_nterror(req, NT_STATUS_NO_MEMORY);
6797 status = check_name(conn, fname_src_dir);
6798 if (!NT_STATUS_IS_OK(status)) {
6799 reply_nterror(req, status);
6803 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
6804 if (dir_hnd == NULL) {
6805 status = map_nt_error_from_unix(errno);
6806 reply_nterror(req, status);
6812 /* Iterate over the src dir copying each entry to the dst. */
6813 while ((dname = ReadDirName(dir_hnd, &offset,
6814 &smb_fname_src->st, &talloced))) {
6815 char *destname = NULL;
6817 if (ISDOT(dname) || ISDOTDOT(dname)) {
6818 TALLOC_FREE(talloced);
6822 if (!is_visible_file(conn, fname_src_dir, dname,
6823 &smb_fname_src->st, false)) {
6824 TALLOC_FREE(talloced);
6828 if(!mask_match(dname, fname_src_mask,
6829 conn->case_sensitive)) {
6830 TALLOC_FREE(talloced);
6834 error = ERRnoaccess;
6836 /* Get the src smb_fname struct setup. */
6837 TALLOC_FREE(smb_fname_src->base_name);
6838 smb_fname_src->base_name =
6839 talloc_asprintf(smb_fname_src, "%s/%s",
6840 fname_src_dir, dname);
6842 if (!smb_fname_src->base_name) {
6843 TALLOC_FREE(dir_hnd);
6844 TALLOC_FREE(talloced);
6845 reply_nterror(req, NT_STATUS_NO_MEMORY);
6849 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6850 smb_fname_dst->base_name,
6852 TALLOC_FREE(talloced);
6856 TALLOC_FREE(dir_hnd);
6857 TALLOC_FREE(talloced);
6858 reply_nterror(req, NT_STATUS_NO_MEMORY);
6862 TALLOC_FREE(smb_fname_dst->base_name);
6863 smb_fname_dst->base_name = destname;
6865 status = check_name(conn, smb_fname_src->base_name);
6866 if (!NT_STATUS_IS_OK(status)) {
6867 TALLOC_FREE(dir_hnd);
6868 TALLOC_FREE(talloced);
6869 reply_nterror(req, status);
6873 status = check_name(conn, smb_fname_dst->base_name);
6874 if (!NT_STATUS_IS_OK(status)) {
6875 TALLOC_FREE(dir_hnd);
6876 TALLOC_FREE(talloced);
6877 reply_nterror(req, status);
6881 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
6882 smb_fname_src->base_name,
6883 smb_fname_dst->base_name));
6885 status = copy_file(ctx, conn, smb_fname_src,
6886 smb_fname_dst, ofun, count,
6887 target_is_directory);
6888 if (NT_STATUS_IS_OK(status)) {
6892 TALLOC_FREE(talloced);
6894 TALLOC_FREE(dir_hnd);
6898 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
6902 reply_outbuf(req, 1, 0);
6903 SSVAL(req->outbuf,smb_vwv0,count);
6905 TALLOC_FREE(smb_fname_src);
6906 TALLOC_FREE(smb_fname_dst);
6907 TALLOC_FREE(fname_src);
6908 TALLOC_FREE(fname_dst);
6909 TALLOC_FREE(fname_src_mask);
6910 TALLOC_FREE(fname_src_dir);
6912 END_PROFILE(SMBcopy);
6917 #define DBGC_CLASS DBGC_LOCKING
6919 /****************************************************************************
6920 Get a lock pid, dealing with large count requests.
6921 ****************************************************************************/
6923 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
6924 bool large_file_format)
6926 if(!large_file_format)
6927 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
6929 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6932 /****************************************************************************
6933 Get a lock count, dealing with large count requests.
6934 ****************************************************************************/
6936 uint64_t get_lock_count(const uint8_t *data, int data_offset,
6937 bool large_file_format)
6941 if(!large_file_format) {
6942 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6945 #if defined(HAVE_LONGLONG)
6946 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6947 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6948 #else /* HAVE_LONGLONG */
6951 * NT4.x seems to be broken in that it sends large file (64 bit)
6952 * lockingX calls even if the CAP_LARGE_FILES was *not*
6953 * negotiated. For boxes without large unsigned ints truncate the
6954 * lock count by dropping the top 32 bits.
6957 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6958 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6959 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6960 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6961 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6964 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6965 #endif /* HAVE_LONGLONG */
6971 #if !defined(HAVE_LONGLONG)
6972 /****************************************************************************
6973 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6974 ****************************************************************************/
6976 static uint32 map_lock_offset(uint32 high, uint32 low)
6980 uint32 highcopy = high;
6983 * Try and find out how many significant bits there are in high.
6986 for(i = 0; highcopy; i++)
6990 * We use 31 bits not 32 here as POSIX
6991 * lock offsets may not be negative.
6994 mask = (~0) << (31 - i);
6997 return 0; /* Fail. */
7003 #endif /* !defined(HAVE_LONGLONG) */
7005 /****************************************************************************
7006 Get a lock offset, dealing with large offset requests.
7007 ****************************************************************************/
7009 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7010 bool large_file_format, bool *err)
7012 uint64_t offset = 0;
7016 if(!large_file_format) {
7017 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7020 #if defined(HAVE_LONGLONG)
7021 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7022 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7023 #else /* HAVE_LONGLONG */
7026 * NT4.x seems to be broken in that it sends large file (64 bit)
7027 * lockingX calls even if the CAP_LARGE_FILES was *not*
7028 * negotiated. For boxes without large unsigned ints mangle the
7029 * lock offset by mapping the top 32 bits onto the lower 32.
7032 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7033 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7034 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7037 if((new_low = map_lock_offset(high, low)) == 0) {
7039 return (uint64_t)-1;
7042 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7043 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7044 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7045 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7048 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7049 #endif /* HAVE_LONGLONG */
7055 NTSTATUS smbd_do_locking(struct smb_request *req,
7059 uint16_t num_ulocks,
7060 struct smbd_lock_element *ulocks,
7062 struct smbd_lock_element *locks,
7065 connection_struct *conn = req->conn;
7067 NTSTATUS status = NT_STATUS_OK;
7071 /* Data now points at the beginning of the list
7072 of smb_unlkrng structs */
7073 for(i = 0; i < (int)num_ulocks; i++) {
7074 struct smbd_lock_element *e = &ulocks[i];
7076 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7077 "pid %u, file %s\n",
7080 (unsigned int)e->smblctx,
7083 if (e->brltype != UNLOCK_LOCK) {
7084 /* this can only happen with SMB2 */
7085 return NT_STATUS_INVALID_PARAMETER;
7088 status = do_unlock(req->sconn->msg_ctx,
7095 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7096 nt_errstr(status)));
7098 if (!NT_STATUS_IS_OK(status)) {
7103 /* Setup the timeout in seconds. */
7105 if (!lp_blocking_locks(SNUM(conn))) {
7109 /* Data now points at the beginning of the list
7110 of smb_lkrng structs */
7112 for(i = 0; i < (int)num_locks; i++) {
7113 struct smbd_lock_element *e = &locks[i];
7115 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7116 "%llu, file %s timeout = %d\n",
7119 (unsigned long long)e->smblctx,
7123 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7124 struct blocking_lock_record *blr = NULL;
7126 if (num_locks > 1) {
7128 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7129 * if the lock vector contains one entry. When given mutliple cancel
7130 * requests in a single PDU we expect the server to return an
7131 * error. Windows servers seem to accept the request but only
7132 * cancel the first lock.
7133 * JRA - Do what Windows does (tm) :-).
7137 /* MS-CIFS (2.2.4.32.1) behavior. */
7138 return NT_STATUS_DOS(ERRDOS,
7139 ERRcancelviolation);
7141 /* Windows behavior. */
7143 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7144 "cancel request\n"));
7150 if (lp_blocking_locks(SNUM(conn))) {
7152 /* Schedule a message to ourselves to
7153 remove the blocking lock record and
7154 return the right error. */
7156 blr = blocking_lock_cancel_smb1(fsp,
7162 NT_STATUS_FILE_LOCK_CONFLICT);
7164 return NT_STATUS_DOS(
7166 ERRcancelviolation);
7169 /* Remove a matching pending lock. */
7170 status = do_lock_cancel(fsp,
7177 bool blocking_lock = timeout ? true : false;
7178 bool defer_lock = false;
7179 struct byte_range_lock *br_lck;
7180 uint64_t block_smblctx;
7182 br_lck = do_lock(req->sconn->msg_ctx,
7194 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7195 /* Windows internal resolution for blocking locks seems
7196 to be about 200ms... Don't wait for less than that. JRA. */
7197 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7198 timeout = lp_lock_spin_time();
7203 /* If a lock sent with timeout of zero would fail, and
7204 * this lock has been requested multiple times,
7205 * according to brl_lock_failed() we convert this
7206 * request to a blocking lock with a timeout of between
7207 * 150 - 300 milliseconds.
7209 * If lp_lock_spin_time() has been set to 0, we skip
7210 * this blocking retry and fail immediately.
7212 * Replacement for do_lock_spin(). JRA. */
7214 if (!req->sconn->using_smb2 &&
7215 br_lck && lp_blocking_locks(SNUM(conn)) &&
7216 lp_lock_spin_time() && !blocking_lock &&
7217 NT_STATUS_EQUAL((status),
7218 NT_STATUS_FILE_LOCK_CONFLICT))
7221 timeout = lp_lock_spin_time();
7224 if (br_lck && defer_lock) {
7226 * A blocking lock was requested. Package up
7227 * this smb into a queued request and push it
7228 * onto the blocking lock queue.
7230 if(push_blocking_lock_request(br_lck,
7241 TALLOC_FREE(br_lck);
7243 return NT_STATUS_OK;
7247 TALLOC_FREE(br_lck);
7250 if (!NT_STATUS_IS_OK(status)) {
7255 /* If any of the above locks failed, then we must unlock
7256 all of the previous locks (X/Open spec). */
7258 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7260 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7261 i = -1; /* we want to skip the for loop */
7265 * Ensure we don't do a remove on the lock that just failed,
7266 * as under POSIX rules, if we have a lock already there, we
7267 * will delete it (and we shouldn't) .....
7269 for(i--; i >= 0; i--) {
7270 struct smbd_lock_element *e = &locks[i];
7272 do_unlock(req->sconn->msg_ctx,
7282 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7283 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7285 return NT_STATUS_OK;
7288 /****************************************************************************
7289 Reply to a lockingX request.
7290 ****************************************************************************/
7292 void reply_lockingX(struct smb_request *req)
7294 connection_struct *conn = req->conn;
7296 unsigned char locktype;
7297 unsigned char oplocklevel;
7302 const uint8_t *data;
7303 bool large_file_format;
7305 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7306 struct smbd_lock_element *ulocks;
7307 struct smbd_lock_element *locks;
7310 START_PROFILE(SMBlockingX);
7313 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7314 END_PROFILE(SMBlockingX);
7318 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7319 locktype = CVAL(req->vwv+3, 0);
7320 oplocklevel = CVAL(req->vwv+3, 1);
7321 num_ulocks = SVAL(req->vwv+6, 0);
7322 num_locks = SVAL(req->vwv+7, 0);
7323 lock_timeout = IVAL(req->vwv+4, 0);
7324 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7326 if (!check_fsp(conn, req, fsp)) {
7327 END_PROFILE(SMBlockingX);
7333 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7334 /* we don't support these - and CANCEL_LOCK makes w2k
7335 and XP reboot so I don't really want to be
7336 compatible! (tridge) */
7337 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7338 END_PROFILE(SMBlockingX);
7342 /* Check if this is an oplock break on a file
7343 we have granted an oplock on.
7345 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7346 /* Client can insist on breaking to none. */
7347 bool break_to_none = (oplocklevel == 0);
7350 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7351 "for fnum = %d\n", (unsigned int)oplocklevel,
7355 * Make sure we have granted an exclusive or batch oplock on
7359 if (fsp->oplock_type == 0) {
7361 /* The Samba4 nbench simulator doesn't understand
7362 the difference between break to level2 and break
7363 to none from level2 - it sends oplock break
7364 replies in both cases. Don't keep logging an error
7365 message here - just ignore it. JRA. */
7367 DEBUG(5,("reply_lockingX: Error : oplock break from "
7368 "client for fnum = %d (oplock=%d) and no "
7369 "oplock granted on this file (%s).\n",
7370 fsp->fnum, fsp->oplock_type,
7373 /* if this is a pure oplock break request then don't
7375 if (num_locks == 0 && num_ulocks == 0) {
7376 END_PROFILE(SMBlockingX);
7379 END_PROFILE(SMBlockingX);
7380 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7385 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7387 result = remove_oplock(fsp);
7389 result = downgrade_oplock(fsp);
7393 DEBUG(0, ("reply_lockingX: error in removing "
7394 "oplock on file %s\n", fsp_str_dbg(fsp)));
7395 /* Hmmm. Is this panic justified? */
7396 smb_panic("internal tdb error");
7399 reply_to_oplock_break_requests(fsp);
7401 /* if this is a pure oplock break request then don't send a
7403 if (num_locks == 0 && num_ulocks == 0) {
7404 /* Sanity check - ensure a pure oplock break is not a
7406 if(CVAL(req->vwv+0, 0) != 0xff)
7407 DEBUG(0,("reply_lockingX: Error : pure oplock "
7408 "break is a chained %d request !\n",
7409 (unsigned int)CVAL(req->vwv+0, 0)));
7410 END_PROFILE(SMBlockingX);
7416 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7417 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7418 END_PROFILE(SMBlockingX);
7422 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7423 if (ulocks == NULL) {
7424 reply_nterror(req, NT_STATUS_NO_MEMORY);
7425 END_PROFILE(SMBlockingX);
7429 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7430 if (locks == NULL) {
7431 reply_nterror(req, NT_STATUS_NO_MEMORY);
7432 END_PROFILE(SMBlockingX);
7436 /* Data now points at the beginning of the list
7437 of smb_unlkrng structs */
7438 for(i = 0; i < (int)num_ulocks; i++) {
7439 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7440 ulocks[i].count = get_lock_count(data, i, large_file_format);
7441 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7442 ulocks[i].brltype = UNLOCK_LOCK;
7445 * There is no error code marked "stupid client bug".... :-).
7448 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7449 END_PROFILE(SMBlockingX);
7454 /* Now do any requested locks */
7455 data += ((large_file_format ? 20 : 10)*num_ulocks);
7457 /* Data now points at the beginning of the list
7458 of smb_lkrng structs */
7460 for(i = 0; i < (int)num_locks; i++) {
7461 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7462 locks[i].count = get_lock_count(data, i, large_file_format);
7463 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7465 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7466 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7467 locks[i].brltype = PENDING_READ_LOCK;
7469 locks[i].brltype = READ_LOCK;
7472 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7473 locks[i].brltype = PENDING_WRITE_LOCK;
7475 locks[i].brltype = WRITE_LOCK;
7480 * There is no error code marked "stupid client bug".... :-).
7483 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7484 END_PROFILE(SMBlockingX);
7489 status = smbd_do_locking(req, fsp,
7490 locktype, lock_timeout,
7494 if (!NT_STATUS_IS_OK(status)) {
7495 END_PROFILE(SMBlockingX);
7496 reply_nterror(req, status);
7500 END_PROFILE(SMBlockingX);
7504 reply_outbuf(req, 2, 0);
7506 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7507 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7509 END_PROFILE(SMBlockingX);
7514 #define DBGC_CLASS DBGC_ALL
7516 /****************************************************************************
7517 Reply to a SMBreadbmpx (read block multiplex) request.
7518 Always reply with an error, if someone has a platform really needs this,
7519 please contact vl@samba.org
7520 ****************************************************************************/
7522 void reply_readbmpx(struct smb_request *req)
7524 START_PROFILE(SMBreadBmpx);
7525 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7526 END_PROFILE(SMBreadBmpx);
7530 /****************************************************************************
7531 Reply to a SMBreadbs (read block multiplex secondary) request.
7532 Always reply with an error, if someone has a platform really needs this,
7533 please contact vl@samba.org
7534 ****************************************************************************/
7536 void reply_readbs(struct smb_request *req)
7538 START_PROFILE(SMBreadBs);
7539 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7540 END_PROFILE(SMBreadBs);
7544 /****************************************************************************
7545 Reply to a SMBsetattrE.
7546 ****************************************************************************/
7548 void reply_setattrE(struct smb_request *req)
7550 connection_struct *conn = req->conn;
7551 struct smb_file_time ft;
7555 START_PROFILE(SMBsetattrE);
7559 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7563 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7565 if(!fsp || (fsp->conn != conn)) {
7566 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7571 * Convert the DOS times into unix times.
7574 ft.atime = convert_time_t_to_timespec(
7575 srv_make_unix_date2(req->vwv+3));
7576 ft.mtime = convert_time_t_to_timespec(
7577 srv_make_unix_date2(req->vwv+5));
7578 ft.create_time = convert_time_t_to_timespec(
7579 srv_make_unix_date2(req->vwv+1));
7581 reply_outbuf(req, 0, 0);
7584 * Patch from Ray Frush <frush@engr.colostate.edu>
7585 * Sometimes times are sent as zero - ignore them.
7588 /* Ensure we have a valid stat struct for the source. */
7589 status = vfs_stat_fsp(fsp);
7590 if (!NT_STATUS_IS_OK(status)) {
7591 reply_nterror(req, status);
7595 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7596 if (!NT_STATUS_IS_OK(status)) {
7597 reply_nterror(req, status);
7601 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7604 (unsigned int)ft.atime.tv_sec,
7605 (unsigned int)ft.mtime.tv_sec,
7606 (unsigned int)ft.create_time.tv_sec
7609 END_PROFILE(SMBsetattrE);
7614 /* Back from the dead for OS/2..... JRA. */
7616 /****************************************************************************
7617 Reply to a SMBwritebmpx (write block multiplex primary) request.
7618 Always reply with an error, if someone has a platform really needs this,
7619 please contact vl@samba.org
7620 ****************************************************************************/
7622 void reply_writebmpx(struct smb_request *req)
7624 START_PROFILE(SMBwriteBmpx);
7625 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7626 END_PROFILE(SMBwriteBmpx);
7630 /****************************************************************************
7631 Reply to a SMBwritebs (write block multiplex secondary) request.
7632 Always reply with an error, if someone has a platform really needs this,
7633 please contact vl@samba.org
7634 ****************************************************************************/
7636 void reply_writebs(struct smb_request *req)
7638 START_PROFILE(SMBwriteBs);
7639 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7640 END_PROFILE(SMBwriteBs);
7644 /****************************************************************************
7645 Reply to a SMBgetattrE.
7646 ****************************************************************************/
7648 void reply_getattrE(struct smb_request *req)
7650 connection_struct *conn = req->conn;
7653 struct timespec create_ts;
7655 START_PROFILE(SMBgetattrE);
7658 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7659 END_PROFILE(SMBgetattrE);
7663 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7665 if(!fsp || (fsp->conn != conn)) {
7666 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7667 END_PROFILE(SMBgetattrE);
7671 /* Do an fstat on this file */
7673 reply_nterror(req, map_nt_error_from_unix(errno));
7674 END_PROFILE(SMBgetattrE);
7678 mode = dos_mode(conn, fsp->fsp_name);
7681 * Convert the times into dos times. Set create
7682 * date to be last modify date as UNIX doesn't save
7686 reply_outbuf(req, 11, 0);
7688 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7689 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7690 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7691 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7692 /* Should we check pending modtime here ? JRA */
7693 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7694 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7697 SIVAL(req->outbuf, smb_vwv6, 0);
7698 SIVAL(req->outbuf, smb_vwv8, 0);
7700 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7701 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
7702 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7704 SSVAL(req->outbuf,smb_vwv10, mode);
7706 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7708 END_PROFILE(SMBgetattrE);