2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
29 #include "smbd/globals.h"
30 #include "fake_file.h"
31 #include "../librpc/gen_ndr/cli_spoolss.h"
32 #include "rpc_client/cli_spoolss.h"
33 #include "rpc_client/init_spoolss.h"
35 /****************************************************************************
36 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
37 path or anything including wildcards.
38 We're assuming here that '/' is not the second byte in any multibyte char
39 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
41 ****************************************************************************/
43 /* Custom version for processing POSIX paths. */
44 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
46 static NTSTATUS check_path_syntax_internal(char *path,
48 bool *p_last_component_contains_wcard)
52 NTSTATUS ret = NT_STATUS_OK;
53 bool start_of_name_component = True;
54 bool stream_started = false;
56 *p_last_component_contains_wcard = False;
63 return NT_STATUS_OBJECT_NAME_INVALID;
66 return NT_STATUS_OBJECT_NAME_INVALID;
68 if (strchr_m(&s[1], ':')) {
69 return NT_STATUS_OBJECT_NAME_INVALID;
75 if ((*s == ':') && !posix_path && !stream_started) {
76 if (*p_last_component_contains_wcard) {
77 return NT_STATUS_OBJECT_NAME_INVALID;
79 /* Stream names allow more characters than file names.
80 We're overloading posix_path here to allow a wider
81 range of characters. If stream_started is true this
82 is still a Windows path even if posix_path is true.
85 stream_started = true;
86 start_of_name_component = false;
90 return NT_STATUS_OBJECT_NAME_INVALID;
94 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
96 * Safe to assume is not the second part of a mb char
97 * as this is handled below.
99 /* Eat multiple '/' or '\\' */
100 while (IS_PATH_SEP(*s,posix_path)) {
103 if ((d != path) && (*s != '\0')) {
104 /* We only care about non-leading or trailing '/' or '\\' */
108 start_of_name_component = True;
110 *p_last_component_contains_wcard = False;
114 if (start_of_name_component) {
115 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
116 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
119 * No mb char starts with '.' so we're safe checking the directory separator here.
122 /* If we just added a '/' - delete it */
123 if ((d > path) && (*(d-1) == '/')) {
128 /* Are we at the start ? Can't go back further if so. */
130 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
133 /* Go back one level... */
134 /* We know this is safe as '/' cannot be part of a mb sequence. */
135 /* NOTE - if this assumption is invalid we are not in good shape... */
136 /* Decrement d first as d points to the *next* char to write into. */
137 for (d--; d > path; d--) {
141 s += 2; /* Else go past the .. */
142 /* We're still at the start of a name component, just the previous one. */
145 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
157 if (*s <= 0x1f || *s == '|') {
158 return NT_STATUS_OBJECT_NAME_INVALID;
166 *p_last_component_contains_wcard = True;
175 /* Get the size of the next MB character. */
176 next_codepoint(s,&siz);
194 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
196 return NT_STATUS_INVALID_PARAMETER;
199 start_of_name_component = False;
207 /****************************************************************************
208 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
209 No wildcards allowed.
210 ****************************************************************************/
212 NTSTATUS check_path_syntax(char *path)
215 return check_path_syntax_internal(path, False, &ignore);
218 /****************************************************************************
219 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
220 Wildcards allowed - p_contains_wcard returns true if the last component contained
222 ****************************************************************************/
224 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
226 return check_path_syntax_internal(path, False, p_contains_wcard);
229 /****************************************************************************
230 Check the path for a POSIX client.
231 We're assuming here that '/' is not the second byte in any multibyte char
232 set (a safe assumption).
233 ****************************************************************************/
235 NTSTATUS check_path_syntax_posix(char *path)
238 return check_path_syntax_internal(path, True, &ignore);
241 /****************************************************************************
242 Pull a string and check the path allowing a wilcard - provide for error return.
243 ****************************************************************************/
245 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
246 const char *base_ptr,
253 bool *contains_wcard)
259 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
263 *err = NT_STATUS_INVALID_PARAMETER;
267 *contains_wcard = False;
269 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
271 * For a DFS path the function parse_dfs_path()
272 * will do the path processing, just make a copy.
278 if (lp_posix_pathnames()) {
279 *err = check_path_syntax_posix(*pp_dest);
281 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
287 /****************************************************************************
288 Pull a string and check the path - provide for error return.
289 ****************************************************************************/
291 size_t srvstr_get_path(TALLOC_CTX *ctx,
292 const char *base_ptr,
301 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
302 src_len, flags, err, &ignore);
305 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
306 char **pp_dest, const char *src, int flags,
307 NTSTATUS *err, bool *contains_wcard)
309 return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
310 pp_dest, src, smbreq_bufrem(req, src),
311 flags, err, contains_wcard);
314 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
315 char **pp_dest, const char *src, int flags,
319 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
320 flags, err, &ignore);
323 /****************************************************************************
324 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
325 ****************************************************************************/
327 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
330 if ((fsp == NULL) || (conn == NULL)) {
331 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
334 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
335 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
341 /****************************************************************************
342 Check if we have a correct fsp pointing to a file.
343 ****************************************************************************/
345 bool check_fsp(connection_struct *conn, struct smb_request *req,
348 if (!check_fsp_open(conn, req, fsp)) {
351 if (fsp->is_directory) {
352 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
355 if (fsp->fh->fd == -1) {
356 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
359 fsp->num_smb_operations++;
363 /****************************************************************************
364 Check if we have a correct fsp pointing to a quota fake file. Replacement for
365 the CHECK_NTQUOTA_HANDLE_OK macro.
366 ****************************************************************************/
368 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
371 if (!check_fsp_open(conn, req, fsp)) {
375 if (fsp->is_directory) {
379 if (fsp->fake_file_handle == NULL) {
383 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
387 if (fsp->fake_file_handle->private_data == NULL) {
394 static bool netbios_session_retarget(struct smbd_server_connection *sconn,
395 const char *name, int name_type)
398 char *trim_name_type;
399 const char *retarget_parm;
402 int retarget_type = 0x20;
403 int retarget_port = 139;
404 struct sockaddr_storage retarget_addr;
405 struct sockaddr_in *in_addr;
409 if (get_socket_port(sconn->sock) != 139) {
413 trim_name = talloc_strdup(talloc_tos(), name);
414 if (trim_name == NULL) {
417 trim_char(trim_name, ' ', ' ');
419 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
421 if (trim_name_type == NULL) {
425 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
426 trim_name_type, NULL);
427 if (retarget_parm == NULL) {
428 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
431 if (retarget_parm == NULL) {
435 retarget = talloc_strdup(trim_name, retarget_parm);
436 if (retarget == NULL) {
440 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
442 p = strchr(retarget, ':');
445 retarget_port = atoi(p);
448 p = strchr_m(retarget, '#');
451 sscanf(p, "%x", &retarget_type);
454 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
456 DEBUG(10, ("could not resolve %s\n", retarget));
460 if (retarget_addr.ss_family != AF_INET) {
461 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
465 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
467 _smb_setlen(outbuf, 6);
468 SCVAL(outbuf, 0, 0x84);
469 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
470 *(uint16_t *)(outbuf+8) = htons(retarget_port);
472 if (!srv_send_smb(sconn, (char *)outbuf, false, 0, false,
474 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
480 TALLOC_FREE(trim_name);
484 /****************************************************************************
485 Reply to a (netbios-level) special message.
486 ****************************************************************************/
488 void reply_special(struct smbd_server_connection *sconn, char *inbuf)
490 int msg_type = CVAL(inbuf,0);
491 int msg_flags = CVAL(inbuf,1);
493 char name_type1, name_type2;
496 * We only really use 4 bytes of the outbuf, but for the smb_setlen
497 * calculation & friends (srv_send_smb uses that) we need the full smb
500 char outbuf[smb_size];
504 memset(outbuf, '\0', sizeof(outbuf));
506 smb_setlen(outbuf,0);
509 case 0x81: /* session request */
511 if (sconn->nbt.got_session) {
512 exit_server_cleanly("multiple session request not permitted");
515 SCVAL(outbuf,0,0x82);
517 if (name_len(inbuf+4) > 50 ||
518 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
519 DEBUG(0,("Invalid name length in session request\n"));
522 name_type1 = name_extract(inbuf,4,name1);
523 name_type2 = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
524 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
525 name1, name_type1, name2, name_type2));
527 if (netbios_session_retarget(sconn, name1, name_type1)) {
528 exit_server_cleanly("retargeted client");
531 set_local_machine_name(name1, True);
532 set_remote_machine_name(name2, True);
534 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
535 get_local_machine_name(), get_remote_machine_name(),
538 if (name_type2 == 'R') {
539 /* We are being asked for a pathworks session ---
541 SCVAL(outbuf, 0,0x83);
545 /* only add the client's machine name to the list
546 of possibly valid usernames if we are operating
547 in share mode security */
548 if (lp_security() == SEC_SHARE) {
549 add_session_user(sconn, get_remote_machine_name());
552 reload_services(sconn->msg_ctx, sconn->sock, True);
555 sconn->nbt.got_session = true;
558 case 0x89: /* session keepalive request
559 (some old clients produce this?) */
560 SCVAL(outbuf,0,SMBkeepalive);
564 case 0x82: /* positive session response */
565 case 0x83: /* negative session response */
566 case 0x84: /* retarget session response */
567 DEBUG(0,("Unexpected session response\n"));
570 case SMBkeepalive: /* session keepalive */
575 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
576 msg_type, msg_flags));
578 srv_send_smb(sconn, outbuf, false, 0, false, NULL);
582 /****************************************************************************
584 conn POINTER CAN BE NULL HERE !
585 ****************************************************************************/
587 void reply_tcon(struct smb_request *req)
589 connection_struct *conn = req->conn;
591 char *service_buf = NULL;
592 char *password = NULL;
597 DATA_BLOB password_blob;
598 TALLOC_CTX *ctx = talloc_tos();
599 struct smbd_server_connection *sconn = req->sconn;
601 START_PROFILE(SMBtcon);
603 if (req->buflen < 4) {
604 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
605 END_PROFILE(SMBtcon);
609 p = (const char *)req->buf + 1;
610 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
612 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
614 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
617 if (service_buf == NULL || password == NULL || dev == NULL) {
618 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
619 END_PROFILE(SMBtcon);
622 p = strrchr_m(service_buf,'\\');
626 service = service_buf;
629 password_blob = data_blob(password, pwlen+1);
631 conn = make_connection(sconn,service,password_blob,dev,
632 req->vuid,&nt_status);
635 data_blob_clear_free(&password_blob);
638 reply_nterror(req, nt_status);
639 END_PROFILE(SMBtcon);
643 reply_outbuf(req, 2, 0);
644 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
645 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
646 SSVAL(req->outbuf,smb_tid,conn->cnum);
648 DEBUG(3,("tcon service=%s cnum=%d\n",
649 service, conn->cnum));
651 END_PROFILE(SMBtcon);
655 /****************************************************************************
656 Reply to a tcon and X.
657 conn POINTER CAN BE NULL HERE !
658 ****************************************************************************/
660 void reply_tcon_and_X(struct smb_request *req)
662 connection_struct *conn = req->conn;
663 const char *service = NULL;
665 TALLOC_CTX *ctx = talloc_tos();
666 /* what the cleint thinks the device is */
667 char *client_devicetype = NULL;
668 /* what the server tells the client the share represents */
669 const char *server_devicetype;
675 struct smbd_server_connection *sconn = req->sconn;
677 START_PROFILE(SMBtconX);
680 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
681 END_PROFILE(SMBtconX);
685 passlen = SVAL(req->vwv+3, 0);
686 tcon_flags = SVAL(req->vwv+2, 0);
688 /* we might have to close an old one */
689 if ((tcon_flags & 0x1) && conn) {
690 close_cnum(conn,req->vuid);
695 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
696 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
697 END_PROFILE(SMBtconX);
701 if (sconn->smb1.negprot.encrypted_passwords) {
702 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
703 if (lp_security() == SEC_SHARE) {
705 * Security = share always has a pad byte
706 * after the password.
708 p = (const char *)req->buf + passlen + 1;
710 p = (const char *)req->buf + passlen;
713 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
714 /* Ensure correct termination */
715 password.data[passlen]=0;
716 p = (const char *)req->buf + passlen + 1;
719 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
722 data_blob_clear_free(&password);
723 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
724 END_PROFILE(SMBtconX);
729 * the service name can be either: \\server\share
730 * or share directly like on the DELL PowerVault 705
733 q = strchr_m(path+2,'\\');
735 data_blob_clear_free(&password);
736 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
737 END_PROFILE(SMBtconX);
745 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
746 &client_devicetype, p,
747 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
749 if (client_devicetype == NULL) {
750 data_blob_clear_free(&password);
751 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
752 END_PROFILE(SMBtconX);
756 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
758 conn = make_connection(sconn, service, password, client_devicetype,
759 req->vuid, &nt_status);
762 data_blob_clear_free(&password);
765 reply_nterror(req, nt_status);
766 END_PROFILE(SMBtconX);
771 server_devicetype = "IPC";
772 else if ( IS_PRINT(conn) )
773 server_devicetype = "LPT1:";
775 server_devicetype = "A:";
777 if (get_Protocol() < PROTOCOL_NT1) {
778 reply_outbuf(req, 2, 0);
779 if (message_push_string(&req->outbuf, server_devicetype,
780 STR_TERMINATE|STR_ASCII) == -1) {
781 reply_nterror(req, NT_STATUS_NO_MEMORY);
782 END_PROFILE(SMBtconX);
786 /* NT sets the fstype of IPC$ to the null string */
787 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
789 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
790 /* Return permissions. */
794 reply_outbuf(req, 7, 0);
797 perm1 = FILE_ALL_ACCESS;
798 perm2 = FILE_ALL_ACCESS;
800 perm1 = CAN_WRITE(conn) ?
805 SIVAL(req->outbuf, smb_vwv3, perm1);
806 SIVAL(req->outbuf, smb_vwv5, perm2);
808 reply_outbuf(req, 3, 0);
811 if ((message_push_string(&req->outbuf, server_devicetype,
812 STR_TERMINATE|STR_ASCII) == -1)
813 || (message_push_string(&req->outbuf, fstype,
814 STR_TERMINATE) == -1)) {
815 reply_nterror(req, NT_STATUS_NO_MEMORY);
816 END_PROFILE(SMBtconX);
820 /* what does setting this bit do? It is set by NT4 and
821 may affect the ability to autorun mounted cdroms */
822 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
823 (lp_csc_policy(SNUM(conn)) << 2));
825 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
826 DEBUG(2,("Serving %s as a Dfs root\n",
827 lp_servicename(SNUM(conn)) ));
828 SSVAL(req->outbuf, smb_vwv2,
829 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
834 DEBUG(3,("tconX service=%s \n",
837 /* set the incoming and outgoing tid to the just created one */
838 SSVAL(req->inbuf,smb_tid,conn->cnum);
839 SSVAL(req->outbuf,smb_tid,conn->cnum);
841 END_PROFILE(SMBtconX);
843 req->tid = conn->cnum;
848 /****************************************************************************
849 Reply to an unknown type.
850 ****************************************************************************/
852 void reply_unknown_new(struct smb_request *req, uint8 type)
854 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
855 smb_fn_name(type), type, type));
856 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
860 /****************************************************************************
862 conn POINTER CAN BE NULL HERE !
863 ****************************************************************************/
865 void reply_ioctl(struct smb_request *req)
867 connection_struct *conn = req->conn;
874 START_PROFILE(SMBioctl);
877 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
878 END_PROFILE(SMBioctl);
882 device = SVAL(req->vwv+1, 0);
883 function = SVAL(req->vwv+2, 0);
884 ioctl_code = (device << 16) + function;
886 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
888 switch (ioctl_code) {
889 case IOCTL_QUERY_JOB_INFO:
893 reply_force_doserror(req, ERRSRV, ERRnosupport);
894 END_PROFILE(SMBioctl);
898 reply_outbuf(req, 8, replysize+1);
899 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
900 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
901 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
902 p = smb_buf(req->outbuf);
903 memset(p, '\0', replysize+1); /* valgrind-safe. */
904 p += 1; /* Allow for alignment */
906 switch (ioctl_code) {
907 case IOCTL_QUERY_JOB_INFO:
909 files_struct *fsp = file_fsp(
910 req, SVAL(req->vwv+0, 0));
912 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
913 END_PROFILE(SMBioctl);
917 if (fsp->print_file) {
918 SSVAL(p, 0, fsp->print_file->rap_jobid);
922 srvstr_push((char *)req->outbuf, req->flags2, p+2,
924 STR_TERMINATE|STR_ASCII);
926 srvstr_push((char *)req->outbuf, req->flags2,
927 p+18, lp_servicename(SNUM(conn)),
928 13, STR_TERMINATE|STR_ASCII);
936 END_PROFILE(SMBioctl);
940 /****************************************************************************
941 Strange checkpath NTSTATUS mapping.
942 ****************************************************************************/
944 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
946 /* Strange DOS error code semantics only for checkpath... */
947 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
948 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
949 /* We need to map to ERRbadpath */
950 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
956 /****************************************************************************
957 Reply to a checkpath.
958 ****************************************************************************/
960 void reply_checkpath(struct smb_request *req)
962 connection_struct *conn = req->conn;
963 struct smb_filename *smb_fname = NULL;
966 TALLOC_CTX *ctx = talloc_tos();
968 START_PROFILE(SMBcheckpath);
970 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
971 STR_TERMINATE, &status);
973 if (!NT_STATUS_IS_OK(status)) {
974 status = map_checkpath_error(req->flags2, status);
975 reply_nterror(req, status);
976 END_PROFILE(SMBcheckpath);
980 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
982 status = filename_convert(ctx,
984 req->flags2 & FLAGS2_DFS_PATHNAMES,
990 if (!NT_STATUS_IS_OK(status)) {
991 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
992 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
994 END_PROFILE(SMBcheckpath);
1000 if (!VALID_STAT(smb_fname->st) &&
1001 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1002 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1003 smb_fname_str_dbg(smb_fname), strerror(errno)));
1004 status = map_nt_error_from_unix(errno);
1008 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1009 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1010 ERRDOS, ERRbadpath);
1014 reply_outbuf(req, 0, 0);
1017 /* We special case this - as when a Windows machine
1018 is parsing a path is steps through the components
1019 one at a time - if a component fails it expects
1020 ERRbadpath, not ERRbadfile.
1022 status = map_checkpath_error(req->flags2, status);
1023 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1025 * Windows returns different error codes if
1026 * the parent directory is valid but not the
1027 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1028 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1029 * if the path is invalid.
1031 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1032 ERRDOS, ERRbadpath);
1036 reply_nterror(req, status);
1039 TALLOC_FREE(smb_fname);
1040 END_PROFILE(SMBcheckpath);
1044 /****************************************************************************
1046 ****************************************************************************/
1048 void reply_getatr(struct smb_request *req)
1050 connection_struct *conn = req->conn;
1051 struct smb_filename *smb_fname = NULL;
1058 TALLOC_CTX *ctx = talloc_tos();
1059 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1061 START_PROFILE(SMBgetatr);
1063 p = (const char *)req->buf + 1;
1064 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1065 if (!NT_STATUS_IS_OK(status)) {
1066 reply_nterror(req, status);
1070 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1071 under WfWg - weird! */
1072 if (*fname == '\0') {
1073 mode = aHIDDEN | aDIR;
1074 if (!CAN_WRITE(conn)) {
1080 status = filename_convert(ctx,
1082 req->flags2 & FLAGS2_DFS_PATHNAMES,
1087 if (!NT_STATUS_IS_OK(status)) {
1088 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1089 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1090 ERRSRV, ERRbadpath);
1093 reply_nterror(req, status);
1096 if (!VALID_STAT(smb_fname->st) &&
1097 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1098 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1099 smb_fname_str_dbg(smb_fname),
1101 reply_nterror(req, map_nt_error_from_unix(errno));
1105 mode = dos_mode(conn, smb_fname);
1106 size = smb_fname->st.st_ex_size;
1108 if (ask_sharemode) {
1109 struct timespec write_time_ts;
1110 struct file_id fileid;
1112 ZERO_STRUCT(write_time_ts);
1113 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1114 get_file_infos(fileid, NULL, &write_time_ts);
1115 if (!null_timespec(write_time_ts)) {
1116 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1120 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1126 reply_outbuf(req, 10, 0);
1128 SSVAL(req->outbuf,smb_vwv0,mode);
1129 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1130 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1132 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1134 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1136 if (get_Protocol() >= PROTOCOL_NT1) {
1137 SSVAL(req->outbuf, smb_flg2,
1138 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1141 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1142 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1145 TALLOC_FREE(smb_fname);
1147 END_PROFILE(SMBgetatr);
1151 /****************************************************************************
1153 ****************************************************************************/
1155 void reply_setatr(struct smb_request *req)
1157 struct smb_file_time ft;
1158 connection_struct *conn = req->conn;
1159 struct smb_filename *smb_fname = NULL;
1165 TALLOC_CTX *ctx = talloc_tos();
1167 START_PROFILE(SMBsetatr);
1172 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1176 p = (const char *)req->buf + 1;
1177 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1178 if (!NT_STATUS_IS_OK(status)) {
1179 reply_nterror(req, status);
1183 status = filename_convert(ctx,
1185 req->flags2 & FLAGS2_DFS_PATHNAMES,
1190 if (!NT_STATUS_IS_OK(status)) {
1191 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1192 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1193 ERRSRV, ERRbadpath);
1196 reply_nterror(req, status);
1200 if (smb_fname->base_name[0] == '.' &&
1201 smb_fname->base_name[1] == '\0') {
1203 * Not sure here is the right place to catch this
1204 * condition. Might be moved to somewhere else later -- vl
1206 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1210 mode = SVAL(req->vwv+0, 0);
1211 mtime = srv_make_unix_date3(req->vwv+1);
1213 ft.mtime = convert_time_t_to_timespec(mtime);
1214 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1215 if (!NT_STATUS_IS_OK(status)) {
1216 reply_nterror(req, status);
1220 if (mode != FILE_ATTRIBUTE_NORMAL) {
1221 if (VALID_STAT_OF_DIR(smb_fname->st))
1226 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1228 reply_nterror(req, map_nt_error_from_unix(errno));
1233 reply_outbuf(req, 0, 0);
1235 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1238 TALLOC_FREE(smb_fname);
1239 END_PROFILE(SMBsetatr);
1243 /****************************************************************************
1245 ****************************************************************************/
1247 void reply_dskattr(struct smb_request *req)
1249 connection_struct *conn = req->conn;
1250 uint64_t dfree,dsize,bsize;
1251 START_PROFILE(SMBdskattr);
1253 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1254 reply_nterror(req, map_nt_error_from_unix(errno));
1255 END_PROFILE(SMBdskattr);
1259 reply_outbuf(req, 5, 0);
1261 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1262 double total_space, free_space;
1263 /* we need to scale this to a number that DOS6 can handle. We
1264 use floating point so we can handle large drives on systems
1265 that don't have 64 bit integers
1267 we end up displaying a maximum of 2G to DOS systems
1269 total_space = dsize * (double)bsize;
1270 free_space = dfree * (double)bsize;
1272 dsize = (uint64_t)((total_space+63*512) / (64*512));
1273 dfree = (uint64_t)((free_space+63*512) / (64*512));
1275 if (dsize > 0xFFFF) dsize = 0xFFFF;
1276 if (dfree > 0xFFFF) dfree = 0xFFFF;
1278 SSVAL(req->outbuf,smb_vwv0,dsize);
1279 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1280 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1281 SSVAL(req->outbuf,smb_vwv3,dfree);
1283 SSVAL(req->outbuf,smb_vwv0,dsize);
1284 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1285 SSVAL(req->outbuf,smb_vwv2,512);
1286 SSVAL(req->outbuf,smb_vwv3,dfree);
1289 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1291 END_PROFILE(SMBdskattr);
1296 * Utility function to split the filename from the directory.
1298 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1299 char **fname_dir_out,
1300 char **fname_mask_out)
1302 const char *p = NULL;
1303 char *fname_dir = NULL;
1304 char *fname_mask = NULL;
1306 p = strrchr_m(fname_in, '/');
1308 fname_dir = talloc_strdup(ctx, ".");
1309 fname_mask = talloc_strdup(ctx, fname_in);
1311 fname_dir = talloc_strndup(ctx, fname_in,
1312 PTR_DIFF(p, fname_in));
1313 fname_mask = talloc_strdup(ctx, p+1);
1316 if (!fname_dir || !fname_mask) {
1317 TALLOC_FREE(fname_dir);
1318 TALLOC_FREE(fname_mask);
1319 return NT_STATUS_NO_MEMORY;
1322 *fname_dir_out = fname_dir;
1323 *fname_mask_out = fname_mask;
1324 return NT_STATUS_OK;
1327 /****************************************************************************
1329 Can be called from SMBsearch, SMBffirst or SMBfunique.
1330 ****************************************************************************/
1332 void reply_search(struct smb_request *req)
1334 connection_struct *conn = req->conn;
1336 const char *mask = NULL;
1337 char *directory = NULL;
1338 struct smb_filename *smb_fname = NULL;
1342 struct timespec date;
1344 unsigned int numentries = 0;
1345 unsigned int maxentries = 0;
1346 bool finished = False;
1351 bool check_descend = False;
1352 bool expect_close = False;
1354 bool mask_contains_wcard = False;
1355 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1356 TALLOC_CTX *ctx = talloc_tos();
1357 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1358 struct dptr_struct *dirptr = NULL;
1359 struct smbd_server_connection *sconn = req->sconn;
1361 START_PROFILE(SMBsearch);
1364 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1368 if (lp_posix_pathnames()) {
1369 reply_unknown_new(req, req->cmd);
1373 /* If we were called as SMBffirst then we must expect close. */
1374 if(req->cmd == SMBffirst) {
1375 expect_close = True;
1378 reply_outbuf(req, 1, 3);
1379 maxentries = SVAL(req->vwv+0, 0);
1380 dirtype = SVAL(req->vwv+1, 0);
1381 p = (const char *)req->buf + 1;
1382 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1383 &nt_status, &mask_contains_wcard);
1384 if (!NT_STATUS_IS_OK(nt_status)) {
1385 reply_nterror(req, nt_status);
1390 status_len = SVAL(p, 0);
1393 /* dirtype &= ~aDIR; */
1395 if (status_len == 0) {
1396 nt_status = filename_convert(ctx, conn,
1397 req->flags2 & FLAGS2_DFS_PATHNAMES,
1399 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1400 &mask_contains_wcard,
1402 if (!NT_STATUS_IS_OK(nt_status)) {
1403 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1404 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1405 ERRSRV, ERRbadpath);
1408 reply_nterror(req, nt_status);
1412 directory = smb_fname->base_name;
1414 p = strrchr_m(directory,'/');
1415 if ((p != NULL) && (*directory != '/')) {
1417 directory = talloc_strndup(ctx, directory,
1418 PTR_DIFF(p, directory));
1421 directory = talloc_strdup(ctx,".");
1425 reply_nterror(req, NT_STATUS_NO_MEMORY);
1429 memset((char *)status,'\0',21);
1430 SCVAL(status,0,(dirtype & 0x1F));
1432 nt_status = dptr_create(conn,
1438 mask_contains_wcard,
1441 if (!NT_STATUS_IS_OK(nt_status)) {
1442 reply_nterror(req, nt_status);
1445 dptr_num = dptr_dnum(dirptr);
1448 const char *dirpath;
1450 memcpy(status,p,21);
1451 status_dirtype = CVAL(status,0) & 0x1F;
1452 if (status_dirtype != (dirtype & 0x1F)) {
1453 dirtype = status_dirtype;
1456 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1460 dirpath = dptr_path(sconn, dptr_num);
1461 directory = talloc_strdup(ctx, dirpath);
1463 reply_nterror(req, NT_STATUS_NO_MEMORY);
1467 mask = dptr_wcard(sconn, dptr_num);
1472 * For a 'continue' search we have no string. So
1473 * check from the initial saved string.
1475 mask_contains_wcard = ms_has_wild(mask);
1476 dirtype = dptr_attr(sconn, dptr_num);
1479 DEBUG(4,("dptr_num is %d\n",dptr_num));
1481 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1482 dptr_init_search_op(dirptr);
1484 if ((dirtype&0x1F) == aVOLID) {
1485 char buf[DIR_STRUCT_SIZE];
1486 memcpy(buf,status,21);
1487 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1488 0,aVOLID,0,!allow_long_path_components)) {
1489 reply_nterror(req, NT_STATUS_NO_MEMORY);
1492 dptr_fill(sconn, buf+12,dptr_num);
1493 if (dptr_zero(buf+12) && (status_len==0)) {
1498 if (message_push_blob(&req->outbuf,
1499 data_blob_const(buf, sizeof(buf)))
1501 reply_nterror(req, NT_STATUS_NO_MEMORY);
1509 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1512 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1513 directory,lp_dontdescend(SNUM(conn))));
1514 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1515 check_descend = True;
1518 for (i=numentries;(i<maxentries) && !finished;i++) {
1519 finished = !get_dir_entry(ctx,
1530 char buf[DIR_STRUCT_SIZE];
1531 memcpy(buf,status,21);
1532 if (!make_dir_struct(ctx,
1538 convert_timespec_to_time_t(date),
1539 !allow_long_path_components)) {
1540 reply_nterror(req, NT_STATUS_NO_MEMORY);
1543 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1546 if (message_push_blob(&req->outbuf,
1547 data_blob_const(buf, sizeof(buf)))
1549 reply_nterror(req, NT_STATUS_NO_MEMORY);
1559 /* If we were called as SMBffirst with smb_search_id == NULL
1560 and no entries were found then return error and close dirptr
1563 if (numentries == 0) {
1564 dptr_close(sconn, &dptr_num);
1565 } else if(expect_close && status_len == 0) {
1566 /* Close the dptr - we know it's gone */
1567 dptr_close(sconn, &dptr_num);
1570 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1571 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1572 dptr_close(sconn, &dptr_num);
1575 if ((numentries == 0) && !mask_contains_wcard) {
1576 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1580 SSVAL(req->outbuf,smb_vwv0,numentries);
1581 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1582 SCVAL(smb_buf(req->outbuf),0,5);
1583 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1585 /* The replies here are never long name. */
1586 SSVAL(req->outbuf, smb_flg2,
1587 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1588 if (!allow_long_path_components) {
1589 SSVAL(req->outbuf, smb_flg2,
1590 SVAL(req->outbuf, smb_flg2)
1591 & (~FLAGS2_LONG_PATH_COMPONENTS));
1594 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1595 SSVAL(req->outbuf, smb_flg2,
1596 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1598 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1599 smb_fn_name(req->cmd),
1606 TALLOC_FREE(directory);
1607 TALLOC_FREE(smb_fname);
1608 END_PROFILE(SMBsearch);
1612 /****************************************************************************
1613 Reply to a fclose (stop directory search).
1614 ****************************************************************************/
1616 void reply_fclose(struct smb_request *req)
1624 bool path_contains_wcard = False;
1625 TALLOC_CTX *ctx = talloc_tos();
1626 struct smbd_server_connection *sconn = req->sconn;
1628 START_PROFILE(SMBfclose);
1630 if (lp_posix_pathnames()) {
1631 reply_unknown_new(req, req->cmd);
1632 END_PROFILE(SMBfclose);
1636 p = (const char *)req->buf + 1;
1637 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1638 &err, &path_contains_wcard);
1639 if (!NT_STATUS_IS_OK(err)) {
1640 reply_nterror(req, err);
1641 END_PROFILE(SMBfclose);
1645 status_len = SVAL(p,0);
1648 if (status_len == 0) {
1649 reply_force_doserror(req, ERRSRV, ERRsrverror);
1650 END_PROFILE(SMBfclose);
1654 memcpy(status,p,21);
1656 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1657 /* Close the dptr - we know it's gone */
1658 dptr_close(sconn, &dptr_num);
1661 reply_outbuf(req, 1, 0);
1662 SSVAL(req->outbuf,smb_vwv0,0);
1664 DEBUG(3,("search close\n"));
1666 END_PROFILE(SMBfclose);
1670 /****************************************************************************
1672 ****************************************************************************/
1674 void reply_open(struct smb_request *req)
1676 connection_struct *conn = req->conn;
1677 struct smb_filename *smb_fname = NULL;
1689 uint32 create_disposition;
1690 uint32 create_options = 0;
1691 uint32_t private_flags = 0;
1693 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1694 TALLOC_CTX *ctx = talloc_tos();
1696 START_PROFILE(SMBopen);
1699 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1703 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1704 deny_mode = SVAL(req->vwv+0, 0);
1705 dos_attr = SVAL(req->vwv+1, 0);
1707 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1708 STR_TERMINATE, &status);
1709 if (!NT_STATUS_IS_OK(status)) {
1710 reply_nterror(req, status);
1714 status = filename_convert(ctx,
1716 req->flags2 & FLAGS2_DFS_PATHNAMES,
1721 if (!NT_STATUS_IS_OK(status)) {
1722 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1723 reply_botherror(req,
1724 NT_STATUS_PATH_NOT_COVERED,
1725 ERRSRV, ERRbadpath);
1728 reply_nterror(req, status);
1732 if (!map_open_params_to_ntcreate(smb_fname, deny_mode,
1733 OPENX_FILE_EXISTS_OPEN, &access_mask,
1734 &share_mode, &create_disposition,
1735 &create_options, &private_flags)) {
1736 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1740 status = SMB_VFS_CREATE_FILE(
1743 0, /* root_dir_fid */
1744 smb_fname, /* fname */
1745 access_mask, /* access_mask */
1746 share_mode, /* share_access */
1747 create_disposition, /* create_disposition*/
1748 create_options, /* create_options */
1749 dos_attr, /* file_attributes */
1750 oplock_request, /* oplock_request */
1751 0, /* allocation_size */
1758 if (!NT_STATUS_IS_OK(status)) {
1759 if (open_was_deferred(req->mid)) {
1760 /* We have re-scheduled this call. */
1763 reply_openerror(req, status);
1767 size = smb_fname->st.st_ex_size;
1768 fattr = dos_mode(conn, smb_fname);
1770 /* Deal with other possible opens having a modified
1772 if (ask_sharemode) {
1773 struct timespec write_time_ts;
1775 ZERO_STRUCT(write_time_ts);
1776 get_file_infos(fsp->file_id, NULL, &write_time_ts);
1777 if (!null_timespec(write_time_ts)) {
1778 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1782 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1785 DEBUG(3,("attempt to open a directory %s\n",
1787 close_file(req, fsp, ERROR_CLOSE);
1788 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1789 ERRDOS, ERRnoaccess);
1793 reply_outbuf(req, 7, 0);
1794 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1795 SSVAL(req->outbuf,smb_vwv1,fattr);
1796 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1797 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1799 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1801 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1802 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1804 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1805 SCVAL(req->outbuf,smb_flg,
1806 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1809 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1810 SCVAL(req->outbuf,smb_flg,
1811 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1814 TALLOC_FREE(smb_fname);
1815 END_PROFILE(SMBopen);
1819 /****************************************************************************
1820 Reply to an open and X.
1821 ****************************************************************************/
1823 void reply_open_and_X(struct smb_request *req)
1825 connection_struct *conn = req->conn;
1826 struct smb_filename *smb_fname = NULL;
1831 /* Breakout the oplock request bits so we can set the
1832 reply bits separately. */
1833 int ex_oplock_request;
1834 int core_oplock_request;
1837 int smb_sattr = SVAL(req->vwv+4, 0);
1838 uint32 smb_time = make_unix_date3(req->vwv+6);
1846 uint64_t allocation_size;
1847 ssize_t retval = -1;
1850 uint32 create_disposition;
1851 uint32 create_options = 0;
1852 uint32_t private_flags = 0;
1853 TALLOC_CTX *ctx = talloc_tos();
1855 START_PROFILE(SMBopenX);
1857 if (req->wct < 15) {
1858 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1862 open_flags = SVAL(req->vwv+2, 0);
1863 deny_mode = SVAL(req->vwv+3, 0);
1864 smb_attr = SVAL(req->vwv+5, 0);
1865 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1866 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1867 oplock_request = ex_oplock_request | core_oplock_request;
1868 smb_ofun = SVAL(req->vwv+8, 0);
1869 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1871 /* If it's an IPC, pass off the pipe handler. */
1873 if (lp_nt_pipe_support()) {
1874 reply_open_pipe_and_X(conn, req);
1876 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1881 /* XXXX we need to handle passed times, sattr and flags */
1882 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1883 STR_TERMINATE, &status);
1884 if (!NT_STATUS_IS_OK(status)) {
1885 reply_nterror(req, status);
1889 status = filename_convert(ctx,
1891 req->flags2 & FLAGS2_DFS_PATHNAMES,
1896 if (!NT_STATUS_IS_OK(status)) {
1897 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1898 reply_botherror(req,
1899 NT_STATUS_PATH_NOT_COVERED,
1900 ERRSRV, ERRbadpath);
1903 reply_nterror(req, status);
1907 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, smb_ofun,
1908 &access_mask, &share_mode,
1909 &create_disposition,
1912 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1916 status = SMB_VFS_CREATE_FILE(
1919 0, /* root_dir_fid */
1920 smb_fname, /* fname */
1921 access_mask, /* access_mask */
1922 share_mode, /* share_access */
1923 create_disposition, /* create_disposition*/
1924 create_options, /* create_options */
1925 smb_attr, /* file_attributes */
1926 oplock_request, /* oplock_request */
1927 0, /* allocation_size */
1932 &smb_action); /* pinfo */
1934 if (!NT_STATUS_IS_OK(status)) {
1935 if (open_was_deferred(req->mid)) {
1936 /* We have re-scheduled this call. */
1939 reply_openerror(req, status);
1943 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1944 if the file is truncated or created. */
1945 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1946 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1947 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1948 close_file(req, fsp, ERROR_CLOSE);
1949 reply_nterror(req, NT_STATUS_DISK_FULL);
1952 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1954 close_file(req, fsp, ERROR_CLOSE);
1955 reply_nterror(req, NT_STATUS_DISK_FULL);
1958 smb_fname->st.st_ex_size =
1959 SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
1962 fattr = dos_mode(conn, smb_fname);
1963 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1965 close_file(req, fsp, ERROR_CLOSE);
1966 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1970 /* If the caller set the extended oplock request bit
1971 and we granted one (by whatever means) - set the
1972 correct bit for extended oplock reply.
1975 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1976 smb_action |= EXTENDED_OPLOCK_GRANTED;
1979 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1980 smb_action |= EXTENDED_OPLOCK_GRANTED;
1983 /* If the caller set the core oplock request bit
1984 and we granted one (by whatever means) - set the
1985 correct bit for core oplock reply.
1988 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1989 reply_outbuf(req, 19, 0);
1991 reply_outbuf(req, 15, 0);
1994 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1995 SCVAL(req->outbuf, smb_flg,
1996 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1999 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2000 SCVAL(req->outbuf, smb_flg,
2001 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2004 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2005 SSVAL(req->outbuf,smb_vwv3,fattr);
2006 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2007 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2009 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2011 SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size);
2012 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2013 SSVAL(req->outbuf,smb_vwv11,smb_action);
2015 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2016 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2021 TALLOC_FREE(smb_fname);
2022 END_PROFILE(SMBopenX);
2026 /****************************************************************************
2027 Reply to a SMBulogoffX.
2028 ****************************************************************************/
2030 void reply_ulogoffX(struct smb_request *req)
2032 struct smbd_server_connection *sconn = req->sconn;
2035 START_PROFILE(SMBulogoffX);
2037 vuser = get_valid_user_struct(sconn, req->vuid);
2040 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2044 /* in user level security we are supposed to close any files
2045 open by this user */
2046 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2047 file_close_user(req->vuid);
2050 invalidate_vuid(sconn, req->vuid);
2052 reply_outbuf(req, 2, 0);
2054 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2056 END_PROFILE(SMBulogoffX);
2057 req->vuid = UID_FIELD_INVALID;
2061 /****************************************************************************
2062 Reply to a mknew or a create.
2063 ****************************************************************************/
2065 void reply_mknew(struct smb_request *req)
2067 connection_struct *conn = req->conn;
2068 struct smb_filename *smb_fname = NULL;
2071 struct smb_file_time ft;
2073 int oplock_request = 0;
2075 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2076 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2077 uint32 create_disposition;
2078 uint32 create_options = 0;
2079 TALLOC_CTX *ctx = talloc_tos();
2081 START_PROFILE(SMBcreate);
2085 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2089 fattr = SVAL(req->vwv+0, 0);
2090 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2093 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2095 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2096 STR_TERMINATE, &status);
2097 if (!NT_STATUS_IS_OK(status)) {
2098 reply_nterror(req, status);
2102 status = filename_convert(ctx,
2104 req->flags2 & FLAGS2_DFS_PATHNAMES,
2109 if (!NT_STATUS_IS_OK(status)) {
2110 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2111 reply_botherror(req,
2112 NT_STATUS_PATH_NOT_COVERED,
2113 ERRSRV, ERRbadpath);
2116 reply_nterror(req, status);
2120 if (fattr & aVOLID) {
2121 DEBUG(0,("Attempt to create file (%s) with volid set - "
2122 "please report this\n",
2123 smb_fname_str_dbg(smb_fname)));
2126 if(req->cmd == SMBmknew) {
2127 /* We should fail if file exists. */
2128 create_disposition = FILE_CREATE;
2130 /* Create if file doesn't exist, truncate if it does. */
2131 create_disposition = FILE_OVERWRITE_IF;
2134 status = SMB_VFS_CREATE_FILE(
2137 0, /* root_dir_fid */
2138 smb_fname, /* fname */
2139 access_mask, /* access_mask */
2140 share_mode, /* share_access */
2141 create_disposition, /* create_disposition*/
2142 create_options, /* create_options */
2143 fattr, /* file_attributes */
2144 oplock_request, /* oplock_request */
2145 0, /* allocation_size */
2146 0, /* private_flags */
2152 if (!NT_STATUS_IS_OK(status)) {
2153 if (open_was_deferred(req->mid)) {
2154 /* We have re-scheduled this call. */
2157 reply_openerror(req, status);
2161 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2162 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2163 if (!NT_STATUS_IS_OK(status)) {
2164 END_PROFILE(SMBcreate);
2168 reply_outbuf(req, 1, 0);
2169 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2171 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2172 SCVAL(req->outbuf,smb_flg,
2173 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2176 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2177 SCVAL(req->outbuf,smb_flg,
2178 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2181 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2182 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2183 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2184 (unsigned int)fattr));
2187 TALLOC_FREE(smb_fname);
2188 END_PROFILE(SMBcreate);
2192 /****************************************************************************
2193 Reply to a create temporary file.
2194 ****************************************************************************/
2196 void reply_ctemp(struct smb_request *req)
2198 connection_struct *conn = req->conn;
2199 struct smb_filename *smb_fname = NULL;
2207 TALLOC_CTX *ctx = talloc_tos();
2209 START_PROFILE(SMBctemp);
2212 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2216 fattr = SVAL(req->vwv+0, 0);
2217 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2219 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2220 STR_TERMINATE, &status);
2221 if (!NT_STATUS_IS_OK(status)) {
2222 reply_nterror(req, status);
2226 fname = talloc_asprintf(ctx,
2230 fname = talloc_strdup(ctx, "TMXXXXXX");
2234 reply_nterror(req, NT_STATUS_NO_MEMORY);
2238 status = filename_convert(ctx, conn,
2239 req->flags2 & FLAGS2_DFS_PATHNAMES,
2244 if (!NT_STATUS_IS_OK(status)) {
2245 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2246 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2247 ERRSRV, ERRbadpath);
2250 reply_nterror(req, status);
2254 tmpfd = mkstemp(smb_fname->base_name);
2256 reply_nterror(req, map_nt_error_from_unix(errno));
2260 SMB_VFS_STAT(conn, smb_fname);
2262 /* We should fail if file does not exist. */
2263 status = SMB_VFS_CREATE_FILE(
2266 0, /* root_dir_fid */
2267 smb_fname, /* fname */
2268 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2269 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2270 FILE_OPEN, /* create_disposition*/
2271 0, /* create_options */
2272 fattr, /* file_attributes */
2273 oplock_request, /* oplock_request */
2274 0, /* allocation_size */
2275 0, /* private_flags */
2281 /* close fd from mkstemp() */
2284 if (!NT_STATUS_IS_OK(status)) {
2285 if (open_was_deferred(req->mid)) {
2286 /* We have re-scheduled this call. */
2289 reply_openerror(req, status);
2293 reply_outbuf(req, 1, 0);
2294 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2296 /* the returned filename is relative to the directory */
2297 s = strrchr_m(fsp->fsp_name->base_name, '/');
2299 s = fsp->fsp_name->base_name;
2305 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2306 thing in the byte section. JRA */
2307 SSVALS(p, 0, -1); /* what is this? not in spec */
2309 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2311 reply_nterror(req, NT_STATUS_NO_MEMORY);
2315 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2316 SCVAL(req->outbuf, smb_flg,
2317 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2320 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2321 SCVAL(req->outbuf, smb_flg,
2322 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2325 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2326 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2327 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2329 TALLOC_FREE(smb_fname);
2330 END_PROFILE(SMBctemp);
2334 /*******************************************************************
2335 Check if a user is allowed to rename a file.
2336 ********************************************************************/
2338 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2343 if (!CAN_WRITE(conn)) {
2344 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2347 fmode = dos_mode(conn, fsp->fsp_name);
2348 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2349 return NT_STATUS_NO_SUCH_FILE;
2352 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2353 if (fsp->posix_open) {
2354 return NT_STATUS_OK;
2357 /* If no pathnames are open below this
2358 directory, allow the rename. */
2360 if (file_find_subpath(fsp)) {
2361 return NT_STATUS_ACCESS_DENIED;
2363 return NT_STATUS_OK;
2366 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2367 return NT_STATUS_OK;
2370 return NT_STATUS_ACCESS_DENIED;
2373 /*******************************************************************
2374 * unlink a file with all relevant access checks
2375 *******************************************************************/
2377 static NTSTATUS do_unlink(connection_struct *conn,
2378 struct smb_request *req,
2379 struct smb_filename *smb_fname,
2384 uint32 dirtype_orig = dirtype;
2387 bool posix_paths = lp_posix_pathnames();
2389 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2390 smb_fname_str_dbg(smb_fname),
2393 if (!CAN_WRITE(conn)) {
2394 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2398 ret = SMB_VFS_LSTAT(conn, smb_fname);
2400 ret = SMB_VFS_STAT(conn, smb_fname);
2403 return map_nt_error_from_unix(errno);
2406 fattr = dos_mode(conn, smb_fname);
2408 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2409 dirtype = aDIR|aARCH|aRONLY;
2412 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2414 return NT_STATUS_NO_SUCH_FILE;
2417 if (!dir_check_ftype(conn, fattr, dirtype)) {
2419 return NT_STATUS_FILE_IS_A_DIRECTORY;
2421 return NT_STATUS_NO_SUCH_FILE;
2424 if (dirtype_orig & 0x8000) {
2425 /* These will never be set for POSIX. */
2426 return NT_STATUS_NO_SUCH_FILE;
2430 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2431 return NT_STATUS_FILE_IS_A_DIRECTORY;
2434 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2435 return NT_STATUS_NO_SUCH_FILE;
2438 if (dirtype & 0xFF00) {
2439 /* These will never be set for POSIX. */
2440 return NT_STATUS_NO_SUCH_FILE;
2445 return NT_STATUS_NO_SUCH_FILE;
2448 /* Can't delete a directory. */
2450 return NT_STATUS_FILE_IS_A_DIRECTORY;
2455 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2456 return NT_STATUS_OBJECT_NAME_INVALID;
2457 #endif /* JRATEST */
2459 /* On open checks the open itself will check the share mode, so
2460 don't do it here as we'll get it wrong. */
2462 status = SMB_VFS_CREATE_FILE
2465 0, /* root_dir_fid */
2466 smb_fname, /* fname */
2467 DELETE_ACCESS, /* access_mask */
2468 FILE_SHARE_NONE, /* share_access */
2469 FILE_OPEN, /* create_disposition*/
2470 FILE_NON_DIRECTORY_FILE, /* create_options */
2471 /* file_attributes */
2472 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2473 FILE_ATTRIBUTE_NORMAL,
2474 0, /* oplock_request */
2475 0, /* allocation_size */
2476 0, /* private_flags */
2482 if (!NT_STATUS_IS_OK(status)) {
2483 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2484 nt_errstr(status)));
2488 status = can_set_delete_on_close(fsp, fattr);
2489 if (!NT_STATUS_IS_OK(status)) {
2490 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2492 smb_fname_str_dbg(smb_fname),
2493 nt_errstr(status)));
2494 close_file(req, fsp, NORMAL_CLOSE);
2498 /* The set is across all open files on this dev/inode pair. */
2499 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2500 close_file(req, fsp, NORMAL_CLOSE);
2501 return NT_STATUS_ACCESS_DENIED;
2504 return close_file(req, fsp, NORMAL_CLOSE);
2507 /****************************************************************************
2508 The guts of the unlink command, split out so it may be called by the NT SMB
2510 ****************************************************************************/
2512 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2513 uint32 dirtype, struct smb_filename *smb_fname,
2516 char *fname_dir = NULL;
2517 char *fname_mask = NULL;
2519 NTSTATUS status = NT_STATUS_OK;
2520 TALLOC_CTX *ctx = talloc_tos();
2522 /* Split up the directory from the filename/mask. */
2523 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2524 &fname_dir, &fname_mask);
2525 if (!NT_STATUS_IS_OK(status)) {
2530 * We should only check the mangled cache
2531 * here if unix_convert failed. This means
2532 * that the path in 'mask' doesn't exist
2533 * on the file system and so we need to look
2534 * for a possible mangle. This patch from
2535 * Tine Smukavec <valentin.smukavec@hermes.si>.
2538 if (!VALID_STAT(smb_fname->st) &&
2539 mangle_is_mangled(fname_mask, conn->params)) {
2540 char *new_mask = NULL;
2541 mangle_lookup_name_from_8_3(ctx, fname_mask,
2542 &new_mask, conn->params);
2544 TALLOC_FREE(fname_mask);
2545 fname_mask = new_mask;
2552 * Only one file needs to be unlinked. Append the mask back
2553 * onto the directory.
2555 TALLOC_FREE(smb_fname->base_name);
2556 smb_fname->base_name = talloc_asprintf(smb_fname,
2560 if (!smb_fname->base_name) {
2561 status = NT_STATUS_NO_MEMORY;
2565 dirtype = FILE_ATTRIBUTE_NORMAL;
2568 status = check_name(conn, smb_fname->base_name);
2569 if (!NT_STATUS_IS_OK(status)) {
2573 status = do_unlink(conn, req, smb_fname, dirtype);
2574 if (!NT_STATUS_IS_OK(status)) {
2580 struct smb_Dir *dir_hnd = NULL;
2582 const char *dname = NULL;
2583 char *talloced = NULL;
2585 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2586 status = NT_STATUS_OBJECT_NAME_INVALID;
2590 if (strequal(fname_mask,"????????.???")) {
2591 TALLOC_FREE(fname_mask);
2592 fname_mask = talloc_strdup(ctx, "*");
2594 status = NT_STATUS_NO_MEMORY;
2599 status = check_name(conn, fname_dir);
2600 if (!NT_STATUS_IS_OK(status)) {
2604 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2606 if (dir_hnd == NULL) {
2607 status = map_nt_error_from_unix(errno);
2611 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2612 the pattern matches against the long name, otherwise the short name
2613 We don't implement this yet XXXX
2616 status = NT_STATUS_NO_SUCH_FILE;
2618 while ((dname = ReadDirName(dir_hnd, &offset,
2619 &smb_fname->st, &talloced))) {
2620 TALLOC_CTX *frame = talloc_stackframe();
2622 if (!is_visible_file(conn, fname_dir, dname,
2623 &smb_fname->st, true)) {
2625 TALLOC_FREE(talloced);
2629 /* Quick check for "." and ".." */
2630 if (ISDOT(dname) || ISDOTDOT(dname)) {
2632 TALLOC_FREE(talloced);
2636 if(!mask_match(dname, fname_mask,
2637 conn->case_sensitive)) {
2639 TALLOC_FREE(talloced);
2643 TALLOC_FREE(smb_fname->base_name);
2644 smb_fname->base_name =
2645 talloc_asprintf(smb_fname, "%s/%s",
2648 if (!smb_fname->base_name) {
2649 TALLOC_FREE(dir_hnd);
2650 status = NT_STATUS_NO_MEMORY;
2652 TALLOC_FREE(talloced);
2656 status = check_name(conn, smb_fname->base_name);
2657 if (!NT_STATUS_IS_OK(status)) {
2658 TALLOC_FREE(dir_hnd);
2660 TALLOC_FREE(talloced);
2664 status = do_unlink(conn, req, smb_fname, dirtype);
2665 if (!NT_STATUS_IS_OK(status)) {
2667 TALLOC_FREE(talloced);
2672 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2673 smb_fname->base_name));
2676 TALLOC_FREE(talloced);
2678 TALLOC_FREE(dir_hnd);
2681 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2682 status = map_nt_error_from_unix(errno);
2686 TALLOC_FREE(fname_dir);
2687 TALLOC_FREE(fname_mask);
2691 /****************************************************************************
2693 ****************************************************************************/
2695 void reply_unlink(struct smb_request *req)
2697 connection_struct *conn = req->conn;
2699 struct smb_filename *smb_fname = NULL;
2702 bool path_contains_wcard = False;
2703 TALLOC_CTX *ctx = talloc_tos();
2705 START_PROFILE(SMBunlink);
2708 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2712 dirtype = SVAL(req->vwv+0, 0);
2714 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2715 STR_TERMINATE, &status,
2716 &path_contains_wcard);
2717 if (!NT_STATUS_IS_OK(status)) {
2718 reply_nterror(req, status);
2722 status = filename_convert(ctx, conn,
2723 req->flags2 & FLAGS2_DFS_PATHNAMES,
2725 UCF_COND_ALLOW_WCARD_LCOMP,
2726 &path_contains_wcard,
2728 if (!NT_STATUS_IS_OK(status)) {
2729 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2730 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2731 ERRSRV, ERRbadpath);
2734 reply_nterror(req, status);
2738 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2740 status = unlink_internals(conn, req, dirtype, smb_fname,
2741 path_contains_wcard);
2742 if (!NT_STATUS_IS_OK(status)) {
2743 if (open_was_deferred(req->mid)) {
2744 /* We have re-scheduled this call. */
2747 reply_nterror(req, status);
2751 reply_outbuf(req, 0, 0);
2753 TALLOC_FREE(smb_fname);
2754 END_PROFILE(SMBunlink);
2758 /****************************************************************************
2760 ****************************************************************************/
2762 static void fail_readraw(void)
2764 const char *errstr = talloc_asprintf(talloc_tos(),
2765 "FAIL ! reply_readbraw: socket write fail (%s)",
2770 exit_server_cleanly(errstr);
2773 /****************************************************************************
2774 Fake (read/write) sendfile. Returns -1 on read or write fail.
2775 ****************************************************************************/
2777 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2781 size_t tosend = nread;
2788 bufsize = MIN(nread, 65536);
2790 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2794 while (tosend > 0) {
2798 if (tosend > bufsize) {
2803 ret = read_file(fsp,buf,startpos,cur_read);
2809 /* If we had a short read, fill with zeros. */
2810 if (ret < cur_read) {
2811 memset(buf + ret, '\0', cur_read - ret);
2814 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
2816 char addr[INET6_ADDRSTRLEN];
2818 * Try and give an error message saying what
2821 DEBUG(0, ("write_data failed for client %s. "
2823 get_peer_addr(fsp->conn->sconn->sock, addr,
2830 startpos += cur_read;
2834 return (ssize_t)nread;
2837 #if defined(WITH_SENDFILE)
2838 /****************************************************************************
2839 Deal with the case of sendfile reading less bytes from the file than
2840 requested. Fill with zeros (all we can do).
2841 ****************************************************************************/
2843 static void sendfile_short_send(files_struct *fsp,
2848 #define SHORT_SEND_BUFSIZE 1024
2849 if (nread < headersize) {
2850 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2851 "header for file %s (%s). Terminating\n",
2852 fsp_str_dbg(fsp), strerror(errno)));
2853 exit_server_cleanly("sendfile_short_send failed");
2856 nread -= headersize;
2858 if (nread < smb_maxcnt) {
2859 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2861 exit_server_cleanly("sendfile_short_send: "
2865 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2866 "with zeros !\n", fsp_str_dbg(fsp)));
2868 while (nread < smb_maxcnt) {
2870 * We asked for the real file size and told sendfile
2871 * to not go beyond the end of the file. But it can
2872 * happen that in between our fstat call and the
2873 * sendfile call the file was truncated. This is very
2874 * bad because we have already announced the larger
2875 * number of bytes to the client.
2877 * The best we can do now is to send 0-bytes, just as
2878 * a read from a hole in a sparse file would do.
2880 * This should happen rarely enough that I don't care
2881 * about efficiency here :-)
2885 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2886 if (write_data(fsp->conn->sconn->sock, buf, to_write)
2888 char addr[INET6_ADDRSTRLEN];
2890 * Try and give an error message saying what
2893 DEBUG(0, ("write_data failed for client %s. "
2896 fsp->conn->sconn->sock, addr,
2899 exit_server_cleanly("sendfile_short_send: "
2900 "write_data failed");
2907 #endif /* defined WITH_SENDFILE */
2909 /****************************************************************************
2910 Return a readbraw error (4 bytes of zero).
2911 ****************************************************************************/
2913 static void reply_readbraw_error(struct smbd_server_connection *sconn)
2919 smbd_lock_socket(sconn);
2920 if (write_data(sconn->sock,header,4) != 4) {
2921 char addr[INET6_ADDRSTRLEN];
2923 * Try and give an error message saying what
2926 DEBUG(0, ("write_data failed for client %s. "
2928 get_peer_addr(sconn->sock, addr, sizeof(addr)),
2933 smbd_unlock_socket(sconn);
2936 /****************************************************************************
2937 Use sendfile in readbraw.
2938 ****************************************************************************/
2940 static void send_file_readbraw(connection_struct *conn,
2941 struct smb_request *req,
2947 struct smbd_server_connection *sconn = req->sconn;
2948 char *outbuf = NULL;
2951 #if defined(WITH_SENDFILE)
2953 * We can only use sendfile on a non-chained packet
2954 * but we can use on a non-oplocked file. tridge proved this
2955 * on a train in Germany :-). JRA.
2956 * reply_readbraw has already checked the length.
2959 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2960 (fsp->wcp == NULL) &&
2961 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
2962 ssize_t sendfile_read = -1;
2964 DATA_BLOB header_blob;
2966 _smb_setlen(header,nread);
2967 header_blob = data_blob_const(header, 4);
2969 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
2970 &header_blob, startpos,
2972 if (sendfile_read == -1) {
2973 /* Returning ENOSYS means no data at all was sent.
2974 * Do this as a normal read. */
2975 if (errno == ENOSYS) {
2976 goto normal_readbraw;
2980 * Special hack for broken Linux with no working sendfile. If we
2981 * return EINTR we sent the header but not the rest of the data.
2982 * Fake this up by doing read/write calls.
2984 if (errno == EINTR) {
2985 /* Ensure we don't do this again. */
2986 set_use_sendfile(SNUM(conn), False);
2987 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2989 if (fake_sendfile(fsp, startpos, nread) == -1) {
2990 DEBUG(0,("send_file_readbraw: "
2991 "fake_sendfile failed for "
2995 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3000 DEBUG(0,("send_file_readbraw: sendfile failed for "
3001 "file %s (%s). Terminating\n",
3002 fsp_str_dbg(fsp), strerror(errno)));
3003 exit_server_cleanly("send_file_readbraw sendfile failed");
3004 } else if (sendfile_read == 0) {
3006 * Some sendfile implementations return 0 to indicate
3007 * that there was a short read, but nothing was
3008 * actually written to the socket. In this case,
3009 * fallback to the normal read path so the header gets
3010 * the correct byte count.
3012 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3013 "bytes falling back to the normal read: "
3014 "%s\n", fsp_str_dbg(fsp)));
3015 goto normal_readbraw;
3018 /* Deal with possible short send. */
3019 if (sendfile_read != 4+nread) {
3020 sendfile_short_send(fsp, sendfile_read, 4, nread);
3028 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
3030 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
3031 (unsigned)(nread+4)));
3032 reply_readbraw_error(sconn);
3037 ret = read_file(fsp,outbuf+4,startpos,nread);
3038 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3047 _smb_setlen(outbuf,ret);
3048 if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
3049 char addr[INET6_ADDRSTRLEN];
3051 * Try and give an error message saying what
3054 DEBUG(0, ("write_data failed for client %s. "
3056 get_peer_addr(fsp->conn->sconn->sock, addr,
3063 TALLOC_FREE(outbuf);
3066 /****************************************************************************
3067 Reply to a readbraw (core+ protocol).
3068 ****************************************************************************/
3070 void reply_readbraw(struct smb_request *req)
3072 connection_struct *conn = req->conn;
3073 struct smbd_server_connection *sconn = req->sconn;
3074 ssize_t maxcount,mincount;
3078 struct lock_struct lock;
3081 START_PROFILE(SMBreadbraw);
3083 if (srv_is_signing_active(sconn) ||
3084 is_encrypted_packet(req->inbuf)) {
3085 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3086 "raw reads/writes are disallowed.");
3090 reply_readbraw_error(sconn);
3091 END_PROFILE(SMBreadbraw);
3095 if (sconn->smb1.echo_handler.trusted_fde) {
3096 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3097 "'async smb echo handler = yes'\n"));
3098 reply_readbraw_error(sconn);
3099 END_PROFILE(SMBreadbraw);
3104 * Special check if an oplock break has been issued
3105 * and the readraw request croses on the wire, we must
3106 * return a zero length response here.
3109 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3112 * We have to do a check_fsp by hand here, as
3113 * we must always return 4 zero bytes on error,
3117 if (!fsp || !conn || conn != fsp->conn ||
3118 req->vuid != fsp->vuid ||
3119 fsp->is_directory || fsp->fh->fd == -1) {
3121 * fsp could be NULL here so use the value from the packet. JRA.
3123 DEBUG(3,("reply_readbraw: fnum %d not valid "
3125 (int)SVAL(req->vwv+0, 0)));
3126 reply_readbraw_error(sconn);
3127 END_PROFILE(SMBreadbraw);
3131 /* Do a "by hand" version of CHECK_READ. */
3132 if (!(fsp->can_read ||
3133 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3134 (fsp->access_mask & FILE_EXECUTE)))) {
3135 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3136 (int)SVAL(req->vwv+0, 0)));
3137 reply_readbraw_error(sconn);
3138 END_PROFILE(SMBreadbraw);
3142 flush_write_cache(fsp, READRAW_FLUSH);
3144 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3145 if(req->wct == 10) {
3147 * This is a large offset (64 bit) read.
3149 #ifdef LARGE_SMB_OFF_T
3151 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3153 #else /* !LARGE_SMB_OFF_T */
3156 * Ensure we haven't been sent a >32 bit offset.
3159 if(IVAL(req->vwv+8, 0) != 0) {
3160 DEBUG(0,("reply_readbraw: large offset "
3161 "(%x << 32) used and we don't support "
3162 "64 bit offsets.\n",
3163 (unsigned int)IVAL(req->vwv+8, 0) ));
3164 reply_readbraw_error();
3165 END_PROFILE(SMBreadbraw);
3169 #endif /* LARGE_SMB_OFF_T */
3172 DEBUG(0,("reply_readbraw: negative 64 bit "
3173 "readraw offset (%.0f) !\n",
3174 (double)startpos ));
3175 reply_readbraw_error(sconn);
3176 END_PROFILE(SMBreadbraw);
3181 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3182 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3184 /* ensure we don't overrun the packet size */
3185 maxcount = MIN(65535,maxcount);
3187 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3188 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3191 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3192 reply_readbraw_error(sconn);
3193 END_PROFILE(SMBreadbraw);
3197 if (fsp_stat(fsp) == 0) {
3198 size = fsp->fsp_name->st.st_ex_size;
3201 if (startpos >= size) {
3204 nread = MIN(maxcount,(size - startpos));
3207 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3208 if (nread < mincount)
3212 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3213 "min=%lu nread=%lu\n",
3214 fsp->fnum, (double)startpos,
3215 (unsigned long)maxcount,
3216 (unsigned long)mincount,
3217 (unsigned long)nread ) );
3219 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3221 DEBUG(5,("reply_readbraw finished\n"));
3223 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3225 END_PROFILE(SMBreadbraw);
3230 #define DBGC_CLASS DBGC_LOCKING
3232 /****************************************************************************
3233 Reply to a lockread (core+ protocol).
3234 ****************************************************************************/
3236 void reply_lockread(struct smb_request *req)
3238 connection_struct *conn = req->conn;
3245 struct byte_range_lock *br_lck = NULL;
3247 struct smbd_server_connection *sconn = req->sconn;
3249 START_PROFILE(SMBlockread);
3252 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3253 END_PROFILE(SMBlockread);
3257 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3259 if (!check_fsp(conn, req, fsp)) {
3260 END_PROFILE(SMBlockread);
3264 if (!CHECK_READ(fsp,req)) {
3265 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3266 END_PROFILE(SMBlockread);
3270 numtoread = SVAL(req->vwv+1, 0);
3271 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3273 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3275 reply_outbuf(req, 5, numtoread + 3);
3277 data = smb_buf(req->outbuf) + 3;
3280 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3281 * protocol request that predates the read/write lock concept.
3282 * Thus instead of asking for a read lock here we need to ask
3283 * for a write lock. JRA.
3284 * Note that the requested lock size is unaffected by max_recv.
3287 br_lck = do_lock(req->sconn->msg_ctx,
3289 (uint64_t)req->smbpid,
3290 (uint64_t)numtoread,
3294 False, /* Non-blocking lock. */
3298 TALLOC_FREE(br_lck);
3300 if (NT_STATUS_V(status)) {
3301 reply_nterror(req, status);
3302 END_PROFILE(SMBlockread);
3307 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3310 if (numtoread > sconn->smb1.negprot.max_recv) {
3311 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3312 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3313 (unsigned int)numtoread,
3314 (unsigned int)sconn->smb1.negprot.max_recv));
3315 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3317 nread = read_file(fsp,data,startpos,numtoread);
3320 reply_nterror(req, map_nt_error_from_unix(errno));
3321 END_PROFILE(SMBlockread);
3325 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3327 SSVAL(req->outbuf,smb_vwv0,nread);
3328 SSVAL(req->outbuf,smb_vwv5,nread+3);
3329 p = smb_buf(req->outbuf);
3330 SCVAL(p,0,0); /* pad byte. */
3333 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3334 fsp->fnum, (int)numtoread, (int)nread));
3336 END_PROFILE(SMBlockread);
3341 #define DBGC_CLASS DBGC_ALL
3343 /****************************************************************************
3345 ****************************************************************************/
3347 void reply_read(struct smb_request *req)
3349 connection_struct *conn = req->conn;
3356 struct lock_struct lock;
3357 struct smbd_server_connection *sconn = req->sconn;
3359 START_PROFILE(SMBread);
3362 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3363 END_PROFILE(SMBread);
3367 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3369 if (!check_fsp(conn, req, fsp)) {
3370 END_PROFILE(SMBread);
3374 if (!CHECK_READ(fsp,req)) {
3375 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3376 END_PROFILE(SMBread);
3380 numtoread = SVAL(req->vwv+1, 0);
3381 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3383 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3386 * The requested read size cannot be greater than max_recv. JRA.
3388 if (numtoread > sconn->smb1.negprot.max_recv) {
3389 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3390 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3391 (unsigned int)numtoread,
3392 (unsigned int)sconn->smb1.negprot.max_recv));
3393 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3396 reply_outbuf(req, 5, numtoread+3);
3398 data = smb_buf(req->outbuf) + 3;
3400 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3401 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3404 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3405 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3406 END_PROFILE(SMBread);
3411 nread = read_file(fsp,data,startpos,numtoread);
3414 reply_nterror(req, map_nt_error_from_unix(errno));
3418 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3420 SSVAL(req->outbuf,smb_vwv0,nread);
3421 SSVAL(req->outbuf,smb_vwv5,nread+3);
3422 SCVAL(smb_buf(req->outbuf),0,1);
3423 SSVAL(smb_buf(req->outbuf),1,nread);
3425 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3426 fsp->fnum, (int)numtoread, (int)nread ) );
3429 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3431 END_PROFILE(SMBread);
3435 /****************************************************************************
3437 ****************************************************************************/
3439 static int setup_readX_header(struct smb_request *req, char *outbuf,
3445 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3446 data = smb_buf(outbuf);
3448 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3450 SCVAL(outbuf,smb_vwv0,0xFF);
3451 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3452 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3453 SSVAL(outbuf,smb_vwv6,
3455 + 1 /* the wct field */
3456 + 12 * sizeof(uint16_t) /* vwv */
3457 + 2); /* the buflen field */
3458 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3459 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3460 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3461 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3465 /****************************************************************************
3466 Reply to a read and X - possibly using sendfile.
3467 ****************************************************************************/
3469 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3470 files_struct *fsp, SMB_OFF_T startpos,
3474 struct lock_struct lock;
3475 int saved_errno = 0;
3477 if(fsp_stat(fsp) == -1) {
3478 reply_nterror(req, map_nt_error_from_unix(errno));
3482 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3483 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3486 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3487 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3491 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3492 (startpos > fsp->fsp_name->st.st_ex_size)
3493 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3495 * We already know that we would do a short read, so don't
3496 * try the sendfile() path.
3498 goto nosendfile_read;
3501 #if defined(WITH_SENDFILE)
3503 * We can only use sendfile on a non-chained packet
3504 * but we can use on a non-oplocked file. tridge proved this
3505 * on a train in Germany :-). JRA.
3508 if (!req_is_in_chain(req) &&
3509 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3510 (fsp->wcp == NULL) &&
3511 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3512 uint8 headerbuf[smb_size + 12 * 2];
3516 * Set up the packet header before send. We
3517 * assume here the sendfile will work (get the
3518 * correct amount of data).
3521 header = data_blob_const(headerbuf, sizeof(headerbuf));
3523 construct_reply_common_req(req, (char *)headerbuf);
3524 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3526 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3527 startpos, smb_maxcnt);
3529 /* Returning ENOSYS means no data at all was sent.
3530 Do this as a normal read. */
3531 if (errno == ENOSYS) {
3536 * Special hack for broken Linux with no working sendfile. If we
3537 * return EINTR we sent the header but not the rest of the data.
3538 * Fake this up by doing read/write calls.
3541 if (errno == EINTR) {
3542 /* Ensure we don't do this again. */
3543 set_use_sendfile(SNUM(conn), False);
3544 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3545 nread = fake_sendfile(fsp, startpos,
3548 DEBUG(0,("send_file_readX: "
3549 "fake_sendfile failed for "
3553 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3555 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3556 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3557 /* No outbuf here means successful sendfile. */
3561 DEBUG(0,("send_file_readX: sendfile failed for file "
3562 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3564 exit_server_cleanly("send_file_readX sendfile failed");
3565 } else if (nread == 0) {
3567 * Some sendfile implementations return 0 to indicate
3568 * that there was a short read, but nothing was
3569 * actually written to the socket. In this case,
3570 * fallback to the normal read path so the header gets
3571 * the correct byte count.
3573 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3574 "falling back to the normal read: %s\n",
3579 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3580 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3582 /* Deal with possible short send. */
3583 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3584 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3586 /* No outbuf here means successful sendfile. */
3587 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3588 SMB_PERFCOUNT_END(&req->pcd);
3596 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3597 uint8 headerbuf[smb_size + 2*12];
3599 construct_reply_common_req(req, (char *)headerbuf);
3600 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3602 /* Send out the header. */
3603 if (write_data(req->sconn->sock, (char *)headerbuf,
3604 sizeof(headerbuf)) != sizeof(headerbuf)) {
3606 char addr[INET6_ADDRSTRLEN];
3608 * Try and give an error message saying what
3611 DEBUG(0, ("write_data failed for client %s. "
3613 get_peer_addr(req->sconn->sock, addr,
3617 DEBUG(0,("send_file_readX: write_data failed for file "
3618 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3620 exit_server_cleanly("send_file_readX sendfile failed");
3622 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3624 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3625 "file %s (%s).\n", fsp_str_dbg(fsp),
3627 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3634 reply_outbuf(req, 12, smb_maxcnt);
3636 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3637 saved_errno = errno;
3639 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3642 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3646 setup_readX_header(req, (char *)req->outbuf, nread);
3648 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3649 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3655 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3656 TALLOC_FREE(req->outbuf);
3660 /****************************************************************************
3661 Reply to a read and X.
3662 ****************************************************************************/
3664 void reply_read_and_X(struct smb_request *req)
3666 connection_struct *conn = req->conn;
3670 bool big_readX = False;
3672 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3675 START_PROFILE(SMBreadX);
3677 if ((req->wct != 10) && (req->wct != 12)) {
3678 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3682 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3683 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3684 smb_maxcnt = SVAL(req->vwv+5, 0);
3686 /* If it's an IPC, pass off the pipe handler. */
3688 reply_pipe_read_and_X(req);
3689 END_PROFILE(SMBreadX);
3693 if (!check_fsp(conn, req, fsp)) {
3694 END_PROFILE(SMBreadX);
3698 if (!CHECK_READ(fsp,req)) {
3699 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3700 END_PROFILE(SMBreadX);
3704 if (global_client_caps & CAP_LARGE_READX) {
3705 size_t upper_size = SVAL(req->vwv+7, 0);
3706 smb_maxcnt |= (upper_size<<16);
3707 if (upper_size > 1) {
3708 /* Can't do this on a chained packet. */
3709 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3710 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3711 END_PROFILE(SMBreadX);
3714 /* We currently don't do this on signed or sealed data. */
3715 if (srv_is_signing_active(req->sconn) ||
3716 is_encrypted_packet(req->inbuf)) {
3717 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3718 END_PROFILE(SMBreadX);
3721 /* Is there room in the reply for this data ? */
3722 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3724 NT_STATUS_INVALID_PARAMETER);
3725 END_PROFILE(SMBreadX);
3732 if (req->wct == 12) {
3733 #ifdef LARGE_SMB_OFF_T
3735 * This is a large offset (64 bit) read.
3737 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3739 #else /* !LARGE_SMB_OFF_T */
3742 * Ensure we haven't been sent a >32 bit offset.
3745 if(IVAL(req->vwv+10, 0) != 0) {
3746 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3747 "used and we don't support 64 bit offsets.\n",
3748 (unsigned int)IVAL(req->vwv+10, 0) ));
3749 END_PROFILE(SMBreadX);
3750 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3754 #endif /* LARGE_SMB_OFF_T */
3759 NTSTATUS status = schedule_aio_read_and_X(conn,
3764 if (NT_STATUS_IS_OK(status)) {
3765 /* Read scheduled - we're done. */
3768 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3769 /* Real error - report to client. */
3770 END_PROFILE(SMBreadX);
3771 reply_nterror(req, status);
3774 /* NT_STATUS_RETRY - fall back to sync read. */
3777 smbd_lock_socket(req->sconn);
3778 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3779 smbd_unlock_socket(req->sconn);
3782 END_PROFILE(SMBreadX);
3786 /****************************************************************************
3787 Error replies to writebraw must have smb_wct == 1. Fix this up.
3788 ****************************************************************************/
3790 void error_to_writebrawerr(struct smb_request *req)
3792 uint8 *old_outbuf = req->outbuf;
3794 reply_outbuf(req, 1, 0);
3796 memcpy(req->outbuf, old_outbuf, smb_size);
3797 TALLOC_FREE(old_outbuf);
3800 /****************************************************************************
3801 Read 4 bytes of a smb packet and return the smb length of the packet.
3802 Store the result in the buffer. This version of the function will
3803 never return a session keepalive (length of zero).
3804 Timeout is in milliseconds.
3805 ****************************************************************************/
3807 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3810 uint8_t msgtype = SMBkeepalive;
3812 while (msgtype == SMBkeepalive) {
3815 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3817 if (!NT_STATUS_IS_OK(status)) {
3818 char addr[INET6_ADDRSTRLEN];
3819 /* Try and give an error message
3820 * saying what client failed. */
3821 DEBUG(0, ("read_fd_with_timeout failed for "
3822 "client %s read error = %s.\n",
3823 get_peer_addr(fd,addr,sizeof(addr)),
3824 nt_errstr(status)));
3828 msgtype = CVAL(inbuf, 0);
3831 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3832 (unsigned long)len));
3834 return NT_STATUS_OK;
3837 /****************************************************************************
3838 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3839 ****************************************************************************/
3841 void reply_writebraw(struct smb_request *req)
3843 connection_struct *conn = req->conn;
3846 ssize_t total_written=0;
3847 size_t numtowrite=0;
3853 struct lock_struct lock;
3856 START_PROFILE(SMBwritebraw);
3859 * If we ever reply with an error, it must have the SMB command
3860 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3863 SCVAL(req->inbuf,smb_com,SMBwritec);
3865 if (srv_is_signing_active(req->sconn)) {
3866 END_PROFILE(SMBwritebraw);
3867 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3868 "raw reads/writes are disallowed.");
3871 if (req->wct < 12) {
3872 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3873 error_to_writebrawerr(req);
3874 END_PROFILE(SMBwritebraw);
3878 if (req->sconn->smb1.echo_handler.trusted_fde) {
3879 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3880 "'async smb echo handler = yes'\n"));
3881 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3882 error_to_writebrawerr(req);
3883 END_PROFILE(SMBwritebraw);
3887 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3888 if (!check_fsp(conn, req, fsp)) {
3889 error_to_writebrawerr(req);
3890 END_PROFILE(SMBwritebraw);
3894 if (!CHECK_WRITE(fsp)) {
3895 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3896 error_to_writebrawerr(req);
3897 END_PROFILE(SMBwritebraw);
3901 tcount = IVAL(req->vwv+1, 0);
3902 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3903 write_through = BITSETW(req->vwv+7,0);
3905 /* We have to deal with slightly different formats depending
3906 on whether we are using the core+ or lanman1.0 protocol */
3908 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3909 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3910 data = smb_buf(req->inbuf);
3912 numtowrite = SVAL(req->vwv+10, 0);
3913 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3916 /* Ensure we don't write bytes past the end of this packet. */
3917 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3918 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3919 error_to_writebrawerr(req);
3920 END_PROFILE(SMBwritebraw);
3924 if (!fsp->print_file) {
3925 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3926 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3929 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3930 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3931 error_to_writebrawerr(req);
3932 END_PROFILE(SMBwritebraw);
3938 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3941 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3942 "wrote=%d sync=%d\n",
3943 fsp->fnum, (double)startpos, (int)numtowrite,
3944 (int)nwritten, (int)write_through));
3946 if (nwritten < (ssize_t)numtowrite) {
3947 reply_nterror(req, NT_STATUS_DISK_FULL);
3948 error_to_writebrawerr(req);
3952 total_written = nwritten;
3954 /* Allocate a buffer of 64k + length. */
3955 buf = TALLOC_ARRAY(NULL, char, 65540);
3957 reply_nterror(req, NT_STATUS_NO_MEMORY);
3958 error_to_writebrawerr(req);
3962 /* Return a SMBwritebraw message to the redirector to tell
3963 * it to send more bytes */
3965 memcpy(buf, req->inbuf, smb_size);
3966 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
3967 SCVAL(buf,smb_com,SMBwritebraw);
3968 SSVALS(buf,smb_vwv0,0xFFFF);
3970 if (!srv_send_smb(req->sconn,
3972 false, 0, /* no signing */
3973 IS_CONN_ENCRYPTED(conn),
3975 exit_server_cleanly("reply_writebraw: srv_send_smb "
3979 /* Now read the raw data into the buffer and write it */
3980 status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
3982 if (!NT_STATUS_IS_OK(status)) {
3983 exit_server_cleanly("secondary writebraw failed");
3986 /* Set up outbuf to return the correct size */
3987 reply_outbuf(req, 1, 0);
3989 if (numtowrite != 0) {
3991 if (numtowrite > 0xFFFF) {
3992 DEBUG(0,("reply_writebraw: Oversize secondary write "
3993 "raw requested (%u). Terminating\n",
3994 (unsigned int)numtowrite ));
3995 exit_server_cleanly("secondary writebraw failed");
3998 if (tcount > nwritten+numtowrite) {
3999 DEBUG(3,("reply_writebraw: Client overestimated the "
4001 (int)tcount,(int)nwritten,(int)numtowrite));
4004 status = read_data(req->sconn->sock, buf+4, numtowrite);
4006 if (!NT_STATUS_IS_OK(status)) {
4007 char addr[INET6_ADDRSTRLEN];
4008 /* Try and give an error message
4009 * saying what client failed. */
4010 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4011 "raw read failed (%s) for client %s. "
4012 "Terminating\n", nt_errstr(status),
4013 get_peer_addr(req->sconn->sock, addr,
4015 exit_server_cleanly("secondary writebraw failed");
4018 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4019 if (nwritten == -1) {
4021 reply_nterror(req, map_nt_error_from_unix(errno));
4022 error_to_writebrawerr(req);
4026 if (nwritten < (ssize_t)numtowrite) {
4027 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4028 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4032 total_written += nwritten;
4037 SSVAL(req->outbuf,smb_vwv0,total_written);
4039 status = sync_file(conn, fsp, write_through);
4040 if (!NT_STATUS_IS_OK(status)) {
4041 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4042 fsp_str_dbg(fsp), nt_errstr(status)));
4043 reply_nterror(req, status);
4044 error_to_writebrawerr(req);
4048 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4050 fsp->fnum, (double)startpos, (int)numtowrite,
4051 (int)total_written));
4053 if (!fsp->print_file) {
4054 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4057 /* We won't return a status if write through is not selected - this
4058 * follows what WfWg does */
4059 END_PROFILE(SMBwritebraw);
4061 if (!write_through && total_written==tcount) {
4063 #if RABBIT_PELLET_FIX
4065 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4066 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
4069 if (!send_keepalive(req->sconn->sock)) {
4070 exit_server_cleanly("reply_writebraw: send of "
4071 "keepalive failed");
4074 TALLOC_FREE(req->outbuf);
4079 if (!fsp->print_file) {
4080 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4083 END_PROFILE(SMBwritebraw);
4088 #define DBGC_CLASS DBGC_LOCKING
4090 /****************************************************************************
4091 Reply to a writeunlock (core+).
4092 ****************************************************************************/
4094 void reply_writeunlock(struct smb_request *req)
4096 connection_struct *conn = req->conn;
4097 ssize_t nwritten = -1;
4101 NTSTATUS status = NT_STATUS_OK;
4103 struct lock_struct lock;
4104 int saved_errno = 0;
4106 START_PROFILE(SMBwriteunlock);
4109 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4110 END_PROFILE(SMBwriteunlock);
4114 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4116 if (!check_fsp(conn, req, fsp)) {
4117 END_PROFILE(SMBwriteunlock);
4121 if (!CHECK_WRITE(fsp)) {
4122 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4123 END_PROFILE(SMBwriteunlock);
4127 numtowrite = SVAL(req->vwv+1, 0);
4128 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4129 data = (const char *)req->buf + 3;
4131 if (!fsp->print_file && numtowrite > 0) {
4132 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4133 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4136 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4137 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4138 END_PROFILE(SMBwriteunlock);
4143 /* The special X/Open SMB protocol handling of
4144 zero length writes is *NOT* done for
4146 if(numtowrite == 0) {
4149 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4150 saved_errno = errno;
4153 status = sync_file(conn, fsp, False /* write through */);
4154 if (!NT_STATUS_IS_OK(status)) {
4155 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4156 fsp_str_dbg(fsp), nt_errstr(status)));
4157 reply_nterror(req, status);
4162 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4166 if((nwritten < numtowrite) && (numtowrite != 0)) {
4167 reply_nterror(req, NT_STATUS_DISK_FULL);
4171 if (numtowrite && !fsp->print_file) {
4172 status = do_unlock(req->sconn->msg_ctx,
4174 (uint64_t)req->smbpid,
4175 (uint64_t)numtowrite,
4179 if (NT_STATUS_V(status)) {
4180 reply_nterror(req, status);
4185 reply_outbuf(req, 1, 0);
4187 SSVAL(req->outbuf,smb_vwv0,nwritten);
4189 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4190 fsp->fnum, (int)numtowrite, (int)nwritten));
4193 if (numtowrite && !fsp->print_file) {
4194 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4197 END_PROFILE(SMBwriteunlock);
4202 #define DBGC_CLASS DBGC_ALL
4204 /****************************************************************************
4206 ****************************************************************************/
4208 void reply_write(struct smb_request *req)
4210 connection_struct *conn = req->conn;
4212 ssize_t nwritten = -1;
4216 struct lock_struct lock;
4218 int saved_errno = 0;
4220 START_PROFILE(SMBwrite);
4223 END_PROFILE(SMBwrite);
4224 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4228 /* If it's an IPC, pass off the pipe handler. */
4230 reply_pipe_write(req);
4231 END_PROFILE(SMBwrite);
4235 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4237 if (!check_fsp(conn, req, fsp)) {
4238 END_PROFILE(SMBwrite);
4242 if (!CHECK_WRITE(fsp)) {
4243 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4244 END_PROFILE(SMBwrite);
4248 numtowrite = SVAL(req->vwv+1, 0);
4249 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4250 data = (const char *)req->buf + 3;
4252 if (!fsp->print_file) {
4253 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4254 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4257 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4258 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4259 END_PROFILE(SMBwrite);
4265 * X/Open SMB protocol says that if smb_vwv1 is
4266 * zero then the file size should be extended or
4267 * truncated to the size given in smb_vwv[2-3].
4270 if(numtowrite == 0) {
4272 * This is actually an allocate call, and set EOF. JRA.
4274 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4276 reply_nterror(req, NT_STATUS_DISK_FULL);
4279 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4281 reply_nterror(req, NT_STATUS_DISK_FULL);
4284 trigger_write_time_update_immediate(fsp);
4286 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4289 status = sync_file(conn, fsp, False);
4290 if (!NT_STATUS_IS_OK(status)) {
4291 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4292 fsp_str_dbg(fsp), nt_errstr(status)));
4293 reply_nterror(req, status);
4298 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4302 if((nwritten == 0) && (numtowrite != 0)) {
4303 reply_nterror(req, NT_STATUS_DISK_FULL);
4307 reply_outbuf(req, 1, 0);
4309 SSVAL(req->outbuf,smb_vwv0,nwritten);
4311 if (nwritten < (ssize_t)numtowrite) {
4312 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4313 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4316 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4319 if (!fsp->print_file) {
4320 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4323 END_PROFILE(SMBwrite);
4327 /****************************************************************************
4328 Ensure a buffer is a valid writeX for recvfile purposes.
4329 ****************************************************************************/
4331 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4332 (2*14) + /* word count (including bcc) */ \
4335 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4336 const uint8_t *inbuf)
4339 connection_struct *conn = NULL;
4340 unsigned int doff = 0;
4341 size_t len = smb_len_large(inbuf);
4343 if (is_encrypted_packet(inbuf)) {
4344 /* Can't do this on encrypted
4349 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4353 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4354 CVAL(inbuf,smb_wct) != 14) {
4355 DEBUG(10,("is_valid_writeX_buffer: chained or "
4356 "invalid word length.\n"));
4360 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4362 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4366 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4369 if (IS_PRINT(conn)) {
4370 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4373 doff = SVAL(inbuf,smb_vwv11);
4375 numtowrite = SVAL(inbuf,smb_vwv10);
4377 if (len > doff && len - doff > 0xFFFF) {
4378 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4381 if (numtowrite == 0) {
4382 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4386 /* Ensure the sizes match up. */
4387 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4388 /* no pad byte...old smbclient :-( */
4389 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4391 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4395 if (len - doff != numtowrite) {
4396 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4397 "len = %u, doff = %u, numtowrite = %u\n",
4400 (unsigned int)numtowrite ));
4404 DEBUG(10,("is_valid_writeX_buffer: true "
4405 "len = %u, doff = %u, numtowrite = %u\n",
4408 (unsigned int)numtowrite ));
4413 /****************************************************************************
4414 Reply to a write and X.
4415 ****************************************************************************/
4417 void reply_write_and_X(struct smb_request *req)
4419 connection_struct *conn = req->conn;
4421 struct lock_struct lock;
4426 unsigned int smb_doff;
4427 unsigned int smblen;
4430 int saved_errno = 0;
4432 START_PROFILE(SMBwriteX);
4434 if ((req->wct != 12) && (req->wct != 14)) {
4435 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4436 END_PROFILE(SMBwriteX);
4440 numtowrite = SVAL(req->vwv+10, 0);
4441 smb_doff = SVAL(req->vwv+11, 0);
4442 smblen = smb_len(req->inbuf);
4444 if (req->unread_bytes > 0xFFFF ||
4445 (smblen > smb_doff &&
4446 smblen - smb_doff > 0xFFFF)) {
4447 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4450 if (req->unread_bytes) {
4451 /* Can't do a recvfile write on IPC$ */
4453 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4454 END_PROFILE(SMBwriteX);
4457 if (numtowrite != req->unread_bytes) {
4458 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4459 END_PROFILE(SMBwriteX);
4463 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4464 smb_doff + numtowrite > smblen) {
4465 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4466 END_PROFILE(SMBwriteX);
4471 /* If it's an IPC, pass off the pipe handler. */
4473 if (req->unread_bytes) {
4474 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4475 END_PROFILE(SMBwriteX);
4478 reply_pipe_write_and_X(req);
4479 END_PROFILE(SMBwriteX);
4483 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4484 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4485 write_through = BITSETW(req->vwv+7,0);
4487 if (!check_fsp(conn, req, fsp)) {
4488 END_PROFILE(SMBwriteX);
4492 if (!CHECK_WRITE(fsp)) {
4493 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4494 END_PROFILE(SMBwriteX);
4498 data = smb_base(req->inbuf) + smb_doff;
4500 if(req->wct == 14) {
4501 #ifdef LARGE_SMB_OFF_T
4503 * This is a large offset (64 bit) write.
4505 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4507 #else /* !LARGE_SMB_OFF_T */
4510 * Ensure we haven't been sent a >32 bit offset.
4513 if(IVAL(req->vwv+12, 0) != 0) {
4514 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4515 "used and we don't support 64 bit offsets.\n",
4516 (unsigned int)IVAL(req->vwv+12, 0) ));
4517 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4518 END_PROFILE(SMBwriteX);
4522 #endif /* LARGE_SMB_OFF_T */
4525 /* X/Open SMB protocol says that, unlike SMBwrite
4526 if the length is zero then NO truncation is
4527 done, just a write of zero. To truncate a file,
4530 if(numtowrite == 0) {
4533 if (req->unread_bytes == 0) {
4534 status = schedule_aio_write_and_X(conn,
4541 if (NT_STATUS_IS_OK(status)) {
4542 /* write scheduled - we're done. */
4545 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4546 /* Real error - report to client. */
4547 reply_nterror(req, status);
4550 /* NT_STATUS_RETRY - fall through to sync write. */
4553 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4554 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4557 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4558 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4562 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4563 saved_errno = errno;
4565 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4569 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4573 if((nwritten == 0) && (numtowrite != 0)) {
4574 reply_nterror(req, NT_STATUS_DISK_FULL);
4578 reply_outbuf(req, 6, 0);
4579 SSVAL(req->outbuf,smb_vwv2,nwritten);
4580 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4582 if (nwritten < (ssize_t)numtowrite) {
4583 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4584 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4587 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4588 fsp->fnum, (int)numtowrite, (int)nwritten));
4590 status = sync_file(conn, fsp, write_through);
4591 if (!NT_STATUS_IS_OK(status)) {
4592 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4593 fsp_str_dbg(fsp), nt_errstr(status)));
4594 reply_nterror(req, status);
4598 END_PROFILE(SMBwriteX);
4603 END_PROFILE(SMBwriteX);
4607 /****************************************************************************
4609 ****************************************************************************/
4611 void reply_lseek(struct smb_request *req)
4613 connection_struct *conn = req->conn;
4619 START_PROFILE(SMBlseek);
4622 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4623 END_PROFILE(SMBlseek);
4627 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4629 if (!check_fsp(conn, req, fsp)) {
4633 flush_write_cache(fsp, SEEK_FLUSH);
4635 mode = SVAL(req->vwv+1, 0) & 3;
4636 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4637 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4646 res = fsp->fh->pos + startpos;
4657 if (umode == SEEK_END) {
4658 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4659 if(errno == EINVAL) {
4660 SMB_OFF_T current_pos = startpos;
4662 if(fsp_stat(fsp) == -1) {
4664 map_nt_error_from_unix(errno));
4665 END_PROFILE(SMBlseek);
4669 current_pos += fsp->fsp_name->st.st_ex_size;
4671 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4676 reply_nterror(req, map_nt_error_from_unix(errno));
4677 END_PROFILE(SMBlseek);
4684 reply_outbuf(req, 2, 0);
4685 SIVAL(req->outbuf,smb_vwv0,res);
4687 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4688 fsp->fnum, (double)startpos, (double)res, mode));
4690 END_PROFILE(SMBlseek);
4694 /****************************************************************************
4696 ****************************************************************************/
4698 void reply_flush(struct smb_request *req)
4700 connection_struct *conn = req->conn;
4704 START_PROFILE(SMBflush);
4707 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4711 fnum = SVAL(req->vwv+0, 0);
4712 fsp = file_fsp(req, fnum);
4714 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4719 file_sync_all(conn);
4721 NTSTATUS status = sync_file(conn, fsp, True);
4722 if (!NT_STATUS_IS_OK(status)) {
4723 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4724 fsp_str_dbg(fsp), nt_errstr(status)));
4725 reply_nterror(req, status);
4726 END_PROFILE(SMBflush);
4731 reply_outbuf(req, 0, 0);
4733 DEBUG(3,("flush\n"));
4734 END_PROFILE(SMBflush);
4738 /****************************************************************************
4740 conn POINTER CAN BE NULL HERE !
4741 ****************************************************************************/
4743 void reply_exit(struct smb_request *req)
4745 START_PROFILE(SMBexit);
4747 file_close_pid(req->smbpid, req->vuid);
4749 reply_outbuf(req, 0, 0);
4751 DEBUG(3,("exit\n"));
4753 END_PROFILE(SMBexit);
4757 /****************************************************************************
4758 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4759 ****************************************************************************/
4761 void reply_close(struct smb_request *req)
4763 connection_struct *conn = req->conn;
4764 NTSTATUS status = NT_STATUS_OK;
4765 files_struct *fsp = NULL;
4766 START_PROFILE(SMBclose);
4769 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4770 END_PROFILE(SMBclose);
4774 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4777 * We can only use check_fsp if we know it's not a directory.
4780 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4781 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4782 END_PROFILE(SMBclose);
4786 if(fsp->is_directory) {
4788 * Special case - close NT SMB directory handle.
4790 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4791 status = close_file(req, fsp, NORMAL_CLOSE);
4795 * Close ordinary file.
4798 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4799 fsp->fh->fd, fsp->fnum,
4800 conn->num_files_open));
4803 * Take care of any time sent in the close.
4806 t = srv_make_unix_date3(req->vwv+1);
4807 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4810 * close_file() returns the unix errno if an error
4811 * was detected on close - normally this is due to
4812 * a disk full error. If not then it was probably an I/O error.
4815 status = close_file(req, fsp, NORMAL_CLOSE);
4818 if (!NT_STATUS_IS_OK(status)) {
4819 reply_nterror(req, status);
4820 END_PROFILE(SMBclose);
4824 reply_outbuf(req, 0, 0);
4825 END_PROFILE(SMBclose);
4829 /****************************************************************************
4830 Reply to a writeclose (Core+ protocol).
4831 ****************************************************************************/
4833 void reply_writeclose(struct smb_request *req)
4835 connection_struct *conn = req->conn;
4837 ssize_t nwritten = -1;
4838 NTSTATUS close_status = NT_STATUS_OK;
4841 struct timespec mtime;
4843 struct lock_struct lock;
4845 START_PROFILE(SMBwriteclose);
4848 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4849 END_PROFILE(SMBwriteclose);
4853 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4855 if (!check_fsp(conn, req, fsp)) {
4856 END_PROFILE(SMBwriteclose);
4859 if (!CHECK_WRITE(fsp)) {
4860 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4861 END_PROFILE(SMBwriteclose);
4865 numtowrite = SVAL(req->vwv+1, 0);
4866 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4867 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4868 data = (const char *)req->buf + 1;
4870 if (!fsp->print_file) {
4871 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4872 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4875 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4876 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4877 END_PROFILE(SMBwriteclose);
4882 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4884 set_close_write_time(fsp, mtime);
4887 * More insanity. W2K only closes the file if writelen > 0.
4892 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4893 "file %s\n", fsp_str_dbg(fsp)));
4894 close_status = close_file(req, fsp, NORMAL_CLOSE);
4897 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4898 fsp->fnum, (int)numtowrite, (int)nwritten,
4899 conn->num_files_open));
4901 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4902 reply_nterror(req, NT_STATUS_DISK_FULL);
4906 if(!NT_STATUS_IS_OK(close_status)) {
4907 reply_nterror(req, close_status);
4911 reply_outbuf(req, 1, 0);
4913 SSVAL(req->outbuf,smb_vwv0,nwritten);
4916 if (numtowrite && !fsp->print_file) {
4917 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4920 END_PROFILE(SMBwriteclose);
4925 #define DBGC_CLASS DBGC_LOCKING
4927 /****************************************************************************
4929 ****************************************************************************/
4931 void reply_lock(struct smb_request *req)
4933 connection_struct *conn = req->conn;
4934 uint64_t count,offset;
4937 struct byte_range_lock *br_lck = NULL;
4939 START_PROFILE(SMBlock);
4942 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4943 END_PROFILE(SMBlock);
4947 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4949 if (!check_fsp(conn, req, fsp)) {
4950 END_PROFILE(SMBlock);
4954 count = (uint64_t)IVAL(req->vwv+1, 0);
4955 offset = (uint64_t)IVAL(req->vwv+3, 0);
4957 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4958 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4960 br_lck = do_lock(req->sconn->msg_ctx,
4962 (uint64_t)req->smbpid,
4967 False, /* Non-blocking lock. */
4972 TALLOC_FREE(br_lck);
4974 if (NT_STATUS_V(status)) {
4975 reply_nterror(req, status);
4976 END_PROFILE(SMBlock);
4980 reply_outbuf(req, 0, 0);
4982 END_PROFILE(SMBlock);
4986 /****************************************************************************
4988 ****************************************************************************/
4990 void reply_unlock(struct smb_request *req)
4992 connection_struct *conn = req->conn;
4993 uint64_t count,offset;
4997 START_PROFILE(SMBunlock);
5000 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5001 END_PROFILE(SMBunlock);
5005 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5007 if (!check_fsp(conn, req, fsp)) {
5008 END_PROFILE(SMBunlock);
5012 count = (uint64_t)IVAL(req->vwv+1, 0);
5013 offset = (uint64_t)IVAL(req->vwv+3, 0);
5015 status = do_unlock(req->sconn->msg_ctx,
5017 (uint64_t)req->smbpid,
5022 if (NT_STATUS_V(status)) {
5023 reply_nterror(req, status);
5024 END_PROFILE(SMBunlock);
5028 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5029 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
5031 reply_outbuf(req, 0, 0);
5033 END_PROFILE(SMBunlock);
5038 #define DBGC_CLASS DBGC_ALL
5040 /****************************************************************************
5042 conn POINTER CAN BE NULL HERE !
5043 ****************************************************************************/
5045 void reply_tdis(struct smb_request *req)
5047 connection_struct *conn = req->conn;
5048 START_PROFILE(SMBtdis);
5051 DEBUG(4,("Invalid connection in tdis\n"));
5052 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
5053 END_PROFILE(SMBtdis);
5059 close_cnum(conn,req->vuid);
5062 reply_outbuf(req, 0, 0);
5063 END_PROFILE(SMBtdis);
5067 /****************************************************************************
5069 conn POINTER CAN BE NULL HERE !
5070 ****************************************************************************/
5072 void reply_echo(struct smb_request *req)
5074 connection_struct *conn = req->conn;
5075 struct smb_perfcount_data local_pcd;
5076 struct smb_perfcount_data *cur_pcd;
5080 START_PROFILE(SMBecho);
5082 smb_init_perfcount_data(&local_pcd);
5085 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5086 END_PROFILE(SMBecho);
5090 smb_reverb = SVAL(req->vwv+0, 0);
5092 reply_outbuf(req, 1, req->buflen);
5094 /* copy any incoming data back out */
5095 if (req->buflen > 0) {
5096 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5099 if (smb_reverb > 100) {
5100 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5104 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5106 /* this makes sure we catch the request pcd */
5107 if (seq_num == smb_reverb) {
5108 cur_pcd = &req->pcd;
5110 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5111 cur_pcd = &local_pcd;
5114 SSVAL(req->outbuf,smb_vwv0,seq_num);
5116 show_msg((char *)req->outbuf);
5117 if (!srv_send_smb(req->sconn,
5118 (char *)req->outbuf,
5119 true, req->seqnum+1,
5120 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5122 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5125 DEBUG(3,("echo %d times\n", smb_reverb));
5127 TALLOC_FREE(req->outbuf);
5129 END_PROFILE(SMBecho);
5133 /****************************************************************************
5134 Reply to a printopen.
5135 ****************************************************************************/
5137 void reply_printopen(struct smb_request *req)
5139 connection_struct *conn = req->conn;
5143 START_PROFILE(SMBsplopen);
5146 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5147 END_PROFILE(SMBsplopen);
5151 if (!CAN_PRINT(conn)) {
5152 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5153 END_PROFILE(SMBsplopen);
5157 status = file_new(req, conn, &fsp);
5158 if(!NT_STATUS_IS_OK(status)) {
5159 reply_nterror(req, status);
5160 END_PROFILE(SMBsplopen);
5164 /* Open for exclusive use, write only. */
5165 status = print_spool_open(fsp, NULL, req->vuid);
5167 if (!NT_STATUS_IS_OK(status)) {
5168 file_free(req, fsp);
5169 reply_nterror(req, status);
5170 END_PROFILE(SMBsplopen);
5174 reply_outbuf(req, 1, 0);
5175 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5177 DEBUG(3,("openprint fd=%d fnum=%d\n",
5178 fsp->fh->fd, fsp->fnum));
5180 END_PROFILE(SMBsplopen);
5184 /****************************************************************************
5185 Reply to a printclose.
5186 ****************************************************************************/
5188 void reply_printclose(struct smb_request *req)
5190 connection_struct *conn = req->conn;
5194 START_PROFILE(SMBsplclose);
5197 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5198 END_PROFILE(SMBsplclose);
5202 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5204 if (!check_fsp(conn, req, fsp)) {
5205 END_PROFILE(SMBsplclose);
5209 if (!CAN_PRINT(conn)) {
5210 reply_force_doserror(req, ERRSRV, ERRerror);
5211 END_PROFILE(SMBsplclose);
5215 DEBUG(3,("printclose fd=%d fnum=%d\n",
5216 fsp->fh->fd,fsp->fnum));
5218 status = close_file(req, fsp, NORMAL_CLOSE);
5220 if(!NT_STATUS_IS_OK(status)) {
5221 reply_nterror(req, status);
5222 END_PROFILE(SMBsplclose);
5226 reply_outbuf(req, 0, 0);
5228 END_PROFILE(SMBsplclose);
5232 /****************************************************************************
5233 Reply to a printqueue.
5234 ****************************************************************************/
5236 void reply_printqueue(struct smb_request *req)
5238 connection_struct *conn = req->conn;
5242 START_PROFILE(SMBsplretq);
5245 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5246 END_PROFILE(SMBsplretq);
5250 max_count = SVAL(req->vwv+0, 0);
5251 start_index = SVAL(req->vwv+1, 0);
5253 /* we used to allow the client to get the cnum wrong, but that
5254 is really quite gross and only worked when there was only
5255 one printer - I think we should now only accept it if they
5256 get it right (tridge) */
5257 if (!CAN_PRINT(conn)) {
5258 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5259 END_PROFILE(SMBsplretq);
5263 reply_outbuf(req, 2, 3);
5264 SSVAL(req->outbuf,smb_vwv0,0);
5265 SSVAL(req->outbuf,smb_vwv1,0);
5266 SCVAL(smb_buf(req->outbuf),0,1);
5267 SSVAL(smb_buf(req->outbuf),1,0);
5269 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5270 start_index, max_count));
5273 TALLOC_CTX *mem_ctx = talloc_tos();
5276 const char *sharename = lp_servicename(SNUM(conn));
5277 struct rpc_pipe_client *cli = NULL;
5278 struct policy_handle handle;
5279 struct spoolss_DevmodeContainer devmode_ctr;
5280 union spoolss_JobInfo *info;
5282 uint32_t num_to_get;
5286 ZERO_STRUCT(handle);
5288 status = rpc_connect_spoolss_pipe(conn, &cli);
5289 if (!NT_STATUS_IS_OK(status)) {
5290 DEBUG(0, ("reply_printqueue: "
5291 "could not connect to spoolss: %s\n",
5292 nt_errstr(status)));
5293 reply_nterror(req, status);
5297 ZERO_STRUCT(devmode_ctr);
5299 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
5302 SEC_FLAG_MAXIMUM_ALLOWED,
5305 if (!NT_STATUS_IS_OK(status)) {
5306 reply_nterror(req, status);
5309 if (!W_ERROR_IS_OK(werr)) {
5310 reply_nterror(req, werror_to_ntstatus(werr));
5314 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5322 if (!W_ERROR_IS_OK(werr)) {
5323 reply_nterror(req, werror_to_ntstatus(werr));
5327 if (max_count > 0) {
5328 first = start_index;
5330 first = start_index + max_count + 1;
5333 if (first >= count) {
5336 num_to_get = first + MIN(ABS(max_count), count - first);
5339 for (i = first; i < num_to_get; i++) {
5342 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5344 uint16_t qrapjobid = pjobid_to_rap(sharename,
5345 info[i].info2.job_id);
5347 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5353 srv_put_dos_date2(p, 0, qtime);
5354 SCVAL(p, 4, qstatus);
5355 SSVAL(p, 5, qrapjobid);
5356 SIVAL(p, 7, info[i].info2.size);
5358 srvstr_push(blob, req->flags2, p+12,
5359 info[i].info2.notify_name, 16, STR_ASCII);
5361 if (message_push_blob(
5364 blob, sizeof(blob))) == -1) {
5365 reply_nterror(req, NT_STATUS_NO_MEMORY);
5371 SSVAL(req->outbuf,smb_vwv0,count);
5372 SSVAL(req->outbuf,smb_vwv1,
5373 (max_count>0?first+count:first-1));
5374 SCVAL(smb_buf(req->outbuf),0,1);
5375 SSVAL(smb_buf(req->outbuf),1,28*count);
5379 DEBUG(3, ("%u entries returned in queue\n",
5383 if (cli && is_valid_policy_hnd(&handle)) {
5384 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
5389 END_PROFILE(SMBsplretq);
5393 /****************************************************************************
5394 Reply to a printwrite.
5395 ****************************************************************************/
5397 void reply_printwrite(struct smb_request *req)
5399 connection_struct *conn = req->conn;
5404 START_PROFILE(SMBsplwr);
5407 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5408 END_PROFILE(SMBsplwr);
5412 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5414 if (!check_fsp(conn, req, fsp)) {
5415 END_PROFILE(SMBsplwr);
5419 if (!fsp->print_file) {
5420 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5421 END_PROFILE(SMBsplwr);
5425 if (!CHECK_WRITE(fsp)) {
5426 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5427 END_PROFILE(SMBsplwr);
5431 numtowrite = SVAL(req->buf, 1);
5433 if (req->buflen < numtowrite + 3) {
5434 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5435 END_PROFILE(SMBsplwr);
5439 data = (const char *)req->buf + 3;
5441 if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5442 reply_nterror(req, map_nt_error_from_unix(errno));
5443 END_PROFILE(SMBsplwr);
5447 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5449 END_PROFILE(SMBsplwr);
5453 /****************************************************************************
5455 ****************************************************************************/
5457 void reply_mkdir(struct smb_request *req)
5459 connection_struct *conn = req->conn;
5460 struct smb_filename *smb_dname = NULL;
5461 char *directory = NULL;
5463 TALLOC_CTX *ctx = talloc_tos();
5465 START_PROFILE(SMBmkdir);
5467 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5468 STR_TERMINATE, &status);
5469 if (!NT_STATUS_IS_OK(status)) {
5470 reply_nterror(req, status);
5474 status = filename_convert(ctx, conn,
5475 req->flags2 & FLAGS2_DFS_PATHNAMES,
5480 if (!NT_STATUS_IS_OK(status)) {
5481 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5482 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5483 ERRSRV, ERRbadpath);
5486 reply_nterror(req, status);
5490 status = create_directory(conn, req, smb_dname);
5492 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5494 if (!NT_STATUS_IS_OK(status)) {
5496 if (!use_nt_status()
5497 && NT_STATUS_EQUAL(status,
5498 NT_STATUS_OBJECT_NAME_COLLISION)) {
5500 * Yes, in the DOS error code case we get a
5501 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5502 * samba4 torture test.
5504 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5507 reply_nterror(req, status);
5511 reply_outbuf(req, 0, 0);
5513 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5515 TALLOC_FREE(smb_dname);
5516 END_PROFILE(SMBmkdir);
5520 /****************************************************************************
5522 ****************************************************************************/
5524 void reply_rmdir(struct smb_request *req)
5526 connection_struct *conn = req->conn;
5527 struct smb_filename *smb_dname = NULL;
5528 char *directory = NULL;
5530 TALLOC_CTX *ctx = talloc_tos();
5531 files_struct *fsp = NULL;
5533 struct smbd_server_connection *sconn = req->sconn;
5535 START_PROFILE(SMBrmdir);
5537 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5538 STR_TERMINATE, &status);
5539 if (!NT_STATUS_IS_OK(status)) {
5540 reply_nterror(req, status);
5544 status = filename_convert(ctx, conn,
5545 req->flags2 & FLAGS2_DFS_PATHNAMES,
5550 if (!NT_STATUS_IS_OK(status)) {
5551 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5552 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5553 ERRSRV, ERRbadpath);
5556 reply_nterror(req, status);
5560 if (is_ntfs_stream_smb_fname(smb_dname)) {
5561 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5565 status = SMB_VFS_CREATE_FILE(
5568 0, /* root_dir_fid */
5569 smb_dname, /* fname */
5570 DELETE_ACCESS, /* access_mask */
5571 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5573 FILE_OPEN, /* create_disposition*/
5574 FILE_DIRECTORY_FILE, /* create_options */
5575 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5576 0, /* oplock_request */
5577 0, /* allocation_size */
5578 0, /* private_flags */
5584 if (!NT_STATUS_IS_OK(status)) {
5585 if (open_was_deferred(req->mid)) {
5586 /* We have re-scheduled this call. */
5589 reply_nterror(req, status);
5593 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5594 if (!NT_STATUS_IS_OK(status)) {
5595 close_file(req, fsp, ERROR_CLOSE);
5596 reply_nterror(req, status);
5600 if (!set_delete_on_close(fsp, true, &conn->server_info->utok)) {
5601 close_file(req, fsp, ERROR_CLOSE);
5602 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5606 status = close_file(req, fsp, NORMAL_CLOSE);
5607 if (!NT_STATUS_IS_OK(status)) {
5608 reply_nterror(req, status);
5610 reply_outbuf(req, 0, 0);
5613 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5615 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5617 TALLOC_FREE(smb_dname);
5618 END_PROFILE(SMBrmdir);
5622 /*******************************************************************
5623 Resolve wildcards in a filename rename.
5624 ********************************************************************/
5626 static bool resolve_wildcards(TALLOC_CTX *ctx,
5631 char *name2_copy = NULL;
5636 char *p,*p2, *pname1, *pname2;
5638 name2_copy = talloc_strdup(ctx, name2);
5643 pname1 = strrchr_m(name1,'/');
5644 pname2 = strrchr_m(name2_copy,'/');
5646 if (!pname1 || !pname2) {
5650 /* Truncate the copy of name2 at the last '/' */
5653 /* Now go past the '/' */
5657 root1 = talloc_strdup(ctx, pname1);
5658 root2 = talloc_strdup(ctx, pname2);
5660 if (!root1 || !root2) {
5664 p = strrchr_m(root1,'.');
5667 ext1 = talloc_strdup(ctx, p+1);
5669 ext1 = talloc_strdup(ctx, "");
5671 p = strrchr_m(root2,'.');
5674 ext2 = talloc_strdup(ctx, p+1);
5676 ext2 = talloc_strdup(ctx, "");
5679 if (!ext1 || !ext2) {
5687 /* Hmmm. Should this be mb-aware ? */
5690 } else if (*p2 == '*') {
5692 root2 = talloc_asprintf(ctx, "%s%s",
5711 /* Hmmm. Should this be mb-aware ? */
5714 } else if (*p2 == '*') {
5716 ext2 = talloc_asprintf(ctx, "%s%s",
5732 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5737 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5749 /****************************************************************************
5750 Ensure open files have their names updated. Updated to notify other smbd's
5752 ****************************************************************************/
5754 static void rename_open_files(connection_struct *conn,
5755 struct share_mode_lock *lck,
5756 const struct smb_filename *smb_fname_dst)
5759 bool did_rename = False;
5762 for(fsp = file_find_di_first(lck->id); fsp;
5763 fsp = file_find_di_next(fsp)) {
5764 /* fsp_name is a relative path under the fsp. To change this for other
5765 sharepaths we need to manipulate relative paths. */
5766 /* TODO - create the absolute path and manipulate the newname
5767 relative to the sharepath. */
5768 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5771 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5772 "(file_id %s) from %s -> %s\n", fsp->fnum,
5773 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5774 smb_fname_str_dbg(smb_fname_dst)));
5776 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5777 if (NT_STATUS_IS_OK(status)) {
5783 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5784 "for %s\n", file_id_string_tos(&lck->id),
5785 smb_fname_str_dbg(smb_fname_dst)));
5788 /* Send messages to all smbd's (not ourself) that the name has changed. */
5789 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5794 /****************************************************************************
5795 We need to check if the source path is a parent directory of the destination
5796 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5797 refuse the rename with a sharing violation. Under UNIX the above call can
5798 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5799 probably need to check that the client is a Windows one before disallowing
5800 this as a UNIX client (one with UNIX extensions) can know the source is a
5801 symlink and make this decision intelligently. Found by an excellent bug
5802 report from <AndyLiebman@aol.com>.
5803 ****************************************************************************/
5805 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5806 const struct smb_filename *smb_fname_dst)
5808 const char *psrc = smb_fname_src->base_name;
5809 const char *pdst = smb_fname_dst->base_name;
5812 if (psrc[0] == '.' && psrc[1] == '/') {
5815 if (pdst[0] == '.' && pdst[1] == '/') {
5818 if ((slen = strlen(psrc)) > strlen(pdst)) {
5821 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5825 * Do the notify calls from a rename
5828 static void notify_rename(connection_struct *conn, bool is_dir,
5829 const struct smb_filename *smb_fname_src,
5830 const struct smb_filename *smb_fname_dst)
5832 char *parent_dir_src = NULL;
5833 char *parent_dir_dst = NULL;
5836 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5837 : FILE_NOTIFY_CHANGE_FILE_NAME;
5839 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5840 &parent_dir_src, NULL) ||
5841 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5842 &parent_dir_dst, NULL)) {
5846 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5847 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5848 smb_fname_src->base_name);
5849 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5850 smb_fname_dst->base_name);
5853 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5854 smb_fname_src->base_name);
5855 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5856 smb_fname_dst->base_name);
5859 /* this is a strange one. w2k3 gives an additional event for
5860 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5861 files, but not directories */
5863 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5864 FILE_NOTIFY_CHANGE_ATTRIBUTES
5865 |FILE_NOTIFY_CHANGE_CREATION,
5866 smb_fname_dst->base_name);
5869 TALLOC_FREE(parent_dir_src);
5870 TALLOC_FREE(parent_dir_dst);
5873 /****************************************************************************
5874 Rename an open file - given an fsp.
5875 ****************************************************************************/
5877 NTSTATUS rename_internals_fsp(connection_struct *conn,
5879 const struct smb_filename *smb_fname_dst_in,
5881 bool replace_if_exists)
5883 TALLOC_CTX *ctx = talloc_tos();
5884 struct smb_filename *smb_fname_dst = NULL;
5885 NTSTATUS status = NT_STATUS_OK;
5886 struct share_mode_lock *lck = NULL;
5887 bool dst_exists, old_is_stream, new_is_stream;
5889 status = check_name(conn, smb_fname_dst_in->base_name);
5890 if (!NT_STATUS_IS_OK(status)) {
5894 /* Make a copy of the dst smb_fname structs */
5896 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5897 if (!NT_STATUS_IS_OK(status)) {
5901 /* Ensure the dst smb_fname contains a '/' */
5902 if(strrchr_m(smb_fname_dst->base_name,'/') == 0) {
5904 tmp = talloc_asprintf(smb_fname_dst, "./%s",
5905 smb_fname_dst->base_name);
5907 status = NT_STATUS_NO_MEMORY;
5910 TALLOC_FREE(smb_fname_dst->base_name);
5911 smb_fname_dst->base_name = tmp;
5915 * Check for special case with case preserving and not
5916 * case sensitive. If the old last component differs from the original
5917 * last component only by case, then we should allow
5918 * the rename (user is trying to change the case of the
5921 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5922 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5923 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
5925 char *fname_dst_lcomp_base_mod = NULL;
5926 struct smb_filename *smb_fname_orig_lcomp = NULL;
5929 * Get the last component of the destination name. Note that
5930 * we guarantee that destination name contains a '/' character
5933 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5934 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5935 if (!fname_dst_lcomp_base_mod) {
5936 status = NT_STATUS_NO_MEMORY;
5941 * Create an smb_filename struct using the original last
5942 * component of the destination.
5944 status = create_synthetic_smb_fname_split(ctx,
5945 smb_fname_dst->original_lcomp, NULL,
5946 &smb_fname_orig_lcomp);
5947 if (!NT_STATUS_IS_OK(status)) {
5948 TALLOC_FREE(fname_dst_lcomp_base_mod);
5952 /* If the base names only differ by case, use original. */
5953 if(!strcsequal(fname_dst_lcomp_base_mod,
5954 smb_fname_orig_lcomp->base_name)) {
5957 * Replace the modified last component with the
5960 *last_slash = '\0'; /* Truncate at the '/' */
5961 tmp = talloc_asprintf(smb_fname_dst,
5963 smb_fname_dst->base_name,
5964 smb_fname_orig_lcomp->base_name);
5966 status = NT_STATUS_NO_MEMORY;
5967 TALLOC_FREE(fname_dst_lcomp_base_mod);
5968 TALLOC_FREE(smb_fname_orig_lcomp);
5971 TALLOC_FREE(smb_fname_dst->base_name);
5972 smb_fname_dst->base_name = tmp;
5975 /* If the stream_names only differ by case, use original. */
5976 if(!strcsequal(smb_fname_dst->stream_name,
5977 smb_fname_orig_lcomp->stream_name)) {
5979 /* Use the original stream. */
5980 tmp = talloc_strdup(smb_fname_dst,
5981 smb_fname_orig_lcomp->stream_name);
5983 status = NT_STATUS_NO_MEMORY;
5984 TALLOC_FREE(fname_dst_lcomp_base_mod);
5985 TALLOC_FREE(smb_fname_orig_lcomp);
5988 TALLOC_FREE(smb_fname_dst->stream_name);
5989 smb_fname_dst->stream_name = tmp;
5991 TALLOC_FREE(fname_dst_lcomp_base_mod);
5992 TALLOC_FREE(smb_fname_orig_lcomp);
5996 * If the src and dest names are identical - including case,
5997 * don't do the rename, just return success.
6000 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6001 strcsequal(fsp->fsp_name->stream_name,
6002 smb_fname_dst->stream_name)) {
6003 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6004 "- returning success\n",
6005 smb_fname_str_dbg(smb_fname_dst)));
6006 status = NT_STATUS_OK;
6010 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6011 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6013 /* Return the correct error code if both names aren't streams. */
6014 if (!old_is_stream && new_is_stream) {
6015 status = NT_STATUS_OBJECT_NAME_INVALID;
6019 if (old_is_stream && !new_is_stream) {
6020 status = NT_STATUS_INVALID_PARAMETER;
6024 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6026 if(!replace_if_exists && dst_exists) {
6027 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6028 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6029 smb_fname_str_dbg(smb_fname_dst)));
6030 status = NT_STATUS_OBJECT_NAME_COLLISION;
6035 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6036 &smb_fname_dst->st);
6037 files_struct *dst_fsp = file_find_di_first(fileid);
6038 /* The file can be open when renaming a stream */
6039 if (dst_fsp && !new_is_stream) {
6040 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6041 status = NT_STATUS_ACCESS_DENIED;
6046 /* Ensure we have a valid stat struct for the source. */
6047 status = vfs_stat_fsp(fsp);
6048 if (!NT_STATUS_IS_OK(status)) {
6052 status = can_rename(conn, fsp, attrs);
6054 if (!NT_STATUS_IS_OK(status)) {
6055 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6056 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6057 smb_fname_str_dbg(smb_fname_dst)));
6058 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6059 status = NT_STATUS_ACCESS_DENIED;
6063 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6064 status = NT_STATUS_ACCESS_DENIED;
6067 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6071 * We have the file open ourselves, so not being able to get the
6072 * corresponding share mode lock is a fatal error.
6075 SMB_ASSERT(lck != NULL);
6077 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6078 uint32 create_options = fsp->fh->private_options;
6080 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6081 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6082 smb_fname_str_dbg(smb_fname_dst)));
6084 if (lp_map_archive(SNUM(conn)) ||
6085 lp_store_dos_attributes(SNUM(conn))) {
6086 /* We must set the archive bit on the newly
6088 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6089 uint32_t old_dosmode = dos_mode(conn,
6091 file_set_dosmode(conn,
6093 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6099 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6102 rename_open_files(conn, lck, smb_fname_dst);
6105 * A rename acts as a new file create w.r.t. allowing an initial delete
6106 * on close, probably because in Windows there is a new handle to the
6107 * new file. If initial delete on close was requested but not
6108 * originally set, we need to set it here. This is probably not 100% correct,
6109 * but will work for the CIFSFS client which in non-posix mode
6110 * depends on these semantics. JRA.
6113 if (create_options & FILE_DELETE_ON_CLOSE) {
6114 status = can_set_delete_on_close(fsp, 0);
6116 if (NT_STATUS_IS_OK(status)) {
6117 /* Note that here we set the *inital* delete on close flag,
6118 * not the regular one. The magic gets handled in close. */
6119 fsp->initial_delete_on_close = True;
6123 status = NT_STATUS_OK;
6129 if (errno == ENOTDIR || errno == EISDIR) {
6130 status = NT_STATUS_OBJECT_NAME_COLLISION;
6132 status = map_nt_error_from_unix(errno);
6135 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6136 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6137 smb_fname_str_dbg(smb_fname_dst)));
6140 TALLOC_FREE(smb_fname_dst);
6145 /****************************************************************************
6146 The guts of the rename command, split out so it may be called by the NT SMB
6148 ****************************************************************************/
6150 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6151 connection_struct *conn,
6152 struct smb_request *req,
6153 struct smb_filename *smb_fname_src,
6154 struct smb_filename *smb_fname_dst,
6156 bool replace_if_exists,
6159 uint32_t access_mask)
6161 char *fname_src_dir = NULL;
6162 char *fname_src_mask = NULL;
6164 NTSTATUS status = NT_STATUS_OK;
6165 struct smb_Dir *dir_hnd = NULL;
6166 const char *dname = NULL;
6167 char *talloced = NULL;
6169 int create_options = 0;
6170 bool posix_pathnames = lp_posix_pathnames();
6173 * Split the old name into directory and last component
6174 * strings. Note that unix_convert may have stripped off a
6175 * leading ./ from both name and newname if the rename is
6176 * at the root of the share. We need to make sure either both
6177 * name and newname contain a / character or neither of them do
6178 * as this is checked in resolve_wildcards().
6181 /* Split up the directory from the filename/mask. */
6182 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6183 &fname_src_dir, &fname_src_mask);
6184 if (!NT_STATUS_IS_OK(status)) {
6185 status = NT_STATUS_NO_MEMORY;
6190 * We should only check the mangled cache
6191 * here if unix_convert failed. This means
6192 * that the path in 'mask' doesn't exist
6193 * on the file system and so we need to look
6194 * for a possible mangle. This patch from
6195 * Tine Smukavec <valentin.smukavec@hermes.si>.
6198 if (!VALID_STAT(smb_fname_src->st) &&
6199 mangle_is_mangled(fname_src_mask, conn->params)) {
6200 char *new_mask = NULL;
6201 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6204 TALLOC_FREE(fname_src_mask);
6205 fname_src_mask = new_mask;
6209 if (!src_has_wild) {
6213 * Only one file needs to be renamed. Append the mask back
6214 * onto the directory.
6216 TALLOC_FREE(smb_fname_src->base_name);
6217 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6221 if (!smb_fname_src->base_name) {
6222 status = NT_STATUS_NO_MEMORY;
6226 /* Ensure dst fname contains a '/' also */
6227 if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
6229 tmp = talloc_asprintf(smb_fname_dst, "./%s",
6230 smb_fname_dst->base_name);
6232 status = NT_STATUS_NO_MEMORY;
6235 TALLOC_FREE(smb_fname_dst->base_name);
6236 smb_fname_dst->base_name = tmp;
6239 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6240 "case_preserve = %d, short case preserve = %d, "
6241 "directory = %s, newname = %s, "
6242 "last_component_dest = %s\n",
6243 conn->case_sensitive, conn->case_preserve,
6244 conn->short_case_preserve,
6245 smb_fname_str_dbg(smb_fname_src),
6246 smb_fname_str_dbg(smb_fname_dst),
6247 smb_fname_dst->original_lcomp));
6249 /* The dest name still may have wildcards. */
6250 if (dest_has_wild) {
6251 char *fname_dst_mod = NULL;
6252 if (!resolve_wildcards(smb_fname_dst,
6253 smb_fname_src->base_name,
6254 smb_fname_dst->base_name,
6256 DEBUG(6, ("rename_internals: resolve_wildcards "
6258 smb_fname_src->base_name,
6259 smb_fname_dst->base_name));
6260 status = NT_STATUS_NO_MEMORY;
6263 TALLOC_FREE(smb_fname_dst->base_name);
6264 smb_fname_dst->base_name = fname_dst_mod;
6267 ZERO_STRUCT(smb_fname_src->st);
6268 if (posix_pathnames) {
6269 SMB_VFS_LSTAT(conn, smb_fname_src);
6271 SMB_VFS_STAT(conn, smb_fname_src);
6274 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6275 create_options |= FILE_DIRECTORY_FILE;
6278 status = SMB_VFS_CREATE_FILE(
6281 0, /* root_dir_fid */
6282 smb_fname_src, /* fname */
6283 access_mask, /* access_mask */
6284 (FILE_SHARE_READ | /* share_access */
6286 FILE_OPEN, /* create_disposition*/
6287 create_options, /* create_options */
6288 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6289 0, /* oplock_request */
6290 0, /* allocation_size */
6291 0, /* private_flags */
6297 if (!NT_STATUS_IS_OK(status)) {
6298 DEBUG(3, ("Could not open rename source %s: %s\n",
6299 smb_fname_str_dbg(smb_fname_src),
6300 nt_errstr(status)));
6304 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6305 attrs, replace_if_exists);
6307 close_file(req, fsp, NORMAL_CLOSE);
6309 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6310 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6311 smb_fname_str_dbg(smb_fname_dst)));
6317 * Wildcards - process each file that matches.
6319 if (strequal(fname_src_mask, "????????.???")) {
6320 TALLOC_FREE(fname_src_mask);
6321 fname_src_mask = talloc_strdup(ctx, "*");
6322 if (!fname_src_mask) {
6323 status = NT_STATUS_NO_MEMORY;
6328 status = check_name(conn, fname_src_dir);
6329 if (!NT_STATUS_IS_OK(status)) {
6333 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6335 if (dir_hnd == NULL) {
6336 status = map_nt_error_from_unix(errno);
6340 status = NT_STATUS_NO_SUCH_FILE;
6342 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6343 * - gentest fix. JRA
6346 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6348 files_struct *fsp = NULL;
6349 char *destname = NULL;
6350 bool sysdir_entry = False;
6352 /* Quick check for "." and ".." */
6353 if (ISDOT(dname) || ISDOTDOT(dname)) {
6355 sysdir_entry = True;
6357 TALLOC_FREE(talloced);
6362 if (!is_visible_file(conn, fname_src_dir, dname,
6363 &smb_fname_src->st, false)) {
6364 TALLOC_FREE(talloced);
6368 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6369 TALLOC_FREE(talloced);
6374 status = NT_STATUS_OBJECT_NAME_INVALID;
6378 TALLOC_FREE(smb_fname_src->base_name);
6379 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6383 if (!smb_fname_src->base_name) {
6384 status = NT_STATUS_NO_MEMORY;
6388 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6389 smb_fname_dst->base_name,
6391 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6392 smb_fname_src->base_name, destname));
6393 TALLOC_FREE(talloced);
6397 status = NT_STATUS_NO_MEMORY;
6401 TALLOC_FREE(smb_fname_dst->base_name);
6402 smb_fname_dst->base_name = destname;
6404 ZERO_STRUCT(smb_fname_src->st);
6405 if (posix_pathnames) {
6406 SMB_VFS_LSTAT(conn, smb_fname_src);
6408 SMB_VFS_STAT(conn, smb_fname_src);
6413 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6414 create_options |= FILE_DIRECTORY_FILE;
6417 status = SMB_VFS_CREATE_FILE(
6420 0, /* root_dir_fid */
6421 smb_fname_src, /* fname */
6422 access_mask, /* access_mask */
6423 (FILE_SHARE_READ | /* share_access */
6425 FILE_OPEN, /* create_disposition*/
6426 create_options, /* create_options */
6427 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6428 0, /* oplock_request */
6429 0, /* allocation_size */
6430 0, /* private_flags */
6436 if (!NT_STATUS_IS_OK(status)) {
6437 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6438 "returned %s rename %s -> %s\n",
6440 smb_fname_str_dbg(smb_fname_src),
6441 smb_fname_str_dbg(smb_fname_dst)));
6445 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6447 if (!smb_fname_dst->original_lcomp) {
6448 status = NT_STATUS_NO_MEMORY;
6452 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6453 attrs, replace_if_exists);
6455 close_file(req, fsp, NORMAL_CLOSE);
6457 if (!NT_STATUS_IS_OK(status)) {
6458 DEBUG(3, ("rename_internals_fsp returned %s for "
6459 "rename %s -> %s\n", nt_errstr(status),
6460 smb_fname_str_dbg(smb_fname_src),
6461 smb_fname_str_dbg(smb_fname_dst)));
6467 DEBUG(3,("rename_internals: doing rename on %s -> "
6468 "%s\n", smb_fname_str_dbg(smb_fname_src),
6469 smb_fname_str_dbg(smb_fname_src)));
6470 TALLOC_FREE(talloced);
6472 TALLOC_FREE(dir_hnd);
6474 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6475 status = map_nt_error_from_unix(errno);
6479 TALLOC_FREE(talloced);
6480 TALLOC_FREE(fname_src_dir);
6481 TALLOC_FREE(fname_src_mask);
6485 /****************************************************************************
6487 ****************************************************************************/
6489 void reply_mv(struct smb_request *req)
6491 connection_struct *conn = req->conn;
6493 char *newname = NULL;
6497 bool src_has_wcard = False;
6498 bool dest_has_wcard = False;
6499 TALLOC_CTX *ctx = talloc_tos();
6500 struct smb_filename *smb_fname_src = NULL;
6501 struct smb_filename *smb_fname_dst = NULL;
6503 START_PROFILE(SMBmv);
6506 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6510 attrs = SVAL(req->vwv+0, 0);
6512 p = (const char *)req->buf + 1;
6513 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6514 &status, &src_has_wcard);
6515 if (!NT_STATUS_IS_OK(status)) {
6516 reply_nterror(req, status);
6520 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6521 &status, &dest_has_wcard);
6522 if (!NT_STATUS_IS_OK(status)) {
6523 reply_nterror(req, status);
6527 status = filename_convert(ctx,
6529 req->flags2 & FLAGS2_DFS_PATHNAMES,
6531 UCF_COND_ALLOW_WCARD_LCOMP,
6535 if (!NT_STATUS_IS_OK(status)) {
6536 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6537 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6538 ERRSRV, ERRbadpath);
6541 reply_nterror(req, status);
6545 status = filename_convert(ctx,
6547 req->flags2 & FLAGS2_DFS_PATHNAMES,
6549 UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6553 if (!NT_STATUS_IS_OK(status)) {
6554 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6555 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6556 ERRSRV, ERRbadpath);
6559 reply_nterror(req, status);
6563 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6564 smb_fname_str_dbg(smb_fname_dst)));
6566 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6567 attrs, False, src_has_wcard, dest_has_wcard,
6569 if (!NT_STATUS_IS_OK(status)) {
6570 if (open_was_deferred(req->mid)) {
6571 /* We have re-scheduled this call. */
6574 reply_nterror(req, status);
6578 reply_outbuf(req, 0, 0);
6580 TALLOC_FREE(smb_fname_src);
6581 TALLOC_FREE(smb_fname_dst);
6586 /*******************************************************************
6587 Copy a file as part of a reply_copy.
6588 ******************************************************************/
6591 * TODO: check error codes on all callers
6594 NTSTATUS copy_file(TALLOC_CTX *ctx,
6595 connection_struct *conn,
6596 struct smb_filename *smb_fname_src,
6597 struct smb_filename *smb_fname_dst,
6600 bool target_is_directory)
6602 struct smb_filename *smb_fname_dst_tmp = NULL;
6604 files_struct *fsp1,*fsp2;
6606 uint32 new_create_disposition;
6610 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6611 if (!NT_STATUS_IS_OK(status)) {
6616 * If the target is a directory, extract the last component from the
6617 * src filename and append it to the dst filename
6619 if (target_is_directory) {
6622 /* dest/target can't be a stream if it's a directory. */
6623 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6625 p = strrchr_m(smb_fname_src->base_name,'/');
6629 p = smb_fname_src->base_name;
6631 smb_fname_dst_tmp->base_name =
6632 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6634 if (!smb_fname_dst_tmp->base_name) {
6635 status = NT_STATUS_NO_MEMORY;
6640 status = vfs_file_exist(conn, smb_fname_src);
6641 if (!NT_STATUS_IS_OK(status)) {
6645 if (!target_is_directory && count) {
6646 new_create_disposition = FILE_OPEN;
6648 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
6650 &new_create_disposition,
6653 status = NT_STATUS_INVALID_PARAMETER;
6658 /* Open the src file for reading. */
6659 status = SMB_VFS_CREATE_FILE(
6662 0, /* root_dir_fid */
6663 smb_fname_src, /* fname */
6664 FILE_GENERIC_READ, /* access_mask */
6665 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6666 FILE_OPEN, /* create_disposition*/
6667 0, /* create_options */
6668 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6669 INTERNAL_OPEN_ONLY, /* oplock_request */
6670 0, /* allocation_size */
6671 0, /* private_flags */
6677 if (!NT_STATUS_IS_OK(status)) {
6681 dosattrs = dos_mode(conn, smb_fname_src);
6683 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6684 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6687 /* Open the dst file for writing. */
6688 status = SMB_VFS_CREATE_FILE(
6691 0, /* root_dir_fid */
6692 smb_fname_dst, /* fname */
6693 FILE_GENERIC_WRITE, /* access_mask */
6694 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6695 new_create_disposition, /* create_disposition*/
6696 0, /* create_options */
6697 dosattrs, /* file_attributes */
6698 INTERNAL_OPEN_ONLY, /* oplock_request */
6699 0, /* allocation_size */
6700 0, /* private_flags */
6706 if (!NT_STATUS_IS_OK(status)) {
6707 close_file(NULL, fsp1, ERROR_CLOSE);
6711 if ((ofun&3) == 1) {
6712 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6713 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6715 * Stop the copy from occurring.
6718 smb_fname_src->st.st_ex_size = 0;
6722 /* Do the actual copy. */
6723 if (smb_fname_src->st.st_ex_size) {
6724 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6727 close_file(NULL, fsp1, NORMAL_CLOSE);
6729 /* Ensure the modtime is set correctly on the destination file. */
6730 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6733 * As we are opening fsp1 read-only we only expect
6734 * an error on close on fsp2 if we are out of space.
6735 * Thus we don't look at the error return from the
6738 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6740 if (!NT_STATUS_IS_OK(status)) {
6744 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6745 status = NT_STATUS_DISK_FULL;
6749 status = NT_STATUS_OK;
6752 TALLOC_FREE(smb_fname_dst_tmp);
6756 /****************************************************************************
6757 Reply to a file copy.
6758 ****************************************************************************/
6760 void reply_copy(struct smb_request *req)
6762 connection_struct *conn = req->conn;
6763 struct smb_filename *smb_fname_src = NULL;
6764 struct smb_filename *smb_fname_dst = NULL;
6765 char *fname_src = NULL;
6766 char *fname_dst = NULL;
6767 char *fname_src_mask = NULL;
6768 char *fname_src_dir = NULL;
6771 int error = ERRnoaccess;
6775 bool target_is_directory=False;
6776 bool source_has_wild = False;
6777 bool dest_has_wild = False;
6779 TALLOC_CTX *ctx = talloc_tos();
6781 START_PROFILE(SMBcopy);
6784 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6788 tid2 = SVAL(req->vwv+0, 0);
6789 ofun = SVAL(req->vwv+1, 0);
6790 flags = SVAL(req->vwv+2, 0);
6792 p = (const char *)req->buf;
6793 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6794 &status, &source_has_wild);
6795 if (!NT_STATUS_IS_OK(status)) {
6796 reply_nterror(req, status);
6799 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6800 &status, &dest_has_wild);
6801 if (!NT_STATUS_IS_OK(status)) {
6802 reply_nterror(req, status);
6806 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6808 if (tid2 != conn->cnum) {
6809 /* can't currently handle inter share copies XXXX */
6810 DEBUG(3,("Rejecting inter-share copy\n"));
6811 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6815 status = filename_convert(ctx, conn,
6816 req->flags2 & FLAGS2_DFS_PATHNAMES,
6818 UCF_COND_ALLOW_WCARD_LCOMP,
6821 if (!NT_STATUS_IS_OK(status)) {
6822 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6823 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6824 ERRSRV, ERRbadpath);
6827 reply_nterror(req, status);
6831 status = filename_convert(ctx, conn,
6832 req->flags2 & FLAGS2_DFS_PATHNAMES,
6834 UCF_COND_ALLOW_WCARD_LCOMP,
6837 if (!NT_STATUS_IS_OK(status)) {
6838 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6839 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6840 ERRSRV, ERRbadpath);
6843 reply_nterror(req, status);
6847 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6849 if ((flags&1) && target_is_directory) {
6850 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6854 if ((flags&2) && !target_is_directory) {
6855 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
6859 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6860 /* wants a tree copy! XXXX */
6861 DEBUG(3,("Rejecting tree copy\n"));
6862 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6866 /* Split up the directory from the filename/mask. */
6867 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6868 &fname_src_dir, &fname_src_mask);
6869 if (!NT_STATUS_IS_OK(status)) {
6870 reply_nterror(req, NT_STATUS_NO_MEMORY);
6875 * We should only check the mangled cache
6876 * here if unix_convert failed. This means
6877 * that the path in 'mask' doesn't exist
6878 * on the file system and so we need to look
6879 * for a possible mangle. This patch from
6880 * Tine Smukavec <valentin.smukavec@hermes.si>.
6882 if (!VALID_STAT(smb_fname_src->st) &&
6883 mangle_is_mangled(fname_src_mask, conn->params)) {
6884 char *new_mask = NULL;
6885 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6886 &new_mask, conn->params);
6888 /* Use demangled name if one was successfully found. */
6890 TALLOC_FREE(fname_src_mask);
6891 fname_src_mask = new_mask;
6895 if (!source_has_wild) {
6898 * Only one file needs to be copied. Append the mask back onto
6901 TALLOC_FREE(smb_fname_src->base_name);
6902 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6906 if (!smb_fname_src->base_name) {
6907 reply_nterror(req, NT_STATUS_NO_MEMORY);
6911 if (dest_has_wild) {
6912 char *fname_dst_mod = NULL;
6913 if (!resolve_wildcards(smb_fname_dst,
6914 smb_fname_src->base_name,
6915 smb_fname_dst->base_name,
6917 reply_nterror(req, NT_STATUS_NO_MEMORY);
6920 TALLOC_FREE(smb_fname_dst->base_name);
6921 smb_fname_dst->base_name = fname_dst_mod;
6924 status = check_name(conn, smb_fname_src->base_name);
6925 if (!NT_STATUS_IS_OK(status)) {
6926 reply_nterror(req, status);
6930 status = check_name(conn, smb_fname_dst->base_name);
6931 if (!NT_STATUS_IS_OK(status)) {
6932 reply_nterror(req, status);
6936 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
6937 ofun, count, target_is_directory);
6939 if(!NT_STATUS_IS_OK(status)) {
6940 reply_nterror(req, status);
6946 struct smb_Dir *dir_hnd = NULL;
6947 const char *dname = NULL;
6948 char *talloced = NULL;
6952 * There is a wildcard that requires us to actually read the
6953 * src dir and copy each file matching the mask to the dst.
6954 * Right now streams won't be copied, but this could
6955 * presumably be added with a nested loop for reach dir entry.
6957 SMB_ASSERT(!smb_fname_src->stream_name);
6958 SMB_ASSERT(!smb_fname_dst->stream_name);
6960 smb_fname_src->stream_name = NULL;
6961 smb_fname_dst->stream_name = NULL;
6963 if (strequal(fname_src_mask,"????????.???")) {
6964 TALLOC_FREE(fname_src_mask);
6965 fname_src_mask = talloc_strdup(ctx, "*");
6966 if (!fname_src_mask) {
6967 reply_nterror(req, NT_STATUS_NO_MEMORY);
6972 status = check_name(conn, fname_src_dir);
6973 if (!NT_STATUS_IS_OK(status)) {
6974 reply_nterror(req, status);
6978 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
6979 if (dir_hnd == NULL) {
6980 status = map_nt_error_from_unix(errno);
6981 reply_nterror(req, status);
6987 /* Iterate over the src dir copying each entry to the dst. */
6988 while ((dname = ReadDirName(dir_hnd, &offset,
6989 &smb_fname_src->st, &talloced))) {
6990 char *destname = NULL;
6992 if (ISDOT(dname) || ISDOTDOT(dname)) {
6993 TALLOC_FREE(talloced);
6997 if (!is_visible_file(conn, fname_src_dir, dname,
6998 &smb_fname_src->st, false)) {
6999 TALLOC_FREE(talloced);
7003 if(!mask_match(dname, fname_src_mask,
7004 conn->case_sensitive)) {
7005 TALLOC_FREE(talloced);
7009 error = ERRnoaccess;
7011 /* Get the src smb_fname struct setup. */
7012 TALLOC_FREE(smb_fname_src->base_name);
7013 smb_fname_src->base_name =
7014 talloc_asprintf(smb_fname_src, "%s/%s",
7015 fname_src_dir, dname);
7017 if (!smb_fname_src->base_name) {
7018 TALLOC_FREE(dir_hnd);
7019 TALLOC_FREE(talloced);
7020 reply_nterror(req, NT_STATUS_NO_MEMORY);
7024 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7025 smb_fname_dst->base_name,
7027 TALLOC_FREE(talloced);
7031 TALLOC_FREE(dir_hnd);
7032 TALLOC_FREE(talloced);
7033 reply_nterror(req, NT_STATUS_NO_MEMORY);
7037 TALLOC_FREE(smb_fname_dst->base_name);
7038 smb_fname_dst->base_name = destname;
7040 status = check_name(conn, smb_fname_src->base_name);
7041 if (!NT_STATUS_IS_OK(status)) {
7042 TALLOC_FREE(dir_hnd);
7043 TALLOC_FREE(talloced);
7044 reply_nterror(req, status);
7048 status = check_name(conn, smb_fname_dst->base_name);
7049 if (!NT_STATUS_IS_OK(status)) {
7050 TALLOC_FREE(dir_hnd);
7051 TALLOC_FREE(talloced);
7052 reply_nterror(req, status);
7056 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7057 smb_fname_src->base_name,
7058 smb_fname_dst->base_name));
7060 status = copy_file(ctx, conn, smb_fname_src,
7061 smb_fname_dst, ofun, count,
7062 target_is_directory);
7063 if (NT_STATUS_IS_OK(status)) {
7067 TALLOC_FREE(talloced);
7069 TALLOC_FREE(dir_hnd);
7073 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7077 reply_outbuf(req, 1, 0);
7078 SSVAL(req->outbuf,smb_vwv0,count);
7080 TALLOC_FREE(smb_fname_src);
7081 TALLOC_FREE(smb_fname_dst);
7082 TALLOC_FREE(fname_src);
7083 TALLOC_FREE(fname_dst);
7084 TALLOC_FREE(fname_src_mask);
7085 TALLOC_FREE(fname_src_dir);
7087 END_PROFILE(SMBcopy);
7092 #define DBGC_CLASS DBGC_LOCKING
7094 /****************************************************************************
7095 Get a lock pid, dealing with large count requests.
7096 ****************************************************************************/
7098 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7099 bool large_file_format)
7101 if(!large_file_format)
7102 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7104 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7107 /****************************************************************************
7108 Get a lock count, dealing with large count requests.
7109 ****************************************************************************/
7111 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7112 bool large_file_format)
7116 if(!large_file_format) {
7117 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7120 #if defined(HAVE_LONGLONG)
7121 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7122 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7123 #else /* HAVE_LONGLONG */
7126 * NT4.x seems to be broken in that it sends large file (64 bit)
7127 * lockingX calls even if the CAP_LARGE_FILES was *not*
7128 * negotiated. For boxes without large unsigned ints truncate the
7129 * lock count by dropping the top 32 bits.
7132 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7133 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7134 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7135 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7136 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7139 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7140 #endif /* HAVE_LONGLONG */
7146 #if !defined(HAVE_LONGLONG)
7147 /****************************************************************************
7148 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7149 ****************************************************************************/
7151 static uint32 map_lock_offset(uint32 high, uint32 low)
7155 uint32 highcopy = high;
7158 * Try and find out how many significant bits there are in high.
7161 for(i = 0; highcopy; i++)
7165 * We use 31 bits not 32 here as POSIX
7166 * lock offsets may not be negative.
7169 mask = (~0) << (31 - i);
7172 return 0; /* Fail. */
7178 #endif /* !defined(HAVE_LONGLONG) */
7180 /****************************************************************************
7181 Get a lock offset, dealing with large offset requests.
7182 ****************************************************************************/
7184 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7185 bool large_file_format, bool *err)
7187 uint64_t offset = 0;
7191 if(!large_file_format) {
7192 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7195 #if defined(HAVE_LONGLONG)
7196 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7197 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7198 #else /* HAVE_LONGLONG */
7201 * NT4.x seems to be broken in that it sends large file (64 bit)
7202 * lockingX calls even if the CAP_LARGE_FILES was *not*
7203 * negotiated. For boxes without large unsigned ints mangle the
7204 * lock offset by mapping the top 32 bits onto the lower 32.
7207 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7208 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7209 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7212 if((new_low = map_lock_offset(high, low)) == 0) {
7214 return (uint64_t)-1;
7217 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7218 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7219 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7220 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7223 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7224 #endif /* HAVE_LONGLONG */
7230 NTSTATUS smbd_do_locking(struct smb_request *req,
7234 uint16_t num_ulocks,
7235 struct smbd_lock_element *ulocks,
7237 struct smbd_lock_element *locks,
7240 connection_struct *conn = req->conn;
7242 NTSTATUS status = NT_STATUS_OK;
7246 /* Data now points at the beginning of the list
7247 of smb_unlkrng structs */
7248 for(i = 0; i < (int)num_ulocks; i++) {
7249 struct smbd_lock_element *e = &ulocks[i];
7251 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7252 "pid %u, file %s\n",
7255 (unsigned int)e->smblctx,
7258 if (e->brltype != UNLOCK_LOCK) {
7259 /* this can only happen with SMB2 */
7260 return NT_STATUS_INVALID_PARAMETER;
7263 status = do_unlock(req->sconn->msg_ctx,
7270 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7271 nt_errstr(status)));
7273 if (!NT_STATUS_IS_OK(status)) {
7278 /* Setup the timeout in seconds. */
7280 if (!lp_blocking_locks(SNUM(conn))) {
7284 /* Data now points at the beginning of the list
7285 of smb_lkrng structs */
7287 for(i = 0; i < (int)num_locks; i++) {
7288 struct smbd_lock_element *e = &locks[i];
7290 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7291 "%llu, file %s timeout = %d\n",
7294 (unsigned long long)e->smblctx,
7298 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7299 struct blocking_lock_record *blr = NULL;
7301 if (num_locks > 1) {
7303 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7304 * if the lock vector contains one entry. When given mutliple cancel
7305 * requests in a single PDU we expect the server to return an
7306 * error. Windows servers seem to accept the request but only
7307 * cancel the first lock.
7308 * JRA - Do what Windows does (tm) :-).
7312 /* MS-CIFS (2.2.4.32.1) behavior. */
7313 return NT_STATUS_DOS(ERRDOS,
7314 ERRcancelviolation);
7316 /* Windows behavior. */
7318 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7319 "cancel request\n"));
7325 if (lp_blocking_locks(SNUM(conn))) {
7327 /* Schedule a message to ourselves to
7328 remove the blocking lock record and
7329 return the right error. */
7331 blr = blocking_lock_cancel_smb1(fsp,
7337 NT_STATUS_FILE_LOCK_CONFLICT);
7339 return NT_STATUS_DOS(
7341 ERRcancelviolation);
7344 /* Remove a matching pending lock. */
7345 status = do_lock_cancel(fsp,
7352 bool blocking_lock = timeout ? true : false;
7353 bool defer_lock = false;
7354 struct byte_range_lock *br_lck;
7355 uint64_t block_smblctx;
7357 br_lck = do_lock(req->sconn->msg_ctx,
7369 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7370 /* Windows internal resolution for blocking locks seems
7371 to be about 200ms... Don't wait for less than that. JRA. */
7372 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7373 timeout = lp_lock_spin_time();
7378 /* If a lock sent with timeout of zero would fail, and
7379 * this lock has been requested multiple times,
7380 * according to brl_lock_failed() we convert this
7381 * request to a blocking lock with a timeout of between
7382 * 150 - 300 milliseconds.
7384 * If lp_lock_spin_time() has been set to 0, we skip
7385 * this blocking retry and fail immediately.
7387 * Replacement for do_lock_spin(). JRA. */
7389 if (!req->sconn->using_smb2 &&
7390 br_lck && lp_blocking_locks(SNUM(conn)) &&
7391 lp_lock_spin_time() && !blocking_lock &&
7392 NT_STATUS_EQUAL((status),
7393 NT_STATUS_FILE_LOCK_CONFLICT))
7396 timeout = lp_lock_spin_time();
7399 if (br_lck && defer_lock) {
7401 * A blocking lock was requested. Package up
7402 * this smb into a queued request and push it
7403 * onto the blocking lock queue.
7405 if(push_blocking_lock_request(br_lck,
7416 TALLOC_FREE(br_lck);
7418 return NT_STATUS_OK;
7422 TALLOC_FREE(br_lck);
7425 if (!NT_STATUS_IS_OK(status)) {
7430 /* If any of the above locks failed, then we must unlock
7431 all of the previous locks (X/Open spec). */
7433 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7435 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7436 i = -1; /* we want to skip the for loop */
7440 * Ensure we don't do a remove on the lock that just failed,
7441 * as under POSIX rules, if we have a lock already there, we
7442 * will delete it (and we shouldn't) .....
7444 for(i--; i >= 0; i--) {
7445 struct smbd_lock_element *e = &locks[i];
7447 do_unlock(req->sconn->msg_ctx,
7457 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7458 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7460 return NT_STATUS_OK;
7463 /****************************************************************************
7464 Reply to a lockingX request.
7465 ****************************************************************************/
7467 void reply_lockingX(struct smb_request *req)
7469 connection_struct *conn = req->conn;
7471 unsigned char locktype;
7472 unsigned char oplocklevel;
7477 const uint8_t *data;
7478 bool large_file_format;
7480 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7481 struct smbd_lock_element *ulocks;
7482 struct smbd_lock_element *locks;
7485 START_PROFILE(SMBlockingX);
7488 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7489 END_PROFILE(SMBlockingX);
7493 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7494 locktype = CVAL(req->vwv+3, 0);
7495 oplocklevel = CVAL(req->vwv+3, 1);
7496 num_ulocks = SVAL(req->vwv+6, 0);
7497 num_locks = SVAL(req->vwv+7, 0);
7498 lock_timeout = IVAL(req->vwv+4, 0);
7499 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7501 if (!check_fsp(conn, req, fsp)) {
7502 END_PROFILE(SMBlockingX);
7508 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7509 /* we don't support these - and CANCEL_LOCK makes w2k
7510 and XP reboot so I don't really want to be
7511 compatible! (tridge) */
7512 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7513 END_PROFILE(SMBlockingX);
7517 /* Check if this is an oplock break on a file
7518 we have granted an oplock on.
7520 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7521 /* Client can insist on breaking to none. */
7522 bool break_to_none = (oplocklevel == 0);
7525 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7526 "for fnum = %d\n", (unsigned int)oplocklevel,
7530 * Make sure we have granted an exclusive or batch oplock on
7534 if (fsp->oplock_type == 0) {
7536 /* The Samba4 nbench simulator doesn't understand
7537 the difference between break to level2 and break
7538 to none from level2 - it sends oplock break
7539 replies in both cases. Don't keep logging an error
7540 message here - just ignore it. JRA. */
7542 DEBUG(5,("reply_lockingX: Error : oplock break from "
7543 "client for fnum = %d (oplock=%d) and no "
7544 "oplock granted on this file (%s).\n",
7545 fsp->fnum, fsp->oplock_type,
7548 /* if this is a pure oplock break request then don't
7550 if (num_locks == 0 && num_ulocks == 0) {
7551 END_PROFILE(SMBlockingX);
7554 END_PROFILE(SMBlockingX);
7555 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7560 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7562 result = remove_oplock(fsp);
7564 result = downgrade_oplock(fsp);
7568 DEBUG(0, ("reply_lockingX: error in removing "
7569 "oplock on file %s\n", fsp_str_dbg(fsp)));
7570 /* Hmmm. Is this panic justified? */
7571 smb_panic("internal tdb error");
7574 reply_to_oplock_break_requests(fsp);
7576 /* if this is a pure oplock break request then don't send a
7578 if (num_locks == 0 && num_ulocks == 0) {
7579 /* Sanity check - ensure a pure oplock break is not a
7581 if(CVAL(req->vwv+0, 0) != 0xff)
7582 DEBUG(0,("reply_lockingX: Error : pure oplock "
7583 "break is a chained %d request !\n",
7584 (unsigned int)CVAL(req->vwv+0, 0)));
7585 END_PROFILE(SMBlockingX);
7591 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7592 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7593 END_PROFILE(SMBlockingX);
7597 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7598 if (ulocks == NULL) {
7599 reply_nterror(req, NT_STATUS_NO_MEMORY);
7600 END_PROFILE(SMBlockingX);
7604 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7605 if (locks == NULL) {
7606 reply_nterror(req, NT_STATUS_NO_MEMORY);
7607 END_PROFILE(SMBlockingX);
7611 /* Data now points at the beginning of the list
7612 of smb_unlkrng structs */
7613 for(i = 0; i < (int)num_ulocks; i++) {
7614 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7615 ulocks[i].count = get_lock_count(data, i, large_file_format);
7616 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7617 ulocks[i].brltype = UNLOCK_LOCK;
7620 * There is no error code marked "stupid client bug".... :-).
7623 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7624 END_PROFILE(SMBlockingX);
7629 /* Now do any requested locks */
7630 data += ((large_file_format ? 20 : 10)*num_ulocks);
7632 /* Data now points at the beginning of the list
7633 of smb_lkrng structs */
7635 for(i = 0; i < (int)num_locks; i++) {
7636 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7637 locks[i].count = get_lock_count(data, i, large_file_format);
7638 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7640 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7641 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7642 locks[i].brltype = PENDING_READ_LOCK;
7644 locks[i].brltype = READ_LOCK;
7647 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7648 locks[i].brltype = PENDING_WRITE_LOCK;
7650 locks[i].brltype = WRITE_LOCK;
7655 * There is no error code marked "stupid client bug".... :-).
7658 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7659 END_PROFILE(SMBlockingX);
7664 status = smbd_do_locking(req, fsp,
7665 locktype, lock_timeout,
7669 if (!NT_STATUS_IS_OK(status)) {
7670 END_PROFILE(SMBlockingX);
7671 reply_nterror(req, status);
7675 END_PROFILE(SMBlockingX);
7679 reply_outbuf(req, 2, 0);
7681 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7682 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7684 END_PROFILE(SMBlockingX);
7689 #define DBGC_CLASS DBGC_ALL
7691 /****************************************************************************
7692 Reply to a SMBreadbmpx (read block multiplex) request.
7693 Always reply with an error, if someone has a platform really needs this,
7694 please contact vl@samba.org
7695 ****************************************************************************/
7697 void reply_readbmpx(struct smb_request *req)
7699 START_PROFILE(SMBreadBmpx);
7700 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7701 END_PROFILE(SMBreadBmpx);
7705 /****************************************************************************
7706 Reply to a SMBreadbs (read block multiplex secondary) request.
7707 Always reply with an error, if someone has a platform really needs this,
7708 please contact vl@samba.org
7709 ****************************************************************************/
7711 void reply_readbs(struct smb_request *req)
7713 START_PROFILE(SMBreadBs);
7714 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7715 END_PROFILE(SMBreadBs);
7719 /****************************************************************************
7720 Reply to a SMBsetattrE.
7721 ****************************************************************************/
7723 void reply_setattrE(struct smb_request *req)
7725 connection_struct *conn = req->conn;
7726 struct smb_file_time ft;
7730 START_PROFILE(SMBsetattrE);
7734 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7738 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7740 if(!fsp || (fsp->conn != conn)) {
7741 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7746 * Convert the DOS times into unix times.
7749 ft.atime = convert_time_t_to_timespec(
7750 srv_make_unix_date2(req->vwv+3));
7751 ft.mtime = convert_time_t_to_timespec(
7752 srv_make_unix_date2(req->vwv+5));
7753 ft.create_time = convert_time_t_to_timespec(
7754 srv_make_unix_date2(req->vwv+1));
7756 reply_outbuf(req, 0, 0);
7759 * Patch from Ray Frush <frush@engr.colostate.edu>
7760 * Sometimes times are sent as zero - ignore them.
7763 /* Ensure we have a valid stat struct for the source. */
7764 status = vfs_stat_fsp(fsp);
7765 if (!NT_STATUS_IS_OK(status)) {
7766 reply_nterror(req, status);
7770 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7771 if (!NT_STATUS_IS_OK(status)) {
7772 reply_nterror(req, status);
7776 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7779 (unsigned int)ft.atime.tv_sec,
7780 (unsigned int)ft.mtime.tv_sec,
7781 (unsigned int)ft.create_time.tv_sec
7784 END_PROFILE(SMBsetattrE);
7789 /* Back from the dead for OS/2..... JRA. */
7791 /****************************************************************************
7792 Reply to a SMBwritebmpx (write block multiplex primary) request.
7793 Always reply with an error, if someone has a platform really needs this,
7794 please contact vl@samba.org
7795 ****************************************************************************/
7797 void reply_writebmpx(struct smb_request *req)
7799 START_PROFILE(SMBwriteBmpx);
7800 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7801 END_PROFILE(SMBwriteBmpx);
7805 /****************************************************************************
7806 Reply to a SMBwritebs (write block multiplex secondary) request.
7807 Always reply with an error, if someone has a platform really needs this,
7808 please contact vl@samba.org
7809 ****************************************************************************/
7811 void reply_writebs(struct smb_request *req)
7813 START_PROFILE(SMBwriteBs);
7814 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7815 END_PROFILE(SMBwriteBs);
7819 /****************************************************************************
7820 Reply to a SMBgetattrE.
7821 ****************************************************************************/
7823 void reply_getattrE(struct smb_request *req)
7825 connection_struct *conn = req->conn;
7828 struct timespec create_ts;
7830 START_PROFILE(SMBgetattrE);
7833 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7834 END_PROFILE(SMBgetattrE);
7838 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7840 if(!fsp || (fsp->conn != conn)) {
7841 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7842 END_PROFILE(SMBgetattrE);
7846 /* Do an fstat on this file */
7848 reply_nterror(req, map_nt_error_from_unix(errno));
7849 END_PROFILE(SMBgetattrE);
7853 mode = dos_mode(conn, fsp->fsp_name);
7856 * Convert the times into dos times. Set create
7857 * date to be last modify date as UNIX doesn't save
7861 reply_outbuf(req, 11, 0);
7863 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7864 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7865 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7866 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7867 /* Should we check pending modtime here ? JRA */
7868 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7869 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7872 SIVAL(req->outbuf, smb_vwv6, 0);
7873 SIVAL(req->outbuf, smb_vwv8, 0);
7875 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7876 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
7877 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7879 SSVAL(req->outbuf,smb_vwv10, mode);
7881 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7883 END_PROFILE(SMBgetattrE);