2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
29 #include "smbd/globals.h"
30 #include "fake_file.h"
31 #include "../librpc/gen_ndr/cli_spoolss.h"
32 #include "rpc_client/cli_spoolss.h"
33 #include "rpc_client/init_spoolss.h"
34 #include "rpc_server/rpc_ncacn_np.h"
36 /****************************************************************************
37 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
38 path or anything including wildcards.
39 We're assuming here that '/' is not the second byte in any multibyte char
40 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
42 ****************************************************************************/
44 /* Custom version for processing POSIX paths. */
45 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
47 static NTSTATUS check_path_syntax_internal(char *path,
49 bool *p_last_component_contains_wcard)
53 NTSTATUS ret = NT_STATUS_OK;
54 bool start_of_name_component = True;
55 bool stream_started = false;
57 *p_last_component_contains_wcard = False;
64 return NT_STATUS_OBJECT_NAME_INVALID;
67 return NT_STATUS_OBJECT_NAME_INVALID;
69 if (strchr_m(&s[1], ':')) {
70 return NT_STATUS_OBJECT_NAME_INVALID;
76 if ((*s == ':') && !posix_path && !stream_started) {
77 if (*p_last_component_contains_wcard) {
78 return NT_STATUS_OBJECT_NAME_INVALID;
80 /* Stream names allow more characters than file names.
81 We're overloading posix_path here to allow a wider
82 range of characters. If stream_started is true this
83 is still a Windows path even if posix_path is true.
86 stream_started = true;
87 start_of_name_component = false;
91 return NT_STATUS_OBJECT_NAME_INVALID;
95 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
97 * Safe to assume is not the second part of a mb char
98 * as this is handled below.
100 /* Eat multiple '/' or '\\' */
101 while (IS_PATH_SEP(*s,posix_path)) {
104 if ((d != path) && (*s != '\0')) {
105 /* We only care about non-leading or trailing '/' or '\\' */
109 start_of_name_component = True;
111 *p_last_component_contains_wcard = False;
115 if (start_of_name_component) {
116 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
117 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
120 * No mb char starts with '.' so we're safe checking the directory separator here.
123 /* If we just added a '/' - delete it */
124 if ((d > path) && (*(d-1) == '/')) {
129 /* Are we at the start ? Can't go back further if so. */
131 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
134 /* Go back one level... */
135 /* We know this is safe as '/' cannot be part of a mb sequence. */
136 /* NOTE - if this assumption is invalid we are not in good shape... */
137 /* Decrement d first as d points to the *next* char to write into. */
138 for (d--; d > path; d--) {
142 s += 2; /* Else go past the .. */
143 /* We're still at the start of a name component, just the previous one. */
146 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
158 if (*s <= 0x1f || *s == '|') {
159 return NT_STATUS_OBJECT_NAME_INVALID;
167 *p_last_component_contains_wcard = True;
176 /* Get the size of the next MB character. */
177 next_codepoint(s,&siz);
195 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
197 return NT_STATUS_INVALID_PARAMETER;
200 start_of_name_component = False;
208 /****************************************************************************
209 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
210 No wildcards allowed.
211 ****************************************************************************/
213 NTSTATUS check_path_syntax(char *path)
216 return check_path_syntax_internal(path, False, &ignore);
219 /****************************************************************************
220 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
221 Wildcards allowed - p_contains_wcard returns true if the last component contained
223 ****************************************************************************/
225 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
227 return check_path_syntax_internal(path, False, p_contains_wcard);
230 /****************************************************************************
231 Check the path for a POSIX client.
232 We're assuming here that '/' is not the second byte in any multibyte char
233 set (a safe assumption).
234 ****************************************************************************/
236 NTSTATUS check_path_syntax_posix(char *path)
239 return check_path_syntax_internal(path, True, &ignore);
242 /****************************************************************************
243 Pull a string and check the path allowing a wilcard - provide for error return.
244 ****************************************************************************/
246 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
247 const char *base_ptr,
254 bool *contains_wcard)
260 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
264 *err = NT_STATUS_INVALID_PARAMETER;
268 *contains_wcard = False;
270 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
272 * For a DFS path the function parse_dfs_path()
273 * will do the path processing, just make a copy.
279 if (lp_posix_pathnames()) {
280 *err = check_path_syntax_posix(*pp_dest);
282 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
288 /****************************************************************************
289 Pull a string and check the path - provide for error return.
290 ****************************************************************************/
292 size_t srvstr_get_path(TALLOC_CTX *ctx,
293 const char *base_ptr,
302 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
303 src_len, flags, err, &ignore);
306 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
307 char **pp_dest, const char *src, int flags,
308 NTSTATUS *err, bool *contains_wcard)
310 return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
311 pp_dest, src, smbreq_bufrem(req, src),
312 flags, err, contains_wcard);
315 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
316 char **pp_dest, const char *src, int flags,
320 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
321 flags, err, &ignore);
324 /****************************************************************************
325 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
326 ****************************************************************************/
328 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
331 if ((fsp == NULL) || (conn == NULL)) {
332 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
335 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
336 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
342 /****************************************************************************
343 Check if we have a correct fsp pointing to a file.
344 ****************************************************************************/
346 bool check_fsp(connection_struct *conn, struct smb_request *req,
349 if (!check_fsp_open(conn, req, fsp)) {
352 if (fsp->is_directory) {
353 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
356 if (fsp->fh->fd == -1) {
357 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
360 fsp->num_smb_operations++;
364 /****************************************************************************
365 Check if we have a correct fsp pointing to a quota fake file. Replacement for
366 the CHECK_NTQUOTA_HANDLE_OK macro.
367 ****************************************************************************/
369 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
372 if (!check_fsp_open(conn, req, fsp)) {
376 if (fsp->is_directory) {
380 if (fsp->fake_file_handle == NULL) {
384 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
388 if (fsp->fake_file_handle->private_data == NULL) {
395 static bool netbios_session_retarget(struct smbd_server_connection *sconn,
396 const char *name, int name_type)
399 char *trim_name_type;
400 const char *retarget_parm;
403 int retarget_type = 0x20;
404 int retarget_port = 139;
405 struct sockaddr_storage retarget_addr;
406 struct sockaddr_in *in_addr;
410 if (get_socket_port(sconn->sock) != 139) {
414 trim_name = talloc_strdup(talloc_tos(), name);
415 if (trim_name == NULL) {
418 trim_char(trim_name, ' ', ' ');
420 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
422 if (trim_name_type == NULL) {
426 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
427 trim_name_type, NULL);
428 if (retarget_parm == NULL) {
429 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
432 if (retarget_parm == NULL) {
436 retarget = talloc_strdup(trim_name, retarget_parm);
437 if (retarget == NULL) {
441 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
443 p = strchr(retarget, ':');
446 retarget_port = atoi(p);
449 p = strchr_m(retarget, '#');
452 sscanf(p, "%x", &retarget_type);
455 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
457 DEBUG(10, ("could not resolve %s\n", retarget));
461 if (retarget_addr.ss_family != AF_INET) {
462 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
466 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
468 _smb_setlen(outbuf, 6);
469 SCVAL(outbuf, 0, 0x84);
470 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
471 *(uint16_t *)(outbuf+8) = htons(retarget_port);
473 if (!srv_send_smb(sconn, (char *)outbuf, false, 0, false,
475 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
481 TALLOC_FREE(trim_name);
485 /****************************************************************************
486 Reply to a (netbios-level) special message.
487 ****************************************************************************/
489 void reply_special(struct smbd_server_connection *sconn, char *inbuf)
491 int msg_type = CVAL(inbuf,0);
492 int msg_flags = CVAL(inbuf,1);
494 char name_type1, name_type2;
497 * We only really use 4 bytes of the outbuf, but for the smb_setlen
498 * calculation & friends (srv_send_smb uses that) we need the full smb
501 char outbuf[smb_size];
505 memset(outbuf, '\0', sizeof(outbuf));
507 smb_setlen(outbuf,0);
510 case 0x81: /* session request */
512 if (sconn->nbt.got_session) {
513 exit_server_cleanly("multiple session request not permitted");
516 SCVAL(outbuf,0,0x82);
518 if (name_len(inbuf+4) > 50 ||
519 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
520 DEBUG(0,("Invalid name length in session request\n"));
523 name_type1 = name_extract(inbuf,4,name1);
524 name_type2 = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
525 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
526 name1, name_type1, name2, name_type2));
528 if (netbios_session_retarget(sconn, name1, name_type1)) {
529 exit_server_cleanly("retargeted client");
533 * Windows NT/2k uses "*SMBSERVER" and XP uses
534 * "*SMBSERV" arrggg!!!
536 if (strequal(name1, "*SMBSERVER ")
537 || strequal(name1, "*SMBSERV ")) {
538 fstrcpy(name1, sconn->client_id.addr);
541 set_local_machine_name(name1, True);
542 set_remote_machine_name(name2, True);
544 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
545 get_local_machine_name(), get_remote_machine_name(),
548 if (name_type2 == 'R') {
549 /* We are being asked for a pathworks session ---
551 SCVAL(outbuf, 0,0x83);
555 /* only add the client's machine name to the list
556 of possibly valid usernames if we are operating
557 in share mode security */
558 if (lp_security() == SEC_SHARE) {
559 add_session_user(sconn, get_remote_machine_name());
562 reload_services(sconn->msg_ctx, sconn->sock, True);
565 sconn->nbt.got_session = true;
568 case 0x89: /* session keepalive request
569 (some old clients produce this?) */
570 SCVAL(outbuf,0,SMBkeepalive);
574 case 0x82: /* positive session response */
575 case 0x83: /* negative session response */
576 case 0x84: /* retarget session response */
577 DEBUG(0,("Unexpected session response\n"));
580 case SMBkeepalive: /* session keepalive */
585 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
586 msg_type, msg_flags));
588 srv_send_smb(sconn, outbuf, false, 0, false, NULL);
592 /****************************************************************************
594 conn POINTER CAN BE NULL HERE !
595 ****************************************************************************/
597 void reply_tcon(struct smb_request *req)
599 connection_struct *conn = req->conn;
601 char *service_buf = NULL;
602 char *password = NULL;
607 DATA_BLOB password_blob;
608 TALLOC_CTX *ctx = talloc_tos();
609 struct smbd_server_connection *sconn = req->sconn;
611 START_PROFILE(SMBtcon);
613 if (req->buflen < 4) {
614 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
615 END_PROFILE(SMBtcon);
619 p = (const char *)req->buf + 1;
620 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
622 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
624 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
627 if (service_buf == NULL || password == NULL || dev == NULL) {
628 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
629 END_PROFILE(SMBtcon);
632 p = strrchr_m(service_buf,'\\');
636 service = service_buf;
639 password_blob = data_blob(password, pwlen+1);
641 conn = make_connection(sconn,service,password_blob,dev,
642 req->vuid,&nt_status);
645 data_blob_clear_free(&password_blob);
648 reply_nterror(req, nt_status);
649 END_PROFILE(SMBtcon);
653 reply_outbuf(req, 2, 0);
654 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
655 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
656 SSVAL(req->outbuf,smb_tid,conn->cnum);
658 DEBUG(3,("tcon service=%s cnum=%d\n",
659 service, conn->cnum));
661 END_PROFILE(SMBtcon);
665 /****************************************************************************
666 Reply to a tcon and X.
667 conn POINTER CAN BE NULL HERE !
668 ****************************************************************************/
670 void reply_tcon_and_X(struct smb_request *req)
672 connection_struct *conn = req->conn;
673 const char *service = NULL;
675 TALLOC_CTX *ctx = talloc_tos();
676 /* what the cleint thinks the device is */
677 char *client_devicetype = NULL;
678 /* what the server tells the client the share represents */
679 const char *server_devicetype;
685 struct smbd_server_connection *sconn = req->sconn;
687 START_PROFILE(SMBtconX);
690 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
691 END_PROFILE(SMBtconX);
695 passlen = SVAL(req->vwv+3, 0);
696 tcon_flags = SVAL(req->vwv+2, 0);
698 /* we might have to close an old one */
699 if ((tcon_flags & 0x1) && conn) {
700 close_cnum(conn,req->vuid);
705 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
706 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
707 END_PROFILE(SMBtconX);
711 if (sconn->smb1.negprot.encrypted_passwords) {
712 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
713 if (lp_security() == SEC_SHARE) {
715 * Security = share always has a pad byte
716 * after the password.
718 p = (const char *)req->buf + passlen + 1;
720 p = (const char *)req->buf + passlen;
723 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
724 /* Ensure correct termination */
725 password.data[passlen]=0;
726 p = (const char *)req->buf + passlen + 1;
729 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
732 data_blob_clear_free(&password);
733 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
734 END_PROFILE(SMBtconX);
739 * the service name can be either: \\server\share
740 * or share directly like on the DELL PowerVault 705
743 q = strchr_m(path+2,'\\');
745 data_blob_clear_free(&password);
746 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
747 END_PROFILE(SMBtconX);
755 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
756 &client_devicetype, p,
757 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
759 if (client_devicetype == NULL) {
760 data_blob_clear_free(&password);
761 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
762 END_PROFILE(SMBtconX);
766 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
768 conn = make_connection(sconn, service, password, client_devicetype,
769 req->vuid, &nt_status);
772 data_blob_clear_free(&password);
775 reply_nterror(req, nt_status);
776 END_PROFILE(SMBtconX);
781 server_devicetype = "IPC";
782 else if ( IS_PRINT(conn) )
783 server_devicetype = "LPT1:";
785 server_devicetype = "A:";
787 if (get_Protocol() < PROTOCOL_NT1) {
788 reply_outbuf(req, 2, 0);
789 if (message_push_string(&req->outbuf, server_devicetype,
790 STR_TERMINATE|STR_ASCII) == -1) {
791 reply_nterror(req, NT_STATUS_NO_MEMORY);
792 END_PROFILE(SMBtconX);
796 /* NT sets the fstype of IPC$ to the null string */
797 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
799 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
800 /* Return permissions. */
804 reply_outbuf(req, 7, 0);
807 perm1 = FILE_ALL_ACCESS;
808 perm2 = FILE_ALL_ACCESS;
810 perm1 = CAN_WRITE(conn) ?
815 SIVAL(req->outbuf, smb_vwv3, perm1);
816 SIVAL(req->outbuf, smb_vwv5, perm2);
818 reply_outbuf(req, 3, 0);
821 if ((message_push_string(&req->outbuf, server_devicetype,
822 STR_TERMINATE|STR_ASCII) == -1)
823 || (message_push_string(&req->outbuf, fstype,
824 STR_TERMINATE) == -1)) {
825 reply_nterror(req, NT_STATUS_NO_MEMORY);
826 END_PROFILE(SMBtconX);
830 /* what does setting this bit do? It is set by NT4 and
831 may affect the ability to autorun mounted cdroms */
832 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
833 (lp_csc_policy(SNUM(conn)) << 2));
835 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
836 DEBUG(2,("Serving %s as a Dfs root\n",
837 lp_servicename(SNUM(conn)) ));
838 SSVAL(req->outbuf, smb_vwv2,
839 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
844 DEBUG(3,("tconX service=%s \n",
847 /* set the incoming and outgoing tid to the just created one */
848 SSVAL(req->inbuf,smb_tid,conn->cnum);
849 SSVAL(req->outbuf,smb_tid,conn->cnum);
851 END_PROFILE(SMBtconX);
853 req->tid = conn->cnum;
858 /****************************************************************************
859 Reply to an unknown type.
860 ****************************************************************************/
862 void reply_unknown_new(struct smb_request *req, uint8 type)
864 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
865 smb_fn_name(type), type, type));
866 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
870 /****************************************************************************
872 conn POINTER CAN BE NULL HERE !
873 ****************************************************************************/
875 void reply_ioctl(struct smb_request *req)
877 connection_struct *conn = req->conn;
884 START_PROFILE(SMBioctl);
887 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
888 END_PROFILE(SMBioctl);
892 device = SVAL(req->vwv+1, 0);
893 function = SVAL(req->vwv+2, 0);
894 ioctl_code = (device << 16) + function;
896 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
898 switch (ioctl_code) {
899 case IOCTL_QUERY_JOB_INFO:
903 reply_force_doserror(req, ERRSRV, ERRnosupport);
904 END_PROFILE(SMBioctl);
908 reply_outbuf(req, 8, replysize+1);
909 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
910 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
911 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
912 p = smb_buf(req->outbuf);
913 memset(p, '\0', replysize+1); /* valgrind-safe. */
914 p += 1; /* Allow for alignment */
916 switch (ioctl_code) {
917 case IOCTL_QUERY_JOB_INFO:
919 files_struct *fsp = file_fsp(
920 req, SVAL(req->vwv+0, 0));
922 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
923 END_PROFILE(SMBioctl);
927 if (fsp->print_file) {
928 SSVAL(p, 0, fsp->print_file->rap_jobid);
932 srvstr_push((char *)req->outbuf, req->flags2, p+2,
934 STR_TERMINATE|STR_ASCII);
936 srvstr_push((char *)req->outbuf, req->flags2,
937 p+18, lp_servicename(SNUM(conn)),
938 13, STR_TERMINATE|STR_ASCII);
946 END_PROFILE(SMBioctl);
950 /****************************************************************************
951 Strange checkpath NTSTATUS mapping.
952 ****************************************************************************/
954 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
956 /* Strange DOS error code semantics only for checkpath... */
957 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
958 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
959 /* We need to map to ERRbadpath */
960 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
966 /****************************************************************************
967 Reply to a checkpath.
968 ****************************************************************************/
970 void reply_checkpath(struct smb_request *req)
972 connection_struct *conn = req->conn;
973 struct smb_filename *smb_fname = NULL;
976 TALLOC_CTX *ctx = talloc_tos();
978 START_PROFILE(SMBcheckpath);
980 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
981 STR_TERMINATE, &status);
983 if (!NT_STATUS_IS_OK(status)) {
984 status = map_checkpath_error(req->flags2, status);
985 reply_nterror(req, status);
986 END_PROFILE(SMBcheckpath);
990 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
992 status = filename_convert(ctx,
994 req->flags2 & FLAGS2_DFS_PATHNAMES,
1000 if (!NT_STATUS_IS_OK(status)) {
1001 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1002 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1003 ERRSRV, ERRbadpath);
1004 END_PROFILE(SMBcheckpath);
1010 if (!VALID_STAT(smb_fname->st) &&
1011 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1012 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1013 smb_fname_str_dbg(smb_fname), strerror(errno)));
1014 status = map_nt_error_from_unix(errno);
1018 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1019 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1020 ERRDOS, ERRbadpath);
1024 reply_outbuf(req, 0, 0);
1027 /* We special case this - as when a Windows machine
1028 is parsing a path is steps through the components
1029 one at a time - if a component fails it expects
1030 ERRbadpath, not ERRbadfile.
1032 status = map_checkpath_error(req->flags2, status);
1033 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1035 * Windows returns different error codes if
1036 * the parent directory is valid but not the
1037 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1038 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1039 * if the path is invalid.
1041 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1042 ERRDOS, ERRbadpath);
1046 reply_nterror(req, status);
1049 TALLOC_FREE(smb_fname);
1050 END_PROFILE(SMBcheckpath);
1054 /****************************************************************************
1056 ****************************************************************************/
1058 void reply_getatr(struct smb_request *req)
1060 connection_struct *conn = req->conn;
1061 struct smb_filename *smb_fname = NULL;
1068 TALLOC_CTX *ctx = talloc_tos();
1069 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1071 START_PROFILE(SMBgetatr);
1073 p = (const char *)req->buf + 1;
1074 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1075 if (!NT_STATUS_IS_OK(status)) {
1076 reply_nterror(req, status);
1080 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1081 under WfWg - weird! */
1082 if (*fname == '\0') {
1083 mode = aHIDDEN | aDIR;
1084 if (!CAN_WRITE(conn)) {
1090 status = filename_convert(ctx,
1092 req->flags2 & FLAGS2_DFS_PATHNAMES,
1097 if (!NT_STATUS_IS_OK(status)) {
1098 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1099 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1100 ERRSRV, ERRbadpath);
1103 reply_nterror(req, status);
1106 if (!VALID_STAT(smb_fname->st) &&
1107 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1108 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1109 smb_fname_str_dbg(smb_fname),
1111 reply_nterror(req, map_nt_error_from_unix(errno));
1115 mode = dos_mode(conn, smb_fname);
1116 size = smb_fname->st.st_ex_size;
1118 if (ask_sharemode) {
1119 struct timespec write_time_ts;
1120 struct file_id fileid;
1122 ZERO_STRUCT(write_time_ts);
1123 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1124 get_file_infos(fileid, NULL, &write_time_ts);
1125 if (!null_timespec(write_time_ts)) {
1126 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1130 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1136 reply_outbuf(req, 10, 0);
1138 SSVAL(req->outbuf,smb_vwv0,mode);
1139 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1140 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1142 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1144 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1146 if (get_Protocol() >= PROTOCOL_NT1) {
1147 SSVAL(req->outbuf, smb_flg2,
1148 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1151 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1152 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1155 TALLOC_FREE(smb_fname);
1157 END_PROFILE(SMBgetatr);
1161 /****************************************************************************
1163 ****************************************************************************/
1165 void reply_setatr(struct smb_request *req)
1167 struct smb_file_time ft;
1168 connection_struct *conn = req->conn;
1169 struct smb_filename *smb_fname = NULL;
1175 TALLOC_CTX *ctx = talloc_tos();
1177 START_PROFILE(SMBsetatr);
1182 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1186 p = (const char *)req->buf + 1;
1187 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1188 if (!NT_STATUS_IS_OK(status)) {
1189 reply_nterror(req, status);
1193 status = filename_convert(ctx,
1195 req->flags2 & FLAGS2_DFS_PATHNAMES,
1200 if (!NT_STATUS_IS_OK(status)) {
1201 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1202 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1203 ERRSRV, ERRbadpath);
1206 reply_nterror(req, status);
1210 if (smb_fname->base_name[0] == '.' &&
1211 smb_fname->base_name[1] == '\0') {
1213 * Not sure here is the right place to catch this
1214 * condition. Might be moved to somewhere else later -- vl
1216 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1220 mode = SVAL(req->vwv+0, 0);
1221 mtime = srv_make_unix_date3(req->vwv+1);
1223 ft.mtime = convert_time_t_to_timespec(mtime);
1224 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1225 if (!NT_STATUS_IS_OK(status)) {
1226 reply_nterror(req, status);
1230 if (mode != FILE_ATTRIBUTE_NORMAL) {
1231 if (VALID_STAT_OF_DIR(smb_fname->st))
1236 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1238 reply_nterror(req, map_nt_error_from_unix(errno));
1243 reply_outbuf(req, 0, 0);
1245 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1248 TALLOC_FREE(smb_fname);
1249 END_PROFILE(SMBsetatr);
1253 /****************************************************************************
1255 ****************************************************************************/
1257 void reply_dskattr(struct smb_request *req)
1259 connection_struct *conn = req->conn;
1260 uint64_t dfree,dsize,bsize;
1261 START_PROFILE(SMBdskattr);
1263 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1264 reply_nterror(req, map_nt_error_from_unix(errno));
1265 END_PROFILE(SMBdskattr);
1269 reply_outbuf(req, 5, 0);
1271 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1272 double total_space, free_space;
1273 /* we need to scale this to a number that DOS6 can handle. We
1274 use floating point so we can handle large drives on systems
1275 that don't have 64 bit integers
1277 we end up displaying a maximum of 2G to DOS systems
1279 total_space = dsize * (double)bsize;
1280 free_space = dfree * (double)bsize;
1282 dsize = (uint64_t)((total_space+63*512) / (64*512));
1283 dfree = (uint64_t)((free_space+63*512) / (64*512));
1285 if (dsize > 0xFFFF) dsize = 0xFFFF;
1286 if (dfree > 0xFFFF) dfree = 0xFFFF;
1288 SSVAL(req->outbuf,smb_vwv0,dsize);
1289 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1290 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1291 SSVAL(req->outbuf,smb_vwv3,dfree);
1293 SSVAL(req->outbuf,smb_vwv0,dsize);
1294 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1295 SSVAL(req->outbuf,smb_vwv2,512);
1296 SSVAL(req->outbuf,smb_vwv3,dfree);
1299 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1301 END_PROFILE(SMBdskattr);
1306 * Utility function to split the filename from the directory.
1308 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1309 char **fname_dir_out,
1310 char **fname_mask_out)
1312 const char *p = NULL;
1313 char *fname_dir = NULL;
1314 char *fname_mask = NULL;
1316 p = strrchr_m(fname_in, '/');
1318 fname_dir = talloc_strdup(ctx, ".");
1319 fname_mask = talloc_strdup(ctx, fname_in);
1321 fname_dir = talloc_strndup(ctx, fname_in,
1322 PTR_DIFF(p, fname_in));
1323 fname_mask = talloc_strdup(ctx, p+1);
1326 if (!fname_dir || !fname_mask) {
1327 TALLOC_FREE(fname_dir);
1328 TALLOC_FREE(fname_mask);
1329 return NT_STATUS_NO_MEMORY;
1332 *fname_dir_out = fname_dir;
1333 *fname_mask_out = fname_mask;
1334 return NT_STATUS_OK;
1337 /****************************************************************************
1339 Can be called from SMBsearch, SMBffirst or SMBfunique.
1340 ****************************************************************************/
1342 void reply_search(struct smb_request *req)
1344 connection_struct *conn = req->conn;
1346 const char *mask = NULL;
1347 char *directory = NULL;
1348 struct smb_filename *smb_fname = NULL;
1352 struct timespec date;
1354 unsigned int numentries = 0;
1355 unsigned int maxentries = 0;
1356 bool finished = False;
1361 bool check_descend = False;
1362 bool expect_close = False;
1364 bool mask_contains_wcard = False;
1365 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1366 TALLOC_CTX *ctx = talloc_tos();
1367 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1368 struct dptr_struct *dirptr = NULL;
1369 struct smbd_server_connection *sconn = req->sconn;
1371 START_PROFILE(SMBsearch);
1374 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1378 if (lp_posix_pathnames()) {
1379 reply_unknown_new(req, req->cmd);
1383 /* If we were called as SMBffirst then we must expect close. */
1384 if(req->cmd == SMBffirst) {
1385 expect_close = True;
1388 reply_outbuf(req, 1, 3);
1389 maxentries = SVAL(req->vwv+0, 0);
1390 dirtype = SVAL(req->vwv+1, 0);
1391 p = (const char *)req->buf + 1;
1392 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1393 &nt_status, &mask_contains_wcard);
1394 if (!NT_STATUS_IS_OK(nt_status)) {
1395 reply_nterror(req, nt_status);
1400 status_len = SVAL(p, 0);
1403 /* dirtype &= ~aDIR; */
1405 if (status_len == 0) {
1406 nt_status = filename_convert(ctx, conn,
1407 req->flags2 & FLAGS2_DFS_PATHNAMES,
1409 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1410 &mask_contains_wcard,
1412 if (!NT_STATUS_IS_OK(nt_status)) {
1413 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1414 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1415 ERRSRV, ERRbadpath);
1418 reply_nterror(req, nt_status);
1422 directory = smb_fname->base_name;
1424 p = strrchr_m(directory,'/');
1425 if ((p != NULL) && (*directory != '/')) {
1427 directory = talloc_strndup(ctx, directory,
1428 PTR_DIFF(p, directory));
1431 directory = talloc_strdup(ctx,".");
1435 reply_nterror(req, NT_STATUS_NO_MEMORY);
1439 memset((char *)status,'\0',21);
1440 SCVAL(status,0,(dirtype & 0x1F));
1442 nt_status = dptr_create(conn,
1448 mask_contains_wcard,
1451 if (!NT_STATUS_IS_OK(nt_status)) {
1452 reply_nterror(req, nt_status);
1455 dptr_num = dptr_dnum(dirptr);
1458 const char *dirpath;
1460 memcpy(status,p,21);
1461 status_dirtype = CVAL(status,0) & 0x1F;
1462 if (status_dirtype != (dirtype & 0x1F)) {
1463 dirtype = status_dirtype;
1466 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1470 dirpath = dptr_path(sconn, dptr_num);
1471 directory = talloc_strdup(ctx, dirpath);
1473 reply_nterror(req, NT_STATUS_NO_MEMORY);
1477 mask = dptr_wcard(sconn, dptr_num);
1482 * For a 'continue' search we have no string. So
1483 * check from the initial saved string.
1485 mask_contains_wcard = ms_has_wild(mask);
1486 dirtype = dptr_attr(sconn, dptr_num);
1489 DEBUG(4,("dptr_num is %d\n",dptr_num));
1491 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1492 dptr_init_search_op(dirptr);
1494 if ((dirtype&0x1F) == aVOLID) {
1495 char buf[DIR_STRUCT_SIZE];
1496 memcpy(buf,status,21);
1497 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1498 0,aVOLID,0,!allow_long_path_components)) {
1499 reply_nterror(req, NT_STATUS_NO_MEMORY);
1502 dptr_fill(sconn, buf+12,dptr_num);
1503 if (dptr_zero(buf+12) && (status_len==0)) {
1508 if (message_push_blob(&req->outbuf,
1509 data_blob_const(buf, sizeof(buf)))
1511 reply_nterror(req, NT_STATUS_NO_MEMORY);
1519 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1522 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1523 directory,lp_dontdescend(SNUM(conn))));
1524 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1525 check_descend = True;
1528 for (i=numentries;(i<maxentries) && !finished;i++) {
1529 finished = !get_dir_entry(ctx,
1540 char buf[DIR_STRUCT_SIZE];
1541 memcpy(buf,status,21);
1542 if (!make_dir_struct(ctx,
1548 convert_timespec_to_time_t(date),
1549 !allow_long_path_components)) {
1550 reply_nterror(req, NT_STATUS_NO_MEMORY);
1553 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1556 if (message_push_blob(&req->outbuf,
1557 data_blob_const(buf, sizeof(buf)))
1559 reply_nterror(req, NT_STATUS_NO_MEMORY);
1569 /* If we were called as SMBffirst with smb_search_id == NULL
1570 and no entries were found then return error and close dirptr
1573 if (numentries == 0) {
1574 dptr_close(sconn, &dptr_num);
1575 } else if(expect_close && status_len == 0) {
1576 /* Close the dptr - we know it's gone */
1577 dptr_close(sconn, &dptr_num);
1580 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1581 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1582 dptr_close(sconn, &dptr_num);
1585 if ((numentries == 0) && !mask_contains_wcard) {
1586 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1590 SSVAL(req->outbuf,smb_vwv0,numentries);
1591 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1592 SCVAL(smb_buf(req->outbuf),0,5);
1593 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1595 /* The replies here are never long name. */
1596 SSVAL(req->outbuf, smb_flg2,
1597 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1598 if (!allow_long_path_components) {
1599 SSVAL(req->outbuf, smb_flg2,
1600 SVAL(req->outbuf, smb_flg2)
1601 & (~FLAGS2_LONG_PATH_COMPONENTS));
1604 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1605 SSVAL(req->outbuf, smb_flg2,
1606 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1608 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1609 smb_fn_name(req->cmd),
1616 TALLOC_FREE(directory);
1617 TALLOC_FREE(smb_fname);
1618 END_PROFILE(SMBsearch);
1622 /****************************************************************************
1623 Reply to a fclose (stop directory search).
1624 ****************************************************************************/
1626 void reply_fclose(struct smb_request *req)
1634 bool path_contains_wcard = False;
1635 TALLOC_CTX *ctx = talloc_tos();
1636 struct smbd_server_connection *sconn = req->sconn;
1638 START_PROFILE(SMBfclose);
1640 if (lp_posix_pathnames()) {
1641 reply_unknown_new(req, req->cmd);
1642 END_PROFILE(SMBfclose);
1646 p = (const char *)req->buf + 1;
1647 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1648 &err, &path_contains_wcard);
1649 if (!NT_STATUS_IS_OK(err)) {
1650 reply_nterror(req, err);
1651 END_PROFILE(SMBfclose);
1655 status_len = SVAL(p,0);
1658 if (status_len == 0) {
1659 reply_force_doserror(req, ERRSRV, ERRsrverror);
1660 END_PROFILE(SMBfclose);
1664 memcpy(status,p,21);
1666 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1667 /* Close the dptr - we know it's gone */
1668 dptr_close(sconn, &dptr_num);
1671 reply_outbuf(req, 1, 0);
1672 SSVAL(req->outbuf,smb_vwv0,0);
1674 DEBUG(3,("search close\n"));
1676 END_PROFILE(SMBfclose);
1680 /****************************************************************************
1682 ****************************************************************************/
1684 void reply_open(struct smb_request *req)
1686 connection_struct *conn = req->conn;
1687 struct smb_filename *smb_fname = NULL;
1699 uint32 create_disposition;
1700 uint32 create_options = 0;
1701 uint32_t private_flags = 0;
1703 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1704 TALLOC_CTX *ctx = talloc_tos();
1706 START_PROFILE(SMBopen);
1709 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1713 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1714 deny_mode = SVAL(req->vwv+0, 0);
1715 dos_attr = SVAL(req->vwv+1, 0);
1717 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1718 STR_TERMINATE, &status);
1719 if (!NT_STATUS_IS_OK(status)) {
1720 reply_nterror(req, status);
1724 status = filename_convert(ctx,
1726 req->flags2 & FLAGS2_DFS_PATHNAMES,
1731 if (!NT_STATUS_IS_OK(status)) {
1732 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1733 reply_botherror(req,
1734 NT_STATUS_PATH_NOT_COVERED,
1735 ERRSRV, ERRbadpath);
1738 reply_nterror(req, status);
1742 if (!map_open_params_to_ntcreate(smb_fname, deny_mode,
1743 OPENX_FILE_EXISTS_OPEN, &access_mask,
1744 &share_mode, &create_disposition,
1745 &create_options, &private_flags)) {
1746 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1750 status = SMB_VFS_CREATE_FILE(
1753 0, /* root_dir_fid */
1754 smb_fname, /* fname */
1755 access_mask, /* access_mask */
1756 share_mode, /* share_access */
1757 create_disposition, /* create_disposition*/
1758 create_options, /* create_options */
1759 dos_attr, /* file_attributes */
1760 oplock_request, /* oplock_request */
1761 0, /* allocation_size */
1768 if (!NT_STATUS_IS_OK(status)) {
1769 if (open_was_deferred(req->mid)) {
1770 /* We have re-scheduled this call. */
1773 reply_openerror(req, status);
1777 size = smb_fname->st.st_ex_size;
1778 fattr = dos_mode(conn, smb_fname);
1780 /* Deal with other possible opens having a modified
1782 if (ask_sharemode) {
1783 struct timespec write_time_ts;
1785 ZERO_STRUCT(write_time_ts);
1786 get_file_infos(fsp->file_id, NULL, &write_time_ts);
1787 if (!null_timespec(write_time_ts)) {
1788 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1792 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1795 DEBUG(3,("attempt to open a directory %s\n",
1797 close_file(req, fsp, ERROR_CLOSE);
1798 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1799 ERRDOS, ERRnoaccess);
1803 reply_outbuf(req, 7, 0);
1804 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1805 SSVAL(req->outbuf,smb_vwv1,fattr);
1806 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1807 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1809 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1811 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1812 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1814 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1815 SCVAL(req->outbuf,smb_flg,
1816 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1819 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1820 SCVAL(req->outbuf,smb_flg,
1821 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1824 TALLOC_FREE(smb_fname);
1825 END_PROFILE(SMBopen);
1829 /****************************************************************************
1830 Reply to an open and X.
1831 ****************************************************************************/
1833 void reply_open_and_X(struct smb_request *req)
1835 connection_struct *conn = req->conn;
1836 struct smb_filename *smb_fname = NULL;
1841 /* Breakout the oplock request bits so we can set the
1842 reply bits separately. */
1843 int ex_oplock_request;
1844 int core_oplock_request;
1847 int smb_sattr = SVAL(req->vwv+4, 0);
1848 uint32 smb_time = make_unix_date3(req->vwv+6);
1856 uint64_t allocation_size;
1857 ssize_t retval = -1;
1860 uint32 create_disposition;
1861 uint32 create_options = 0;
1862 uint32_t private_flags = 0;
1863 TALLOC_CTX *ctx = talloc_tos();
1865 START_PROFILE(SMBopenX);
1867 if (req->wct < 15) {
1868 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1872 open_flags = SVAL(req->vwv+2, 0);
1873 deny_mode = SVAL(req->vwv+3, 0);
1874 smb_attr = SVAL(req->vwv+5, 0);
1875 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1876 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1877 oplock_request = ex_oplock_request | core_oplock_request;
1878 smb_ofun = SVAL(req->vwv+8, 0);
1879 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1881 /* If it's an IPC, pass off the pipe handler. */
1883 if (lp_nt_pipe_support()) {
1884 reply_open_pipe_and_X(conn, req);
1886 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1891 /* XXXX we need to handle passed times, sattr and flags */
1892 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1893 STR_TERMINATE, &status);
1894 if (!NT_STATUS_IS_OK(status)) {
1895 reply_nterror(req, status);
1899 status = filename_convert(ctx,
1901 req->flags2 & FLAGS2_DFS_PATHNAMES,
1906 if (!NT_STATUS_IS_OK(status)) {
1907 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1908 reply_botherror(req,
1909 NT_STATUS_PATH_NOT_COVERED,
1910 ERRSRV, ERRbadpath);
1913 reply_nterror(req, status);
1917 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, smb_ofun,
1918 &access_mask, &share_mode,
1919 &create_disposition,
1922 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1926 status = SMB_VFS_CREATE_FILE(
1929 0, /* root_dir_fid */
1930 smb_fname, /* fname */
1931 access_mask, /* access_mask */
1932 share_mode, /* share_access */
1933 create_disposition, /* create_disposition*/
1934 create_options, /* create_options */
1935 smb_attr, /* file_attributes */
1936 oplock_request, /* oplock_request */
1937 0, /* allocation_size */
1942 &smb_action); /* pinfo */
1944 if (!NT_STATUS_IS_OK(status)) {
1945 if (open_was_deferred(req->mid)) {
1946 /* We have re-scheduled this call. */
1949 reply_openerror(req, status);
1953 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1954 if the file is truncated or created. */
1955 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1956 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1957 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1958 close_file(req, fsp, ERROR_CLOSE);
1959 reply_nterror(req, NT_STATUS_DISK_FULL);
1962 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1964 close_file(req, fsp, ERROR_CLOSE);
1965 reply_nterror(req, NT_STATUS_DISK_FULL);
1968 smb_fname->st.st_ex_size =
1969 SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
1972 fattr = dos_mode(conn, smb_fname);
1973 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1975 close_file(req, fsp, ERROR_CLOSE);
1976 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1980 /* If the caller set the extended oplock request bit
1981 and we granted one (by whatever means) - set the
1982 correct bit for extended oplock reply.
1985 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1986 smb_action |= EXTENDED_OPLOCK_GRANTED;
1989 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1990 smb_action |= EXTENDED_OPLOCK_GRANTED;
1993 /* If the caller set the core oplock request bit
1994 and we granted one (by whatever means) - set the
1995 correct bit for core oplock reply.
1998 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1999 reply_outbuf(req, 19, 0);
2001 reply_outbuf(req, 15, 0);
2004 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2005 SCVAL(req->outbuf, smb_flg,
2006 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2009 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2010 SCVAL(req->outbuf, smb_flg,
2011 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2014 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2015 SSVAL(req->outbuf,smb_vwv3,fattr);
2016 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2017 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2019 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2021 SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size);
2022 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2023 SSVAL(req->outbuf,smb_vwv11,smb_action);
2025 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2026 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2031 TALLOC_FREE(smb_fname);
2032 END_PROFILE(SMBopenX);
2036 /****************************************************************************
2037 Reply to a SMBulogoffX.
2038 ****************************************************************************/
2040 void reply_ulogoffX(struct smb_request *req)
2042 struct smbd_server_connection *sconn = req->sconn;
2045 START_PROFILE(SMBulogoffX);
2047 vuser = get_valid_user_struct(sconn, req->vuid);
2050 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2054 /* in user level security we are supposed to close any files
2055 open by this user */
2056 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2057 file_close_user(req->vuid);
2060 invalidate_vuid(sconn, req->vuid);
2062 reply_outbuf(req, 2, 0);
2064 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2066 END_PROFILE(SMBulogoffX);
2067 req->vuid = UID_FIELD_INVALID;
2071 /****************************************************************************
2072 Reply to a mknew or a create.
2073 ****************************************************************************/
2075 void reply_mknew(struct smb_request *req)
2077 connection_struct *conn = req->conn;
2078 struct smb_filename *smb_fname = NULL;
2081 struct smb_file_time ft;
2083 int oplock_request = 0;
2085 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2086 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2087 uint32 create_disposition;
2088 uint32 create_options = 0;
2089 TALLOC_CTX *ctx = talloc_tos();
2091 START_PROFILE(SMBcreate);
2095 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2099 fattr = SVAL(req->vwv+0, 0);
2100 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2103 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2105 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2106 STR_TERMINATE, &status);
2107 if (!NT_STATUS_IS_OK(status)) {
2108 reply_nterror(req, status);
2112 status = filename_convert(ctx,
2114 req->flags2 & FLAGS2_DFS_PATHNAMES,
2119 if (!NT_STATUS_IS_OK(status)) {
2120 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2121 reply_botherror(req,
2122 NT_STATUS_PATH_NOT_COVERED,
2123 ERRSRV, ERRbadpath);
2126 reply_nterror(req, status);
2130 if (fattr & aVOLID) {
2131 DEBUG(0,("Attempt to create file (%s) with volid set - "
2132 "please report this\n",
2133 smb_fname_str_dbg(smb_fname)));
2136 if(req->cmd == SMBmknew) {
2137 /* We should fail if file exists. */
2138 create_disposition = FILE_CREATE;
2140 /* Create if file doesn't exist, truncate if it does. */
2141 create_disposition = FILE_OVERWRITE_IF;
2144 status = SMB_VFS_CREATE_FILE(
2147 0, /* root_dir_fid */
2148 smb_fname, /* fname */
2149 access_mask, /* access_mask */
2150 share_mode, /* share_access */
2151 create_disposition, /* create_disposition*/
2152 create_options, /* create_options */
2153 fattr, /* file_attributes */
2154 oplock_request, /* oplock_request */
2155 0, /* allocation_size */
2156 0, /* private_flags */
2162 if (!NT_STATUS_IS_OK(status)) {
2163 if (open_was_deferred(req->mid)) {
2164 /* We have re-scheduled this call. */
2167 reply_openerror(req, status);
2171 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2172 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2173 if (!NT_STATUS_IS_OK(status)) {
2174 END_PROFILE(SMBcreate);
2178 reply_outbuf(req, 1, 0);
2179 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2181 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2182 SCVAL(req->outbuf,smb_flg,
2183 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2186 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2187 SCVAL(req->outbuf,smb_flg,
2188 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2191 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2192 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2193 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2194 (unsigned int)fattr));
2197 TALLOC_FREE(smb_fname);
2198 END_PROFILE(SMBcreate);
2202 /****************************************************************************
2203 Reply to a create temporary file.
2204 ****************************************************************************/
2206 void reply_ctemp(struct smb_request *req)
2208 connection_struct *conn = req->conn;
2209 struct smb_filename *smb_fname = NULL;
2217 TALLOC_CTX *ctx = talloc_tos();
2219 START_PROFILE(SMBctemp);
2222 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2226 fattr = SVAL(req->vwv+0, 0);
2227 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2229 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2230 STR_TERMINATE, &status);
2231 if (!NT_STATUS_IS_OK(status)) {
2232 reply_nterror(req, status);
2236 fname = talloc_asprintf(ctx,
2240 fname = talloc_strdup(ctx, "TMXXXXXX");
2244 reply_nterror(req, NT_STATUS_NO_MEMORY);
2248 status = filename_convert(ctx, conn,
2249 req->flags2 & FLAGS2_DFS_PATHNAMES,
2254 if (!NT_STATUS_IS_OK(status)) {
2255 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2256 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2257 ERRSRV, ERRbadpath);
2260 reply_nterror(req, status);
2264 tmpfd = mkstemp(smb_fname->base_name);
2266 reply_nterror(req, map_nt_error_from_unix(errno));
2270 SMB_VFS_STAT(conn, smb_fname);
2272 /* We should fail if file does not exist. */
2273 status = SMB_VFS_CREATE_FILE(
2276 0, /* root_dir_fid */
2277 smb_fname, /* fname */
2278 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2279 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2280 FILE_OPEN, /* create_disposition*/
2281 0, /* create_options */
2282 fattr, /* file_attributes */
2283 oplock_request, /* oplock_request */
2284 0, /* allocation_size */
2285 0, /* private_flags */
2291 /* close fd from mkstemp() */
2294 if (!NT_STATUS_IS_OK(status)) {
2295 if (open_was_deferred(req->mid)) {
2296 /* We have re-scheduled this call. */
2299 reply_openerror(req, status);
2303 reply_outbuf(req, 1, 0);
2304 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2306 /* the returned filename is relative to the directory */
2307 s = strrchr_m(fsp->fsp_name->base_name, '/');
2309 s = fsp->fsp_name->base_name;
2315 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2316 thing in the byte section. JRA */
2317 SSVALS(p, 0, -1); /* what is this? not in spec */
2319 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2321 reply_nterror(req, NT_STATUS_NO_MEMORY);
2325 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2326 SCVAL(req->outbuf, smb_flg,
2327 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2330 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2331 SCVAL(req->outbuf, smb_flg,
2332 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2335 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2336 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2337 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2339 TALLOC_FREE(smb_fname);
2340 END_PROFILE(SMBctemp);
2344 /*******************************************************************
2345 Check if a user is allowed to rename a file.
2346 ********************************************************************/
2348 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2353 if (!CAN_WRITE(conn)) {
2354 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2357 fmode = dos_mode(conn, fsp->fsp_name);
2358 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2359 return NT_STATUS_NO_SUCH_FILE;
2362 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2363 if (fsp->posix_open) {
2364 return NT_STATUS_OK;
2367 /* If no pathnames are open below this
2368 directory, allow the rename. */
2370 if (file_find_subpath(fsp)) {
2371 return NT_STATUS_ACCESS_DENIED;
2373 return NT_STATUS_OK;
2376 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2377 return NT_STATUS_OK;
2380 return NT_STATUS_ACCESS_DENIED;
2383 /*******************************************************************
2384 * unlink a file with all relevant access checks
2385 *******************************************************************/
2387 static NTSTATUS do_unlink(connection_struct *conn,
2388 struct smb_request *req,
2389 struct smb_filename *smb_fname,
2394 uint32 dirtype_orig = dirtype;
2397 bool posix_paths = lp_posix_pathnames();
2399 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2400 smb_fname_str_dbg(smb_fname),
2403 if (!CAN_WRITE(conn)) {
2404 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2408 ret = SMB_VFS_LSTAT(conn, smb_fname);
2410 ret = SMB_VFS_STAT(conn, smb_fname);
2413 return map_nt_error_from_unix(errno);
2416 fattr = dos_mode(conn, smb_fname);
2418 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2419 dirtype = aDIR|aARCH|aRONLY;
2422 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2424 return NT_STATUS_NO_SUCH_FILE;
2427 if (!dir_check_ftype(conn, fattr, dirtype)) {
2429 return NT_STATUS_FILE_IS_A_DIRECTORY;
2431 return NT_STATUS_NO_SUCH_FILE;
2434 if (dirtype_orig & 0x8000) {
2435 /* These will never be set for POSIX. */
2436 return NT_STATUS_NO_SUCH_FILE;
2440 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2441 return NT_STATUS_FILE_IS_A_DIRECTORY;
2444 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2445 return NT_STATUS_NO_SUCH_FILE;
2448 if (dirtype & 0xFF00) {
2449 /* These will never be set for POSIX. */
2450 return NT_STATUS_NO_SUCH_FILE;
2455 return NT_STATUS_NO_SUCH_FILE;
2458 /* Can't delete a directory. */
2460 return NT_STATUS_FILE_IS_A_DIRECTORY;
2465 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2466 return NT_STATUS_OBJECT_NAME_INVALID;
2467 #endif /* JRATEST */
2469 /* On open checks the open itself will check the share mode, so
2470 don't do it here as we'll get it wrong. */
2472 status = SMB_VFS_CREATE_FILE
2475 0, /* root_dir_fid */
2476 smb_fname, /* fname */
2477 DELETE_ACCESS, /* access_mask */
2478 FILE_SHARE_NONE, /* share_access */
2479 FILE_OPEN, /* create_disposition*/
2480 FILE_NON_DIRECTORY_FILE, /* create_options */
2481 /* file_attributes */
2482 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2483 FILE_ATTRIBUTE_NORMAL,
2484 0, /* oplock_request */
2485 0, /* allocation_size */
2486 0, /* private_flags */
2492 if (!NT_STATUS_IS_OK(status)) {
2493 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2494 nt_errstr(status)));
2498 status = can_set_delete_on_close(fsp, fattr);
2499 if (!NT_STATUS_IS_OK(status)) {
2500 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2502 smb_fname_str_dbg(smb_fname),
2503 nt_errstr(status)));
2504 close_file(req, fsp, NORMAL_CLOSE);
2508 /* The set is across all open files on this dev/inode pair. */
2509 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2510 close_file(req, fsp, NORMAL_CLOSE);
2511 return NT_STATUS_ACCESS_DENIED;
2514 return close_file(req, fsp, NORMAL_CLOSE);
2517 /****************************************************************************
2518 The guts of the unlink command, split out so it may be called by the NT SMB
2520 ****************************************************************************/
2522 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2523 uint32 dirtype, struct smb_filename *smb_fname,
2526 char *fname_dir = NULL;
2527 char *fname_mask = NULL;
2529 NTSTATUS status = NT_STATUS_OK;
2530 TALLOC_CTX *ctx = talloc_tos();
2532 /* Split up the directory from the filename/mask. */
2533 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2534 &fname_dir, &fname_mask);
2535 if (!NT_STATUS_IS_OK(status)) {
2540 * We should only check the mangled cache
2541 * here if unix_convert failed. This means
2542 * that the path in 'mask' doesn't exist
2543 * on the file system and so we need to look
2544 * for a possible mangle. This patch from
2545 * Tine Smukavec <valentin.smukavec@hermes.si>.
2548 if (!VALID_STAT(smb_fname->st) &&
2549 mangle_is_mangled(fname_mask, conn->params)) {
2550 char *new_mask = NULL;
2551 mangle_lookup_name_from_8_3(ctx, fname_mask,
2552 &new_mask, conn->params);
2554 TALLOC_FREE(fname_mask);
2555 fname_mask = new_mask;
2562 * Only one file needs to be unlinked. Append the mask back
2563 * onto the directory.
2565 TALLOC_FREE(smb_fname->base_name);
2566 smb_fname->base_name = talloc_asprintf(smb_fname,
2570 if (!smb_fname->base_name) {
2571 status = NT_STATUS_NO_MEMORY;
2575 dirtype = FILE_ATTRIBUTE_NORMAL;
2578 status = check_name(conn, smb_fname->base_name);
2579 if (!NT_STATUS_IS_OK(status)) {
2583 status = do_unlink(conn, req, smb_fname, dirtype);
2584 if (!NT_STATUS_IS_OK(status)) {
2590 struct smb_Dir *dir_hnd = NULL;
2592 const char *dname = NULL;
2593 char *talloced = NULL;
2595 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2596 status = NT_STATUS_OBJECT_NAME_INVALID;
2600 if (strequal(fname_mask,"????????.???")) {
2601 TALLOC_FREE(fname_mask);
2602 fname_mask = talloc_strdup(ctx, "*");
2604 status = NT_STATUS_NO_MEMORY;
2609 status = check_name(conn, fname_dir);
2610 if (!NT_STATUS_IS_OK(status)) {
2614 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2616 if (dir_hnd == NULL) {
2617 status = map_nt_error_from_unix(errno);
2621 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2622 the pattern matches against the long name, otherwise the short name
2623 We don't implement this yet XXXX
2626 status = NT_STATUS_NO_SUCH_FILE;
2628 while ((dname = ReadDirName(dir_hnd, &offset,
2629 &smb_fname->st, &talloced))) {
2630 TALLOC_CTX *frame = talloc_stackframe();
2632 if (!is_visible_file(conn, fname_dir, dname,
2633 &smb_fname->st, true)) {
2635 TALLOC_FREE(talloced);
2639 /* Quick check for "." and ".." */
2640 if (ISDOT(dname) || ISDOTDOT(dname)) {
2642 TALLOC_FREE(talloced);
2646 if(!mask_match(dname, fname_mask,
2647 conn->case_sensitive)) {
2649 TALLOC_FREE(talloced);
2653 TALLOC_FREE(smb_fname->base_name);
2654 smb_fname->base_name =
2655 talloc_asprintf(smb_fname, "%s/%s",
2658 if (!smb_fname->base_name) {
2659 TALLOC_FREE(dir_hnd);
2660 status = NT_STATUS_NO_MEMORY;
2662 TALLOC_FREE(talloced);
2666 status = check_name(conn, smb_fname->base_name);
2667 if (!NT_STATUS_IS_OK(status)) {
2668 TALLOC_FREE(dir_hnd);
2670 TALLOC_FREE(talloced);
2674 status = do_unlink(conn, req, smb_fname, dirtype);
2675 if (!NT_STATUS_IS_OK(status)) {
2677 TALLOC_FREE(talloced);
2682 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2683 smb_fname->base_name));
2686 TALLOC_FREE(talloced);
2688 TALLOC_FREE(dir_hnd);
2691 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2692 status = map_nt_error_from_unix(errno);
2696 TALLOC_FREE(fname_dir);
2697 TALLOC_FREE(fname_mask);
2701 /****************************************************************************
2703 ****************************************************************************/
2705 void reply_unlink(struct smb_request *req)
2707 connection_struct *conn = req->conn;
2709 struct smb_filename *smb_fname = NULL;
2712 bool path_contains_wcard = False;
2713 TALLOC_CTX *ctx = talloc_tos();
2715 START_PROFILE(SMBunlink);
2718 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2722 dirtype = SVAL(req->vwv+0, 0);
2724 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2725 STR_TERMINATE, &status,
2726 &path_contains_wcard);
2727 if (!NT_STATUS_IS_OK(status)) {
2728 reply_nterror(req, status);
2732 status = filename_convert(ctx, conn,
2733 req->flags2 & FLAGS2_DFS_PATHNAMES,
2735 UCF_COND_ALLOW_WCARD_LCOMP,
2736 &path_contains_wcard,
2738 if (!NT_STATUS_IS_OK(status)) {
2739 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2740 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2741 ERRSRV, ERRbadpath);
2744 reply_nterror(req, status);
2748 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2750 status = unlink_internals(conn, req, dirtype, smb_fname,
2751 path_contains_wcard);
2752 if (!NT_STATUS_IS_OK(status)) {
2753 if (open_was_deferred(req->mid)) {
2754 /* We have re-scheduled this call. */
2757 reply_nterror(req, status);
2761 reply_outbuf(req, 0, 0);
2763 TALLOC_FREE(smb_fname);
2764 END_PROFILE(SMBunlink);
2768 /****************************************************************************
2770 ****************************************************************************/
2772 static void fail_readraw(void)
2774 const char *errstr = talloc_asprintf(talloc_tos(),
2775 "FAIL ! reply_readbraw: socket write fail (%s)",
2780 exit_server_cleanly(errstr);
2783 /****************************************************************************
2784 Fake (read/write) sendfile. Returns -1 on read or write fail.
2785 ****************************************************************************/
2787 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2791 size_t tosend = nread;
2798 bufsize = MIN(nread, 65536);
2800 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2804 while (tosend > 0) {
2808 if (tosend > bufsize) {
2813 ret = read_file(fsp,buf,startpos,cur_read);
2819 /* If we had a short read, fill with zeros. */
2820 if (ret < cur_read) {
2821 memset(buf + ret, '\0', cur_read - ret);
2824 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
2826 char addr[INET6_ADDRSTRLEN];
2828 * Try and give an error message saying what
2831 DEBUG(0, ("write_data failed for client %s. "
2833 get_peer_addr(fsp->conn->sconn->sock, addr,
2840 startpos += cur_read;
2844 return (ssize_t)nread;
2847 #if defined(WITH_SENDFILE)
2848 /****************************************************************************
2849 Deal with the case of sendfile reading less bytes from the file than
2850 requested. Fill with zeros (all we can do).
2851 ****************************************************************************/
2853 static void sendfile_short_send(files_struct *fsp,
2858 #define SHORT_SEND_BUFSIZE 1024
2859 if (nread < headersize) {
2860 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2861 "header for file %s (%s). Terminating\n",
2862 fsp_str_dbg(fsp), strerror(errno)));
2863 exit_server_cleanly("sendfile_short_send failed");
2866 nread -= headersize;
2868 if (nread < smb_maxcnt) {
2869 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2871 exit_server_cleanly("sendfile_short_send: "
2875 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2876 "with zeros !\n", fsp_str_dbg(fsp)));
2878 while (nread < smb_maxcnt) {
2880 * We asked for the real file size and told sendfile
2881 * to not go beyond the end of the file. But it can
2882 * happen that in between our fstat call and the
2883 * sendfile call the file was truncated. This is very
2884 * bad because we have already announced the larger
2885 * number of bytes to the client.
2887 * The best we can do now is to send 0-bytes, just as
2888 * a read from a hole in a sparse file would do.
2890 * This should happen rarely enough that I don't care
2891 * about efficiency here :-)
2895 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2896 if (write_data(fsp->conn->sconn->sock, buf, to_write)
2898 char addr[INET6_ADDRSTRLEN];
2900 * Try and give an error message saying what
2903 DEBUG(0, ("write_data failed for client %s. "
2906 fsp->conn->sconn->sock, addr,
2909 exit_server_cleanly("sendfile_short_send: "
2910 "write_data failed");
2917 #endif /* defined WITH_SENDFILE */
2919 /****************************************************************************
2920 Return a readbraw error (4 bytes of zero).
2921 ****************************************************************************/
2923 static void reply_readbraw_error(struct smbd_server_connection *sconn)
2929 smbd_lock_socket(sconn);
2930 if (write_data(sconn->sock,header,4) != 4) {
2931 char addr[INET6_ADDRSTRLEN];
2933 * Try and give an error message saying what
2936 DEBUG(0, ("write_data failed for client %s. "
2938 get_peer_addr(sconn->sock, addr, sizeof(addr)),
2943 smbd_unlock_socket(sconn);
2946 /****************************************************************************
2947 Use sendfile in readbraw.
2948 ****************************************************************************/
2950 static void send_file_readbraw(connection_struct *conn,
2951 struct smb_request *req,
2957 struct smbd_server_connection *sconn = req->sconn;
2958 char *outbuf = NULL;
2961 #if defined(WITH_SENDFILE)
2963 * We can only use sendfile on a non-chained packet
2964 * but we can use on a non-oplocked file. tridge proved this
2965 * on a train in Germany :-). JRA.
2966 * reply_readbraw has already checked the length.
2969 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2970 (fsp->wcp == NULL) &&
2971 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
2972 ssize_t sendfile_read = -1;
2974 DATA_BLOB header_blob;
2976 _smb_setlen(header,nread);
2977 header_blob = data_blob_const(header, 4);
2979 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
2980 &header_blob, startpos,
2982 if (sendfile_read == -1) {
2983 /* Returning ENOSYS means no data at all was sent.
2984 * Do this as a normal read. */
2985 if (errno == ENOSYS) {
2986 goto normal_readbraw;
2990 * Special hack for broken Linux with no working sendfile. If we
2991 * return EINTR we sent the header but not the rest of the data.
2992 * Fake this up by doing read/write calls.
2994 if (errno == EINTR) {
2995 /* Ensure we don't do this again. */
2996 set_use_sendfile(SNUM(conn), False);
2997 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2999 if (fake_sendfile(fsp, startpos, nread) == -1) {
3000 DEBUG(0,("send_file_readbraw: "
3001 "fake_sendfile failed for "
3005 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3010 DEBUG(0,("send_file_readbraw: sendfile failed for "
3011 "file %s (%s). Terminating\n",
3012 fsp_str_dbg(fsp), strerror(errno)));
3013 exit_server_cleanly("send_file_readbraw sendfile failed");
3014 } else if (sendfile_read == 0) {
3016 * Some sendfile implementations return 0 to indicate
3017 * that there was a short read, but nothing was
3018 * actually written to the socket. In this case,
3019 * fallback to the normal read path so the header gets
3020 * the correct byte count.
3022 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3023 "bytes falling back to the normal read: "
3024 "%s\n", fsp_str_dbg(fsp)));
3025 goto normal_readbraw;
3028 /* Deal with possible short send. */
3029 if (sendfile_read != 4+nread) {
3030 sendfile_short_send(fsp, sendfile_read, 4, nread);
3038 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
3040 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
3041 (unsigned)(nread+4)));
3042 reply_readbraw_error(sconn);
3047 ret = read_file(fsp,outbuf+4,startpos,nread);
3048 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3057 _smb_setlen(outbuf,ret);
3058 if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
3059 char addr[INET6_ADDRSTRLEN];
3061 * Try and give an error message saying what
3064 DEBUG(0, ("write_data failed for client %s. "
3066 get_peer_addr(fsp->conn->sconn->sock, addr,
3073 TALLOC_FREE(outbuf);
3076 /****************************************************************************
3077 Reply to a readbraw (core+ protocol).
3078 ****************************************************************************/
3080 void reply_readbraw(struct smb_request *req)
3082 connection_struct *conn = req->conn;
3083 struct smbd_server_connection *sconn = req->sconn;
3084 ssize_t maxcount,mincount;
3088 struct lock_struct lock;
3091 START_PROFILE(SMBreadbraw);
3093 if (srv_is_signing_active(sconn) ||
3094 is_encrypted_packet(req->inbuf)) {
3095 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3096 "raw reads/writes are disallowed.");
3100 reply_readbraw_error(sconn);
3101 END_PROFILE(SMBreadbraw);
3105 if (sconn->smb1.echo_handler.trusted_fde) {
3106 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3107 "'async smb echo handler = yes'\n"));
3108 reply_readbraw_error(sconn);
3109 END_PROFILE(SMBreadbraw);
3114 * Special check if an oplock break has been issued
3115 * and the readraw request croses on the wire, we must
3116 * return a zero length response here.
3119 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3122 * We have to do a check_fsp by hand here, as
3123 * we must always return 4 zero bytes on error,
3127 if (!fsp || !conn || conn != fsp->conn ||
3128 req->vuid != fsp->vuid ||
3129 fsp->is_directory || fsp->fh->fd == -1) {
3131 * fsp could be NULL here so use the value from the packet. JRA.
3133 DEBUG(3,("reply_readbraw: fnum %d not valid "
3135 (int)SVAL(req->vwv+0, 0)));
3136 reply_readbraw_error(sconn);
3137 END_PROFILE(SMBreadbraw);
3141 /* Do a "by hand" version of CHECK_READ. */
3142 if (!(fsp->can_read ||
3143 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3144 (fsp->access_mask & FILE_EXECUTE)))) {
3145 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3146 (int)SVAL(req->vwv+0, 0)));
3147 reply_readbraw_error(sconn);
3148 END_PROFILE(SMBreadbraw);
3152 flush_write_cache(fsp, READRAW_FLUSH);
3154 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3155 if(req->wct == 10) {
3157 * This is a large offset (64 bit) read.
3159 #ifdef LARGE_SMB_OFF_T
3161 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3163 #else /* !LARGE_SMB_OFF_T */
3166 * Ensure we haven't been sent a >32 bit offset.
3169 if(IVAL(req->vwv+8, 0) != 0) {
3170 DEBUG(0,("reply_readbraw: large offset "
3171 "(%x << 32) used and we don't support "
3172 "64 bit offsets.\n",
3173 (unsigned int)IVAL(req->vwv+8, 0) ));
3174 reply_readbraw_error();
3175 END_PROFILE(SMBreadbraw);
3179 #endif /* LARGE_SMB_OFF_T */
3182 DEBUG(0,("reply_readbraw: negative 64 bit "
3183 "readraw offset (%.0f) !\n",
3184 (double)startpos ));
3185 reply_readbraw_error(sconn);
3186 END_PROFILE(SMBreadbraw);
3191 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3192 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3194 /* ensure we don't overrun the packet size */
3195 maxcount = MIN(65535,maxcount);
3197 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3198 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3201 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3202 reply_readbraw_error(sconn);
3203 END_PROFILE(SMBreadbraw);
3207 if (fsp_stat(fsp) == 0) {
3208 size = fsp->fsp_name->st.st_ex_size;
3211 if (startpos >= size) {
3214 nread = MIN(maxcount,(size - startpos));
3217 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3218 if (nread < mincount)
3222 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3223 "min=%lu nread=%lu\n",
3224 fsp->fnum, (double)startpos,
3225 (unsigned long)maxcount,
3226 (unsigned long)mincount,
3227 (unsigned long)nread ) );
3229 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3231 DEBUG(5,("reply_readbraw finished\n"));
3233 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3235 END_PROFILE(SMBreadbraw);
3240 #define DBGC_CLASS DBGC_LOCKING
3242 /****************************************************************************
3243 Reply to a lockread (core+ protocol).
3244 ****************************************************************************/
3246 void reply_lockread(struct smb_request *req)
3248 connection_struct *conn = req->conn;
3255 struct byte_range_lock *br_lck = NULL;
3257 struct smbd_server_connection *sconn = req->sconn;
3259 START_PROFILE(SMBlockread);
3262 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3263 END_PROFILE(SMBlockread);
3267 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3269 if (!check_fsp(conn, req, fsp)) {
3270 END_PROFILE(SMBlockread);
3274 if (!CHECK_READ(fsp,req)) {
3275 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3276 END_PROFILE(SMBlockread);
3280 numtoread = SVAL(req->vwv+1, 0);
3281 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3283 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3285 reply_outbuf(req, 5, numtoread + 3);
3287 data = smb_buf(req->outbuf) + 3;
3290 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3291 * protocol request that predates the read/write lock concept.
3292 * Thus instead of asking for a read lock here we need to ask
3293 * for a write lock. JRA.
3294 * Note that the requested lock size is unaffected by max_recv.
3297 br_lck = do_lock(req->sconn->msg_ctx,
3299 (uint64_t)req->smbpid,
3300 (uint64_t)numtoread,
3304 False, /* Non-blocking lock. */
3308 TALLOC_FREE(br_lck);
3310 if (NT_STATUS_V(status)) {
3311 reply_nterror(req, status);
3312 END_PROFILE(SMBlockread);
3317 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3320 if (numtoread > sconn->smb1.negprot.max_recv) {
3321 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3322 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3323 (unsigned int)numtoread,
3324 (unsigned int)sconn->smb1.negprot.max_recv));
3325 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3327 nread = read_file(fsp,data,startpos,numtoread);
3330 reply_nterror(req, map_nt_error_from_unix(errno));
3331 END_PROFILE(SMBlockread);
3335 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3337 SSVAL(req->outbuf,smb_vwv0,nread);
3338 SSVAL(req->outbuf,smb_vwv5,nread+3);
3339 p = smb_buf(req->outbuf);
3340 SCVAL(p,0,0); /* pad byte. */
3343 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3344 fsp->fnum, (int)numtoread, (int)nread));
3346 END_PROFILE(SMBlockread);
3351 #define DBGC_CLASS DBGC_ALL
3353 /****************************************************************************
3355 ****************************************************************************/
3357 void reply_read(struct smb_request *req)
3359 connection_struct *conn = req->conn;
3366 struct lock_struct lock;
3367 struct smbd_server_connection *sconn = req->sconn;
3369 START_PROFILE(SMBread);
3372 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3373 END_PROFILE(SMBread);
3377 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3379 if (!check_fsp(conn, req, fsp)) {
3380 END_PROFILE(SMBread);
3384 if (!CHECK_READ(fsp,req)) {
3385 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3386 END_PROFILE(SMBread);
3390 numtoread = SVAL(req->vwv+1, 0);
3391 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3393 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3396 * The requested read size cannot be greater than max_recv. JRA.
3398 if (numtoread > sconn->smb1.negprot.max_recv) {
3399 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3400 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3401 (unsigned int)numtoread,
3402 (unsigned int)sconn->smb1.negprot.max_recv));
3403 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3406 reply_outbuf(req, 5, numtoread+3);
3408 data = smb_buf(req->outbuf) + 3;
3410 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3411 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3414 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3415 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3416 END_PROFILE(SMBread);
3421 nread = read_file(fsp,data,startpos,numtoread);
3424 reply_nterror(req, map_nt_error_from_unix(errno));
3428 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3430 SSVAL(req->outbuf,smb_vwv0,nread);
3431 SSVAL(req->outbuf,smb_vwv5,nread+3);
3432 SCVAL(smb_buf(req->outbuf),0,1);
3433 SSVAL(smb_buf(req->outbuf),1,nread);
3435 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3436 fsp->fnum, (int)numtoread, (int)nread ) );
3439 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3441 END_PROFILE(SMBread);
3445 /****************************************************************************
3447 ****************************************************************************/
3449 static int setup_readX_header(struct smb_request *req, char *outbuf,
3455 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3456 data = smb_buf(outbuf);
3458 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3460 SCVAL(outbuf,smb_vwv0,0xFF);
3461 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3462 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3463 SSVAL(outbuf,smb_vwv6,
3465 + 1 /* the wct field */
3466 + 12 * sizeof(uint16_t) /* vwv */
3467 + 2); /* the buflen field */
3468 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3469 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3470 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3471 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3475 /****************************************************************************
3476 Reply to a read and X - possibly using sendfile.
3477 ****************************************************************************/
3479 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3480 files_struct *fsp, SMB_OFF_T startpos,
3484 struct lock_struct lock;
3485 int saved_errno = 0;
3487 if(fsp_stat(fsp) == -1) {
3488 reply_nterror(req, map_nt_error_from_unix(errno));
3492 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3493 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3496 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3497 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3501 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3502 (startpos > fsp->fsp_name->st.st_ex_size)
3503 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3505 * We already know that we would do a short read, so don't
3506 * try the sendfile() path.
3508 goto nosendfile_read;
3511 #if defined(WITH_SENDFILE)
3513 * We can only use sendfile on a non-chained packet
3514 * but we can use on a non-oplocked file. tridge proved this
3515 * on a train in Germany :-). JRA.
3518 if (!req_is_in_chain(req) &&
3519 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3520 (fsp->wcp == NULL) &&
3521 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3522 uint8 headerbuf[smb_size + 12 * 2];
3526 * Set up the packet header before send. We
3527 * assume here the sendfile will work (get the
3528 * correct amount of data).
3531 header = data_blob_const(headerbuf, sizeof(headerbuf));
3533 construct_reply_common_req(req, (char *)headerbuf);
3534 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3536 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3537 startpos, smb_maxcnt);
3539 /* Returning ENOSYS means no data at all was sent.
3540 Do this as a normal read. */
3541 if (errno == ENOSYS) {
3546 * Special hack for broken Linux with no working sendfile. If we
3547 * return EINTR we sent the header but not the rest of the data.
3548 * Fake this up by doing read/write calls.
3551 if (errno == EINTR) {
3552 /* Ensure we don't do this again. */
3553 set_use_sendfile(SNUM(conn), False);
3554 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3555 nread = fake_sendfile(fsp, startpos,
3558 DEBUG(0,("send_file_readX: "
3559 "fake_sendfile failed for "
3563 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3565 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3566 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3567 /* No outbuf here means successful sendfile. */
3571 DEBUG(0,("send_file_readX: sendfile failed for file "
3572 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3574 exit_server_cleanly("send_file_readX sendfile failed");
3575 } else if (nread == 0) {
3577 * Some sendfile implementations return 0 to indicate
3578 * that there was a short read, but nothing was
3579 * actually written to the socket. In this case,
3580 * fallback to the normal read path so the header gets
3581 * the correct byte count.
3583 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3584 "falling back to the normal read: %s\n",
3589 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3590 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3592 /* Deal with possible short send. */
3593 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3594 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3596 /* No outbuf here means successful sendfile. */
3597 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3598 SMB_PERFCOUNT_END(&req->pcd);
3606 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3607 uint8 headerbuf[smb_size + 2*12];
3609 construct_reply_common_req(req, (char *)headerbuf);
3610 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3612 /* Send out the header. */
3613 if (write_data(req->sconn->sock, (char *)headerbuf,
3614 sizeof(headerbuf)) != sizeof(headerbuf)) {
3616 char addr[INET6_ADDRSTRLEN];
3618 * Try and give an error message saying what
3621 DEBUG(0, ("write_data failed for client %s. "
3623 get_peer_addr(req->sconn->sock, addr,
3627 DEBUG(0,("send_file_readX: write_data failed for file "
3628 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3630 exit_server_cleanly("send_file_readX sendfile failed");
3632 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3634 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3635 "file %s (%s).\n", fsp_str_dbg(fsp),
3637 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3644 reply_outbuf(req, 12, smb_maxcnt);
3646 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3647 saved_errno = errno;
3649 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3652 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3656 setup_readX_header(req, (char *)req->outbuf, nread);
3658 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3659 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3665 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3666 TALLOC_FREE(req->outbuf);
3670 /****************************************************************************
3671 Reply to a read and X.
3672 ****************************************************************************/
3674 void reply_read_and_X(struct smb_request *req)
3676 connection_struct *conn = req->conn;
3680 bool big_readX = False;
3682 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3685 START_PROFILE(SMBreadX);
3687 if ((req->wct != 10) && (req->wct != 12)) {
3688 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3692 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3693 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3694 smb_maxcnt = SVAL(req->vwv+5, 0);
3696 /* If it's an IPC, pass off the pipe handler. */
3698 reply_pipe_read_and_X(req);
3699 END_PROFILE(SMBreadX);
3703 if (!check_fsp(conn, req, fsp)) {
3704 END_PROFILE(SMBreadX);
3708 if (!CHECK_READ(fsp,req)) {
3709 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3710 END_PROFILE(SMBreadX);
3714 if (global_client_caps & CAP_LARGE_READX) {
3715 size_t upper_size = SVAL(req->vwv+7, 0);
3716 smb_maxcnt |= (upper_size<<16);
3717 if (upper_size > 1) {
3718 /* Can't do this on a chained packet. */
3719 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3720 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3721 END_PROFILE(SMBreadX);
3724 /* We currently don't do this on signed or sealed data. */
3725 if (srv_is_signing_active(req->sconn) ||
3726 is_encrypted_packet(req->inbuf)) {
3727 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3728 END_PROFILE(SMBreadX);
3731 /* Is there room in the reply for this data ? */
3732 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3734 NT_STATUS_INVALID_PARAMETER);
3735 END_PROFILE(SMBreadX);
3742 if (req->wct == 12) {
3743 #ifdef LARGE_SMB_OFF_T
3745 * This is a large offset (64 bit) read.
3747 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3749 #else /* !LARGE_SMB_OFF_T */
3752 * Ensure we haven't been sent a >32 bit offset.
3755 if(IVAL(req->vwv+10, 0) != 0) {
3756 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3757 "used and we don't support 64 bit offsets.\n",
3758 (unsigned int)IVAL(req->vwv+10, 0) ));
3759 END_PROFILE(SMBreadX);
3760 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3764 #endif /* LARGE_SMB_OFF_T */
3769 NTSTATUS status = schedule_aio_read_and_X(conn,
3774 if (NT_STATUS_IS_OK(status)) {
3775 /* Read scheduled - we're done. */
3778 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3779 /* Real error - report to client. */
3780 END_PROFILE(SMBreadX);
3781 reply_nterror(req, status);
3784 /* NT_STATUS_RETRY - fall back to sync read. */
3787 smbd_lock_socket(req->sconn);
3788 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3789 smbd_unlock_socket(req->sconn);
3792 END_PROFILE(SMBreadX);
3796 /****************************************************************************
3797 Error replies to writebraw must have smb_wct == 1. Fix this up.
3798 ****************************************************************************/
3800 void error_to_writebrawerr(struct smb_request *req)
3802 uint8 *old_outbuf = req->outbuf;
3804 reply_outbuf(req, 1, 0);
3806 memcpy(req->outbuf, old_outbuf, smb_size);
3807 TALLOC_FREE(old_outbuf);
3810 /****************************************************************************
3811 Read 4 bytes of a smb packet and return the smb length of the packet.
3812 Store the result in the buffer. This version of the function will
3813 never return a session keepalive (length of zero).
3814 Timeout is in milliseconds.
3815 ****************************************************************************/
3817 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3820 uint8_t msgtype = SMBkeepalive;
3822 while (msgtype == SMBkeepalive) {
3825 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3827 if (!NT_STATUS_IS_OK(status)) {
3828 char addr[INET6_ADDRSTRLEN];
3829 /* Try and give an error message
3830 * saying what client failed. */
3831 DEBUG(0, ("read_fd_with_timeout failed for "
3832 "client %s read error = %s.\n",
3833 get_peer_addr(fd,addr,sizeof(addr)),
3834 nt_errstr(status)));
3838 msgtype = CVAL(inbuf, 0);
3841 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3842 (unsigned long)len));
3844 return NT_STATUS_OK;
3847 /****************************************************************************
3848 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3849 ****************************************************************************/
3851 void reply_writebraw(struct smb_request *req)
3853 connection_struct *conn = req->conn;
3856 ssize_t total_written=0;
3857 size_t numtowrite=0;
3863 struct lock_struct lock;
3866 START_PROFILE(SMBwritebraw);
3869 * If we ever reply with an error, it must have the SMB command
3870 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3873 SCVAL(req->inbuf,smb_com,SMBwritec);
3875 if (srv_is_signing_active(req->sconn)) {
3876 END_PROFILE(SMBwritebraw);
3877 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3878 "raw reads/writes are disallowed.");
3881 if (req->wct < 12) {
3882 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3883 error_to_writebrawerr(req);
3884 END_PROFILE(SMBwritebraw);
3888 if (req->sconn->smb1.echo_handler.trusted_fde) {
3889 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3890 "'async smb echo handler = yes'\n"));
3891 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3892 error_to_writebrawerr(req);
3893 END_PROFILE(SMBwritebraw);
3897 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3898 if (!check_fsp(conn, req, fsp)) {
3899 error_to_writebrawerr(req);
3900 END_PROFILE(SMBwritebraw);
3904 if (!CHECK_WRITE(fsp)) {
3905 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3906 error_to_writebrawerr(req);
3907 END_PROFILE(SMBwritebraw);
3911 tcount = IVAL(req->vwv+1, 0);
3912 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3913 write_through = BITSETW(req->vwv+7,0);
3915 /* We have to deal with slightly different formats depending
3916 on whether we are using the core+ or lanman1.0 protocol */
3918 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3919 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3920 data = smb_buf(req->inbuf);
3922 numtowrite = SVAL(req->vwv+10, 0);
3923 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3926 /* Ensure we don't write bytes past the end of this packet. */
3927 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3928 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3929 error_to_writebrawerr(req);
3930 END_PROFILE(SMBwritebraw);
3934 if (!fsp->print_file) {
3935 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3936 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3939 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3940 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3941 error_to_writebrawerr(req);
3942 END_PROFILE(SMBwritebraw);
3948 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3951 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3952 "wrote=%d sync=%d\n",
3953 fsp->fnum, (double)startpos, (int)numtowrite,
3954 (int)nwritten, (int)write_through));
3956 if (nwritten < (ssize_t)numtowrite) {
3957 reply_nterror(req, NT_STATUS_DISK_FULL);
3958 error_to_writebrawerr(req);
3962 total_written = nwritten;
3964 /* Allocate a buffer of 64k + length. */
3965 buf = TALLOC_ARRAY(NULL, char, 65540);
3967 reply_nterror(req, NT_STATUS_NO_MEMORY);
3968 error_to_writebrawerr(req);
3972 /* Return a SMBwritebraw message to the redirector to tell
3973 * it to send more bytes */
3975 memcpy(buf, req->inbuf, smb_size);
3976 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
3977 SCVAL(buf,smb_com,SMBwritebraw);
3978 SSVALS(buf,smb_vwv0,0xFFFF);
3980 if (!srv_send_smb(req->sconn,
3982 false, 0, /* no signing */
3983 IS_CONN_ENCRYPTED(conn),
3985 exit_server_cleanly("reply_writebraw: srv_send_smb "
3989 /* Now read the raw data into the buffer and write it */
3990 status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
3992 if (!NT_STATUS_IS_OK(status)) {
3993 exit_server_cleanly("secondary writebraw failed");
3996 /* Set up outbuf to return the correct size */
3997 reply_outbuf(req, 1, 0);
3999 if (numtowrite != 0) {
4001 if (numtowrite > 0xFFFF) {
4002 DEBUG(0,("reply_writebraw: Oversize secondary write "
4003 "raw requested (%u). Terminating\n",
4004 (unsigned int)numtowrite ));
4005 exit_server_cleanly("secondary writebraw failed");
4008 if (tcount > nwritten+numtowrite) {
4009 DEBUG(3,("reply_writebraw: Client overestimated the "
4011 (int)tcount,(int)nwritten,(int)numtowrite));
4014 status = read_data(req->sconn->sock, buf+4, numtowrite);
4016 if (!NT_STATUS_IS_OK(status)) {
4017 char addr[INET6_ADDRSTRLEN];
4018 /* Try and give an error message
4019 * saying what client failed. */
4020 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4021 "raw read failed (%s) for client %s. "
4022 "Terminating\n", nt_errstr(status),
4023 get_peer_addr(req->sconn->sock, addr,
4025 exit_server_cleanly("secondary writebraw failed");
4028 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4029 if (nwritten == -1) {
4031 reply_nterror(req, map_nt_error_from_unix(errno));
4032 error_to_writebrawerr(req);
4036 if (nwritten < (ssize_t)numtowrite) {
4037 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4038 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4042 total_written += nwritten;
4047 SSVAL(req->outbuf,smb_vwv0,total_written);
4049 status = sync_file(conn, fsp, write_through);
4050 if (!NT_STATUS_IS_OK(status)) {
4051 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4052 fsp_str_dbg(fsp), nt_errstr(status)));
4053 reply_nterror(req, status);
4054 error_to_writebrawerr(req);
4058 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4060 fsp->fnum, (double)startpos, (int)numtowrite,
4061 (int)total_written));
4063 if (!fsp->print_file) {
4064 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4067 /* We won't return a status if write through is not selected - this
4068 * follows what WfWg does */
4069 END_PROFILE(SMBwritebraw);
4071 if (!write_through && total_written==tcount) {
4073 #if RABBIT_PELLET_FIX
4075 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4076 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
4079 if (!send_keepalive(req->sconn->sock)) {
4080 exit_server_cleanly("reply_writebraw: send of "
4081 "keepalive failed");
4084 TALLOC_FREE(req->outbuf);
4089 if (!fsp->print_file) {
4090 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4093 END_PROFILE(SMBwritebraw);
4098 #define DBGC_CLASS DBGC_LOCKING
4100 /****************************************************************************
4101 Reply to a writeunlock (core+).
4102 ****************************************************************************/
4104 void reply_writeunlock(struct smb_request *req)
4106 connection_struct *conn = req->conn;
4107 ssize_t nwritten = -1;
4111 NTSTATUS status = NT_STATUS_OK;
4113 struct lock_struct lock;
4114 int saved_errno = 0;
4116 START_PROFILE(SMBwriteunlock);
4119 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4120 END_PROFILE(SMBwriteunlock);
4124 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4126 if (!check_fsp(conn, req, fsp)) {
4127 END_PROFILE(SMBwriteunlock);
4131 if (!CHECK_WRITE(fsp)) {
4132 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4133 END_PROFILE(SMBwriteunlock);
4137 numtowrite = SVAL(req->vwv+1, 0);
4138 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4139 data = (const char *)req->buf + 3;
4141 if (!fsp->print_file && numtowrite > 0) {
4142 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4143 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4146 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4147 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4148 END_PROFILE(SMBwriteunlock);
4153 /* The special X/Open SMB protocol handling of
4154 zero length writes is *NOT* done for
4156 if(numtowrite == 0) {
4159 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4160 saved_errno = errno;
4163 status = sync_file(conn, fsp, False /* write through */);
4164 if (!NT_STATUS_IS_OK(status)) {
4165 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4166 fsp_str_dbg(fsp), nt_errstr(status)));
4167 reply_nterror(req, status);
4172 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4176 if((nwritten < numtowrite) && (numtowrite != 0)) {
4177 reply_nterror(req, NT_STATUS_DISK_FULL);
4181 if (numtowrite && !fsp->print_file) {
4182 status = do_unlock(req->sconn->msg_ctx,
4184 (uint64_t)req->smbpid,
4185 (uint64_t)numtowrite,
4189 if (NT_STATUS_V(status)) {
4190 reply_nterror(req, status);
4195 reply_outbuf(req, 1, 0);
4197 SSVAL(req->outbuf,smb_vwv0,nwritten);
4199 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4200 fsp->fnum, (int)numtowrite, (int)nwritten));
4203 if (numtowrite && !fsp->print_file) {
4204 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4207 END_PROFILE(SMBwriteunlock);
4212 #define DBGC_CLASS DBGC_ALL
4214 /****************************************************************************
4216 ****************************************************************************/
4218 void reply_write(struct smb_request *req)
4220 connection_struct *conn = req->conn;
4222 ssize_t nwritten = -1;
4226 struct lock_struct lock;
4228 int saved_errno = 0;
4230 START_PROFILE(SMBwrite);
4233 END_PROFILE(SMBwrite);
4234 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4238 /* If it's an IPC, pass off the pipe handler. */
4240 reply_pipe_write(req);
4241 END_PROFILE(SMBwrite);
4245 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4247 if (!check_fsp(conn, req, fsp)) {
4248 END_PROFILE(SMBwrite);
4252 if (!CHECK_WRITE(fsp)) {
4253 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4254 END_PROFILE(SMBwrite);
4258 numtowrite = SVAL(req->vwv+1, 0);
4259 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4260 data = (const char *)req->buf + 3;
4262 if (!fsp->print_file) {
4263 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4264 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4267 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4268 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4269 END_PROFILE(SMBwrite);
4275 * X/Open SMB protocol says that if smb_vwv1 is
4276 * zero then the file size should be extended or
4277 * truncated to the size given in smb_vwv[2-3].
4280 if(numtowrite == 0) {
4282 * This is actually an allocate call, and set EOF. JRA.
4284 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4286 reply_nterror(req, NT_STATUS_DISK_FULL);
4289 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4291 reply_nterror(req, NT_STATUS_DISK_FULL);
4294 trigger_write_time_update_immediate(fsp);
4296 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4299 status = sync_file(conn, fsp, False);
4300 if (!NT_STATUS_IS_OK(status)) {
4301 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4302 fsp_str_dbg(fsp), nt_errstr(status)));
4303 reply_nterror(req, status);
4308 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4312 if((nwritten == 0) && (numtowrite != 0)) {
4313 reply_nterror(req, NT_STATUS_DISK_FULL);
4317 reply_outbuf(req, 1, 0);
4319 SSVAL(req->outbuf,smb_vwv0,nwritten);
4321 if (nwritten < (ssize_t)numtowrite) {
4322 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4323 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4326 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4329 if (!fsp->print_file) {
4330 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4333 END_PROFILE(SMBwrite);
4337 /****************************************************************************
4338 Ensure a buffer is a valid writeX for recvfile purposes.
4339 ****************************************************************************/
4341 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4342 (2*14) + /* word count (including bcc) */ \
4345 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4346 const uint8_t *inbuf)
4349 connection_struct *conn = NULL;
4350 unsigned int doff = 0;
4351 size_t len = smb_len_large(inbuf);
4353 if (is_encrypted_packet(inbuf)) {
4354 /* Can't do this on encrypted
4359 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4363 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4364 CVAL(inbuf,smb_wct) != 14) {
4365 DEBUG(10,("is_valid_writeX_buffer: chained or "
4366 "invalid word length.\n"));
4370 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4372 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4376 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4379 if (IS_PRINT(conn)) {
4380 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4383 doff = SVAL(inbuf,smb_vwv11);
4385 numtowrite = SVAL(inbuf,smb_vwv10);
4387 if (len > doff && len - doff > 0xFFFF) {
4388 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4391 if (numtowrite == 0) {
4392 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4396 /* Ensure the sizes match up. */
4397 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4398 /* no pad byte...old smbclient :-( */
4399 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4401 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4405 if (len - doff != numtowrite) {
4406 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4407 "len = %u, doff = %u, numtowrite = %u\n",
4410 (unsigned int)numtowrite ));
4414 DEBUG(10,("is_valid_writeX_buffer: true "
4415 "len = %u, doff = %u, numtowrite = %u\n",
4418 (unsigned int)numtowrite ));
4423 /****************************************************************************
4424 Reply to a write and X.
4425 ****************************************************************************/
4427 void reply_write_and_X(struct smb_request *req)
4429 connection_struct *conn = req->conn;
4431 struct lock_struct lock;
4436 unsigned int smb_doff;
4437 unsigned int smblen;
4440 int saved_errno = 0;
4442 START_PROFILE(SMBwriteX);
4444 if ((req->wct != 12) && (req->wct != 14)) {
4445 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4446 END_PROFILE(SMBwriteX);
4450 numtowrite = SVAL(req->vwv+10, 0);
4451 smb_doff = SVAL(req->vwv+11, 0);
4452 smblen = smb_len(req->inbuf);
4454 if (req->unread_bytes > 0xFFFF ||
4455 (smblen > smb_doff &&
4456 smblen - smb_doff > 0xFFFF)) {
4457 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4460 if (req->unread_bytes) {
4461 /* Can't do a recvfile write on IPC$ */
4463 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4464 END_PROFILE(SMBwriteX);
4467 if (numtowrite != req->unread_bytes) {
4468 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4469 END_PROFILE(SMBwriteX);
4473 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4474 smb_doff + numtowrite > smblen) {
4475 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4476 END_PROFILE(SMBwriteX);
4481 /* If it's an IPC, pass off the pipe handler. */
4483 if (req->unread_bytes) {
4484 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4485 END_PROFILE(SMBwriteX);
4488 reply_pipe_write_and_X(req);
4489 END_PROFILE(SMBwriteX);
4493 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4494 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4495 write_through = BITSETW(req->vwv+7,0);
4497 if (!check_fsp(conn, req, fsp)) {
4498 END_PROFILE(SMBwriteX);
4502 if (!CHECK_WRITE(fsp)) {
4503 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4504 END_PROFILE(SMBwriteX);
4508 data = smb_base(req->inbuf) + smb_doff;
4510 if(req->wct == 14) {
4511 #ifdef LARGE_SMB_OFF_T
4513 * This is a large offset (64 bit) write.
4515 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4517 #else /* !LARGE_SMB_OFF_T */
4520 * Ensure we haven't been sent a >32 bit offset.
4523 if(IVAL(req->vwv+12, 0) != 0) {
4524 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4525 "used and we don't support 64 bit offsets.\n",
4526 (unsigned int)IVAL(req->vwv+12, 0) ));
4527 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4528 END_PROFILE(SMBwriteX);
4532 #endif /* LARGE_SMB_OFF_T */
4535 /* X/Open SMB protocol says that, unlike SMBwrite
4536 if the length is zero then NO truncation is
4537 done, just a write of zero. To truncate a file,
4540 if(numtowrite == 0) {
4543 if (req->unread_bytes == 0) {
4544 status = schedule_aio_write_and_X(conn,
4551 if (NT_STATUS_IS_OK(status)) {
4552 /* write scheduled - we're done. */
4555 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4556 /* Real error - report to client. */
4557 reply_nterror(req, status);
4560 /* NT_STATUS_RETRY - fall through to sync write. */
4563 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4564 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4567 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4568 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4572 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4573 saved_errno = errno;
4575 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4579 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4583 if((nwritten == 0) && (numtowrite != 0)) {
4584 reply_nterror(req, NT_STATUS_DISK_FULL);
4588 reply_outbuf(req, 6, 0);
4589 SSVAL(req->outbuf,smb_vwv2,nwritten);
4590 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4592 if (nwritten < (ssize_t)numtowrite) {
4593 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4594 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4597 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4598 fsp->fnum, (int)numtowrite, (int)nwritten));
4600 status = sync_file(conn, fsp, write_through);
4601 if (!NT_STATUS_IS_OK(status)) {
4602 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4603 fsp_str_dbg(fsp), nt_errstr(status)));
4604 reply_nterror(req, status);
4608 END_PROFILE(SMBwriteX);
4613 END_PROFILE(SMBwriteX);
4617 /****************************************************************************
4619 ****************************************************************************/
4621 void reply_lseek(struct smb_request *req)
4623 connection_struct *conn = req->conn;
4629 START_PROFILE(SMBlseek);
4632 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4633 END_PROFILE(SMBlseek);
4637 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4639 if (!check_fsp(conn, req, fsp)) {
4643 flush_write_cache(fsp, SEEK_FLUSH);
4645 mode = SVAL(req->vwv+1, 0) & 3;
4646 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4647 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4656 res = fsp->fh->pos + startpos;
4667 if (umode == SEEK_END) {
4668 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4669 if(errno == EINVAL) {
4670 SMB_OFF_T current_pos = startpos;
4672 if(fsp_stat(fsp) == -1) {
4674 map_nt_error_from_unix(errno));
4675 END_PROFILE(SMBlseek);
4679 current_pos += fsp->fsp_name->st.st_ex_size;
4681 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4686 reply_nterror(req, map_nt_error_from_unix(errno));
4687 END_PROFILE(SMBlseek);
4694 reply_outbuf(req, 2, 0);
4695 SIVAL(req->outbuf,smb_vwv0,res);
4697 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4698 fsp->fnum, (double)startpos, (double)res, mode));
4700 END_PROFILE(SMBlseek);
4704 /****************************************************************************
4706 ****************************************************************************/
4708 void reply_flush(struct smb_request *req)
4710 connection_struct *conn = req->conn;
4714 START_PROFILE(SMBflush);
4717 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4721 fnum = SVAL(req->vwv+0, 0);
4722 fsp = file_fsp(req, fnum);
4724 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4729 file_sync_all(conn);
4731 NTSTATUS status = sync_file(conn, fsp, True);
4732 if (!NT_STATUS_IS_OK(status)) {
4733 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4734 fsp_str_dbg(fsp), nt_errstr(status)));
4735 reply_nterror(req, status);
4736 END_PROFILE(SMBflush);
4741 reply_outbuf(req, 0, 0);
4743 DEBUG(3,("flush\n"));
4744 END_PROFILE(SMBflush);
4748 /****************************************************************************
4750 conn POINTER CAN BE NULL HERE !
4751 ****************************************************************************/
4753 void reply_exit(struct smb_request *req)
4755 START_PROFILE(SMBexit);
4757 file_close_pid(req->smbpid, req->vuid);
4759 reply_outbuf(req, 0, 0);
4761 DEBUG(3,("exit\n"));
4763 END_PROFILE(SMBexit);
4767 /****************************************************************************
4768 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4769 ****************************************************************************/
4771 void reply_close(struct smb_request *req)
4773 connection_struct *conn = req->conn;
4774 NTSTATUS status = NT_STATUS_OK;
4775 files_struct *fsp = NULL;
4776 START_PROFILE(SMBclose);
4779 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4780 END_PROFILE(SMBclose);
4784 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4787 * We can only use check_fsp if we know it's not a directory.
4790 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4791 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4792 END_PROFILE(SMBclose);
4796 if(fsp->is_directory) {
4798 * Special case - close NT SMB directory handle.
4800 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4801 status = close_file(req, fsp, NORMAL_CLOSE);
4805 * Close ordinary file.
4808 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4809 fsp->fh->fd, fsp->fnum,
4810 conn->num_files_open));
4813 * Take care of any time sent in the close.
4816 t = srv_make_unix_date3(req->vwv+1);
4817 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4820 * close_file() returns the unix errno if an error
4821 * was detected on close - normally this is due to
4822 * a disk full error. If not then it was probably an I/O error.
4825 status = close_file(req, fsp, NORMAL_CLOSE);
4828 if (!NT_STATUS_IS_OK(status)) {
4829 reply_nterror(req, status);
4830 END_PROFILE(SMBclose);
4834 reply_outbuf(req, 0, 0);
4835 END_PROFILE(SMBclose);
4839 /****************************************************************************
4840 Reply to a writeclose (Core+ protocol).
4841 ****************************************************************************/
4843 void reply_writeclose(struct smb_request *req)
4845 connection_struct *conn = req->conn;
4847 ssize_t nwritten = -1;
4848 NTSTATUS close_status = NT_STATUS_OK;
4851 struct timespec mtime;
4853 struct lock_struct lock;
4855 START_PROFILE(SMBwriteclose);
4858 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4859 END_PROFILE(SMBwriteclose);
4863 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4865 if (!check_fsp(conn, req, fsp)) {
4866 END_PROFILE(SMBwriteclose);
4869 if (!CHECK_WRITE(fsp)) {
4870 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4871 END_PROFILE(SMBwriteclose);
4875 numtowrite = SVAL(req->vwv+1, 0);
4876 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4877 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4878 data = (const char *)req->buf + 1;
4880 if (!fsp->print_file) {
4881 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4882 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4885 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4886 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4887 END_PROFILE(SMBwriteclose);
4892 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4894 set_close_write_time(fsp, mtime);
4897 * More insanity. W2K only closes the file if writelen > 0.
4902 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4903 "file %s\n", fsp_str_dbg(fsp)));
4904 close_status = close_file(req, fsp, NORMAL_CLOSE);
4907 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4908 fsp->fnum, (int)numtowrite, (int)nwritten,
4909 conn->num_files_open));
4911 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4912 reply_nterror(req, NT_STATUS_DISK_FULL);
4916 if(!NT_STATUS_IS_OK(close_status)) {
4917 reply_nterror(req, close_status);
4921 reply_outbuf(req, 1, 0);
4923 SSVAL(req->outbuf,smb_vwv0,nwritten);
4926 if (numtowrite && !fsp->print_file) {
4927 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4930 END_PROFILE(SMBwriteclose);
4935 #define DBGC_CLASS DBGC_LOCKING
4937 /****************************************************************************
4939 ****************************************************************************/
4941 void reply_lock(struct smb_request *req)
4943 connection_struct *conn = req->conn;
4944 uint64_t count,offset;
4947 struct byte_range_lock *br_lck = NULL;
4949 START_PROFILE(SMBlock);
4952 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4953 END_PROFILE(SMBlock);
4957 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4959 if (!check_fsp(conn, req, fsp)) {
4960 END_PROFILE(SMBlock);
4964 count = (uint64_t)IVAL(req->vwv+1, 0);
4965 offset = (uint64_t)IVAL(req->vwv+3, 0);
4967 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4968 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4970 br_lck = do_lock(req->sconn->msg_ctx,
4972 (uint64_t)req->smbpid,
4977 False, /* Non-blocking lock. */
4982 TALLOC_FREE(br_lck);
4984 if (NT_STATUS_V(status)) {
4985 reply_nterror(req, status);
4986 END_PROFILE(SMBlock);
4990 reply_outbuf(req, 0, 0);
4992 END_PROFILE(SMBlock);
4996 /****************************************************************************
4998 ****************************************************************************/
5000 void reply_unlock(struct smb_request *req)
5002 connection_struct *conn = req->conn;
5003 uint64_t count,offset;
5007 START_PROFILE(SMBunlock);
5010 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5011 END_PROFILE(SMBunlock);
5015 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5017 if (!check_fsp(conn, req, fsp)) {
5018 END_PROFILE(SMBunlock);
5022 count = (uint64_t)IVAL(req->vwv+1, 0);
5023 offset = (uint64_t)IVAL(req->vwv+3, 0);
5025 status = do_unlock(req->sconn->msg_ctx,
5027 (uint64_t)req->smbpid,
5032 if (NT_STATUS_V(status)) {
5033 reply_nterror(req, status);
5034 END_PROFILE(SMBunlock);
5038 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5039 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
5041 reply_outbuf(req, 0, 0);
5043 END_PROFILE(SMBunlock);
5048 #define DBGC_CLASS DBGC_ALL
5050 /****************************************************************************
5052 conn POINTER CAN BE NULL HERE !
5053 ****************************************************************************/
5055 void reply_tdis(struct smb_request *req)
5057 connection_struct *conn = req->conn;
5058 START_PROFILE(SMBtdis);
5061 DEBUG(4,("Invalid connection in tdis\n"));
5062 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
5063 END_PROFILE(SMBtdis);
5069 close_cnum(conn,req->vuid);
5072 reply_outbuf(req, 0, 0);
5073 END_PROFILE(SMBtdis);
5077 /****************************************************************************
5079 conn POINTER CAN BE NULL HERE !
5080 ****************************************************************************/
5082 void reply_echo(struct smb_request *req)
5084 connection_struct *conn = req->conn;
5085 struct smb_perfcount_data local_pcd;
5086 struct smb_perfcount_data *cur_pcd;
5090 START_PROFILE(SMBecho);
5092 smb_init_perfcount_data(&local_pcd);
5095 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5096 END_PROFILE(SMBecho);
5100 smb_reverb = SVAL(req->vwv+0, 0);
5102 reply_outbuf(req, 1, req->buflen);
5104 /* copy any incoming data back out */
5105 if (req->buflen > 0) {
5106 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5109 if (smb_reverb > 100) {
5110 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5114 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5116 /* this makes sure we catch the request pcd */
5117 if (seq_num == smb_reverb) {
5118 cur_pcd = &req->pcd;
5120 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5121 cur_pcd = &local_pcd;
5124 SSVAL(req->outbuf,smb_vwv0,seq_num);
5126 show_msg((char *)req->outbuf);
5127 if (!srv_send_smb(req->sconn,
5128 (char *)req->outbuf,
5129 true, req->seqnum+1,
5130 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5132 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5135 DEBUG(3,("echo %d times\n", smb_reverb));
5137 TALLOC_FREE(req->outbuf);
5139 END_PROFILE(SMBecho);
5143 /****************************************************************************
5144 Reply to a printopen.
5145 ****************************************************************************/
5147 void reply_printopen(struct smb_request *req)
5149 connection_struct *conn = req->conn;
5153 START_PROFILE(SMBsplopen);
5156 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5157 END_PROFILE(SMBsplopen);
5161 if (!CAN_PRINT(conn)) {
5162 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5163 END_PROFILE(SMBsplopen);
5167 status = file_new(req, conn, &fsp);
5168 if(!NT_STATUS_IS_OK(status)) {
5169 reply_nterror(req, status);
5170 END_PROFILE(SMBsplopen);
5174 /* Open for exclusive use, write only. */
5175 status = print_spool_open(fsp, NULL, req->vuid);
5177 if (!NT_STATUS_IS_OK(status)) {
5178 file_free(req, fsp);
5179 reply_nterror(req, status);
5180 END_PROFILE(SMBsplopen);
5184 reply_outbuf(req, 1, 0);
5185 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5187 DEBUG(3,("openprint fd=%d fnum=%d\n",
5188 fsp->fh->fd, fsp->fnum));
5190 END_PROFILE(SMBsplopen);
5194 /****************************************************************************
5195 Reply to a printclose.
5196 ****************************************************************************/
5198 void reply_printclose(struct smb_request *req)
5200 connection_struct *conn = req->conn;
5204 START_PROFILE(SMBsplclose);
5207 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5208 END_PROFILE(SMBsplclose);
5212 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5214 if (!check_fsp(conn, req, fsp)) {
5215 END_PROFILE(SMBsplclose);
5219 if (!CAN_PRINT(conn)) {
5220 reply_force_doserror(req, ERRSRV, ERRerror);
5221 END_PROFILE(SMBsplclose);
5225 DEBUG(3,("printclose fd=%d fnum=%d\n",
5226 fsp->fh->fd,fsp->fnum));
5228 status = close_file(req, fsp, NORMAL_CLOSE);
5230 if(!NT_STATUS_IS_OK(status)) {
5231 reply_nterror(req, status);
5232 END_PROFILE(SMBsplclose);
5236 reply_outbuf(req, 0, 0);
5238 END_PROFILE(SMBsplclose);
5242 /****************************************************************************
5243 Reply to a printqueue.
5244 ****************************************************************************/
5246 void reply_printqueue(struct smb_request *req)
5248 connection_struct *conn = req->conn;
5252 START_PROFILE(SMBsplretq);
5255 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5256 END_PROFILE(SMBsplretq);
5260 max_count = SVAL(req->vwv+0, 0);
5261 start_index = SVAL(req->vwv+1, 0);
5263 /* we used to allow the client to get the cnum wrong, but that
5264 is really quite gross and only worked when there was only
5265 one printer - I think we should now only accept it if they
5266 get it right (tridge) */
5267 if (!CAN_PRINT(conn)) {
5268 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5269 END_PROFILE(SMBsplretq);
5273 reply_outbuf(req, 2, 3);
5274 SSVAL(req->outbuf,smb_vwv0,0);
5275 SSVAL(req->outbuf,smb_vwv1,0);
5276 SCVAL(smb_buf(req->outbuf),0,1);
5277 SSVAL(smb_buf(req->outbuf),1,0);
5279 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5280 start_index, max_count));
5283 TALLOC_CTX *mem_ctx = talloc_tos();
5286 const char *sharename = lp_servicename(SNUM(conn));
5287 struct rpc_pipe_client *cli = NULL;
5288 struct policy_handle handle;
5289 struct spoolss_DevmodeContainer devmode_ctr;
5290 union spoolss_JobInfo *info;
5292 uint32_t num_to_get;
5296 ZERO_STRUCT(handle);
5298 status = rpc_pipe_open_interface(conn,
5299 &ndr_table_spoolss.syntax_id,
5301 &conn->sconn->client_id,
5302 conn->sconn->msg_ctx,
5304 if (!NT_STATUS_IS_OK(status)) {
5305 DEBUG(0, ("reply_printqueue: "
5306 "could not connect to spoolss: %s\n",
5307 nt_errstr(status)));
5308 reply_nterror(req, status);
5312 ZERO_STRUCT(devmode_ctr);
5314 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
5317 SEC_FLAG_MAXIMUM_ALLOWED,
5320 if (!NT_STATUS_IS_OK(status)) {
5321 reply_nterror(req, status);
5324 if (!W_ERROR_IS_OK(werr)) {
5325 reply_nterror(req, werror_to_ntstatus(werr));
5329 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5337 if (!W_ERROR_IS_OK(werr)) {
5338 reply_nterror(req, werror_to_ntstatus(werr));
5342 if (max_count > 0) {
5343 first = start_index;
5345 first = start_index + max_count + 1;
5348 if (first >= count) {
5351 num_to_get = first + MIN(ABS(max_count), count - first);
5354 for (i = first; i < num_to_get; i++) {
5357 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5359 uint16_t qrapjobid = pjobid_to_rap(sharename,
5360 info[i].info2.job_id);
5362 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5368 srv_put_dos_date2(p, 0, qtime);
5369 SCVAL(p, 4, qstatus);
5370 SSVAL(p, 5, qrapjobid);
5371 SIVAL(p, 7, info[i].info2.size);
5373 srvstr_push(blob, req->flags2, p+12,
5374 info[i].info2.notify_name, 16, STR_ASCII);
5376 if (message_push_blob(
5379 blob, sizeof(blob))) == -1) {
5380 reply_nterror(req, NT_STATUS_NO_MEMORY);
5386 SSVAL(req->outbuf,smb_vwv0,count);
5387 SSVAL(req->outbuf,smb_vwv1,
5388 (max_count>0?first+count:first-1));
5389 SCVAL(smb_buf(req->outbuf),0,1);
5390 SSVAL(smb_buf(req->outbuf),1,28*count);
5394 DEBUG(3, ("%u entries returned in queue\n",
5398 if (cli && is_valid_policy_hnd(&handle)) {
5399 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
5404 END_PROFILE(SMBsplretq);
5408 /****************************************************************************
5409 Reply to a printwrite.
5410 ****************************************************************************/
5412 void reply_printwrite(struct smb_request *req)
5414 connection_struct *conn = req->conn;
5419 START_PROFILE(SMBsplwr);
5422 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5423 END_PROFILE(SMBsplwr);
5427 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5429 if (!check_fsp(conn, req, fsp)) {
5430 END_PROFILE(SMBsplwr);
5434 if (!fsp->print_file) {
5435 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5436 END_PROFILE(SMBsplwr);
5440 if (!CHECK_WRITE(fsp)) {
5441 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5442 END_PROFILE(SMBsplwr);
5446 numtowrite = SVAL(req->buf, 1);
5448 if (req->buflen < numtowrite + 3) {
5449 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5450 END_PROFILE(SMBsplwr);
5454 data = (const char *)req->buf + 3;
5456 if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5457 reply_nterror(req, map_nt_error_from_unix(errno));
5458 END_PROFILE(SMBsplwr);
5462 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5464 END_PROFILE(SMBsplwr);
5468 /****************************************************************************
5470 ****************************************************************************/
5472 void reply_mkdir(struct smb_request *req)
5474 connection_struct *conn = req->conn;
5475 struct smb_filename *smb_dname = NULL;
5476 char *directory = NULL;
5478 TALLOC_CTX *ctx = talloc_tos();
5480 START_PROFILE(SMBmkdir);
5482 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5483 STR_TERMINATE, &status);
5484 if (!NT_STATUS_IS_OK(status)) {
5485 reply_nterror(req, status);
5489 status = filename_convert(ctx, conn,
5490 req->flags2 & FLAGS2_DFS_PATHNAMES,
5495 if (!NT_STATUS_IS_OK(status)) {
5496 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5497 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5498 ERRSRV, ERRbadpath);
5501 reply_nterror(req, status);
5505 status = create_directory(conn, req, smb_dname);
5507 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5509 if (!NT_STATUS_IS_OK(status)) {
5511 if (!use_nt_status()
5512 && NT_STATUS_EQUAL(status,
5513 NT_STATUS_OBJECT_NAME_COLLISION)) {
5515 * Yes, in the DOS error code case we get a
5516 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5517 * samba4 torture test.
5519 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5522 reply_nterror(req, status);
5526 reply_outbuf(req, 0, 0);
5528 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5530 TALLOC_FREE(smb_dname);
5531 END_PROFILE(SMBmkdir);
5535 /****************************************************************************
5537 ****************************************************************************/
5539 void reply_rmdir(struct smb_request *req)
5541 connection_struct *conn = req->conn;
5542 struct smb_filename *smb_dname = NULL;
5543 char *directory = NULL;
5545 TALLOC_CTX *ctx = talloc_tos();
5546 files_struct *fsp = NULL;
5548 struct smbd_server_connection *sconn = req->sconn;
5550 START_PROFILE(SMBrmdir);
5552 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5553 STR_TERMINATE, &status);
5554 if (!NT_STATUS_IS_OK(status)) {
5555 reply_nterror(req, status);
5559 status = filename_convert(ctx, conn,
5560 req->flags2 & FLAGS2_DFS_PATHNAMES,
5565 if (!NT_STATUS_IS_OK(status)) {
5566 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5567 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5568 ERRSRV, ERRbadpath);
5571 reply_nterror(req, status);
5575 if (is_ntfs_stream_smb_fname(smb_dname)) {
5576 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5580 status = SMB_VFS_CREATE_FILE(
5583 0, /* root_dir_fid */
5584 smb_dname, /* fname */
5585 DELETE_ACCESS, /* access_mask */
5586 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5588 FILE_OPEN, /* create_disposition*/
5589 FILE_DIRECTORY_FILE, /* create_options */
5590 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5591 0, /* oplock_request */
5592 0, /* allocation_size */
5593 0, /* private_flags */
5599 if (!NT_STATUS_IS_OK(status)) {
5600 if (open_was_deferred(req->mid)) {
5601 /* We have re-scheduled this call. */
5604 reply_nterror(req, status);
5608 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5609 if (!NT_STATUS_IS_OK(status)) {
5610 close_file(req, fsp, ERROR_CLOSE);
5611 reply_nterror(req, status);
5615 if (!set_delete_on_close(fsp, true, &conn->server_info->utok)) {
5616 close_file(req, fsp, ERROR_CLOSE);
5617 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5621 status = close_file(req, fsp, NORMAL_CLOSE);
5622 if (!NT_STATUS_IS_OK(status)) {
5623 reply_nterror(req, status);
5625 reply_outbuf(req, 0, 0);
5628 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5630 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5632 TALLOC_FREE(smb_dname);
5633 END_PROFILE(SMBrmdir);
5637 /*******************************************************************
5638 Resolve wildcards in a filename rename.
5639 ********************************************************************/
5641 static bool resolve_wildcards(TALLOC_CTX *ctx,
5646 char *name2_copy = NULL;
5651 char *p,*p2, *pname1, *pname2;
5653 name2_copy = talloc_strdup(ctx, name2);
5658 pname1 = strrchr_m(name1,'/');
5659 pname2 = strrchr_m(name2_copy,'/');
5661 if (!pname1 || !pname2) {
5665 /* Truncate the copy of name2 at the last '/' */
5668 /* Now go past the '/' */
5672 root1 = talloc_strdup(ctx, pname1);
5673 root2 = talloc_strdup(ctx, pname2);
5675 if (!root1 || !root2) {
5679 p = strrchr_m(root1,'.');
5682 ext1 = talloc_strdup(ctx, p+1);
5684 ext1 = talloc_strdup(ctx, "");
5686 p = strrchr_m(root2,'.');
5689 ext2 = talloc_strdup(ctx, p+1);
5691 ext2 = talloc_strdup(ctx, "");
5694 if (!ext1 || !ext2) {
5702 /* Hmmm. Should this be mb-aware ? */
5705 } else if (*p2 == '*') {
5707 root2 = talloc_asprintf(ctx, "%s%s",
5726 /* Hmmm. Should this be mb-aware ? */
5729 } else if (*p2 == '*') {
5731 ext2 = talloc_asprintf(ctx, "%s%s",
5747 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5752 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5764 /****************************************************************************
5765 Ensure open files have their names updated. Updated to notify other smbd's
5767 ****************************************************************************/
5769 static void rename_open_files(connection_struct *conn,
5770 struct share_mode_lock *lck,
5771 const struct smb_filename *smb_fname_dst)
5774 bool did_rename = False;
5777 for(fsp = file_find_di_first(lck->id); fsp;
5778 fsp = file_find_di_next(fsp)) {
5779 /* fsp_name is a relative path under the fsp. To change this for other
5780 sharepaths we need to manipulate relative paths. */
5781 /* TODO - create the absolute path and manipulate the newname
5782 relative to the sharepath. */
5783 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5786 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5787 "(file_id %s) from %s -> %s\n", fsp->fnum,
5788 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5789 smb_fname_str_dbg(smb_fname_dst)));
5791 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5792 if (NT_STATUS_IS_OK(status)) {
5798 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5799 "for %s\n", file_id_string_tos(&lck->id),
5800 smb_fname_str_dbg(smb_fname_dst)));
5803 /* Send messages to all smbd's (not ourself) that the name has changed. */
5804 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5809 /****************************************************************************
5810 We need to check if the source path is a parent directory of the destination
5811 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5812 refuse the rename with a sharing violation. Under UNIX the above call can
5813 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5814 probably need to check that the client is a Windows one before disallowing
5815 this as a UNIX client (one with UNIX extensions) can know the source is a
5816 symlink and make this decision intelligently. Found by an excellent bug
5817 report from <AndyLiebman@aol.com>.
5818 ****************************************************************************/
5820 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5821 const struct smb_filename *smb_fname_dst)
5823 const char *psrc = smb_fname_src->base_name;
5824 const char *pdst = smb_fname_dst->base_name;
5827 if (psrc[0] == '.' && psrc[1] == '/') {
5830 if (pdst[0] == '.' && pdst[1] == '/') {
5833 if ((slen = strlen(psrc)) > strlen(pdst)) {
5836 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5840 * Do the notify calls from a rename
5843 static void notify_rename(connection_struct *conn, bool is_dir,
5844 const struct smb_filename *smb_fname_src,
5845 const struct smb_filename *smb_fname_dst)
5847 char *parent_dir_src = NULL;
5848 char *parent_dir_dst = NULL;
5851 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5852 : FILE_NOTIFY_CHANGE_FILE_NAME;
5854 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5855 &parent_dir_src, NULL) ||
5856 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5857 &parent_dir_dst, NULL)) {
5861 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5862 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5863 smb_fname_src->base_name);
5864 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5865 smb_fname_dst->base_name);
5868 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5869 smb_fname_src->base_name);
5870 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5871 smb_fname_dst->base_name);
5874 /* this is a strange one. w2k3 gives an additional event for
5875 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5876 files, but not directories */
5878 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5879 FILE_NOTIFY_CHANGE_ATTRIBUTES
5880 |FILE_NOTIFY_CHANGE_CREATION,
5881 smb_fname_dst->base_name);
5884 TALLOC_FREE(parent_dir_src);
5885 TALLOC_FREE(parent_dir_dst);
5888 /****************************************************************************
5889 Rename an open file - given an fsp.
5890 ****************************************************************************/
5892 NTSTATUS rename_internals_fsp(connection_struct *conn,
5894 const struct smb_filename *smb_fname_dst_in,
5896 bool replace_if_exists)
5898 TALLOC_CTX *ctx = talloc_tos();
5899 struct smb_filename *smb_fname_dst = NULL;
5900 NTSTATUS status = NT_STATUS_OK;
5901 struct share_mode_lock *lck = NULL;
5902 bool dst_exists, old_is_stream, new_is_stream;
5904 status = check_name(conn, smb_fname_dst_in->base_name);
5905 if (!NT_STATUS_IS_OK(status)) {
5909 /* Make a copy of the dst smb_fname structs */
5911 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5912 if (!NT_STATUS_IS_OK(status)) {
5916 /* Ensure the dst smb_fname contains a '/' */
5917 if(strrchr_m(smb_fname_dst->base_name,'/') == 0) {
5919 tmp = talloc_asprintf(smb_fname_dst, "./%s",
5920 smb_fname_dst->base_name);
5922 status = NT_STATUS_NO_MEMORY;
5925 TALLOC_FREE(smb_fname_dst->base_name);
5926 smb_fname_dst->base_name = tmp;
5930 * Check for special case with case preserving and not
5931 * case sensitive. If the old last component differs from the original
5932 * last component only by case, then we should allow
5933 * the rename (user is trying to change the case of the
5936 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5937 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5938 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
5940 char *fname_dst_lcomp_base_mod = NULL;
5941 struct smb_filename *smb_fname_orig_lcomp = NULL;
5944 * Get the last component of the destination name. Note that
5945 * we guarantee that destination name contains a '/' character
5948 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5949 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5950 if (!fname_dst_lcomp_base_mod) {
5951 status = NT_STATUS_NO_MEMORY;
5956 * Create an smb_filename struct using the original last
5957 * component of the destination.
5959 status = create_synthetic_smb_fname_split(ctx,
5960 smb_fname_dst->original_lcomp, NULL,
5961 &smb_fname_orig_lcomp);
5962 if (!NT_STATUS_IS_OK(status)) {
5963 TALLOC_FREE(fname_dst_lcomp_base_mod);
5967 /* If the base names only differ by case, use original. */
5968 if(!strcsequal(fname_dst_lcomp_base_mod,
5969 smb_fname_orig_lcomp->base_name)) {
5972 * Replace the modified last component with the
5975 *last_slash = '\0'; /* Truncate at the '/' */
5976 tmp = talloc_asprintf(smb_fname_dst,
5978 smb_fname_dst->base_name,
5979 smb_fname_orig_lcomp->base_name);
5981 status = NT_STATUS_NO_MEMORY;
5982 TALLOC_FREE(fname_dst_lcomp_base_mod);
5983 TALLOC_FREE(smb_fname_orig_lcomp);
5986 TALLOC_FREE(smb_fname_dst->base_name);
5987 smb_fname_dst->base_name = tmp;
5990 /* If the stream_names only differ by case, use original. */
5991 if(!strcsequal(smb_fname_dst->stream_name,
5992 smb_fname_orig_lcomp->stream_name)) {
5994 /* Use the original stream. */
5995 tmp = talloc_strdup(smb_fname_dst,
5996 smb_fname_orig_lcomp->stream_name);
5998 status = NT_STATUS_NO_MEMORY;
5999 TALLOC_FREE(fname_dst_lcomp_base_mod);
6000 TALLOC_FREE(smb_fname_orig_lcomp);
6003 TALLOC_FREE(smb_fname_dst->stream_name);
6004 smb_fname_dst->stream_name = tmp;
6006 TALLOC_FREE(fname_dst_lcomp_base_mod);
6007 TALLOC_FREE(smb_fname_orig_lcomp);
6011 * If the src and dest names are identical - including case,
6012 * don't do the rename, just return success.
6015 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6016 strcsequal(fsp->fsp_name->stream_name,
6017 smb_fname_dst->stream_name)) {
6018 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6019 "- returning success\n",
6020 smb_fname_str_dbg(smb_fname_dst)));
6021 status = NT_STATUS_OK;
6025 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6026 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6028 /* Return the correct error code if both names aren't streams. */
6029 if (!old_is_stream && new_is_stream) {
6030 status = NT_STATUS_OBJECT_NAME_INVALID;
6034 if (old_is_stream && !new_is_stream) {
6035 status = NT_STATUS_INVALID_PARAMETER;
6039 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6041 if(!replace_if_exists && dst_exists) {
6042 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6043 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6044 smb_fname_str_dbg(smb_fname_dst)));
6045 status = NT_STATUS_OBJECT_NAME_COLLISION;
6050 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6051 &smb_fname_dst->st);
6052 files_struct *dst_fsp = file_find_di_first(fileid);
6053 /* The file can be open when renaming a stream */
6054 if (dst_fsp && !new_is_stream) {
6055 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6056 status = NT_STATUS_ACCESS_DENIED;
6061 /* Ensure we have a valid stat struct for the source. */
6062 status = vfs_stat_fsp(fsp);
6063 if (!NT_STATUS_IS_OK(status)) {
6067 status = can_rename(conn, fsp, attrs);
6069 if (!NT_STATUS_IS_OK(status)) {
6070 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6071 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6072 smb_fname_str_dbg(smb_fname_dst)));
6073 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6074 status = NT_STATUS_ACCESS_DENIED;
6078 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6079 status = NT_STATUS_ACCESS_DENIED;
6082 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6086 * We have the file open ourselves, so not being able to get the
6087 * corresponding share mode lock is a fatal error.
6090 SMB_ASSERT(lck != NULL);
6092 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6093 uint32 create_options = fsp->fh->private_options;
6095 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6096 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6097 smb_fname_str_dbg(smb_fname_dst)));
6099 if (!lp_unix_extensions() &&
6100 (lp_map_archive(SNUM(conn)) ||
6101 lp_store_dos_attributes(SNUM(conn)))) {
6102 /* We must set the archive bit on the newly
6104 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6105 uint32_t old_dosmode = dos_mode(conn,
6107 file_set_dosmode(conn,
6109 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6115 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6118 rename_open_files(conn, lck, smb_fname_dst);
6121 * A rename acts as a new file create w.r.t. allowing an initial delete
6122 * on close, probably because in Windows there is a new handle to the
6123 * new file. If initial delete on close was requested but not
6124 * originally set, we need to set it here. This is probably not 100% correct,
6125 * but will work for the CIFSFS client which in non-posix mode
6126 * depends on these semantics. JRA.
6129 if (create_options & FILE_DELETE_ON_CLOSE) {
6130 status = can_set_delete_on_close(fsp, 0);
6132 if (NT_STATUS_IS_OK(status)) {
6133 /* Note that here we set the *inital* delete on close flag,
6134 * not the regular one. The magic gets handled in close. */
6135 fsp->initial_delete_on_close = True;
6139 status = NT_STATUS_OK;
6145 if (errno == ENOTDIR || errno == EISDIR) {
6146 status = NT_STATUS_OBJECT_NAME_COLLISION;
6148 status = map_nt_error_from_unix(errno);
6151 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6152 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6153 smb_fname_str_dbg(smb_fname_dst)));
6156 TALLOC_FREE(smb_fname_dst);
6161 /****************************************************************************
6162 The guts of the rename command, split out so it may be called by the NT SMB
6164 ****************************************************************************/
6166 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6167 connection_struct *conn,
6168 struct smb_request *req,
6169 struct smb_filename *smb_fname_src,
6170 struct smb_filename *smb_fname_dst,
6172 bool replace_if_exists,
6175 uint32_t access_mask)
6177 char *fname_src_dir = NULL;
6178 char *fname_src_mask = NULL;
6180 NTSTATUS status = NT_STATUS_OK;
6181 struct smb_Dir *dir_hnd = NULL;
6182 const char *dname = NULL;
6183 char *talloced = NULL;
6185 int create_options = 0;
6186 bool posix_pathnames = lp_posix_pathnames();
6189 * Split the old name into directory and last component
6190 * strings. Note that unix_convert may have stripped off a
6191 * leading ./ from both name and newname if the rename is
6192 * at the root of the share. We need to make sure either both
6193 * name and newname contain a / character or neither of them do
6194 * as this is checked in resolve_wildcards().
6197 /* Split up the directory from the filename/mask. */
6198 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6199 &fname_src_dir, &fname_src_mask);
6200 if (!NT_STATUS_IS_OK(status)) {
6201 status = NT_STATUS_NO_MEMORY;
6206 * We should only check the mangled cache
6207 * here if unix_convert failed. This means
6208 * that the path in 'mask' doesn't exist
6209 * on the file system and so we need to look
6210 * for a possible mangle. This patch from
6211 * Tine Smukavec <valentin.smukavec@hermes.si>.
6214 if (!VALID_STAT(smb_fname_src->st) &&
6215 mangle_is_mangled(fname_src_mask, conn->params)) {
6216 char *new_mask = NULL;
6217 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6220 TALLOC_FREE(fname_src_mask);
6221 fname_src_mask = new_mask;
6225 if (!src_has_wild) {
6229 * Only one file needs to be renamed. Append the mask back
6230 * onto the directory.
6232 TALLOC_FREE(smb_fname_src->base_name);
6233 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6237 if (!smb_fname_src->base_name) {
6238 status = NT_STATUS_NO_MEMORY;
6242 /* Ensure dst fname contains a '/' also */
6243 if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
6245 tmp = talloc_asprintf(smb_fname_dst, "./%s",
6246 smb_fname_dst->base_name);
6248 status = NT_STATUS_NO_MEMORY;
6251 TALLOC_FREE(smb_fname_dst->base_name);
6252 smb_fname_dst->base_name = tmp;
6255 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6256 "case_preserve = %d, short case preserve = %d, "
6257 "directory = %s, newname = %s, "
6258 "last_component_dest = %s\n",
6259 conn->case_sensitive, conn->case_preserve,
6260 conn->short_case_preserve,
6261 smb_fname_str_dbg(smb_fname_src),
6262 smb_fname_str_dbg(smb_fname_dst),
6263 smb_fname_dst->original_lcomp));
6265 /* The dest name still may have wildcards. */
6266 if (dest_has_wild) {
6267 char *fname_dst_mod = NULL;
6268 if (!resolve_wildcards(smb_fname_dst,
6269 smb_fname_src->base_name,
6270 smb_fname_dst->base_name,
6272 DEBUG(6, ("rename_internals: resolve_wildcards "
6274 smb_fname_src->base_name,
6275 smb_fname_dst->base_name));
6276 status = NT_STATUS_NO_MEMORY;
6279 TALLOC_FREE(smb_fname_dst->base_name);
6280 smb_fname_dst->base_name = fname_dst_mod;
6283 ZERO_STRUCT(smb_fname_src->st);
6284 if (posix_pathnames) {
6285 SMB_VFS_LSTAT(conn, smb_fname_src);
6287 SMB_VFS_STAT(conn, smb_fname_src);
6290 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6291 create_options |= FILE_DIRECTORY_FILE;
6294 status = SMB_VFS_CREATE_FILE(
6297 0, /* root_dir_fid */
6298 smb_fname_src, /* fname */
6299 access_mask, /* access_mask */
6300 (FILE_SHARE_READ | /* share_access */
6302 FILE_OPEN, /* create_disposition*/
6303 create_options, /* create_options */
6304 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6305 0, /* oplock_request */
6306 0, /* allocation_size */
6307 0, /* private_flags */
6313 if (!NT_STATUS_IS_OK(status)) {
6314 DEBUG(3, ("Could not open rename source %s: %s\n",
6315 smb_fname_str_dbg(smb_fname_src),
6316 nt_errstr(status)));
6320 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6321 attrs, replace_if_exists);
6323 close_file(req, fsp, NORMAL_CLOSE);
6325 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6326 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6327 smb_fname_str_dbg(smb_fname_dst)));
6333 * Wildcards - process each file that matches.
6335 if (strequal(fname_src_mask, "????????.???")) {
6336 TALLOC_FREE(fname_src_mask);
6337 fname_src_mask = talloc_strdup(ctx, "*");
6338 if (!fname_src_mask) {
6339 status = NT_STATUS_NO_MEMORY;
6344 status = check_name(conn, fname_src_dir);
6345 if (!NT_STATUS_IS_OK(status)) {
6349 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6351 if (dir_hnd == NULL) {
6352 status = map_nt_error_from_unix(errno);
6356 status = NT_STATUS_NO_SUCH_FILE;
6358 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6359 * - gentest fix. JRA
6362 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6364 files_struct *fsp = NULL;
6365 char *destname = NULL;
6366 bool sysdir_entry = False;
6368 /* Quick check for "." and ".." */
6369 if (ISDOT(dname) || ISDOTDOT(dname)) {
6371 sysdir_entry = True;
6373 TALLOC_FREE(talloced);
6378 if (!is_visible_file(conn, fname_src_dir, dname,
6379 &smb_fname_src->st, false)) {
6380 TALLOC_FREE(talloced);
6384 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6385 TALLOC_FREE(talloced);
6390 status = NT_STATUS_OBJECT_NAME_INVALID;
6394 TALLOC_FREE(smb_fname_src->base_name);
6395 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6399 if (!smb_fname_src->base_name) {
6400 status = NT_STATUS_NO_MEMORY;
6404 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6405 smb_fname_dst->base_name,
6407 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6408 smb_fname_src->base_name, destname));
6409 TALLOC_FREE(talloced);
6413 status = NT_STATUS_NO_MEMORY;
6417 TALLOC_FREE(smb_fname_dst->base_name);
6418 smb_fname_dst->base_name = destname;
6420 ZERO_STRUCT(smb_fname_src->st);
6421 if (posix_pathnames) {
6422 SMB_VFS_LSTAT(conn, smb_fname_src);
6424 SMB_VFS_STAT(conn, smb_fname_src);
6429 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6430 create_options |= FILE_DIRECTORY_FILE;
6433 status = SMB_VFS_CREATE_FILE(
6436 0, /* root_dir_fid */
6437 smb_fname_src, /* fname */
6438 access_mask, /* access_mask */
6439 (FILE_SHARE_READ | /* share_access */
6441 FILE_OPEN, /* create_disposition*/
6442 create_options, /* create_options */
6443 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6444 0, /* oplock_request */
6445 0, /* allocation_size */
6446 0, /* private_flags */
6452 if (!NT_STATUS_IS_OK(status)) {
6453 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6454 "returned %s rename %s -> %s\n",
6456 smb_fname_str_dbg(smb_fname_src),
6457 smb_fname_str_dbg(smb_fname_dst)));
6461 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6463 if (!smb_fname_dst->original_lcomp) {
6464 status = NT_STATUS_NO_MEMORY;
6468 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6469 attrs, replace_if_exists);
6471 close_file(req, fsp, NORMAL_CLOSE);
6473 if (!NT_STATUS_IS_OK(status)) {
6474 DEBUG(3, ("rename_internals_fsp returned %s for "
6475 "rename %s -> %s\n", nt_errstr(status),
6476 smb_fname_str_dbg(smb_fname_src),
6477 smb_fname_str_dbg(smb_fname_dst)));
6483 DEBUG(3,("rename_internals: doing rename on %s -> "
6484 "%s\n", smb_fname_str_dbg(smb_fname_src),
6485 smb_fname_str_dbg(smb_fname_src)));
6486 TALLOC_FREE(talloced);
6488 TALLOC_FREE(dir_hnd);
6490 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6491 status = map_nt_error_from_unix(errno);
6495 TALLOC_FREE(talloced);
6496 TALLOC_FREE(fname_src_dir);
6497 TALLOC_FREE(fname_src_mask);
6501 /****************************************************************************
6503 ****************************************************************************/
6505 void reply_mv(struct smb_request *req)
6507 connection_struct *conn = req->conn;
6509 char *newname = NULL;
6513 bool src_has_wcard = False;
6514 bool dest_has_wcard = False;
6515 TALLOC_CTX *ctx = talloc_tos();
6516 struct smb_filename *smb_fname_src = NULL;
6517 struct smb_filename *smb_fname_dst = NULL;
6519 START_PROFILE(SMBmv);
6522 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6526 attrs = SVAL(req->vwv+0, 0);
6528 p = (const char *)req->buf + 1;
6529 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6530 &status, &src_has_wcard);
6531 if (!NT_STATUS_IS_OK(status)) {
6532 reply_nterror(req, status);
6536 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6537 &status, &dest_has_wcard);
6538 if (!NT_STATUS_IS_OK(status)) {
6539 reply_nterror(req, status);
6543 status = filename_convert(ctx,
6545 req->flags2 & FLAGS2_DFS_PATHNAMES,
6547 UCF_COND_ALLOW_WCARD_LCOMP,
6551 if (!NT_STATUS_IS_OK(status)) {
6552 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6553 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6554 ERRSRV, ERRbadpath);
6557 reply_nterror(req, status);
6561 status = filename_convert(ctx,
6563 req->flags2 & FLAGS2_DFS_PATHNAMES,
6565 UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6569 if (!NT_STATUS_IS_OK(status)) {
6570 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6571 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6572 ERRSRV, ERRbadpath);
6575 reply_nterror(req, status);
6579 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6580 smb_fname_str_dbg(smb_fname_dst)));
6582 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6583 attrs, False, src_has_wcard, dest_has_wcard,
6585 if (!NT_STATUS_IS_OK(status)) {
6586 if (open_was_deferred(req->mid)) {
6587 /* We have re-scheduled this call. */
6590 reply_nterror(req, status);
6594 reply_outbuf(req, 0, 0);
6596 TALLOC_FREE(smb_fname_src);
6597 TALLOC_FREE(smb_fname_dst);
6602 /*******************************************************************
6603 Copy a file as part of a reply_copy.
6604 ******************************************************************/
6607 * TODO: check error codes on all callers
6610 NTSTATUS copy_file(TALLOC_CTX *ctx,
6611 connection_struct *conn,
6612 struct smb_filename *smb_fname_src,
6613 struct smb_filename *smb_fname_dst,
6616 bool target_is_directory)
6618 struct smb_filename *smb_fname_dst_tmp = NULL;
6620 files_struct *fsp1,*fsp2;
6622 uint32 new_create_disposition;
6626 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6627 if (!NT_STATUS_IS_OK(status)) {
6632 * If the target is a directory, extract the last component from the
6633 * src filename and append it to the dst filename
6635 if (target_is_directory) {
6638 /* dest/target can't be a stream if it's a directory. */
6639 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6641 p = strrchr_m(smb_fname_src->base_name,'/');
6645 p = smb_fname_src->base_name;
6647 smb_fname_dst_tmp->base_name =
6648 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6650 if (!smb_fname_dst_tmp->base_name) {
6651 status = NT_STATUS_NO_MEMORY;
6656 status = vfs_file_exist(conn, smb_fname_src);
6657 if (!NT_STATUS_IS_OK(status)) {
6661 if (!target_is_directory && count) {
6662 new_create_disposition = FILE_OPEN;
6664 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
6666 &new_create_disposition,
6669 status = NT_STATUS_INVALID_PARAMETER;
6674 /* Open the src file for reading. */
6675 status = SMB_VFS_CREATE_FILE(
6678 0, /* root_dir_fid */
6679 smb_fname_src, /* fname */
6680 FILE_GENERIC_READ, /* access_mask */
6681 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6682 FILE_OPEN, /* create_disposition*/
6683 0, /* create_options */
6684 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6685 INTERNAL_OPEN_ONLY, /* oplock_request */
6686 0, /* allocation_size */
6687 0, /* private_flags */
6693 if (!NT_STATUS_IS_OK(status)) {
6697 dosattrs = dos_mode(conn, smb_fname_src);
6699 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6700 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6703 /* Open the dst file for writing. */
6704 status = SMB_VFS_CREATE_FILE(
6707 0, /* root_dir_fid */
6708 smb_fname_dst, /* fname */
6709 FILE_GENERIC_WRITE, /* access_mask */
6710 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6711 new_create_disposition, /* create_disposition*/
6712 0, /* create_options */
6713 dosattrs, /* file_attributes */
6714 INTERNAL_OPEN_ONLY, /* oplock_request */
6715 0, /* allocation_size */
6716 0, /* private_flags */
6722 if (!NT_STATUS_IS_OK(status)) {
6723 close_file(NULL, fsp1, ERROR_CLOSE);
6727 if ((ofun&3) == 1) {
6728 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6729 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6731 * Stop the copy from occurring.
6734 smb_fname_src->st.st_ex_size = 0;
6738 /* Do the actual copy. */
6739 if (smb_fname_src->st.st_ex_size) {
6740 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6743 close_file(NULL, fsp1, NORMAL_CLOSE);
6745 /* Ensure the modtime is set correctly on the destination file. */
6746 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6749 * As we are opening fsp1 read-only we only expect
6750 * an error on close on fsp2 if we are out of space.
6751 * Thus we don't look at the error return from the
6754 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6756 if (!NT_STATUS_IS_OK(status)) {
6760 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6761 status = NT_STATUS_DISK_FULL;
6765 status = NT_STATUS_OK;
6768 TALLOC_FREE(smb_fname_dst_tmp);
6772 /****************************************************************************
6773 Reply to a file copy.
6774 ****************************************************************************/
6776 void reply_copy(struct smb_request *req)
6778 connection_struct *conn = req->conn;
6779 struct smb_filename *smb_fname_src = NULL;
6780 struct smb_filename *smb_fname_dst = NULL;
6781 char *fname_src = NULL;
6782 char *fname_dst = NULL;
6783 char *fname_src_mask = NULL;
6784 char *fname_src_dir = NULL;
6787 int error = ERRnoaccess;
6791 bool target_is_directory=False;
6792 bool source_has_wild = False;
6793 bool dest_has_wild = False;
6795 TALLOC_CTX *ctx = talloc_tos();
6797 START_PROFILE(SMBcopy);
6800 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6804 tid2 = SVAL(req->vwv+0, 0);
6805 ofun = SVAL(req->vwv+1, 0);
6806 flags = SVAL(req->vwv+2, 0);
6808 p = (const char *)req->buf;
6809 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6810 &status, &source_has_wild);
6811 if (!NT_STATUS_IS_OK(status)) {
6812 reply_nterror(req, status);
6815 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6816 &status, &dest_has_wild);
6817 if (!NT_STATUS_IS_OK(status)) {
6818 reply_nterror(req, status);
6822 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6824 if (tid2 != conn->cnum) {
6825 /* can't currently handle inter share copies XXXX */
6826 DEBUG(3,("Rejecting inter-share copy\n"));
6827 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6831 status = filename_convert(ctx, conn,
6832 req->flags2 & FLAGS2_DFS_PATHNAMES,
6834 UCF_COND_ALLOW_WCARD_LCOMP,
6837 if (!NT_STATUS_IS_OK(status)) {
6838 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6839 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6840 ERRSRV, ERRbadpath);
6843 reply_nterror(req, status);
6847 status = filename_convert(ctx, conn,
6848 req->flags2 & FLAGS2_DFS_PATHNAMES,
6850 UCF_COND_ALLOW_WCARD_LCOMP,
6853 if (!NT_STATUS_IS_OK(status)) {
6854 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6855 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6856 ERRSRV, ERRbadpath);
6859 reply_nterror(req, status);
6863 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6865 if ((flags&1) && target_is_directory) {
6866 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6870 if ((flags&2) && !target_is_directory) {
6871 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
6875 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6876 /* wants a tree copy! XXXX */
6877 DEBUG(3,("Rejecting tree copy\n"));
6878 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6882 /* Split up the directory from the filename/mask. */
6883 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6884 &fname_src_dir, &fname_src_mask);
6885 if (!NT_STATUS_IS_OK(status)) {
6886 reply_nterror(req, NT_STATUS_NO_MEMORY);
6891 * We should only check the mangled cache
6892 * here if unix_convert failed. This means
6893 * that the path in 'mask' doesn't exist
6894 * on the file system and so we need to look
6895 * for a possible mangle. This patch from
6896 * Tine Smukavec <valentin.smukavec@hermes.si>.
6898 if (!VALID_STAT(smb_fname_src->st) &&
6899 mangle_is_mangled(fname_src_mask, conn->params)) {
6900 char *new_mask = NULL;
6901 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6902 &new_mask, conn->params);
6904 /* Use demangled name if one was successfully found. */
6906 TALLOC_FREE(fname_src_mask);
6907 fname_src_mask = new_mask;
6911 if (!source_has_wild) {
6914 * Only one file needs to be copied. Append the mask back onto
6917 TALLOC_FREE(smb_fname_src->base_name);
6918 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6922 if (!smb_fname_src->base_name) {
6923 reply_nterror(req, NT_STATUS_NO_MEMORY);
6927 if (dest_has_wild) {
6928 char *fname_dst_mod = NULL;
6929 if (!resolve_wildcards(smb_fname_dst,
6930 smb_fname_src->base_name,
6931 smb_fname_dst->base_name,
6933 reply_nterror(req, NT_STATUS_NO_MEMORY);
6936 TALLOC_FREE(smb_fname_dst->base_name);
6937 smb_fname_dst->base_name = fname_dst_mod;
6940 status = check_name(conn, smb_fname_src->base_name);
6941 if (!NT_STATUS_IS_OK(status)) {
6942 reply_nterror(req, status);
6946 status = check_name(conn, smb_fname_dst->base_name);
6947 if (!NT_STATUS_IS_OK(status)) {
6948 reply_nterror(req, status);
6952 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
6953 ofun, count, target_is_directory);
6955 if(!NT_STATUS_IS_OK(status)) {
6956 reply_nterror(req, status);
6962 struct smb_Dir *dir_hnd = NULL;
6963 const char *dname = NULL;
6964 char *talloced = NULL;
6968 * There is a wildcard that requires us to actually read the
6969 * src dir and copy each file matching the mask to the dst.
6970 * Right now streams won't be copied, but this could
6971 * presumably be added with a nested loop for reach dir entry.
6973 SMB_ASSERT(!smb_fname_src->stream_name);
6974 SMB_ASSERT(!smb_fname_dst->stream_name);
6976 smb_fname_src->stream_name = NULL;
6977 smb_fname_dst->stream_name = NULL;
6979 if (strequal(fname_src_mask,"????????.???")) {
6980 TALLOC_FREE(fname_src_mask);
6981 fname_src_mask = talloc_strdup(ctx, "*");
6982 if (!fname_src_mask) {
6983 reply_nterror(req, NT_STATUS_NO_MEMORY);
6988 status = check_name(conn, fname_src_dir);
6989 if (!NT_STATUS_IS_OK(status)) {
6990 reply_nterror(req, status);
6994 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
6995 if (dir_hnd == NULL) {
6996 status = map_nt_error_from_unix(errno);
6997 reply_nterror(req, status);
7003 /* Iterate over the src dir copying each entry to the dst. */
7004 while ((dname = ReadDirName(dir_hnd, &offset,
7005 &smb_fname_src->st, &talloced))) {
7006 char *destname = NULL;
7008 if (ISDOT(dname) || ISDOTDOT(dname)) {
7009 TALLOC_FREE(talloced);
7013 if (!is_visible_file(conn, fname_src_dir, dname,
7014 &smb_fname_src->st, false)) {
7015 TALLOC_FREE(talloced);
7019 if(!mask_match(dname, fname_src_mask,
7020 conn->case_sensitive)) {
7021 TALLOC_FREE(talloced);
7025 error = ERRnoaccess;
7027 /* Get the src smb_fname struct setup. */
7028 TALLOC_FREE(smb_fname_src->base_name);
7029 smb_fname_src->base_name =
7030 talloc_asprintf(smb_fname_src, "%s/%s",
7031 fname_src_dir, dname);
7033 if (!smb_fname_src->base_name) {
7034 TALLOC_FREE(dir_hnd);
7035 TALLOC_FREE(talloced);
7036 reply_nterror(req, NT_STATUS_NO_MEMORY);
7040 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7041 smb_fname_dst->base_name,
7043 TALLOC_FREE(talloced);
7047 TALLOC_FREE(dir_hnd);
7048 TALLOC_FREE(talloced);
7049 reply_nterror(req, NT_STATUS_NO_MEMORY);
7053 TALLOC_FREE(smb_fname_dst->base_name);
7054 smb_fname_dst->base_name = destname;
7056 status = check_name(conn, smb_fname_src->base_name);
7057 if (!NT_STATUS_IS_OK(status)) {
7058 TALLOC_FREE(dir_hnd);
7059 TALLOC_FREE(talloced);
7060 reply_nterror(req, status);
7064 status = check_name(conn, smb_fname_dst->base_name);
7065 if (!NT_STATUS_IS_OK(status)) {
7066 TALLOC_FREE(dir_hnd);
7067 TALLOC_FREE(talloced);
7068 reply_nterror(req, status);
7072 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7073 smb_fname_src->base_name,
7074 smb_fname_dst->base_name));
7076 status = copy_file(ctx, conn, smb_fname_src,
7077 smb_fname_dst, ofun, count,
7078 target_is_directory);
7079 if (NT_STATUS_IS_OK(status)) {
7083 TALLOC_FREE(talloced);
7085 TALLOC_FREE(dir_hnd);
7089 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7093 reply_outbuf(req, 1, 0);
7094 SSVAL(req->outbuf,smb_vwv0,count);
7096 TALLOC_FREE(smb_fname_src);
7097 TALLOC_FREE(smb_fname_dst);
7098 TALLOC_FREE(fname_src);
7099 TALLOC_FREE(fname_dst);
7100 TALLOC_FREE(fname_src_mask);
7101 TALLOC_FREE(fname_src_dir);
7103 END_PROFILE(SMBcopy);
7108 #define DBGC_CLASS DBGC_LOCKING
7110 /****************************************************************************
7111 Get a lock pid, dealing with large count requests.
7112 ****************************************************************************/
7114 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7115 bool large_file_format)
7117 if(!large_file_format)
7118 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7120 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7123 /****************************************************************************
7124 Get a lock count, dealing with large count requests.
7125 ****************************************************************************/
7127 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7128 bool large_file_format)
7132 if(!large_file_format) {
7133 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7136 #if defined(HAVE_LONGLONG)
7137 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7138 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7139 #else /* HAVE_LONGLONG */
7142 * NT4.x seems to be broken in that it sends large file (64 bit)
7143 * lockingX calls even if the CAP_LARGE_FILES was *not*
7144 * negotiated. For boxes without large unsigned ints truncate the
7145 * lock count by dropping the top 32 bits.
7148 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7149 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7150 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7151 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7152 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7155 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7156 #endif /* HAVE_LONGLONG */
7162 #if !defined(HAVE_LONGLONG)
7163 /****************************************************************************
7164 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7165 ****************************************************************************/
7167 static uint32 map_lock_offset(uint32 high, uint32 low)
7171 uint32 highcopy = high;
7174 * Try and find out how many significant bits there are in high.
7177 for(i = 0; highcopy; i++)
7181 * We use 31 bits not 32 here as POSIX
7182 * lock offsets may not be negative.
7185 mask = (~0) << (31 - i);
7188 return 0; /* Fail. */
7194 #endif /* !defined(HAVE_LONGLONG) */
7196 /****************************************************************************
7197 Get a lock offset, dealing with large offset requests.
7198 ****************************************************************************/
7200 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7201 bool large_file_format, bool *err)
7203 uint64_t offset = 0;
7207 if(!large_file_format) {
7208 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7211 #if defined(HAVE_LONGLONG)
7212 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7213 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7214 #else /* HAVE_LONGLONG */
7217 * NT4.x seems to be broken in that it sends large file (64 bit)
7218 * lockingX calls even if the CAP_LARGE_FILES was *not*
7219 * negotiated. For boxes without large unsigned ints mangle the
7220 * lock offset by mapping the top 32 bits onto the lower 32.
7223 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7224 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7225 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7228 if((new_low = map_lock_offset(high, low)) == 0) {
7230 return (uint64_t)-1;
7233 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7234 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7235 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7236 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7239 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7240 #endif /* HAVE_LONGLONG */
7246 NTSTATUS smbd_do_locking(struct smb_request *req,
7250 uint16_t num_ulocks,
7251 struct smbd_lock_element *ulocks,
7253 struct smbd_lock_element *locks,
7256 connection_struct *conn = req->conn;
7258 NTSTATUS status = NT_STATUS_OK;
7262 /* Data now points at the beginning of the list
7263 of smb_unlkrng structs */
7264 for(i = 0; i < (int)num_ulocks; i++) {
7265 struct smbd_lock_element *e = &ulocks[i];
7267 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7268 "pid %u, file %s\n",
7271 (unsigned int)e->smblctx,
7274 if (e->brltype != UNLOCK_LOCK) {
7275 /* this can only happen with SMB2 */
7276 return NT_STATUS_INVALID_PARAMETER;
7279 status = do_unlock(req->sconn->msg_ctx,
7286 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7287 nt_errstr(status)));
7289 if (!NT_STATUS_IS_OK(status)) {
7294 /* Setup the timeout in seconds. */
7296 if (!lp_blocking_locks(SNUM(conn))) {
7300 /* Data now points at the beginning of the list
7301 of smb_lkrng structs */
7303 for(i = 0; i < (int)num_locks; i++) {
7304 struct smbd_lock_element *e = &locks[i];
7306 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7307 "%llu, file %s timeout = %d\n",
7310 (unsigned long long)e->smblctx,
7314 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7315 struct blocking_lock_record *blr = NULL;
7317 if (num_locks > 1) {
7319 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7320 * if the lock vector contains one entry. When given mutliple cancel
7321 * requests in a single PDU we expect the server to return an
7322 * error. Windows servers seem to accept the request but only
7323 * cancel the first lock.
7324 * JRA - Do what Windows does (tm) :-).
7328 /* MS-CIFS (2.2.4.32.1) behavior. */
7329 return NT_STATUS_DOS(ERRDOS,
7330 ERRcancelviolation);
7332 /* Windows behavior. */
7334 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7335 "cancel request\n"));
7341 if (lp_blocking_locks(SNUM(conn))) {
7343 /* Schedule a message to ourselves to
7344 remove the blocking lock record and
7345 return the right error. */
7347 blr = blocking_lock_cancel_smb1(fsp,
7353 NT_STATUS_FILE_LOCK_CONFLICT);
7355 return NT_STATUS_DOS(
7357 ERRcancelviolation);
7360 /* Remove a matching pending lock. */
7361 status = do_lock_cancel(fsp,
7368 bool blocking_lock = timeout ? true : false;
7369 bool defer_lock = false;
7370 struct byte_range_lock *br_lck;
7371 uint64_t block_smblctx;
7373 br_lck = do_lock(req->sconn->msg_ctx,
7385 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7386 /* Windows internal resolution for blocking locks seems
7387 to be about 200ms... Don't wait for less than that. JRA. */
7388 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7389 timeout = lp_lock_spin_time();
7394 /* If a lock sent with timeout of zero would fail, and
7395 * this lock has been requested multiple times,
7396 * according to brl_lock_failed() we convert this
7397 * request to a blocking lock with a timeout of between
7398 * 150 - 300 milliseconds.
7400 * If lp_lock_spin_time() has been set to 0, we skip
7401 * this blocking retry and fail immediately.
7403 * Replacement for do_lock_spin(). JRA. */
7405 if (!req->sconn->using_smb2 &&
7406 br_lck && lp_blocking_locks(SNUM(conn)) &&
7407 lp_lock_spin_time() && !blocking_lock &&
7408 NT_STATUS_EQUAL((status),
7409 NT_STATUS_FILE_LOCK_CONFLICT))
7412 timeout = lp_lock_spin_time();
7415 if (br_lck && defer_lock) {
7417 * A blocking lock was requested. Package up
7418 * this smb into a queued request and push it
7419 * onto the blocking lock queue.
7421 if(push_blocking_lock_request(br_lck,
7432 TALLOC_FREE(br_lck);
7434 return NT_STATUS_OK;
7438 TALLOC_FREE(br_lck);
7441 if (!NT_STATUS_IS_OK(status)) {
7446 /* If any of the above locks failed, then we must unlock
7447 all of the previous locks (X/Open spec). */
7449 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7451 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7452 i = -1; /* we want to skip the for loop */
7456 * Ensure we don't do a remove on the lock that just failed,
7457 * as under POSIX rules, if we have a lock already there, we
7458 * will delete it (and we shouldn't) .....
7460 for(i--; i >= 0; i--) {
7461 struct smbd_lock_element *e = &locks[i];
7463 do_unlock(req->sconn->msg_ctx,
7473 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7474 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7476 return NT_STATUS_OK;
7479 /****************************************************************************
7480 Reply to a lockingX request.
7481 ****************************************************************************/
7483 void reply_lockingX(struct smb_request *req)
7485 connection_struct *conn = req->conn;
7487 unsigned char locktype;
7488 unsigned char oplocklevel;
7493 const uint8_t *data;
7494 bool large_file_format;
7496 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7497 struct smbd_lock_element *ulocks;
7498 struct smbd_lock_element *locks;
7501 START_PROFILE(SMBlockingX);
7504 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7505 END_PROFILE(SMBlockingX);
7509 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7510 locktype = CVAL(req->vwv+3, 0);
7511 oplocklevel = CVAL(req->vwv+3, 1);
7512 num_ulocks = SVAL(req->vwv+6, 0);
7513 num_locks = SVAL(req->vwv+7, 0);
7514 lock_timeout = IVAL(req->vwv+4, 0);
7515 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7517 if (!check_fsp(conn, req, fsp)) {
7518 END_PROFILE(SMBlockingX);
7524 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7525 /* we don't support these - and CANCEL_LOCK makes w2k
7526 and XP reboot so I don't really want to be
7527 compatible! (tridge) */
7528 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7529 END_PROFILE(SMBlockingX);
7533 /* Check if this is an oplock break on a file
7534 we have granted an oplock on.
7536 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7537 /* Client can insist on breaking to none. */
7538 bool break_to_none = (oplocklevel == 0);
7541 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7542 "for fnum = %d\n", (unsigned int)oplocklevel,
7546 * Make sure we have granted an exclusive or batch oplock on
7550 if (fsp->oplock_type == 0) {
7552 /* The Samba4 nbench simulator doesn't understand
7553 the difference between break to level2 and break
7554 to none from level2 - it sends oplock break
7555 replies in both cases. Don't keep logging an error
7556 message here - just ignore it. JRA. */
7558 DEBUG(5,("reply_lockingX: Error : oplock break from "
7559 "client for fnum = %d (oplock=%d) and no "
7560 "oplock granted on this file (%s).\n",
7561 fsp->fnum, fsp->oplock_type,
7564 /* if this is a pure oplock break request then don't
7566 if (num_locks == 0 && num_ulocks == 0) {
7567 END_PROFILE(SMBlockingX);
7570 END_PROFILE(SMBlockingX);
7571 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7576 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7578 result = remove_oplock(fsp);
7580 result = downgrade_oplock(fsp);
7584 DEBUG(0, ("reply_lockingX: error in removing "
7585 "oplock on file %s\n", fsp_str_dbg(fsp)));
7586 /* Hmmm. Is this panic justified? */
7587 smb_panic("internal tdb error");
7590 reply_to_oplock_break_requests(fsp);
7592 /* if this is a pure oplock break request then don't send a
7594 if (num_locks == 0 && num_ulocks == 0) {
7595 /* Sanity check - ensure a pure oplock break is not a
7597 if(CVAL(req->vwv+0, 0) != 0xff)
7598 DEBUG(0,("reply_lockingX: Error : pure oplock "
7599 "break is a chained %d request !\n",
7600 (unsigned int)CVAL(req->vwv+0, 0)));
7601 END_PROFILE(SMBlockingX);
7607 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7608 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7609 END_PROFILE(SMBlockingX);
7613 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7614 if (ulocks == NULL) {
7615 reply_nterror(req, NT_STATUS_NO_MEMORY);
7616 END_PROFILE(SMBlockingX);
7620 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7621 if (locks == NULL) {
7622 reply_nterror(req, NT_STATUS_NO_MEMORY);
7623 END_PROFILE(SMBlockingX);
7627 /* Data now points at the beginning of the list
7628 of smb_unlkrng structs */
7629 for(i = 0; i < (int)num_ulocks; i++) {
7630 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7631 ulocks[i].count = get_lock_count(data, i, large_file_format);
7632 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7633 ulocks[i].brltype = UNLOCK_LOCK;
7636 * There is no error code marked "stupid client bug".... :-).
7639 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7640 END_PROFILE(SMBlockingX);
7645 /* Now do any requested locks */
7646 data += ((large_file_format ? 20 : 10)*num_ulocks);
7648 /* Data now points at the beginning of the list
7649 of smb_lkrng structs */
7651 for(i = 0; i < (int)num_locks; i++) {
7652 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7653 locks[i].count = get_lock_count(data, i, large_file_format);
7654 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7656 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7657 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7658 locks[i].brltype = PENDING_READ_LOCK;
7660 locks[i].brltype = READ_LOCK;
7663 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7664 locks[i].brltype = PENDING_WRITE_LOCK;
7666 locks[i].brltype = WRITE_LOCK;
7671 * There is no error code marked "stupid client bug".... :-).
7674 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7675 END_PROFILE(SMBlockingX);
7680 status = smbd_do_locking(req, fsp,
7681 locktype, lock_timeout,
7685 if (!NT_STATUS_IS_OK(status)) {
7686 END_PROFILE(SMBlockingX);
7687 reply_nterror(req, status);
7691 END_PROFILE(SMBlockingX);
7695 reply_outbuf(req, 2, 0);
7697 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7698 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7700 END_PROFILE(SMBlockingX);
7705 #define DBGC_CLASS DBGC_ALL
7707 /****************************************************************************
7708 Reply to a SMBreadbmpx (read block multiplex) request.
7709 Always reply with an error, if someone has a platform really needs this,
7710 please contact vl@samba.org
7711 ****************************************************************************/
7713 void reply_readbmpx(struct smb_request *req)
7715 START_PROFILE(SMBreadBmpx);
7716 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7717 END_PROFILE(SMBreadBmpx);
7721 /****************************************************************************
7722 Reply to a SMBreadbs (read block multiplex secondary) request.
7723 Always reply with an error, if someone has a platform really needs this,
7724 please contact vl@samba.org
7725 ****************************************************************************/
7727 void reply_readbs(struct smb_request *req)
7729 START_PROFILE(SMBreadBs);
7730 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7731 END_PROFILE(SMBreadBs);
7735 /****************************************************************************
7736 Reply to a SMBsetattrE.
7737 ****************************************************************************/
7739 void reply_setattrE(struct smb_request *req)
7741 connection_struct *conn = req->conn;
7742 struct smb_file_time ft;
7746 START_PROFILE(SMBsetattrE);
7750 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7754 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7756 if(!fsp || (fsp->conn != conn)) {
7757 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7762 * Convert the DOS times into unix times.
7765 ft.atime = convert_time_t_to_timespec(
7766 srv_make_unix_date2(req->vwv+3));
7767 ft.mtime = convert_time_t_to_timespec(
7768 srv_make_unix_date2(req->vwv+5));
7769 ft.create_time = convert_time_t_to_timespec(
7770 srv_make_unix_date2(req->vwv+1));
7772 reply_outbuf(req, 0, 0);
7775 * Patch from Ray Frush <frush@engr.colostate.edu>
7776 * Sometimes times are sent as zero - ignore them.
7779 /* Ensure we have a valid stat struct for the source. */
7780 status = vfs_stat_fsp(fsp);
7781 if (!NT_STATUS_IS_OK(status)) {
7782 reply_nterror(req, status);
7786 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7787 if (!NT_STATUS_IS_OK(status)) {
7788 reply_nterror(req, status);
7792 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7795 (unsigned int)ft.atime.tv_sec,
7796 (unsigned int)ft.mtime.tv_sec,
7797 (unsigned int)ft.create_time.tv_sec
7800 END_PROFILE(SMBsetattrE);
7805 /* Back from the dead for OS/2..... JRA. */
7807 /****************************************************************************
7808 Reply to a SMBwritebmpx (write block multiplex primary) request.
7809 Always reply with an error, if someone has a platform really needs this,
7810 please contact vl@samba.org
7811 ****************************************************************************/
7813 void reply_writebmpx(struct smb_request *req)
7815 START_PROFILE(SMBwriteBmpx);
7816 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7817 END_PROFILE(SMBwriteBmpx);
7821 /****************************************************************************
7822 Reply to a SMBwritebs (write block multiplex secondary) request.
7823 Always reply with an error, if someone has a platform really needs this,
7824 please contact vl@samba.org
7825 ****************************************************************************/
7827 void reply_writebs(struct smb_request *req)
7829 START_PROFILE(SMBwriteBs);
7830 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7831 END_PROFILE(SMBwriteBs);
7835 /****************************************************************************
7836 Reply to a SMBgetattrE.
7837 ****************************************************************************/
7839 void reply_getattrE(struct smb_request *req)
7841 connection_struct *conn = req->conn;
7844 struct timespec create_ts;
7846 START_PROFILE(SMBgetattrE);
7849 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7850 END_PROFILE(SMBgetattrE);
7854 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7856 if(!fsp || (fsp->conn != conn)) {
7857 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7858 END_PROFILE(SMBgetattrE);
7862 /* Do an fstat on this file */
7864 reply_nterror(req, map_nt_error_from_unix(errno));
7865 END_PROFILE(SMBgetattrE);
7869 mode = dos_mode(conn, fsp->fsp_name);
7872 * Convert the times into dos times. Set create
7873 * date to be last modify date as UNIX doesn't save
7877 reply_outbuf(req, 11, 0);
7879 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7880 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7881 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7882 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7883 /* Should we check pending modtime here ? JRA */
7884 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7885 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7888 SIVAL(req->outbuf, smb_vwv6, 0);
7889 SIVAL(req->outbuf, smb_vwv8, 0);
7891 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7892 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
7893 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7895 SSVAL(req->outbuf,smb_vwv10, mode);
7897 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7899 END_PROFILE(SMBgetattrE);