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
28 #include "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "fake_file.h"
33 #include "rpc_client/rpc_client.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "rpc_client/cli_spoolss.h"
37 #include "rpc_client/init_spoolss.h"
38 #include "rpc_server/rpc_ncacn_np.h"
39 #include "libcli/security/security.h"
40 #include "libsmb/nmblib.h"
42 #include "smbprofile.h"
43 #include "../lib/tsocket/tsocket.h"
45 /****************************************************************************
46 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
47 path or anything including wildcards.
48 We're assuming here that '/' is not the second byte in any multibyte char
49 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
51 ****************************************************************************/
53 /* Custom version for processing POSIX paths. */
54 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
56 static NTSTATUS check_path_syntax_internal(char *path,
58 bool *p_last_component_contains_wcard)
62 NTSTATUS ret = NT_STATUS_OK;
63 bool start_of_name_component = True;
64 bool stream_started = false;
66 *p_last_component_contains_wcard = False;
73 return NT_STATUS_OBJECT_NAME_INVALID;
76 return NT_STATUS_OBJECT_NAME_INVALID;
78 if (strchr_m(&s[1], ':')) {
79 return NT_STATUS_OBJECT_NAME_INVALID;
85 if ((*s == ':') && !posix_path && !stream_started) {
86 if (*p_last_component_contains_wcard) {
87 return NT_STATUS_OBJECT_NAME_INVALID;
89 /* Stream names allow more characters than file names.
90 We're overloading posix_path here to allow a wider
91 range of characters. If stream_started is true this
92 is still a Windows path even if posix_path is true.
95 stream_started = true;
96 start_of_name_component = false;
100 return NT_STATUS_OBJECT_NAME_INVALID;
104 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
106 * Safe to assume is not the second part of a mb char
107 * as this is handled below.
109 /* Eat multiple '/' or '\\' */
110 while (IS_PATH_SEP(*s,posix_path)) {
113 if ((d != path) && (*s != '\0')) {
114 /* We only care about non-leading or trailing '/' or '\\' */
118 start_of_name_component = True;
120 *p_last_component_contains_wcard = False;
124 if (start_of_name_component) {
125 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
126 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
129 * No mb char starts with '.' so we're safe checking the directory separator here.
132 /* If we just added a '/' - delete it */
133 if ((d > path) && (*(d-1) == '/')) {
138 /* Are we at the start ? Can't go back further if so. */
140 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
143 /* Go back one level... */
144 /* We know this is safe as '/' cannot be part of a mb sequence. */
145 /* NOTE - if this assumption is invalid we are not in good shape... */
146 /* Decrement d first as d points to the *next* char to write into. */
147 for (d--; d > path; d--) {
151 s += 2; /* Else go past the .. */
152 /* We're still at the start of a name component, just the previous one. */
155 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
167 if (*s <= 0x1f || *s == '|') {
168 return NT_STATUS_OBJECT_NAME_INVALID;
176 *p_last_component_contains_wcard = True;
185 /* Get the size of the next MB character. */
186 next_codepoint(s,&siz);
204 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
206 return NT_STATUS_INVALID_PARAMETER;
209 start_of_name_component = False;
217 /****************************************************************************
218 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
219 No wildcards allowed.
220 ****************************************************************************/
222 NTSTATUS check_path_syntax(char *path)
225 return check_path_syntax_internal(path, False, &ignore);
228 /****************************************************************************
229 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
230 Wildcards allowed - p_contains_wcard returns true if the last component contained
232 ****************************************************************************/
234 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
236 return check_path_syntax_internal(path, False, p_contains_wcard);
239 /****************************************************************************
240 Check the path for a POSIX client.
241 We're assuming here that '/' is not the second byte in any multibyte char
242 set (a safe assumption).
243 ****************************************************************************/
245 NTSTATUS check_path_syntax_posix(char *path)
248 return check_path_syntax_internal(path, True, &ignore);
251 /****************************************************************************
252 Pull a string and check the path allowing a wilcard - provide for error return.
253 ****************************************************************************/
255 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
256 const char *base_ptr,
263 bool *contains_wcard)
269 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
273 *err = NT_STATUS_INVALID_PARAMETER;
277 *contains_wcard = False;
279 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
281 * For a DFS path the function parse_dfs_path()
282 * will do the path processing, just make a copy.
288 if (lp_posix_pathnames()) {
289 *err = check_path_syntax_posix(*pp_dest);
291 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
297 /****************************************************************************
298 Pull a string and check the path - provide for error return.
299 ****************************************************************************/
301 size_t srvstr_get_path(TALLOC_CTX *ctx,
302 const char *base_ptr,
311 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
312 src_len, flags, err, &ignore);
315 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
316 char **pp_dest, const char *src, int flags,
317 NTSTATUS *err, bool *contains_wcard)
319 return srvstr_get_path_wcard(mem_ctx, (const char *)req->inbuf, req->flags2,
320 pp_dest, src, smbreq_bufrem(req, src),
321 flags, err, contains_wcard);
324 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
325 char **pp_dest, const char *src, int flags,
329 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
330 flags, err, &ignore);
333 /****************************************************************************
334 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
335 ****************************************************************************/
337 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
340 if ((fsp == NULL) || (conn == NULL)) {
341 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
344 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
345 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
351 /****************************************************************************
352 Check if we have a correct fsp pointing to a file.
353 ****************************************************************************/
355 bool check_fsp(connection_struct *conn, struct smb_request *req,
358 if (!check_fsp_open(conn, req, fsp)) {
361 if (fsp->is_directory) {
362 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
365 if (fsp->fh->fd == -1) {
366 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
369 fsp->num_smb_operations++;
373 /****************************************************************************
374 Check if we have a correct fsp pointing to a quota fake file. Replacement for
375 the CHECK_NTQUOTA_HANDLE_OK macro.
376 ****************************************************************************/
378 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
381 if (!check_fsp_open(conn, req, fsp)) {
385 if (fsp->is_directory) {
389 if (fsp->fake_file_handle == NULL) {
393 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
397 if (fsp->fake_file_handle->private_data == NULL) {
404 static bool netbios_session_retarget(struct smbd_server_connection *sconn,
405 const char *name, int name_type)
408 char *trim_name_type;
409 const char *retarget_parm;
412 int retarget_type = 0x20;
413 int retarget_port = NBT_SMB_PORT;
414 struct sockaddr_storage retarget_addr;
415 struct sockaddr_in *in_addr;
419 if (get_socket_port(sconn->sock) != NBT_SMB_PORT) {
423 trim_name = talloc_strdup(talloc_tos(), name);
424 if (trim_name == NULL) {
427 trim_char(trim_name, ' ', ' ');
429 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
431 if (trim_name_type == NULL) {
435 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
436 trim_name_type, NULL);
437 if (retarget_parm == NULL) {
438 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
441 if (retarget_parm == NULL) {
445 retarget = talloc_strdup(trim_name, retarget_parm);
446 if (retarget == NULL) {
450 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
452 p = strchr(retarget, ':');
455 retarget_port = atoi(p);
458 p = strchr_m(retarget, '#');
461 if (sscanf(p, "%x", &retarget_type) != 1) {
466 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
468 DEBUG(10, ("could not resolve %s\n", retarget));
472 if (retarget_addr.ss_family != AF_INET) {
473 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
477 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
479 _smb_setlen(outbuf, 6);
480 SCVAL(outbuf, 0, 0x84);
481 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
482 *(uint16_t *)(outbuf+8) = htons(retarget_port);
484 if (!srv_send_smb(sconn, (char *)outbuf, false, 0, false,
486 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
492 TALLOC_FREE(trim_name);
496 static void reply_called_name_not_present(char *outbuf)
498 smb_setlen(outbuf, 1);
499 SCVAL(outbuf, 0, 0x83);
500 SCVAL(outbuf, 4, 0x82);
503 /****************************************************************************
504 Reply to a (netbios-level) special message.
505 ****************************************************************************/
507 void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inbuf_size)
509 int msg_type = CVAL(inbuf,0);
510 int msg_flags = CVAL(inbuf,1);
512 * We only really use 4 bytes of the outbuf, but for the smb_setlen
513 * calculation & friends (srv_send_smb uses that) we need the full smb
516 char outbuf[smb_size];
518 memset(outbuf, '\0', sizeof(outbuf));
520 smb_setlen(outbuf,0);
523 case NBSSrequest: /* session request */
525 /* inbuf_size is guarenteed to be at least 4. */
527 int name_type1, name_type2;
528 int name_len1, name_len2;
532 if (sconn->nbt.got_session) {
533 exit_server_cleanly("multiple session request not permitted");
536 SCVAL(outbuf,0,NBSSpositive);
539 /* inbuf_size is guaranteed to be at least 4. */
540 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
541 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
542 DEBUG(0,("Invalid name length in session request\n"));
543 reply_called_name_not_present(outbuf);
546 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
547 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
548 DEBUG(0,("Invalid name length in session request\n"));
549 reply_called_name_not_present(outbuf);
553 name_type1 = name_extract((unsigned char *)inbuf,
554 inbuf_size,(unsigned int)4,name1);
555 name_type2 = name_extract((unsigned char *)inbuf,
556 inbuf_size,(unsigned int)(4 + name_len1),name2);
558 if (name_type1 == -1 || name_type2 == -1) {
559 DEBUG(0,("Invalid name type in session request\n"));
560 reply_called_name_not_present(outbuf);
564 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
565 name1, name_type1, name2, name_type2));
567 if (netbios_session_retarget(sconn, name1, name_type1)) {
568 exit_server_cleanly("retargeted client");
572 * Windows NT/2k uses "*SMBSERVER" and XP uses
573 * "*SMBSERV" arrggg!!!
575 if (strequal(name1, "*SMBSERVER ")
576 || strequal(name1, "*SMBSERV ")) {
579 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
582 exit_server_cleanly("could not allocate raddr");
585 fstrcpy(name1, raddr);
588 set_local_machine_name(name1, True);
589 set_remote_machine_name(name2, True);
591 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
592 get_local_machine_name(), get_remote_machine_name(),
595 if (name_type2 == 'R') {
596 /* We are being asked for a pathworks session ---
598 reply_called_name_not_present(outbuf);
602 /* only add the client's machine name to the list
603 of possibly valid usernames if we are operating
604 in share mode security */
605 if (lp_security() == SEC_SHARE) {
606 add_session_user(sconn, get_remote_machine_name());
609 reload_services(sconn, conn_snum_used, true);
612 sconn->nbt.got_session = true;
616 case 0x89: /* session keepalive request
617 (some old clients produce this?) */
618 SCVAL(outbuf,0,NBSSkeepalive);
622 case NBSSpositive: /* positive session response */
623 case NBSSnegative: /* negative session response */
624 case NBSSretarget: /* retarget session response */
625 DEBUG(0,("Unexpected session response\n"));
628 case NBSSkeepalive: /* session keepalive */
633 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
634 msg_type, msg_flags));
636 srv_send_smb(sconn, outbuf, false, 0, false, NULL);
638 if (CVAL(outbuf, 0) != 0x82) {
639 exit_server_cleanly("invalid netbios session");
644 /****************************************************************************
646 conn POINTER CAN BE NULL HERE !
647 ****************************************************************************/
649 void reply_tcon(struct smb_request *req)
651 connection_struct *conn = req->conn;
653 char *service_buf = NULL;
654 char *password = NULL;
659 DATA_BLOB password_blob;
660 TALLOC_CTX *ctx = talloc_tos();
661 struct smbd_server_connection *sconn = req->sconn;
663 START_PROFILE(SMBtcon);
665 if (req->buflen < 4) {
666 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
667 END_PROFILE(SMBtcon);
671 p = (const char *)req->buf + 1;
672 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
674 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
676 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
679 if (service_buf == NULL || password == NULL || dev == NULL) {
680 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
681 END_PROFILE(SMBtcon);
684 p = strrchr_m(service_buf,'\\');
688 service = service_buf;
691 password_blob = data_blob(password, pwlen+1);
693 conn = make_connection(sconn,service,password_blob,dev,
694 req->vuid,&nt_status);
697 data_blob_clear_free(&password_blob);
700 reply_nterror(req, nt_status);
701 END_PROFILE(SMBtcon);
705 reply_outbuf(req, 2, 0);
706 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
707 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
708 SSVAL(req->outbuf,smb_tid,conn->cnum);
710 DEBUG(3,("tcon service=%s cnum=%d\n",
711 service, conn->cnum));
713 END_PROFILE(SMBtcon);
717 /****************************************************************************
718 Reply to a tcon and X.
719 conn POINTER CAN BE NULL HERE !
720 ****************************************************************************/
722 void reply_tcon_and_X(struct smb_request *req)
724 connection_struct *conn = req->conn;
725 const char *service = NULL;
727 TALLOC_CTX *ctx = talloc_tos();
728 /* what the cleint thinks the device is */
729 char *client_devicetype = NULL;
730 /* what the server tells the client the share represents */
731 const char *server_devicetype;
737 struct smbd_server_connection *sconn = req->sconn;
739 START_PROFILE(SMBtconX);
742 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
743 END_PROFILE(SMBtconX);
747 passlen = SVAL(req->vwv+3, 0);
748 tcon_flags = SVAL(req->vwv+2, 0);
750 /* we might have to close an old one */
751 if ((tcon_flags & 0x1) && conn) {
752 close_cnum(conn,req->vuid);
757 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
758 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
759 END_PROFILE(SMBtconX);
763 if (sconn->smb1.negprot.encrypted_passwords) {
764 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
765 if (lp_security() == SEC_SHARE) {
767 * Security = share always has a pad byte
768 * after the password.
770 p = (const char *)req->buf + passlen + 1;
772 p = (const char *)req->buf + passlen;
775 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
776 /* Ensure correct termination */
777 password.data[passlen]=0;
778 p = (const char *)req->buf + passlen + 1;
781 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
784 data_blob_clear_free(&password);
785 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
786 END_PROFILE(SMBtconX);
791 * the service name can be either: \\server\share
792 * or share directly like on the DELL PowerVault 705
795 q = strchr_m(path+2,'\\');
797 data_blob_clear_free(&password);
798 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
799 END_PROFILE(SMBtconX);
807 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
808 &client_devicetype, p,
809 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
811 if (client_devicetype == NULL) {
812 data_blob_clear_free(&password);
813 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
814 END_PROFILE(SMBtconX);
818 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
820 conn = make_connection(sconn, service, password, client_devicetype,
821 req->vuid, &nt_status);
824 data_blob_clear_free(&password);
827 reply_nterror(req, nt_status);
828 END_PROFILE(SMBtconX);
833 server_devicetype = "IPC";
834 else if ( IS_PRINT(conn) )
835 server_devicetype = "LPT1:";
837 server_devicetype = "A:";
839 if (get_Protocol() < PROTOCOL_NT1) {
840 reply_outbuf(req, 2, 0);
841 if (message_push_string(&req->outbuf, server_devicetype,
842 STR_TERMINATE|STR_ASCII) == -1) {
843 reply_nterror(req, NT_STATUS_NO_MEMORY);
844 END_PROFILE(SMBtconX);
848 /* NT sets the fstype of IPC$ to the null string */
849 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
851 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
852 /* Return permissions. */
856 reply_outbuf(req, 7, 0);
859 perm1 = FILE_ALL_ACCESS;
860 perm2 = FILE_ALL_ACCESS;
862 perm1 = conn->share_access;
865 SIVAL(req->outbuf, smb_vwv3, perm1);
866 SIVAL(req->outbuf, smb_vwv5, perm2);
868 reply_outbuf(req, 3, 0);
871 if ((message_push_string(&req->outbuf, server_devicetype,
872 STR_TERMINATE|STR_ASCII) == -1)
873 || (message_push_string(&req->outbuf, fstype,
874 STR_TERMINATE) == -1)) {
875 reply_nterror(req, NT_STATUS_NO_MEMORY);
876 END_PROFILE(SMBtconX);
880 /* what does setting this bit do? It is set by NT4 and
881 may affect the ability to autorun mounted cdroms */
882 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
883 (lp_csc_policy(SNUM(conn)) << 2));
885 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
886 DEBUG(2,("Serving %s as a Dfs root\n",
887 lp_servicename(SNUM(conn)) ));
888 SSVAL(req->outbuf, smb_vwv2,
889 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
894 DEBUG(3,("tconX service=%s \n",
897 /* set the incoming and outgoing tid to the just created one */
898 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
899 SSVAL(req->outbuf,smb_tid,conn->cnum);
901 END_PROFILE(SMBtconX);
903 req->tid = conn->cnum;
908 /****************************************************************************
909 Reply to an unknown type.
910 ****************************************************************************/
912 void reply_unknown_new(struct smb_request *req, uint8 type)
914 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
915 smb_fn_name(type), type, type));
916 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
920 /****************************************************************************
922 conn POINTER CAN BE NULL HERE !
923 ****************************************************************************/
925 void reply_ioctl(struct smb_request *req)
927 connection_struct *conn = req->conn;
934 START_PROFILE(SMBioctl);
937 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
938 END_PROFILE(SMBioctl);
942 device = SVAL(req->vwv+1, 0);
943 function = SVAL(req->vwv+2, 0);
944 ioctl_code = (device << 16) + function;
946 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
948 switch (ioctl_code) {
949 case IOCTL_QUERY_JOB_INFO:
953 reply_force_doserror(req, ERRSRV, ERRnosupport);
954 END_PROFILE(SMBioctl);
958 reply_outbuf(req, 8, replysize+1);
959 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
960 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
961 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
962 p = smb_buf(req->outbuf);
963 memset(p, '\0', replysize+1); /* valgrind-safe. */
964 p += 1; /* Allow for alignment */
966 switch (ioctl_code) {
967 case IOCTL_QUERY_JOB_INFO:
969 files_struct *fsp = file_fsp(
970 req, SVAL(req->vwv+0, 0));
972 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
973 END_PROFILE(SMBioctl);
977 if (fsp->print_file) {
978 SSVAL(p, 0, fsp->print_file->rap_jobid);
982 srvstr_push((char *)req->outbuf, req->flags2, p+2,
983 lp_netbios_name(), 15,
984 STR_TERMINATE|STR_ASCII);
986 srvstr_push((char *)req->outbuf, req->flags2,
987 p+18, lp_servicename(SNUM(conn)),
988 13, STR_TERMINATE|STR_ASCII);
996 END_PROFILE(SMBioctl);
1000 /****************************************************************************
1001 Strange checkpath NTSTATUS mapping.
1002 ****************************************************************************/
1004 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1006 /* Strange DOS error code semantics only for checkpath... */
1007 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1008 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1009 /* We need to map to ERRbadpath */
1010 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1016 /****************************************************************************
1017 Reply to a checkpath.
1018 ****************************************************************************/
1020 void reply_checkpath(struct smb_request *req)
1022 connection_struct *conn = req->conn;
1023 struct smb_filename *smb_fname = NULL;
1026 TALLOC_CTX *ctx = talloc_tos();
1028 START_PROFILE(SMBcheckpath);
1030 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1031 STR_TERMINATE, &status);
1033 if (!NT_STATUS_IS_OK(status)) {
1034 status = map_checkpath_error(req->flags2, status);
1035 reply_nterror(req, status);
1036 END_PROFILE(SMBcheckpath);
1040 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1042 status = filename_convert(ctx,
1044 req->flags2 & FLAGS2_DFS_PATHNAMES,
1050 if (!NT_STATUS_IS_OK(status)) {
1051 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1052 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1053 ERRSRV, ERRbadpath);
1054 END_PROFILE(SMBcheckpath);
1060 if (!VALID_STAT(smb_fname->st) &&
1061 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1062 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1063 smb_fname_str_dbg(smb_fname), strerror(errno)));
1064 status = map_nt_error_from_unix(errno);
1068 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1069 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1070 ERRDOS, ERRbadpath);
1074 reply_outbuf(req, 0, 0);
1077 /* We special case this - as when a Windows machine
1078 is parsing a path is steps through the components
1079 one at a time - if a component fails it expects
1080 ERRbadpath, not ERRbadfile.
1082 status = map_checkpath_error(req->flags2, status);
1083 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1085 * Windows returns different error codes if
1086 * the parent directory is valid but not the
1087 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1088 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1089 * if the path is invalid.
1091 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1092 ERRDOS, ERRbadpath);
1096 reply_nterror(req, status);
1099 TALLOC_FREE(smb_fname);
1100 END_PROFILE(SMBcheckpath);
1104 /****************************************************************************
1106 ****************************************************************************/
1108 void reply_getatr(struct smb_request *req)
1110 connection_struct *conn = req->conn;
1111 struct smb_filename *smb_fname = NULL;
1118 TALLOC_CTX *ctx = talloc_tos();
1119 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1121 START_PROFILE(SMBgetatr);
1123 p = (const char *)req->buf + 1;
1124 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1125 if (!NT_STATUS_IS_OK(status)) {
1126 reply_nterror(req, status);
1130 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1131 under WfWg - weird! */
1132 if (*fname == '\0') {
1133 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1134 if (!CAN_WRITE(conn)) {
1135 mode |= FILE_ATTRIBUTE_READONLY;
1140 status = filename_convert(ctx,
1142 req->flags2 & FLAGS2_DFS_PATHNAMES,
1147 if (!NT_STATUS_IS_OK(status)) {
1148 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1149 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1150 ERRSRV, ERRbadpath);
1153 reply_nterror(req, status);
1156 if (!VALID_STAT(smb_fname->st) &&
1157 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1158 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1159 smb_fname_str_dbg(smb_fname),
1161 reply_nterror(req, map_nt_error_from_unix(errno));
1165 mode = dos_mode(conn, smb_fname);
1166 size = smb_fname->st.st_ex_size;
1168 if (ask_sharemode) {
1169 struct timespec write_time_ts;
1170 struct file_id fileid;
1172 ZERO_STRUCT(write_time_ts);
1173 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1174 get_file_infos(fileid, 0, NULL, &write_time_ts);
1175 if (!null_timespec(write_time_ts)) {
1176 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1180 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1181 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1186 reply_outbuf(req, 10, 0);
1188 SSVAL(req->outbuf,smb_vwv0,mode);
1189 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1190 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1192 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1194 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1196 if (get_Protocol() >= PROTOCOL_NT1) {
1197 SSVAL(req->outbuf, smb_flg2,
1198 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1201 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1202 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1205 TALLOC_FREE(smb_fname);
1207 END_PROFILE(SMBgetatr);
1211 /****************************************************************************
1213 ****************************************************************************/
1215 void reply_setatr(struct smb_request *req)
1217 struct smb_file_time ft;
1218 connection_struct *conn = req->conn;
1219 struct smb_filename *smb_fname = NULL;
1225 TALLOC_CTX *ctx = talloc_tos();
1227 START_PROFILE(SMBsetatr);
1232 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1236 p = (const char *)req->buf + 1;
1237 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1238 if (!NT_STATUS_IS_OK(status)) {
1239 reply_nterror(req, status);
1243 status = filename_convert(ctx,
1245 req->flags2 & FLAGS2_DFS_PATHNAMES,
1250 if (!NT_STATUS_IS_OK(status)) {
1251 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1252 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1253 ERRSRV, ERRbadpath);
1256 reply_nterror(req, status);
1260 if (smb_fname->base_name[0] == '.' &&
1261 smb_fname->base_name[1] == '\0') {
1263 * Not sure here is the right place to catch this
1264 * condition. Might be moved to somewhere else later -- vl
1266 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1270 mode = SVAL(req->vwv+0, 0);
1271 mtime = srv_make_unix_date3(req->vwv+1);
1273 if (mode != FILE_ATTRIBUTE_NORMAL) {
1274 if (VALID_STAT_OF_DIR(smb_fname->st))
1275 mode |= FILE_ATTRIBUTE_DIRECTORY;
1277 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1279 status = check_access(conn, NULL, smb_fname,
1280 FILE_WRITE_ATTRIBUTES);
1281 if (!NT_STATUS_IS_OK(status)) {
1282 reply_nterror(req, status);
1286 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1288 reply_nterror(req, map_nt_error_from_unix(errno));
1293 ft.mtime = convert_time_t_to_timespec(mtime);
1294 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1295 if (!NT_STATUS_IS_OK(status)) {
1296 reply_nterror(req, status);
1300 reply_outbuf(req, 0, 0);
1302 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1305 TALLOC_FREE(smb_fname);
1306 END_PROFILE(SMBsetatr);
1310 /****************************************************************************
1312 ****************************************************************************/
1314 void reply_dskattr(struct smb_request *req)
1316 connection_struct *conn = req->conn;
1317 uint64_t dfree,dsize,bsize;
1318 START_PROFILE(SMBdskattr);
1320 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1321 reply_nterror(req, map_nt_error_from_unix(errno));
1322 END_PROFILE(SMBdskattr);
1326 reply_outbuf(req, 5, 0);
1328 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1329 double total_space, free_space;
1330 /* we need to scale this to a number that DOS6 can handle. We
1331 use floating point so we can handle large drives on systems
1332 that don't have 64 bit integers
1334 we end up displaying a maximum of 2G to DOS systems
1336 total_space = dsize * (double)bsize;
1337 free_space = dfree * (double)bsize;
1339 dsize = (uint64_t)((total_space+63*512) / (64*512));
1340 dfree = (uint64_t)((free_space+63*512) / (64*512));
1342 if (dsize > 0xFFFF) dsize = 0xFFFF;
1343 if (dfree > 0xFFFF) dfree = 0xFFFF;
1345 SSVAL(req->outbuf,smb_vwv0,dsize);
1346 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1347 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1348 SSVAL(req->outbuf,smb_vwv3,dfree);
1350 SSVAL(req->outbuf,smb_vwv0,dsize);
1351 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1352 SSVAL(req->outbuf,smb_vwv2,512);
1353 SSVAL(req->outbuf,smb_vwv3,dfree);
1356 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1358 END_PROFILE(SMBdskattr);
1363 * Utility function to split the filename from the directory.
1365 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1366 char **fname_dir_out,
1367 char **fname_mask_out)
1369 const char *p = NULL;
1370 char *fname_dir = NULL;
1371 char *fname_mask = NULL;
1373 p = strrchr_m(fname_in, '/');
1375 fname_dir = talloc_strdup(ctx, ".");
1376 fname_mask = talloc_strdup(ctx, fname_in);
1378 fname_dir = talloc_strndup(ctx, fname_in,
1379 PTR_DIFF(p, fname_in));
1380 fname_mask = talloc_strdup(ctx, p+1);
1383 if (!fname_dir || !fname_mask) {
1384 TALLOC_FREE(fname_dir);
1385 TALLOC_FREE(fname_mask);
1386 return NT_STATUS_NO_MEMORY;
1389 *fname_dir_out = fname_dir;
1390 *fname_mask_out = fname_mask;
1391 return NT_STATUS_OK;
1394 /****************************************************************************
1396 Can be called from SMBsearch, SMBffirst or SMBfunique.
1397 ****************************************************************************/
1399 void reply_search(struct smb_request *req)
1401 connection_struct *conn = req->conn;
1403 const char *mask = NULL;
1404 char *directory = NULL;
1405 struct smb_filename *smb_fname = NULL;
1409 struct timespec date;
1411 unsigned int numentries = 0;
1412 unsigned int maxentries = 0;
1413 bool finished = False;
1418 bool check_descend = False;
1419 bool expect_close = False;
1421 bool mask_contains_wcard = False;
1422 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1423 TALLOC_CTX *ctx = talloc_tos();
1424 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1425 struct dptr_struct *dirptr = NULL;
1426 struct smbd_server_connection *sconn = req->sconn;
1428 START_PROFILE(SMBsearch);
1431 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1435 if (lp_posix_pathnames()) {
1436 reply_unknown_new(req, req->cmd);
1440 /* If we were called as SMBffirst then we must expect close. */
1441 if(req->cmd == SMBffirst) {
1442 expect_close = True;
1445 reply_outbuf(req, 1, 3);
1446 maxentries = SVAL(req->vwv+0, 0);
1447 dirtype = SVAL(req->vwv+1, 0);
1448 p = (const char *)req->buf + 1;
1449 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1450 &nt_status, &mask_contains_wcard);
1451 if (!NT_STATUS_IS_OK(nt_status)) {
1452 reply_nterror(req, nt_status);
1457 status_len = SVAL(p, 0);
1460 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1462 if (status_len == 0) {
1463 nt_status = filename_convert(ctx, conn,
1464 req->flags2 & FLAGS2_DFS_PATHNAMES,
1466 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1467 &mask_contains_wcard,
1469 if (!NT_STATUS_IS_OK(nt_status)) {
1470 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1471 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1472 ERRSRV, ERRbadpath);
1475 reply_nterror(req, nt_status);
1479 directory = smb_fname->base_name;
1481 p = strrchr_m(directory,'/');
1482 if ((p != NULL) && (*directory != '/')) {
1484 directory = talloc_strndup(ctx, directory,
1485 PTR_DIFF(p, directory));
1488 directory = talloc_strdup(ctx,".");
1492 reply_nterror(req, NT_STATUS_NO_MEMORY);
1496 memset((char *)status,'\0',21);
1497 SCVAL(status,0,(dirtype & 0x1F));
1499 nt_status = dptr_create(conn,
1507 mask_contains_wcard,
1510 if (!NT_STATUS_IS_OK(nt_status)) {
1511 reply_nterror(req, nt_status);
1514 dptr_num = dptr_dnum(dirptr);
1517 const char *dirpath;
1519 memcpy(status,p,21);
1520 status_dirtype = CVAL(status,0) & 0x1F;
1521 if (status_dirtype != (dirtype & 0x1F)) {
1522 dirtype = status_dirtype;
1525 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1529 dirpath = dptr_path(sconn, dptr_num);
1530 directory = talloc_strdup(ctx, dirpath);
1532 reply_nterror(req, NT_STATUS_NO_MEMORY);
1536 mask = dptr_wcard(sconn, dptr_num);
1541 * For a 'continue' search we have no string. So
1542 * check from the initial saved string.
1544 mask_contains_wcard = ms_has_wild(mask);
1545 dirtype = dptr_attr(sconn, dptr_num);
1548 DEBUG(4,("dptr_num is %d\n",dptr_num));
1550 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1551 dptr_init_search_op(dirptr);
1553 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1554 char buf[DIR_STRUCT_SIZE];
1555 memcpy(buf,status,21);
1556 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1557 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1558 reply_nterror(req, NT_STATUS_NO_MEMORY);
1561 dptr_fill(sconn, buf+12,dptr_num);
1562 if (dptr_zero(buf+12) && (status_len==0)) {
1567 if (message_push_blob(&req->outbuf,
1568 data_blob_const(buf, sizeof(buf)))
1570 reply_nterror(req, NT_STATUS_NO_MEMORY);
1578 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1581 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1582 directory,lp_dontdescend(SNUM(conn))));
1583 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1584 check_descend = True;
1587 for (i=numentries;(i<maxentries) && !finished;i++) {
1588 finished = !get_dir_entry(ctx,
1599 char buf[DIR_STRUCT_SIZE];
1600 memcpy(buf,status,21);
1601 if (!make_dir_struct(ctx,
1607 convert_timespec_to_time_t(date),
1608 !allow_long_path_components)) {
1609 reply_nterror(req, NT_STATUS_NO_MEMORY);
1612 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1615 if (message_push_blob(&req->outbuf,
1616 data_blob_const(buf, sizeof(buf)))
1618 reply_nterror(req, NT_STATUS_NO_MEMORY);
1628 /* If we were called as SMBffirst with smb_search_id == NULL
1629 and no entries were found then return error and close dirptr
1632 if (numentries == 0) {
1633 dptr_close(sconn, &dptr_num);
1634 } else if(expect_close && status_len == 0) {
1635 /* Close the dptr - we know it's gone */
1636 dptr_close(sconn, &dptr_num);
1639 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1640 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1641 dptr_close(sconn, &dptr_num);
1644 if ((numentries == 0) && !mask_contains_wcard) {
1645 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1649 SSVAL(req->outbuf,smb_vwv0,numentries);
1650 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1651 SCVAL(smb_buf(req->outbuf),0,5);
1652 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1654 /* The replies here are never long name. */
1655 SSVAL(req->outbuf, smb_flg2,
1656 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1657 if (!allow_long_path_components) {
1658 SSVAL(req->outbuf, smb_flg2,
1659 SVAL(req->outbuf, smb_flg2)
1660 & (~FLAGS2_LONG_PATH_COMPONENTS));
1663 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1664 SSVAL(req->outbuf, smb_flg2,
1665 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1667 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1668 smb_fn_name(req->cmd),
1675 TALLOC_FREE(directory);
1676 TALLOC_FREE(smb_fname);
1677 END_PROFILE(SMBsearch);
1681 /****************************************************************************
1682 Reply to a fclose (stop directory search).
1683 ****************************************************************************/
1685 void reply_fclose(struct smb_request *req)
1693 bool path_contains_wcard = False;
1694 TALLOC_CTX *ctx = talloc_tos();
1695 struct smbd_server_connection *sconn = req->sconn;
1697 START_PROFILE(SMBfclose);
1699 if (lp_posix_pathnames()) {
1700 reply_unknown_new(req, req->cmd);
1701 END_PROFILE(SMBfclose);
1705 p = (const char *)req->buf + 1;
1706 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1707 &err, &path_contains_wcard);
1708 if (!NT_STATUS_IS_OK(err)) {
1709 reply_nterror(req, err);
1710 END_PROFILE(SMBfclose);
1714 status_len = SVAL(p,0);
1717 if (status_len == 0) {
1718 reply_force_doserror(req, ERRSRV, ERRsrverror);
1719 END_PROFILE(SMBfclose);
1723 memcpy(status,p,21);
1725 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1726 /* Close the dptr - we know it's gone */
1727 dptr_close(sconn, &dptr_num);
1730 reply_outbuf(req, 1, 0);
1731 SSVAL(req->outbuf,smb_vwv0,0);
1733 DEBUG(3,("search close\n"));
1735 END_PROFILE(SMBfclose);
1739 /****************************************************************************
1741 ****************************************************************************/
1743 void reply_open(struct smb_request *req)
1745 connection_struct *conn = req->conn;
1746 struct smb_filename *smb_fname = NULL;
1758 uint32 create_disposition;
1759 uint32 create_options = 0;
1760 uint32_t private_flags = 0;
1762 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1763 TALLOC_CTX *ctx = talloc_tos();
1765 START_PROFILE(SMBopen);
1768 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1772 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1773 deny_mode = SVAL(req->vwv+0, 0);
1774 dos_attr = SVAL(req->vwv+1, 0);
1776 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1777 STR_TERMINATE, &status);
1778 if (!NT_STATUS_IS_OK(status)) {
1779 reply_nterror(req, status);
1783 status = filename_convert(ctx,
1785 req->flags2 & FLAGS2_DFS_PATHNAMES,
1790 if (!NT_STATUS_IS_OK(status)) {
1791 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1792 reply_botherror(req,
1793 NT_STATUS_PATH_NOT_COVERED,
1794 ERRSRV, ERRbadpath);
1797 reply_nterror(req, status);
1801 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1802 OPENX_FILE_EXISTS_OPEN, &access_mask,
1803 &share_mode, &create_disposition,
1804 &create_options, &private_flags)) {
1805 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1809 status = SMB_VFS_CREATE_FILE(
1812 0, /* root_dir_fid */
1813 smb_fname, /* fname */
1814 access_mask, /* access_mask */
1815 share_mode, /* share_access */
1816 create_disposition, /* create_disposition*/
1817 create_options, /* create_options */
1818 dos_attr, /* file_attributes */
1819 oplock_request, /* oplock_request */
1820 0, /* allocation_size */
1827 if (!NT_STATUS_IS_OK(status)) {
1828 if (open_was_deferred(req->sconn, req->mid)) {
1829 /* We have re-scheduled this call. */
1832 reply_openerror(req, status);
1836 size = smb_fname->st.st_ex_size;
1837 fattr = dos_mode(conn, smb_fname);
1839 /* Deal with other possible opens having a modified
1841 if (ask_sharemode) {
1842 struct timespec write_time_ts;
1844 ZERO_STRUCT(write_time_ts);
1845 get_file_infos(fsp->file_id, 0, NULL, &write_time_ts);
1846 if (!null_timespec(write_time_ts)) {
1847 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1851 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1853 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1854 DEBUG(3,("attempt to open a directory %s\n",
1856 close_file(req, fsp, ERROR_CLOSE);
1857 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1858 ERRDOS, ERRnoaccess);
1862 reply_outbuf(req, 7, 0);
1863 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1864 SSVAL(req->outbuf,smb_vwv1,fattr);
1865 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1866 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1868 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1870 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1871 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1873 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1874 SCVAL(req->outbuf,smb_flg,
1875 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1878 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1879 SCVAL(req->outbuf,smb_flg,
1880 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1883 TALLOC_FREE(smb_fname);
1884 END_PROFILE(SMBopen);
1888 /****************************************************************************
1889 Reply to an open and X.
1890 ****************************************************************************/
1892 void reply_open_and_X(struct smb_request *req)
1894 connection_struct *conn = req->conn;
1895 struct smb_filename *smb_fname = NULL;
1900 /* Breakout the oplock request bits so we can set the
1901 reply bits separately. */
1902 int ex_oplock_request;
1903 int core_oplock_request;
1906 int smb_sattr = SVAL(req->vwv+4, 0);
1907 uint32 smb_time = make_unix_date3(req->vwv+6);
1915 uint64_t allocation_size;
1916 ssize_t retval = -1;
1919 uint32 create_disposition;
1920 uint32 create_options = 0;
1921 uint32_t private_flags = 0;
1922 TALLOC_CTX *ctx = talloc_tos();
1924 START_PROFILE(SMBopenX);
1926 if (req->wct < 15) {
1927 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1931 open_flags = SVAL(req->vwv+2, 0);
1932 deny_mode = SVAL(req->vwv+3, 0);
1933 smb_attr = SVAL(req->vwv+5, 0);
1934 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1935 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1936 oplock_request = ex_oplock_request | core_oplock_request;
1937 smb_ofun = SVAL(req->vwv+8, 0);
1938 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1940 /* If it's an IPC, pass off the pipe handler. */
1942 if (lp_nt_pipe_support()) {
1943 reply_open_pipe_and_X(conn, req);
1945 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1950 /* XXXX we need to handle passed times, sattr and flags */
1951 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1952 STR_TERMINATE, &status);
1953 if (!NT_STATUS_IS_OK(status)) {
1954 reply_nterror(req, status);
1958 status = filename_convert(ctx,
1960 req->flags2 & FLAGS2_DFS_PATHNAMES,
1965 if (!NT_STATUS_IS_OK(status)) {
1966 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1967 reply_botherror(req,
1968 NT_STATUS_PATH_NOT_COVERED,
1969 ERRSRV, ERRbadpath);
1972 reply_nterror(req, status);
1976 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1978 &access_mask, &share_mode,
1979 &create_disposition,
1982 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1986 status = SMB_VFS_CREATE_FILE(
1989 0, /* root_dir_fid */
1990 smb_fname, /* fname */
1991 access_mask, /* access_mask */
1992 share_mode, /* share_access */
1993 create_disposition, /* create_disposition*/
1994 create_options, /* create_options */
1995 smb_attr, /* file_attributes */
1996 oplock_request, /* oplock_request */
1997 0, /* allocation_size */
2002 &smb_action); /* pinfo */
2004 if (!NT_STATUS_IS_OK(status)) {
2005 if (open_was_deferred(req->sconn, req->mid)) {
2006 /* We have re-scheduled this call. */
2009 reply_openerror(req, status);
2013 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2014 if the file is truncated or created. */
2015 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2016 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2017 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2018 close_file(req, fsp, ERROR_CLOSE);
2019 reply_nterror(req, NT_STATUS_DISK_FULL);
2022 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
2024 close_file(req, fsp, ERROR_CLOSE);
2025 reply_nterror(req, NT_STATUS_DISK_FULL);
2028 status = vfs_stat_fsp(fsp);
2029 if (!NT_STATUS_IS_OK(status)) {
2030 close_file(req, fsp, ERROR_CLOSE);
2031 reply_nterror(req, status);
2036 fattr = dos_mode(conn, fsp->fsp_name);
2037 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2038 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2039 close_file(req, fsp, ERROR_CLOSE);
2040 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2044 /* If the caller set the extended oplock request bit
2045 and we granted one (by whatever means) - set the
2046 correct bit for extended oplock reply.
2049 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2050 smb_action |= EXTENDED_OPLOCK_GRANTED;
2053 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2054 smb_action |= EXTENDED_OPLOCK_GRANTED;
2057 /* If the caller set the core oplock request bit
2058 and we granted one (by whatever means) - set the
2059 correct bit for core oplock reply.
2062 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2063 reply_outbuf(req, 19, 0);
2065 reply_outbuf(req, 15, 0);
2068 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2069 SCVAL(req->outbuf, smb_flg,
2070 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2073 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2074 SCVAL(req->outbuf, smb_flg,
2075 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2078 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2079 SSVAL(req->outbuf,smb_vwv3,fattr);
2080 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2081 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2083 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2085 SIVAL(req->outbuf,smb_vwv6,(uint32)fsp->fsp_name->st.st_ex_size);
2086 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2087 SSVAL(req->outbuf,smb_vwv11,smb_action);
2089 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2090 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2095 TALLOC_FREE(smb_fname);
2096 END_PROFILE(SMBopenX);
2100 /****************************************************************************
2101 Reply to a SMBulogoffX.
2102 ****************************************************************************/
2104 void reply_ulogoffX(struct smb_request *req)
2106 struct smbd_server_connection *sconn = req->sconn;
2109 START_PROFILE(SMBulogoffX);
2111 vuser = get_valid_user_struct(sconn, req->vuid);
2114 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2118 /* in user level security we are supposed to close any files
2119 open by this user */
2120 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2121 file_close_user(sconn, req->vuid);
2124 invalidate_vuid(sconn, req->vuid);
2126 reply_outbuf(req, 2, 0);
2128 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2130 END_PROFILE(SMBulogoffX);
2131 req->vuid = UID_FIELD_INVALID;
2135 /****************************************************************************
2136 Reply to a mknew or a create.
2137 ****************************************************************************/
2139 void reply_mknew(struct smb_request *req)
2141 connection_struct *conn = req->conn;
2142 struct smb_filename *smb_fname = NULL;
2145 struct smb_file_time ft;
2147 int oplock_request = 0;
2149 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2150 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2151 uint32 create_disposition;
2152 uint32 create_options = 0;
2153 TALLOC_CTX *ctx = talloc_tos();
2155 START_PROFILE(SMBcreate);
2159 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2163 fattr = SVAL(req->vwv+0, 0);
2164 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2167 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2169 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2170 STR_TERMINATE, &status);
2171 if (!NT_STATUS_IS_OK(status)) {
2172 reply_nterror(req, status);
2176 status = filename_convert(ctx,
2178 req->flags2 & FLAGS2_DFS_PATHNAMES,
2183 if (!NT_STATUS_IS_OK(status)) {
2184 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2185 reply_botherror(req,
2186 NT_STATUS_PATH_NOT_COVERED,
2187 ERRSRV, ERRbadpath);
2190 reply_nterror(req, status);
2194 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2195 DEBUG(0,("Attempt to create file (%s) with volid set - "
2196 "please report this\n",
2197 smb_fname_str_dbg(smb_fname)));
2200 if(req->cmd == SMBmknew) {
2201 /* We should fail if file exists. */
2202 create_disposition = FILE_CREATE;
2204 /* Create if file doesn't exist, truncate if it does. */
2205 create_disposition = FILE_OVERWRITE_IF;
2208 status = SMB_VFS_CREATE_FILE(
2211 0, /* root_dir_fid */
2212 smb_fname, /* fname */
2213 access_mask, /* access_mask */
2214 share_mode, /* share_access */
2215 create_disposition, /* create_disposition*/
2216 create_options, /* create_options */
2217 fattr, /* file_attributes */
2218 oplock_request, /* oplock_request */
2219 0, /* allocation_size */
2220 0, /* private_flags */
2226 if (!NT_STATUS_IS_OK(status)) {
2227 if (open_was_deferred(req->sconn, req->mid)) {
2228 /* We have re-scheduled this call. */
2231 reply_openerror(req, status);
2235 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2236 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2237 if (!NT_STATUS_IS_OK(status)) {
2238 END_PROFILE(SMBcreate);
2242 reply_outbuf(req, 1, 0);
2243 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2245 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2246 SCVAL(req->outbuf,smb_flg,
2247 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2250 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2251 SCVAL(req->outbuf,smb_flg,
2252 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2255 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2256 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2257 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2258 (unsigned int)fattr));
2261 TALLOC_FREE(smb_fname);
2262 END_PROFILE(SMBcreate);
2266 /****************************************************************************
2267 Reply to a create temporary file.
2268 ****************************************************************************/
2270 void reply_ctemp(struct smb_request *req)
2272 connection_struct *conn = req->conn;
2273 struct smb_filename *smb_fname = NULL;
2281 TALLOC_CTX *ctx = talloc_tos();
2283 START_PROFILE(SMBctemp);
2286 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2290 fattr = SVAL(req->vwv+0, 0);
2291 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2293 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2294 STR_TERMINATE, &status);
2295 if (!NT_STATUS_IS_OK(status)) {
2296 reply_nterror(req, status);
2300 fname = talloc_asprintf(ctx,
2304 fname = talloc_strdup(ctx, "TMXXXXXX");
2308 reply_nterror(req, NT_STATUS_NO_MEMORY);
2312 status = filename_convert(ctx, conn,
2313 req->flags2 & FLAGS2_DFS_PATHNAMES,
2318 if (!NT_STATUS_IS_OK(status)) {
2319 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2320 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2321 ERRSRV, ERRbadpath);
2324 reply_nterror(req, status);
2328 tmpfd = mkstemp(smb_fname->base_name);
2330 reply_nterror(req, map_nt_error_from_unix(errno));
2334 SMB_VFS_STAT(conn, smb_fname);
2336 /* We should fail if file does not exist. */
2337 status = SMB_VFS_CREATE_FILE(
2340 0, /* root_dir_fid */
2341 smb_fname, /* fname */
2342 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2343 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2344 FILE_OPEN, /* create_disposition*/
2345 0, /* create_options */
2346 fattr, /* file_attributes */
2347 oplock_request, /* oplock_request */
2348 0, /* allocation_size */
2349 0, /* private_flags */
2355 /* close fd from mkstemp() */
2358 if (!NT_STATUS_IS_OK(status)) {
2359 if (open_was_deferred(req->sconn, req->mid)) {
2360 /* We have re-scheduled this call. */
2363 reply_openerror(req, status);
2367 reply_outbuf(req, 1, 0);
2368 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2370 /* the returned filename is relative to the directory */
2371 s = strrchr_m(fsp->fsp_name->base_name, '/');
2373 s = fsp->fsp_name->base_name;
2379 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2380 thing in the byte section. JRA */
2381 SSVALS(p, 0, -1); /* what is this? not in spec */
2383 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2385 reply_nterror(req, NT_STATUS_NO_MEMORY);
2389 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2390 SCVAL(req->outbuf, smb_flg,
2391 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2394 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2395 SCVAL(req->outbuf, smb_flg,
2396 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2399 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2400 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2401 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2403 TALLOC_FREE(smb_fname);
2404 END_PROFILE(SMBctemp);
2408 /*******************************************************************
2409 Check if a user is allowed to rename a file.
2410 ********************************************************************/
2412 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2415 if (!CAN_WRITE(conn)) {
2416 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2419 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2420 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2421 /* Only bother to read the DOS attribute if we might deny the
2422 rename on the grounds of attribute missmatch. */
2423 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2424 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2425 return NT_STATUS_NO_SUCH_FILE;
2429 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2430 if (fsp->posix_open) {
2431 return NT_STATUS_OK;
2434 /* If no pathnames are open below this
2435 directory, allow the rename. */
2437 if (file_find_subpath(fsp)) {
2438 return NT_STATUS_ACCESS_DENIED;
2440 return NT_STATUS_OK;
2443 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2444 return NT_STATUS_OK;
2447 return NT_STATUS_ACCESS_DENIED;
2450 /*******************************************************************
2451 * unlink a file with all relevant access checks
2452 *******************************************************************/
2454 static NTSTATUS do_unlink(connection_struct *conn,
2455 struct smb_request *req,
2456 struct smb_filename *smb_fname,
2461 uint32 dirtype_orig = dirtype;
2464 bool posix_paths = lp_posix_pathnames();
2466 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2467 smb_fname_str_dbg(smb_fname),
2470 if (!CAN_WRITE(conn)) {
2471 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2475 ret = SMB_VFS_LSTAT(conn, smb_fname);
2477 ret = SMB_VFS_STAT(conn, smb_fname);
2480 return map_nt_error_from_unix(errno);
2483 fattr = dos_mode(conn, smb_fname);
2485 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2486 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2489 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2491 return NT_STATUS_NO_SUCH_FILE;
2494 if (!dir_check_ftype(conn, fattr, dirtype)) {
2495 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2496 return NT_STATUS_FILE_IS_A_DIRECTORY;
2498 return NT_STATUS_NO_SUCH_FILE;
2501 if (dirtype_orig & 0x8000) {
2502 /* These will never be set for POSIX. */
2503 return NT_STATUS_NO_SUCH_FILE;
2507 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2508 return NT_STATUS_FILE_IS_A_DIRECTORY;
2511 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2512 return NT_STATUS_NO_SUCH_FILE;
2515 if (dirtype & 0xFF00) {
2516 /* These will never be set for POSIX. */
2517 return NT_STATUS_NO_SUCH_FILE;
2522 return NT_STATUS_NO_SUCH_FILE;
2525 /* Can't delete a directory. */
2526 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2527 return NT_STATUS_FILE_IS_A_DIRECTORY;
2532 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2533 return NT_STATUS_OBJECT_NAME_INVALID;
2534 #endif /* JRATEST */
2536 /* On open checks the open itself will check the share mode, so
2537 don't do it here as we'll get it wrong. */
2539 status = SMB_VFS_CREATE_FILE
2542 0, /* root_dir_fid */
2543 smb_fname, /* fname */
2544 DELETE_ACCESS, /* access_mask */
2545 FILE_SHARE_NONE, /* share_access */
2546 FILE_OPEN, /* create_disposition*/
2547 FILE_NON_DIRECTORY_FILE, /* create_options */
2548 /* file_attributes */
2549 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2550 FILE_ATTRIBUTE_NORMAL,
2551 0, /* oplock_request */
2552 0, /* allocation_size */
2553 0, /* private_flags */
2559 if (!NT_STATUS_IS_OK(status)) {
2560 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2561 nt_errstr(status)));
2565 status = can_set_delete_on_close(fsp, fattr);
2566 if (!NT_STATUS_IS_OK(status)) {
2567 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2569 smb_fname_str_dbg(smb_fname),
2570 nt_errstr(status)));
2571 close_file(req, fsp, NORMAL_CLOSE);
2575 /* The set is across all open files on this dev/inode pair. */
2576 if (!set_delete_on_close(fsp, True, conn->session_info->unix_token)) {
2577 close_file(req, fsp, NORMAL_CLOSE);
2578 return NT_STATUS_ACCESS_DENIED;
2581 return close_file(req, fsp, NORMAL_CLOSE);
2584 /****************************************************************************
2585 The guts of the unlink command, split out so it may be called by the NT SMB
2587 ****************************************************************************/
2589 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2590 uint32 dirtype, struct smb_filename *smb_fname,
2593 char *fname_dir = NULL;
2594 char *fname_mask = NULL;
2596 NTSTATUS status = NT_STATUS_OK;
2597 TALLOC_CTX *ctx = talloc_tos();
2599 /* Split up the directory from the filename/mask. */
2600 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2601 &fname_dir, &fname_mask);
2602 if (!NT_STATUS_IS_OK(status)) {
2607 * We should only check the mangled cache
2608 * here if unix_convert failed. This means
2609 * that the path in 'mask' doesn't exist
2610 * on the file system and so we need to look
2611 * for a possible mangle. This patch from
2612 * Tine Smukavec <valentin.smukavec@hermes.si>.
2615 if (!VALID_STAT(smb_fname->st) &&
2616 mangle_is_mangled(fname_mask, conn->params)) {
2617 char *new_mask = NULL;
2618 mangle_lookup_name_from_8_3(ctx, fname_mask,
2619 &new_mask, conn->params);
2621 TALLOC_FREE(fname_mask);
2622 fname_mask = new_mask;
2629 * Only one file needs to be unlinked. Append the mask back
2630 * onto the directory.
2632 TALLOC_FREE(smb_fname->base_name);
2633 if (ISDOT(fname_dir)) {
2634 /* Ensure we use canonical names on open. */
2635 smb_fname->base_name = talloc_asprintf(smb_fname,
2639 smb_fname->base_name = talloc_asprintf(smb_fname,
2644 if (!smb_fname->base_name) {
2645 status = NT_STATUS_NO_MEMORY;
2649 dirtype = FILE_ATTRIBUTE_NORMAL;
2652 status = check_name(conn, smb_fname->base_name);
2653 if (!NT_STATUS_IS_OK(status)) {
2657 status = do_unlink(conn, req, smb_fname, dirtype);
2658 if (!NT_STATUS_IS_OK(status)) {
2664 struct smb_Dir *dir_hnd = NULL;
2666 const char *dname = NULL;
2667 char *talloced = NULL;
2669 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
2670 status = NT_STATUS_OBJECT_NAME_INVALID;
2674 if (strequal(fname_mask,"????????.???")) {
2675 TALLOC_FREE(fname_mask);
2676 fname_mask = talloc_strdup(ctx, "*");
2678 status = NT_STATUS_NO_MEMORY;
2683 status = check_name(conn, fname_dir);
2684 if (!NT_STATUS_IS_OK(status)) {
2688 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2690 if (dir_hnd == NULL) {
2691 status = map_nt_error_from_unix(errno);
2695 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2696 the pattern matches against the long name, otherwise the short name
2697 We don't implement this yet XXXX
2700 status = NT_STATUS_NO_SUCH_FILE;
2702 while ((dname = ReadDirName(dir_hnd, &offset,
2703 &smb_fname->st, &talloced))) {
2704 TALLOC_CTX *frame = talloc_stackframe();
2706 if (!is_visible_file(conn, fname_dir, dname,
2707 &smb_fname->st, true)) {
2709 TALLOC_FREE(talloced);
2713 /* Quick check for "." and ".." */
2714 if (ISDOT(dname) || ISDOTDOT(dname)) {
2716 TALLOC_FREE(talloced);
2720 if(!mask_match(dname, fname_mask,
2721 conn->case_sensitive)) {
2723 TALLOC_FREE(talloced);
2727 TALLOC_FREE(smb_fname->base_name);
2728 if (ISDOT(fname_dir)) {
2729 /* Ensure we use canonical names on open. */
2730 smb_fname->base_name =
2731 talloc_asprintf(smb_fname, "%s",
2734 smb_fname->base_name =
2735 talloc_asprintf(smb_fname, "%s/%s",
2739 if (!smb_fname->base_name) {
2740 TALLOC_FREE(dir_hnd);
2741 status = NT_STATUS_NO_MEMORY;
2743 TALLOC_FREE(talloced);
2747 status = check_name(conn, smb_fname->base_name);
2748 if (!NT_STATUS_IS_OK(status)) {
2749 TALLOC_FREE(dir_hnd);
2751 TALLOC_FREE(talloced);
2755 status = do_unlink(conn, req, smb_fname, dirtype);
2756 if (!NT_STATUS_IS_OK(status)) {
2758 TALLOC_FREE(talloced);
2763 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2764 smb_fname->base_name));
2767 TALLOC_FREE(talloced);
2769 TALLOC_FREE(dir_hnd);
2772 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2773 status = map_nt_error_from_unix(errno);
2777 TALLOC_FREE(fname_dir);
2778 TALLOC_FREE(fname_mask);
2782 /****************************************************************************
2784 ****************************************************************************/
2786 void reply_unlink(struct smb_request *req)
2788 connection_struct *conn = req->conn;
2790 struct smb_filename *smb_fname = NULL;
2793 bool path_contains_wcard = False;
2794 TALLOC_CTX *ctx = talloc_tos();
2796 START_PROFILE(SMBunlink);
2799 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2803 dirtype = SVAL(req->vwv+0, 0);
2805 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2806 STR_TERMINATE, &status,
2807 &path_contains_wcard);
2808 if (!NT_STATUS_IS_OK(status)) {
2809 reply_nterror(req, status);
2813 status = filename_convert(ctx, conn,
2814 req->flags2 & FLAGS2_DFS_PATHNAMES,
2816 UCF_COND_ALLOW_WCARD_LCOMP,
2817 &path_contains_wcard,
2819 if (!NT_STATUS_IS_OK(status)) {
2820 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2821 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2822 ERRSRV, ERRbadpath);
2825 reply_nterror(req, status);
2829 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2831 status = unlink_internals(conn, req, dirtype, smb_fname,
2832 path_contains_wcard);
2833 if (!NT_STATUS_IS_OK(status)) {
2834 if (open_was_deferred(req->sconn, req->mid)) {
2835 /* We have re-scheduled this call. */
2838 reply_nterror(req, status);
2842 reply_outbuf(req, 0, 0);
2844 TALLOC_FREE(smb_fname);
2845 END_PROFILE(SMBunlink);
2849 /****************************************************************************
2851 ****************************************************************************/
2853 static void fail_readraw(void)
2855 const char *errstr = talloc_asprintf(talloc_tos(),
2856 "FAIL ! reply_readbraw: socket write fail (%s)",
2861 exit_server_cleanly(errstr);
2864 /****************************************************************************
2865 Fake (read/write) sendfile. Returns -1 on read or write fail.
2866 ****************************************************************************/
2868 ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread)
2871 size_t tosend = nread;
2878 bufsize = MIN(nread, 65536);
2880 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2884 while (tosend > 0) {
2888 if (tosend > bufsize) {
2893 ret = read_file(fsp,buf,startpos,cur_read);
2899 /* If we had a short read, fill with zeros. */
2900 if (ret < cur_read) {
2901 memset(buf + ret, '\0', cur_read - ret);
2904 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
2906 char addr[INET6_ADDRSTRLEN];
2908 * Try and give an error message saying what
2911 DEBUG(0, ("write_data failed for client %s. "
2913 get_peer_addr(fsp->conn->sconn->sock, addr,
2920 startpos += cur_read;
2924 return (ssize_t)nread;
2927 /****************************************************************************
2928 Deal with the case of sendfile reading less bytes from the file than
2929 requested. Fill with zeros (all we can do).
2930 ****************************************************************************/
2932 void sendfile_short_send(files_struct *fsp,
2937 #define SHORT_SEND_BUFSIZE 1024
2938 if (nread < headersize) {
2939 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2940 "header for file %s (%s). Terminating\n",
2941 fsp_str_dbg(fsp), strerror(errno)));
2942 exit_server_cleanly("sendfile_short_send failed");
2945 nread -= headersize;
2947 if (nread < smb_maxcnt) {
2948 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2950 exit_server_cleanly("sendfile_short_send: "
2954 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2955 "with zeros !\n", fsp_str_dbg(fsp)));
2957 while (nread < smb_maxcnt) {
2959 * We asked for the real file size and told sendfile
2960 * to not go beyond the end of the file. But it can
2961 * happen that in between our fstat call and the
2962 * sendfile call the file was truncated. This is very
2963 * bad because we have already announced the larger
2964 * number of bytes to the client.
2966 * The best we can do now is to send 0-bytes, just as
2967 * a read from a hole in a sparse file would do.
2969 * This should happen rarely enough that I don't care
2970 * about efficiency here :-)
2974 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2975 if (write_data(fsp->conn->sconn->sock, buf, to_write)
2977 char addr[INET6_ADDRSTRLEN];
2979 * Try and give an error message saying what
2982 DEBUG(0, ("write_data failed for client %s. "
2985 fsp->conn->sconn->sock, addr,
2988 exit_server_cleanly("sendfile_short_send: "
2989 "write_data failed");
2997 /****************************************************************************
2998 Return a readbraw error (4 bytes of zero).
2999 ****************************************************************************/
3001 static void reply_readbraw_error(struct smbd_server_connection *sconn)
3007 smbd_lock_socket(sconn);
3008 if (write_data(sconn->sock,header,4) != 4) {
3009 char addr[INET6_ADDRSTRLEN];
3011 * Try and give an error message saying what
3014 DEBUG(0, ("write_data failed for client %s. "
3016 get_peer_addr(sconn->sock, addr, sizeof(addr)),
3021 smbd_unlock_socket(sconn);
3024 /****************************************************************************
3025 Use sendfile in readbraw.
3026 ****************************************************************************/
3028 static void send_file_readbraw(connection_struct *conn,
3029 struct smb_request *req,
3035 struct smbd_server_connection *sconn = req->sconn;
3036 char *outbuf = NULL;
3040 * We can only use sendfile on a non-chained packet
3041 * but we can use on a non-oplocked file. tridge proved this
3042 * on a train in Germany :-). JRA.
3043 * reply_readbraw has already checked the length.
3046 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3047 (fsp->wcp == NULL) &&
3048 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3049 ssize_t sendfile_read = -1;
3051 DATA_BLOB header_blob;
3053 _smb_setlen(header,nread);
3054 header_blob = data_blob_const(header, 4);
3056 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
3057 &header_blob, startpos,
3059 if (sendfile_read == -1) {
3060 /* Returning ENOSYS means no data at all was sent.
3061 * Do this as a normal read. */
3062 if (errno == ENOSYS) {
3063 goto normal_readbraw;
3067 * Special hack for broken Linux with no working sendfile. If we
3068 * return EINTR we sent the header but not the rest of the data.
3069 * Fake this up by doing read/write calls.
3071 if (errno == EINTR) {
3072 /* Ensure we don't do this again. */
3073 set_use_sendfile(SNUM(conn), False);
3074 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3076 if (fake_sendfile(fsp, startpos, nread) == -1) {
3077 DEBUG(0,("send_file_readbraw: "
3078 "fake_sendfile failed for "
3082 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3087 DEBUG(0,("send_file_readbraw: sendfile failed for "
3088 "file %s (%s). Terminating\n",
3089 fsp_str_dbg(fsp), strerror(errno)));
3090 exit_server_cleanly("send_file_readbraw sendfile failed");
3091 } else if (sendfile_read == 0) {
3093 * Some sendfile implementations return 0 to indicate
3094 * that there was a short read, but nothing was
3095 * actually written to the socket. In this case,
3096 * fallback to the normal read path so the header gets
3097 * the correct byte count.
3099 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3100 "bytes falling back to the normal read: "
3101 "%s\n", fsp_str_dbg(fsp)));
3102 goto normal_readbraw;
3105 /* Deal with possible short send. */
3106 if (sendfile_read != 4+nread) {
3107 sendfile_short_send(fsp, sendfile_read, 4, nread);
3114 outbuf = talloc_array(NULL, char, nread+4);
3116 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3117 (unsigned)(nread+4)));
3118 reply_readbraw_error(sconn);
3123 ret = read_file(fsp,outbuf+4,startpos,nread);
3124 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3133 _smb_setlen(outbuf,ret);
3134 if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
3135 char addr[INET6_ADDRSTRLEN];
3137 * Try and give an error message saying what
3140 DEBUG(0, ("write_data failed for client %s. "
3142 get_peer_addr(fsp->conn->sconn->sock, addr,
3149 TALLOC_FREE(outbuf);
3152 /****************************************************************************
3153 Reply to a readbraw (core+ protocol).
3154 ****************************************************************************/
3156 void reply_readbraw(struct smb_request *req)
3158 connection_struct *conn = req->conn;
3159 struct smbd_server_connection *sconn = req->sconn;
3160 ssize_t maxcount,mincount;
3164 struct lock_struct lock;
3167 START_PROFILE(SMBreadbraw);
3169 if (srv_is_signing_active(sconn) ||
3170 is_encrypted_packet(sconn, req->inbuf)) {
3171 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3172 "raw reads/writes are disallowed.");
3176 reply_readbraw_error(sconn);
3177 END_PROFILE(SMBreadbraw);
3181 if (sconn->smb1.echo_handler.trusted_fde) {
3182 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3183 "'async smb echo handler = yes'\n"));
3184 reply_readbraw_error(sconn);
3185 END_PROFILE(SMBreadbraw);
3190 * Special check if an oplock break has been issued
3191 * and the readraw request croses on the wire, we must
3192 * return a zero length response here.
3195 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3198 * We have to do a check_fsp by hand here, as
3199 * we must always return 4 zero bytes on error,
3203 if (!fsp || !conn || conn != fsp->conn ||
3204 req->vuid != fsp->vuid ||
3205 fsp->is_directory || fsp->fh->fd == -1) {
3207 * fsp could be NULL here so use the value from the packet. JRA.
3209 DEBUG(3,("reply_readbraw: fnum %d not valid "
3211 (int)SVAL(req->vwv+0, 0)));
3212 reply_readbraw_error(sconn);
3213 END_PROFILE(SMBreadbraw);
3217 /* Do a "by hand" version of CHECK_READ. */
3218 if (!(fsp->can_read ||
3219 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3220 (fsp->access_mask & FILE_EXECUTE)))) {
3221 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3222 (int)SVAL(req->vwv+0, 0)));
3223 reply_readbraw_error(sconn);
3224 END_PROFILE(SMBreadbraw);
3228 flush_write_cache(fsp, READRAW_FLUSH);
3230 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3231 if(req->wct == 10) {
3233 * This is a large offset (64 bit) read.
3235 #ifdef LARGE_SMB_OFF_T
3237 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3239 #else /* !LARGE_SMB_OFF_T */
3242 * Ensure we haven't been sent a >32 bit offset.
3245 if(IVAL(req->vwv+8, 0) != 0) {
3246 DEBUG(0,("reply_readbraw: large offset "
3247 "(%x << 32) used and we don't support "
3248 "64 bit offsets.\n",
3249 (unsigned int)IVAL(req->vwv+8, 0) ));
3250 reply_readbraw_error(sconn);
3251 END_PROFILE(SMBreadbraw);
3255 #endif /* LARGE_SMB_OFF_T */
3258 DEBUG(0,("reply_readbraw: negative 64 bit "
3259 "readraw offset (%.0f) !\n",
3260 (double)startpos ));
3261 reply_readbraw_error(sconn);
3262 END_PROFILE(SMBreadbraw);
3267 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3268 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3270 /* ensure we don't overrun the packet size */
3271 maxcount = MIN(65535,maxcount);
3273 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3274 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3277 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3278 reply_readbraw_error(sconn);
3279 END_PROFILE(SMBreadbraw);
3283 if (fsp_stat(fsp) == 0) {
3284 size = fsp->fsp_name->st.st_ex_size;
3287 if (startpos >= size) {
3290 nread = MIN(maxcount,(size - startpos));
3293 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3294 if (nread < mincount)
3298 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3299 "min=%lu nread=%lu\n",
3300 fsp->fnum, (double)startpos,
3301 (unsigned long)maxcount,
3302 (unsigned long)mincount,
3303 (unsigned long)nread ) );
3305 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3307 DEBUG(5,("reply_readbraw finished\n"));
3309 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3311 END_PROFILE(SMBreadbraw);
3316 #define DBGC_CLASS DBGC_LOCKING
3318 /****************************************************************************
3319 Reply to a lockread (core+ protocol).
3320 ****************************************************************************/
3322 void reply_lockread(struct smb_request *req)
3324 connection_struct *conn = req->conn;
3331 struct byte_range_lock *br_lck = NULL;
3333 struct smbd_server_connection *sconn = req->sconn;
3335 START_PROFILE(SMBlockread);
3338 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3339 END_PROFILE(SMBlockread);
3343 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3345 if (!check_fsp(conn, req, fsp)) {
3346 END_PROFILE(SMBlockread);
3350 if (!CHECK_READ(fsp,req)) {
3351 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3352 END_PROFILE(SMBlockread);
3356 numtoread = SVAL(req->vwv+1, 0);
3357 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3359 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3361 reply_outbuf(req, 5, numtoread + 3);
3363 data = smb_buf(req->outbuf) + 3;
3366 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3367 * protocol request that predates the read/write lock concept.
3368 * Thus instead of asking for a read lock here we need to ask
3369 * for a write lock. JRA.
3370 * Note that the requested lock size is unaffected by max_recv.
3373 br_lck = do_lock(req->sconn->msg_ctx,
3375 (uint64_t)req->smbpid,
3376 (uint64_t)numtoread,
3380 False, /* Non-blocking lock. */
3384 TALLOC_FREE(br_lck);
3386 if (NT_STATUS_V(status)) {
3387 reply_nterror(req, status);
3388 END_PROFILE(SMBlockread);
3393 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3396 if (numtoread > sconn->smb1.negprot.max_recv) {
3397 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3398 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3399 (unsigned int)numtoread,
3400 (unsigned int)sconn->smb1.negprot.max_recv));
3401 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3403 nread = read_file(fsp,data,startpos,numtoread);
3406 reply_nterror(req, map_nt_error_from_unix(errno));
3407 END_PROFILE(SMBlockread);
3411 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3413 SSVAL(req->outbuf,smb_vwv0,nread);
3414 SSVAL(req->outbuf,smb_vwv5,nread+3);
3415 p = smb_buf(req->outbuf);
3416 SCVAL(p,0,0); /* pad byte. */
3419 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3420 fsp->fnum, (int)numtoread, (int)nread));
3422 END_PROFILE(SMBlockread);
3427 #define DBGC_CLASS DBGC_ALL
3429 /****************************************************************************
3431 ****************************************************************************/
3433 void reply_read(struct smb_request *req)
3435 connection_struct *conn = req->conn;
3442 struct lock_struct lock;
3443 struct smbd_server_connection *sconn = req->sconn;
3445 START_PROFILE(SMBread);
3448 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3449 END_PROFILE(SMBread);
3453 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3455 if (!check_fsp(conn, req, fsp)) {
3456 END_PROFILE(SMBread);
3460 if (!CHECK_READ(fsp,req)) {
3461 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3462 END_PROFILE(SMBread);
3466 numtoread = SVAL(req->vwv+1, 0);
3467 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3469 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3472 * The requested read size cannot be greater than max_recv. JRA.
3474 if (numtoread > sconn->smb1.negprot.max_recv) {
3475 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3476 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3477 (unsigned int)numtoread,
3478 (unsigned int)sconn->smb1.negprot.max_recv));
3479 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3482 reply_outbuf(req, 5, numtoread+3);
3484 data = smb_buf(req->outbuf) + 3;
3486 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3487 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3490 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3491 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3492 END_PROFILE(SMBread);
3497 nread = read_file(fsp,data,startpos,numtoread);
3500 reply_nterror(req, map_nt_error_from_unix(errno));
3504 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3506 SSVAL(req->outbuf,smb_vwv0,nread);
3507 SSVAL(req->outbuf,smb_vwv5,nread+3);
3508 SCVAL(smb_buf(req->outbuf),0,1);
3509 SSVAL(smb_buf(req->outbuf),1,nread);
3511 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3512 fsp->fnum, (int)numtoread, (int)nread ) );
3515 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3517 END_PROFILE(SMBread);
3521 /****************************************************************************
3523 ****************************************************************************/
3525 static int setup_readX_header(struct smb_request *req, char *outbuf,
3530 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3532 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3534 SCVAL(outbuf,smb_vwv0,0xFF);
3535 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3536 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3537 SSVAL(outbuf,smb_vwv6,
3539 + 1 /* the wct field */
3540 + 12 * sizeof(uint16_t) /* vwv */
3541 + 2); /* the buflen field */
3542 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3543 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3544 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3545 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3549 /****************************************************************************
3550 Reply to a read and X - possibly using sendfile.
3551 ****************************************************************************/
3553 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3554 files_struct *fsp, SMB_OFF_T startpos,
3558 struct lock_struct lock;
3559 int saved_errno = 0;
3561 if(fsp_stat(fsp) == -1) {
3562 reply_nterror(req, map_nt_error_from_unix(errno));
3566 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3567 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3570 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3571 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3575 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3576 (startpos > fsp->fsp_name->st.st_ex_size)
3577 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3579 * We already know that we would do a short read, so don't
3580 * try the sendfile() path.
3582 goto nosendfile_read;
3586 * We can only use sendfile on a non-chained packet
3587 * but we can use on a non-oplocked file. tridge proved this
3588 * on a train in Germany :-). JRA.
3591 if (!req_is_in_chain(req) &&
3592 !is_encrypted_packet(req->sconn, req->inbuf) &&
3593 (fsp->base_fsp == NULL) &&
3594 (fsp->wcp == NULL) &&
3595 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3596 uint8 headerbuf[smb_size + 12 * 2];
3600 * Set up the packet header before send. We
3601 * assume here the sendfile will work (get the
3602 * correct amount of data).
3605 header = data_blob_const(headerbuf, sizeof(headerbuf));
3607 construct_reply_common_req(req, (char *)headerbuf);
3608 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3610 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3611 startpos, smb_maxcnt);
3613 /* Returning ENOSYS means no data at all was sent.
3614 Do this as a normal read. */
3615 if (errno == ENOSYS) {
3620 * Special hack for broken Linux with no working sendfile. If we
3621 * return EINTR we sent the header but not the rest of the data.
3622 * Fake this up by doing read/write calls.
3625 if (errno == EINTR) {
3626 /* Ensure we don't do this again. */
3627 set_use_sendfile(SNUM(conn), False);
3628 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3629 nread = fake_sendfile(fsp, startpos,
3632 DEBUG(0,("send_file_readX: "
3633 "fake_sendfile failed for "
3637 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3639 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3640 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3641 /* No outbuf here means successful sendfile. */
3645 DEBUG(0,("send_file_readX: sendfile failed for file "
3646 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3648 exit_server_cleanly("send_file_readX sendfile failed");
3649 } else if (nread == 0) {
3651 * Some sendfile implementations return 0 to indicate
3652 * that there was a short read, but nothing was
3653 * actually written to the socket. In this case,
3654 * fallback to the normal read path so the header gets
3655 * the correct byte count.
3657 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3658 "falling back to the normal read: %s\n",
3663 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3664 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3666 /* Deal with possible short send. */
3667 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3668 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3670 /* No outbuf here means successful sendfile. */
3671 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3672 SMB_PERFCOUNT_END(&req->pcd);
3678 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3679 uint8 headerbuf[smb_size + 2*12];
3681 construct_reply_common_req(req, (char *)headerbuf);
3682 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3684 /* Send out the header. */
3685 if (write_data(req->sconn->sock, (char *)headerbuf,
3686 sizeof(headerbuf)) != sizeof(headerbuf)) {
3688 char addr[INET6_ADDRSTRLEN];
3690 * Try and give an error message saying what
3693 DEBUG(0, ("write_data failed for client %s. "
3695 get_peer_addr(req->sconn->sock, addr,
3699 DEBUG(0,("send_file_readX: write_data failed for file "
3700 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3702 exit_server_cleanly("send_file_readX sendfile failed");
3704 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3706 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3707 "file %s (%s).\n", fsp_str_dbg(fsp),
3709 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3716 reply_outbuf(req, 12, smb_maxcnt);
3718 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3719 saved_errno = errno;
3721 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3724 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3728 setup_readX_header(req, (char *)req->outbuf, nread);
3730 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3731 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3737 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3738 TALLOC_FREE(req->outbuf);
3742 /****************************************************************************
3743 Reply to a read and X.
3744 ****************************************************************************/
3746 void reply_read_and_X(struct smb_request *req)
3748 struct smbd_server_connection *sconn = req->sconn;
3749 connection_struct *conn = req->conn;
3753 bool big_readX = False;
3755 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3758 START_PROFILE(SMBreadX);
3760 if ((req->wct != 10) && (req->wct != 12)) {
3761 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3765 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3766 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3767 smb_maxcnt = SVAL(req->vwv+5, 0);
3769 /* If it's an IPC, pass off the pipe handler. */
3771 reply_pipe_read_and_X(req);
3772 END_PROFILE(SMBreadX);
3776 if (!check_fsp(conn, req, fsp)) {
3777 END_PROFILE(SMBreadX);
3781 if (!CHECK_READ(fsp,req)) {
3782 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3783 END_PROFILE(SMBreadX);
3787 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_LARGE_READ_CAP) ||
3788 (get_remote_arch() == RA_SAMBA)) {
3790 * This is Samba only behavior (up to Samba 3.6)!
3792 * Windows 2008 R2 ignores the upper_size,
3793 * so we do unless unix extentions are active
3794 * or "smbclient" is talking to us.
3796 size_t upper_size = SVAL(req->vwv+7, 0);
3797 smb_maxcnt |= (upper_size<<16);
3798 if (upper_size > 1) {
3799 /* Can't do this on a chained packet. */
3800 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3801 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3802 END_PROFILE(SMBreadX);
3805 /* We currently don't do this on signed or sealed data. */
3806 if (srv_is_signing_active(req->sconn) ||
3807 is_encrypted_packet(req->sconn, req->inbuf)) {
3808 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3809 END_PROFILE(SMBreadX);
3812 /* Is there room in the reply for this data ? */
3813 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3815 NT_STATUS_INVALID_PARAMETER);
3816 END_PROFILE(SMBreadX);
3823 if (req->wct == 12) {
3824 #ifdef LARGE_SMB_OFF_T
3826 * This is a large offset (64 bit) read.
3828 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3830 #else /* !LARGE_SMB_OFF_T */
3833 * Ensure we haven't been sent a >32 bit offset.
3836 if(IVAL(req->vwv+10, 0) != 0) {
3837 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3838 "used and we don't support 64 bit offsets.\n",
3839 (unsigned int)IVAL(req->vwv+10, 0) ));
3840 END_PROFILE(SMBreadX);
3841 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3845 #endif /* LARGE_SMB_OFF_T */
3850 NTSTATUS status = schedule_aio_read_and_X(conn,
3855 if (NT_STATUS_IS_OK(status)) {
3856 /* Read scheduled - we're done. */
3859 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3860 /* Real error - report to client. */
3861 END_PROFILE(SMBreadX);
3862 reply_nterror(req, status);
3865 /* NT_STATUS_RETRY - fall back to sync read. */
3868 smbd_lock_socket(req->sconn);
3869 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3870 smbd_unlock_socket(req->sconn);
3873 END_PROFILE(SMBreadX);
3877 /****************************************************************************
3878 Error replies to writebraw must have smb_wct == 1. Fix this up.
3879 ****************************************************************************/
3881 void error_to_writebrawerr(struct smb_request *req)
3883 uint8 *old_outbuf = req->outbuf;
3885 reply_outbuf(req, 1, 0);
3887 memcpy(req->outbuf, old_outbuf, smb_size);
3888 TALLOC_FREE(old_outbuf);
3891 /****************************************************************************
3892 Read 4 bytes of a smb packet and return the smb length of the packet.
3893 Store the result in the buffer. This version of the function will
3894 never return a session keepalive (length of zero).
3895 Timeout is in milliseconds.
3896 ****************************************************************************/
3898 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3901 uint8_t msgtype = NBSSkeepalive;
3903 while (msgtype == NBSSkeepalive) {
3906 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3908 if (!NT_STATUS_IS_OK(status)) {
3909 char addr[INET6_ADDRSTRLEN];
3910 /* Try and give an error message
3911 * saying what client failed. */
3912 DEBUG(0, ("read_fd_with_timeout failed for "
3913 "client %s read error = %s.\n",
3914 get_peer_addr(fd,addr,sizeof(addr)),
3915 nt_errstr(status)));
3919 msgtype = CVAL(inbuf, 0);
3922 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3923 (unsigned long)len));
3925 return NT_STATUS_OK;
3928 /****************************************************************************
3929 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3930 ****************************************************************************/
3932 void reply_writebraw(struct smb_request *req)
3934 connection_struct *conn = req->conn;
3937 ssize_t total_written=0;
3938 size_t numtowrite=0;
3941 const char *data=NULL;
3944 struct lock_struct lock;
3947 START_PROFILE(SMBwritebraw);
3950 * If we ever reply with an error, it must have the SMB command
3951 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3954 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
3956 if (srv_is_signing_active(req->sconn)) {
3957 END_PROFILE(SMBwritebraw);
3958 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3959 "raw reads/writes are disallowed.");
3962 if (req->wct < 12) {
3963 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3964 error_to_writebrawerr(req);
3965 END_PROFILE(SMBwritebraw);
3969 if (req->sconn->smb1.echo_handler.trusted_fde) {
3970 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3971 "'async smb echo handler = yes'\n"));
3972 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3973 error_to_writebrawerr(req);
3974 END_PROFILE(SMBwritebraw);
3978 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3979 if (!check_fsp(conn, req, fsp)) {
3980 error_to_writebrawerr(req);
3981 END_PROFILE(SMBwritebraw);
3985 if (!CHECK_WRITE(fsp)) {
3986 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3987 error_to_writebrawerr(req);
3988 END_PROFILE(SMBwritebraw);
3992 tcount = IVAL(req->vwv+1, 0);
3993 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3994 write_through = BITSETW(req->vwv+7,0);
3996 /* We have to deal with slightly different formats depending
3997 on whether we are using the core+ or lanman1.0 protocol */
3999 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4000 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4001 data = smb_buf_const(req->inbuf);
4003 numtowrite = SVAL(req->vwv+10, 0);
4004 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4007 /* Ensure we don't write bytes past the end of this packet. */
4008 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4009 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4010 error_to_writebrawerr(req);
4011 END_PROFILE(SMBwritebraw);
4015 if (!fsp->print_file) {
4016 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4017 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4020 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4021 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4022 error_to_writebrawerr(req);
4023 END_PROFILE(SMBwritebraw);
4029 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4032 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
4033 "wrote=%d sync=%d\n",
4034 fsp->fnum, (double)startpos, (int)numtowrite,
4035 (int)nwritten, (int)write_through));
4037 if (nwritten < (ssize_t)numtowrite) {
4038 reply_nterror(req, NT_STATUS_DISK_FULL);
4039 error_to_writebrawerr(req);
4043 total_written = nwritten;
4045 /* Allocate a buffer of 64k + length. */
4046 buf = talloc_array(NULL, char, 65540);
4048 reply_nterror(req, NT_STATUS_NO_MEMORY);
4049 error_to_writebrawerr(req);
4053 /* Return a SMBwritebraw message to the redirector to tell
4054 * it to send more bytes */
4056 memcpy(buf, req->inbuf, smb_size);
4057 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4058 SCVAL(buf,smb_com,SMBwritebraw);
4059 SSVALS(buf,smb_vwv0,0xFFFF);
4061 if (!srv_send_smb(req->sconn,
4063 false, 0, /* no signing */
4064 IS_CONN_ENCRYPTED(conn),
4066 exit_server_cleanly("reply_writebraw: srv_send_smb "
4070 /* Now read the raw data into the buffer and write it */
4071 status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
4073 if (!NT_STATUS_IS_OK(status)) {
4074 exit_server_cleanly("secondary writebraw failed");
4077 /* Set up outbuf to return the correct size */
4078 reply_outbuf(req, 1, 0);
4080 if (numtowrite != 0) {
4082 if (numtowrite > 0xFFFF) {
4083 DEBUG(0,("reply_writebraw: Oversize secondary write "
4084 "raw requested (%u). Terminating\n",
4085 (unsigned int)numtowrite ));
4086 exit_server_cleanly("secondary writebraw failed");
4089 if (tcount > nwritten+numtowrite) {
4090 DEBUG(3,("reply_writebraw: Client overestimated the "
4092 (int)tcount,(int)nwritten,(int)numtowrite));
4095 status = read_data(req->sconn->sock, buf+4, numtowrite);
4097 if (!NT_STATUS_IS_OK(status)) {
4098 char addr[INET6_ADDRSTRLEN];
4099 /* Try and give an error message
4100 * saying what client failed. */
4101 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4102 "raw read failed (%s) for client %s. "
4103 "Terminating\n", nt_errstr(status),
4104 get_peer_addr(req->sconn->sock, addr,
4106 exit_server_cleanly("secondary writebraw failed");
4109 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4110 if (nwritten == -1) {
4112 reply_nterror(req, map_nt_error_from_unix(errno));
4113 error_to_writebrawerr(req);
4117 if (nwritten < (ssize_t)numtowrite) {
4118 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4119 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4123 total_written += nwritten;
4128 SSVAL(req->outbuf,smb_vwv0,total_written);
4130 status = sync_file(conn, fsp, write_through);
4131 if (!NT_STATUS_IS_OK(status)) {
4132 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4133 fsp_str_dbg(fsp), nt_errstr(status)));
4134 reply_nterror(req, status);
4135 error_to_writebrawerr(req);
4139 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4141 fsp->fnum, (double)startpos, (int)numtowrite,
4142 (int)total_written));
4144 if (!fsp->print_file) {
4145 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4148 /* We won't return a status if write through is not selected - this
4149 * follows what WfWg does */
4150 END_PROFILE(SMBwritebraw);
4152 if (!write_through && total_written==tcount) {
4154 #if RABBIT_PELLET_FIX
4156 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4157 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4160 if (!send_keepalive(req->sconn->sock)) {
4161 exit_server_cleanly("reply_writebraw: send of "
4162 "keepalive failed");
4165 TALLOC_FREE(req->outbuf);
4170 if (!fsp->print_file) {
4171 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4174 END_PROFILE(SMBwritebraw);
4179 #define DBGC_CLASS DBGC_LOCKING
4181 /****************************************************************************
4182 Reply to a writeunlock (core+).
4183 ****************************************************************************/
4185 void reply_writeunlock(struct smb_request *req)
4187 connection_struct *conn = req->conn;
4188 ssize_t nwritten = -1;
4192 NTSTATUS status = NT_STATUS_OK;
4194 struct lock_struct lock;
4195 int saved_errno = 0;
4197 START_PROFILE(SMBwriteunlock);
4200 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4201 END_PROFILE(SMBwriteunlock);
4205 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4207 if (!check_fsp(conn, req, fsp)) {
4208 END_PROFILE(SMBwriteunlock);
4212 if (!CHECK_WRITE(fsp)) {
4213 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4214 END_PROFILE(SMBwriteunlock);
4218 numtowrite = SVAL(req->vwv+1, 0);
4219 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4220 data = (const char *)req->buf + 3;
4222 if (!fsp->print_file && numtowrite > 0) {
4223 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4224 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4227 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4228 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4229 END_PROFILE(SMBwriteunlock);
4234 /* The special X/Open SMB protocol handling of
4235 zero length writes is *NOT* done for
4237 if(numtowrite == 0) {
4240 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4241 saved_errno = errno;
4244 status = sync_file(conn, fsp, False /* write through */);
4245 if (!NT_STATUS_IS_OK(status)) {
4246 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4247 fsp_str_dbg(fsp), nt_errstr(status)));
4248 reply_nterror(req, status);
4253 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4257 if((nwritten < numtowrite) && (numtowrite != 0)) {
4258 reply_nterror(req, NT_STATUS_DISK_FULL);
4262 if (numtowrite && !fsp->print_file) {
4263 status = do_unlock(req->sconn->msg_ctx,
4265 (uint64_t)req->smbpid,
4266 (uint64_t)numtowrite,
4270 if (NT_STATUS_V(status)) {
4271 reply_nterror(req, status);
4276 reply_outbuf(req, 1, 0);
4278 SSVAL(req->outbuf,smb_vwv0,nwritten);
4280 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4281 fsp->fnum, (int)numtowrite, (int)nwritten));
4284 if (numtowrite && !fsp->print_file) {
4285 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4288 END_PROFILE(SMBwriteunlock);
4293 #define DBGC_CLASS DBGC_ALL
4295 /****************************************************************************
4297 ****************************************************************************/
4299 void reply_write(struct smb_request *req)
4301 connection_struct *conn = req->conn;
4303 ssize_t nwritten = -1;
4307 struct lock_struct lock;
4309 int saved_errno = 0;
4311 START_PROFILE(SMBwrite);
4314 END_PROFILE(SMBwrite);
4315 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4319 /* If it's an IPC, pass off the pipe handler. */
4321 reply_pipe_write(req);
4322 END_PROFILE(SMBwrite);
4326 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4328 if (!check_fsp(conn, req, fsp)) {
4329 END_PROFILE(SMBwrite);
4333 if (!CHECK_WRITE(fsp)) {
4334 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4335 END_PROFILE(SMBwrite);
4339 numtowrite = SVAL(req->vwv+1, 0);
4340 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4341 data = (const char *)req->buf + 3;
4343 if (!fsp->print_file) {
4344 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4345 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4348 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4349 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4350 END_PROFILE(SMBwrite);
4356 * X/Open SMB protocol says that if smb_vwv1 is
4357 * zero then the file size should be extended or
4358 * truncated to the size given in smb_vwv[2-3].
4361 if(numtowrite == 0) {
4363 * This is actually an allocate call, and set EOF. JRA.
4365 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4367 reply_nterror(req, NT_STATUS_DISK_FULL);
4370 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4372 reply_nterror(req, NT_STATUS_DISK_FULL);
4375 trigger_write_time_update_immediate(fsp);
4377 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4380 status = sync_file(conn, fsp, False);
4381 if (!NT_STATUS_IS_OK(status)) {
4382 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4383 fsp_str_dbg(fsp), nt_errstr(status)));
4384 reply_nterror(req, status);
4389 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4393 if((nwritten == 0) && (numtowrite != 0)) {
4394 reply_nterror(req, NT_STATUS_DISK_FULL);
4398 reply_outbuf(req, 1, 0);
4400 SSVAL(req->outbuf,smb_vwv0,nwritten);
4402 if (nwritten < (ssize_t)numtowrite) {
4403 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4404 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4407 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4410 if (!fsp->print_file) {
4411 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4414 END_PROFILE(SMBwrite);
4418 /****************************************************************************
4419 Ensure a buffer is a valid writeX for recvfile purposes.
4420 ****************************************************************************/
4422 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4423 (2*14) + /* word count (including bcc) */ \
4426 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4427 const uint8_t *inbuf)
4430 connection_struct *conn = NULL;
4431 unsigned int doff = 0;
4432 size_t len = smb_len_large(inbuf);
4434 if (is_encrypted_packet(sconn, inbuf)) {
4435 /* Can't do this on encrypted
4440 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4444 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4445 CVAL(inbuf,smb_wct) != 14) {
4446 DEBUG(10,("is_valid_writeX_buffer: chained or "
4447 "invalid word length.\n"));
4451 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4453 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4457 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4460 if (IS_PRINT(conn)) {
4461 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4464 doff = SVAL(inbuf,smb_vwv11);
4466 numtowrite = SVAL(inbuf,smb_vwv10);
4468 if (len > doff && len - doff > 0xFFFF) {
4469 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4472 if (numtowrite == 0) {
4473 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4477 /* Ensure the sizes match up. */
4478 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4479 /* no pad byte...old smbclient :-( */
4480 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4482 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4486 if (len - doff != numtowrite) {
4487 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4488 "len = %u, doff = %u, numtowrite = %u\n",
4491 (unsigned int)numtowrite ));
4495 DEBUG(10,("is_valid_writeX_buffer: true "
4496 "len = %u, doff = %u, numtowrite = %u\n",
4499 (unsigned int)numtowrite ));
4504 /****************************************************************************
4505 Reply to a write and X.
4506 ****************************************************************************/
4508 void reply_write_and_X(struct smb_request *req)
4510 connection_struct *conn = req->conn;
4512 struct lock_struct lock;
4517 unsigned int smb_doff;
4518 unsigned int smblen;
4521 int saved_errno = 0;
4523 START_PROFILE(SMBwriteX);
4525 if ((req->wct != 12) && (req->wct != 14)) {
4526 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4527 END_PROFILE(SMBwriteX);
4531 numtowrite = SVAL(req->vwv+10, 0);
4532 smb_doff = SVAL(req->vwv+11, 0);
4533 smblen = smb_len(req->inbuf);
4535 if (req->unread_bytes > 0xFFFF ||
4536 (smblen > smb_doff &&
4537 smblen - smb_doff > 0xFFFF)) {
4538 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4541 if (req->unread_bytes) {
4542 /* Can't do a recvfile write on IPC$ */
4544 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4545 END_PROFILE(SMBwriteX);
4548 if (numtowrite != req->unread_bytes) {
4549 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4550 END_PROFILE(SMBwriteX);
4554 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4555 smb_doff + numtowrite > smblen) {
4556 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4557 END_PROFILE(SMBwriteX);
4562 /* If it's an IPC, pass off the pipe handler. */
4564 if (req->unread_bytes) {
4565 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4566 END_PROFILE(SMBwriteX);
4569 reply_pipe_write_and_X(req);
4570 END_PROFILE(SMBwriteX);
4574 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4575 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4576 write_through = BITSETW(req->vwv+7,0);
4578 if (!check_fsp(conn, req, fsp)) {
4579 END_PROFILE(SMBwriteX);
4583 if (!CHECK_WRITE(fsp)) {
4584 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4585 END_PROFILE(SMBwriteX);
4589 data = smb_base(req->inbuf) + smb_doff;
4591 if(req->wct == 14) {
4592 #ifdef LARGE_SMB_OFF_T
4594 * This is a large offset (64 bit) write.
4596 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4598 #else /* !LARGE_SMB_OFF_T */
4601 * Ensure we haven't been sent a >32 bit offset.
4604 if(IVAL(req->vwv+12, 0) != 0) {
4605 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4606 "used and we don't support 64 bit offsets.\n",
4607 (unsigned int)IVAL(req->vwv+12, 0) ));
4608 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4609 END_PROFILE(SMBwriteX);
4613 #endif /* LARGE_SMB_OFF_T */
4616 /* X/Open SMB protocol says that, unlike SMBwrite
4617 if the length is zero then NO truncation is
4618 done, just a write of zero. To truncate a file,
4621 if(numtowrite == 0) {
4624 if (req->unread_bytes == 0) {
4625 status = schedule_aio_write_and_X(conn,
4632 if (NT_STATUS_IS_OK(status)) {
4633 /* write scheduled - we're done. */
4636 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4637 /* Real error - report to client. */
4638 reply_nterror(req, status);
4641 /* NT_STATUS_RETRY - fall through to sync write. */
4644 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4645 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4648 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4649 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4653 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4654 saved_errno = errno;
4656 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4660 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4664 if((nwritten == 0) && (numtowrite != 0)) {
4665 reply_nterror(req, NT_STATUS_DISK_FULL);
4669 reply_outbuf(req, 6, 0);
4670 SSVAL(req->outbuf,smb_vwv2,nwritten);
4671 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4673 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4674 fsp->fnum, (int)numtowrite, (int)nwritten));
4676 status = sync_file(conn, fsp, write_through);
4677 if (!NT_STATUS_IS_OK(status)) {
4678 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4679 fsp_str_dbg(fsp), nt_errstr(status)));
4680 reply_nterror(req, status);
4684 END_PROFILE(SMBwriteX);
4689 END_PROFILE(SMBwriteX);
4693 /****************************************************************************
4695 ****************************************************************************/
4697 void reply_lseek(struct smb_request *req)
4699 connection_struct *conn = req->conn;
4705 START_PROFILE(SMBlseek);
4708 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4709 END_PROFILE(SMBlseek);
4713 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4715 if (!check_fsp(conn, req, fsp)) {
4719 flush_write_cache(fsp, SEEK_FLUSH);
4721 mode = SVAL(req->vwv+1, 0) & 3;
4722 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4723 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4732 res = fsp->fh->pos + startpos;
4743 if (umode == SEEK_END) {
4744 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4745 if(errno == EINVAL) {
4746 SMB_OFF_T current_pos = startpos;
4748 if(fsp_stat(fsp) == -1) {
4750 map_nt_error_from_unix(errno));
4751 END_PROFILE(SMBlseek);
4755 current_pos += fsp->fsp_name->st.st_ex_size;
4757 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4762 reply_nterror(req, map_nt_error_from_unix(errno));
4763 END_PROFILE(SMBlseek);
4770 reply_outbuf(req, 2, 0);
4771 SIVAL(req->outbuf,smb_vwv0,res);
4773 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4774 fsp->fnum, (double)startpos, (double)res, mode));
4776 END_PROFILE(SMBlseek);
4780 /****************************************************************************
4782 ****************************************************************************/
4784 void reply_flush(struct smb_request *req)
4786 connection_struct *conn = req->conn;
4790 START_PROFILE(SMBflush);
4793 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4797 fnum = SVAL(req->vwv+0, 0);
4798 fsp = file_fsp(req, fnum);
4800 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4805 file_sync_all(conn);
4807 NTSTATUS status = sync_file(conn, fsp, True);
4808 if (!NT_STATUS_IS_OK(status)) {
4809 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4810 fsp_str_dbg(fsp), nt_errstr(status)));
4811 reply_nterror(req, status);
4812 END_PROFILE(SMBflush);
4817 reply_outbuf(req, 0, 0);
4819 DEBUG(3,("flush\n"));
4820 END_PROFILE(SMBflush);
4824 /****************************************************************************
4826 conn POINTER CAN BE NULL HERE !
4827 ****************************************************************************/
4829 void reply_exit(struct smb_request *req)
4831 START_PROFILE(SMBexit);
4833 file_close_pid(req->sconn, req->smbpid, req->vuid);
4835 reply_outbuf(req, 0, 0);
4837 DEBUG(3,("exit\n"));
4839 END_PROFILE(SMBexit);
4843 /****************************************************************************
4844 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4845 ****************************************************************************/
4847 void reply_close(struct smb_request *req)
4849 connection_struct *conn = req->conn;
4850 NTSTATUS status = NT_STATUS_OK;
4851 files_struct *fsp = NULL;
4852 START_PROFILE(SMBclose);
4855 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4856 END_PROFILE(SMBclose);
4860 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4863 * We can only use check_fsp if we know it's not a directory.
4866 if (!check_fsp_open(conn, req, fsp)) {
4867 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4868 END_PROFILE(SMBclose);
4872 if(fsp->is_directory) {
4874 * Special case - close NT SMB directory handle.
4876 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4877 status = close_file(req, fsp, NORMAL_CLOSE);
4881 * Close ordinary file.
4884 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4885 fsp->fh->fd, fsp->fnum,
4886 conn->num_files_open));
4889 * Take care of any time sent in the close.
4892 t = srv_make_unix_date3(req->vwv+1);
4893 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4896 * close_file() returns the unix errno if an error
4897 * was detected on close - normally this is due to
4898 * a disk full error. If not then it was probably an I/O error.
4901 status = close_file(req, fsp, NORMAL_CLOSE);
4904 if (!NT_STATUS_IS_OK(status)) {
4905 reply_nterror(req, status);
4906 END_PROFILE(SMBclose);
4910 reply_outbuf(req, 0, 0);
4911 END_PROFILE(SMBclose);
4915 /****************************************************************************
4916 Reply to a writeclose (Core+ protocol).
4917 ****************************************************************************/
4919 void reply_writeclose(struct smb_request *req)
4921 connection_struct *conn = req->conn;
4923 ssize_t nwritten = -1;
4924 NTSTATUS close_status = NT_STATUS_OK;
4927 struct timespec mtime;
4929 struct lock_struct lock;
4931 START_PROFILE(SMBwriteclose);
4934 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4935 END_PROFILE(SMBwriteclose);
4939 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4941 if (!check_fsp(conn, req, fsp)) {
4942 END_PROFILE(SMBwriteclose);
4945 if (!CHECK_WRITE(fsp)) {
4946 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4947 END_PROFILE(SMBwriteclose);
4951 numtowrite = SVAL(req->vwv+1, 0);
4952 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4953 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4954 data = (const char *)req->buf + 1;
4956 if (!fsp->print_file) {
4957 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4958 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4961 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4962 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4963 END_PROFILE(SMBwriteclose);
4968 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4970 set_close_write_time(fsp, mtime);
4973 * More insanity. W2K only closes the file if writelen > 0.
4978 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4979 "file %s\n", fsp_str_dbg(fsp)));
4980 close_status = close_file(req, fsp, NORMAL_CLOSE);
4983 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4984 fsp->fnum, (int)numtowrite, (int)nwritten,
4985 conn->num_files_open));
4987 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4988 reply_nterror(req, NT_STATUS_DISK_FULL);
4992 if(!NT_STATUS_IS_OK(close_status)) {
4993 reply_nterror(req, close_status);
4997 reply_outbuf(req, 1, 0);
4999 SSVAL(req->outbuf,smb_vwv0,nwritten);
5002 if (numtowrite && !fsp->print_file) {
5003 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5006 END_PROFILE(SMBwriteclose);
5011 #define DBGC_CLASS DBGC_LOCKING
5013 /****************************************************************************
5015 ****************************************************************************/
5017 void reply_lock(struct smb_request *req)
5019 connection_struct *conn = req->conn;
5020 uint64_t count,offset;
5023 struct byte_range_lock *br_lck = NULL;
5025 START_PROFILE(SMBlock);
5028 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5029 END_PROFILE(SMBlock);
5033 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5035 if (!check_fsp(conn, req, fsp)) {
5036 END_PROFILE(SMBlock);
5040 count = (uint64_t)IVAL(req->vwv+1, 0);
5041 offset = (uint64_t)IVAL(req->vwv+3, 0);
5043 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5044 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
5046 br_lck = do_lock(req->sconn->msg_ctx,
5048 (uint64_t)req->smbpid,
5053 False, /* Non-blocking lock. */
5058 TALLOC_FREE(br_lck);
5060 if (NT_STATUS_V(status)) {
5061 reply_nterror(req, status);
5062 END_PROFILE(SMBlock);
5066 reply_outbuf(req, 0, 0);
5068 END_PROFILE(SMBlock);
5072 /****************************************************************************
5074 ****************************************************************************/
5076 void reply_unlock(struct smb_request *req)
5078 connection_struct *conn = req->conn;
5079 uint64_t count,offset;
5083 START_PROFILE(SMBunlock);
5086 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5087 END_PROFILE(SMBunlock);
5091 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5093 if (!check_fsp(conn, req, fsp)) {
5094 END_PROFILE(SMBunlock);
5098 count = (uint64_t)IVAL(req->vwv+1, 0);
5099 offset = (uint64_t)IVAL(req->vwv+3, 0);
5101 status = do_unlock(req->sconn->msg_ctx,
5103 (uint64_t)req->smbpid,
5108 if (NT_STATUS_V(status)) {
5109 reply_nterror(req, status);
5110 END_PROFILE(SMBunlock);
5114 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5115 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
5117 reply_outbuf(req, 0, 0);
5119 END_PROFILE(SMBunlock);
5124 #define DBGC_CLASS DBGC_ALL
5126 /****************************************************************************
5128 conn POINTER CAN BE NULL HERE !
5129 ****************************************************************************/
5131 void reply_tdis(struct smb_request *req)
5133 connection_struct *conn = req->conn;
5134 START_PROFILE(SMBtdis);
5137 DEBUG(4,("Invalid connection in tdis\n"));
5138 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
5139 END_PROFILE(SMBtdis);
5145 close_cnum(conn,req->vuid);
5148 reply_outbuf(req, 0, 0);
5149 END_PROFILE(SMBtdis);
5153 /****************************************************************************
5155 conn POINTER CAN BE NULL HERE !
5156 ****************************************************************************/
5158 void reply_echo(struct smb_request *req)
5160 connection_struct *conn = req->conn;
5161 struct smb_perfcount_data local_pcd;
5162 struct smb_perfcount_data *cur_pcd;
5166 START_PROFILE(SMBecho);
5168 smb_init_perfcount_data(&local_pcd);
5171 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5172 END_PROFILE(SMBecho);
5176 smb_reverb = SVAL(req->vwv+0, 0);
5178 reply_outbuf(req, 1, req->buflen);
5180 /* copy any incoming data back out */
5181 if (req->buflen > 0) {
5182 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5185 if (smb_reverb > 100) {
5186 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5190 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5192 /* this makes sure we catch the request pcd */
5193 if (seq_num == smb_reverb) {
5194 cur_pcd = &req->pcd;
5196 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5197 cur_pcd = &local_pcd;
5200 SSVAL(req->outbuf,smb_vwv0,seq_num);
5202 show_msg((char *)req->outbuf);
5203 if (!srv_send_smb(req->sconn,
5204 (char *)req->outbuf,
5205 true, req->seqnum+1,
5206 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5208 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5211 DEBUG(3,("echo %d times\n", smb_reverb));
5213 TALLOC_FREE(req->outbuf);
5215 END_PROFILE(SMBecho);
5219 /****************************************************************************
5220 Reply to a printopen.
5221 ****************************************************************************/
5223 void reply_printopen(struct smb_request *req)
5225 connection_struct *conn = req->conn;
5229 START_PROFILE(SMBsplopen);
5232 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5233 END_PROFILE(SMBsplopen);
5237 if (!CAN_PRINT(conn)) {
5238 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5239 END_PROFILE(SMBsplopen);
5243 status = file_new(req, conn, &fsp);
5244 if(!NT_STATUS_IS_OK(status)) {
5245 reply_nterror(req, status);
5246 END_PROFILE(SMBsplopen);
5250 /* Open for exclusive use, write only. */
5251 status = print_spool_open(fsp, NULL, req->vuid);
5253 if (!NT_STATUS_IS_OK(status)) {
5254 file_free(req, fsp);
5255 reply_nterror(req, status);
5256 END_PROFILE(SMBsplopen);
5260 reply_outbuf(req, 1, 0);
5261 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5263 DEBUG(3,("openprint fd=%d fnum=%d\n",
5264 fsp->fh->fd, fsp->fnum));
5266 END_PROFILE(SMBsplopen);
5270 /****************************************************************************
5271 Reply to a printclose.
5272 ****************************************************************************/
5274 void reply_printclose(struct smb_request *req)
5276 connection_struct *conn = req->conn;
5280 START_PROFILE(SMBsplclose);
5283 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5284 END_PROFILE(SMBsplclose);
5288 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5290 if (!check_fsp(conn, req, fsp)) {
5291 END_PROFILE(SMBsplclose);
5295 if (!CAN_PRINT(conn)) {
5296 reply_force_doserror(req, ERRSRV, ERRerror);
5297 END_PROFILE(SMBsplclose);
5301 DEBUG(3,("printclose fd=%d fnum=%d\n",
5302 fsp->fh->fd,fsp->fnum));
5304 status = close_file(req, fsp, NORMAL_CLOSE);
5306 if(!NT_STATUS_IS_OK(status)) {
5307 reply_nterror(req, status);
5308 END_PROFILE(SMBsplclose);
5312 reply_outbuf(req, 0, 0);
5314 END_PROFILE(SMBsplclose);
5318 /****************************************************************************
5319 Reply to a printqueue.
5320 ****************************************************************************/
5322 void reply_printqueue(struct smb_request *req)
5324 connection_struct *conn = req->conn;
5328 START_PROFILE(SMBsplretq);
5331 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5332 END_PROFILE(SMBsplretq);
5336 max_count = SVAL(req->vwv+0, 0);
5337 start_index = SVAL(req->vwv+1, 0);
5339 /* we used to allow the client to get the cnum wrong, but that
5340 is really quite gross and only worked when there was only
5341 one printer - I think we should now only accept it if they
5342 get it right (tridge) */
5343 if (!CAN_PRINT(conn)) {
5344 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5345 END_PROFILE(SMBsplretq);
5349 reply_outbuf(req, 2, 3);
5350 SSVAL(req->outbuf,smb_vwv0,0);
5351 SSVAL(req->outbuf,smb_vwv1,0);
5352 SCVAL(smb_buf(req->outbuf),0,1);
5353 SSVAL(smb_buf(req->outbuf),1,0);
5355 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5356 start_index, max_count));
5359 TALLOC_CTX *mem_ctx = talloc_tos();
5362 const char *sharename = lp_servicename(SNUM(conn));
5363 struct rpc_pipe_client *cli = NULL;
5364 struct dcerpc_binding_handle *b = NULL;
5365 struct policy_handle handle;
5366 struct spoolss_DevmodeContainer devmode_ctr;
5367 union spoolss_JobInfo *info;
5369 uint32_t num_to_get;
5373 ZERO_STRUCT(handle);
5375 status = rpc_pipe_open_interface(conn,
5376 &ndr_table_spoolss.syntax_id,
5378 conn->sconn->remote_address,
5379 conn->sconn->msg_ctx,
5381 if (!NT_STATUS_IS_OK(status)) {
5382 DEBUG(0, ("reply_printqueue: "
5383 "could not connect to spoolss: %s\n",
5384 nt_errstr(status)));
5385 reply_nterror(req, status);
5388 b = cli->binding_handle;
5390 ZERO_STRUCT(devmode_ctr);
5392 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5395 SEC_FLAG_MAXIMUM_ALLOWED,
5398 if (!NT_STATUS_IS_OK(status)) {
5399 reply_nterror(req, status);
5402 if (!W_ERROR_IS_OK(werr)) {
5403 reply_nterror(req, werror_to_ntstatus(werr));
5407 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5415 if (!W_ERROR_IS_OK(werr)) {
5416 reply_nterror(req, werror_to_ntstatus(werr));
5420 if (max_count > 0) {
5421 first = start_index;
5423 first = start_index + max_count + 1;
5426 if (first >= count) {
5429 num_to_get = first + MIN(ABS(max_count), count - first);
5432 for (i = first; i < num_to_get; i++) {
5435 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5437 uint16_t qrapjobid = pjobid_to_rap(sharename,
5438 info[i].info2.job_id);
5440 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5446 srv_put_dos_date2(p, 0, qtime);
5447 SCVAL(p, 4, qstatus);
5448 SSVAL(p, 5, qrapjobid);
5449 SIVAL(p, 7, info[i].info2.size);
5451 srvstr_push(blob, req->flags2, p+12,
5452 info[i].info2.notify_name, 16, STR_ASCII);
5454 if (message_push_blob(
5457 blob, sizeof(blob))) == -1) {
5458 reply_nterror(req, NT_STATUS_NO_MEMORY);
5464 SSVAL(req->outbuf,smb_vwv0,count);
5465 SSVAL(req->outbuf,smb_vwv1,
5466 (max_count>0?first+count:first-1));
5467 SCVAL(smb_buf(req->outbuf),0,1);
5468 SSVAL(smb_buf(req->outbuf),1,28*count);
5472 DEBUG(3, ("%u entries returned in queue\n",
5476 if (b && is_valid_policy_hnd(&handle)) {
5477 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5482 END_PROFILE(SMBsplretq);
5486 /****************************************************************************
5487 Reply to a printwrite.
5488 ****************************************************************************/
5490 void reply_printwrite(struct smb_request *req)
5492 connection_struct *conn = req->conn;
5497 START_PROFILE(SMBsplwr);
5500 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5501 END_PROFILE(SMBsplwr);
5505 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5507 if (!check_fsp(conn, req, fsp)) {
5508 END_PROFILE(SMBsplwr);
5512 if (!fsp->print_file) {
5513 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5514 END_PROFILE(SMBsplwr);
5518 if (!CHECK_WRITE(fsp)) {
5519 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5520 END_PROFILE(SMBsplwr);
5524 numtowrite = SVAL(req->buf, 1);
5526 if (req->buflen < numtowrite + 3) {
5527 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5528 END_PROFILE(SMBsplwr);
5532 data = (const char *)req->buf + 3;
5534 if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5535 reply_nterror(req, map_nt_error_from_unix(errno));
5536 END_PROFILE(SMBsplwr);
5540 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5542 END_PROFILE(SMBsplwr);
5546 /****************************************************************************
5548 ****************************************************************************/
5550 void reply_mkdir(struct smb_request *req)
5552 connection_struct *conn = req->conn;
5553 struct smb_filename *smb_dname = NULL;
5554 char *directory = NULL;
5556 TALLOC_CTX *ctx = talloc_tos();
5558 START_PROFILE(SMBmkdir);
5560 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5561 STR_TERMINATE, &status);
5562 if (!NT_STATUS_IS_OK(status)) {
5563 reply_nterror(req, status);
5567 status = filename_convert(ctx, conn,
5568 req->flags2 & FLAGS2_DFS_PATHNAMES,
5573 if (!NT_STATUS_IS_OK(status)) {
5574 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5575 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5576 ERRSRV, ERRbadpath);
5579 reply_nterror(req, status);
5583 status = create_directory(conn, req, smb_dname);
5585 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5587 if (!NT_STATUS_IS_OK(status)) {
5589 if (!use_nt_status()
5590 && NT_STATUS_EQUAL(status,
5591 NT_STATUS_OBJECT_NAME_COLLISION)) {
5593 * Yes, in the DOS error code case we get a
5594 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5595 * samba4 torture test.
5597 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5600 reply_nterror(req, status);
5604 reply_outbuf(req, 0, 0);
5606 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5608 TALLOC_FREE(smb_dname);
5609 END_PROFILE(SMBmkdir);
5613 /****************************************************************************
5615 ****************************************************************************/
5617 void reply_rmdir(struct smb_request *req)
5619 connection_struct *conn = req->conn;
5620 struct smb_filename *smb_dname = NULL;
5621 char *directory = NULL;
5623 TALLOC_CTX *ctx = talloc_tos();
5624 files_struct *fsp = NULL;
5626 struct smbd_server_connection *sconn = req->sconn;
5628 START_PROFILE(SMBrmdir);
5630 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5631 STR_TERMINATE, &status);
5632 if (!NT_STATUS_IS_OK(status)) {
5633 reply_nterror(req, status);
5637 status = filename_convert(ctx, conn,
5638 req->flags2 & FLAGS2_DFS_PATHNAMES,
5643 if (!NT_STATUS_IS_OK(status)) {
5644 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5645 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5646 ERRSRV, ERRbadpath);
5649 reply_nterror(req, status);
5653 if (is_ntfs_stream_smb_fname(smb_dname)) {
5654 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5658 status = SMB_VFS_CREATE_FILE(
5661 0, /* root_dir_fid */
5662 smb_dname, /* fname */
5663 DELETE_ACCESS, /* access_mask */
5664 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5666 FILE_OPEN, /* create_disposition*/
5667 FILE_DIRECTORY_FILE, /* create_options */
5668 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5669 0, /* oplock_request */
5670 0, /* allocation_size */
5671 0, /* private_flags */
5677 if (!NT_STATUS_IS_OK(status)) {
5678 if (open_was_deferred(req->sconn, req->mid)) {
5679 /* We have re-scheduled this call. */
5682 reply_nterror(req, status);
5686 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5687 if (!NT_STATUS_IS_OK(status)) {
5688 close_file(req, fsp, ERROR_CLOSE);
5689 reply_nterror(req, status);
5693 if (!set_delete_on_close(fsp, true, conn->session_info->unix_token)) {
5694 close_file(req, fsp, ERROR_CLOSE);
5695 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5699 status = close_file(req, fsp, NORMAL_CLOSE);
5700 if (!NT_STATUS_IS_OK(status)) {
5701 reply_nterror(req, status);
5703 reply_outbuf(req, 0, 0);
5706 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5708 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5710 TALLOC_FREE(smb_dname);
5711 END_PROFILE(SMBrmdir);
5715 /*******************************************************************
5716 Resolve wildcards in a filename rename.
5717 ********************************************************************/
5719 static bool resolve_wildcards(TALLOC_CTX *ctx,
5724 char *name2_copy = NULL;
5729 char *p,*p2, *pname1, *pname2;
5731 name2_copy = talloc_strdup(ctx, name2);
5736 pname1 = strrchr_m(name1,'/');
5737 pname2 = strrchr_m(name2_copy,'/');
5739 if (!pname1 || !pname2) {
5743 /* Truncate the copy of name2 at the last '/' */
5746 /* Now go past the '/' */
5750 root1 = talloc_strdup(ctx, pname1);
5751 root2 = talloc_strdup(ctx, pname2);
5753 if (!root1 || !root2) {
5757 p = strrchr_m(root1,'.');
5760 ext1 = talloc_strdup(ctx, p+1);
5762 ext1 = talloc_strdup(ctx, "");
5764 p = strrchr_m(root2,'.');
5767 ext2 = talloc_strdup(ctx, p+1);
5769 ext2 = talloc_strdup(ctx, "");
5772 if (!ext1 || !ext2) {
5780 /* Hmmm. Should this be mb-aware ? */
5783 } else if (*p2 == '*') {
5785 root2 = talloc_asprintf(ctx, "%s%s",
5804 /* Hmmm. Should this be mb-aware ? */
5807 } else if (*p2 == '*') {
5809 ext2 = talloc_asprintf(ctx, "%s%s",
5825 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5830 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5842 /****************************************************************************
5843 Ensure open files have their names updated. Updated to notify other smbd's
5845 ****************************************************************************/
5847 static void rename_open_files(connection_struct *conn,
5848 struct share_mode_lock *lck,
5849 uint32_t orig_name_hash,
5850 const struct smb_filename *smb_fname_dst)
5853 bool did_rename = False;
5855 uint32_t new_name_hash = 0;
5857 for(fsp = file_find_di_first(conn->sconn, lck->data->id); fsp;
5858 fsp = file_find_di_next(fsp)) {
5859 /* fsp_name is a relative path under the fsp. To change this for other
5860 sharepaths we need to manipulate relative paths. */
5861 /* TODO - create the absolute path and manipulate the newname
5862 relative to the sharepath. */
5863 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5866 if (fsp->name_hash != orig_name_hash) {
5869 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5870 "(file_id %s) from %s -> %s\n", fsp->fnum,
5871 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5872 smb_fname_str_dbg(smb_fname_dst)));
5874 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5875 if (NT_STATUS_IS_OK(status)) {
5877 new_name_hash = fsp->name_hash;
5882 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5883 "for %s\n", file_id_string_tos(&lck->data->id),
5884 smb_fname_str_dbg(smb_fname_dst)));
5887 /* Send messages to all smbd's (not ourself) that the name has changed. */
5888 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5889 orig_name_hash, new_name_hash,
5894 /****************************************************************************
5895 We need to check if the source path is a parent directory of the destination
5896 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5897 refuse the rename with a sharing violation. Under UNIX the above call can
5898 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5899 probably need to check that the client is a Windows one before disallowing
5900 this as a UNIX client (one with UNIX extensions) can know the source is a
5901 symlink and make this decision intelligently. Found by an excellent bug
5902 report from <AndyLiebman@aol.com>.
5903 ****************************************************************************/
5905 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5906 const struct smb_filename *smb_fname_dst)
5908 const char *psrc = smb_fname_src->base_name;
5909 const char *pdst = smb_fname_dst->base_name;
5912 if (psrc[0] == '.' && psrc[1] == '/') {
5915 if (pdst[0] == '.' && pdst[1] == '/') {
5918 if ((slen = strlen(psrc)) > strlen(pdst)) {
5921 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5925 * Do the notify calls from a rename
5928 static void notify_rename(connection_struct *conn, bool is_dir,
5929 const struct smb_filename *smb_fname_src,
5930 const struct smb_filename *smb_fname_dst)
5932 char *parent_dir_src = NULL;
5933 char *parent_dir_dst = NULL;
5936 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5937 : FILE_NOTIFY_CHANGE_FILE_NAME;
5939 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5940 &parent_dir_src, NULL) ||
5941 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5942 &parent_dir_dst, NULL)) {
5946 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5947 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5948 smb_fname_src->base_name);
5949 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5950 smb_fname_dst->base_name);
5953 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5954 smb_fname_src->base_name);
5955 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5956 smb_fname_dst->base_name);
5959 /* this is a strange one. w2k3 gives an additional event for
5960 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5961 files, but not directories */
5963 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5964 FILE_NOTIFY_CHANGE_ATTRIBUTES
5965 |FILE_NOTIFY_CHANGE_CREATION,
5966 smb_fname_dst->base_name);
5969 TALLOC_FREE(parent_dir_src);
5970 TALLOC_FREE(parent_dir_dst);
5973 /****************************************************************************
5974 Returns an error if the parent directory for a filename is open in an
5976 ****************************************************************************/
5978 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
5979 const struct smb_filename *smb_fname_dst_in)
5981 char *parent_dir = NULL;
5982 struct smb_filename smb_fname_parent;
5984 files_struct *fsp = NULL;
5987 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
5988 &parent_dir, NULL)) {
5989 return NT_STATUS_NO_MEMORY;
5991 ZERO_STRUCT(smb_fname_parent);
5992 smb_fname_parent.base_name = parent_dir;
5994 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
5996 return map_nt_error_from_unix(errno);
6000 * We're only checking on this smbd here, mostly good
6001 * enough.. and will pass tests.
6004 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6005 for (fsp = file_find_di_first(conn->sconn, id); fsp;
6006 fsp = file_find_di_next(fsp)) {
6007 if (fsp->access_mask & DELETE_ACCESS) {
6008 return NT_STATUS_SHARING_VIOLATION;
6011 return NT_STATUS_OK;
6014 /****************************************************************************
6015 Rename an open file - given an fsp.
6016 ****************************************************************************/
6018 NTSTATUS rename_internals_fsp(connection_struct *conn,
6020 const struct smb_filename *smb_fname_dst_in,
6022 bool replace_if_exists)
6024 TALLOC_CTX *ctx = talloc_tos();
6025 struct smb_filename *smb_fname_dst = NULL;
6026 NTSTATUS status = NT_STATUS_OK;
6027 struct share_mode_lock *lck = NULL;
6028 bool dst_exists, old_is_stream, new_is_stream;
6030 status = check_name(conn, smb_fname_dst_in->base_name);
6031 if (!NT_STATUS_IS_OK(status)) {
6035 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6036 if (!NT_STATUS_IS_OK(status)) {
6040 /* Make a copy of the dst smb_fname structs */
6042 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
6043 if (!NT_STATUS_IS_OK(status)) {
6048 * Check for special case with case preserving and not
6049 * case sensitive. If the old last component differs from the original
6050 * last component only by case, then we should allow
6051 * the rename (user is trying to change the case of the
6054 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
6055 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6056 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6058 char *fname_dst_lcomp_base_mod = NULL;
6059 struct smb_filename *smb_fname_orig_lcomp = NULL;
6062 * Get the last component of the destination name.
6064 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
6066 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
6068 fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
6070 if (!fname_dst_lcomp_base_mod) {
6071 status = NT_STATUS_NO_MEMORY;
6076 * Create an smb_filename struct using the original last
6077 * component of the destination.
6079 status = create_synthetic_smb_fname_split(ctx,
6080 smb_fname_dst->original_lcomp, NULL,
6081 &smb_fname_orig_lcomp);
6082 if (!NT_STATUS_IS_OK(status)) {
6083 TALLOC_FREE(fname_dst_lcomp_base_mod);
6087 /* If the base names only differ by case, use original. */
6088 if(!strcsequal(fname_dst_lcomp_base_mod,
6089 smb_fname_orig_lcomp->base_name)) {
6092 * Replace the modified last component with the
6096 *last_slash = '\0'; /* Truncate at the '/' */
6097 tmp = talloc_asprintf(smb_fname_dst,
6099 smb_fname_dst->base_name,
6100 smb_fname_orig_lcomp->base_name);
6102 tmp = talloc_asprintf(smb_fname_dst,
6104 smb_fname_orig_lcomp->base_name);
6107 status = NT_STATUS_NO_MEMORY;
6108 TALLOC_FREE(fname_dst_lcomp_base_mod);
6109 TALLOC_FREE(smb_fname_orig_lcomp);
6112 TALLOC_FREE(smb_fname_dst->base_name);
6113 smb_fname_dst->base_name = tmp;
6116 /* If the stream_names only differ by case, use original. */
6117 if(!strcsequal(smb_fname_dst->stream_name,
6118 smb_fname_orig_lcomp->stream_name)) {
6120 /* Use the original stream. */
6121 tmp = talloc_strdup(smb_fname_dst,
6122 smb_fname_orig_lcomp->stream_name);
6124 status = NT_STATUS_NO_MEMORY;
6125 TALLOC_FREE(fname_dst_lcomp_base_mod);
6126 TALLOC_FREE(smb_fname_orig_lcomp);
6129 TALLOC_FREE(smb_fname_dst->stream_name);
6130 smb_fname_dst->stream_name = tmp;
6132 TALLOC_FREE(fname_dst_lcomp_base_mod);
6133 TALLOC_FREE(smb_fname_orig_lcomp);
6137 * If the src and dest names are identical - including case,
6138 * don't do the rename, just return success.
6141 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6142 strcsequal(fsp->fsp_name->stream_name,
6143 smb_fname_dst->stream_name)) {
6144 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6145 "- returning success\n",
6146 smb_fname_str_dbg(smb_fname_dst)));
6147 status = NT_STATUS_OK;
6151 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6152 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6154 /* Return the correct error code if both names aren't streams. */
6155 if (!old_is_stream && new_is_stream) {
6156 status = NT_STATUS_OBJECT_NAME_INVALID;
6160 if (old_is_stream && !new_is_stream) {
6161 status = NT_STATUS_INVALID_PARAMETER;
6165 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6167 if(!replace_if_exists && dst_exists) {
6168 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6169 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6170 smb_fname_str_dbg(smb_fname_dst)));
6171 status = NT_STATUS_OBJECT_NAME_COLLISION;
6176 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6177 &smb_fname_dst->st);
6178 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6180 /* The file can be open when renaming a stream */
6181 if (dst_fsp && !new_is_stream) {
6182 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6183 status = NT_STATUS_ACCESS_DENIED;
6188 /* Ensure we have a valid stat struct for the source. */
6189 status = vfs_stat_fsp(fsp);
6190 if (!NT_STATUS_IS_OK(status)) {
6194 status = can_rename(conn, fsp, attrs);
6196 if (!NT_STATUS_IS_OK(status)) {
6197 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6198 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6199 smb_fname_str_dbg(smb_fname_dst)));
6200 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6201 status = NT_STATUS_ACCESS_DENIED;
6205 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6206 status = NT_STATUS_ACCESS_DENIED;
6209 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6212 * We have the file open ourselves, so not being able to get the
6213 * corresponding share mode lock is a fatal error.
6216 SMB_ASSERT(lck != NULL);
6218 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6219 uint32 create_options = fsp->fh->private_options;
6221 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6222 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6223 smb_fname_str_dbg(smb_fname_dst)));
6225 if (!lp_posix_pathnames() &&
6226 (lp_map_archive(SNUM(conn)) ||
6227 lp_store_dos_attributes(SNUM(conn)))) {
6228 /* We must set the archive bit on the newly
6230 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6231 uint32_t old_dosmode = dos_mode(conn,
6233 file_set_dosmode(conn,
6235 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6241 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6244 rename_open_files(conn, lck, fsp->name_hash, smb_fname_dst);
6247 * A rename acts as a new file create w.r.t. allowing an initial delete
6248 * on close, probably because in Windows there is a new handle to the
6249 * new file. If initial delete on close was requested but not
6250 * originally set, we need to set it here. This is probably not 100% correct,
6251 * but will work for the CIFSFS client which in non-posix mode
6252 * depends on these semantics. JRA.
6255 if (create_options & FILE_DELETE_ON_CLOSE) {
6256 status = can_set_delete_on_close(fsp, 0);
6258 if (NT_STATUS_IS_OK(status)) {
6259 /* Note that here we set the *inital* delete on close flag,
6260 * not the regular one. The magic gets handled in close. */
6261 fsp->initial_delete_on_close = True;
6265 status = NT_STATUS_OK;
6271 if (errno == ENOTDIR || errno == EISDIR) {
6272 status = NT_STATUS_OBJECT_NAME_COLLISION;
6274 status = map_nt_error_from_unix(errno);
6277 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6278 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6279 smb_fname_str_dbg(smb_fname_dst)));
6282 TALLOC_FREE(smb_fname_dst);
6287 /****************************************************************************
6288 The guts of the rename command, split out so it may be called by the NT SMB
6290 ****************************************************************************/
6292 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6293 connection_struct *conn,
6294 struct smb_request *req,
6295 struct smb_filename *smb_fname_src,
6296 struct smb_filename *smb_fname_dst,
6298 bool replace_if_exists,
6301 uint32_t access_mask)
6303 char *fname_src_dir = NULL;
6304 char *fname_src_mask = NULL;
6306 NTSTATUS status = NT_STATUS_OK;
6307 struct smb_Dir *dir_hnd = NULL;
6308 const char *dname = NULL;
6309 char *talloced = NULL;
6311 int create_options = 0;
6312 bool posix_pathnames = lp_posix_pathnames();
6315 * Split the old name into directory and last component
6316 * strings. Note that unix_convert may have stripped off a
6317 * leading ./ from both name and newname if the rename is
6318 * at the root of the share. We need to make sure either both
6319 * name and newname contain a / character or neither of them do
6320 * as this is checked in resolve_wildcards().
6323 /* Split up the directory from the filename/mask. */
6324 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6325 &fname_src_dir, &fname_src_mask);
6326 if (!NT_STATUS_IS_OK(status)) {
6327 status = NT_STATUS_NO_MEMORY;
6332 * We should only check the mangled cache
6333 * here if unix_convert failed. This means
6334 * that the path in 'mask' doesn't exist
6335 * on the file system and so we need to look
6336 * for a possible mangle. This patch from
6337 * Tine Smukavec <valentin.smukavec@hermes.si>.
6340 if (!VALID_STAT(smb_fname_src->st) &&
6341 mangle_is_mangled(fname_src_mask, conn->params)) {
6342 char *new_mask = NULL;
6343 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6346 TALLOC_FREE(fname_src_mask);
6347 fname_src_mask = new_mask;
6351 if (!src_has_wild) {
6355 * Only one file needs to be renamed. Append the mask back
6356 * onto the directory.
6358 TALLOC_FREE(smb_fname_src->base_name);
6359 if (ISDOT(fname_src_dir)) {
6360 /* Ensure we use canonical names on open. */
6361 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6365 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6370 if (!smb_fname_src->base_name) {
6371 status = NT_STATUS_NO_MEMORY;
6375 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6376 "case_preserve = %d, short case preserve = %d, "
6377 "directory = %s, newname = %s, "
6378 "last_component_dest = %s\n",
6379 conn->case_sensitive, conn->case_preserve,
6380 conn->short_case_preserve,
6381 smb_fname_str_dbg(smb_fname_src),
6382 smb_fname_str_dbg(smb_fname_dst),
6383 smb_fname_dst->original_lcomp));
6385 /* The dest name still may have wildcards. */
6386 if (dest_has_wild) {
6387 char *fname_dst_mod = NULL;
6388 if (!resolve_wildcards(smb_fname_dst,
6389 smb_fname_src->base_name,
6390 smb_fname_dst->base_name,
6392 DEBUG(6, ("rename_internals: resolve_wildcards "
6394 smb_fname_src->base_name,
6395 smb_fname_dst->base_name));
6396 status = NT_STATUS_NO_MEMORY;
6399 TALLOC_FREE(smb_fname_dst->base_name);
6400 smb_fname_dst->base_name = fname_dst_mod;
6403 ZERO_STRUCT(smb_fname_src->st);
6404 if (posix_pathnames) {
6405 SMB_VFS_LSTAT(conn, smb_fname_src);
6407 SMB_VFS_STAT(conn, smb_fname_src);
6410 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6411 create_options |= FILE_DIRECTORY_FILE;
6414 status = SMB_VFS_CREATE_FILE(
6417 0, /* root_dir_fid */
6418 smb_fname_src, /* fname */
6419 access_mask, /* access_mask */
6420 (FILE_SHARE_READ | /* share_access */
6422 FILE_OPEN, /* create_disposition*/
6423 create_options, /* create_options */
6424 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6425 0, /* oplock_request */
6426 0, /* allocation_size */
6427 0, /* private_flags */
6433 if (!NT_STATUS_IS_OK(status)) {
6434 DEBUG(3, ("Could not open rename source %s: %s\n",
6435 smb_fname_str_dbg(smb_fname_src),
6436 nt_errstr(status)));
6440 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6441 attrs, replace_if_exists);
6443 close_file(req, fsp, NORMAL_CLOSE);
6445 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6446 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6447 smb_fname_str_dbg(smb_fname_dst)));
6453 * Wildcards - process each file that matches.
6455 if (strequal(fname_src_mask, "????????.???")) {
6456 TALLOC_FREE(fname_src_mask);
6457 fname_src_mask = talloc_strdup(ctx, "*");
6458 if (!fname_src_mask) {
6459 status = NT_STATUS_NO_MEMORY;
6464 status = check_name(conn, fname_src_dir);
6465 if (!NT_STATUS_IS_OK(status)) {
6469 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6471 if (dir_hnd == NULL) {
6472 status = map_nt_error_from_unix(errno);
6476 status = NT_STATUS_NO_SUCH_FILE;
6478 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6479 * - gentest fix. JRA
6482 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6484 files_struct *fsp = NULL;
6485 char *destname = NULL;
6486 bool sysdir_entry = False;
6488 /* Quick check for "." and ".." */
6489 if (ISDOT(dname) || ISDOTDOT(dname)) {
6490 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6491 sysdir_entry = True;
6493 TALLOC_FREE(talloced);
6498 if (!is_visible_file(conn, fname_src_dir, dname,
6499 &smb_fname_src->st, false)) {
6500 TALLOC_FREE(talloced);
6504 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6505 TALLOC_FREE(talloced);
6510 status = NT_STATUS_OBJECT_NAME_INVALID;
6514 TALLOC_FREE(smb_fname_src->base_name);
6515 if (ISDOT(fname_src_dir)) {
6516 /* Ensure we use canonical names on open. */
6517 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6521 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6526 if (!smb_fname_src->base_name) {
6527 status = NT_STATUS_NO_MEMORY;
6531 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6532 smb_fname_dst->base_name,
6534 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6535 smb_fname_src->base_name, destname));
6536 TALLOC_FREE(talloced);
6540 status = NT_STATUS_NO_MEMORY;
6544 TALLOC_FREE(smb_fname_dst->base_name);
6545 smb_fname_dst->base_name = destname;
6547 ZERO_STRUCT(smb_fname_src->st);
6548 if (posix_pathnames) {
6549 SMB_VFS_LSTAT(conn, smb_fname_src);
6551 SMB_VFS_STAT(conn, smb_fname_src);
6556 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6557 create_options |= FILE_DIRECTORY_FILE;
6560 status = SMB_VFS_CREATE_FILE(
6563 0, /* root_dir_fid */
6564 smb_fname_src, /* fname */
6565 access_mask, /* access_mask */
6566 (FILE_SHARE_READ | /* share_access */
6568 FILE_OPEN, /* create_disposition*/
6569 create_options, /* create_options */
6570 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6571 0, /* oplock_request */
6572 0, /* allocation_size */
6573 0, /* private_flags */
6579 if (!NT_STATUS_IS_OK(status)) {
6580 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6581 "returned %s rename %s -> %s\n",
6583 smb_fname_str_dbg(smb_fname_src),
6584 smb_fname_str_dbg(smb_fname_dst)));
6588 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6590 if (!smb_fname_dst->original_lcomp) {
6591 status = NT_STATUS_NO_MEMORY;
6595 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6596 attrs, replace_if_exists);
6598 close_file(req, fsp, NORMAL_CLOSE);
6600 if (!NT_STATUS_IS_OK(status)) {
6601 DEBUG(3, ("rename_internals_fsp returned %s for "
6602 "rename %s -> %s\n", nt_errstr(status),
6603 smb_fname_str_dbg(smb_fname_src),
6604 smb_fname_str_dbg(smb_fname_dst)));
6610 DEBUG(3,("rename_internals: doing rename on %s -> "
6611 "%s\n", smb_fname_str_dbg(smb_fname_src),
6612 smb_fname_str_dbg(smb_fname_src)));
6613 TALLOC_FREE(talloced);
6615 TALLOC_FREE(dir_hnd);
6617 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6618 status = map_nt_error_from_unix(errno);
6622 TALLOC_FREE(talloced);
6623 TALLOC_FREE(fname_src_dir);
6624 TALLOC_FREE(fname_src_mask);
6628 /****************************************************************************
6630 ****************************************************************************/
6632 void reply_mv(struct smb_request *req)
6634 connection_struct *conn = req->conn;
6636 char *newname = NULL;
6640 bool src_has_wcard = False;
6641 bool dest_has_wcard = False;
6642 TALLOC_CTX *ctx = talloc_tos();
6643 struct smb_filename *smb_fname_src = NULL;
6644 struct smb_filename *smb_fname_dst = NULL;
6645 uint32_t src_ucf_flags = lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP : UCF_COND_ALLOW_WCARD_LCOMP;
6646 uint32_t dst_ucf_flags = UCF_SAVE_LCOMP | (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP);
6647 bool stream_rename = false;
6649 START_PROFILE(SMBmv);
6652 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6656 attrs = SVAL(req->vwv+0, 0);
6658 p = (const char *)req->buf + 1;
6659 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6660 &status, &src_has_wcard);
6661 if (!NT_STATUS_IS_OK(status)) {
6662 reply_nterror(req, status);
6666 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6667 &status, &dest_has_wcard);
6668 if (!NT_STATUS_IS_OK(status)) {
6669 reply_nterror(req, status);
6673 if (!lp_posix_pathnames()) {
6674 /* The newname must begin with a ':' if the
6675 name contains a ':'. */
6676 if (strchr_m(name, ':')) {
6677 if (newname[0] != ':') {
6678 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6681 stream_rename = true;
6685 status = filename_convert(ctx,
6687 req->flags2 & FLAGS2_DFS_PATHNAMES,
6693 if (!NT_STATUS_IS_OK(status)) {
6694 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6695 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6696 ERRSRV, ERRbadpath);
6699 reply_nterror(req, status);
6703 status = filename_convert(ctx,
6705 req->flags2 & FLAGS2_DFS_PATHNAMES,
6711 if (!NT_STATUS_IS_OK(status)) {
6712 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6713 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6714 ERRSRV, ERRbadpath);
6717 reply_nterror(req, status);
6721 if (stream_rename) {
6722 /* smb_fname_dst->base_name must be the same as
6723 smb_fname_src->base_name. */
6724 TALLOC_FREE(smb_fname_dst->base_name);
6725 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6726 smb_fname_src->base_name);
6727 if (!smb_fname_dst->base_name) {
6728 reply_nterror(req, NT_STATUS_NO_MEMORY);
6733 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6734 smb_fname_str_dbg(smb_fname_dst)));
6736 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6737 attrs, False, src_has_wcard, dest_has_wcard,
6739 if (!NT_STATUS_IS_OK(status)) {
6740 if (open_was_deferred(req->sconn, req->mid)) {
6741 /* We have re-scheduled this call. */
6744 reply_nterror(req, status);
6748 reply_outbuf(req, 0, 0);
6750 TALLOC_FREE(smb_fname_src);
6751 TALLOC_FREE(smb_fname_dst);
6756 /*******************************************************************
6757 Copy a file as part of a reply_copy.
6758 ******************************************************************/
6761 * TODO: check error codes on all callers
6764 NTSTATUS copy_file(TALLOC_CTX *ctx,
6765 connection_struct *conn,
6766 struct smb_filename *smb_fname_src,
6767 struct smb_filename *smb_fname_dst,
6770 bool target_is_directory)
6772 struct smb_filename *smb_fname_dst_tmp = NULL;
6774 files_struct *fsp1,*fsp2;
6776 uint32 new_create_disposition;
6780 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6781 if (!NT_STATUS_IS_OK(status)) {
6786 * If the target is a directory, extract the last component from the
6787 * src filename and append it to the dst filename
6789 if (target_is_directory) {
6792 /* dest/target can't be a stream if it's a directory. */
6793 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6795 p = strrchr_m(smb_fname_src->base_name,'/');
6799 p = smb_fname_src->base_name;
6801 smb_fname_dst_tmp->base_name =
6802 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6804 if (!smb_fname_dst_tmp->base_name) {
6805 status = NT_STATUS_NO_MEMORY;
6810 status = vfs_file_exist(conn, smb_fname_src);
6811 if (!NT_STATUS_IS_OK(status)) {
6815 if (!target_is_directory && count) {
6816 new_create_disposition = FILE_OPEN;
6818 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
6821 &new_create_disposition,
6824 status = NT_STATUS_INVALID_PARAMETER;
6829 /* Open the src file for reading. */
6830 status = SMB_VFS_CREATE_FILE(
6833 0, /* root_dir_fid */
6834 smb_fname_src, /* fname */
6835 FILE_GENERIC_READ, /* access_mask */
6836 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6837 FILE_OPEN, /* create_disposition*/
6838 0, /* create_options */
6839 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6840 INTERNAL_OPEN_ONLY, /* oplock_request */
6841 0, /* allocation_size */
6842 0, /* private_flags */
6848 if (!NT_STATUS_IS_OK(status)) {
6852 dosattrs = dos_mode(conn, smb_fname_src);
6854 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6855 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6858 /* Open the dst file for writing. */
6859 status = SMB_VFS_CREATE_FILE(
6862 0, /* root_dir_fid */
6863 smb_fname_dst, /* fname */
6864 FILE_GENERIC_WRITE, /* access_mask */
6865 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6866 new_create_disposition, /* create_disposition*/
6867 0, /* create_options */
6868 dosattrs, /* file_attributes */
6869 INTERNAL_OPEN_ONLY, /* oplock_request */
6870 0, /* allocation_size */
6871 0, /* private_flags */
6877 if (!NT_STATUS_IS_OK(status)) {
6878 close_file(NULL, fsp1, ERROR_CLOSE);
6882 if (ofun & OPENX_FILE_EXISTS_OPEN) {
6883 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
6885 DEBUG(0, ("error - vfs lseek returned error %s\n",
6887 status = map_nt_error_from_unix(errno);
6888 close_file(NULL, fsp1, ERROR_CLOSE);
6889 close_file(NULL, fsp2, ERROR_CLOSE);
6894 /* Do the actual copy. */
6895 if (smb_fname_src->st.st_ex_size) {
6896 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6901 close_file(NULL, fsp1, NORMAL_CLOSE);
6903 /* Ensure the modtime is set correctly on the destination file. */
6904 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6907 * As we are opening fsp1 read-only we only expect
6908 * an error on close on fsp2 if we are out of space.
6909 * Thus we don't look at the error return from the
6912 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6914 if (!NT_STATUS_IS_OK(status)) {
6918 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6919 status = NT_STATUS_DISK_FULL;
6923 status = NT_STATUS_OK;
6926 TALLOC_FREE(smb_fname_dst_tmp);
6930 /****************************************************************************
6931 Reply to a file copy.
6932 ****************************************************************************/
6934 void reply_copy(struct smb_request *req)
6936 connection_struct *conn = req->conn;
6937 struct smb_filename *smb_fname_src = NULL;
6938 struct smb_filename *smb_fname_dst = NULL;
6939 char *fname_src = NULL;
6940 char *fname_dst = NULL;
6941 char *fname_src_mask = NULL;
6942 char *fname_src_dir = NULL;
6945 int error = ERRnoaccess;
6949 bool target_is_directory=False;
6950 bool source_has_wild = False;
6951 bool dest_has_wild = False;
6953 TALLOC_CTX *ctx = talloc_tos();
6955 START_PROFILE(SMBcopy);
6958 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6962 tid2 = SVAL(req->vwv+0, 0);
6963 ofun = SVAL(req->vwv+1, 0);
6964 flags = SVAL(req->vwv+2, 0);
6966 p = (const char *)req->buf;
6967 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6968 &status, &source_has_wild);
6969 if (!NT_STATUS_IS_OK(status)) {
6970 reply_nterror(req, status);
6973 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6974 &status, &dest_has_wild);
6975 if (!NT_STATUS_IS_OK(status)) {
6976 reply_nterror(req, status);
6980 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6982 if (tid2 != conn->cnum) {
6983 /* can't currently handle inter share copies XXXX */
6984 DEBUG(3,("Rejecting inter-share copy\n"));
6985 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6989 status = filename_convert(ctx, conn,
6990 req->flags2 & FLAGS2_DFS_PATHNAMES,
6992 UCF_COND_ALLOW_WCARD_LCOMP,
6995 if (!NT_STATUS_IS_OK(status)) {
6996 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6997 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6998 ERRSRV, ERRbadpath);
7001 reply_nterror(req, status);
7005 status = filename_convert(ctx, conn,
7006 req->flags2 & FLAGS2_DFS_PATHNAMES,
7008 UCF_COND_ALLOW_WCARD_LCOMP,
7011 if (!NT_STATUS_IS_OK(status)) {
7012 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7013 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7014 ERRSRV, ERRbadpath);
7017 reply_nterror(req, status);
7021 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7023 if ((flags&1) && target_is_directory) {
7024 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7028 if ((flags&2) && !target_is_directory) {
7029 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7033 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7034 /* wants a tree copy! XXXX */
7035 DEBUG(3,("Rejecting tree copy\n"));
7036 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7040 /* Split up the directory from the filename/mask. */
7041 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7042 &fname_src_dir, &fname_src_mask);
7043 if (!NT_STATUS_IS_OK(status)) {
7044 reply_nterror(req, NT_STATUS_NO_MEMORY);
7049 * We should only check the mangled cache
7050 * here if unix_convert failed. This means
7051 * that the path in 'mask' doesn't exist
7052 * on the file system and so we need to look
7053 * for a possible mangle. This patch from
7054 * Tine Smukavec <valentin.smukavec@hermes.si>.
7056 if (!VALID_STAT(smb_fname_src->st) &&
7057 mangle_is_mangled(fname_src_mask, conn->params)) {
7058 char *new_mask = NULL;
7059 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7060 &new_mask, conn->params);
7062 /* Use demangled name if one was successfully found. */
7064 TALLOC_FREE(fname_src_mask);
7065 fname_src_mask = new_mask;
7069 if (!source_has_wild) {
7072 * Only one file needs to be copied. Append the mask back onto
7075 TALLOC_FREE(smb_fname_src->base_name);
7076 if (ISDOT(fname_src_dir)) {
7077 /* Ensure we use canonical names on open. */
7078 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7082 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7087 if (!smb_fname_src->base_name) {
7088 reply_nterror(req, NT_STATUS_NO_MEMORY);
7092 if (dest_has_wild) {
7093 char *fname_dst_mod = NULL;
7094 if (!resolve_wildcards(smb_fname_dst,
7095 smb_fname_src->base_name,
7096 smb_fname_dst->base_name,
7098 reply_nterror(req, NT_STATUS_NO_MEMORY);
7101 TALLOC_FREE(smb_fname_dst->base_name);
7102 smb_fname_dst->base_name = fname_dst_mod;
7105 status = check_name(conn, smb_fname_src->base_name);
7106 if (!NT_STATUS_IS_OK(status)) {
7107 reply_nterror(req, status);
7111 status = check_name(conn, smb_fname_dst->base_name);
7112 if (!NT_STATUS_IS_OK(status)) {
7113 reply_nterror(req, status);
7117 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7118 ofun, count, target_is_directory);
7120 if(!NT_STATUS_IS_OK(status)) {
7121 reply_nterror(req, status);
7127 struct smb_Dir *dir_hnd = NULL;
7128 const char *dname = NULL;
7129 char *talloced = NULL;
7133 * There is a wildcard that requires us to actually read the
7134 * src dir and copy each file matching the mask to the dst.
7135 * Right now streams won't be copied, but this could
7136 * presumably be added with a nested loop for reach dir entry.
7138 SMB_ASSERT(!smb_fname_src->stream_name);
7139 SMB_ASSERT(!smb_fname_dst->stream_name);
7141 smb_fname_src->stream_name = NULL;
7142 smb_fname_dst->stream_name = NULL;
7144 if (strequal(fname_src_mask,"????????.???")) {
7145 TALLOC_FREE(fname_src_mask);
7146 fname_src_mask = talloc_strdup(ctx, "*");
7147 if (!fname_src_mask) {
7148 reply_nterror(req, NT_STATUS_NO_MEMORY);
7153 status = check_name(conn, fname_src_dir);
7154 if (!NT_STATUS_IS_OK(status)) {
7155 reply_nterror(req, status);
7159 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7160 if (dir_hnd == NULL) {
7161 status = map_nt_error_from_unix(errno);
7162 reply_nterror(req, status);
7168 /* Iterate over the src dir copying each entry to the dst. */
7169 while ((dname = ReadDirName(dir_hnd, &offset,
7170 &smb_fname_src->st, &talloced))) {
7171 char *destname = NULL;
7173 if (ISDOT(dname) || ISDOTDOT(dname)) {
7174 TALLOC_FREE(talloced);
7178 if (!is_visible_file(conn, fname_src_dir, dname,
7179 &smb_fname_src->st, false)) {
7180 TALLOC_FREE(talloced);
7184 if(!mask_match(dname, fname_src_mask,
7185 conn->case_sensitive)) {
7186 TALLOC_FREE(talloced);
7190 error = ERRnoaccess;
7192 /* Get the src smb_fname struct setup. */
7193 TALLOC_FREE(smb_fname_src->base_name);
7194 if (ISDOT(fname_src_dir)) {
7195 /* Ensure we use canonical names on open. */
7196 smb_fname_src->base_name =
7197 talloc_asprintf(smb_fname_src, "%s",
7200 smb_fname_src->base_name =
7201 talloc_asprintf(smb_fname_src, "%s/%s",
7202 fname_src_dir, dname);
7205 if (!smb_fname_src->base_name) {
7206 TALLOC_FREE(dir_hnd);
7207 TALLOC_FREE(talloced);
7208 reply_nterror(req, NT_STATUS_NO_MEMORY);
7212 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7213 smb_fname_dst->base_name,
7215 TALLOC_FREE(talloced);
7219 TALLOC_FREE(dir_hnd);
7220 TALLOC_FREE(talloced);
7221 reply_nterror(req, NT_STATUS_NO_MEMORY);
7225 TALLOC_FREE(smb_fname_dst->base_name);
7226 smb_fname_dst->base_name = destname;
7228 status = check_name(conn, smb_fname_src->base_name);
7229 if (!NT_STATUS_IS_OK(status)) {
7230 TALLOC_FREE(dir_hnd);
7231 TALLOC_FREE(talloced);
7232 reply_nterror(req, status);
7236 status = check_name(conn, smb_fname_dst->base_name);
7237 if (!NT_STATUS_IS_OK(status)) {
7238 TALLOC_FREE(dir_hnd);
7239 TALLOC_FREE(talloced);
7240 reply_nterror(req, status);
7244 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7245 smb_fname_src->base_name,
7246 smb_fname_dst->base_name));
7248 status = copy_file(ctx, conn, smb_fname_src,
7249 smb_fname_dst, ofun, count,
7250 target_is_directory);
7251 if (NT_STATUS_IS_OK(status)) {
7255 TALLOC_FREE(talloced);
7257 TALLOC_FREE(dir_hnd);
7261 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7265 reply_outbuf(req, 1, 0);
7266 SSVAL(req->outbuf,smb_vwv0,count);
7268 TALLOC_FREE(smb_fname_src);
7269 TALLOC_FREE(smb_fname_dst);
7270 TALLOC_FREE(fname_src);
7271 TALLOC_FREE(fname_dst);
7272 TALLOC_FREE(fname_src_mask);
7273 TALLOC_FREE(fname_src_dir);
7275 END_PROFILE(SMBcopy);
7280 #define DBGC_CLASS DBGC_LOCKING
7282 /****************************************************************************
7283 Get a lock pid, dealing with large count requests.
7284 ****************************************************************************/
7286 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7287 bool large_file_format)
7289 if(!large_file_format)
7290 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7292 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7295 /****************************************************************************
7296 Get a lock count, dealing with large count requests.
7297 ****************************************************************************/
7299 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7300 bool large_file_format)
7304 if(!large_file_format) {
7305 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7308 #if defined(HAVE_LONGLONG)
7309 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7310 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7311 #else /* HAVE_LONGLONG */
7314 * NT4.x seems to be broken in that it sends large file (64 bit)
7315 * lockingX calls even if the CAP_LARGE_FILES was *not*
7316 * negotiated. For boxes without large unsigned ints truncate the
7317 * lock count by dropping the top 32 bits.
7320 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7321 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7322 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7323 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7324 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7327 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7328 #endif /* HAVE_LONGLONG */
7334 #if !defined(HAVE_LONGLONG)
7335 /****************************************************************************
7336 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7337 ****************************************************************************/
7339 static uint32 map_lock_offset(uint32 high, uint32 low)
7343 uint32 highcopy = high;
7346 * Try and find out how many significant bits there are in high.
7349 for(i = 0; highcopy; i++)
7353 * We use 31 bits not 32 here as POSIX
7354 * lock offsets may not be negative.
7357 mask = (~0) << (31 - i);
7360 return 0; /* Fail. */
7366 #endif /* !defined(HAVE_LONGLONG) */
7368 /****************************************************************************
7369 Get a lock offset, dealing with large offset requests.
7370 ****************************************************************************/
7372 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7373 bool large_file_format, bool *err)
7375 uint64_t offset = 0;
7379 if(!large_file_format) {
7380 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7383 #if defined(HAVE_LONGLONG)
7384 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7385 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7386 #else /* HAVE_LONGLONG */
7389 * NT4.x seems to be broken in that it sends large file (64 bit)
7390 * lockingX calls even if the CAP_LARGE_FILES was *not*
7391 * negotiated. For boxes without large unsigned ints mangle the
7392 * lock offset by mapping the top 32 bits onto the lower 32.
7395 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7396 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7397 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7400 if((new_low = map_lock_offset(high, low)) == 0) {
7402 return (uint64_t)-1;
7405 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7406 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7407 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7408 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7411 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7412 #endif /* HAVE_LONGLONG */
7418 NTSTATUS smbd_do_locking(struct smb_request *req,
7422 uint16_t num_ulocks,
7423 struct smbd_lock_element *ulocks,
7425 struct smbd_lock_element *locks,
7428 connection_struct *conn = req->conn;
7430 NTSTATUS status = NT_STATUS_OK;
7434 /* Data now points at the beginning of the list
7435 of smb_unlkrng structs */
7436 for(i = 0; i < (int)num_ulocks; i++) {
7437 struct smbd_lock_element *e = &ulocks[i];
7439 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7440 "pid %u, file %s\n",
7443 (unsigned int)e->smblctx,
7446 if (e->brltype != UNLOCK_LOCK) {
7447 /* this can only happen with SMB2 */
7448 return NT_STATUS_INVALID_PARAMETER;
7451 status = do_unlock(req->sconn->msg_ctx,
7458 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7459 nt_errstr(status)));
7461 if (!NT_STATUS_IS_OK(status)) {
7466 /* Setup the timeout in seconds. */
7468 if (!lp_blocking_locks(SNUM(conn))) {
7472 /* Data now points at the beginning of the list
7473 of smb_lkrng structs */
7475 for(i = 0; i < (int)num_locks; i++) {
7476 struct smbd_lock_element *e = &locks[i];
7478 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7479 "%llu, file %s timeout = %d\n",
7482 (unsigned long long)e->smblctx,
7486 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7487 struct blocking_lock_record *blr = NULL;
7489 if (num_locks > 1) {
7491 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7492 * if the lock vector contains one entry. When given mutliple cancel
7493 * requests in a single PDU we expect the server to return an
7494 * error. Windows servers seem to accept the request but only
7495 * cancel the first lock.
7496 * JRA - Do what Windows does (tm) :-).
7500 /* MS-CIFS (2.2.4.32.1) behavior. */
7501 return NT_STATUS_DOS(ERRDOS,
7502 ERRcancelviolation);
7504 /* Windows behavior. */
7506 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7507 "cancel request\n"));
7513 if (lp_blocking_locks(SNUM(conn))) {
7515 /* Schedule a message to ourselves to
7516 remove the blocking lock record and
7517 return the right error. */
7519 blr = blocking_lock_cancel_smb1(fsp,
7525 NT_STATUS_FILE_LOCK_CONFLICT);
7527 return NT_STATUS_DOS(
7529 ERRcancelviolation);
7532 /* Remove a matching pending lock. */
7533 status = do_lock_cancel(fsp,
7540 bool blocking_lock = timeout ? true : false;
7541 bool defer_lock = false;
7542 struct byte_range_lock *br_lck;
7543 uint64_t block_smblctx;
7545 br_lck = do_lock(req->sconn->msg_ctx,
7557 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7558 /* Windows internal resolution for blocking locks seems
7559 to be about 200ms... Don't wait for less than that. JRA. */
7560 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7561 timeout = lp_lock_spin_time();
7566 /* If a lock sent with timeout of zero would fail, and
7567 * this lock has been requested multiple times,
7568 * according to brl_lock_failed() we convert this
7569 * request to a blocking lock with a timeout of between
7570 * 150 - 300 milliseconds.
7572 * If lp_lock_spin_time() has been set to 0, we skip
7573 * this blocking retry and fail immediately.
7575 * Replacement for do_lock_spin(). JRA. */
7577 if (!req->sconn->using_smb2 &&
7578 br_lck && lp_blocking_locks(SNUM(conn)) &&
7579 lp_lock_spin_time() && !blocking_lock &&
7580 NT_STATUS_EQUAL((status),
7581 NT_STATUS_FILE_LOCK_CONFLICT))
7584 timeout = lp_lock_spin_time();
7587 if (br_lck && defer_lock) {
7589 * A blocking lock was requested. Package up
7590 * this smb into a queued request and push it
7591 * onto the blocking lock queue.
7593 if(push_blocking_lock_request(br_lck,
7604 TALLOC_FREE(br_lck);
7606 return NT_STATUS_OK;
7610 TALLOC_FREE(br_lck);
7613 if (!NT_STATUS_IS_OK(status)) {
7618 /* If any of the above locks failed, then we must unlock
7619 all of the previous locks (X/Open spec). */
7621 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7623 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7624 i = -1; /* we want to skip the for loop */
7628 * Ensure we don't do a remove on the lock that just failed,
7629 * as under POSIX rules, if we have a lock already there, we
7630 * will delete it (and we shouldn't) .....
7632 for(i--; i >= 0; i--) {
7633 struct smbd_lock_element *e = &locks[i];
7635 do_unlock(req->sconn->msg_ctx,
7645 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7646 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7648 return NT_STATUS_OK;
7651 /****************************************************************************
7652 Reply to a lockingX request.
7653 ****************************************************************************/
7655 void reply_lockingX(struct smb_request *req)
7657 connection_struct *conn = req->conn;
7659 unsigned char locktype;
7660 unsigned char oplocklevel;
7665 const uint8_t *data;
7666 bool large_file_format;
7668 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7669 struct smbd_lock_element *ulocks;
7670 struct smbd_lock_element *locks;
7673 START_PROFILE(SMBlockingX);
7676 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7677 END_PROFILE(SMBlockingX);
7681 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7682 locktype = CVAL(req->vwv+3, 0);
7683 oplocklevel = CVAL(req->vwv+3, 1);
7684 num_ulocks = SVAL(req->vwv+6, 0);
7685 num_locks = SVAL(req->vwv+7, 0);
7686 lock_timeout = IVAL(req->vwv+4, 0);
7687 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7689 if (!check_fsp(conn, req, fsp)) {
7690 END_PROFILE(SMBlockingX);
7696 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7697 /* we don't support these - and CANCEL_LOCK makes w2k
7698 and XP reboot so I don't really want to be
7699 compatible! (tridge) */
7700 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7701 END_PROFILE(SMBlockingX);
7705 /* Check if this is an oplock break on a file
7706 we have granted an oplock on.
7708 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7709 /* Client can insist on breaking to none. */
7710 bool break_to_none = (oplocklevel == 0);
7713 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7714 "for fnum = %d\n", (unsigned int)oplocklevel,
7718 * Make sure we have granted an exclusive or batch oplock on
7722 if (fsp->oplock_type == 0) {
7724 /* The Samba4 nbench simulator doesn't understand
7725 the difference between break to level2 and break
7726 to none from level2 - it sends oplock break
7727 replies in both cases. Don't keep logging an error
7728 message here - just ignore it. JRA. */
7730 DEBUG(5,("reply_lockingX: Error : oplock break from "
7731 "client for fnum = %d (oplock=%d) and no "
7732 "oplock granted on this file (%s).\n",
7733 fsp->fnum, fsp->oplock_type,
7736 /* if this is a pure oplock break request then don't
7738 if (num_locks == 0 && num_ulocks == 0) {
7739 END_PROFILE(SMBlockingX);
7742 END_PROFILE(SMBlockingX);
7743 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7748 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7750 result = remove_oplock(fsp);
7752 result = downgrade_oplock(fsp);
7756 DEBUG(0, ("reply_lockingX: error in removing "
7757 "oplock on file %s\n", fsp_str_dbg(fsp)));
7758 /* Hmmm. Is this panic justified? */
7759 smb_panic("internal tdb error");
7762 reply_to_oplock_break_requests(fsp);
7764 /* if this is a pure oplock break request then don't send a
7766 if (num_locks == 0 && num_ulocks == 0) {
7767 /* Sanity check - ensure a pure oplock break is not a
7769 if(CVAL(req->vwv+0, 0) != 0xff)
7770 DEBUG(0,("reply_lockingX: Error : pure oplock "
7771 "break is a chained %d request !\n",
7772 (unsigned int)CVAL(req->vwv+0, 0)));
7773 END_PROFILE(SMBlockingX);
7779 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7780 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7781 END_PROFILE(SMBlockingX);
7785 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7786 if (ulocks == NULL) {
7787 reply_nterror(req, NT_STATUS_NO_MEMORY);
7788 END_PROFILE(SMBlockingX);
7792 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7793 if (locks == NULL) {
7794 reply_nterror(req, NT_STATUS_NO_MEMORY);
7795 END_PROFILE(SMBlockingX);
7799 /* Data now points at the beginning of the list
7800 of smb_unlkrng structs */
7801 for(i = 0; i < (int)num_ulocks; i++) {
7802 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7803 ulocks[i].count = get_lock_count(data, i, large_file_format);
7804 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7805 ulocks[i].brltype = UNLOCK_LOCK;
7808 * There is no error code marked "stupid client bug".... :-).
7811 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7812 END_PROFILE(SMBlockingX);
7817 /* Now do any requested locks */
7818 data += ((large_file_format ? 20 : 10)*num_ulocks);
7820 /* Data now points at the beginning of the list
7821 of smb_lkrng structs */
7823 for(i = 0; i < (int)num_locks; i++) {
7824 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7825 locks[i].count = get_lock_count(data, i, large_file_format);
7826 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7828 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7829 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7830 locks[i].brltype = PENDING_READ_LOCK;
7832 locks[i].brltype = READ_LOCK;
7835 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7836 locks[i].brltype = PENDING_WRITE_LOCK;
7838 locks[i].brltype = WRITE_LOCK;
7843 * There is no error code marked "stupid client bug".... :-).
7846 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7847 END_PROFILE(SMBlockingX);
7852 status = smbd_do_locking(req, fsp,
7853 locktype, lock_timeout,
7857 if (!NT_STATUS_IS_OK(status)) {
7858 END_PROFILE(SMBlockingX);
7859 reply_nterror(req, status);
7863 END_PROFILE(SMBlockingX);
7867 reply_outbuf(req, 2, 0);
7869 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7870 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7872 END_PROFILE(SMBlockingX);
7877 #define DBGC_CLASS DBGC_ALL
7879 /****************************************************************************
7880 Reply to a SMBreadbmpx (read block multiplex) request.
7881 Always reply with an error, if someone has a platform really needs this,
7882 please contact vl@samba.org
7883 ****************************************************************************/
7885 void reply_readbmpx(struct smb_request *req)
7887 START_PROFILE(SMBreadBmpx);
7888 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7889 END_PROFILE(SMBreadBmpx);
7893 /****************************************************************************
7894 Reply to a SMBreadbs (read block multiplex secondary) request.
7895 Always reply with an error, if someone has a platform really needs this,
7896 please contact vl@samba.org
7897 ****************************************************************************/
7899 void reply_readbs(struct smb_request *req)
7901 START_PROFILE(SMBreadBs);
7902 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7903 END_PROFILE(SMBreadBs);
7907 /****************************************************************************
7908 Reply to a SMBsetattrE.
7909 ****************************************************************************/
7911 void reply_setattrE(struct smb_request *req)
7913 connection_struct *conn = req->conn;
7914 struct smb_file_time ft;
7918 START_PROFILE(SMBsetattrE);
7922 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7926 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7928 if(!fsp || (fsp->conn != conn)) {
7929 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7934 * Convert the DOS times into unix times.
7937 ft.atime = convert_time_t_to_timespec(
7938 srv_make_unix_date2(req->vwv+3));
7939 ft.mtime = convert_time_t_to_timespec(
7940 srv_make_unix_date2(req->vwv+5));
7941 ft.create_time = convert_time_t_to_timespec(
7942 srv_make_unix_date2(req->vwv+1));
7944 reply_outbuf(req, 0, 0);
7947 * Patch from Ray Frush <frush@engr.colostate.edu>
7948 * Sometimes times are sent as zero - ignore them.
7951 /* Ensure we have a valid stat struct for the source. */
7952 status = vfs_stat_fsp(fsp);
7953 if (!NT_STATUS_IS_OK(status)) {
7954 reply_nterror(req, status);
7958 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
7959 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7963 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7964 if (!NT_STATUS_IS_OK(status)) {
7965 reply_nterror(req, status);
7969 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7972 (unsigned int)ft.atime.tv_sec,
7973 (unsigned int)ft.mtime.tv_sec,
7974 (unsigned int)ft.create_time.tv_sec
7977 END_PROFILE(SMBsetattrE);
7982 /* Back from the dead for OS/2..... JRA. */
7984 /****************************************************************************
7985 Reply to a SMBwritebmpx (write block multiplex primary) request.
7986 Always reply with an error, if someone has a platform really needs this,
7987 please contact vl@samba.org
7988 ****************************************************************************/
7990 void reply_writebmpx(struct smb_request *req)
7992 START_PROFILE(SMBwriteBmpx);
7993 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7994 END_PROFILE(SMBwriteBmpx);
7998 /****************************************************************************
7999 Reply to a SMBwritebs (write block multiplex secondary) request.
8000 Always reply with an error, if someone has a platform really needs this,
8001 please contact vl@samba.org
8002 ****************************************************************************/
8004 void reply_writebs(struct smb_request *req)
8006 START_PROFILE(SMBwriteBs);
8007 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8008 END_PROFILE(SMBwriteBs);
8012 /****************************************************************************
8013 Reply to a SMBgetattrE.
8014 ****************************************************************************/
8016 void reply_getattrE(struct smb_request *req)
8018 connection_struct *conn = req->conn;
8021 struct timespec create_ts;
8023 START_PROFILE(SMBgetattrE);
8026 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8027 END_PROFILE(SMBgetattrE);
8031 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8033 if(!fsp || (fsp->conn != conn)) {
8034 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8035 END_PROFILE(SMBgetattrE);
8039 /* Do an fstat on this file */
8041 reply_nterror(req, map_nt_error_from_unix(errno));
8042 END_PROFILE(SMBgetattrE);
8046 mode = dos_mode(conn, fsp->fsp_name);
8049 * Convert the times into dos times. Set create
8050 * date to be last modify date as UNIX doesn't save
8054 reply_outbuf(req, 11, 0);
8056 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8057 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8058 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8059 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8060 /* Should we check pending modtime here ? JRA */
8061 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8062 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8064 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8065 SIVAL(req->outbuf, smb_vwv6, 0);
8066 SIVAL(req->outbuf, smb_vwv8, 0);
8068 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8069 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
8070 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8072 SSVAL(req->outbuf,smb_vwv10, mode);
8074 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
8076 END_PROFILE(SMBgetattrE);