2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
29 #include "smbd/globals.h"
30 #include "../librpc/gen_ndr/cli_spoolss.h"
31 #include "rpc_client/cli_spoolss.h"
32 #include "rpc_client/init_spoolss.h"
34 /****************************************************************************
35 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
36 path or anything including wildcards.
37 We're assuming here that '/' is not the second byte in any multibyte char
38 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
40 ****************************************************************************/
42 /* Custom version for processing POSIX paths. */
43 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
45 static NTSTATUS check_path_syntax_internal(char *path,
47 bool *p_last_component_contains_wcard)
51 NTSTATUS ret = NT_STATUS_OK;
52 bool start_of_name_component = True;
53 bool stream_started = false;
55 *p_last_component_contains_wcard = False;
62 return NT_STATUS_OBJECT_NAME_INVALID;
65 return NT_STATUS_OBJECT_NAME_INVALID;
67 if (strchr_m(&s[1], ':')) {
68 return NT_STATUS_OBJECT_NAME_INVALID;
74 if ((*s == ':') && !posix_path && !stream_started) {
75 if (*p_last_component_contains_wcard) {
76 return NT_STATUS_OBJECT_NAME_INVALID;
78 /* Stream names allow more characters than file names.
79 We're overloading posix_path here to allow a wider
80 range of characters. If stream_started is true this
81 is still a Windows path even if posix_path is true.
84 stream_started = true;
85 start_of_name_component = false;
89 return NT_STATUS_OBJECT_NAME_INVALID;
93 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
95 * Safe to assume is not the second part of a mb char
96 * as this is handled below.
98 /* Eat multiple '/' or '\\' */
99 while (IS_PATH_SEP(*s,posix_path)) {
102 if ((d != path) && (*s != '\0')) {
103 /* We only care about non-leading or trailing '/' or '\\' */
107 start_of_name_component = True;
109 *p_last_component_contains_wcard = False;
113 if (start_of_name_component) {
114 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
115 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
118 * No mb char starts with '.' so we're safe checking the directory separator here.
121 /* If we just added a '/' - delete it */
122 if ((d > path) && (*(d-1) == '/')) {
127 /* Are we at the start ? Can't go back further if so. */
129 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
132 /* Go back one level... */
133 /* We know this is safe as '/' cannot be part of a mb sequence. */
134 /* NOTE - if this assumption is invalid we are not in good shape... */
135 /* Decrement d first as d points to the *next* char to write into. */
136 for (d--; d > path; d--) {
140 s += 2; /* Else go past the .. */
141 /* We're still at the start of a name component, just the previous one. */
144 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
156 if (*s <= 0x1f || *s == '|') {
157 return NT_STATUS_OBJECT_NAME_INVALID;
165 *p_last_component_contains_wcard = True;
174 /* Get the size of the next MB character. */
175 next_codepoint(s,&siz);
193 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
195 return NT_STATUS_INVALID_PARAMETER;
198 start_of_name_component = False;
206 /****************************************************************************
207 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
208 No wildcards allowed.
209 ****************************************************************************/
211 NTSTATUS check_path_syntax(char *path)
214 return check_path_syntax_internal(path, False, &ignore);
217 /****************************************************************************
218 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
219 Wildcards allowed - p_contains_wcard returns true if the last component contained
221 ****************************************************************************/
223 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
225 return check_path_syntax_internal(path, False, p_contains_wcard);
228 /****************************************************************************
229 Check the path for a POSIX client.
230 We're assuming here that '/' is not the second byte in any multibyte char
231 set (a safe assumption).
232 ****************************************************************************/
234 NTSTATUS check_path_syntax_posix(char *path)
237 return check_path_syntax_internal(path, True, &ignore);
240 /****************************************************************************
241 Pull a string and check the path allowing a wilcard - provide for error return.
242 ****************************************************************************/
244 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
245 const char *base_ptr,
252 bool *contains_wcard)
258 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
262 *err = NT_STATUS_INVALID_PARAMETER;
266 *contains_wcard = False;
268 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
270 * For a DFS path the function parse_dfs_path()
271 * will do the path processing, just make a copy.
277 if (lp_posix_pathnames()) {
278 *err = check_path_syntax_posix(*pp_dest);
280 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
286 /****************************************************************************
287 Pull a string and check the path - provide for error return.
288 ****************************************************************************/
290 size_t srvstr_get_path(TALLOC_CTX *ctx,
291 const char *base_ptr,
300 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
301 src_len, flags, err, &ignore);
304 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
305 char **pp_dest, const char *src, int flags,
306 NTSTATUS *err, bool *contains_wcard)
308 return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
309 pp_dest, src, smbreq_bufrem(req, src),
310 flags, err, contains_wcard);
313 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
314 char **pp_dest, const char *src, int flags,
318 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
319 flags, err, &ignore);
322 /****************************************************************************
323 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
324 ****************************************************************************/
326 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
329 if ((fsp == NULL) || (conn == NULL)) {
330 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
333 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
334 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
340 /****************************************************************************
341 Check if we have a correct fsp pointing to a file.
342 ****************************************************************************/
344 bool check_fsp(connection_struct *conn, struct smb_request *req,
347 if (!check_fsp_open(conn, req, fsp)) {
350 if (fsp->is_directory) {
351 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
354 if (fsp->fh->fd == -1) {
355 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
358 fsp->num_smb_operations++;
362 /****************************************************************************
363 Check if we have a correct fsp pointing to a quota fake file. Replacement for
364 the CHECK_NTQUOTA_HANDLE_OK macro.
365 ****************************************************************************/
367 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
370 if (!check_fsp_open(conn, req, fsp)) {
374 if (fsp->is_directory) {
378 if (fsp->fake_file_handle == NULL) {
382 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
386 if (fsp->fake_file_handle->private_data == NULL) {
393 static bool netbios_session_retarget(struct smbd_server_connection *sconn,
394 const char *name, int name_type)
397 char *trim_name_type;
398 const char *retarget_parm;
401 int retarget_type = 0x20;
402 int retarget_port = 139;
403 struct sockaddr_storage retarget_addr;
404 struct sockaddr_in *in_addr;
408 if (get_socket_port(sconn->sock) != 139) {
412 trim_name = talloc_strdup(talloc_tos(), name);
413 if (trim_name == NULL) {
416 trim_char(trim_name, ' ', ' ');
418 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
420 if (trim_name_type == NULL) {
424 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
425 trim_name_type, NULL);
426 if (retarget_parm == NULL) {
427 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
430 if (retarget_parm == NULL) {
434 retarget = talloc_strdup(trim_name, retarget_parm);
435 if (retarget == NULL) {
439 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
441 p = strchr(retarget, ':');
444 retarget_port = atoi(p);
447 p = strchr_m(retarget, '#');
450 sscanf(p, "%x", &retarget_type);
453 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
455 DEBUG(10, ("could not resolve %s\n", retarget));
459 if (retarget_addr.ss_family != AF_INET) {
460 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
464 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
466 _smb_setlen(outbuf, 6);
467 SCVAL(outbuf, 0, 0x84);
468 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
469 *(uint16_t *)(outbuf+8) = htons(retarget_port);
471 if (!srv_send_smb(sconn->sock, (char *)outbuf, false, 0, false,
473 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
479 TALLOC_FREE(trim_name);
483 /****************************************************************************
484 Reply to a (netbios-level) special message.
485 ****************************************************************************/
487 void reply_special(struct smbd_server_connection *sconn, char *inbuf)
489 int msg_type = CVAL(inbuf,0);
490 int msg_flags = CVAL(inbuf,1);
492 char name_type1, name_type2;
495 * We only really use 4 bytes of the outbuf, but for the smb_setlen
496 * calculation & friends (srv_send_smb uses that) we need the full smb
499 char outbuf[smb_size];
503 memset(outbuf, '\0', sizeof(outbuf));
505 smb_setlen(outbuf,0);
508 case 0x81: /* session request */
510 if (sconn->nbt.got_session) {
511 exit_server_cleanly("multiple session request not permitted");
514 SCVAL(outbuf,0,0x82);
516 if (name_len(inbuf+4) > 50 ||
517 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
518 DEBUG(0,("Invalid name length in session request\n"));
521 name_type1 = name_extract(inbuf,4,name1);
522 name_type2 = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
523 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
524 name1, name_type1, name2, name_type2));
526 if (netbios_session_retarget(sconn, name1, name_type1)) {
527 exit_server_cleanly("retargeted client");
530 set_local_machine_name(name1, True);
531 set_remote_machine_name(name2, True);
533 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
534 get_local_machine_name(), get_remote_machine_name(),
537 if (name_type2 == 'R') {
538 /* We are being asked for a pathworks session ---
540 SCVAL(outbuf, 0,0x83);
544 /* only add the client's machine name to the list
545 of possibly valid usernames if we are operating
546 in share mode security */
547 if (lp_security() == SEC_SHARE) {
548 add_session_user(sconn, get_remote_machine_name());
551 reload_services(sconn->msg_ctx, sconn->sock, True);
554 sconn->nbt.got_session = true;
557 case 0x89: /* session keepalive request
558 (some old clients produce this?) */
559 SCVAL(outbuf,0,SMBkeepalive);
563 case 0x82: /* positive session response */
564 case 0x83: /* negative session response */
565 case 0x84: /* retarget session response */
566 DEBUG(0,("Unexpected session response\n"));
569 case SMBkeepalive: /* session keepalive */
574 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
575 msg_type, msg_flags));
577 srv_send_smb(sconn->sock, outbuf, false, 0, false, NULL);
581 /****************************************************************************
583 conn POINTER CAN BE NULL HERE !
584 ****************************************************************************/
586 void reply_tcon(struct smb_request *req)
588 connection_struct *conn = req->conn;
590 char *service_buf = NULL;
591 char *password = NULL;
596 DATA_BLOB password_blob;
597 TALLOC_CTX *ctx = talloc_tos();
598 struct smbd_server_connection *sconn = req->sconn;
600 START_PROFILE(SMBtcon);
602 if (req->buflen < 4) {
603 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
604 END_PROFILE(SMBtcon);
608 p = (const char *)req->buf + 1;
609 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
611 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
613 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
616 if (service_buf == NULL || password == NULL || dev == NULL) {
617 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
618 END_PROFILE(SMBtcon);
621 p = strrchr_m(service_buf,'\\');
625 service = service_buf;
628 password_blob = data_blob(password, pwlen+1);
630 conn = make_connection(sconn,service,password_blob,dev,
631 req->vuid,&nt_status);
634 data_blob_clear_free(&password_blob);
637 reply_nterror(req, nt_status);
638 END_PROFILE(SMBtcon);
642 reply_outbuf(req, 2, 0);
643 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
644 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
645 SSVAL(req->outbuf,smb_tid,conn->cnum);
647 DEBUG(3,("tcon service=%s cnum=%d\n",
648 service, conn->cnum));
650 END_PROFILE(SMBtcon);
654 /****************************************************************************
655 Reply to a tcon and X.
656 conn POINTER CAN BE NULL HERE !
657 ****************************************************************************/
659 void reply_tcon_and_X(struct smb_request *req)
661 connection_struct *conn = req->conn;
662 const char *service = NULL;
664 TALLOC_CTX *ctx = talloc_tos();
665 /* what the cleint thinks the device is */
666 char *client_devicetype = NULL;
667 /* what the server tells the client the share represents */
668 const char *server_devicetype;
674 struct smbd_server_connection *sconn = req->sconn;
676 START_PROFILE(SMBtconX);
679 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
680 END_PROFILE(SMBtconX);
684 passlen = SVAL(req->vwv+3, 0);
685 tcon_flags = SVAL(req->vwv+2, 0);
687 /* we might have to close an old one */
688 if ((tcon_flags & 0x1) && conn) {
689 close_cnum(conn,req->vuid);
694 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
695 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
696 END_PROFILE(SMBtconX);
700 if (sconn->smb1.negprot.encrypted_passwords) {
701 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
702 if (lp_security() == SEC_SHARE) {
704 * Security = share always has a pad byte
705 * after the password.
707 p = (const char *)req->buf + passlen + 1;
709 p = (const char *)req->buf + passlen;
712 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
713 /* Ensure correct termination */
714 password.data[passlen]=0;
715 p = (const char *)req->buf + passlen + 1;
718 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
721 data_blob_clear_free(&password);
722 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
723 END_PROFILE(SMBtconX);
728 * the service name can be either: \\server\share
729 * or share directly like on the DELL PowerVault 705
732 q = strchr_m(path+2,'\\');
734 data_blob_clear_free(&password);
735 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
736 END_PROFILE(SMBtconX);
744 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
745 &client_devicetype, p,
746 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
748 if (client_devicetype == NULL) {
749 data_blob_clear_free(&password);
750 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
751 END_PROFILE(SMBtconX);
755 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
757 conn = make_connection(sconn, service, password, client_devicetype,
758 req->vuid, &nt_status);
761 data_blob_clear_free(&password);
764 reply_nterror(req, nt_status);
765 END_PROFILE(SMBtconX);
770 server_devicetype = "IPC";
771 else if ( IS_PRINT(conn) )
772 server_devicetype = "LPT1:";
774 server_devicetype = "A:";
776 if (get_Protocol() < PROTOCOL_NT1) {
777 reply_outbuf(req, 2, 0);
778 if (message_push_string(&req->outbuf, server_devicetype,
779 STR_TERMINATE|STR_ASCII) == -1) {
780 reply_nterror(req, NT_STATUS_NO_MEMORY);
781 END_PROFILE(SMBtconX);
785 /* NT sets the fstype of IPC$ to the null string */
786 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
788 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
789 /* Return permissions. */
793 reply_outbuf(req, 7, 0);
796 perm1 = FILE_ALL_ACCESS;
797 perm2 = FILE_ALL_ACCESS;
799 perm1 = CAN_WRITE(conn) ?
804 SIVAL(req->outbuf, smb_vwv3, perm1);
805 SIVAL(req->outbuf, smb_vwv5, perm2);
807 reply_outbuf(req, 3, 0);
810 if ((message_push_string(&req->outbuf, server_devicetype,
811 STR_TERMINATE|STR_ASCII) == -1)
812 || (message_push_string(&req->outbuf, fstype,
813 STR_TERMINATE) == -1)) {
814 reply_nterror(req, NT_STATUS_NO_MEMORY);
815 END_PROFILE(SMBtconX);
819 /* what does setting this bit do? It is set by NT4 and
820 may affect the ability to autorun mounted cdroms */
821 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
822 (lp_csc_policy(SNUM(conn)) << 2));
824 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
825 DEBUG(2,("Serving %s as a Dfs root\n",
826 lp_servicename(SNUM(conn)) ));
827 SSVAL(req->outbuf, smb_vwv2,
828 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
833 DEBUG(3,("tconX service=%s \n",
836 /* set the incoming and outgoing tid to the just created one */
837 SSVAL(req->inbuf,smb_tid,conn->cnum);
838 SSVAL(req->outbuf,smb_tid,conn->cnum);
840 END_PROFILE(SMBtconX);
842 req->tid = conn->cnum;
847 /****************************************************************************
848 Reply to an unknown type.
849 ****************************************************************************/
851 void reply_unknown_new(struct smb_request *req, uint8 type)
853 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
854 smb_fn_name(type), type, type));
855 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
859 /****************************************************************************
861 conn POINTER CAN BE NULL HERE !
862 ****************************************************************************/
864 void reply_ioctl(struct smb_request *req)
866 connection_struct *conn = req->conn;
873 START_PROFILE(SMBioctl);
876 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
877 END_PROFILE(SMBioctl);
881 device = SVAL(req->vwv+1, 0);
882 function = SVAL(req->vwv+2, 0);
883 ioctl_code = (device << 16) + function;
885 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
887 switch (ioctl_code) {
888 case IOCTL_QUERY_JOB_INFO:
892 reply_force_doserror(req, ERRSRV, ERRnosupport);
893 END_PROFILE(SMBioctl);
897 reply_outbuf(req, 8, replysize+1);
898 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
899 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
900 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
901 p = smb_buf(req->outbuf);
902 memset(p, '\0', replysize+1); /* valgrind-safe. */
903 p += 1; /* Allow for alignment */
905 switch (ioctl_code) {
906 case IOCTL_QUERY_JOB_INFO:
908 files_struct *fsp = file_fsp(
909 req, SVAL(req->vwv+0, 0));
911 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
912 END_PROFILE(SMBioctl);
916 if (fsp->print_file) {
917 SSVAL(p, 0, fsp->print_file->rap_jobid);
921 srvstr_push((char *)req->outbuf, req->flags2, p+2,
923 STR_TERMINATE|STR_ASCII);
925 srvstr_push((char *)req->outbuf, req->flags2,
926 p+18, lp_servicename(SNUM(conn)),
927 13, STR_TERMINATE|STR_ASCII);
935 END_PROFILE(SMBioctl);
939 /****************************************************************************
940 Strange checkpath NTSTATUS mapping.
941 ****************************************************************************/
943 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
945 /* Strange DOS error code semantics only for checkpath... */
946 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
947 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
948 /* We need to map to ERRbadpath */
949 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
955 /****************************************************************************
956 Reply to a checkpath.
957 ****************************************************************************/
959 void reply_checkpath(struct smb_request *req)
961 connection_struct *conn = req->conn;
962 struct smb_filename *smb_fname = NULL;
965 TALLOC_CTX *ctx = talloc_tos();
967 START_PROFILE(SMBcheckpath);
969 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
970 STR_TERMINATE, &status);
972 if (!NT_STATUS_IS_OK(status)) {
973 status = map_checkpath_error(req->flags2, status);
974 reply_nterror(req, status);
975 END_PROFILE(SMBcheckpath);
979 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
981 status = filename_convert(ctx,
983 req->flags2 & FLAGS2_DFS_PATHNAMES,
989 if (!NT_STATUS_IS_OK(status)) {
990 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
991 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
993 END_PROFILE(SMBcheckpath);
999 if (!VALID_STAT(smb_fname->st) &&
1000 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1001 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1002 smb_fname_str_dbg(smb_fname), strerror(errno)));
1003 status = map_nt_error_from_unix(errno);
1007 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1008 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1009 ERRDOS, ERRbadpath);
1013 reply_outbuf(req, 0, 0);
1016 /* We special case this - as when a Windows machine
1017 is parsing a path is steps through the components
1018 one at a time - if a component fails it expects
1019 ERRbadpath, not ERRbadfile.
1021 status = map_checkpath_error(req->flags2, status);
1022 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1024 * Windows returns different error codes if
1025 * the parent directory is valid but not the
1026 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1027 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1028 * if the path is invalid.
1030 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1031 ERRDOS, ERRbadpath);
1035 reply_nterror(req, status);
1038 TALLOC_FREE(smb_fname);
1039 END_PROFILE(SMBcheckpath);
1043 /****************************************************************************
1045 ****************************************************************************/
1047 void reply_getatr(struct smb_request *req)
1049 connection_struct *conn = req->conn;
1050 struct smb_filename *smb_fname = NULL;
1057 TALLOC_CTX *ctx = talloc_tos();
1058 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1060 START_PROFILE(SMBgetatr);
1062 p = (const char *)req->buf + 1;
1063 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1064 if (!NT_STATUS_IS_OK(status)) {
1065 reply_nterror(req, status);
1069 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1070 under WfWg - weird! */
1071 if (*fname == '\0') {
1072 mode = aHIDDEN | aDIR;
1073 if (!CAN_WRITE(conn)) {
1079 status = filename_convert(ctx,
1081 req->flags2 & FLAGS2_DFS_PATHNAMES,
1086 if (!NT_STATUS_IS_OK(status)) {
1087 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1088 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1089 ERRSRV, ERRbadpath);
1092 reply_nterror(req, status);
1095 if (!VALID_STAT(smb_fname->st) &&
1096 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1097 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1098 smb_fname_str_dbg(smb_fname),
1100 reply_nterror(req, map_nt_error_from_unix(errno));
1104 mode = dos_mode(conn, smb_fname);
1105 size = smb_fname->st.st_ex_size;
1107 if (ask_sharemode) {
1108 struct timespec write_time_ts;
1109 struct file_id fileid;
1111 ZERO_STRUCT(write_time_ts);
1112 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1113 get_file_infos(fileid, NULL, &write_time_ts);
1114 if (!null_timespec(write_time_ts)) {
1115 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1119 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1125 reply_outbuf(req, 10, 0);
1127 SSVAL(req->outbuf,smb_vwv0,mode);
1128 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1129 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1131 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1133 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1135 if (get_Protocol() >= PROTOCOL_NT1) {
1136 SSVAL(req->outbuf, smb_flg2,
1137 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1140 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1141 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1144 TALLOC_FREE(smb_fname);
1146 END_PROFILE(SMBgetatr);
1150 /****************************************************************************
1152 ****************************************************************************/
1154 void reply_setatr(struct smb_request *req)
1156 struct smb_file_time ft;
1157 connection_struct *conn = req->conn;
1158 struct smb_filename *smb_fname = NULL;
1164 TALLOC_CTX *ctx = talloc_tos();
1166 START_PROFILE(SMBsetatr);
1171 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1175 p = (const char *)req->buf + 1;
1176 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1177 if (!NT_STATUS_IS_OK(status)) {
1178 reply_nterror(req, status);
1182 status = filename_convert(ctx,
1184 req->flags2 & FLAGS2_DFS_PATHNAMES,
1189 if (!NT_STATUS_IS_OK(status)) {
1190 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1191 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1192 ERRSRV, ERRbadpath);
1195 reply_nterror(req, status);
1199 if (smb_fname->base_name[0] == '.' &&
1200 smb_fname->base_name[1] == '\0') {
1202 * Not sure here is the right place to catch this
1203 * condition. Might be moved to somewhere else later -- vl
1205 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1209 mode = SVAL(req->vwv+0, 0);
1210 mtime = srv_make_unix_date3(req->vwv+1);
1212 ft.mtime = convert_time_t_to_timespec(mtime);
1213 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1214 if (!NT_STATUS_IS_OK(status)) {
1215 reply_nterror(req, status);
1219 if (mode != FILE_ATTRIBUTE_NORMAL) {
1220 if (VALID_STAT_OF_DIR(smb_fname->st))
1225 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1227 reply_nterror(req, map_nt_error_from_unix(errno));
1232 reply_outbuf(req, 0, 0);
1234 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1237 TALLOC_FREE(smb_fname);
1238 END_PROFILE(SMBsetatr);
1242 /****************************************************************************
1244 ****************************************************************************/
1246 void reply_dskattr(struct smb_request *req)
1248 connection_struct *conn = req->conn;
1249 uint64_t dfree,dsize,bsize;
1250 START_PROFILE(SMBdskattr);
1252 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1253 reply_nterror(req, map_nt_error_from_unix(errno));
1254 END_PROFILE(SMBdskattr);
1258 reply_outbuf(req, 5, 0);
1260 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1261 double total_space, free_space;
1262 /* we need to scale this to a number that DOS6 can handle. We
1263 use floating point so we can handle large drives on systems
1264 that don't have 64 bit integers
1266 we end up displaying a maximum of 2G to DOS systems
1268 total_space = dsize * (double)bsize;
1269 free_space = dfree * (double)bsize;
1271 dsize = (uint64_t)((total_space+63*512) / (64*512));
1272 dfree = (uint64_t)((free_space+63*512) / (64*512));
1274 if (dsize > 0xFFFF) dsize = 0xFFFF;
1275 if (dfree > 0xFFFF) dfree = 0xFFFF;
1277 SSVAL(req->outbuf,smb_vwv0,dsize);
1278 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1279 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1280 SSVAL(req->outbuf,smb_vwv3,dfree);
1282 SSVAL(req->outbuf,smb_vwv0,dsize);
1283 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1284 SSVAL(req->outbuf,smb_vwv2,512);
1285 SSVAL(req->outbuf,smb_vwv3,dfree);
1288 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1290 END_PROFILE(SMBdskattr);
1295 * Utility function to split the filename from the directory.
1297 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1298 char **fname_dir_out,
1299 char **fname_mask_out)
1301 const char *p = NULL;
1302 char *fname_dir = NULL;
1303 char *fname_mask = NULL;
1305 p = strrchr_m(fname_in, '/');
1307 fname_dir = talloc_strdup(ctx, ".");
1308 fname_mask = talloc_strdup(ctx, fname_in);
1310 fname_dir = talloc_strndup(ctx, fname_in,
1311 PTR_DIFF(p, fname_in));
1312 fname_mask = talloc_strdup(ctx, p+1);
1315 if (!fname_dir || !fname_mask) {
1316 TALLOC_FREE(fname_dir);
1317 TALLOC_FREE(fname_mask);
1318 return NT_STATUS_NO_MEMORY;
1321 *fname_dir_out = fname_dir;
1322 *fname_mask_out = fname_mask;
1323 return NT_STATUS_OK;
1326 /****************************************************************************
1328 Can be called from SMBsearch, SMBffirst or SMBfunique.
1329 ****************************************************************************/
1331 void reply_search(struct smb_request *req)
1333 connection_struct *conn = req->conn;
1335 const char *mask = NULL;
1336 char *directory = NULL;
1337 struct smb_filename *smb_fname = NULL;
1341 struct timespec date;
1343 unsigned int numentries = 0;
1344 unsigned int maxentries = 0;
1345 bool finished = False;
1350 bool check_descend = False;
1351 bool expect_close = False;
1353 bool mask_contains_wcard = False;
1354 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1355 TALLOC_CTX *ctx = talloc_tos();
1356 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1357 struct dptr_struct *dirptr = NULL;
1358 struct smbd_server_connection *sconn = req->sconn;
1360 START_PROFILE(SMBsearch);
1363 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1367 if (lp_posix_pathnames()) {
1368 reply_unknown_new(req, req->cmd);
1372 /* If we were called as SMBffirst then we must expect close. */
1373 if(req->cmd == SMBffirst) {
1374 expect_close = True;
1377 reply_outbuf(req, 1, 3);
1378 maxentries = SVAL(req->vwv+0, 0);
1379 dirtype = SVAL(req->vwv+1, 0);
1380 p = (const char *)req->buf + 1;
1381 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1382 &nt_status, &mask_contains_wcard);
1383 if (!NT_STATUS_IS_OK(nt_status)) {
1384 reply_nterror(req, nt_status);
1389 status_len = SVAL(p, 0);
1392 /* dirtype &= ~aDIR; */
1394 if (status_len == 0) {
1395 nt_status = filename_convert(ctx, conn,
1396 req->flags2 & FLAGS2_DFS_PATHNAMES,
1398 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1399 &mask_contains_wcard,
1401 if (!NT_STATUS_IS_OK(nt_status)) {
1402 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1403 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1404 ERRSRV, ERRbadpath);
1407 reply_nterror(req, nt_status);
1411 directory = smb_fname->base_name;
1413 p = strrchr_m(directory,'/');
1414 if ((p != NULL) && (*directory != '/')) {
1416 directory = talloc_strndup(ctx, directory,
1417 PTR_DIFF(p, directory));
1420 directory = talloc_strdup(ctx,".");
1424 reply_nterror(req, NT_STATUS_NO_MEMORY);
1428 memset((char *)status,'\0',21);
1429 SCVAL(status,0,(dirtype & 0x1F));
1431 nt_status = dptr_create(conn,
1437 mask_contains_wcard,
1440 if (!NT_STATUS_IS_OK(nt_status)) {
1441 reply_nterror(req, nt_status);
1444 dptr_num = dptr_dnum(dirptr);
1447 const char *dirpath;
1449 memcpy(status,p,21);
1450 status_dirtype = CVAL(status,0) & 0x1F;
1451 if (status_dirtype != (dirtype & 0x1F)) {
1452 dirtype = status_dirtype;
1455 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1459 dirpath = dptr_path(sconn, dptr_num);
1460 directory = talloc_strdup(ctx, dirpath);
1462 reply_nterror(req, NT_STATUS_NO_MEMORY);
1466 mask = dptr_wcard(sconn, dptr_num);
1471 * For a 'continue' search we have no string. So
1472 * check from the initial saved string.
1474 mask_contains_wcard = ms_has_wild(mask);
1475 dirtype = dptr_attr(sconn, dptr_num);
1478 DEBUG(4,("dptr_num is %d\n",dptr_num));
1480 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1481 dptr_init_search_op(dirptr);
1483 if ((dirtype&0x1F) == aVOLID) {
1484 char buf[DIR_STRUCT_SIZE];
1485 memcpy(buf,status,21);
1486 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1487 0,aVOLID,0,!allow_long_path_components)) {
1488 reply_nterror(req, NT_STATUS_NO_MEMORY);
1491 dptr_fill(sconn, buf+12,dptr_num);
1492 if (dptr_zero(buf+12) && (status_len==0)) {
1497 if (message_push_blob(&req->outbuf,
1498 data_blob_const(buf, sizeof(buf)))
1500 reply_nterror(req, NT_STATUS_NO_MEMORY);
1508 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1511 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1512 directory,lp_dontdescend(SNUM(conn))));
1513 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1514 check_descend = True;
1517 for (i=numentries;(i<maxentries) && !finished;i++) {
1518 finished = !get_dir_entry(ctx,
1529 char buf[DIR_STRUCT_SIZE];
1530 memcpy(buf,status,21);
1531 if (!make_dir_struct(ctx,
1537 convert_timespec_to_time_t(date),
1538 !allow_long_path_components)) {
1539 reply_nterror(req, NT_STATUS_NO_MEMORY);
1542 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1545 if (message_push_blob(&req->outbuf,
1546 data_blob_const(buf, sizeof(buf)))
1548 reply_nterror(req, NT_STATUS_NO_MEMORY);
1558 /* If we were called as SMBffirst with smb_search_id == NULL
1559 and no entries were found then return error and close dirptr
1562 if (numentries == 0) {
1563 dptr_close(sconn, &dptr_num);
1564 } else if(expect_close && status_len == 0) {
1565 /* Close the dptr - we know it's gone */
1566 dptr_close(sconn, &dptr_num);
1569 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1570 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1571 dptr_close(sconn, &dptr_num);
1574 if ((numentries == 0) && !mask_contains_wcard) {
1575 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1579 SSVAL(req->outbuf,smb_vwv0,numentries);
1580 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1581 SCVAL(smb_buf(req->outbuf),0,5);
1582 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1584 /* The replies here are never long name. */
1585 SSVAL(req->outbuf, smb_flg2,
1586 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1587 if (!allow_long_path_components) {
1588 SSVAL(req->outbuf, smb_flg2,
1589 SVAL(req->outbuf, smb_flg2)
1590 & (~FLAGS2_LONG_PATH_COMPONENTS));
1593 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1594 SSVAL(req->outbuf, smb_flg2,
1595 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1597 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1598 smb_fn_name(req->cmd),
1605 TALLOC_FREE(directory);
1606 TALLOC_FREE(smb_fname);
1607 END_PROFILE(SMBsearch);
1611 /****************************************************************************
1612 Reply to a fclose (stop directory search).
1613 ****************************************************************************/
1615 void reply_fclose(struct smb_request *req)
1623 bool path_contains_wcard = False;
1624 TALLOC_CTX *ctx = talloc_tos();
1625 struct smbd_server_connection *sconn = req->sconn;
1627 START_PROFILE(SMBfclose);
1629 if (lp_posix_pathnames()) {
1630 reply_unknown_new(req, req->cmd);
1631 END_PROFILE(SMBfclose);
1635 p = (const char *)req->buf + 1;
1636 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1637 &err, &path_contains_wcard);
1638 if (!NT_STATUS_IS_OK(err)) {
1639 reply_nterror(req, err);
1640 END_PROFILE(SMBfclose);
1644 status_len = SVAL(p,0);
1647 if (status_len == 0) {
1648 reply_force_doserror(req, ERRSRV, ERRsrverror);
1649 END_PROFILE(SMBfclose);
1653 memcpy(status,p,21);
1655 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1656 /* Close the dptr - we know it's gone */
1657 dptr_close(sconn, &dptr_num);
1660 reply_outbuf(req, 1, 0);
1661 SSVAL(req->outbuf,smb_vwv0,0);
1663 DEBUG(3,("search close\n"));
1665 END_PROFILE(SMBfclose);
1669 /****************************************************************************
1671 ****************************************************************************/
1673 void reply_open(struct smb_request *req)
1675 connection_struct *conn = req->conn;
1676 struct smb_filename *smb_fname = NULL;
1688 uint32 create_disposition;
1689 uint32 create_options = 0;
1690 uint32_t private_flags = 0;
1692 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1693 TALLOC_CTX *ctx = talloc_tos();
1695 START_PROFILE(SMBopen);
1698 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1702 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1703 deny_mode = SVAL(req->vwv+0, 0);
1704 dos_attr = SVAL(req->vwv+1, 0);
1706 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1707 STR_TERMINATE, &status);
1708 if (!NT_STATUS_IS_OK(status)) {
1709 reply_nterror(req, status);
1713 status = filename_convert(ctx,
1715 req->flags2 & FLAGS2_DFS_PATHNAMES,
1720 if (!NT_STATUS_IS_OK(status)) {
1721 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1722 reply_botherror(req,
1723 NT_STATUS_PATH_NOT_COVERED,
1724 ERRSRV, ERRbadpath);
1727 reply_nterror(req, status);
1731 if (!map_open_params_to_ntcreate(smb_fname, deny_mode,
1732 OPENX_FILE_EXISTS_OPEN, &access_mask,
1733 &share_mode, &create_disposition,
1734 &create_options, &private_flags)) {
1735 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1739 status = SMB_VFS_CREATE_FILE(
1742 0, /* root_dir_fid */
1743 smb_fname, /* fname */
1744 access_mask, /* access_mask */
1745 share_mode, /* share_access */
1746 create_disposition, /* create_disposition*/
1747 create_options, /* create_options */
1748 dos_attr, /* file_attributes */
1749 oplock_request, /* oplock_request */
1750 0, /* allocation_size */
1757 if (!NT_STATUS_IS_OK(status)) {
1758 if (open_was_deferred(req->mid)) {
1759 /* We have re-scheduled this call. */
1762 reply_openerror(req, status);
1766 size = smb_fname->st.st_ex_size;
1767 fattr = dos_mode(conn, smb_fname);
1769 /* Deal with other possible opens having a modified
1771 if (ask_sharemode) {
1772 struct timespec write_time_ts;
1774 ZERO_STRUCT(write_time_ts);
1775 get_file_infos(fsp->file_id, NULL, &write_time_ts);
1776 if (!null_timespec(write_time_ts)) {
1777 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1781 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1784 DEBUG(3,("attempt to open a directory %s\n",
1786 close_file(req, fsp, ERROR_CLOSE);
1787 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1788 ERRDOS, ERRnoaccess);
1792 reply_outbuf(req, 7, 0);
1793 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1794 SSVAL(req->outbuf,smb_vwv1,fattr);
1795 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1796 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1798 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1800 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1801 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1803 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1804 SCVAL(req->outbuf,smb_flg,
1805 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1808 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1809 SCVAL(req->outbuf,smb_flg,
1810 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1813 TALLOC_FREE(smb_fname);
1814 END_PROFILE(SMBopen);
1818 /****************************************************************************
1819 Reply to an open and X.
1820 ****************************************************************************/
1822 void reply_open_and_X(struct smb_request *req)
1824 connection_struct *conn = req->conn;
1825 struct smb_filename *smb_fname = NULL;
1830 /* Breakout the oplock request bits so we can set the
1831 reply bits separately. */
1832 int ex_oplock_request;
1833 int core_oplock_request;
1836 int smb_sattr = SVAL(req->vwv+4, 0);
1837 uint32 smb_time = make_unix_date3(req->vwv+6);
1845 uint64_t allocation_size;
1846 ssize_t retval = -1;
1849 uint32 create_disposition;
1850 uint32 create_options = 0;
1851 uint32_t private_flags = 0;
1852 TALLOC_CTX *ctx = talloc_tos();
1854 START_PROFILE(SMBopenX);
1856 if (req->wct < 15) {
1857 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1861 open_flags = SVAL(req->vwv+2, 0);
1862 deny_mode = SVAL(req->vwv+3, 0);
1863 smb_attr = SVAL(req->vwv+5, 0);
1864 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1865 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1866 oplock_request = ex_oplock_request | core_oplock_request;
1867 smb_ofun = SVAL(req->vwv+8, 0);
1868 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1870 /* If it's an IPC, pass off the pipe handler. */
1872 if (lp_nt_pipe_support()) {
1873 reply_open_pipe_and_X(conn, req);
1875 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1880 /* XXXX we need to handle passed times, sattr and flags */
1881 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1882 STR_TERMINATE, &status);
1883 if (!NT_STATUS_IS_OK(status)) {
1884 reply_nterror(req, status);
1888 status = filename_convert(ctx,
1890 req->flags2 & FLAGS2_DFS_PATHNAMES,
1895 if (!NT_STATUS_IS_OK(status)) {
1896 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1897 reply_botherror(req,
1898 NT_STATUS_PATH_NOT_COVERED,
1899 ERRSRV, ERRbadpath);
1902 reply_nterror(req, status);
1906 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, smb_ofun,
1907 &access_mask, &share_mode,
1908 &create_disposition,
1911 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1915 status = SMB_VFS_CREATE_FILE(
1918 0, /* root_dir_fid */
1919 smb_fname, /* fname */
1920 access_mask, /* access_mask */
1921 share_mode, /* share_access */
1922 create_disposition, /* create_disposition*/
1923 create_options, /* create_options */
1924 smb_attr, /* file_attributes */
1925 oplock_request, /* oplock_request */
1926 0, /* allocation_size */
1931 &smb_action); /* pinfo */
1933 if (!NT_STATUS_IS_OK(status)) {
1934 if (open_was_deferred(req->mid)) {
1935 /* We have re-scheduled this call. */
1938 reply_openerror(req, status);
1942 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1943 if the file is truncated or created. */
1944 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1945 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1946 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1947 close_file(req, fsp, ERROR_CLOSE);
1948 reply_nterror(req, NT_STATUS_DISK_FULL);
1951 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1953 close_file(req, fsp, ERROR_CLOSE);
1954 reply_nterror(req, NT_STATUS_DISK_FULL);
1957 smb_fname->st.st_ex_size =
1958 SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
1961 fattr = dos_mode(conn, smb_fname);
1962 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1964 close_file(req, fsp, ERROR_CLOSE);
1965 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1969 /* If the caller set the extended oplock request bit
1970 and we granted one (by whatever means) - set the
1971 correct bit for extended oplock reply.
1974 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1975 smb_action |= EXTENDED_OPLOCK_GRANTED;
1978 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1979 smb_action |= EXTENDED_OPLOCK_GRANTED;
1982 /* If the caller set the core oplock request bit
1983 and we granted one (by whatever means) - set the
1984 correct bit for core oplock reply.
1987 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1988 reply_outbuf(req, 19, 0);
1990 reply_outbuf(req, 15, 0);
1993 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1994 SCVAL(req->outbuf, smb_flg,
1995 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1998 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1999 SCVAL(req->outbuf, smb_flg,
2000 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2003 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2004 SSVAL(req->outbuf,smb_vwv3,fattr);
2005 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2006 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2008 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2010 SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size);
2011 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2012 SSVAL(req->outbuf,smb_vwv11,smb_action);
2014 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2015 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2020 TALLOC_FREE(smb_fname);
2021 END_PROFILE(SMBopenX);
2025 /****************************************************************************
2026 Reply to a SMBulogoffX.
2027 ****************************************************************************/
2029 void reply_ulogoffX(struct smb_request *req)
2031 struct smbd_server_connection *sconn = req->sconn;
2034 START_PROFILE(SMBulogoffX);
2036 vuser = get_valid_user_struct(sconn, req->vuid);
2039 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2043 /* in user level security we are supposed to close any files
2044 open by this user */
2045 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2046 file_close_user(req->vuid);
2049 invalidate_vuid(sconn, req->vuid);
2051 reply_outbuf(req, 2, 0);
2053 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2055 END_PROFILE(SMBulogoffX);
2056 req->vuid = UID_FIELD_INVALID;
2060 /****************************************************************************
2061 Reply to a mknew or a create.
2062 ****************************************************************************/
2064 void reply_mknew(struct smb_request *req)
2066 connection_struct *conn = req->conn;
2067 struct smb_filename *smb_fname = NULL;
2070 struct smb_file_time ft;
2072 int oplock_request = 0;
2074 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2075 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2076 uint32 create_disposition;
2077 uint32 create_options = 0;
2078 TALLOC_CTX *ctx = talloc_tos();
2080 START_PROFILE(SMBcreate);
2084 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2088 fattr = SVAL(req->vwv+0, 0);
2089 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2092 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2094 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2095 STR_TERMINATE, &status);
2096 if (!NT_STATUS_IS_OK(status)) {
2097 reply_nterror(req, status);
2101 status = filename_convert(ctx,
2103 req->flags2 & FLAGS2_DFS_PATHNAMES,
2108 if (!NT_STATUS_IS_OK(status)) {
2109 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2110 reply_botherror(req,
2111 NT_STATUS_PATH_NOT_COVERED,
2112 ERRSRV, ERRbadpath);
2115 reply_nterror(req, status);
2119 if (fattr & aVOLID) {
2120 DEBUG(0,("Attempt to create file (%s) with volid set - "
2121 "please report this\n",
2122 smb_fname_str_dbg(smb_fname)));
2125 if(req->cmd == SMBmknew) {
2126 /* We should fail if file exists. */
2127 create_disposition = FILE_CREATE;
2129 /* Create if file doesn't exist, truncate if it does. */
2130 create_disposition = FILE_OVERWRITE_IF;
2133 status = SMB_VFS_CREATE_FILE(
2136 0, /* root_dir_fid */
2137 smb_fname, /* fname */
2138 access_mask, /* access_mask */
2139 share_mode, /* share_access */
2140 create_disposition, /* create_disposition*/
2141 create_options, /* create_options */
2142 fattr, /* file_attributes */
2143 oplock_request, /* oplock_request */
2144 0, /* allocation_size */
2145 0, /* private_flags */
2151 if (!NT_STATUS_IS_OK(status)) {
2152 if (open_was_deferred(req->mid)) {
2153 /* We have re-scheduled this call. */
2156 reply_openerror(req, status);
2160 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2161 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2162 if (!NT_STATUS_IS_OK(status)) {
2163 END_PROFILE(SMBcreate);
2167 reply_outbuf(req, 1, 0);
2168 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2170 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2171 SCVAL(req->outbuf,smb_flg,
2172 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2175 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2176 SCVAL(req->outbuf,smb_flg,
2177 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2180 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2181 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2182 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2183 (unsigned int)fattr));
2186 TALLOC_FREE(smb_fname);
2187 END_PROFILE(SMBcreate);
2191 /****************************************************************************
2192 Reply to a create temporary file.
2193 ****************************************************************************/
2195 void reply_ctemp(struct smb_request *req)
2197 connection_struct *conn = req->conn;
2198 struct smb_filename *smb_fname = NULL;
2206 TALLOC_CTX *ctx = talloc_tos();
2208 START_PROFILE(SMBctemp);
2211 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2215 fattr = SVAL(req->vwv+0, 0);
2216 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2218 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2219 STR_TERMINATE, &status);
2220 if (!NT_STATUS_IS_OK(status)) {
2221 reply_nterror(req, status);
2225 fname = talloc_asprintf(ctx,
2229 fname = talloc_strdup(ctx, "TMXXXXXX");
2233 reply_nterror(req, NT_STATUS_NO_MEMORY);
2237 status = filename_convert(ctx, conn,
2238 req->flags2 & FLAGS2_DFS_PATHNAMES,
2243 if (!NT_STATUS_IS_OK(status)) {
2244 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2245 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2246 ERRSRV, ERRbadpath);
2249 reply_nterror(req, status);
2253 tmpfd = mkstemp(smb_fname->base_name);
2255 reply_nterror(req, map_nt_error_from_unix(errno));
2259 SMB_VFS_STAT(conn, smb_fname);
2261 /* We should fail if file does not exist. */
2262 status = SMB_VFS_CREATE_FILE(
2265 0, /* root_dir_fid */
2266 smb_fname, /* fname */
2267 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2268 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2269 FILE_OPEN, /* create_disposition*/
2270 0, /* create_options */
2271 fattr, /* file_attributes */
2272 oplock_request, /* oplock_request */
2273 0, /* allocation_size */
2274 0, /* private_flags */
2280 /* close fd from mkstemp() */
2283 if (!NT_STATUS_IS_OK(status)) {
2284 if (open_was_deferred(req->mid)) {
2285 /* We have re-scheduled this call. */
2288 reply_openerror(req, status);
2292 reply_outbuf(req, 1, 0);
2293 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2295 /* the returned filename is relative to the directory */
2296 s = strrchr_m(fsp->fsp_name->base_name, '/');
2298 s = fsp->fsp_name->base_name;
2304 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2305 thing in the byte section. JRA */
2306 SSVALS(p, 0, -1); /* what is this? not in spec */
2308 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2310 reply_nterror(req, NT_STATUS_NO_MEMORY);
2314 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2315 SCVAL(req->outbuf, smb_flg,
2316 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2319 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2320 SCVAL(req->outbuf, smb_flg,
2321 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2324 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2325 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2326 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2328 TALLOC_FREE(smb_fname);
2329 END_PROFILE(SMBctemp);
2333 /*******************************************************************
2334 Check if a user is allowed to rename a file.
2335 ********************************************************************/
2337 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2342 if (!CAN_WRITE(conn)) {
2343 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2346 fmode = dos_mode(conn, fsp->fsp_name);
2347 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2348 return NT_STATUS_NO_SUCH_FILE;
2351 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2352 if (fsp->posix_open) {
2353 return NT_STATUS_OK;
2356 /* If no pathnames are open below this
2357 directory, allow the rename. */
2359 if (file_find_subpath(fsp)) {
2360 return NT_STATUS_ACCESS_DENIED;
2362 return NT_STATUS_OK;
2365 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2366 return NT_STATUS_OK;
2369 return NT_STATUS_ACCESS_DENIED;
2372 /*******************************************************************
2373 * unlink a file with all relevant access checks
2374 *******************************************************************/
2376 static NTSTATUS do_unlink(connection_struct *conn,
2377 struct smb_request *req,
2378 struct smb_filename *smb_fname,
2383 uint32 dirtype_orig = dirtype;
2386 bool posix_paths = lp_posix_pathnames();
2388 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2389 smb_fname_str_dbg(smb_fname),
2392 if (!CAN_WRITE(conn)) {
2393 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2397 ret = SMB_VFS_LSTAT(conn, smb_fname);
2399 ret = SMB_VFS_STAT(conn, smb_fname);
2402 return map_nt_error_from_unix(errno);
2405 fattr = dos_mode(conn, smb_fname);
2407 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2408 dirtype = aDIR|aARCH|aRONLY;
2411 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2413 return NT_STATUS_NO_SUCH_FILE;
2416 if (!dir_check_ftype(conn, fattr, dirtype)) {
2418 return NT_STATUS_FILE_IS_A_DIRECTORY;
2420 return NT_STATUS_NO_SUCH_FILE;
2423 if (dirtype_orig & 0x8000) {
2424 /* These will never be set for POSIX. */
2425 return NT_STATUS_NO_SUCH_FILE;
2429 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2430 return NT_STATUS_FILE_IS_A_DIRECTORY;
2433 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2434 return NT_STATUS_NO_SUCH_FILE;
2437 if (dirtype & 0xFF00) {
2438 /* These will never be set for POSIX. */
2439 return NT_STATUS_NO_SUCH_FILE;
2444 return NT_STATUS_NO_SUCH_FILE;
2447 /* Can't delete a directory. */
2449 return NT_STATUS_FILE_IS_A_DIRECTORY;
2454 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2455 return NT_STATUS_OBJECT_NAME_INVALID;
2456 #endif /* JRATEST */
2458 /* On open checks the open itself will check the share mode, so
2459 don't do it here as we'll get it wrong. */
2461 status = SMB_VFS_CREATE_FILE
2464 0, /* root_dir_fid */
2465 smb_fname, /* fname */
2466 DELETE_ACCESS, /* access_mask */
2467 FILE_SHARE_NONE, /* share_access */
2468 FILE_OPEN, /* create_disposition*/
2469 FILE_NON_DIRECTORY_FILE, /* create_options */
2470 /* file_attributes */
2471 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2472 FILE_ATTRIBUTE_NORMAL,
2473 0, /* oplock_request */
2474 0, /* allocation_size */
2475 0, /* private_flags */
2481 if (!NT_STATUS_IS_OK(status)) {
2482 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2483 nt_errstr(status)));
2487 status = can_set_delete_on_close(fsp, fattr);
2488 if (!NT_STATUS_IS_OK(status)) {
2489 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2491 smb_fname_str_dbg(smb_fname),
2492 nt_errstr(status)));
2493 close_file(req, fsp, NORMAL_CLOSE);
2497 /* The set is across all open files on this dev/inode pair. */
2498 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2499 close_file(req, fsp, NORMAL_CLOSE);
2500 return NT_STATUS_ACCESS_DENIED;
2503 return close_file(req, fsp, NORMAL_CLOSE);
2506 /****************************************************************************
2507 The guts of the unlink command, split out so it may be called by the NT SMB
2509 ****************************************************************************/
2511 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2512 uint32 dirtype, struct smb_filename *smb_fname,
2515 char *fname_dir = NULL;
2516 char *fname_mask = NULL;
2518 NTSTATUS status = NT_STATUS_OK;
2519 TALLOC_CTX *ctx = talloc_tos();
2521 /* Split up the directory from the filename/mask. */
2522 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2523 &fname_dir, &fname_mask);
2524 if (!NT_STATUS_IS_OK(status)) {
2529 * We should only check the mangled cache
2530 * here if unix_convert failed. This means
2531 * that the path in 'mask' doesn't exist
2532 * on the file system and so we need to look
2533 * for a possible mangle. This patch from
2534 * Tine Smukavec <valentin.smukavec@hermes.si>.
2537 if (!VALID_STAT(smb_fname->st) &&
2538 mangle_is_mangled(fname_mask, conn->params)) {
2539 char *new_mask = NULL;
2540 mangle_lookup_name_from_8_3(ctx, fname_mask,
2541 &new_mask, conn->params);
2543 TALLOC_FREE(fname_mask);
2544 fname_mask = new_mask;
2551 * Only one file needs to be unlinked. Append the mask back
2552 * onto the directory.
2554 TALLOC_FREE(smb_fname->base_name);
2555 smb_fname->base_name = talloc_asprintf(smb_fname,
2559 if (!smb_fname->base_name) {
2560 status = NT_STATUS_NO_MEMORY;
2564 dirtype = FILE_ATTRIBUTE_NORMAL;
2567 status = check_name(conn, smb_fname->base_name);
2568 if (!NT_STATUS_IS_OK(status)) {
2572 status = do_unlink(conn, req, smb_fname, dirtype);
2573 if (!NT_STATUS_IS_OK(status)) {
2579 struct smb_Dir *dir_hnd = NULL;
2581 const char *dname = NULL;
2582 char *talloced = NULL;
2584 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2585 status = NT_STATUS_OBJECT_NAME_INVALID;
2589 if (strequal(fname_mask,"????????.???")) {
2590 TALLOC_FREE(fname_mask);
2591 fname_mask = talloc_strdup(ctx, "*");
2593 status = NT_STATUS_NO_MEMORY;
2598 status = check_name(conn, fname_dir);
2599 if (!NT_STATUS_IS_OK(status)) {
2603 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2605 if (dir_hnd == NULL) {
2606 status = map_nt_error_from_unix(errno);
2610 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2611 the pattern matches against the long name, otherwise the short name
2612 We don't implement this yet XXXX
2615 status = NT_STATUS_NO_SUCH_FILE;
2617 while ((dname = ReadDirName(dir_hnd, &offset,
2618 &smb_fname->st, &talloced))) {
2619 TALLOC_CTX *frame = talloc_stackframe();
2621 if (!is_visible_file(conn, fname_dir, dname,
2622 &smb_fname->st, true)) {
2624 TALLOC_FREE(talloced);
2628 /* Quick check for "." and ".." */
2629 if (ISDOT(dname) || ISDOTDOT(dname)) {
2631 TALLOC_FREE(talloced);
2635 if(!mask_match(dname, fname_mask,
2636 conn->case_sensitive)) {
2638 TALLOC_FREE(talloced);
2642 TALLOC_FREE(smb_fname->base_name);
2643 smb_fname->base_name =
2644 talloc_asprintf(smb_fname, "%s/%s",
2647 if (!smb_fname->base_name) {
2648 TALLOC_FREE(dir_hnd);
2649 status = NT_STATUS_NO_MEMORY;
2651 TALLOC_FREE(talloced);
2655 status = check_name(conn, smb_fname->base_name);
2656 if (!NT_STATUS_IS_OK(status)) {
2657 TALLOC_FREE(dir_hnd);
2659 TALLOC_FREE(talloced);
2663 status = do_unlink(conn, req, smb_fname, dirtype);
2664 if (!NT_STATUS_IS_OK(status)) {
2666 TALLOC_FREE(talloced);
2671 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2672 smb_fname->base_name));
2675 TALLOC_FREE(talloced);
2677 TALLOC_FREE(dir_hnd);
2680 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2681 status = map_nt_error_from_unix(errno);
2685 TALLOC_FREE(fname_dir);
2686 TALLOC_FREE(fname_mask);
2690 /****************************************************************************
2692 ****************************************************************************/
2694 void reply_unlink(struct smb_request *req)
2696 connection_struct *conn = req->conn;
2698 struct smb_filename *smb_fname = NULL;
2701 bool path_contains_wcard = False;
2702 TALLOC_CTX *ctx = talloc_tos();
2704 START_PROFILE(SMBunlink);
2707 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2711 dirtype = SVAL(req->vwv+0, 0);
2713 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2714 STR_TERMINATE, &status,
2715 &path_contains_wcard);
2716 if (!NT_STATUS_IS_OK(status)) {
2717 reply_nterror(req, status);
2721 status = filename_convert(ctx, conn,
2722 req->flags2 & FLAGS2_DFS_PATHNAMES,
2724 UCF_COND_ALLOW_WCARD_LCOMP,
2725 &path_contains_wcard,
2727 if (!NT_STATUS_IS_OK(status)) {
2728 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2729 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2730 ERRSRV, ERRbadpath);
2733 reply_nterror(req, status);
2737 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2739 status = unlink_internals(conn, req, dirtype, smb_fname,
2740 path_contains_wcard);
2741 if (!NT_STATUS_IS_OK(status)) {
2742 if (open_was_deferred(req->mid)) {
2743 /* We have re-scheduled this call. */
2746 reply_nterror(req, status);
2750 reply_outbuf(req, 0, 0);
2752 TALLOC_FREE(smb_fname);
2753 END_PROFILE(SMBunlink);
2757 /****************************************************************************
2759 ****************************************************************************/
2761 static void fail_readraw(void)
2763 const char *errstr = talloc_asprintf(talloc_tos(),
2764 "FAIL ! reply_readbraw: socket write fail (%s)",
2769 exit_server_cleanly(errstr);
2772 /****************************************************************************
2773 Fake (read/write) sendfile. Returns -1 on read or write fail.
2774 ****************************************************************************/
2776 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2780 size_t tosend = nread;
2787 bufsize = MIN(nread, 65536);
2789 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2793 while (tosend > 0) {
2797 if (tosend > bufsize) {
2802 ret = read_file(fsp,buf,startpos,cur_read);
2808 /* If we had a short read, fill with zeros. */
2809 if (ret < cur_read) {
2810 memset(buf + ret, '\0', cur_read - ret);
2813 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
2815 char addr[INET6_ADDRSTRLEN];
2817 * Try and give an error message saying what
2820 DEBUG(0, ("write_data failed for client %s. "
2822 get_peer_addr(fsp->conn->sconn->sock, addr,
2829 startpos += cur_read;
2833 return (ssize_t)nread;
2836 #if defined(WITH_SENDFILE)
2837 /****************************************************************************
2838 Deal with the case of sendfile reading less bytes from the file than
2839 requested. Fill with zeros (all we can do).
2840 ****************************************************************************/
2842 static void sendfile_short_send(files_struct *fsp,
2847 #define SHORT_SEND_BUFSIZE 1024
2848 if (nread < headersize) {
2849 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2850 "header for file %s (%s). Terminating\n",
2851 fsp_str_dbg(fsp), strerror(errno)));
2852 exit_server_cleanly("sendfile_short_send failed");
2855 nread -= headersize;
2857 if (nread < smb_maxcnt) {
2858 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2860 exit_server_cleanly("sendfile_short_send: "
2864 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2865 "with zeros !\n", fsp_str_dbg(fsp)));
2867 while (nread < smb_maxcnt) {
2869 * We asked for the real file size and told sendfile
2870 * to not go beyond the end of the file. But it can
2871 * happen that in between our fstat call and the
2872 * sendfile call the file was truncated. This is very
2873 * bad because we have already announced the larger
2874 * number of bytes to the client.
2876 * The best we can do now is to send 0-bytes, just as
2877 * a read from a hole in a sparse file would do.
2879 * This should happen rarely enough that I don't care
2880 * about efficiency here :-)
2884 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2885 if (write_data(fsp->conn->sconn->sock, buf, to_write)
2887 char addr[INET6_ADDRSTRLEN];
2889 * Try and give an error message saying what
2892 DEBUG(0, ("write_data failed for client %s. "
2895 fsp->conn->sconn->sock, addr,
2898 exit_server_cleanly("sendfile_short_send: "
2899 "write_data failed");
2906 #endif /* defined WITH_SENDFILE */
2908 /****************************************************************************
2909 Return a readbraw error (4 bytes of zero).
2910 ****************************************************************************/
2912 static void reply_readbraw_error(struct smbd_server_connection *sconn)
2918 smbd_lock_socket(sconn);
2919 if (write_data(sconn->sock,header,4) != 4) {
2920 char addr[INET6_ADDRSTRLEN];
2922 * Try and give an error message saying what
2925 DEBUG(0, ("write_data failed for client %s. "
2927 get_peer_addr(sconn->sock, addr, sizeof(addr)),
2932 smbd_unlock_socket(sconn);
2935 /****************************************************************************
2936 Use sendfile in readbraw.
2937 ****************************************************************************/
2939 static void send_file_readbraw(connection_struct *conn,
2940 struct smb_request *req,
2946 struct smbd_server_connection *sconn = req->sconn;
2947 char *outbuf = NULL;
2950 #if defined(WITH_SENDFILE)
2952 * We can only use sendfile on a non-chained packet
2953 * but we can use on a non-oplocked file. tridge proved this
2954 * on a train in Germany :-). JRA.
2955 * reply_readbraw has already checked the length.
2958 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2959 (fsp->wcp == NULL) &&
2960 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
2961 ssize_t sendfile_read = -1;
2963 DATA_BLOB header_blob;
2965 _smb_setlen(header,nread);
2966 header_blob = data_blob_const(header, 4);
2968 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
2969 &header_blob, startpos,
2971 if (sendfile_read == -1) {
2972 /* Returning ENOSYS means no data at all was sent.
2973 * Do this as a normal read. */
2974 if (errno == ENOSYS) {
2975 goto normal_readbraw;
2979 * Special hack for broken Linux with no working sendfile. If we
2980 * return EINTR we sent the header but not the rest of the data.
2981 * Fake this up by doing read/write calls.
2983 if (errno == EINTR) {
2984 /* Ensure we don't do this again. */
2985 set_use_sendfile(SNUM(conn), False);
2986 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2988 if (fake_sendfile(fsp, startpos, nread) == -1) {
2989 DEBUG(0,("send_file_readbraw: "
2990 "fake_sendfile failed for "
2994 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2999 DEBUG(0,("send_file_readbraw: sendfile failed for "
3000 "file %s (%s). Terminating\n",
3001 fsp_str_dbg(fsp), strerror(errno)));
3002 exit_server_cleanly("send_file_readbraw sendfile failed");
3003 } else if (sendfile_read == 0) {
3005 * Some sendfile implementations return 0 to indicate
3006 * that there was a short read, but nothing was
3007 * actually written to the socket. In this case,
3008 * fallback to the normal read path so the header gets
3009 * the correct byte count.
3011 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3012 "bytes falling back to the normal read: "
3013 "%s\n", fsp_str_dbg(fsp)));
3014 goto normal_readbraw;
3017 /* Deal with possible short send. */
3018 if (sendfile_read != 4+nread) {
3019 sendfile_short_send(fsp, sendfile_read, 4, nread);
3027 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
3029 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
3030 (unsigned)(nread+4)));
3031 reply_readbraw_error(sconn);
3036 ret = read_file(fsp,outbuf+4,startpos,nread);
3037 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3046 _smb_setlen(outbuf,ret);
3047 if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
3048 char addr[INET6_ADDRSTRLEN];
3050 * Try and give an error message saying what
3053 DEBUG(0, ("write_data failed for client %s. "
3055 get_peer_addr(fsp->conn->sconn->sock, addr,
3062 TALLOC_FREE(outbuf);
3065 /****************************************************************************
3066 Reply to a readbraw (core+ protocol).
3067 ****************************************************************************/
3069 void reply_readbraw(struct smb_request *req)
3071 connection_struct *conn = req->conn;
3072 struct smbd_server_connection *sconn = req->sconn;
3073 ssize_t maxcount,mincount;
3077 struct lock_struct lock;
3080 START_PROFILE(SMBreadbraw);
3082 if (srv_is_signing_active(sconn) ||
3083 is_encrypted_packet(req->inbuf)) {
3084 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3085 "raw reads/writes are disallowed.");
3089 reply_readbraw_error(sconn);
3090 END_PROFILE(SMBreadbraw);
3094 if (sconn->smb1.echo_handler.trusted_fde) {
3095 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3096 "'async smb echo handler = yes'\n"));
3097 reply_readbraw_error(sconn);
3098 END_PROFILE(SMBreadbraw);
3103 * Special check if an oplock break has been issued
3104 * and the readraw request croses on the wire, we must
3105 * return a zero length response here.
3108 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3111 * We have to do a check_fsp by hand here, as
3112 * we must always return 4 zero bytes on error,
3116 if (!fsp || !conn || conn != fsp->conn ||
3117 req->vuid != fsp->vuid ||
3118 fsp->is_directory || fsp->fh->fd == -1) {
3120 * fsp could be NULL here so use the value from the packet. JRA.
3122 DEBUG(3,("reply_readbraw: fnum %d not valid "
3124 (int)SVAL(req->vwv+0, 0)));
3125 reply_readbraw_error(sconn);
3126 END_PROFILE(SMBreadbraw);
3130 /* Do a "by hand" version of CHECK_READ. */
3131 if (!(fsp->can_read ||
3132 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3133 (fsp->access_mask & FILE_EXECUTE)))) {
3134 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3135 (int)SVAL(req->vwv+0, 0)));
3136 reply_readbraw_error(sconn);
3137 END_PROFILE(SMBreadbraw);
3141 flush_write_cache(fsp, READRAW_FLUSH);
3143 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3144 if(req->wct == 10) {
3146 * This is a large offset (64 bit) read.
3148 #ifdef LARGE_SMB_OFF_T
3150 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3152 #else /* !LARGE_SMB_OFF_T */
3155 * Ensure we haven't been sent a >32 bit offset.
3158 if(IVAL(req->vwv+8, 0) != 0) {
3159 DEBUG(0,("reply_readbraw: large offset "
3160 "(%x << 32) used and we don't support "
3161 "64 bit offsets.\n",
3162 (unsigned int)IVAL(req->vwv+8, 0) ));
3163 reply_readbraw_error();
3164 END_PROFILE(SMBreadbraw);
3168 #endif /* LARGE_SMB_OFF_T */
3171 DEBUG(0,("reply_readbraw: negative 64 bit "
3172 "readraw offset (%.0f) !\n",
3173 (double)startpos ));
3174 reply_readbraw_error(sconn);
3175 END_PROFILE(SMBreadbraw);
3180 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3181 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3183 /* ensure we don't overrun the packet size */
3184 maxcount = MIN(65535,maxcount);
3186 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3187 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3190 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3191 reply_readbraw_error(sconn);
3192 END_PROFILE(SMBreadbraw);
3196 if (fsp_stat(fsp) == 0) {
3197 size = fsp->fsp_name->st.st_ex_size;
3200 if (startpos >= size) {
3203 nread = MIN(maxcount,(size - startpos));
3206 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3207 if (nread < mincount)
3211 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3212 "min=%lu nread=%lu\n",
3213 fsp->fnum, (double)startpos,
3214 (unsigned long)maxcount,
3215 (unsigned long)mincount,
3216 (unsigned long)nread ) );
3218 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3220 DEBUG(5,("reply_readbraw finished\n"));
3222 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3224 END_PROFILE(SMBreadbraw);
3229 #define DBGC_CLASS DBGC_LOCKING
3231 /****************************************************************************
3232 Reply to a lockread (core+ protocol).
3233 ****************************************************************************/
3235 void reply_lockread(struct smb_request *req)
3237 connection_struct *conn = req->conn;
3244 struct byte_range_lock *br_lck = NULL;
3246 struct smbd_server_connection *sconn = req->sconn;
3248 START_PROFILE(SMBlockread);
3251 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3252 END_PROFILE(SMBlockread);
3256 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3258 if (!check_fsp(conn, req, fsp)) {
3259 END_PROFILE(SMBlockread);
3263 if (!CHECK_READ(fsp,req)) {
3264 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3265 END_PROFILE(SMBlockread);
3269 numtoread = SVAL(req->vwv+1, 0);
3270 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3272 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3274 reply_outbuf(req, 5, numtoread + 3);
3276 data = smb_buf(req->outbuf) + 3;
3279 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3280 * protocol request that predates the read/write lock concept.
3281 * Thus instead of asking for a read lock here we need to ask
3282 * for a write lock. JRA.
3283 * Note that the requested lock size is unaffected by max_recv.
3286 br_lck = do_lock(req->sconn->msg_ctx,
3288 (uint64_t)req->smbpid,
3289 (uint64_t)numtoread,
3293 False, /* Non-blocking lock. */
3297 TALLOC_FREE(br_lck);
3299 if (NT_STATUS_V(status)) {
3300 reply_nterror(req, status);
3301 END_PROFILE(SMBlockread);
3306 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3309 if (numtoread > sconn->smb1.negprot.max_recv) {
3310 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3311 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3312 (unsigned int)numtoread,
3313 (unsigned int)sconn->smb1.negprot.max_recv));
3314 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3316 nread = read_file(fsp,data,startpos,numtoread);
3319 reply_nterror(req, map_nt_error_from_unix(errno));
3320 END_PROFILE(SMBlockread);
3324 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3326 SSVAL(req->outbuf,smb_vwv0,nread);
3327 SSVAL(req->outbuf,smb_vwv5,nread+3);
3328 p = smb_buf(req->outbuf);
3329 SCVAL(p,0,0); /* pad byte. */
3332 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3333 fsp->fnum, (int)numtoread, (int)nread));
3335 END_PROFILE(SMBlockread);
3340 #define DBGC_CLASS DBGC_ALL
3342 /****************************************************************************
3344 ****************************************************************************/
3346 void reply_read(struct smb_request *req)
3348 connection_struct *conn = req->conn;
3355 struct lock_struct lock;
3356 struct smbd_server_connection *sconn = req->sconn;
3358 START_PROFILE(SMBread);
3361 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3362 END_PROFILE(SMBread);
3366 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3368 if (!check_fsp(conn, req, fsp)) {
3369 END_PROFILE(SMBread);
3373 if (!CHECK_READ(fsp,req)) {
3374 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3375 END_PROFILE(SMBread);
3379 numtoread = SVAL(req->vwv+1, 0);
3380 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3382 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3385 * The requested read size cannot be greater than max_recv. JRA.
3387 if (numtoread > sconn->smb1.negprot.max_recv) {
3388 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3389 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3390 (unsigned int)numtoread,
3391 (unsigned int)sconn->smb1.negprot.max_recv));
3392 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3395 reply_outbuf(req, 5, numtoread+3);
3397 data = smb_buf(req->outbuf) + 3;
3399 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3400 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3403 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3404 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3405 END_PROFILE(SMBread);
3410 nread = read_file(fsp,data,startpos,numtoread);
3413 reply_nterror(req, map_nt_error_from_unix(errno));
3417 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3419 SSVAL(req->outbuf,smb_vwv0,nread);
3420 SSVAL(req->outbuf,smb_vwv5,nread+3);
3421 SCVAL(smb_buf(req->outbuf),0,1);
3422 SSVAL(smb_buf(req->outbuf),1,nread);
3424 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3425 fsp->fnum, (int)numtoread, (int)nread ) );
3428 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3430 END_PROFILE(SMBread);
3434 /****************************************************************************
3436 ****************************************************************************/
3438 static int setup_readX_header(struct smb_request *req, char *outbuf,
3444 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3445 data = smb_buf(outbuf);
3447 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3449 SCVAL(outbuf,smb_vwv0,0xFF);
3450 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3451 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3452 SSVAL(outbuf,smb_vwv6,
3454 + 1 /* the wct field */
3455 + 12 * sizeof(uint16_t) /* vwv */
3456 + 2); /* the buflen field */
3457 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3458 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3459 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3460 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3464 /****************************************************************************
3465 Reply to a read and X - possibly using sendfile.
3466 ****************************************************************************/
3468 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3469 files_struct *fsp, SMB_OFF_T startpos,
3473 struct lock_struct lock;
3474 int saved_errno = 0;
3476 if(fsp_stat(fsp) == -1) {
3477 reply_nterror(req, map_nt_error_from_unix(errno));
3481 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3482 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3485 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3486 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3490 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3491 (startpos > fsp->fsp_name->st.st_ex_size)
3492 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3494 * We already know that we would do a short read, so don't
3495 * try the sendfile() path.
3497 goto nosendfile_read;
3500 #if defined(WITH_SENDFILE)
3502 * We can only use sendfile on a non-chained packet
3503 * but we can use on a non-oplocked file. tridge proved this
3504 * on a train in Germany :-). JRA.
3507 if (!req_is_in_chain(req) &&
3508 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3509 (fsp->wcp == NULL) &&
3510 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3511 uint8 headerbuf[smb_size + 12 * 2];
3515 * Set up the packet header before send. We
3516 * assume here the sendfile will work (get the
3517 * correct amount of data).
3520 header = data_blob_const(headerbuf, sizeof(headerbuf));
3522 construct_reply_common_req(req, (char *)headerbuf);
3523 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3525 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3526 startpos, smb_maxcnt);
3528 /* Returning ENOSYS means no data at all was sent.
3529 Do this as a normal read. */
3530 if (errno == ENOSYS) {
3535 * Special hack for broken Linux with no working sendfile. If we
3536 * return EINTR we sent the header but not the rest of the data.
3537 * Fake this up by doing read/write calls.
3540 if (errno == EINTR) {
3541 /* Ensure we don't do this again. */
3542 set_use_sendfile(SNUM(conn), False);
3543 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3544 nread = fake_sendfile(fsp, startpos,
3547 DEBUG(0,("send_file_readX: "
3548 "fake_sendfile failed for "
3552 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3554 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3555 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3556 /* No outbuf here means successful sendfile. */
3560 DEBUG(0,("send_file_readX: sendfile failed for file "
3561 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3563 exit_server_cleanly("send_file_readX sendfile failed");
3564 } else if (nread == 0) {
3566 * Some sendfile implementations return 0 to indicate
3567 * that there was a short read, but nothing was
3568 * actually written to the socket. In this case,
3569 * fallback to the normal read path so the header gets
3570 * the correct byte count.
3572 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3573 "falling back to the normal read: %s\n",
3578 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3579 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3581 /* Deal with possible short send. */
3582 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3583 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3585 /* No outbuf here means successful sendfile. */
3586 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3587 SMB_PERFCOUNT_END(&req->pcd);
3595 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3596 uint8 headerbuf[smb_size + 2*12];
3598 construct_reply_common_req(req, (char *)headerbuf);
3599 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3601 /* Send out the header. */
3602 if (write_data(req->sconn->sock, (char *)headerbuf,
3603 sizeof(headerbuf)) != sizeof(headerbuf)) {
3605 char addr[INET6_ADDRSTRLEN];
3607 * Try and give an error message saying what
3610 DEBUG(0, ("write_data failed for client %s. "
3612 get_peer_addr(req->sconn->sock, addr,
3616 DEBUG(0,("send_file_readX: write_data failed for file "
3617 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3619 exit_server_cleanly("send_file_readX sendfile failed");
3621 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3623 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3624 "file %s (%s).\n", fsp_str_dbg(fsp),
3626 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3633 reply_outbuf(req, 12, smb_maxcnt);
3635 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3636 saved_errno = errno;
3638 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3641 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3645 setup_readX_header(req, (char *)req->outbuf, nread);
3647 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3648 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3654 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3655 TALLOC_FREE(req->outbuf);
3659 /****************************************************************************
3660 Reply to a read and X.
3661 ****************************************************************************/
3663 void reply_read_and_X(struct smb_request *req)
3665 connection_struct *conn = req->conn;
3669 bool big_readX = False;
3671 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3674 START_PROFILE(SMBreadX);
3676 if ((req->wct != 10) && (req->wct != 12)) {
3677 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3681 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3682 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3683 smb_maxcnt = SVAL(req->vwv+5, 0);
3685 /* If it's an IPC, pass off the pipe handler. */
3687 reply_pipe_read_and_X(req);
3688 END_PROFILE(SMBreadX);
3692 if (!check_fsp(conn, req, fsp)) {
3693 END_PROFILE(SMBreadX);
3697 if (!CHECK_READ(fsp,req)) {
3698 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3699 END_PROFILE(SMBreadX);
3703 if (global_client_caps & CAP_LARGE_READX) {
3704 size_t upper_size = SVAL(req->vwv+7, 0);
3705 smb_maxcnt |= (upper_size<<16);
3706 if (upper_size > 1) {
3707 /* Can't do this on a chained packet. */
3708 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3709 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3710 END_PROFILE(SMBreadX);
3713 /* We currently don't do this on signed or sealed data. */
3714 if (srv_is_signing_active(req->sconn) ||
3715 is_encrypted_packet(req->inbuf)) {
3716 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3717 END_PROFILE(SMBreadX);
3720 /* Is there room in the reply for this data ? */
3721 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3723 NT_STATUS_INVALID_PARAMETER);
3724 END_PROFILE(SMBreadX);
3731 if (req->wct == 12) {
3732 #ifdef LARGE_SMB_OFF_T
3734 * This is a large offset (64 bit) read.
3736 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3738 #else /* !LARGE_SMB_OFF_T */
3741 * Ensure we haven't been sent a >32 bit offset.
3744 if(IVAL(req->vwv+10, 0) != 0) {
3745 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3746 "used and we don't support 64 bit offsets.\n",
3747 (unsigned int)IVAL(req->vwv+10, 0) ));
3748 END_PROFILE(SMBreadX);
3749 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3753 #endif /* LARGE_SMB_OFF_T */
3758 NTSTATUS status = schedule_aio_read_and_X(conn,
3763 if (NT_STATUS_IS_OK(status)) {
3764 /* Read scheduled - we're done. */
3767 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3768 /* Real error - report to client. */
3769 END_PROFILE(SMBreadX);
3770 reply_nterror(req, status);
3773 /* NT_STATUS_RETRY - fall back to sync read. */
3776 smbd_lock_socket(req->sconn);
3777 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3778 smbd_unlock_socket(req->sconn);
3781 END_PROFILE(SMBreadX);
3785 /****************************************************************************
3786 Error replies to writebraw must have smb_wct == 1. Fix this up.
3787 ****************************************************************************/
3789 void error_to_writebrawerr(struct smb_request *req)
3791 uint8 *old_outbuf = req->outbuf;
3793 reply_outbuf(req, 1, 0);
3795 memcpy(req->outbuf, old_outbuf, smb_size);
3796 TALLOC_FREE(old_outbuf);
3799 /****************************************************************************
3800 Read 4 bytes of a smb packet and return the smb length of the packet.
3801 Store the result in the buffer. This version of the function will
3802 never return a session keepalive (length of zero).
3803 Timeout is in milliseconds.
3804 ****************************************************************************/
3806 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3809 uint8_t msgtype = SMBkeepalive;
3811 while (msgtype == SMBkeepalive) {
3814 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3816 if (!NT_STATUS_IS_OK(status)) {
3817 char addr[INET6_ADDRSTRLEN];
3818 /* Try and give an error message
3819 * saying what client failed. */
3820 DEBUG(0, ("read_fd_with_timeout failed for "
3821 "client %s read error = %s.\n",
3822 get_peer_addr(fd,addr,sizeof(addr)),
3823 nt_errstr(status)));
3827 msgtype = CVAL(inbuf, 0);
3830 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3831 (unsigned long)len));
3833 return NT_STATUS_OK;
3836 /****************************************************************************
3837 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3838 ****************************************************************************/
3840 void reply_writebraw(struct smb_request *req)
3842 connection_struct *conn = req->conn;
3845 ssize_t total_written=0;
3846 size_t numtowrite=0;
3852 struct lock_struct lock;
3855 START_PROFILE(SMBwritebraw);
3858 * If we ever reply with an error, it must have the SMB command
3859 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3862 SCVAL(req->inbuf,smb_com,SMBwritec);
3864 if (srv_is_signing_active(req->sconn)) {
3865 END_PROFILE(SMBwritebraw);
3866 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3867 "raw reads/writes are disallowed.");
3870 if (req->wct < 12) {
3871 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3872 error_to_writebrawerr(req);
3873 END_PROFILE(SMBwritebraw);
3877 if (req->sconn->smb1.echo_handler.trusted_fde) {
3878 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3879 "'async smb echo handler = yes'\n"));
3880 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3881 error_to_writebrawerr(req);
3882 END_PROFILE(SMBwritebraw);
3886 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3887 if (!check_fsp(conn, req, fsp)) {
3888 error_to_writebrawerr(req);
3889 END_PROFILE(SMBwritebraw);
3893 if (!CHECK_WRITE(fsp)) {
3894 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3895 error_to_writebrawerr(req);
3896 END_PROFILE(SMBwritebraw);
3900 tcount = IVAL(req->vwv+1, 0);
3901 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3902 write_through = BITSETW(req->vwv+7,0);
3904 /* We have to deal with slightly different formats depending
3905 on whether we are using the core+ or lanman1.0 protocol */
3907 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3908 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3909 data = smb_buf(req->inbuf);
3911 numtowrite = SVAL(req->vwv+10, 0);
3912 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3915 /* Ensure we don't write bytes past the end of this packet. */
3916 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3917 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3918 error_to_writebrawerr(req);
3919 END_PROFILE(SMBwritebraw);
3923 if (!fsp->print_file) {
3924 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3925 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3928 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3929 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3930 error_to_writebrawerr(req);
3931 END_PROFILE(SMBwritebraw);
3937 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3940 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3941 "wrote=%d sync=%d\n",
3942 fsp->fnum, (double)startpos, (int)numtowrite,
3943 (int)nwritten, (int)write_through));
3945 if (nwritten < (ssize_t)numtowrite) {
3946 reply_nterror(req, NT_STATUS_DISK_FULL);
3947 error_to_writebrawerr(req);
3951 total_written = nwritten;
3953 /* Allocate a buffer of 64k + length. */
3954 buf = TALLOC_ARRAY(NULL, char, 65540);
3956 reply_nterror(req, NT_STATUS_NO_MEMORY);
3957 error_to_writebrawerr(req);
3961 /* Return a SMBwritebraw message to the redirector to tell
3962 * it to send more bytes */
3964 memcpy(buf, req->inbuf, smb_size);
3965 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
3966 SCVAL(buf,smb_com,SMBwritebraw);
3967 SSVALS(buf,smb_vwv0,0xFFFF);
3969 if (!srv_send_smb(req->sconn->sock,
3971 false, 0, /* no signing */
3972 IS_CONN_ENCRYPTED(conn),
3974 exit_server_cleanly("reply_writebraw: srv_send_smb "
3978 /* Now read the raw data into the buffer and write it */
3979 status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
3981 if (!NT_STATUS_IS_OK(status)) {
3982 exit_server_cleanly("secondary writebraw failed");
3985 /* Set up outbuf to return the correct size */
3986 reply_outbuf(req, 1, 0);
3988 if (numtowrite != 0) {
3990 if (numtowrite > 0xFFFF) {
3991 DEBUG(0,("reply_writebraw: Oversize secondary write "
3992 "raw requested (%u). Terminating\n",
3993 (unsigned int)numtowrite ));
3994 exit_server_cleanly("secondary writebraw failed");
3997 if (tcount > nwritten+numtowrite) {
3998 DEBUG(3,("reply_writebraw: Client overestimated the "
4000 (int)tcount,(int)nwritten,(int)numtowrite));
4003 status = read_data(req->sconn->sock, buf+4, numtowrite);
4005 if (!NT_STATUS_IS_OK(status)) {
4006 char addr[INET6_ADDRSTRLEN];
4007 /* Try and give an error message
4008 * saying what client failed. */
4009 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4010 "raw read failed (%s) for client %s. "
4011 "Terminating\n", nt_errstr(status),
4012 get_peer_addr(req->sconn->sock, addr,
4014 exit_server_cleanly("secondary writebraw failed");
4017 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4018 if (nwritten == -1) {
4020 reply_nterror(req, map_nt_error_from_unix(errno));
4021 error_to_writebrawerr(req);
4025 if (nwritten < (ssize_t)numtowrite) {
4026 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4027 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4031 total_written += nwritten;
4036 SSVAL(req->outbuf,smb_vwv0,total_written);
4038 status = sync_file(conn, fsp, write_through);
4039 if (!NT_STATUS_IS_OK(status)) {
4040 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4041 fsp_str_dbg(fsp), nt_errstr(status)));
4042 reply_nterror(req, status);
4043 error_to_writebrawerr(req);
4047 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4049 fsp->fnum, (double)startpos, (int)numtowrite,
4050 (int)total_written));
4052 if (!fsp->print_file) {
4053 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4056 /* We won't return a status if write through is not selected - this
4057 * follows what WfWg does */
4058 END_PROFILE(SMBwritebraw);
4060 if (!write_through && total_written==tcount) {
4062 #if RABBIT_PELLET_FIX
4064 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4065 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
4068 if (!send_keepalive(req->sconn->sock)) {
4069 exit_server_cleanly("reply_writebraw: send of "
4070 "keepalive failed");
4073 TALLOC_FREE(req->outbuf);
4078 if (!fsp->print_file) {
4079 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4082 END_PROFILE(SMBwritebraw);
4087 #define DBGC_CLASS DBGC_LOCKING
4089 /****************************************************************************
4090 Reply to a writeunlock (core+).
4091 ****************************************************************************/
4093 void reply_writeunlock(struct smb_request *req)
4095 connection_struct *conn = req->conn;
4096 ssize_t nwritten = -1;
4100 NTSTATUS status = NT_STATUS_OK;
4102 struct lock_struct lock;
4103 int saved_errno = 0;
4105 START_PROFILE(SMBwriteunlock);
4108 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4109 END_PROFILE(SMBwriteunlock);
4113 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4115 if (!check_fsp(conn, req, fsp)) {
4116 END_PROFILE(SMBwriteunlock);
4120 if (!CHECK_WRITE(fsp)) {
4121 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4122 END_PROFILE(SMBwriteunlock);
4126 numtowrite = SVAL(req->vwv+1, 0);
4127 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4128 data = (const char *)req->buf + 3;
4130 if (!fsp->print_file && numtowrite > 0) {
4131 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4132 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4135 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4136 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4137 END_PROFILE(SMBwriteunlock);
4142 /* The special X/Open SMB protocol handling of
4143 zero length writes is *NOT* done for
4145 if(numtowrite == 0) {
4148 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4149 saved_errno = errno;
4152 status = sync_file(conn, fsp, False /* write through */);
4153 if (!NT_STATUS_IS_OK(status)) {
4154 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4155 fsp_str_dbg(fsp), nt_errstr(status)));
4156 reply_nterror(req, status);
4161 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4165 if((nwritten < numtowrite) && (numtowrite != 0)) {
4166 reply_nterror(req, NT_STATUS_DISK_FULL);
4170 if (numtowrite && !fsp->print_file) {
4171 status = do_unlock(req->sconn->msg_ctx,
4173 (uint64_t)req->smbpid,
4174 (uint64_t)numtowrite,
4178 if (NT_STATUS_V(status)) {
4179 reply_nterror(req, status);
4184 reply_outbuf(req, 1, 0);
4186 SSVAL(req->outbuf,smb_vwv0,nwritten);
4188 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4189 fsp->fnum, (int)numtowrite, (int)nwritten));
4192 if (numtowrite && !fsp->print_file) {
4193 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4196 END_PROFILE(SMBwriteunlock);
4201 #define DBGC_CLASS DBGC_ALL
4203 /****************************************************************************
4205 ****************************************************************************/
4207 void reply_write(struct smb_request *req)
4209 connection_struct *conn = req->conn;
4211 ssize_t nwritten = -1;
4215 struct lock_struct lock;
4217 int saved_errno = 0;
4219 START_PROFILE(SMBwrite);
4222 END_PROFILE(SMBwrite);
4223 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4227 /* If it's an IPC, pass off the pipe handler. */
4229 reply_pipe_write(req);
4230 END_PROFILE(SMBwrite);
4234 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4236 if (!check_fsp(conn, req, fsp)) {
4237 END_PROFILE(SMBwrite);
4241 if (!CHECK_WRITE(fsp)) {
4242 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4243 END_PROFILE(SMBwrite);
4247 numtowrite = SVAL(req->vwv+1, 0);
4248 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4249 data = (const char *)req->buf + 3;
4251 if (!fsp->print_file) {
4252 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4253 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4256 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4257 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4258 END_PROFILE(SMBwrite);
4264 * X/Open SMB protocol says that if smb_vwv1 is
4265 * zero then the file size should be extended or
4266 * truncated to the size given in smb_vwv[2-3].
4269 if(numtowrite == 0) {
4271 * This is actually an allocate call, and set EOF. JRA.
4273 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4275 reply_nterror(req, NT_STATUS_DISK_FULL);
4278 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4280 reply_nterror(req, NT_STATUS_DISK_FULL);
4283 trigger_write_time_update_immediate(fsp);
4285 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4288 status = sync_file(conn, fsp, False);
4289 if (!NT_STATUS_IS_OK(status)) {
4290 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4291 fsp_str_dbg(fsp), nt_errstr(status)));
4292 reply_nterror(req, status);
4297 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4301 if((nwritten == 0) && (numtowrite != 0)) {
4302 reply_nterror(req, NT_STATUS_DISK_FULL);
4306 reply_outbuf(req, 1, 0);
4308 SSVAL(req->outbuf,smb_vwv0,nwritten);
4310 if (nwritten < (ssize_t)numtowrite) {
4311 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4312 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4315 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4318 if (!fsp->print_file) {
4319 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4322 END_PROFILE(SMBwrite);
4326 /****************************************************************************
4327 Ensure a buffer is a valid writeX for recvfile purposes.
4328 ****************************************************************************/
4330 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4331 (2*14) + /* word count (including bcc) */ \
4334 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4335 const uint8_t *inbuf)
4338 connection_struct *conn = NULL;
4339 unsigned int doff = 0;
4340 size_t len = smb_len_large(inbuf);
4342 if (is_encrypted_packet(inbuf)) {
4343 /* Can't do this on encrypted
4348 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4352 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4353 CVAL(inbuf,smb_wct) != 14) {
4354 DEBUG(10,("is_valid_writeX_buffer: chained or "
4355 "invalid word length.\n"));
4359 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4361 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4365 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4368 if (IS_PRINT(conn)) {
4369 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4372 doff = SVAL(inbuf,smb_vwv11);
4374 numtowrite = SVAL(inbuf,smb_vwv10);
4376 if (len > doff && len - doff > 0xFFFF) {
4377 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4380 if (numtowrite == 0) {
4381 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4385 /* Ensure the sizes match up. */
4386 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4387 /* no pad byte...old smbclient :-( */
4388 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4390 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4394 if (len - doff != numtowrite) {
4395 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4396 "len = %u, doff = %u, numtowrite = %u\n",
4399 (unsigned int)numtowrite ));
4403 DEBUG(10,("is_valid_writeX_buffer: true "
4404 "len = %u, doff = %u, numtowrite = %u\n",
4407 (unsigned int)numtowrite ));
4412 /****************************************************************************
4413 Reply to a write and X.
4414 ****************************************************************************/
4416 void reply_write_and_X(struct smb_request *req)
4418 connection_struct *conn = req->conn;
4420 struct lock_struct lock;
4425 unsigned int smb_doff;
4426 unsigned int smblen;
4429 int saved_errno = 0;
4431 START_PROFILE(SMBwriteX);
4433 if ((req->wct != 12) && (req->wct != 14)) {
4434 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4435 END_PROFILE(SMBwriteX);
4439 numtowrite = SVAL(req->vwv+10, 0);
4440 smb_doff = SVAL(req->vwv+11, 0);
4441 smblen = smb_len(req->inbuf);
4443 if (req->unread_bytes > 0xFFFF ||
4444 (smblen > smb_doff &&
4445 smblen - smb_doff > 0xFFFF)) {
4446 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4449 if (req->unread_bytes) {
4450 /* Can't do a recvfile write on IPC$ */
4452 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4453 END_PROFILE(SMBwriteX);
4456 if (numtowrite != req->unread_bytes) {
4457 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4458 END_PROFILE(SMBwriteX);
4462 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4463 smb_doff + numtowrite > smblen) {
4464 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4465 END_PROFILE(SMBwriteX);
4470 /* If it's an IPC, pass off the pipe handler. */
4472 if (req->unread_bytes) {
4473 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4474 END_PROFILE(SMBwriteX);
4477 reply_pipe_write_and_X(req);
4478 END_PROFILE(SMBwriteX);
4482 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4483 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4484 write_through = BITSETW(req->vwv+7,0);
4486 if (!check_fsp(conn, req, fsp)) {
4487 END_PROFILE(SMBwriteX);
4491 if (!CHECK_WRITE(fsp)) {
4492 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4493 END_PROFILE(SMBwriteX);
4497 data = smb_base(req->inbuf) + smb_doff;
4499 if(req->wct == 14) {
4500 #ifdef LARGE_SMB_OFF_T
4502 * This is a large offset (64 bit) write.
4504 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4506 #else /* !LARGE_SMB_OFF_T */
4509 * Ensure we haven't been sent a >32 bit offset.
4512 if(IVAL(req->vwv+12, 0) != 0) {
4513 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4514 "used and we don't support 64 bit offsets.\n",
4515 (unsigned int)IVAL(req->vwv+12, 0) ));
4516 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4517 END_PROFILE(SMBwriteX);
4521 #endif /* LARGE_SMB_OFF_T */
4524 /* X/Open SMB protocol says that, unlike SMBwrite
4525 if the length is zero then NO truncation is
4526 done, just a write of zero. To truncate a file,
4529 if(numtowrite == 0) {
4532 if (req->unread_bytes == 0) {
4533 status = schedule_aio_write_and_X(conn,
4540 if (NT_STATUS_IS_OK(status)) {
4541 /* write scheduled - we're done. */
4544 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4545 /* Real error - report to client. */
4546 reply_nterror(req, status);
4549 /* NT_STATUS_RETRY - fall through to sync write. */
4552 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4553 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4556 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4557 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4561 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4562 saved_errno = errno;
4564 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4568 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4572 if((nwritten == 0) && (numtowrite != 0)) {
4573 reply_nterror(req, NT_STATUS_DISK_FULL);
4577 reply_outbuf(req, 6, 0);
4578 SSVAL(req->outbuf,smb_vwv2,nwritten);
4579 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4581 if (nwritten < (ssize_t)numtowrite) {
4582 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4583 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4586 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4587 fsp->fnum, (int)numtowrite, (int)nwritten));
4589 status = sync_file(conn, fsp, write_through);
4590 if (!NT_STATUS_IS_OK(status)) {
4591 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4592 fsp_str_dbg(fsp), nt_errstr(status)));
4593 reply_nterror(req, status);
4597 END_PROFILE(SMBwriteX);
4602 END_PROFILE(SMBwriteX);
4606 /****************************************************************************
4608 ****************************************************************************/
4610 void reply_lseek(struct smb_request *req)
4612 connection_struct *conn = req->conn;
4618 START_PROFILE(SMBlseek);
4621 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4622 END_PROFILE(SMBlseek);
4626 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4628 if (!check_fsp(conn, req, fsp)) {
4632 flush_write_cache(fsp, SEEK_FLUSH);
4634 mode = SVAL(req->vwv+1, 0) & 3;
4635 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4636 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4645 res = fsp->fh->pos + startpos;
4656 if (umode == SEEK_END) {
4657 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4658 if(errno == EINVAL) {
4659 SMB_OFF_T current_pos = startpos;
4661 if(fsp_stat(fsp) == -1) {
4663 map_nt_error_from_unix(errno));
4664 END_PROFILE(SMBlseek);
4668 current_pos += fsp->fsp_name->st.st_ex_size;
4670 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4675 reply_nterror(req, map_nt_error_from_unix(errno));
4676 END_PROFILE(SMBlseek);
4683 reply_outbuf(req, 2, 0);
4684 SIVAL(req->outbuf,smb_vwv0,res);
4686 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4687 fsp->fnum, (double)startpos, (double)res, mode));
4689 END_PROFILE(SMBlseek);
4693 /****************************************************************************
4695 ****************************************************************************/
4697 void reply_flush(struct smb_request *req)
4699 connection_struct *conn = req->conn;
4703 START_PROFILE(SMBflush);
4706 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4710 fnum = SVAL(req->vwv+0, 0);
4711 fsp = file_fsp(req, fnum);
4713 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4718 file_sync_all(conn);
4720 NTSTATUS status = sync_file(conn, fsp, True);
4721 if (!NT_STATUS_IS_OK(status)) {
4722 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4723 fsp_str_dbg(fsp), nt_errstr(status)));
4724 reply_nterror(req, status);
4725 END_PROFILE(SMBflush);
4730 reply_outbuf(req, 0, 0);
4732 DEBUG(3,("flush\n"));
4733 END_PROFILE(SMBflush);
4737 /****************************************************************************
4739 conn POINTER CAN BE NULL HERE !
4740 ****************************************************************************/
4742 void reply_exit(struct smb_request *req)
4744 START_PROFILE(SMBexit);
4746 file_close_pid(req->smbpid, req->vuid);
4748 reply_outbuf(req, 0, 0);
4750 DEBUG(3,("exit\n"));
4752 END_PROFILE(SMBexit);
4756 /****************************************************************************
4757 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4758 ****************************************************************************/
4760 void reply_close(struct smb_request *req)
4762 connection_struct *conn = req->conn;
4763 NTSTATUS status = NT_STATUS_OK;
4764 files_struct *fsp = NULL;
4765 START_PROFILE(SMBclose);
4768 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4769 END_PROFILE(SMBclose);
4773 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4776 * We can only use check_fsp if we know it's not a directory.
4779 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4780 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4781 END_PROFILE(SMBclose);
4785 if(fsp->is_directory) {
4787 * Special case - close NT SMB directory handle.
4789 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4790 status = close_file(req, fsp, NORMAL_CLOSE);
4794 * Close ordinary file.
4797 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4798 fsp->fh->fd, fsp->fnum,
4799 conn->num_files_open));
4802 * Take care of any time sent in the close.
4805 t = srv_make_unix_date3(req->vwv+1);
4806 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4809 * close_file() returns the unix errno if an error
4810 * was detected on close - normally this is due to
4811 * a disk full error. If not then it was probably an I/O error.
4814 status = close_file(req, fsp, NORMAL_CLOSE);
4817 if (!NT_STATUS_IS_OK(status)) {
4818 reply_nterror(req, status);
4819 END_PROFILE(SMBclose);
4823 reply_outbuf(req, 0, 0);
4824 END_PROFILE(SMBclose);
4828 /****************************************************************************
4829 Reply to a writeclose (Core+ protocol).
4830 ****************************************************************************/
4832 void reply_writeclose(struct smb_request *req)
4834 connection_struct *conn = req->conn;
4836 ssize_t nwritten = -1;
4837 NTSTATUS close_status = NT_STATUS_OK;
4840 struct timespec mtime;
4842 struct lock_struct lock;
4844 START_PROFILE(SMBwriteclose);
4847 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4848 END_PROFILE(SMBwriteclose);
4852 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4854 if (!check_fsp(conn, req, fsp)) {
4855 END_PROFILE(SMBwriteclose);
4858 if (!CHECK_WRITE(fsp)) {
4859 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4860 END_PROFILE(SMBwriteclose);
4864 numtowrite = SVAL(req->vwv+1, 0);
4865 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4866 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4867 data = (const char *)req->buf + 1;
4869 if (!fsp->print_file) {
4870 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4871 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4874 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4875 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4876 END_PROFILE(SMBwriteclose);
4881 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4883 set_close_write_time(fsp, mtime);
4886 * More insanity. W2K only closes the file if writelen > 0.
4891 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4892 "file %s\n", fsp_str_dbg(fsp)));
4893 close_status = close_file(req, fsp, NORMAL_CLOSE);
4896 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4897 fsp->fnum, (int)numtowrite, (int)nwritten,
4898 conn->num_files_open));
4900 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4901 reply_nterror(req, NT_STATUS_DISK_FULL);
4905 if(!NT_STATUS_IS_OK(close_status)) {
4906 reply_nterror(req, close_status);
4910 reply_outbuf(req, 1, 0);
4912 SSVAL(req->outbuf,smb_vwv0,nwritten);
4915 if (numtowrite && !fsp->print_file) {
4916 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4919 END_PROFILE(SMBwriteclose);
4924 #define DBGC_CLASS DBGC_LOCKING
4926 /****************************************************************************
4928 ****************************************************************************/
4930 void reply_lock(struct smb_request *req)
4932 connection_struct *conn = req->conn;
4933 uint64_t count,offset;
4936 struct byte_range_lock *br_lck = NULL;
4938 START_PROFILE(SMBlock);
4941 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4942 END_PROFILE(SMBlock);
4946 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4948 if (!check_fsp(conn, req, fsp)) {
4949 END_PROFILE(SMBlock);
4953 count = (uint64_t)IVAL(req->vwv+1, 0);
4954 offset = (uint64_t)IVAL(req->vwv+3, 0);
4956 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4957 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4959 br_lck = do_lock(req->sconn->msg_ctx,
4961 (uint64_t)req->smbpid,
4966 False, /* Non-blocking lock. */
4971 TALLOC_FREE(br_lck);
4973 if (NT_STATUS_V(status)) {
4974 reply_nterror(req, status);
4975 END_PROFILE(SMBlock);
4979 reply_outbuf(req, 0, 0);
4981 END_PROFILE(SMBlock);
4985 /****************************************************************************
4987 ****************************************************************************/
4989 void reply_unlock(struct smb_request *req)
4991 connection_struct *conn = req->conn;
4992 uint64_t count,offset;
4996 START_PROFILE(SMBunlock);
4999 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5000 END_PROFILE(SMBunlock);
5004 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5006 if (!check_fsp(conn, req, fsp)) {
5007 END_PROFILE(SMBunlock);
5011 count = (uint64_t)IVAL(req->vwv+1, 0);
5012 offset = (uint64_t)IVAL(req->vwv+3, 0);
5014 status = do_unlock(req->sconn->msg_ctx,
5016 (uint64_t)req->smbpid,
5021 if (NT_STATUS_V(status)) {
5022 reply_nterror(req, status);
5023 END_PROFILE(SMBunlock);
5027 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5028 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
5030 reply_outbuf(req, 0, 0);
5032 END_PROFILE(SMBunlock);
5037 #define DBGC_CLASS DBGC_ALL
5039 /****************************************************************************
5041 conn POINTER CAN BE NULL HERE !
5042 ****************************************************************************/
5044 void reply_tdis(struct smb_request *req)
5046 connection_struct *conn = req->conn;
5047 START_PROFILE(SMBtdis);
5050 DEBUG(4,("Invalid connection in tdis\n"));
5051 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
5052 END_PROFILE(SMBtdis);
5058 close_cnum(conn,req->vuid);
5061 reply_outbuf(req, 0, 0);
5062 END_PROFILE(SMBtdis);
5066 /****************************************************************************
5068 conn POINTER CAN BE NULL HERE !
5069 ****************************************************************************/
5071 void reply_echo(struct smb_request *req)
5073 connection_struct *conn = req->conn;
5074 struct smb_perfcount_data local_pcd;
5075 struct smb_perfcount_data *cur_pcd;
5079 START_PROFILE(SMBecho);
5081 smb_init_perfcount_data(&local_pcd);
5084 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5085 END_PROFILE(SMBecho);
5089 smb_reverb = SVAL(req->vwv+0, 0);
5091 reply_outbuf(req, 1, req->buflen);
5093 /* copy any incoming data back out */
5094 if (req->buflen > 0) {
5095 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5098 if (smb_reverb > 100) {
5099 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5103 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5105 /* this makes sure we catch the request pcd */
5106 if (seq_num == smb_reverb) {
5107 cur_pcd = &req->pcd;
5109 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5110 cur_pcd = &local_pcd;
5113 SSVAL(req->outbuf,smb_vwv0,seq_num);
5115 show_msg((char *)req->outbuf);
5116 if (!srv_send_smb(req->sconn->sock,
5117 (char *)req->outbuf,
5118 true, req->seqnum+1,
5119 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5121 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5124 DEBUG(3,("echo %d times\n", smb_reverb));
5126 TALLOC_FREE(req->outbuf);
5128 END_PROFILE(SMBecho);
5132 /****************************************************************************
5133 Reply to a printopen.
5134 ****************************************************************************/
5136 void reply_printopen(struct smb_request *req)
5138 connection_struct *conn = req->conn;
5142 START_PROFILE(SMBsplopen);
5145 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5146 END_PROFILE(SMBsplopen);
5150 if (!CAN_PRINT(conn)) {
5151 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5152 END_PROFILE(SMBsplopen);
5156 status = file_new(req, conn, &fsp);
5157 if(!NT_STATUS_IS_OK(status)) {
5158 reply_nterror(req, status);
5159 END_PROFILE(SMBsplopen);
5163 /* Open for exclusive use, write only. */
5164 status = print_spool_open(fsp, NULL, req->vuid);
5166 if (!NT_STATUS_IS_OK(status)) {
5167 file_free(req, fsp);
5168 reply_nterror(req, status);
5169 END_PROFILE(SMBsplopen);
5173 reply_outbuf(req, 1, 0);
5174 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5176 DEBUG(3,("openprint fd=%d fnum=%d\n",
5177 fsp->fh->fd, fsp->fnum));
5179 END_PROFILE(SMBsplopen);
5183 /****************************************************************************
5184 Reply to a printclose.
5185 ****************************************************************************/
5187 void reply_printclose(struct smb_request *req)
5189 connection_struct *conn = req->conn;
5193 START_PROFILE(SMBsplclose);
5196 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5197 END_PROFILE(SMBsplclose);
5201 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5203 if (!check_fsp(conn, req, fsp)) {
5204 END_PROFILE(SMBsplclose);
5208 if (!CAN_PRINT(conn)) {
5209 reply_force_doserror(req, ERRSRV, ERRerror);
5210 END_PROFILE(SMBsplclose);
5214 DEBUG(3,("printclose fd=%d fnum=%d\n",
5215 fsp->fh->fd,fsp->fnum));
5217 status = close_file(req, fsp, NORMAL_CLOSE);
5219 if(!NT_STATUS_IS_OK(status)) {
5220 reply_nterror(req, status);
5221 END_PROFILE(SMBsplclose);
5225 reply_outbuf(req, 0, 0);
5227 END_PROFILE(SMBsplclose);
5231 /****************************************************************************
5232 Reply to a printqueue.
5233 ****************************************************************************/
5235 void reply_printqueue(struct smb_request *req)
5237 connection_struct *conn = req->conn;
5241 START_PROFILE(SMBsplretq);
5244 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5245 END_PROFILE(SMBsplretq);
5249 max_count = SVAL(req->vwv+0, 0);
5250 start_index = SVAL(req->vwv+1, 0);
5252 /* we used to allow the client to get the cnum wrong, but that
5253 is really quite gross and only worked when there was only
5254 one printer - I think we should now only accept it if they
5255 get it right (tridge) */
5256 if (!CAN_PRINT(conn)) {
5257 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5258 END_PROFILE(SMBsplretq);
5262 reply_outbuf(req, 2, 3);
5263 SSVAL(req->outbuf,smb_vwv0,0);
5264 SSVAL(req->outbuf,smb_vwv1,0);
5265 SCVAL(smb_buf(req->outbuf),0,1);
5266 SSVAL(smb_buf(req->outbuf),1,0);
5268 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5269 start_index, max_count));
5272 TALLOC_CTX *mem_ctx = talloc_tos();
5275 const char *sharename = lp_servicename(SNUM(conn));
5276 struct rpc_pipe_client *cli = NULL;
5277 struct policy_handle handle;
5278 struct spoolss_DevmodeContainer devmode_ctr;
5279 union spoolss_JobInfo *info;
5281 uint32_t num_to_get;
5285 ZERO_STRUCT(handle);
5287 status = rpc_connect_spoolss_pipe(conn, &cli);
5288 if (!NT_STATUS_IS_OK(status)) {
5289 DEBUG(0, ("reply_printqueue: "
5290 "could not connect to spoolss: %s\n",
5291 nt_errstr(status)));
5292 reply_nterror(req, status);
5296 ZERO_STRUCT(devmode_ctr);
5298 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
5301 SEC_FLAG_MAXIMUM_ALLOWED,
5304 if (!NT_STATUS_IS_OK(status)) {
5305 reply_nterror(req, status);
5308 if (!W_ERROR_IS_OK(werr)) {
5309 reply_nterror(req, werror_to_ntstatus(werr));
5313 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5321 if (!W_ERROR_IS_OK(werr)) {
5322 reply_nterror(req, werror_to_ntstatus(werr));
5326 if (max_count > 0) {
5327 first = start_index;
5329 first = start_index + max_count + 1;
5332 if (first >= count) {
5335 num_to_get = first + MIN(ABS(max_count), count - first);
5338 for (i = first; i < num_to_get; i++) {
5341 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5343 uint16_t qrapjobid = pjobid_to_rap(sharename,
5344 info[i].info2.job_id);
5346 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5352 srv_put_dos_date2(p, 0, qtime);
5353 SCVAL(p, 4, qstatus);
5354 SSVAL(p, 5, qrapjobid);
5355 SIVAL(p, 7, info[i].info2.size);
5357 srvstr_push(blob, req->flags2, p+12,
5358 info[i].info2.notify_name, 16, STR_ASCII);
5360 if (message_push_blob(
5363 blob, sizeof(blob))) == -1) {
5364 reply_nterror(req, NT_STATUS_NO_MEMORY);
5370 SSVAL(req->outbuf,smb_vwv0,count);
5371 SSVAL(req->outbuf,smb_vwv1,
5372 (max_count>0?first+count:first-1));
5373 SCVAL(smb_buf(req->outbuf),0,1);
5374 SSVAL(smb_buf(req->outbuf),1,28*count);
5378 DEBUG(3, ("%u entries returned in queue\n",
5382 if (cli && is_valid_policy_hnd(&handle)) {
5383 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
5388 END_PROFILE(SMBsplretq);
5392 /****************************************************************************
5393 Reply to a printwrite.
5394 ****************************************************************************/
5396 void reply_printwrite(struct smb_request *req)
5398 connection_struct *conn = req->conn;
5403 START_PROFILE(SMBsplwr);
5406 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5407 END_PROFILE(SMBsplwr);
5411 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5413 if (!check_fsp(conn, req, fsp)) {
5414 END_PROFILE(SMBsplwr);
5418 if (!fsp->print_file) {
5419 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5420 END_PROFILE(SMBsplwr);
5424 if (!CHECK_WRITE(fsp)) {
5425 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5426 END_PROFILE(SMBsplwr);
5430 numtowrite = SVAL(req->buf, 1);
5432 if (req->buflen < numtowrite + 3) {
5433 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5434 END_PROFILE(SMBsplwr);
5438 data = (const char *)req->buf + 3;
5440 if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5441 reply_nterror(req, map_nt_error_from_unix(errno));
5442 END_PROFILE(SMBsplwr);
5446 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5448 END_PROFILE(SMBsplwr);
5452 /****************************************************************************
5454 ****************************************************************************/
5456 void reply_mkdir(struct smb_request *req)
5458 connection_struct *conn = req->conn;
5459 struct smb_filename *smb_dname = NULL;
5460 char *directory = NULL;
5462 TALLOC_CTX *ctx = talloc_tos();
5464 START_PROFILE(SMBmkdir);
5466 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5467 STR_TERMINATE, &status);
5468 if (!NT_STATUS_IS_OK(status)) {
5469 reply_nterror(req, status);
5473 status = filename_convert(ctx, conn,
5474 req->flags2 & FLAGS2_DFS_PATHNAMES,
5479 if (!NT_STATUS_IS_OK(status)) {
5480 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5481 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5482 ERRSRV, ERRbadpath);
5485 reply_nterror(req, status);
5489 status = create_directory(conn, req, smb_dname);
5491 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5493 if (!NT_STATUS_IS_OK(status)) {
5495 if (!use_nt_status()
5496 && NT_STATUS_EQUAL(status,
5497 NT_STATUS_OBJECT_NAME_COLLISION)) {
5499 * Yes, in the DOS error code case we get a
5500 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5501 * samba4 torture test.
5503 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5506 reply_nterror(req, status);
5510 reply_outbuf(req, 0, 0);
5512 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5514 TALLOC_FREE(smb_dname);
5515 END_PROFILE(SMBmkdir);
5519 /****************************************************************************
5521 ****************************************************************************/
5523 void reply_rmdir(struct smb_request *req)
5525 connection_struct *conn = req->conn;
5526 struct smb_filename *smb_dname = NULL;
5527 char *directory = NULL;
5529 TALLOC_CTX *ctx = talloc_tos();
5530 files_struct *fsp = NULL;
5532 struct smbd_server_connection *sconn = req->sconn;
5534 START_PROFILE(SMBrmdir);
5536 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5537 STR_TERMINATE, &status);
5538 if (!NT_STATUS_IS_OK(status)) {
5539 reply_nterror(req, status);
5543 status = filename_convert(ctx, conn,
5544 req->flags2 & FLAGS2_DFS_PATHNAMES,
5549 if (!NT_STATUS_IS_OK(status)) {
5550 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5551 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5552 ERRSRV, ERRbadpath);
5555 reply_nterror(req, status);
5559 if (is_ntfs_stream_smb_fname(smb_dname)) {
5560 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5564 status = SMB_VFS_CREATE_FILE(
5567 0, /* root_dir_fid */
5568 smb_dname, /* fname */
5569 DELETE_ACCESS, /* access_mask */
5570 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5572 FILE_OPEN, /* create_disposition*/
5573 FILE_DIRECTORY_FILE, /* create_options */
5574 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5575 0, /* oplock_request */
5576 0, /* allocation_size */
5577 0, /* private_flags */
5583 if (!NT_STATUS_IS_OK(status)) {
5584 if (open_was_deferred(req->mid)) {
5585 /* We have re-scheduled this call. */
5588 reply_nterror(req, status);
5592 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5593 if (!NT_STATUS_IS_OK(status)) {
5594 close_file(req, fsp, ERROR_CLOSE);
5595 reply_nterror(req, status);
5599 if (!set_delete_on_close(fsp, true, &conn->server_info->utok)) {
5600 close_file(req, fsp, ERROR_CLOSE);
5601 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5605 status = close_file(req, fsp, NORMAL_CLOSE);
5606 if (!NT_STATUS_IS_OK(status)) {
5607 reply_nterror(req, status);
5609 reply_outbuf(req, 0, 0);
5612 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5614 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5616 TALLOC_FREE(smb_dname);
5617 END_PROFILE(SMBrmdir);
5621 /*******************************************************************
5622 Resolve wildcards in a filename rename.
5623 ********************************************************************/
5625 static bool resolve_wildcards(TALLOC_CTX *ctx,
5630 char *name2_copy = NULL;
5635 char *p,*p2, *pname1, *pname2;
5637 name2_copy = talloc_strdup(ctx, name2);
5642 pname1 = strrchr_m(name1,'/');
5643 pname2 = strrchr_m(name2_copy,'/');
5645 if (!pname1 || !pname2) {
5649 /* Truncate the copy of name2 at the last '/' */
5652 /* Now go past the '/' */
5656 root1 = talloc_strdup(ctx, pname1);
5657 root2 = talloc_strdup(ctx, pname2);
5659 if (!root1 || !root2) {
5663 p = strrchr_m(root1,'.');
5666 ext1 = talloc_strdup(ctx, p+1);
5668 ext1 = talloc_strdup(ctx, "");
5670 p = strrchr_m(root2,'.');
5673 ext2 = talloc_strdup(ctx, p+1);
5675 ext2 = talloc_strdup(ctx, "");
5678 if (!ext1 || !ext2) {
5686 /* Hmmm. Should this be mb-aware ? */
5689 } else if (*p2 == '*') {
5691 root2 = talloc_asprintf(ctx, "%s%s",
5710 /* Hmmm. Should this be mb-aware ? */
5713 } else if (*p2 == '*') {
5715 ext2 = talloc_asprintf(ctx, "%s%s",
5731 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5736 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5748 /****************************************************************************
5749 Ensure open files have their names updated. Updated to notify other smbd's
5751 ****************************************************************************/
5753 static void rename_open_files(connection_struct *conn,
5754 struct share_mode_lock *lck,
5755 const struct smb_filename *smb_fname_dst)
5758 bool did_rename = False;
5761 for(fsp = file_find_di_first(lck->id); fsp;
5762 fsp = file_find_di_next(fsp)) {
5763 /* fsp_name is a relative path under the fsp. To change this for other
5764 sharepaths we need to manipulate relative paths. */
5765 /* TODO - create the absolute path and manipulate the newname
5766 relative to the sharepath. */
5767 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5770 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5771 "(file_id %s) from %s -> %s\n", fsp->fnum,
5772 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5773 smb_fname_str_dbg(smb_fname_dst)));
5775 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5776 if (NT_STATUS_IS_OK(status)) {
5782 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5783 "for %s\n", file_id_string_tos(&lck->id),
5784 smb_fname_str_dbg(smb_fname_dst)));
5787 /* Send messages to all smbd's (not ourself) that the name has changed. */
5788 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5793 /****************************************************************************
5794 We need to check if the source path is a parent directory of the destination
5795 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5796 refuse the rename with a sharing violation. Under UNIX the above call can
5797 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5798 probably need to check that the client is a Windows one before disallowing
5799 this as a UNIX client (one with UNIX extensions) can know the source is a
5800 symlink and make this decision intelligently. Found by an excellent bug
5801 report from <AndyLiebman@aol.com>.
5802 ****************************************************************************/
5804 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5805 const struct smb_filename *smb_fname_dst)
5807 const char *psrc = smb_fname_src->base_name;
5808 const char *pdst = smb_fname_dst->base_name;
5811 if (psrc[0] == '.' && psrc[1] == '/') {
5814 if (pdst[0] == '.' && pdst[1] == '/') {
5817 if ((slen = strlen(psrc)) > strlen(pdst)) {
5820 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5824 * Do the notify calls from a rename
5827 static void notify_rename(connection_struct *conn, bool is_dir,
5828 const struct smb_filename *smb_fname_src,
5829 const struct smb_filename *smb_fname_dst)
5831 char *parent_dir_src = NULL;
5832 char *parent_dir_dst = NULL;
5835 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5836 : FILE_NOTIFY_CHANGE_FILE_NAME;
5838 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5839 &parent_dir_src, NULL) ||
5840 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5841 &parent_dir_dst, NULL)) {
5845 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5846 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5847 smb_fname_src->base_name);
5848 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5849 smb_fname_dst->base_name);
5852 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5853 smb_fname_src->base_name);
5854 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5855 smb_fname_dst->base_name);
5858 /* this is a strange one. w2k3 gives an additional event for
5859 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5860 files, but not directories */
5862 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5863 FILE_NOTIFY_CHANGE_ATTRIBUTES
5864 |FILE_NOTIFY_CHANGE_CREATION,
5865 smb_fname_dst->base_name);
5868 TALLOC_FREE(parent_dir_src);
5869 TALLOC_FREE(parent_dir_dst);
5872 /****************************************************************************
5873 Rename an open file - given an fsp.
5874 ****************************************************************************/
5876 NTSTATUS rename_internals_fsp(connection_struct *conn,
5878 const struct smb_filename *smb_fname_dst_in,
5880 bool replace_if_exists)
5882 TALLOC_CTX *ctx = talloc_tos();
5883 struct smb_filename *smb_fname_dst = NULL;
5884 NTSTATUS status = NT_STATUS_OK;
5885 struct share_mode_lock *lck = NULL;
5886 bool dst_exists, old_is_stream, new_is_stream;
5888 status = check_name(conn, smb_fname_dst_in->base_name);
5889 if (!NT_STATUS_IS_OK(status)) {
5893 /* Make a copy of the dst smb_fname structs */
5895 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5896 if (!NT_STATUS_IS_OK(status)) {
5900 /* Ensure the dst smb_fname contains a '/' */
5901 if(strrchr_m(smb_fname_dst->base_name,'/') == 0) {
5903 tmp = talloc_asprintf(smb_fname_dst, "./%s",
5904 smb_fname_dst->base_name);
5906 status = NT_STATUS_NO_MEMORY;
5909 TALLOC_FREE(smb_fname_dst->base_name);
5910 smb_fname_dst->base_name = tmp;
5914 * Check for special case with case preserving and not
5915 * case sensitive. If the old last component differs from the original
5916 * last component only by case, then we should allow
5917 * the rename (user is trying to change the case of the
5920 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5921 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5922 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
5924 char *fname_dst_lcomp_base_mod = NULL;
5925 struct smb_filename *smb_fname_orig_lcomp = NULL;
5928 * Get the last component of the destination name. Note that
5929 * we guarantee that destination name contains a '/' character
5932 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5933 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5934 if (!fname_dst_lcomp_base_mod) {
5935 status = NT_STATUS_NO_MEMORY;
5940 * Create an smb_filename struct using the original last
5941 * component of the destination.
5943 status = create_synthetic_smb_fname_split(ctx,
5944 smb_fname_dst->original_lcomp, NULL,
5945 &smb_fname_orig_lcomp);
5946 if (!NT_STATUS_IS_OK(status)) {
5947 TALLOC_FREE(fname_dst_lcomp_base_mod);
5951 /* If the base names only differ by case, use original. */
5952 if(!strcsequal(fname_dst_lcomp_base_mod,
5953 smb_fname_orig_lcomp->base_name)) {
5956 * Replace the modified last component with the
5959 *last_slash = '\0'; /* Truncate at the '/' */
5960 tmp = talloc_asprintf(smb_fname_dst,
5962 smb_fname_dst->base_name,
5963 smb_fname_orig_lcomp->base_name);
5965 status = NT_STATUS_NO_MEMORY;
5966 TALLOC_FREE(fname_dst_lcomp_base_mod);
5967 TALLOC_FREE(smb_fname_orig_lcomp);
5970 TALLOC_FREE(smb_fname_dst->base_name);
5971 smb_fname_dst->base_name = tmp;
5974 /* If the stream_names only differ by case, use original. */
5975 if(!strcsequal(smb_fname_dst->stream_name,
5976 smb_fname_orig_lcomp->stream_name)) {
5978 /* Use the original stream. */
5979 tmp = talloc_strdup(smb_fname_dst,
5980 smb_fname_orig_lcomp->stream_name);
5982 status = NT_STATUS_NO_MEMORY;
5983 TALLOC_FREE(fname_dst_lcomp_base_mod);
5984 TALLOC_FREE(smb_fname_orig_lcomp);
5987 TALLOC_FREE(smb_fname_dst->stream_name);
5988 smb_fname_dst->stream_name = tmp;
5990 TALLOC_FREE(fname_dst_lcomp_base_mod);
5991 TALLOC_FREE(smb_fname_orig_lcomp);
5995 * If the src and dest names are identical - including case,
5996 * don't do the rename, just return success.
5999 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6000 strcsequal(fsp->fsp_name->stream_name,
6001 smb_fname_dst->stream_name)) {
6002 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6003 "- returning success\n",
6004 smb_fname_str_dbg(smb_fname_dst)));
6005 status = NT_STATUS_OK;
6009 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6010 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6012 /* Return the correct error code if both names aren't streams. */
6013 if (!old_is_stream && new_is_stream) {
6014 status = NT_STATUS_OBJECT_NAME_INVALID;
6018 if (old_is_stream && !new_is_stream) {
6019 status = NT_STATUS_INVALID_PARAMETER;
6023 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6025 if(!replace_if_exists && dst_exists) {
6026 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6027 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6028 smb_fname_str_dbg(smb_fname_dst)));
6029 status = NT_STATUS_OBJECT_NAME_COLLISION;
6034 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6035 &smb_fname_dst->st);
6036 files_struct *dst_fsp = file_find_di_first(fileid);
6037 /* The file can be open when renaming a stream */
6038 if (dst_fsp && !new_is_stream) {
6039 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6040 status = NT_STATUS_ACCESS_DENIED;
6045 /* Ensure we have a valid stat struct for the source. */
6046 status = vfs_stat_fsp(fsp);
6047 if (!NT_STATUS_IS_OK(status)) {
6051 status = can_rename(conn, fsp, attrs);
6053 if (!NT_STATUS_IS_OK(status)) {
6054 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6055 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6056 smb_fname_str_dbg(smb_fname_dst)));
6057 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6058 status = NT_STATUS_ACCESS_DENIED;
6062 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6063 status = NT_STATUS_ACCESS_DENIED;
6066 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6070 * We have the file open ourselves, so not being able to get the
6071 * corresponding share mode lock is a fatal error.
6074 SMB_ASSERT(lck != NULL);
6076 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6077 uint32 create_options = fsp->fh->private_options;
6079 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6080 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6081 smb_fname_str_dbg(smb_fname_dst)));
6083 if (lp_map_archive(SNUM(conn)) ||
6084 lp_store_dos_attributes(SNUM(conn))) {
6085 /* We must set the archive bit on the newly
6087 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6088 uint32_t old_dosmode = dos_mode(conn,
6090 file_set_dosmode(conn,
6092 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6098 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6101 rename_open_files(conn, lck, smb_fname_dst);
6104 * A rename acts as a new file create w.r.t. allowing an initial delete
6105 * on close, probably because in Windows there is a new handle to the
6106 * new file. If initial delete on close was requested but not
6107 * originally set, we need to set it here. This is probably not 100% correct,
6108 * but will work for the CIFSFS client which in non-posix mode
6109 * depends on these semantics. JRA.
6112 if (create_options & FILE_DELETE_ON_CLOSE) {
6113 status = can_set_delete_on_close(fsp, 0);
6115 if (NT_STATUS_IS_OK(status)) {
6116 /* Note that here we set the *inital* delete on close flag,
6117 * not the regular one. The magic gets handled in close. */
6118 fsp->initial_delete_on_close = True;
6122 status = NT_STATUS_OK;
6128 if (errno == ENOTDIR || errno == EISDIR) {
6129 status = NT_STATUS_OBJECT_NAME_COLLISION;
6131 status = map_nt_error_from_unix(errno);
6134 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6135 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6136 smb_fname_str_dbg(smb_fname_dst)));
6139 TALLOC_FREE(smb_fname_dst);
6144 /****************************************************************************
6145 The guts of the rename command, split out so it may be called by the NT SMB
6147 ****************************************************************************/
6149 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6150 connection_struct *conn,
6151 struct smb_request *req,
6152 struct smb_filename *smb_fname_src,
6153 struct smb_filename *smb_fname_dst,
6155 bool replace_if_exists,
6158 uint32_t access_mask)
6160 char *fname_src_dir = NULL;
6161 char *fname_src_mask = NULL;
6163 NTSTATUS status = NT_STATUS_OK;
6164 struct smb_Dir *dir_hnd = NULL;
6165 const char *dname = NULL;
6166 char *talloced = NULL;
6168 int create_options = 0;
6169 bool posix_pathnames = lp_posix_pathnames();
6172 * Split the old name into directory and last component
6173 * strings. Note that unix_convert may have stripped off a
6174 * leading ./ from both name and newname if the rename is
6175 * at the root of the share. We need to make sure either both
6176 * name and newname contain a / character or neither of them do
6177 * as this is checked in resolve_wildcards().
6180 /* Split up the directory from the filename/mask. */
6181 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6182 &fname_src_dir, &fname_src_mask);
6183 if (!NT_STATUS_IS_OK(status)) {
6184 status = NT_STATUS_NO_MEMORY;
6189 * We should only check the mangled cache
6190 * here if unix_convert failed. This means
6191 * that the path in 'mask' doesn't exist
6192 * on the file system and so we need to look
6193 * for a possible mangle. This patch from
6194 * Tine Smukavec <valentin.smukavec@hermes.si>.
6197 if (!VALID_STAT(smb_fname_src->st) &&
6198 mangle_is_mangled(fname_src_mask, conn->params)) {
6199 char *new_mask = NULL;
6200 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6203 TALLOC_FREE(fname_src_mask);
6204 fname_src_mask = new_mask;
6208 if (!src_has_wild) {
6212 * Only one file needs to be renamed. Append the mask back
6213 * onto the directory.
6215 TALLOC_FREE(smb_fname_src->base_name);
6216 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6220 if (!smb_fname_src->base_name) {
6221 status = NT_STATUS_NO_MEMORY;
6225 /* Ensure dst fname contains a '/' also */
6226 if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
6228 tmp = talloc_asprintf(smb_fname_dst, "./%s",
6229 smb_fname_dst->base_name);
6231 status = NT_STATUS_NO_MEMORY;
6234 TALLOC_FREE(smb_fname_dst->base_name);
6235 smb_fname_dst->base_name = tmp;
6238 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6239 "case_preserve = %d, short case preserve = %d, "
6240 "directory = %s, newname = %s, "
6241 "last_component_dest = %s\n",
6242 conn->case_sensitive, conn->case_preserve,
6243 conn->short_case_preserve,
6244 smb_fname_str_dbg(smb_fname_src),
6245 smb_fname_str_dbg(smb_fname_dst),
6246 smb_fname_dst->original_lcomp));
6248 /* The dest name still may have wildcards. */
6249 if (dest_has_wild) {
6250 char *fname_dst_mod = NULL;
6251 if (!resolve_wildcards(smb_fname_dst,
6252 smb_fname_src->base_name,
6253 smb_fname_dst->base_name,
6255 DEBUG(6, ("rename_internals: resolve_wildcards "
6257 smb_fname_src->base_name,
6258 smb_fname_dst->base_name));
6259 status = NT_STATUS_NO_MEMORY;
6262 TALLOC_FREE(smb_fname_dst->base_name);
6263 smb_fname_dst->base_name = fname_dst_mod;
6266 ZERO_STRUCT(smb_fname_src->st);
6267 if (posix_pathnames) {
6268 SMB_VFS_LSTAT(conn, smb_fname_src);
6270 SMB_VFS_STAT(conn, smb_fname_src);
6273 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6274 create_options |= FILE_DIRECTORY_FILE;
6277 status = SMB_VFS_CREATE_FILE(
6280 0, /* root_dir_fid */
6281 smb_fname_src, /* fname */
6282 access_mask, /* access_mask */
6283 (FILE_SHARE_READ | /* share_access */
6285 FILE_OPEN, /* create_disposition*/
6286 create_options, /* create_options */
6287 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6288 0, /* oplock_request */
6289 0, /* allocation_size */
6290 0, /* private_flags */
6296 if (!NT_STATUS_IS_OK(status)) {
6297 DEBUG(3, ("Could not open rename source %s: %s\n",
6298 smb_fname_str_dbg(smb_fname_src),
6299 nt_errstr(status)));
6303 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6304 attrs, replace_if_exists);
6306 close_file(req, fsp, NORMAL_CLOSE);
6308 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6309 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6310 smb_fname_str_dbg(smb_fname_dst)));
6316 * Wildcards - process each file that matches.
6318 if (strequal(fname_src_mask, "????????.???")) {
6319 TALLOC_FREE(fname_src_mask);
6320 fname_src_mask = talloc_strdup(ctx, "*");
6321 if (!fname_src_mask) {
6322 status = NT_STATUS_NO_MEMORY;
6327 status = check_name(conn, fname_src_dir);
6328 if (!NT_STATUS_IS_OK(status)) {
6332 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6334 if (dir_hnd == NULL) {
6335 status = map_nt_error_from_unix(errno);
6339 status = NT_STATUS_NO_SUCH_FILE;
6341 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6342 * - gentest fix. JRA
6345 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6347 files_struct *fsp = NULL;
6348 char *destname = NULL;
6349 bool sysdir_entry = False;
6351 /* Quick check for "." and ".." */
6352 if (ISDOT(dname) || ISDOTDOT(dname)) {
6354 sysdir_entry = True;
6356 TALLOC_FREE(talloced);
6361 if (!is_visible_file(conn, fname_src_dir, dname,
6362 &smb_fname_src->st, false)) {
6363 TALLOC_FREE(talloced);
6367 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6368 TALLOC_FREE(talloced);
6373 status = NT_STATUS_OBJECT_NAME_INVALID;
6377 TALLOC_FREE(smb_fname_src->base_name);
6378 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6382 if (!smb_fname_src->base_name) {
6383 status = NT_STATUS_NO_MEMORY;
6387 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6388 smb_fname_dst->base_name,
6390 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6391 smb_fname_src->base_name, destname));
6392 TALLOC_FREE(talloced);
6396 status = NT_STATUS_NO_MEMORY;
6400 TALLOC_FREE(smb_fname_dst->base_name);
6401 smb_fname_dst->base_name = destname;
6403 ZERO_STRUCT(smb_fname_src->st);
6404 if (posix_pathnames) {
6405 SMB_VFS_LSTAT(conn, smb_fname_src);
6407 SMB_VFS_STAT(conn, smb_fname_src);
6412 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6413 create_options |= FILE_DIRECTORY_FILE;
6416 status = SMB_VFS_CREATE_FILE(
6419 0, /* root_dir_fid */
6420 smb_fname_src, /* fname */
6421 access_mask, /* access_mask */
6422 (FILE_SHARE_READ | /* share_access */
6424 FILE_OPEN, /* create_disposition*/
6425 create_options, /* create_options */
6426 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6427 0, /* oplock_request */
6428 0, /* allocation_size */
6429 0, /* private_flags */
6435 if (!NT_STATUS_IS_OK(status)) {
6436 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6437 "returned %s rename %s -> %s\n",
6439 smb_fname_str_dbg(smb_fname_src),
6440 smb_fname_str_dbg(smb_fname_dst)));
6444 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6446 if (!smb_fname_dst->original_lcomp) {
6447 status = NT_STATUS_NO_MEMORY;
6451 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6452 attrs, replace_if_exists);
6454 close_file(req, fsp, NORMAL_CLOSE);
6456 if (!NT_STATUS_IS_OK(status)) {
6457 DEBUG(3, ("rename_internals_fsp returned %s for "
6458 "rename %s -> %s\n", nt_errstr(status),
6459 smb_fname_str_dbg(smb_fname_src),
6460 smb_fname_str_dbg(smb_fname_dst)));
6466 DEBUG(3,("rename_internals: doing rename on %s -> "
6467 "%s\n", smb_fname_str_dbg(smb_fname_src),
6468 smb_fname_str_dbg(smb_fname_src)));
6469 TALLOC_FREE(talloced);
6471 TALLOC_FREE(dir_hnd);
6473 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6474 status = map_nt_error_from_unix(errno);
6478 TALLOC_FREE(talloced);
6479 TALLOC_FREE(fname_src_dir);
6480 TALLOC_FREE(fname_src_mask);
6484 /****************************************************************************
6486 ****************************************************************************/
6488 void reply_mv(struct smb_request *req)
6490 connection_struct *conn = req->conn;
6492 char *newname = NULL;
6496 bool src_has_wcard = False;
6497 bool dest_has_wcard = False;
6498 TALLOC_CTX *ctx = talloc_tos();
6499 struct smb_filename *smb_fname_src = NULL;
6500 struct smb_filename *smb_fname_dst = NULL;
6502 START_PROFILE(SMBmv);
6505 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6509 attrs = SVAL(req->vwv+0, 0);
6511 p = (const char *)req->buf + 1;
6512 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6513 &status, &src_has_wcard);
6514 if (!NT_STATUS_IS_OK(status)) {
6515 reply_nterror(req, status);
6519 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6520 &status, &dest_has_wcard);
6521 if (!NT_STATUS_IS_OK(status)) {
6522 reply_nterror(req, status);
6526 status = filename_convert(ctx,
6528 req->flags2 & FLAGS2_DFS_PATHNAMES,
6530 UCF_COND_ALLOW_WCARD_LCOMP,
6534 if (!NT_STATUS_IS_OK(status)) {
6535 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6536 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6537 ERRSRV, ERRbadpath);
6540 reply_nterror(req, status);
6544 status = filename_convert(ctx,
6546 req->flags2 & FLAGS2_DFS_PATHNAMES,
6548 UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6552 if (!NT_STATUS_IS_OK(status)) {
6553 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6554 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6555 ERRSRV, ERRbadpath);
6558 reply_nterror(req, status);
6562 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6563 smb_fname_str_dbg(smb_fname_dst)));
6565 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6566 attrs, False, src_has_wcard, dest_has_wcard,
6568 if (!NT_STATUS_IS_OK(status)) {
6569 if (open_was_deferred(req->mid)) {
6570 /* We have re-scheduled this call. */
6573 reply_nterror(req, status);
6577 reply_outbuf(req, 0, 0);
6579 TALLOC_FREE(smb_fname_src);
6580 TALLOC_FREE(smb_fname_dst);
6585 /*******************************************************************
6586 Copy a file as part of a reply_copy.
6587 ******************************************************************/
6590 * TODO: check error codes on all callers
6593 NTSTATUS copy_file(TALLOC_CTX *ctx,
6594 connection_struct *conn,
6595 struct smb_filename *smb_fname_src,
6596 struct smb_filename *smb_fname_dst,
6599 bool target_is_directory)
6601 struct smb_filename *smb_fname_dst_tmp = NULL;
6603 files_struct *fsp1,*fsp2;
6605 uint32 new_create_disposition;
6609 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6610 if (!NT_STATUS_IS_OK(status)) {
6615 * If the target is a directory, extract the last component from the
6616 * src filename and append it to the dst filename
6618 if (target_is_directory) {
6621 /* dest/target can't be a stream if it's a directory. */
6622 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6624 p = strrchr_m(smb_fname_src->base_name,'/');
6628 p = smb_fname_src->base_name;
6630 smb_fname_dst_tmp->base_name =
6631 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6633 if (!smb_fname_dst_tmp->base_name) {
6634 status = NT_STATUS_NO_MEMORY;
6639 status = vfs_file_exist(conn, smb_fname_src);
6640 if (!NT_STATUS_IS_OK(status)) {
6644 if (!target_is_directory && count) {
6645 new_create_disposition = FILE_OPEN;
6647 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
6649 &new_create_disposition,
6652 status = NT_STATUS_INVALID_PARAMETER;
6657 /* Open the src file for reading. */
6658 status = SMB_VFS_CREATE_FILE(
6661 0, /* root_dir_fid */
6662 smb_fname_src, /* fname */
6663 FILE_GENERIC_READ, /* access_mask */
6664 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6665 FILE_OPEN, /* create_disposition*/
6666 0, /* create_options */
6667 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6668 INTERNAL_OPEN_ONLY, /* oplock_request */
6669 0, /* allocation_size */
6670 0, /* private_flags */
6676 if (!NT_STATUS_IS_OK(status)) {
6680 dosattrs = dos_mode(conn, smb_fname_src);
6682 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6683 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6686 /* Open the dst file for writing. */
6687 status = SMB_VFS_CREATE_FILE(
6690 0, /* root_dir_fid */
6691 smb_fname_dst, /* fname */
6692 FILE_GENERIC_WRITE, /* access_mask */
6693 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6694 new_create_disposition, /* create_disposition*/
6695 0, /* create_options */
6696 dosattrs, /* file_attributes */
6697 INTERNAL_OPEN_ONLY, /* oplock_request */
6698 0, /* allocation_size */
6699 0, /* private_flags */
6705 if (!NT_STATUS_IS_OK(status)) {
6706 close_file(NULL, fsp1, ERROR_CLOSE);
6710 if ((ofun&3) == 1) {
6711 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6712 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6714 * Stop the copy from occurring.
6717 smb_fname_src->st.st_ex_size = 0;
6721 /* Do the actual copy. */
6722 if (smb_fname_src->st.st_ex_size) {
6723 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6726 close_file(NULL, fsp1, NORMAL_CLOSE);
6728 /* Ensure the modtime is set correctly on the destination file. */
6729 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6732 * As we are opening fsp1 read-only we only expect
6733 * an error on close on fsp2 if we are out of space.
6734 * Thus we don't look at the error return from the
6737 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6739 if (!NT_STATUS_IS_OK(status)) {
6743 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6744 status = NT_STATUS_DISK_FULL;
6748 status = NT_STATUS_OK;
6751 TALLOC_FREE(smb_fname_dst_tmp);
6755 /****************************************************************************
6756 Reply to a file copy.
6757 ****************************************************************************/
6759 void reply_copy(struct smb_request *req)
6761 connection_struct *conn = req->conn;
6762 struct smb_filename *smb_fname_src = NULL;
6763 struct smb_filename *smb_fname_dst = NULL;
6764 char *fname_src = NULL;
6765 char *fname_dst = NULL;
6766 char *fname_src_mask = NULL;
6767 char *fname_src_dir = NULL;
6770 int error = ERRnoaccess;
6774 bool target_is_directory=False;
6775 bool source_has_wild = False;
6776 bool dest_has_wild = False;
6778 TALLOC_CTX *ctx = talloc_tos();
6780 START_PROFILE(SMBcopy);
6783 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6787 tid2 = SVAL(req->vwv+0, 0);
6788 ofun = SVAL(req->vwv+1, 0);
6789 flags = SVAL(req->vwv+2, 0);
6791 p = (const char *)req->buf;
6792 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6793 &status, &source_has_wild);
6794 if (!NT_STATUS_IS_OK(status)) {
6795 reply_nterror(req, status);
6798 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6799 &status, &dest_has_wild);
6800 if (!NT_STATUS_IS_OK(status)) {
6801 reply_nterror(req, status);
6805 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6807 if (tid2 != conn->cnum) {
6808 /* can't currently handle inter share copies XXXX */
6809 DEBUG(3,("Rejecting inter-share copy\n"));
6810 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6814 status = filename_convert(ctx, conn,
6815 req->flags2 & FLAGS2_DFS_PATHNAMES,
6817 UCF_COND_ALLOW_WCARD_LCOMP,
6820 if (!NT_STATUS_IS_OK(status)) {
6821 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6822 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6823 ERRSRV, ERRbadpath);
6826 reply_nterror(req, status);
6830 status = filename_convert(ctx, conn,
6831 req->flags2 & FLAGS2_DFS_PATHNAMES,
6833 UCF_COND_ALLOW_WCARD_LCOMP,
6836 if (!NT_STATUS_IS_OK(status)) {
6837 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6838 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6839 ERRSRV, ERRbadpath);
6842 reply_nterror(req, status);
6846 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6848 if ((flags&1) && target_is_directory) {
6849 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6853 if ((flags&2) && !target_is_directory) {
6854 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
6858 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6859 /* wants a tree copy! XXXX */
6860 DEBUG(3,("Rejecting tree copy\n"));
6861 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6865 /* Split up the directory from the filename/mask. */
6866 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6867 &fname_src_dir, &fname_src_mask);
6868 if (!NT_STATUS_IS_OK(status)) {
6869 reply_nterror(req, NT_STATUS_NO_MEMORY);
6874 * We should only check the mangled cache
6875 * here if unix_convert failed. This means
6876 * that the path in 'mask' doesn't exist
6877 * on the file system and so we need to look
6878 * for a possible mangle. This patch from
6879 * Tine Smukavec <valentin.smukavec@hermes.si>.
6881 if (!VALID_STAT(smb_fname_src->st) &&
6882 mangle_is_mangled(fname_src_mask, conn->params)) {
6883 char *new_mask = NULL;
6884 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6885 &new_mask, conn->params);
6887 /* Use demangled name if one was successfully found. */
6889 TALLOC_FREE(fname_src_mask);
6890 fname_src_mask = new_mask;
6894 if (!source_has_wild) {
6897 * Only one file needs to be copied. Append the mask back onto
6900 TALLOC_FREE(smb_fname_src->base_name);
6901 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6905 if (!smb_fname_src->base_name) {
6906 reply_nterror(req, NT_STATUS_NO_MEMORY);
6910 if (dest_has_wild) {
6911 char *fname_dst_mod = NULL;
6912 if (!resolve_wildcards(smb_fname_dst,
6913 smb_fname_src->base_name,
6914 smb_fname_dst->base_name,
6916 reply_nterror(req, NT_STATUS_NO_MEMORY);
6919 TALLOC_FREE(smb_fname_dst->base_name);
6920 smb_fname_dst->base_name = fname_dst_mod;
6923 status = check_name(conn, smb_fname_src->base_name);
6924 if (!NT_STATUS_IS_OK(status)) {
6925 reply_nterror(req, status);
6929 status = check_name(conn, smb_fname_dst->base_name);
6930 if (!NT_STATUS_IS_OK(status)) {
6931 reply_nterror(req, status);
6935 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
6936 ofun, count, target_is_directory);
6938 if(!NT_STATUS_IS_OK(status)) {
6939 reply_nterror(req, status);
6945 struct smb_Dir *dir_hnd = NULL;
6946 const char *dname = NULL;
6947 char *talloced = NULL;
6951 * There is a wildcard that requires us to actually read the
6952 * src dir and copy each file matching the mask to the dst.
6953 * Right now streams won't be copied, but this could
6954 * presumably be added with a nested loop for reach dir entry.
6956 SMB_ASSERT(!smb_fname_src->stream_name);
6957 SMB_ASSERT(!smb_fname_dst->stream_name);
6959 smb_fname_src->stream_name = NULL;
6960 smb_fname_dst->stream_name = NULL;
6962 if (strequal(fname_src_mask,"????????.???")) {
6963 TALLOC_FREE(fname_src_mask);
6964 fname_src_mask = talloc_strdup(ctx, "*");
6965 if (!fname_src_mask) {
6966 reply_nterror(req, NT_STATUS_NO_MEMORY);
6971 status = check_name(conn, fname_src_dir);
6972 if (!NT_STATUS_IS_OK(status)) {
6973 reply_nterror(req, status);
6977 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
6978 if (dir_hnd == NULL) {
6979 status = map_nt_error_from_unix(errno);
6980 reply_nterror(req, status);
6986 /* Iterate over the src dir copying each entry to the dst. */
6987 while ((dname = ReadDirName(dir_hnd, &offset,
6988 &smb_fname_src->st, &talloced))) {
6989 char *destname = NULL;
6991 if (ISDOT(dname) || ISDOTDOT(dname)) {
6992 TALLOC_FREE(talloced);
6996 if (!is_visible_file(conn, fname_src_dir, dname,
6997 &smb_fname_src->st, false)) {
6998 TALLOC_FREE(talloced);
7002 if(!mask_match(dname, fname_src_mask,
7003 conn->case_sensitive)) {
7004 TALLOC_FREE(talloced);
7008 error = ERRnoaccess;
7010 /* Get the src smb_fname struct setup. */
7011 TALLOC_FREE(smb_fname_src->base_name);
7012 smb_fname_src->base_name =
7013 talloc_asprintf(smb_fname_src, "%s/%s",
7014 fname_src_dir, dname);
7016 if (!smb_fname_src->base_name) {
7017 TALLOC_FREE(dir_hnd);
7018 TALLOC_FREE(talloced);
7019 reply_nterror(req, NT_STATUS_NO_MEMORY);
7023 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7024 smb_fname_dst->base_name,
7026 TALLOC_FREE(talloced);
7030 TALLOC_FREE(dir_hnd);
7031 TALLOC_FREE(talloced);
7032 reply_nterror(req, NT_STATUS_NO_MEMORY);
7036 TALLOC_FREE(smb_fname_dst->base_name);
7037 smb_fname_dst->base_name = destname;
7039 status = check_name(conn, smb_fname_src->base_name);
7040 if (!NT_STATUS_IS_OK(status)) {
7041 TALLOC_FREE(dir_hnd);
7042 TALLOC_FREE(talloced);
7043 reply_nterror(req, status);
7047 status = check_name(conn, smb_fname_dst->base_name);
7048 if (!NT_STATUS_IS_OK(status)) {
7049 TALLOC_FREE(dir_hnd);
7050 TALLOC_FREE(talloced);
7051 reply_nterror(req, status);
7055 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7056 smb_fname_src->base_name,
7057 smb_fname_dst->base_name));
7059 status = copy_file(ctx, conn, smb_fname_src,
7060 smb_fname_dst, ofun, count,
7061 target_is_directory);
7062 if (NT_STATUS_IS_OK(status)) {
7066 TALLOC_FREE(talloced);
7068 TALLOC_FREE(dir_hnd);
7072 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7076 reply_outbuf(req, 1, 0);
7077 SSVAL(req->outbuf,smb_vwv0,count);
7079 TALLOC_FREE(smb_fname_src);
7080 TALLOC_FREE(smb_fname_dst);
7081 TALLOC_FREE(fname_src);
7082 TALLOC_FREE(fname_dst);
7083 TALLOC_FREE(fname_src_mask);
7084 TALLOC_FREE(fname_src_dir);
7086 END_PROFILE(SMBcopy);
7091 #define DBGC_CLASS DBGC_LOCKING
7093 /****************************************************************************
7094 Get a lock pid, dealing with large count requests.
7095 ****************************************************************************/
7097 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7098 bool large_file_format)
7100 if(!large_file_format)
7101 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7103 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7106 /****************************************************************************
7107 Get a lock count, dealing with large count requests.
7108 ****************************************************************************/
7110 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7111 bool large_file_format)
7115 if(!large_file_format) {
7116 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7119 #if defined(HAVE_LONGLONG)
7120 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7121 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7122 #else /* HAVE_LONGLONG */
7125 * NT4.x seems to be broken in that it sends large file (64 bit)
7126 * lockingX calls even if the CAP_LARGE_FILES was *not*
7127 * negotiated. For boxes without large unsigned ints truncate the
7128 * lock count by dropping the top 32 bits.
7131 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7132 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7133 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7134 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7135 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7138 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7139 #endif /* HAVE_LONGLONG */
7145 #if !defined(HAVE_LONGLONG)
7146 /****************************************************************************
7147 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7148 ****************************************************************************/
7150 static uint32 map_lock_offset(uint32 high, uint32 low)
7154 uint32 highcopy = high;
7157 * Try and find out how many significant bits there are in high.
7160 for(i = 0; highcopy; i++)
7164 * We use 31 bits not 32 here as POSIX
7165 * lock offsets may not be negative.
7168 mask = (~0) << (31 - i);
7171 return 0; /* Fail. */
7177 #endif /* !defined(HAVE_LONGLONG) */
7179 /****************************************************************************
7180 Get a lock offset, dealing with large offset requests.
7181 ****************************************************************************/
7183 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7184 bool large_file_format, bool *err)
7186 uint64_t offset = 0;
7190 if(!large_file_format) {
7191 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7194 #if defined(HAVE_LONGLONG)
7195 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7196 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7197 #else /* HAVE_LONGLONG */
7200 * NT4.x seems to be broken in that it sends large file (64 bit)
7201 * lockingX calls even if the CAP_LARGE_FILES was *not*
7202 * negotiated. For boxes without large unsigned ints mangle the
7203 * lock offset by mapping the top 32 bits onto the lower 32.
7206 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7207 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7208 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7211 if((new_low = map_lock_offset(high, low)) == 0) {
7213 return (uint64_t)-1;
7216 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7217 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7218 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7219 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7222 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7223 #endif /* HAVE_LONGLONG */
7229 NTSTATUS smbd_do_locking(struct smb_request *req,
7233 uint16_t num_ulocks,
7234 struct smbd_lock_element *ulocks,
7236 struct smbd_lock_element *locks,
7239 connection_struct *conn = req->conn;
7241 NTSTATUS status = NT_STATUS_OK;
7245 /* Data now points at the beginning of the list
7246 of smb_unlkrng structs */
7247 for(i = 0; i < (int)num_ulocks; i++) {
7248 struct smbd_lock_element *e = &ulocks[i];
7250 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7251 "pid %u, file %s\n",
7254 (unsigned int)e->smblctx,
7257 if (e->brltype != UNLOCK_LOCK) {
7258 /* this can only happen with SMB2 */
7259 return NT_STATUS_INVALID_PARAMETER;
7262 status = do_unlock(req->sconn->msg_ctx,
7269 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7270 nt_errstr(status)));
7272 if (!NT_STATUS_IS_OK(status)) {
7277 /* Setup the timeout in seconds. */
7279 if (!lp_blocking_locks(SNUM(conn))) {
7283 /* Data now points at the beginning of the list
7284 of smb_lkrng structs */
7286 for(i = 0; i < (int)num_locks; i++) {
7287 struct smbd_lock_element *e = &locks[i];
7289 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7290 "%llu, file %s timeout = %d\n",
7293 (unsigned long long)e->smblctx,
7297 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7298 struct blocking_lock_record *blr = NULL;
7300 if (num_locks > 1) {
7302 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7303 * if the lock vector contains one entry. When given mutliple cancel
7304 * requests in a single PDU we expect the server to return an
7305 * error. Windows servers seem to accept the request but only
7306 * cancel the first lock.
7307 * JRA - Do what Windows does (tm) :-).
7311 /* MS-CIFS (2.2.4.32.1) behavior. */
7312 return NT_STATUS_DOS(ERRDOS,
7313 ERRcancelviolation);
7315 /* Windows behavior. */
7317 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7318 "cancel request\n"));
7324 if (lp_blocking_locks(SNUM(conn))) {
7326 /* Schedule a message to ourselves to
7327 remove the blocking lock record and
7328 return the right error. */
7330 blr = blocking_lock_cancel_smb1(fsp,
7336 NT_STATUS_FILE_LOCK_CONFLICT);
7338 return NT_STATUS_DOS(
7340 ERRcancelviolation);
7343 /* Remove a matching pending lock. */
7344 status = do_lock_cancel(fsp,
7351 bool blocking_lock = timeout ? true : false;
7352 bool defer_lock = false;
7353 struct byte_range_lock *br_lck;
7354 uint64_t block_smblctx;
7356 br_lck = do_lock(req->sconn->msg_ctx,
7368 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7369 /* Windows internal resolution for blocking locks seems
7370 to be about 200ms... Don't wait for less than that. JRA. */
7371 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7372 timeout = lp_lock_spin_time();
7377 /* If a lock sent with timeout of zero would fail, and
7378 * this lock has been requested multiple times,
7379 * according to brl_lock_failed() we convert this
7380 * request to a blocking lock with a timeout of between
7381 * 150 - 300 milliseconds.
7383 * If lp_lock_spin_time() has been set to 0, we skip
7384 * this blocking retry and fail immediately.
7386 * Replacement for do_lock_spin(). JRA. */
7388 if (!req->sconn->using_smb2 &&
7389 br_lck && lp_blocking_locks(SNUM(conn)) &&
7390 lp_lock_spin_time() && !blocking_lock &&
7391 NT_STATUS_EQUAL((status),
7392 NT_STATUS_FILE_LOCK_CONFLICT))
7395 timeout = lp_lock_spin_time();
7398 if (br_lck && defer_lock) {
7400 * A blocking lock was requested. Package up
7401 * this smb into a queued request and push it
7402 * onto the blocking lock queue.
7404 if(push_blocking_lock_request(br_lck,
7415 TALLOC_FREE(br_lck);
7417 return NT_STATUS_OK;
7421 TALLOC_FREE(br_lck);
7424 if (!NT_STATUS_IS_OK(status)) {
7429 /* If any of the above locks failed, then we must unlock
7430 all of the previous locks (X/Open spec). */
7432 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7434 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7435 i = -1; /* we want to skip the for loop */
7439 * Ensure we don't do a remove on the lock that just failed,
7440 * as under POSIX rules, if we have a lock already there, we
7441 * will delete it (and we shouldn't) .....
7443 for(i--; i >= 0; i--) {
7444 struct smbd_lock_element *e = &locks[i];
7446 do_unlock(req->sconn->msg_ctx,
7456 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7457 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7459 return NT_STATUS_OK;
7462 /****************************************************************************
7463 Reply to a lockingX request.
7464 ****************************************************************************/
7466 void reply_lockingX(struct smb_request *req)
7468 connection_struct *conn = req->conn;
7470 unsigned char locktype;
7471 unsigned char oplocklevel;
7476 const uint8_t *data;
7477 bool large_file_format;
7479 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7480 struct smbd_lock_element *ulocks;
7481 struct smbd_lock_element *locks;
7484 START_PROFILE(SMBlockingX);
7487 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7488 END_PROFILE(SMBlockingX);
7492 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7493 locktype = CVAL(req->vwv+3, 0);
7494 oplocklevel = CVAL(req->vwv+3, 1);
7495 num_ulocks = SVAL(req->vwv+6, 0);
7496 num_locks = SVAL(req->vwv+7, 0);
7497 lock_timeout = IVAL(req->vwv+4, 0);
7498 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7500 if (!check_fsp(conn, req, fsp)) {
7501 END_PROFILE(SMBlockingX);
7507 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7508 /* we don't support these - and CANCEL_LOCK makes w2k
7509 and XP reboot so I don't really want to be
7510 compatible! (tridge) */
7511 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7512 END_PROFILE(SMBlockingX);
7516 /* Check if this is an oplock break on a file
7517 we have granted an oplock on.
7519 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7520 /* Client can insist on breaking to none. */
7521 bool break_to_none = (oplocklevel == 0);
7524 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7525 "for fnum = %d\n", (unsigned int)oplocklevel,
7529 * Make sure we have granted an exclusive or batch oplock on
7533 if (fsp->oplock_type == 0) {
7535 /* The Samba4 nbench simulator doesn't understand
7536 the difference between break to level2 and break
7537 to none from level2 - it sends oplock break
7538 replies in both cases. Don't keep logging an error
7539 message here - just ignore it. JRA. */
7541 DEBUG(5,("reply_lockingX: Error : oplock break from "
7542 "client for fnum = %d (oplock=%d) and no "
7543 "oplock granted on this file (%s).\n",
7544 fsp->fnum, fsp->oplock_type,
7547 /* if this is a pure oplock break request then don't
7549 if (num_locks == 0 && num_ulocks == 0) {
7550 END_PROFILE(SMBlockingX);
7553 END_PROFILE(SMBlockingX);
7554 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7559 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7561 result = remove_oplock(fsp);
7563 result = downgrade_oplock(fsp);
7567 DEBUG(0, ("reply_lockingX: error in removing "
7568 "oplock on file %s\n", fsp_str_dbg(fsp)));
7569 /* Hmmm. Is this panic justified? */
7570 smb_panic("internal tdb error");
7573 reply_to_oplock_break_requests(fsp);
7575 /* if this is a pure oplock break request then don't send a
7577 if (num_locks == 0 && num_ulocks == 0) {
7578 /* Sanity check - ensure a pure oplock break is not a
7580 if(CVAL(req->vwv+0, 0) != 0xff)
7581 DEBUG(0,("reply_lockingX: Error : pure oplock "
7582 "break is a chained %d request !\n",
7583 (unsigned int)CVAL(req->vwv+0, 0)));
7584 END_PROFILE(SMBlockingX);
7590 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7591 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7592 END_PROFILE(SMBlockingX);
7596 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7597 if (ulocks == NULL) {
7598 reply_nterror(req, NT_STATUS_NO_MEMORY);
7599 END_PROFILE(SMBlockingX);
7603 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7604 if (locks == NULL) {
7605 reply_nterror(req, NT_STATUS_NO_MEMORY);
7606 END_PROFILE(SMBlockingX);
7610 /* Data now points at the beginning of the list
7611 of smb_unlkrng structs */
7612 for(i = 0; i < (int)num_ulocks; i++) {
7613 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7614 ulocks[i].count = get_lock_count(data, i, large_file_format);
7615 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7616 ulocks[i].brltype = UNLOCK_LOCK;
7619 * There is no error code marked "stupid client bug".... :-).
7622 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7623 END_PROFILE(SMBlockingX);
7628 /* Now do any requested locks */
7629 data += ((large_file_format ? 20 : 10)*num_ulocks);
7631 /* Data now points at the beginning of the list
7632 of smb_lkrng structs */
7634 for(i = 0; i < (int)num_locks; i++) {
7635 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7636 locks[i].count = get_lock_count(data, i, large_file_format);
7637 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7639 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7640 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7641 locks[i].brltype = PENDING_READ_LOCK;
7643 locks[i].brltype = READ_LOCK;
7646 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7647 locks[i].brltype = PENDING_WRITE_LOCK;
7649 locks[i].brltype = WRITE_LOCK;
7654 * There is no error code marked "stupid client bug".... :-).
7657 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7658 END_PROFILE(SMBlockingX);
7663 status = smbd_do_locking(req, fsp,
7664 locktype, lock_timeout,
7668 if (!NT_STATUS_IS_OK(status)) {
7669 END_PROFILE(SMBlockingX);
7670 reply_nterror(req, status);
7674 END_PROFILE(SMBlockingX);
7678 reply_outbuf(req, 2, 0);
7680 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7681 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7683 END_PROFILE(SMBlockingX);
7688 #define DBGC_CLASS DBGC_ALL
7690 /****************************************************************************
7691 Reply to a SMBreadbmpx (read block multiplex) request.
7692 Always reply with an error, if someone has a platform really needs this,
7693 please contact vl@samba.org
7694 ****************************************************************************/
7696 void reply_readbmpx(struct smb_request *req)
7698 START_PROFILE(SMBreadBmpx);
7699 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7700 END_PROFILE(SMBreadBmpx);
7704 /****************************************************************************
7705 Reply to a SMBreadbs (read block multiplex secondary) request.
7706 Always reply with an error, if someone has a platform really needs this,
7707 please contact vl@samba.org
7708 ****************************************************************************/
7710 void reply_readbs(struct smb_request *req)
7712 START_PROFILE(SMBreadBs);
7713 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7714 END_PROFILE(SMBreadBs);
7718 /****************************************************************************
7719 Reply to a SMBsetattrE.
7720 ****************************************************************************/
7722 void reply_setattrE(struct smb_request *req)
7724 connection_struct *conn = req->conn;
7725 struct smb_file_time ft;
7729 START_PROFILE(SMBsetattrE);
7733 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7737 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7739 if(!fsp || (fsp->conn != conn)) {
7740 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7745 * Convert the DOS times into unix times.
7748 ft.atime = convert_time_t_to_timespec(
7749 srv_make_unix_date2(req->vwv+3));
7750 ft.mtime = convert_time_t_to_timespec(
7751 srv_make_unix_date2(req->vwv+5));
7752 ft.create_time = convert_time_t_to_timespec(
7753 srv_make_unix_date2(req->vwv+1));
7755 reply_outbuf(req, 0, 0);
7758 * Patch from Ray Frush <frush@engr.colostate.edu>
7759 * Sometimes times are sent as zero - ignore them.
7762 /* Ensure we have a valid stat struct for the source. */
7763 status = vfs_stat_fsp(fsp);
7764 if (!NT_STATUS_IS_OK(status)) {
7765 reply_nterror(req, status);
7769 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7770 if (!NT_STATUS_IS_OK(status)) {
7771 reply_nterror(req, status);
7775 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7778 (unsigned int)ft.atime.tv_sec,
7779 (unsigned int)ft.mtime.tv_sec,
7780 (unsigned int)ft.create_time.tv_sec
7783 END_PROFILE(SMBsetattrE);
7788 /* Back from the dead for OS/2..... JRA. */
7790 /****************************************************************************
7791 Reply to a SMBwritebmpx (write block multiplex primary) request.
7792 Always reply with an error, if someone has a platform really needs this,
7793 please contact vl@samba.org
7794 ****************************************************************************/
7796 void reply_writebmpx(struct smb_request *req)
7798 START_PROFILE(SMBwriteBmpx);
7799 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7800 END_PROFILE(SMBwriteBmpx);
7804 /****************************************************************************
7805 Reply to a SMBwritebs (write block multiplex secondary) request.
7806 Always reply with an error, if someone has a platform really needs this,
7807 please contact vl@samba.org
7808 ****************************************************************************/
7810 void reply_writebs(struct smb_request *req)
7812 START_PROFILE(SMBwriteBs);
7813 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7814 END_PROFILE(SMBwriteBs);
7818 /****************************************************************************
7819 Reply to a SMBgetattrE.
7820 ****************************************************************************/
7822 void reply_getattrE(struct smb_request *req)
7824 connection_struct *conn = req->conn;
7827 struct timespec create_ts;
7829 START_PROFILE(SMBgetattrE);
7832 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7833 END_PROFILE(SMBgetattrE);
7837 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7839 if(!fsp || (fsp->conn != conn)) {
7840 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7841 END_PROFILE(SMBgetattrE);
7845 /* Do an fstat on this file */
7847 reply_nterror(req, map_nt_error_from_unix(errno));
7848 END_PROFILE(SMBgetattrE);
7852 mode = dos_mode(conn, fsp->fsp_name);
7855 * Convert the times into dos times. Set create
7856 * date to be last modify date as UNIX doesn't save
7860 reply_outbuf(req, 11, 0);
7862 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7863 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7864 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7865 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7866 /* Should we check pending modtime here ? JRA */
7867 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7868 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7871 SIVAL(req->outbuf, smb_vwv6, 0);
7872 SIVAL(req->outbuf, smb_vwv8, 0);
7874 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7875 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
7876 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7878 SSVAL(req->outbuf,smb_vwv10, mode);
7880 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7882 END_PROFILE(SMBgetattrE);