dnsp: Parse TXT records
[Samba/gebeck_regimport.git] / source3 / smbd / reply.c
blobc84c077d581b968ab9f35987c9c70b351934cad5
1 /*
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
27 #include "includes.h"
28 #include "printing.h"
29 #include "smbd/globals.h"
30 #include "fake_file.h"
31 #include "../librpc/gen_ndr/cli_spoolss.h"
32 #include "rpc_client/cli_spoolss.h"
33 #include "rpc_client/init_spoolss.h"
34 #include "rpc_server/rpc_ncacn_np.h"
36 /****************************************************************************
37 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
38 path or anything including wildcards.
39 We're assuming here that '/' is not the second byte in any multibyte char
40 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
41 set.
42 ****************************************************************************/
44 /* Custom version for processing POSIX paths. */
45 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
47 static NTSTATUS check_path_syntax_internal(char *path,
48 bool posix_path,
49 bool *p_last_component_contains_wcard)
51 char *d = path;
52 const char *s = path;
53 NTSTATUS ret = NT_STATUS_OK;
54 bool start_of_name_component = True;
55 bool stream_started = false;
57 *p_last_component_contains_wcard = False;
59 while (*s) {
60 if (stream_started) {
61 switch (*s) {
62 case '/':
63 case '\\':
64 return NT_STATUS_OBJECT_NAME_INVALID;
65 case ':':
66 if (s[1] == '\0') {
67 return NT_STATUS_OBJECT_NAME_INVALID;
69 if (strchr_m(&s[1], ':')) {
70 return NT_STATUS_OBJECT_NAME_INVALID;
72 break;
76 if ((*s == ':') && !posix_path && !stream_started) {
77 if (*p_last_component_contains_wcard) {
78 return NT_STATUS_OBJECT_NAME_INVALID;
80 /* Stream names allow more characters than file names.
81 We're overloading posix_path here to allow a wider
82 range of characters. If stream_started is true this
83 is still a Windows path even if posix_path is true.
84 JRA.
86 stream_started = true;
87 start_of_name_component = false;
88 posix_path = true;
90 if (s[1] == '\0') {
91 return NT_STATUS_OBJECT_NAME_INVALID;
95 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
97 * Safe to assume is not the second part of a mb char
98 * as this is handled below.
100 /* Eat multiple '/' or '\\' */
101 while (IS_PATH_SEP(*s,posix_path)) {
102 s++;
104 if ((d != path) && (*s != '\0')) {
105 /* We only care about non-leading or trailing '/' or '\\' */
106 *d++ = '/';
109 start_of_name_component = True;
110 /* New component. */
111 *p_last_component_contains_wcard = False;
112 continue;
115 if (start_of_name_component) {
116 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
117 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
120 * No mb char starts with '.' so we're safe checking the directory separator here.
123 /* If we just added a '/' - delete it */
124 if ((d > path) && (*(d-1) == '/')) {
125 *(d-1) = '\0';
126 d--;
129 /* Are we at the start ? Can't go back further if so. */
130 if (d <= path) {
131 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
132 break;
134 /* Go back one level... */
135 /* We know this is safe as '/' cannot be part of a mb sequence. */
136 /* NOTE - if this assumption is invalid we are not in good shape... */
137 /* Decrement d first as d points to the *next* char to write into. */
138 for (d--; d > path; d--) {
139 if (*d == '/')
140 break;
142 s += 2; /* Else go past the .. */
143 /* We're still at the start of a name component, just the previous one. */
144 continue;
146 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
147 if (posix_path) {
148 /* Eat the '.' */
149 s++;
150 continue;
156 if (!(*s & 0x80)) {
157 if (!posix_path) {
158 if (*s <= 0x1f || *s == '|') {
159 return NT_STATUS_OBJECT_NAME_INVALID;
161 switch (*s) {
162 case '*':
163 case '?':
164 case '<':
165 case '>':
166 case '"':
167 *p_last_component_contains_wcard = True;
168 break;
169 default:
170 break;
173 *d++ = *s++;
174 } else {
175 size_t siz;
176 /* Get the size of the next MB character. */
177 next_codepoint(s,&siz);
178 switch(siz) {
179 case 5:
180 *d++ = *s++;
181 /*fall through*/
182 case 4:
183 *d++ = *s++;
184 /*fall through*/
185 case 3:
186 *d++ = *s++;
187 /*fall through*/
188 case 2:
189 *d++ = *s++;
190 /*fall through*/
191 case 1:
192 *d++ = *s++;
193 break;
194 default:
195 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
196 *d = '\0';
197 return NT_STATUS_INVALID_PARAMETER;
200 start_of_name_component = False;
203 *d = '\0';
205 return ret;
208 /****************************************************************************
209 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
210 No wildcards allowed.
211 ****************************************************************************/
213 NTSTATUS check_path_syntax(char *path)
215 bool ignore;
216 return check_path_syntax_internal(path, False, &ignore);
219 /****************************************************************************
220 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
221 Wildcards allowed - p_contains_wcard returns true if the last component contained
222 a wildcard.
223 ****************************************************************************/
225 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
227 return check_path_syntax_internal(path, False, p_contains_wcard);
230 /****************************************************************************
231 Check the path for a POSIX client.
232 We're assuming here that '/' is not the second byte in any multibyte char
233 set (a safe assumption).
234 ****************************************************************************/
236 NTSTATUS check_path_syntax_posix(char *path)
238 bool ignore;
239 return check_path_syntax_internal(path, True, &ignore);
242 /****************************************************************************
243 Pull a string and check the path allowing a wilcard - provide for error return.
244 ****************************************************************************/
246 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
247 const char *base_ptr,
248 uint16 smb_flags2,
249 char **pp_dest,
250 const char *src,
251 size_t src_len,
252 int flags,
253 NTSTATUS *err,
254 bool *contains_wcard)
256 size_t ret;
258 *pp_dest = NULL;
260 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
261 src_len, flags);
263 if (!*pp_dest) {
264 *err = NT_STATUS_INVALID_PARAMETER;
265 return ret;
268 *contains_wcard = False;
270 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
272 * For a DFS path the function parse_dfs_path()
273 * will do the path processing, just make a copy.
275 *err = NT_STATUS_OK;
276 return ret;
279 if (lp_posix_pathnames()) {
280 *err = check_path_syntax_posix(*pp_dest);
281 } else {
282 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
285 return ret;
288 /****************************************************************************
289 Pull a string and check the path - provide for error return.
290 ****************************************************************************/
292 size_t srvstr_get_path(TALLOC_CTX *ctx,
293 const char *base_ptr,
294 uint16 smb_flags2,
295 char **pp_dest,
296 const char *src,
297 size_t src_len,
298 int flags,
299 NTSTATUS *err)
301 bool ignore;
302 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
303 src_len, flags, err, &ignore);
306 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
307 char **pp_dest, const char *src, int flags,
308 NTSTATUS *err, bool *contains_wcard)
310 return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
311 pp_dest, src, smbreq_bufrem(req, src),
312 flags, err, contains_wcard);
315 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
316 char **pp_dest, const char *src, int flags,
317 NTSTATUS *err)
319 bool ignore;
320 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
321 flags, err, &ignore);
324 /****************************************************************************
325 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
326 ****************************************************************************/
328 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
329 files_struct *fsp)
331 if ((fsp == NULL) || (conn == NULL)) {
332 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
333 return False;
335 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
336 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
337 return False;
339 return True;
342 /****************************************************************************
343 Check if we have a correct fsp pointing to a file.
344 ****************************************************************************/
346 bool check_fsp(connection_struct *conn, struct smb_request *req,
347 files_struct *fsp)
349 if (!check_fsp_open(conn, req, fsp)) {
350 return False;
352 if (fsp->is_directory) {
353 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
354 return False;
356 if (fsp->fh->fd == -1) {
357 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
358 return False;
360 fsp->num_smb_operations++;
361 return True;
364 /****************************************************************************
365 Check if we have a correct fsp pointing to a quota fake file. Replacement for
366 the CHECK_NTQUOTA_HANDLE_OK macro.
367 ****************************************************************************/
369 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
370 files_struct *fsp)
372 if (!check_fsp_open(conn, req, fsp)) {
373 return false;
376 if (fsp->is_directory) {
377 return false;
380 if (fsp->fake_file_handle == NULL) {
381 return false;
384 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
385 return false;
388 if (fsp->fake_file_handle->private_data == NULL) {
389 return false;
392 return true;
395 static bool netbios_session_retarget(struct smbd_server_connection *sconn,
396 const char *name, int name_type)
398 char *trim_name;
399 char *trim_name_type;
400 const char *retarget_parm;
401 char *retarget;
402 char *p;
403 int retarget_type = 0x20;
404 int retarget_port = 139;
405 struct sockaddr_storage retarget_addr;
406 struct sockaddr_in *in_addr;
407 bool ret = false;
408 uint8_t outbuf[10];
410 if (get_socket_port(sconn->sock) != 139) {
411 return false;
414 trim_name = talloc_strdup(talloc_tos(), name);
415 if (trim_name == NULL) {
416 goto fail;
418 trim_char(trim_name, ' ', ' ');
420 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
421 name_type);
422 if (trim_name_type == NULL) {
423 goto fail;
426 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
427 trim_name_type, NULL);
428 if (retarget_parm == NULL) {
429 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
430 trim_name, NULL);
432 if (retarget_parm == NULL) {
433 goto fail;
436 retarget = talloc_strdup(trim_name, retarget_parm);
437 if (retarget == NULL) {
438 goto fail;
441 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
443 p = strchr(retarget, ':');
444 if (p != NULL) {
445 *p++ = '\0';
446 retarget_port = atoi(p);
449 p = strchr_m(retarget, '#');
450 if (p != NULL) {
451 *p++ = '\0';
452 sscanf(p, "%x", &retarget_type);
455 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
456 if (!ret) {
457 DEBUG(10, ("could not resolve %s\n", retarget));
458 goto fail;
461 if (retarget_addr.ss_family != AF_INET) {
462 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
463 goto fail;
466 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
468 _smb_setlen(outbuf, 6);
469 SCVAL(outbuf, 0, 0x84);
470 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
471 *(uint16_t *)(outbuf+8) = htons(retarget_port);
473 if (!srv_send_smb(sconn, (char *)outbuf, false, 0, false,
474 NULL)) {
475 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
476 "failed.");
479 ret = true;
480 fail:
481 TALLOC_FREE(trim_name);
482 return ret;
485 /****************************************************************************
486 Reply to a (netbios-level) special message.
487 ****************************************************************************/
489 void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inbuf_size)
491 int msg_type = CVAL(inbuf,0);
492 int msg_flags = CVAL(inbuf,1);
494 * We only really use 4 bytes of the outbuf, but for the smb_setlen
495 * calculation & friends (srv_send_smb uses that) we need the full smb
496 * header.
498 char outbuf[smb_size];
500 memset(outbuf, '\0', sizeof(outbuf));
502 smb_setlen(outbuf,0);
504 switch (msg_type) {
505 case 0x81: /* session request */
507 /* inbuf_size is guarenteed to be at least 4. */
508 fstring name1,name2;
509 int name_type1, name_type2;
510 int name_len1, name_len2;
512 *name1 = *name2 = 0;
514 if (sconn->nbt.got_session) {
515 exit_server_cleanly("multiple session request not permitted");
518 SCVAL(outbuf,0,0x82);
519 SCVAL(outbuf,3,0);
521 /* inbuf_size is guaranteed to be at least 4. */
522 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
523 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
524 DEBUG(0,("Invalid name length in session request\n"));
525 break;
527 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
528 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
529 DEBUG(0,("Invalid name length in session request\n"));
530 break;
533 name_type1 = name_extract((unsigned char *)inbuf,
534 inbuf_size,(unsigned int)4,name1);
535 name_type2 = name_extract((unsigned char *)inbuf,
536 inbuf_size,(unsigned int)(4 + name_len1),name2);
538 if (name_type1 == -1 || name_type2 == -1) {
539 DEBUG(0,("Invalid name type in session request\n"));
540 break;
543 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
544 name1, name_type1, name2, name_type2));
546 if (netbios_session_retarget(sconn, name1, name_type1)) {
547 exit_server_cleanly("retargeted client");
551 * Windows NT/2k uses "*SMBSERVER" and XP uses
552 * "*SMBSERV" arrggg!!!
554 if (strequal(name1, "*SMBSERVER ")
555 || strequal(name1, "*SMBSERV ")) {
556 fstrcpy(name1, sconn->client_id.addr);
559 set_local_machine_name(name1, True);
560 set_remote_machine_name(name2, True);
562 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
563 get_local_machine_name(), get_remote_machine_name(),
564 name_type2));
566 if (name_type2 == 'R') {
567 /* We are being asked for a pathworks session ---
568 no thanks! */
569 SCVAL(outbuf, 0,0x83);
570 break;
573 /* only add the client's machine name to the list
574 of possibly valid usernames if we are operating
575 in share mode security */
576 if (lp_security() == SEC_SHARE) {
577 add_session_user(sconn, get_remote_machine_name());
580 reload_services(sconn->msg_ctx, sconn->sock, True);
581 reopen_logs();
583 sconn->nbt.got_session = true;
584 break;
587 case 0x89: /* session keepalive request
588 (some old clients produce this?) */
589 SCVAL(outbuf,0,SMBkeepalive);
590 SCVAL(outbuf,3,0);
591 break;
593 case 0x82: /* positive session response */
594 case 0x83: /* negative session response */
595 case 0x84: /* retarget session response */
596 DEBUG(0,("Unexpected session response\n"));
597 break;
599 case SMBkeepalive: /* session keepalive */
600 default:
601 return;
604 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
605 msg_type, msg_flags));
607 srv_send_smb(sconn, outbuf, false, 0, false, NULL);
608 return;
611 /****************************************************************************
612 Reply to a tcon.
613 conn POINTER CAN BE NULL HERE !
614 ****************************************************************************/
616 void reply_tcon(struct smb_request *req)
618 connection_struct *conn = req->conn;
619 const char *service;
620 char *service_buf = NULL;
621 char *password = NULL;
622 char *dev = NULL;
623 int pwlen=0;
624 NTSTATUS nt_status;
625 const char *p;
626 DATA_BLOB password_blob;
627 TALLOC_CTX *ctx = talloc_tos();
628 struct smbd_server_connection *sconn = req->sconn;
630 START_PROFILE(SMBtcon);
632 if (req->buflen < 4) {
633 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
634 END_PROFILE(SMBtcon);
635 return;
638 p = (const char *)req->buf + 1;
639 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
640 p += 1;
641 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
642 p += pwlen+1;
643 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
644 p += 1;
646 if (service_buf == NULL || password == NULL || dev == NULL) {
647 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
648 END_PROFILE(SMBtcon);
649 return;
651 p = strrchr_m(service_buf,'\\');
652 if (p) {
653 service = p+1;
654 } else {
655 service = service_buf;
658 password_blob = data_blob(password, pwlen+1);
660 conn = make_connection(sconn,service,password_blob,dev,
661 req->vuid,&nt_status);
662 req->conn = conn;
664 data_blob_clear_free(&password_blob);
666 if (!conn) {
667 reply_nterror(req, nt_status);
668 END_PROFILE(SMBtcon);
669 return;
672 reply_outbuf(req, 2, 0);
673 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
674 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
675 SSVAL(req->outbuf,smb_tid,conn->cnum);
677 DEBUG(3,("tcon service=%s cnum=%d\n",
678 service, conn->cnum));
680 END_PROFILE(SMBtcon);
681 return;
684 /****************************************************************************
685 Reply to a tcon and X.
686 conn POINTER CAN BE NULL HERE !
687 ****************************************************************************/
689 void reply_tcon_and_X(struct smb_request *req)
691 connection_struct *conn = req->conn;
692 const char *service = NULL;
693 DATA_BLOB password;
694 TALLOC_CTX *ctx = talloc_tos();
695 /* what the cleint thinks the device is */
696 char *client_devicetype = NULL;
697 /* what the server tells the client the share represents */
698 const char *server_devicetype;
699 NTSTATUS nt_status;
700 int passlen;
701 char *path = NULL;
702 const char *p, *q;
703 uint16 tcon_flags;
704 struct smbd_server_connection *sconn = req->sconn;
706 START_PROFILE(SMBtconX);
708 if (req->wct < 4) {
709 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
710 END_PROFILE(SMBtconX);
711 return;
714 passlen = SVAL(req->vwv+3, 0);
715 tcon_flags = SVAL(req->vwv+2, 0);
717 /* we might have to close an old one */
718 if ((tcon_flags & 0x1) && conn) {
719 close_cnum(conn,req->vuid);
720 req->conn = NULL;
721 conn = NULL;
724 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
725 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
726 END_PROFILE(SMBtconX);
727 return;
730 if (sconn->smb1.negprot.encrypted_passwords) {
731 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
732 if (lp_security() == SEC_SHARE) {
734 * Security = share always has a pad byte
735 * after the password.
737 p = (const char *)req->buf + passlen + 1;
738 } else {
739 p = (const char *)req->buf + passlen;
741 } else {
742 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
743 /* Ensure correct termination */
744 password.data[passlen]=0;
745 p = (const char *)req->buf + passlen + 1;
748 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
750 if (path == NULL) {
751 data_blob_clear_free(&password);
752 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
753 END_PROFILE(SMBtconX);
754 return;
758 * the service name can be either: \\server\share
759 * or share directly like on the DELL PowerVault 705
761 if (*path=='\\') {
762 q = strchr_m(path+2,'\\');
763 if (!q) {
764 data_blob_clear_free(&password);
765 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
766 END_PROFILE(SMBtconX);
767 return;
769 service = q+1;
770 } else {
771 service = path;
774 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
775 &client_devicetype, p,
776 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
778 if (client_devicetype == NULL) {
779 data_blob_clear_free(&password);
780 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
781 END_PROFILE(SMBtconX);
782 return;
785 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
787 conn = make_connection(sconn, service, password, client_devicetype,
788 req->vuid, &nt_status);
789 req->conn =conn;
791 data_blob_clear_free(&password);
793 if (!conn) {
794 reply_nterror(req, nt_status);
795 END_PROFILE(SMBtconX);
796 return;
799 if ( IS_IPC(conn) )
800 server_devicetype = "IPC";
801 else if ( IS_PRINT(conn) )
802 server_devicetype = "LPT1:";
803 else
804 server_devicetype = "A:";
806 if (get_Protocol() < PROTOCOL_NT1) {
807 reply_outbuf(req, 2, 0);
808 if (message_push_string(&req->outbuf, server_devicetype,
809 STR_TERMINATE|STR_ASCII) == -1) {
810 reply_nterror(req, NT_STATUS_NO_MEMORY);
811 END_PROFILE(SMBtconX);
812 return;
814 } else {
815 /* NT sets the fstype of IPC$ to the null string */
816 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
818 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
819 /* Return permissions. */
820 uint32 perm1 = 0;
821 uint32 perm2 = 0;
823 reply_outbuf(req, 7, 0);
825 if (IS_IPC(conn)) {
826 perm1 = FILE_ALL_ACCESS;
827 perm2 = FILE_ALL_ACCESS;
828 } else {
829 perm1 = CAN_WRITE(conn) ?
830 SHARE_ALL_ACCESS :
831 SHARE_READ_ONLY;
834 SIVAL(req->outbuf, smb_vwv3, perm1);
835 SIVAL(req->outbuf, smb_vwv5, perm2);
836 } else {
837 reply_outbuf(req, 3, 0);
840 if ((message_push_string(&req->outbuf, server_devicetype,
841 STR_TERMINATE|STR_ASCII) == -1)
842 || (message_push_string(&req->outbuf, fstype,
843 STR_TERMINATE) == -1)) {
844 reply_nterror(req, NT_STATUS_NO_MEMORY);
845 END_PROFILE(SMBtconX);
846 return;
849 /* what does setting this bit do? It is set by NT4 and
850 may affect the ability to autorun mounted cdroms */
851 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
852 (lp_csc_policy(SNUM(conn)) << 2));
854 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
855 DEBUG(2,("Serving %s as a Dfs root\n",
856 lp_servicename(SNUM(conn)) ));
857 SSVAL(req->outbuf, smb_vwv2,
858 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
863 DEBUG(3,("tconX service=%s \n",
864 service));
866 /* set the incoming and outgoing tid to the just created one */
867 SSVAL(req->inbuf,smb_tid,conn->cnum);
868 SSVAL(req->outbuf,smb_tid,conn->cnum);
870 END_PROFILE(SMBtconX);
872 req->tid = conn->cnum;
873 chain_reply(req);
874 return;
877 /****************************************************************************
878 Reply to an unknown type.
879 ****************************************************************************/
881 void reply_unknown_new(struct smb_request *req, uint8 type)
883 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
884 smb_fn_name(type), type, type));
885 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
886 return;
889 /****************************************************************************
890 Reply to an ioctl.
891 conn POINTER CAN BE NULL HERE !
892 ****************************************************************************/
894 void reply_ioctl(struct smb_request *req)
896 connection_struct *conn = req->conn;
897 uint16 device;
898 uint16 function;
899 uint32 ioctl_code;
900 int replysize;
901 char *p;
903 START_PROFILE(SMBioctl);
905 if (req->wct < 3) {
906 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
907 END_PROFILE(SMBioctl);
908 return;
911 device = SVAL(req->vwv+1, 0);
912 function = SVAL(req->vwv+2, 0);
913 ioctl_code = (device << 16) + function;
915 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
917 switch (ioctl_code) {
918 case IOCTL_QUERY_JOB_INFO:
919 replysize = 32;
920 break;
921 default:
922 reply_force_doserror(req, ERRSRV, ERRnosupport);
923 END_PROFILE(SMBioctl);
924 return;
927 reply_outbuf(req, 8, replysize+1);
928 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
929 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
930 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
931 p = smb_buf(req->outbuf);
932 memset(p, '\0', replysize+1); /* valgrind-safe. */
933 p += 1; /* Allow for alignment */
935 switch (ioctl_code) {
936 case IOCTL_QUERY_JOB_INFO:
938 files_struct *fsp = file_fsp(
939 req, SVAL(req->vwv+0, 0));
940 if (!fsp) {
941 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
942 END_PROFILE(SMBioctl);
943 return;
945 /* Job number */
946 if (fsp->print_file) {
947 SSVAL(p, 0, fsp->print_file->rap_jobid);
948 } else {
949 SSVAL(p, 0, 0);
951 srvstr_push((char *)req->outbuf, req->flags2, p+2,
952 global_myname(), 15,
953 STR_TERMINATE|STR_ASCII);
954 if (conn) {
955 srvstr_push((char *)req->outbuf, req->flags2,
956 p+18, lp_servicename(SNUM(conn)),
957 13, STR_TERMINATE|STR_ASCII);
958 } else {
959 memset(p+18, 0, 13);
961 break;
965 END_PROFILE(SMBioctl);
966 return;
969 /****************************************************************************
970 Strange checkpath NTSTATUS mapping.
971 ****************************************************************************/
973 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
975 /* Strange DOS error code semantics only for checkpath... */
976 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
977 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
978 /* We need to map to ERRbadpath */
979 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
982 return status;
985 /****************************************************************************
986 Reply to a checkpath.
987 ****************************************************************************/
989 void reply_checkpath(struct smb_request *req)
991 connection_struct *conn = req->conn;
992 struct smb_filename *smb_fname = NULL;
993 char *name = NULL;
994 NTSTATUS status;
995 TALLOC_CTX *ctx = talloc_tos();
997 START_PROFILE(SMBcheckpath);
999 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1000 STR_TERMINATE, &status);
1002 if (!NT_STATUS_IS_OK(status)) {
1003 status = map_checkpath_error(req->flags2, status);
1004 reply_nterror(req, status);
1005 END_PROFILE(SMBcheckpath);
1006 return;
1009 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1011 status = filename_convert(ctx,
1012 conn,
1013 req->flags2 & FLAGS2_DFS_PATHNAMES,
1014 name,
1016 NULL,
1017 &smb_fname);
1019 if (!NT_STATUS_IS_OK(status)) {
1020 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1021 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1022 ERRSRV, ERRbadpath);
1023 END_PROFILE(SMBcheckpath);
1024 return;
1026 goto path_err;
1029 if (!VALID_STAT(smb_fname->st) &&
1030 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1031 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1032 smb_fname_str_dbg(smb_fname), strerror(errno)));
1033 status = map_nt_error_from_unix(errno);
1034 goto path_err;
1037 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1038 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1039 ERRDOS, ERRbadpath);
1040 goto out;
1043 reply_outbuf(req, 0, 0);
1045 path_err:
1046 /* We special case this - as when a Windows machine
1047 is parsing a path is steps through the components
1048 one at a time - if a component fails it expects
1049 ERRbadpath, not ERRbadfile.
1051 status = map_checkpath_error(req->flags2, status);
1052 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1054 * Windows returns different error codes if
1055 * the parent directory is valid but not the
1056 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1057 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1058 * if the path is invalid.
1060 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1061 ERRDOS, ERRbadpath);
1062 goto out;
1065 reply_nterror(req, status);
1067 out:
1068 TALLOC_FREE(smb_fname);
1069 END_PROFILE(SMBcheckpath);
1070 return;
1073 /****************************************************************************
1074 Reply to a getatr.
1075 ****************************************************************************/
1077 void reply_getatr(struct smb_request *req)
1079 connection_struct *conn = req->conn;
1080 struct smb_filename *smb_fname = NULL;
1081 char *fname = NULL;
1082 int mode=0;
1083 SMB_OFF_T size=0;
1084 time_t mtime=0;
1085 const char *p;
1086 NTSTATUS status;
1087 TALLOC_CTX *ctx = talloc_tos();
1088 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1090 START_PROFILE(SMBgetatr);
1092 p = (const char *)req->buf + 1;
1093 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1094 if (!NT_STATUS_IS_OK(status)) {
1095 reply_nterror(req, status);
1096 goto out;
1099 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1100 under WfWg - weird! */
1101 if (*fname == '\0') {
1102 mode = aHIDDEN | aDIR;
1103 if (!CAN_WRITE(conn)) {
1104 mode |= aRONLY;
1106 size = 0;
1107 mtime = 0;
1108 } else {
1109 status = filename_convert(ctx,
1110 conn,
1111 req->flags2 & FLAGS2_DFS_PATHNAMES,
1112 fname,
1114 NULL,
1115 &smb_fname);
1116 if (!NT_STATUS_IS_OK(status)) {
1117 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1118 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1119 ERRSRV, ERRbadpath);
1120 goto out;
1122 reply_nterror(req, status);
1123 goto out;
1125 if (!VALID_STAT(smb_fname->st) &&
1126 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1127 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1128 smb_fname_str_dbg(smb_fname),
1129 strerror(errno)));
1130 reply_nterror(req, map_nt_error_from_unix(errno));
1131 goto out;
1134 mode = dos_mode(conn, smb_fname);
1135 size = smb_fname->st.st_ex_size;
1137 if (ask_sharemode) {
1138 struct timespec write_time_ts;
1139 struct file_id fileid;
1141 ZERO_STRUCT(write_time_ts);
1142 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1143 get_file_infos(fileid, NULL, &write_time_ts);
1144 if (!null_timespec(write_time_ts)) {
1145 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1149 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1150 if (mode & aDIR) {
1151 size = 0;
1155 reply_outbuf(req, 10, 0);
1157 SSVAL(req->outbuf,smb_vwv0,mode);
1158 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1159 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1160 } else {
1161 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1163 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1165 if (get_Protocol() >= PROTOCOL_NT1) {
1166 SSVAL(req->outbuf, smb_flg2,
1167 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1170 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1171 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1173 out:
1174 TALLOC_FREE(smb_fname);
1175 TALLOC_FREE(fname);
1176 END_PROFILE(SMBgetatr);
1177 return;
1180 /****************************************************************************
1181 Reply to a setatr.
1182 ****************************************************************************/
1184 void reply_setatr(struct smb_request *req)
1186 struct smb_file_time ft;
1187 connection_struct *conn = req->conn;
1188 struct smb_filename *smb_fname = NULL;
1189 char *fname = NULL;
1190 int mode;
1191 time_t mtime;
1192 const char *p;
1193 NTSTATUS status;
1194 TALLOC_CTX *ctx = talloc_tos();
1196 START_PROFILE(SMBsetatr);
1198 ZERO_STRUCT(ft);
1200 if (req->wct < 2) {
1201 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1202 goto out;
1205 p = (const char *)req->buf + 1;
1206 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1207 if (!NT_STATUS_IS_OK(status)) {
1208 reply_nterror(req, status);
1209 goto out;
1212 status = filename_convert(ctx,
1213 conn,
1214 req->flags2 & FLAGS2_DFS_PATHNAMES,
1215 fname,
1217 NULL,
1218 &smb_fname);
1219 if (!NT_STATUS_IS_OK(status)) {
1220 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1221 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1222 ERRSRV, ERRbadpath);
1223 goto out;
1225 reply_nterror(req, status);
1226 goto out;
1229 if (smb_fname->base_name[0] == '.' &&
1230 smb_fname->base_name[1] == '\0') {
1232 * Not sure here is the right place to catch this
1233 * condition. Might be moved to somewhere else later -- vl
1235 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1236 goto out;
1239 mode = SVAL(req->vwv+0, 0);
1240 mtime = srv_make_unix_date3(req->vwv+1);
1242 ft.mtime = convert_time_t_to_timespec(mtime);
1243 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1244 if (!NT_STATUS_IS_OK(status)) {
1245 reply_nterror(req, status);
1246 goto out;
1249 if (mode != FILE_ATTRIBUTE_NORMAL) {
1250 if (VALID_STAT_OF_DIR(smb_fname->st))
1251 mode |= aDIR;
1252 else
1253 mode &= ~aDIR;
1255 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1256 false) != 0) {
1257 reply_nterror(req, map_nt_error_from_unix(errno));
1258 goto out;
1262 reply_outbuf(req, 0, 0);
1264 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1265 mode));
1266 out:
1267 TALLOC_FREE(smb_fname);
1268 END_PROFILE(SMBsetatr);
1269 return;
1272 /****************************************************************************
1273 Reply to a dskattr.
1274 ****************************************************************************/
1276 void reply_dskattr(struct smb_request *req)
1278 connection_struct *conn = req->conn;
1279 uint64_t dfree,dsize,bsize;
1280 START_PROFILE(SMBdskattr);
1282 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1283 reply_nterror(req, map_nt_error_from_unix(errno));
1284 END_PROFILE(SMBdskattr);
1285 return;
1288 reply_outbuf(req, 5, 0);
1290 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1291 double total_space, free_space;
1292 /* we need to scale this to a number that DOS6 can handle. We
1293 use floating point so we can handle large drives on systems
1294 that don't have 64 bit integers
1296 we end up displaying a maximum of 2G to DOS systems
1298 total_space = dsize * (double)bsize;
1299 free_space = dfree * (double)bsize;
1301 dsize = (uint64_t)((total_space+63*512) / (64*512));
1302 dfree = (uint64_t)((free_space+63*512) / (64*512));
1304 if (dsize > 0xFFFF) dsize = 0xFFFF;
1305 if (dfree > 0xFFFF) dfree = 0xFFFF;
1307 SSVAL(req->outbuf,smb_vwv0,dsize);
1308 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1309 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1310 SSVAL(req->outbuf,smb_vwv3,dfree);
1311 } else {
1312 SSVAL(req->outbuf,smb_vwv0,dsize);
1313 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1314 SSVAL(req->outbuf,smb_vwv2,512);
1315 SSVAL(req->outbuf,smb_vwv3,dfree);
1318 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1320 END_PROFILE(SMBdskattr);
1321 return;
1325 * Utility function to split the filename from the directory.
1327 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1328 char **fname_dir_out,
1329 char **fname_mask_out)
1331 const char *p = NULL;
1332 char *fname_dir = NULL;
1333 char *fname_mask = NULL;
1335 p = strrchr_m(fname_in, '/');
1336 if (!p) {
1337 fname_dir = talloc_strdup(ctx, ".");
1338 fname_mask = talloc_strdup(ctx, fname_in);
1339 } else {
1340 fname_dir = talloc_strndup(ctx, fname_in,
1341 PTR_DIFF(p, fname_in));
1342 fname_mask = talloc_strdup(ctx, p+1);
1345 if (!fname_dir || !fname_mask) {
1346 TALLOC_FREE(fname_dir);
1347 TALLOC_FREE(fname_mask);
1348 return NT_STATUS_NO_MEMORY;
1351 *fname_dir_out = fname_dir;
1352 *fname_mask_out = fname_mask;
1353 return NT_STATUS_OK;
1356 /****************************************************************************
1357 Reply to a search.
1358 Can be called from SMBsearch, SMBffirst or SMBfunique.
1359 ****************************************************************************/
1361 void reply_search(struct smb_request *req)
1363 connection_struct *conn = req->conn;
1364 char *path = NULL;
1365 const char *mask = NULL;
1366 char *directory = NULL;
1367 struct smb_filename *smb_fname = NULL;
1368 char *fname = NULL;
1369 SMB_OFF_T size;
1370 uint32 mode;
1371 struct timespec date;
1372 uint32 dirtype;
1373 unsigned int numentries = 0;
1374 unsigned int maxentries = 0;
1375 bool finished = False;
1376 const char *p;
1377 int status_len;
1378 char status[21];
1379 int dptr_num= -1;
1380 bool check_descend = False;
1381 bool expect_close = False;
1382 NTSTATUS nt_status;
1383 bool mask_contains_wcard = False;
1384 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1385 TALLOC_CTX *ctx = talloc_tos();
1386 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1387 struct dptr_struct *dirptr = NULL;
1388 struct smbd_server_connection *sconn = req->sconn;
1390 START_PROFILE(SMBsearch);
1392 if (req->wct < 2) {
1393 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1394 goto out;
1397 if (lp_posix_pathnames()) {
1398 reply_unknown_new(req, req->cmd);
1399 goto out;
1402 /* If we were called as SMBffirst then we must expect close. */
1403 if(req->cmd == SMBffirst) {
1404 expect_close = True;
1407 reply_outbuf(req, 1, 3);
1408 maxentries = SVAL(req->vwv+0, 0);
1409 dirtype = SVAL(req->vwv+1, 0);
1410 p = (const char *)req->buf + 1;
1411 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1412 &nt_status, &mask_contains_wcard);
1413 if (!NT_STATUS_IS_OK(nt_status)) {
1414 reply_nterror(req, nt_status);
1415 goto out;
1418 p++;
1419 status_len = SVAL(p, 0);
1420 p += 2;
1422 /* dirtype &= ~aDIR; */
1424 if (status_len == 0) {
1425 nt_status = filename_convert(ctx, conn,
1426 req->flags2 & FLAGS2_DFS_PATHNAMES,
1427 path,
1428 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1429 &mask_contains_wcard,
1430 &smb_fname);
1431 if (!NT_STATUS_IS_OK(nt_status)) {
1432 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1433 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1434 ERRSRV, ERRbadpath);
1435 goto out;
1437 reply_nterror(req, nt_status);
1438 goto out;
1441 directory = smb_fname->base_name;
1443 p = strrchr_m(directory,'/');
1444 if ((p != NULL) && (*directory != '/')) {
1445 mask = p + 1;
1446 directory = talloc_strndup(ctx, directory,
1447 PTR_DIFF(p, directory));
1448 } else {
1449 mask = directory;
1450 directory = talloc_strdup(ctx,".");
1453 if (!directory) {
1454 reply_nterror(req, NT_STATUS_NO_MEMORY);
1455 goto out;
1458 memset((char *)status,'\0',21);
1459 SCVAL(status,0,(dirtype & 0x1F));
1461 nt_status = dptr_create(conn,
1462 directory,
1463 True,
1464 expect_close,
1465 req->smbpid,
1466 mask,
1467 mask_contains_wcard,
1468 dirtype,
1469 &dirptr);
1470 if (!NT_STATUS_IS_OK(nt_status)) {
1471 reply_nterror(req, nt_status);
1472 goto out;
1474 dptr_num = dptr_dnum(dirptr);
1475 } else {
1476 int status_dirtype;
1477 const char *dirpath;
1479 memcpy(status,p,21);
1480 status_dirtype = CVAL(status,0) & 0x1F;
1481 if (status_dirtype != (dirtype & 0x1F)) {
1482 dirtype = status_dirtype;
1485 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1486 if (!dirptr) {
1487 goto SearchEmpty;
1489 dirpath = dptr_path(sconn, dptr_num);
1490 directory = talloc_strdup(ctx, dirpath);
1491 if (!directory) {
1492 reply_nterror(req, NT_STATUS_NO_MEMORY);
1493 goto out;
1496 mask = dptr_wcard(sconn, dptr_num);
1497 if (!mask) {
1498 goto SearchEmpty;
1501 * For a 'continue' search we have no string. So
1502 * check from the initial saved string.
1504 mask_contains_wcard = ms_has_wild(mask);
1505 dirtype = dptr_attr(sconn, dptr_num);
1508 DEBUG(4,("dptr_num is %d\n",dptr_num));
1510 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1511 dptr_init_search_op(dirptr);
1513 if ((dirtype&0x1F) == aVOLID) {
1514 char buf[DIR_STRUCT_SIZE];
1515 memcpy(buf,status,21);
1516 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1517 0,aVOLID,0,!allow_long_path_components)) {
1518 reply_nterror(req, NT_STATUS_NO_MEMORY);
1519 goto out;
1521 dptr_fill(sconn, buf+12,dptr_num);
1522 if (dptr_zero(buf+12) && (status_len==0)) {
1523 numentries = 1;
1524 } else {
1525 numentries = 0;
1527 if (message_push_blob(&req->outbuf,
1528 data_blob_const(buf, sizeof(buf)))
1529 == -1) {
1530 reply_nterror(req, NT_STATUS_NO_MEMORY);
1531 goto out;
1533 } else {
1534 unsigned int i;
1535 maxentries = MIN(
1536 maxentries,
1537 ((BUFFER_SIZE -
1538 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1539 /DIR_STRUCT_SIZE));
1541 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1542 directory,lp_dontdescend(SNUM(conn))));
1543 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1544 check_descend = True;
1547 for (i=numentries;(i<maxentries) && !finished;i++) {
1548 finished = !get_dir_entry(ctx,
1549 dirptr,
1550 mask,
1551 dirtype,
1552 &fname,
1553 &size,
1554 &mode,
1555 &date,
1556 check_descend,
1557 ask_sharemode);
1558 if (!finished) {
1559 char buf[DIR_STRUCT_SIZE];
1560 memcpy(buf,status,21);
1561 if (!make_dir_struct(ctx,
1562 buf,
1563 mask,
1564 fname,
1565 size,
1566 mode,
1567 convert_timespec_to_time_t(date),
1568 !allow_long_path_components)) {
1569 reply_nterror(req, NT_STATUS_NO_MEMORY);
1570 goto out;
1572 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1573 break;
1575 if (message_push_blob(&req->outbuf,
1576 data_blob_const(buf, sizeof(buf)))
1577 == -1) {
1578 reply_nterror(req, NT_STATUS_NO_MEMORY);
1579 goto out;
1581 numentries++;
1586 SearchEmpty:
1588 /* If we were called as SMBffirst with smb_search_id == NULL
1589 and no entries were found then return error and close dirptr
1590 (X/Open spec) */
1592 if (numentries == 0) {
1593 dptr_close(sconn, &dptr_num);
1594 } else if(expect_close && status_len == 0) {
1595 /* Close the dptr - we know it's gone */
1596 dptr_close(sconn, &dptr_num);
1599 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1600 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1601 dptr_close(sconn, &dptr_num);
1604 if ((numentries == 0) && !mask_contains_wcard) {
1605 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1606 goto out;
1609 SSVAL(req->outbuf,smb_vwv0,numentries);
1610 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1611 SCVAL(smb_buf(req->outbuf),0,5);
1612 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1614 /* The replies here are never long name. */
1615 SSVAL(req->outbuf, smb_flg2,
1616 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1617 if (!allow_long_path_components) {
1618 SSVAL(req->outbuf, smb_flg2,
1619 SVAL(req->outbuf, smb_flg2)
1620 & (~FLAGS2_LONG_PATH_COMPONENTS));
1623 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1624 SSVAL(req->outbuf, smb_flg2,
1625 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1627 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1628 smb_fn_name(req->cmd),
1629 mask,
1630 directory,
1631 dirtype,
1632 numentries,
1633 maxentries ));
1634 out:
1635 TALLOC_FREE(directory);
1636 TALLOC_FREE(smb_fname);
1637 END_PROFILE(SMBsearch);
1638 return;
1641 /****************************************************************************
1642 Reply to a fclose (stop directory search).
1643 ****************************************************************************/
1645 void reply_fclose(struct smb_request *req)
1647 int status_len;
1648 char status[21];
1649 int dptr_num= -2;
1650 const char *p;
1651 char *path = NULL;
1652 NTSTATUS err;
1653 bool path_contains_wcard = False;
1654 TALLOC_CTX *ctx = talloc_tos();
1655 struct smbd_server_connection *sconn = req->sconn;
1657 START_PROFILE(SMBfclose);
1659 if (lp_posix_pathnames()) {
1660 reply_unknown_new(req, req->cmd);
1661 END_PROFILE(SMBfclose);
1662 return;
1665 p = (const char *)req->buf + 1;
1666 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1667 &err, &path_contains_wcard);
1668 if (!NT_STATUS_IS_OK(err)) {
1669 reply_nterror(req, err);
1670 END_PROFILE(SMBfclose);
1671 return;
1673 p++;
1674 status_len = SVAL(p,0);
1675 p += 2;
1677 if (status_len == 0) {
1678 reply_force_doserror(req, ERRSRV, ERRsrverror);
1679 END_PROFILE(SMBfclose);
1680 return;
1683 memcpy(status,p,21);
1685 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1686 /* Close the dptr - we know it's gone */
1687 dptr_close(sconn, &dptr_num);
1690 reply_outbuf(req, 1, 0);
1691 SSVAL(req->outbuf,smb_vwv0,0);
1693 DEBUG(3,("search close\n"));
1695 END_PROFILE(SMBfclose);
1696 return;
1699 /****************************************************************************
1700 Reply to an open.
1701 ****************************************************************************/
1703 void reply_open(struct smb_request *req)
1705 connection_struct *conn = req->conn;
1706 struct smb_filename *smb_fname = NULL;
1707 char *fname = NULL;
1708 uint32 fattr=0;
1709 SMB_OFF_T size = 0;
1710 time_t mtime=0;
1711 int info;
1712 files_struct *fsp;
1713 int oplock_request;
1714 int deny_mode;
1715 uint32 dos_attr;
1716 uint32 access_mask;
1717 uint32 share_mode;
1718 uint32 create_disposition;
1719 uint32 create_options = 0;
1720 uint32_t private_flags = 0;
1721 NTSTATUS status;
1722 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1723 TALLOC_CTX *ctx = talloc_tos();
1725 START_PROFILE(SMBopen);
1727 if (req->wct < 2) {
1728 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1729 goto out;
1732 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1733 deny_mode = SVAL(req->vwv+0, 0);
1734 dos_attr = SVAL(req->vwv+1, 0);
1736 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1737 STR_TERMINATE, &status);
1738 if (!NT_STATUS_IS_OK(status)) {
1739 reply_nterror(req, status);
1740 goto out;
1743 status = filename_convert(ctx,
1744 conn,
1745 req->flags2 & FLAGS2_DFS_PATHNAMES,
1746 fname,
1748 NULL,
1749 &smb_fname);
1750 if (!NT_STATUS_IS_OK(status)) {
1751 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1752 reply_botherror(req,
1753 NT_STATUS_PATH_NOT_COVERED,
1754 ERRSRV, ERRbadpath);
1755 goto out;
1757 reply_nterror(req, status);
1758 goto out;
1761 if (!map_open_params_to_ntcreate(smb_fname, deny_mode,
1762 OPENX_FILE_EXISTS_OPEN, &access_mask,
1763 &share_mode, &create_disposition,
1764 &create_options, &private_flags)) {
1765 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1766 goto out;
1769 status = SMB_VFS_CREATE_FILE(
1770 conn, /* conn */
1771 req, /* req */
1772 0, /* root_dir_fid */
1773 smb_fname, /* fname */
1774 access_mask, /* access_mask */
1775 share_mode, /* share_access */
1776 create_disposition, /* create_disposition*/
1777 create_options, /* create_options */
1778 dos_attr, /* file_attributes */
1779 oplock_request, /* oplock_request */
1780 0, /* allocation_size */
1781 private_flags,
1782 NULL, /* sd */
1783 NULL, /* ea_list */
1784 &fsp, /* result */
1785 &info); /* pinfo */
1787 if (!NT_STATUS_IS_OK(status)) {
1788 if (open_was_deferred(req->mid)) {
1789 /* We have re-scheduled this call. */
1790 goto out;
1792 reply_openerror(req, status);
1793 goto out;
1796 size = smb_fname->st.st_ex_size;
1797 fattr = dos_mode(conn, smb_fname);
1799 /* Deal with other possible opens having a modified
1800 write time. JRA. */
1801 if (ask_sharemode) {
1802 struct timespec write_time_ts;
1804 ZERO_STRUCT(write_time_ts);
1805 get_file_infos(fsp->file_id, NULL, &write_time_ts);
1806 if (!null_timespec(write_time_ts)) {
1807 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1811 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1813 if (fattr & aDIR) {
1814 DEBUG(3,("attempt to open a directory %s\n",
1815 fsp_str_dbg(fsp)));
1816 close_file(req, fsp, ERROR_CLOSE);
1817 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1818 ERRDOS, ERRnoaccess);
1819 goto out;
1822 reply_outbuf(req, 7, 0);
1823 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1824 SSVAL(req->outbuf,smb_vwv1,fattr);
1825 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1826 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1827 } else {
1828 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1830 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1831 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1833 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1834 SCVAL(req->outbuf,smb_flg,
1835 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1838 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1839 SCVAL(req->outbuf,smb_flg,
1840 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1842 out:
1843 TALLOC_FREE(smb_fname);
1844 END_PROFILE(SMBopen);
1845 return;
1848 /****************************************************************************
1849 Reply to an open and X.
1850 ****************************************************************************/
1852 void reply_open_and_X(struct smb_request *req)
1854 connection_struct *conn = req->conn;
1855 struct smb_filename *smb_fname = NULL;
1856 char *fname = NULL;
1857 uint16 open_flags;
1858 int deny_mode;
1859 uint32 smb_attr;
1860 /* Breakout the oplock request bits so we can set the
1861 reply bits separately. */
1862 int ex_oplock_request;
1863 int core_oplock_request;
1864 int oplock_request;
1865 #if 0
1866 int smb_sattr = SVAL(req->vwv+4, 0);
1867 uint32 smb_time = make_unix_date3(req->vwv+6);
1868 #endif
1869 int smb_ofun;
1870 uint32 fattr=0;
1871 int mtime=0;
1872 int smb_action = 0;
1873 files_struct *fsp;
1874 NTSTATUS status;
1875 uint64_t allocation_size;
1876 ssize_t retval = -1;
1877 uint32 access_mask;
1878 uint32 share_mode;
1879 uint32 create_disposition;
1880 uint32 create_options = 0;
1881 uint32_t private_flags = 0;
1882 TALLOC_CTX *ctx = talloc_tos();
1884 START_PROFILE(SMBopenX);
1886 if (req->wct < 15) {
1887 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1888 goto out;
1891 open_flags = SVAL(req->vwv+2, 0);
1892 deny_mode = SVAL(req->vwv+3, 0);
1893 smb_attr = SVAL(req->vwv+5, 0);
1894 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1895 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1896 oplock_request = ex_oplock_request | core_oplock_request;
1897 smb_ofun = SVAL(req->vwv+8, 0);
1898 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1900 /* If it's an IPC, pass off the pipe handler. */
1901 if (IS_IPC(conn)) {
1902 if (lp_nt_pipe_support()) {
1903 reply_open_pipe_and_X(conn, req);
1904 } else {
1905 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1907 goto out;
1910 /* XXXX we need to handle passed times, sattr and flags */
1911 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1912 STR_TERMINATE, &status);
1913 if (!NT_STATUS_IS_OK(status)) {
1914 reply_nterror(req, status);
1915 goto out;
1918 status = filename_convert(ctx,
1919 conn,
1920 req->flags2 & FLAGS2_DFS_PATHNAMES,
1921 fname,
1923 NULL,
1924 &smb_fname);
1925 if (!NT_STATUS_IS_OK(status)) {
1926 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1927 reply_botherror(req,
1928 NT_STATUS_PATH_NOT_COVERED,
1929 ERRSRV, ERRbadpath);
1930 goto out;
1932 reply_nterror(req, status);
1933 goto out;
1936 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, smb_ofun,
1937 &access_mask, &share_mode,
1938 &create_disposition,
1939 &create_options,
1940 &private_flags)) {
1941 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1942 goto out;
1945 status = SMB_VFS_CREATE_FILE(
1946 conn, /* conn */
1947 req, /* req */
1948 0, /* root_dir_fid */
1949 smb_fname, /* fname */
1950 access_mask, /* access_mask */
1951 share_mode, /* share_access */
1952 create_disposition, /* create_disposition*/
1953 create_options, /* create_options */
1954 smb_attr, /* file_attributes */
1955 oplock_request, /* oplock_request */
1956 0, /* allocation_size */
1957 private_flags,
1958 NULL, /* sd */
1959 NULL, /* ea_list */
1960 &fsp, /* result */
1961 &smb_action); /* pinfo */
1963 if (!NT_STATUS_IS_OK(status)) {
1964 if (open_was_deferred(req->mid)) {
1965 /* We have re-scheduled this call. */
1966 goto out;
1968 reply_openerror(req, status);
1969 goto out;
1972 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1973 if the file is truncated or created. */
1974 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1975 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1976 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1977 close_file(req, fsp, ERROR_CLOSE);
1978 reply_nterror(req, NT_STATUS_DISK_FULL);
1979 goto out;
1981 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1982 if (retval < 0) {
1983 close_file(req, fsp, ERROR_CLOSE);
1984 reply_nterror(req, NT_STATUS_DISK_FULL);
1985 goto out;
1987 smb_fname->st.st_ex_size =
1988 SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
1991 fattr = dos_mode(conn, smb_fname);
1992 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1993 if (fattr & aDIR) {
1994 close_file(req, fsp, ERROR_CLOSE);
1995 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1996 goto out;
1999 /* If the caller set the extended oplock request bit
2000 and we granted one (by whatever means) - set the
2001 correct bit for extended oplock reply.
2004 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2005 smb_action |= EXTENDED_OPLOCK_GRANTED;
2008 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2009 smb_action |= EXTENDED_OPLOCK_GRANTED;
2012 /* If the caller set the core oplock request bit
2013 and we granted one (by whatever means) - set the
2014 correct bit for core oplock reply.
2017 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2018 reply_outbuf(req, 19, 0);
2019 } else {
2020 reply_outbuf(req, 15, 0);
2023 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2024 SCVAL(req->outbuf, smb_flg,
2025 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2028 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2029 SCVAL(req->outbuf, smb_flg,
2030 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2033 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2034 SSVAL(req->outbuf,smb_vwv3,fattr);
2035 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2036 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2037 } else {
2038 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2040 SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size);
2041 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2042 SSVAL(req->outbuf,smb_vwv11,smb_action);
2044 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2045 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2048 chain_reply(req);
2049 out:
2050 TALLOC_FREE(smb_fname);
2051 END_PROFILE(SMBopenX);
2052 return;
2055 /****************************************************************************
2056 Reply to a SMBulogoffX.
2057 ****************************************************************************/
2059 void reply_ulogoffX(struct smb_request *req)
2061 struct smbd_server_connection *sconn = req->sconn;
2062 user_struct *vuser;
2064 START_PROFILE(SMBulogoffX);
2066 vuser = get_valid_user_struct(sconn, req->vuid);
2068 if(vuser == NULL) {
2069 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2070 req->vuid));
2073 /* in user level security we are supposed to close any files
2074 open by this user */
2075 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2076 file_close_user(sconn, req->vuid);
2079 invalidate_vuid(sconn, req->vuid);
2081 reply_outbuf(req, 2, 0);
2083 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2085 END_PROFILE(SMBulogoffX);
2086 req->vuid = UID_FIELD_INVALID;
2087 chain_reply(req);
2090 /****************************************************************************
2091 Reply to a mknew or a create.
2092 ****************************************************************************/
2094 void reply_mknew(struct smb_request *req)
2096 connection_struct *conn = req->conn;
2097 struct smb_filename *smb_fname = NULL;
2098 char *fname = NULL;
2099 uint32 fattr = 0;
2100 struct smb_file_time ft;
2101 files_struct *fsp;
2102 int oplock_request = 0;
2103 NTSTATUS status;
2104 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2105 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2106 uint32 create_disposition;
2107 uint32 create_options = 0;
2108 TALLOC_CTX *ctx = talloc_tos();
2110 START_PROFILE(SMBcreate);
2111 ZERO_STRUCT(ft);
2113 if (req->wct < 3) {
2114 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2115 goto out;
2118 fattr = SVAL(req->vwv+0, 0);
2119 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2121 /* mtime. */
2122 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2124 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2125 STR_TERMINATE, &status);
2126 if (!NT_STATUS_IS_OK(status)) {
2127 reply_nterror(req, status);
2128 goto out;
2131 status = filename_convert(ctx,
2132 conn,
2133 req->flags2 & FLAGS2_DFS_PATHNAMES,
2134 fname,
2136 NULL,
2137 &smb_fname);
2138 if (!NT_STATUS_IS_OK(status)) {
2139 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2140 reply_botherror(req,
2141 NT_STATUS_PATH_NOT_COVERED,
2142 ERRSRV, ERRbadpath);
2143 goto out;
2145 reply_nterror(req, status);
2146 goto out;
2149 if (fattr & aVOLID) {
2150 DEBUG(0,("Attempt to create file (%s) with volid set - "
2151 "please report this\n",
2152 smb_fname_str_dbg(smb_fname)));
2155 if(req->cmd == SMBmknew) {
2156 /* We should fail if file exists. */
2157 create_disposition = FILE_CREATE;
2158 } else {
2159 /* Create if file doesn't exist, truncate if it does. */
2160 create_disposition = FILE_OVERWRITE_IF;
2163 status = SMB_VFS_CREATE_FILE(
2164 conn, /* conn */
2165 req, /* req */
2166 0, /* root_dir_fid */
2167 smb_fname, /* fname */
2168 access_mask, /* access_mask */
2169 share_mode, /* share_access */
2170 create_disposition, /* create_disposition*/
2171 create_options, /* create_options */
2172 fattr, /* file_attributes */
2173 oplock_request, /* oplock_request */
2174 0, /* allocation_size */
2175 0, /* private_flags */
2176 NULL, /* sd */
2177 NULL, /* ea_list */
2178 &fsp, /* result */
2179 NULL); /* pinfo */
2181 if (!NT_STATUS_IS_OK(status)) {
2182 if (open_was_deferred(req->mid)) {
2183 /* We have re-scheduled this call. */
2184 goto out;
2186 reply_openerror(req, status);
2187 goto out;
2190 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2191 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2192 if (!NT_STATUS_IS_OK(status)) {
2193 END_PROFILE(SMBcreate);
2194 goto out;
2197 reply_outbuf(req, 1, 0);
2198 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2200 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2201 SCVAL(req->outbuf,smb_flg,
2202 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2205 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2206 SCVAL(req->outbuf,smb_flg,
2207 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2210 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2211 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2212 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2213 (unsigned int)fattr));
2215 out:
2216 TALLOC_FREE(smb_fname);
2217 END_PROFILE(SMBcreate);
2218 return;
2221 /****************************************************************************
2222 Reply to a create temporary file.
2223 ****************************************************************************/
2225 void reply_ctemp(struct smb_request *req)
2227 connection_struct *conn = req->conn;
2228 struct smb_filename *smb_fname = NULL;
2229 char *fname = NULL;
2230 uint32 fattr;
2231 files_struct *fsp;
2232 int oplock_request;
2233 int tmpfd;
2234 char *s;
2235 NTSTATUS status;
2236 TALLOC_CTX *ctx = talloc_tos();
2238 START_PROFILE(SMBctemp);
2240 if (req->wct < 3) {
2241 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2242 goto out;
2245 fattr = SVAL(req->vwv+0, 0);
2246 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2248 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2249 STR_TERMINATE, &status);
2250 if (!NT_STATUS_IS_OK(status)) {
2251 reply_nterror(req, status);
2252 goto out;
2254 if (*fname) {
2255 fname = talloc_asprintf(ctx,
2256 "%s/TMXXXXXX",
2257 fname);
2258 } else {
2259 fname = talloc_strdup(ctx, "TMXXXXXX");
2262 if (!fname) {
2263 reply_nterror(req, NT_STATUS_NO_MEMORY);
2264 goto out;
2267 status = filename_convert(ctx, conn,
2268 req->flags2 & FLAGS2_DFS_PATHNAMES,
2269 fname,
2271 NULL,
2272 &smb_fname);
2273 if (!NT_STATUS_IS_OK(status)) {
2274 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2275 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2276 ERRSRV, ERRbadpath);
2277 goto out;
2279 reply_nterror(req, status);
2280 goto out;
2283 tmpfd = mkstemp(smb_fname->base_name);
2284 if (tmpfd == -1) {
2285 reply_nterror(req, map_nt_error_from_unix(errno));
2286 goto out;
2289 SMB_VFS_STAT(conn, smb_fname);
2291 /* We should fail if file does not exist. */
2292 status = SMB_VFS_CREATE_FILE(
2293 conn, /* conn */
2294 req, /* req */
2295 0, /* root_dir_fid */
2296 smb_fname, /* fname */
2297 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2298 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2299 FILE_OPEN, /* create_disposition*/
2300 0, /* create_options */
2301 fattr, /* file_attributes */
2302 oplock_request, /* oplock_request */
2303 0, /* allocation_size */
2304 0, /* private_flags */
2305 NULL, /* sd */
2306 NULL, /* ea_list */
2307 &fsp, /* result */
2308 NULL); /* pinfo */
2310 /* close fd from mkstemp() */
2311 close(tmpfd);
2313 if (!NT_STATUS_IS_OK(status)) {
2314 if (open_was_deferred(req->mid)) {
2315 /* We have re-scheduled this call. */
2316 goto out;
2318 reply_openerror(req, status);
2319 goto out;
2322 reply_outbuf(req, 1, 0);
2323 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2325 /* the returned filename is relative to the directory */
2326 s = strrchr_m(fsp->fsp_name->base_name, '/');
2327 if (!s) {
2328 s = fsp->fsp_name->base_name;
2329 } else {
2330 s++;
2333 #if 0
2334 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2335 thing in the byte section. JRA */
2336 SSVALS(p, 0, -1); /* what is this? not in spec */
2337 #endif
2338 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2339 == -1) {
2340 reply_nterror(req, NT_STATUS_NO_MEMORY);
2341 goto out;
2344 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2345 SCVAL(req->outbuf, smb_flg,
2346 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2349 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2350 SCVAL(req->outbuf, smb_flg,
2351 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2354 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2355 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2356 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2357 out:
2358 TALLOC_FREE(smb_fname);
2359 END_PROFILE(SMBctemp);
2360 return;
2363 /*******************************************************************
2364 Check if a user is allowed to rename a file.
2365 ********************************************************************/
2367 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2368 uint16 dirtype)
2370 uint32 fmode;
2372 if (!CAN_WRITE(conn)) {
2373 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2376 fmode = dos_mode(conn, fsp->fsp_name);
2377 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2378 return NT_STATUS_NO_SUCH_FILE;
2381 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2382 if (fsp->posix_open) {
2383 return NT_STATUS_OK;
2386 /* If no pathnames are open below this
2387 directory, allow the rename. */
2389 if (file_find_subpath(fsp)) {
2390 return NT_STATUS_ACCESS_DENIED;
2392 return NT_STATUS_OK;
2395 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2396 return NT_STATUS_OK;
2399 return NT_STATUS_ACCESS_DENIED;
2402 /*******************************************************************
2403 * unlink a file with all relevant access checks
2404 *******************************************************************/
2406 static NTSTATUS do_unlink(connection_struct *conn,
2407 struct smb_request *req,
2408 struct smb_filename *smb_fname,
2409 uint32 dirtype)
2411 uint32 fattr;
2412 files_struct *fsp;
2413 uint32 dirtype_orig = dirtype;
2414 NTSTATUS status;
2415 int ret;
2416 bool posix_paths = lp_posix_pathnames();
2418 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2419 smb_fname_str_dbg(smb_fname),
2420 dirtype));
2422 if (!CAN_WRITE(conn)) {
2423 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2426 if (posix_paths) {
2427 ret = SMB_VFS_LSTAT(conn, smb_fname);
2428 } else {
2429 ret = SMB_VFS_STAT(conn, smb_fname);
2431 if (ret != 0) {
2432 return map_nt_error_from_unix(errno);
2435 fattr = dos_mode(conn, smb_fname);
2437 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2438 dirtype = aDIR|aARCH|aRONLY;
2441 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2442 if (!dirtype) {
2443 return NT_STATUS_NO_SUCH_FILE;
2446 if (!dir_check_ftype(conn, fattr, dirtype)) {
2447 if (fattr & aDIR) {
2448 return NT_STATUS_FILE_IS_A_DIRECTORY;
2450 return NT_STATUS_NO_SUCH_FILE;
2453 if (dirtype_orig & 0x8000) {
2454 /* These will never be set for POSIX. */
2455 return NT_STATUS_NO_SUCH_FILE;
2458 #if 0
2459 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2460 return NT_STATUS_FILE_IS_A_DIRECTORY;
2463 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2464 return NT_STATUS_NO_SUCH_FILE;
2467 if (dirtype & 0xFF00) {
2468 /* These will never be set for POSIX. */
2469 return NT_STATUS_NO_SUCH_FILE;
2472 dirtype &= 0xFF;
2473 if (!dirtype) {
2474 return NT_STATUS_NO_SUCH_FILE;
2477 /* Can't delete a directory. */
2478 if (fattr & aDIR) {
2479 return NT_STATUS_FILE_IS_A_DIRECTORY;
2481 #endif
2483 #if 0 /* JRATEST */
2484 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2485 return NT_STATUS_OBJECT_NAME_INVALID;
2486 #endif /* JRATEST */
2488 /* On open checks the open itself will check the share mode, so
2489 don't do it here as we'll get it wrong. */
2491 status = SMB_VFS_CREATE_FILE
2492 (conn, /* conn */
2493 req, /* req */
2494 0, /* root_dir_fid */
2495 smb_fname, /* fname */
2496 DELETE_ACCESS, /* access_mask */
2497 FILE_SHARE_NONE, /* share_access */
2498 FILE_OPEN, /* create_disposition*/
2499 FILE_NON_DIRECTORY_FILE, /* create_options */
2500 /* file_attributes */
2501 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2502 FILE_ATTRIBUTE_NORMAL,
2503 0, /* oplock_request */
2504 0, /* allocation_size */
2505 0, /* private_flags */
2506 NULL, /* sd */
2507 NULL, /* ea_list */
2508 &fsp, /* result */
2509 NULL); /* pinfo */
2511 if (!NT_STATUS_IS_OK(status)) {
2512 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2513 nt_errstr(status)));
2514 return status;
2517 status = can_set_delete_on_close(fsp, fattr);
2518 if (!NT_STATUS_IS_OK(status)) {
2519 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2520 "(%s)\n",
2521 smb_fname_str_dbg(smb_fname),
2522 nt_errstr(status)));
2523 close_file(req, fsp, NORMAL_CLOSE);
2524 return status;
2527 /* The set is across all open files on this dev/inode pair. */
2528 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2529 close_file(req, fsp, NORMAL_CLOSE);
2530 return NT_STATUS_ACCESS_DENIED;
2533 return close_file(req, fsp, NORMAL_CLOSE);
2536 /****************************************************************************
2537 The guts of the unlink command, split out so it may be called by the NT SMB
2538 code.
2539 ****************************************************************************/
2541 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2542 uint32 dirtype, struct smb_filename *smb_fname,
2543 bool has_wild)
2545 char *fname_dir = NULL;
2546 char *fname_mask = NULL;
2547 int count=0;
2548 NTSTATUS status = NT_STATUS_OK;
2549 TALLOC_CTX *ctx = talloc_tos();
2551 /* Split up the directory from the filename/mask. */
2552 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2553 &fname_dir, &fname_mask);
2554 if (!NT_STATUS_IS_OK(status)) {
2555 goto out;
2559 * We should only check the mangled cache
2560 * here if unix_convert failed. This means
2561 * that the path in 'mask' doesn't exist
2562 * on the file system and so we need to look
2563 * for a possible mangle. This patch from
2564 * Tine Smukavec <valentin.smukavec@hermes.si>.
2567 if (!VALID_STAT(smb_fname->st) &&
2568 mangle_is_mangled(fname_mask, conn->params)) {
2569 char *new_mask = NULL;
2570 mangle_lookup_name_from_8_3(ctx, fname_mask,
2571 &new_mask, conn->params);
2572 if (new_mask) {
2573 TALLOC_FREE(fname_mask);
2574 fname_mask = new_mask;
2578 if (!has_wild) {
2581 * Only one file needs to be unlinked. Append the mask back
2582 * onto the directory.
2584 TALLOC_FREE(smb_fname->base_name);
2585 smb_fname->base_name = talloc_asprintf(smb_fname,
2586 "%s/%s",
2587 fname_dir,
2588 fname_mask);
2589 if (!smb_fname->base_name) {
2590 status = NT_STATUS_NO_MEMORY;
2591 goto out;
2593 if (dirtype == 0) {
2594 dirtype = FILE_ATTRIBUTE_NORMAL;
2597 status = check_name(conn, smb_fname->base_name);
2598 if (!NT_STATUS_IS_OK(status)) {
2599 goto out;
2602 status = do_unlink(conn, req, smb_fname, dirtype);
2603 if (!NT_STATUS_IS_OK(status)) {
2604 goto out;
2607 count++;
2608 } else {
2609 struct smb_Dir *dir_hnd = NULL;
2610 long offset = 0;
2611 const char *dname = NULL;
2612 char *talloced = NULL;
2614 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2615 status = NT_STATUS_OBJECT_NAME_INVALID;
2616 goto out;
2619 if (strequal(fname_mask,"????????.???")) {
2620 TALLOC_FREE(fname_mask);
2621 fname_mask = talloc_strdup(ctx, "*");
2622 if (!fname_mask) {
2623 status = NT_STATUS_NO_MEMORY;
2624 goto out;
2628 status = check_name(conn, fname_dir);
2629 if (!NT_STATUS_IS_OK(status)) {
2630 goto out;
2633 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2634 dirtype);
2635 if (dir_hnd == NULL) {
2636 status = map_nt_error_from_unix(errno);
2637 goto out;
2640 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2641 the pattern matches against the long name, otherwise the short name
2642 We don't implement this yet XXXX
2645 status = NT_STATUS_NO_SUCH_FILE;
2647 while ((dname = ReadDirName(dir_hnd, &offset,
2648 &smb_fname->st, &talloced))) {
2649 TALLOC_CTX *frame = talloc_stackframe();
2651 if (!is_visible_file(conn, fname_dir, dname,
2652 &smb_fname->st, true)) {
2653 TALLOC_FREE(frame);
2654 TALLOC_FREE(talloced);
2655 continue;
2658 /* Quick check for "." and ".." */
2659 if (ISDOT(dname) || ISDOTDOT(dname)) {
2660 TALLOC_FREE(frame);
2661 TALLOC_FREE(talloced);
2662 continue;
2665 if(!mask_match(dname, fname_mask,
2666 conn->case_sensitive)) {
2667 TALLOC_FREE(frame);
2668 TALLOC_FREE(talloced);
2669 continue;
2672 TALLOC_FREE(smb_fname->base_name);
2673 smb_fname->base_name =
2674 talloc_asprintf(smb_fname, "%s/%s",
2675 fname_dir, dname);
2677 if (!smb_fname->base_name) {
2678 TALLOC_FREE(dir_hnd);
2679 status = NT_STATUS_NO_MEMORY;
2680 TALLOC_FREE(frame);
2681 TALLOC_FREE(talloced);
2682 goto out;
2685 status = check_name(conn, smb_fname->base_name);
2686 if (!NT_STATUS_IS_OK(status)) {
2687 TALLOC_FREE(dir_hnd);
2688 TALLOC_FREE(frame);
2689 TALLOC_FREE(talloced);
2690 goto out;
2693 status = do_unlink(conn, req, smb_fname, dirtype);
2694 if (!NT_STATUS_IS_OK(status)) {
2695 TALLOC_FREE(frame);
2696 TALLOC_FREE(talloced);
2697 continue;
2700 count++;
2701 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2702 smb_fname->base_name));
2704 TALLOC_FREE(frame);
2705 TALLOC_FREE(talloced);
2707 TALLOC_FREE(dir_hnd);
2710 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2711 status = map_nt_error_from_unix(errno);
2714 out:
2715 TALLOC_FREE(fname_dir);
2716 TALLOC_FREE(fname_mask);
2717 return status;
2720 /****************************************************************************
2721 Reply to a unlink
2722 ****************************************************************************/
2724 void reply_unlink(struct smb_request *req)
2726 connection_struct *conn = req->conn;
2727 char *name = NULL;
2728 struct smb_filename *smb_fname = NULL;
2729 uint32 dirtype;
2730 NTSTATUS status;
2731 bool path_contains_wcard = False;
2732 TALLOC_CTX *ctx = talloc_tos();
2734 START_PROFILE(SMBunlink);
2736 if (req->wct < 1) {
2737 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2738 goto out;
2741 dirtype = SVAL(req->vwv+0, 0);
2743 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2744 STR_TERMINATE, &status,
2745 &path_contains_wcard);
2746 if (!NT_STATUS_IS_OK(status)) {
2747 reply_nterror(req, status);
2748 goto out;
2751 status = filename_convert(ctx, conn,
2752 req->flags2 & FLAGS2_DFS_PATHNAMES,
2753 name,
2754 UCF_COND_ALLOW_WCARD_LCOMP,
2755 &path_contains_wcard,
2756 &smb_fname);
2757 if (!NT_STATUS_IS_OK(status)) {
2758 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2759 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2760 ERRSRV, ERRbadpath);
2761 goto out;
2763 reply_nterror(req, status);
2764 goto out;
2767 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2769 status = unlink_internals(conn, req, dirtype, smb_fname,
2770 path_contains_wcard);
2771 if (!NT_STATUS_IS_OK(status)) {
2772 if (open_was_deferred(req->mid)) {
2773 /* We have re-scheduled this call. */
2774 goto out;
2776 reply_nterror(req, status);
2777 goto out;
2780 reply_outbuf(req, 0, 0);
2781 out:
2782 TALLOC_FREE(smb_fname);
2783 END_PROFILE(SMBunlink);
2784 return;
2787 /****************************************************************************
2788 Fail for readbraw.
2789 ****************************************************************************/
2791 static void fail_readraw(void)
2793 const char *errstr = talloc_asprintf(talloc_tos(),
2794 "FAIL ! reply_readbraw: socket write fail (%s)",
2795 strerror(errno));
2796 if (!errstr) {
2797 errstr = "";
2799 exit_server_cleanly(errstr);
2802 /****************************************************************************
2803 Fake (read/write) sendfile. Returns -1 on read or write fail.
2804 ****************************************************************************/
2806 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2807 size_t nread)
2809 size_t bufsize;
2810 size_t tosend = nread;
2811 char *buf;
2813 if (nread == 0) {
2814 return 0;
2817 bufsize = MIN(nread, 65536);
2819 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2820 return -1;
2823 while (tosend > 0) {
2824 ssize_t ret;
2825 size_t cur_read;
2827 if (tosend > bufsize) {
2828 cur_read = bufsize;
2829 } else {
2830 cur_read = tosend;
2832 ret = read_file(fsp,buf,startpos,cur_read);
2833 if (ret == -1) {
2834 SAFE_FREE(buf);
2835 return -1;
2838 /* If we had a short read, fill with zeros. */
2839 if (ret < cur_read) {
2840 memset(buf + ret, '\0', cur_read - ret);
2843 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
2844 != cur_read) {
2845 char addr[INET6_ADDRSTRLEN];
2847 * Try and give an error message saying what
2848 * client failed.
2850 DEBUG(0, ("write_data failed for client %s. "
2851 "Error %s\n",
2852 get_peer_addr(fsp->conn->sconn->sock, addr,
2853 sizeof(addr)),
2854 strerror(errno)));
2855 SAFE_FREE(buf);
2856 return -1;
2858 tosend -= cur_read;
2859 startpos += cur_read;
2862 SAFE_FREE(buf);
2863 return (ssize_t)nread;
2866 #if defined(WITH_SENDFILE)
2867 /****************************************************************************
2868 Deal with the case of sendfile reading less bytes from the file than
2869 requested. Fill with zeros (all we can do).
2870 ****************************************************************************/
2872 static void sendfile_short_send(files_struct *fsp,
2873 ssize_t nread,
2874 size_t headersize,
2875 size_t smb_maxcnt)
2877 #define SHORT_SEND_BUFSIZE 1024
2878 if (nread < headersize) {
2879 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2880 "header for file %s (%s). Terminating\n",
2881 fsp_str_dbg(fsp), strerror(errno)));
2882 exit_server_cleanly("sendfile_short_send failed");
2885 nread -= headersize;
2887 if (nread < smb_maxcnt) {
2888 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2889 if (!buf) {
2890 exit_server_cleanly("sendfile_short_send: "
2891 "malloc failed");
2894 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2895 "with zeros !\n", fsp_str_dbg(fsp)));
2897 while (nread < smb_maxcnt) {
2899 * We asked for the real file size and told sendfile
2900 * to not go beyond the end of the file. But it can
2901 * happen that in between our fstat call and the
2902 * sendfile call the file was truncated. This is very
2903 * bad because we have already announced the larger
2904 * number of bytes to the client.
2906 * The best we can do now is to send 0-bytes, just as
2907 * a read from a hole in a sparse file would do.
2909 * This should happen rarely enough that I don't care
2910 * about efficiency here :-)
2912 size_t to_write;
2914 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2915 if (write_data(fsp->conn->sconn->sock, buf, to_write)
2916 != to_write) {
2917 char addr[INET6_ADDRSTRLEN];
2919 * Try and give an error message saying what
2920 * client failed.
2922 DEBUG(0, ("write_data failed for client %s. "
2923 "Error %s\n",
2924 get_peer_addr(
2925 fsp->conn->sconn->sock, addr,
2926 sizeof(addr)),
2927 strerror(errno)));
2928 exit_server_cleanly("sendfile_short_send: "
2929 "write_data failed");
2931 nread += to_write;
2933 SAFE_FREE(buf);
2936 #endif /* defined WITH_SENDFILE */
2938 /****************************************************************************
2939 Return a readbraw error (4 bytes of zero).
2940 ****************************************************************************/
2942 static void reply_readbraw_error(struct smbd_server_connection *sconn)
2944 char header[4];
2946 SIVAL(header,0,0);
2948 smbd_lock_socket(sconn);
2949 if (write_data(sconn->sock,header,4) != 4) {
2950 char addr[INET6_ADDRSTRLEN];
2952 * Try and give an error message saying what
2953 * client failed.
2955 DEBUG(0, ("write_data failed for client %s. "
2956 "Error %s\n",
2957 get_peer_addr(sconn->sock, addr, sizeof(addr)),
2958 strerror(errno)));
2960 fail_readraw();
2962 smbd_unlock_socket(sconn);
2965 /****************************************************************************
2966 Use sendfile in readbraw.
2967 ****************************************************************************/
2969 static void send_file_readbraw(connection_struct *conn,
2970 struct smb_request *req,
2971 files_struct *fsp,
2972 SMB_OFF_T startpos,
2973 size_t nread,
2974 ssize_t mincount)
2976 struct smbd_server_connection *sconn = req->sconn;
2977 char *outbuf = NULL;
2978 ssize_t ret=0;
2980 #if defined(WITH_SENDFILE)
2982 * We can only use sendfile on a non-chained packet
2983 * but we can use on a non-oplocked file. tridge proved this
2984 * on a train in Germany :-). JRA.
2985 * reply_readbraw has already checked the length.
2988 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2989 (fsp->wcp == NULL) &&
2990 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
2991 ssize_t sendfile_read = -1;
2992 char header[4];
2993 DATA_BLOB header_blob;
2995 _smb_setlen(header,nread);
2996 header_blob = data_blob_const(header, 4);
2998 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
2999 &header_blob, startpos,
3000 nread);
3001 if (sendfile_read == -1) {
3002 /* Returning ENOSYS means no data at all was sent.
3003 * Do this as a normal read. */
3004 if (errno == ENOSYS) {
3005 goto normal_readbraw;
3009 * Special hack for broken Linux with no working sendfile. If we
3010 * return EINTR we sent the header but not the rest of the data.
3011 * Fake this up by doing read/write calls.
3013 if (errno == EINTR) {
3014 /* Ensure we don't do this again. */
3015 set_use_sendfile(SNUM(conn), False);
3016 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3018 if (fake_sendfile(fsp, startpos, nread) == -1) {
3019 DEBUG(0,("send_file_readbraw: "
3020 "fake_sendfile failed for "
3021 "file %s (%s).\n",
3022 fsp_str_dbg(fsp),
3023 strerror(errno)));
3024 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3026 return;
3029 DEBUG(0,("send_file_readbraw: sendfile failed for "
3030 "file %s (%s). Terminating\n",
3031 fsp_str_dbg(fsp), strerror(errno)));
3032 exit_server_cleanly("send_file_readbraw sendfile failed");
3033 } else if (sendfile_read == 0) {
3035 * Some sendfile implementations return 0 to indicate
3036 * that there was a short read, but nothing was
3037 * actually written to the socket. In this case,
3038 * fallback to the normal read path so the header gets
3039 * the correct byte count.
3041 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3042 "bytes falling back to the normal read: "
3043 "%s\n", fsp_str_dbg(fsp)));
3044 goto normal_readbraw;
3047 /* Deal with possible short send. */
3048 if (sendfile_read != 4+nread) {
3049 sendfile_short_send(fsp, sendfile_read, 4, nread);
3051 return;
3054 normal_readbraw:
3055 #endif
3057 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
3058 if (!outbuf) {
3059 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
3060 (unsigned)(nread+4)));
3061 reply_readbraw_error(sconn);
3062 return;
3065 if (nread > 0) {
3066 ret = read_file(fsp,outbuf+4,startpos,nread);
3067 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3068 if (ret < mincount)
3069 ret = 0;
3070 #else
3071 if (ret < nread)
3072 ret = 0;
3073 #endif
3076 _smb_setlen(outbuf,ret);
3077 if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
3078 char addr[INET6_ADDRSTRLEN];
3080 * Try and give an error message saying what
3081 * client failed.
3083 DEBUG(0, ("write_data failed for client %s. "
3084 "Error %s\n",
3085 get_peer_addr(fsp->conn->sconn->sock, addr,
3086 sizeof(addr)),
3087 strerror(errno)));
3089 fail_readraw();
3092 TALLOC_FREE(outbuf);
3095 /****************************************************************************
3096 Reply to a readbraw (core+ protocol).
3097 ****************************************************************************/
3099 void reply_readbraw(struct smb_request *req)
3101 connection_struct *conn = req->conn;
3102 struct smbd_server_connection *sconn = req->sconn;
3103 ssize_t maxcount,mincount;
3104 size_t nread = 0;
3105 SMB_OFF_T startpos;
3106 files_struct *fsp;
3107 struct lock_struct lock;
3108 SMB_OFF_T size = 0;
3110 START_PROFILE(SMBreadbraw);
3112 if (srv_is_signing_active(sconn) ||
3113 is_encrypted_packet(req->inbuf)) {
3114 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3115 "raw reads/writes are disallowed.");
3118 if (req->wct < 8) {
3119 reply_readbraw_error(sconn);
3120 END_PROFILE(SMBreadbraw);
3121 return;
3124 if (sconn->smb1.echo_handler.trusted_fde) {
3125 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3126 "'async smb echo handler = yes'\n"));
3127 reply_readbraw_error(sconn);
3128 END_PROFILE(SMBreadbraw);
3129 return;
3133 * Special check if an oplock break has been issued
3134 * and the readraw request croses on the wire, we must
3135 * return a zero length response here.
3138 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3141 * We have to do a check_fsp by hand here, as
3142 * we must always return 4 zero bytes on error,
3143 * not a NTSTATUS.
3146 if (!fsp || !conn || conn != fsp->conn ||
3147 req->vuid != fsp->vuid ||
3148 fsp->is_directory || fsp->fh->fd == -1) {
3150 * fsp could be NULL here so use the value from the packet. JRA.
3152 DEBUG(3,("reply_readbraw: fnum %d not valid "
3153 "- cache prime?\n",
3154 (int)SVAL(req->vwv+0, 0)));
3155 reply_readbraw_error(sconn);
3156 END_PROFILE(SMBreadbraw);
3157 return;
3160 /* Do a "by hand" version of CHECK_READ. */
3161 if (!(fsp->can_read ||
3162 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3163 (fsp->access_mask & FILE_EXECUTE)))) {
3164 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3165 (int)SVAL(req->vwv+0, 0)));
3166 reply_readbraw_error(sconn);
3167 END_PROFILE(SMBreadbraw);
3168 return;
3171 flush_write_cache(fsp, READRAW_FLUSH);
3173 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3174 if(req->wct == 10) {
3176 * This is a large offset (64 bit) read.
3178 #ifdef LARGE_SMB_OFF_T
3180 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3182 #else /* !LARGE_SMB_OFF_T */
3185 * Ensure we haven't been sent a >32 bit offset.
3188 if(IVAL(req->vwv+8, 0) != 0) {
3189 DEBUG(0,("reply_readbraw: large offset "
3190 "(%x << 32) used and we don't support "
3191 "64 bit offsets.\n",
3192 (unsigned int)IVAL(req->vwv+8, 0) ));
3193 reply_readbraw_error();
3194 END_PROFILE(SMBreadbraw);
3195 return;
3198 #endif /* LARGE_SMB_OFF_T */
3200 if(startpos < 0) {
3201 DEBUG(0,("reply_readbraw: negative 64 bit "
3202 "readraw offset (%.0f) !\n",
3203 (double)startpos ));
3204 reply_readbraw_error(sconn);
3205 END_PROFILE(SMBreadbraw);
3206 return;
3210 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3211 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3213 /* ensure we don't overrun the packet size */
3214 maxcount = MIN(65535,maxcount);
3216 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3217 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3218 &lock);
3220 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3221 reply_readbraw_error(sconn);
3222 END_PROFILE(SMBreadbraw);
3223 return;
3226 if (fsp_stat(fsp) == 0) {
3227 size = fsp->fsp_name->st.st_ex_size;
3230 if (startpos >= size) {
3231 nread = 0;
3232 } else {
3233 nread = MIN(maxcount,(size - startpos));
3236 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3237 if (nread < mincount)
3238 nread = 0;
3239 #endif
3241 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3242 "min=%lu nread=%lu\n",
3243 fsp->fnum, (double)startpos,
3244 (unsigned long)maxcount,
3245 (unsigned long)mincount,
3246 (unsigned long)nread ) );
3248 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3250 DEBUG(5,("reply_readbraw finished\n"));
3252 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3254 END_PROFILE(SMBreadbraw);
3255 return;
3258 #undef DBGC_CLASS
3259 #define DBGC_CLASS DBGC_LOCKING
3261 /****************************************************************************
3262 Reply to a lockread (core+ protocol).
3263 ****************************************************************************/
3265 void reply_lockread(struct smb_request *req)
3267 connection_struct *conn = req->conn;
3268 ssize_t nread = -1;
3269 char *data;
3270 SMB_OFF_T startpos;
3271 size_t numtoread;
3272 NTSTATUS status;
3273 files_struct *fsp;
3274 struct byte_range_lock *br_lck = NULL;
3275 char *p = NULL;
3276 struct smbd_server_connection *sconn = req->sconn;
3278 START_PROFILE(SMBlockread);
3280 if (req->wct < 5) {
3281 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3282 END_PROFILE(SMBlockread);
3283 return;
3286 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3288 if (!check_fsp(conn, req, fsp)) {
3289 END_PROFILE(SMBlockread);
3290 return;
3293 if (!CHECK_READ(fsp,req)) {
3294 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3295 END_PROFILE(SMBlockread);
3296 return;
3299 numtoread = SVAL(req->vwv+1, 0);
3300 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3302 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3304 reply_outbuf(req, 5, numtoread + 3);
3306 data = smb_buf(req->outbuf) + 3;
3309 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3310 * protocol request that predates the read/write lock concept.
3311 * Thus instead of asking for a read lock here we need to ask
3312 * for a write lock. JRA.
3313 * Note that the requested lock size is unaffected by max_recv.
3316 br_lck = do_lock(req->sconn->msg_ctx,
3317 fsp,
3318 (uint64_t)req->smbpid,
3319 (uint64_t)numtoread,
3320 (uint64_t)startpos,
3321 WRITE_LOCK,
3322 WINDOWS_LOCK,
3323 False, /* Non-blocking lock. */
3324 &status,
3325 NULL,
3326 NULL);
3327 TALLOC_FREE(br_lck);
3329 if (NT_STATUS_V(status)) {
3330 reply_nterror(req, status);
3331 END_PROFILE(SMBlockread);
3332 return;
3336 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3339 if (numtoread > sconn->smb1.negprot.max_recv) {
3340 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3341 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3342 (unsigned int)numtoread,
3343 (unsigned int)sconn->smb1.negprot.max_recv));
3344 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3346 nread = read_file(fsp,data,startpos,numtoread);
3348 if (nread < 0) {
3349 reply_nterror(req, map_nt_error_from_unix(errno));
3350 END_PROFILE(SMBlockread);
3351 return;
3354 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3356 SSVAL(req->outbuf,smb_vwv0,nread);
3357 SSVAL(req->outbuf,smb_vwv5,nread+3);
3358 p = smb_buf(req->outbuf);
3359 SCVAL(p,0,0); /* pad byte. */
3360 SSVAL(p,1,nread);
3362 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3363 fsp->fnum, (int)numtoread, (int)nread));
3365 END_PROFILE(SMBlockread);
3366 return;
3369 #undef DBGC_CLASS
3370 #define DBGC_CLASS DBGC_ALL
3372 /****************************************************************************
3373 Reply to a read.
3374 ****************************************************************************/
3376 void reply_read(struct smb_request *req)
3378 connection_struct *conn = req->conn;
3379 size_t numtoread;
3380 ssize_t nread = 0;
3381 char *data;
3382 SMB_OFF_T startpos;
3383 int outsize = 0;
3384 files_struct *fsp;
3385 struct lock_struct lock;
3386 struct smbd_server_connection *sconn = req->sconn;
3388 START_PROFILE(SMBread);
3390 if (req->wct < 3) {
3391 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3392 END_PROFILE(SMBread);
3393 return;
3396 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3398 if (!check_fsp(conn, req, fsp)) {
3399 END_PROFILE(SMBread);
3400 return;
3403 if (!CHECK_READ(fsp,req)) {
3404 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3405 END_PROFILE(SMBread);
3406 return;
3409 numtoread = SVAL(req->vwv+1, 0);
3410 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3412 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3415 * The requested read size cannot be greater than max_recv. JRA.
3417 if (numtoread > sconn->smb1.negprot.max_recv) {
3418 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3419 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3420 (unsigned int)numtoread,
3421 (unsigned int)sconn->smb1.negprot.max_recv));
3422 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3425 reply_outbuf(req, 5, numtoread+3);
3427 data = smb_buf(req->outbuf) + 3;
3429 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3430 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3431 &lock);
3433 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3434 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3435 END_PROFILE(SMBread);
3436 return;
3439 if (numtoread > 0)
3440 nread = read_file(fsp,data,startpos,numtoread);
3442 if (nread < 0) {
3443 reply_nterror(req, map_nt_error_from_unix(errno));
3444 goto strict_unlock;
3447 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3449 SSVAL(req->outbuf,smb_vwv0,nread);
3450 SSVAL(req->outbuf,smb_vwv5,nread+3);
3451 SCVAL(smb_buf(req->outbuf),0,1);
3452 SSVAL(smb_buf(req->outbuf),1,nread);
3454 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3455 fsp->fnum, (int)numtoread, (int)nread ) );
3457 strict_unlock:
3458 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3460 END_PROFILE(SMBread);
3461 return;
3464 /****************************************************************************
3465 Setup readX header.
3466 ****************************************************************************/
3468 static int setup_readX_header(struct smb_request *req, char *outbuf,
3469 size_t smb_maxcnt)
3471 int outsize;
3472 char *data;
3474 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3475 data = smb_buf(outbuf);
3477 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3479 SCVAL(outbuf,smb_vwv0,0xFF);
3480 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3481 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3482 SSVAL(outbuf,smb_vwv6,
3483 req_wct_ofs(req)
3484 + 1 /* the wct field */
3485 + 12 * sizeof(uint16_t) /* vwv */
3486 + 2); /* the buflen field */
3487 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3488 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3489 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3490 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3491 return outsize;
3494 /****************************************************************************
3495 Reply to a read and X - possibly using sendfile.
3496 ****************************************************************************/
3498 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3499 files_struct *fsp, SMB_OFF_T startpos,
3500 size_t smb_maxcnt)
3502 ssize_t nread = -1;
3503 struct lock_struct lock;
3504 int saved_errno = 0;
3506 if(fsp_stat(fsp) == -1) {
3507 reply_nterror(req, map_nt_error_from_unix(errno));
3508 return;
3511 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3512 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3513 &lock);
3515 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3516 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3517 return;
3520 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3521 (startpos > fsp->fsp_name->st.st_ex_size)
3522 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3524 * We already know that we would do a short read, so don't
3525 * try the sendfile() path.
3527 goto nosendfile_read;
3530 #if defined(WITH_SENDFILE)
3532 * We can only use sendfile on a non-chained packet
3533 * but we can use on a non-oplocked file. tridge proved this
3534 * on a train in Germany :-). JRA.
3537 if (!req_is_in_chain(req) &&
3538 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3539 (fsp->wcp == NULL) &&
3540 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3541 uint8 headerbuf[smb_size + 12 * 2];
3542 DATA_BLOB header;
3545 * Set up the packet header before send. We
3546 * assume here the sendfile will work (get the
3547 * correct amount of data).
3550 header = data_blob_const(headerbuf, sizeof(headerbuf));
3552 construct_reply_common_req(req, (char *)headerbuf);
3553 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3555 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3556 startpos, smb_maxcnt);
3557 if (nread == -1) {
3558 /* Returning ENOSYS means no data at all was sent.
3559 Do this as a normal read. */
3560 if (errno == ENOSYS) {
3561 goto normal_read;
3565 * Special hack for broken Linux with no working sendfile. If we
3566 * return EINTR we sent the header but not the rest of the data.
3567 * Fake this up by doing read/write calls.
3570 if (errno == EINTR) {
3571 /* Ensure we don't do this again. */
3572 set_use_sendfile(SNUM(conn), False);
3573 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3574 nread = fake_sendfile(fsp, startpos,
3575 smb_maxcnt);
3576 if (nread == -1) {
3577 DEBUG(0,("send_file_readX: "
3578 "fake_sendfile failed for "
3579 "file %s (%s).\n",
3580 fsp_str_dbg(fsp),
3581 strerror(errno)));
3582 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3584 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3585 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3586 /* No outbuf here means successful sendfile. */
3587 goto strict_unlock;
3590 DEBUG(0,("send_file_readX: sendfile failed for file "
3591 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3592 strerror(errno)));
3593 exit_server_cleanly("send_file_readX sendfile failed");
3594 } else if (nread == 0) {
3596 * Some sendfile implementations return 0 to indicate
3597 * that there was a short read, but nothing was
3598 * actually written to the socket. In this case,
3599 * fallback to the normal read path so the header gets
3600 * the correct byte count.
3602 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3603 "falling back to the normal read: %s\n",
3604 fsp_str_dbg(fsp)));
3605 goto normal_read;
3608 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3609 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3611 /* Deal with possible short send. */
3612 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3613 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3615 /* No outbuf here means successful sendfile. */
3616 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3617 SMB_PERFCOUNT_END(&req->pcd);
3618 goto strict_unlock;
3621 normal_read:
3623 #endif
3625 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3626 uint8 headerbuf[smb_size + 2*12];
3628 construct_reply_common_req(req, (char *)headerbuf);
3629 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3631 /* Send out the header. */
3632 if (write_data(req->sconn->sock, (char *)headerbuf,
3633 sizeof(headerbuf)) != sizeof(headerbuf)) {
3635 char addr[INET6_ADDRSTRLEN];
3637 * Try and give an error message saying what
3638 * client failed.
3640 DEBUG(0, ("write_data failed for client %s. "
3641 "Error %s\n",
3642 get_peer_addr(req->sconn->sock, addr,
3643 sizeof(addr)),
3644 strerror(errno)));
3646 DEBUG(0,("send_file_readX: write_data failed for file "
3647 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3648 strerror(errno)));
3649 exit_server_cleanly("send_file_readX sendfile failed");
3651 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3652 if (nread == -1) {
3653 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3654 "file %s (%s).\n", fsp_str_dbg(fsp),
3655 strerror(errno)));
3656 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3658 goto strict_unlock;
3661 nosendfile_read:
3663 reply_outbuf(req, 12, smb_maxcnt);
3665 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3666 saved_errno = errno;
3668 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3670 if (nread < 0) {
3671 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3672 return;
3675 setup_readX_header(req, (char *)req->outbuf, nread);
3677 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3678 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3680 chain_reply(req);
3681 return;
3683 strict_unlock:
3684 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3685 TALLOC_FREE(req->outbuf);
3686 return;
3689 /****************************************************************************
3690 Reply to a read and X.
3691 ****************************************************************************/
3693 void reply_read_and_X(struct smb_request *req)
3695 connection_struct *conn = req->conn;
3696 files_struct *fsp;
3697 SMB_OFF_T startpos;
3698 size_t smb_maxcnt;
3699 bool big_readX = False;
3700 #if 0
3701 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3702 #endif
3704 START_PROFILE(SMBreadX);
3706 if ((req->wct != 10) && (req->wct != 12)) {
3707 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3708 return;
3711 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3712 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3713 smb_maxcnt = SVAL(req->vwv+5, 0);
3715 /* If it's an IPC, pass off the pipe handler. */
3716 if (IS_IPC(conn)) {
3717 reply_pipe_read_and_X(req);
3718 END_PROFILE(SMBreadX);
3719 return;
3722 if (!check_fsp(conn, req, fsp)) {
3723 END_PROFILE(SMBreadX);
3724 return;
3727 if (!CHECK_READ(fsp,req)) {
3728 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3729 END_PROFILE(SMBreadX);
3730 return;
3733 if (global_client_caps & CAP_LARGE_READX) {
3734 size_t upper_size = SVAL(req->vwv+7, 0);
3735 smb_maxcnt |= (upper_size<<16);
3736 if (upper_size > 1) {
3737 /* Can't do this on a chained packet. */
3738 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3739 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3740 END_PROFILE(SMBreadX);
3741 return;
3743 /* We currently don't do this on signed or sealed data. */
3744 if (srv_is_signing_active(req->sconn) ||
3745 is_encrypted_packet(req->inbuf)) {
3746 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3747 END_PROFILE(SMBreadX);
3748 return;
3750 /* Is there room in the reply for this data ? */
3751 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3752 reply_nterror(req,
3753 NT_STATUS_INVALID_PARAMETER);
3754 END_PROFILE(SMBreadX);
3755 return;
3757 big_readX = True;
3761 if (req->wct == 12) {
3762 #ifdef LARGE_SMB_OFF_T
3764 * This is a large offset (64 bit) read.
3766 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3768 #else /* !LARGE_SMB_OFF_T */
3771 * Ensure we haven't been sent a >32 bit offset.
3774 if(IVAL(req->vwv+10, 0) != 0) {
3775 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3776 "used and we don't support 64 bit offsets.\n",
3777 (unsigned int)IVAL(req->vwv+10, 0) ));
3778 END_PROFILE(SMBreadX);
3779 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3780 return;
3783 #endif /* LARGE_SMB_OFF_T */
3787 if (!big_readX) {
3788 NTSTATUS status = schedule_aio_read_and_X(conn,
3789 req,
3790 fsp,
3791 startpos,
3792 smb_maxcnt);
3793 if (NT_STATUS_IS_OK(status)) {
3794 /* Read scheduled - we're done. */
3795 goto out;
3797 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3798 /* Real error - report to client. */
3799 END_PROFILE(SMBreadX);
3800 reply_nterror(req, status);
3801 return;
3803 /* NT_STATUS_RETRY - fall back to sync read. */
3806 smbd_lock_socket(req->sconn);
3807 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3808 smbd_unlock_socket(req->sconn);
3810 out:
3811 END_PROFILE(SMBreadX);
3812 return;
3815 /****************************************************************************
3816 Error replies to writebraw must have smb_wct == 1. Fix this up.
3817 ****************************************************************************/
3819 void error_to_writebrawerr(struct smb_request *req)
3821 uint8 *old_outbuf = req->outbuf;
3823 reply_outbuf(req, 1, 0);
3825 memcpy(req->outbuf, old_outbuf, smb_size);
3826 TALLOC_FREE(old_outbuf);
3829 /****************************************************************************
3830 Read 4 bytes of a smb packet and return the smb length of the packet.
3831 Store the result in the buffer. This version of the function will
3832 never return a session keepalive (length of zero).
3833 Timeout is in milliseconds.
3834 ****************************************************************************/
3836 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3837 size_t *len)
3839 uint8_t msgtype = SMBkeepalive;
3841 while (msgtype == SMBkeepalive) {
3842 NTSTATUS status;
3844 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3845 len);
3846 if (!NT_STATUS_IS_OK(status)) {
3847 char addr[INET6_ADDRSTRLEN];
3848 /* Try and give an error message
3849 * saying what client failed. */
3850 DEBUG(0, ("read_fd_with_timeout failed for "
3851 "client %s read error = %s.\n",
3852 get_peer_addr(fd,addr,sizeof(addr)),
3853 nt_errstr(status)));
3854 return status;
3857 msgtype = CVAL(inbuf, 0);
3860 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3861 (unsigned long)len));
3863 return NT_STATUS_OK;
3866 /****************************************************************************
3867 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3868 ****************************************************************************/
3870 void reply_writebraw(struct smb_request *req)
3872 connection_struct *conn = req->conn;
3873 char *buf = NULL;
3874 ssize_t nwritten=0;
3875 ssize_t total_written=0;
3876 size_t numtowrite=0;
3877 size_t tcount;
3878 SMB_OFF_T startpos;
3879 char *data=NULL;
3880 bool write_through;
3881 files_struct *fsp;
3882 struct lock_struct lock;
3883 NTSTATUS status;
3885 START_PROFILE(SMBwritebraw);
3888 * If we ever reply with an error, it must have the SMB command
3889 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3890 * we're finished.
3892 SCVAL(req->inbuf,smb_com,SMBwritec);
3894 if (srv_is_signing_active(req->sconn)) {
3895 END_PROFILE(SMBwritebraw);
3896 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3897 "raw reads/writes are disallowed.");
3900 if (req->wct < 12) {
3901 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3902 error_to_writebrawerr(req);
3903 END_PROFILE(SMBwritebraw);
3904 return;
3907 if (req->sconn->smb1.echo_handler.trusted_fde) {
3908 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3909 "'async smb echo handler = yes'\n"));
3910 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3911 error_to_writebrawerr(req);
3912 END_PROFILE(SMBwritebraw);
3913 return;
3916 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3917 if (!check_fsp(conn, req, fsp)) {
3918 error_to_writebrawerr(req);
3919 END_PROFILE(SMBwritebraw);
3920 return;
3923 if (!CHECK_WRITE(fsp)) {
3924 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3925 error_to_writebrawerr(req);
3926 END_PROFILE(SMBwritebraw);
3927 return;
3930 tcount = IVAL(req->vwv+1, 0);
3931 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3932 write_through = BITSETW(req->vwv+7,0);
3934 /* We have to deal with slightly different formats depending
3935 on whether we are using the core+ or lanman1.0 protocol */
3937 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3938 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3939 data = smb_buf(req->inbuf);
3940 } else {
3941 numtowrite = SVAL(req->vwv+10, 0);
3942 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3945 /* Ensure we don't write bytes past the end of this packet. */
3946 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3947 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3948 error_to_writebrawerr(req);
3949 END_PROFILE(SMBwritebraw);
3950 return;
3953 if (!fsp->print_file) {
3954 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3955 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3956 &lock);
3958 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3959 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3960 error_to_writebrawerr(req);
3961 END_PROFILE(SMBwritebraw);
3962 return;
3966 if (numtowrite>0) {
3967 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3970 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3971 "wrote=%d sync=%d\n",
3972 fsp->fnum, (double)startpos, (int)numtowrite,
3973 (int)nwritten, (int)write_through));
3975 if (nwritten < (ssize_t)numtowrite) {
3976 reply_nterror(req, NT_STATUS_DISK_FULL);
3977 error_to_writebrawerr(req);
3978 goto strict_unlock;
3981 total_written = nwritten;
3983 /* Allocate a buffer of 64k + length. */
3984 buf = TALLOC_ARRAY(NULL, char, 65540);
3985 if (!buf) {
3986 reply_nterror(req, NT_STATUS_NO_MEMORY);
3987 error_to_writebrawerr(req);
3988 goto strict_unlock;
3991 /* Return a SMBwritebraw message to the redirector to tell
3992 * it to send more bytes */
3994 memcpy(buf, req->inbuf, smb_size);
3995 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
3996 SCVAL(buf,smb_com,SMBwritebraw);
3997 SSVALS(buf,smb_vwv0,0xFFFF);
3998 show_msg(buf);
3999 if (!srv_send_smb(req->sconn,
4000 buf,
4001 false, 0, /* no signing */
4002 IS_CONN_ENCRYPTED(conn),
4003 &req->pcd)) {
4004 exit_server_cleanly("reply_writebraw: srv_send_smb "
4005 "failed.");
4008 /* Now read the raw data into the buffer and write it */
4009 status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
4010 &numtowrite);
4011 if (!NT_STATUS_IS_OK(status)) {
4012 exit_server_cleanly("secondary writebraw failed");
4015 /* Set up outbuf to return the correct size */
4016 reply_outbuf(req, 1, 0);
4018 if (numtowrite != 0) {
4020 if (numtowrite > 0xFFFF) {
4021 DEBUG(0,("reply_writebraw: Oversize secondary write "
4022 "raw requested (%u). Terminating\n",
4023 (unsigned int)numtowrite ));
4024 exit_server_cleanly("secondary writebraw failed");
4027 if (tcount > nwritten+numtowrite) {
4028 DEBUG(3,("reply_writebraw: Client overestimated the "
4029 "write %d %d %d\n",
4030 (int)tcount,(int)nwritten,(int)numtowrite));
4033 status = read_data(req->sconn->sock, buf+4, numtowrite);
4035 if (!NT_STATUS_IS_OK(status)) {
4036 char addr[INET6_ADDRSTRLEN];
4037 /* Try and give an error message
4038 * saying what client failed. */
4039 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4040 "raw read failed (%s) for client %s. "
4041 "Terminating\n", nt_errstr(status),
4042 get_peer_addr(req->sconn->sock, addr,
4043 sizeof(addr))));
4044 exit_server_cleanly("secondary writebraw failed");
4047 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4048 if (nwritten == -1) {
4049 TALLOC_FREE(buf);
4050 reply_nterror(req, map_nt_error_from_unix(errno));
4051 error_to_writebrawerr(req);
4052 goto strict_unlock;
4055 if (nwritten < (ssize_t)numtowrite) {
4056 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4057 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4060 if (nwritten > 0) {
4061 total_written += nwritten;
4065 TALLOC_FREE(buf);
4066 SSVAL(req->outbuf,smb_vwv0,total_written);
4068 status = sync_file(conn, fsp, write_through);
4069 if (!NT_STATUS_IS_OK(status)) {
4070 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4071 fsp_str_dbg(fsp), nt_errstr(status)));
4072 reply_nterror(req, status);
4073 error_to_writebrawerr(req);
4074 goto strict_unlock;
4077 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4078 "wrote=%d\n",
4079 fsp->fnum, (double)startpos, (int)numtowrite,
4080 (int)total_written));
4082 if (!fsp->print_file) {
4083 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4086 /* We won't return a status if write through is not selected - this
4087 * follows what WfWg does */
4088 END_PROFILE(SMBwritebraw);
4090 if (!write_through && total_written==tcount) {
4092 #if RABBIT_PELLET_FIX
4094 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4095 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
4096 * JRA.
4098 if (!send_keepalive(req->sconn->sock)) {
4099 exit_server_cleanly("reply_writebraw: send of "
4100 "keepalive failed");
4102 #endif
4103 TALLOC_FREE(req->outbuf);
4105 return;
4107 strict_unlock:
4108 if (!fsp->print_file) {
4109 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4112 END_PROFILE(SMBwritebraw);
4113 return;
4116 #undef DBGC_CLASS
4117 #define DBGC_CLASS DBGC_LOCKING
4119 /****************************************************************************
4120 Reply to a writeunlock (core+).
4121 ****************************************************************************/
4123 void reply_writeunlock(struct smb_request *req)
4125 connection_struct *conn = req->conn;
4126 ssize_t nwritten = -1;
4127 size_t numtowrite;
4128 SMB_OFF_T startpos;
4129 const char *data;
4130 NTSTATUS status = NT_STATUS_OK;
4131 files_struct *fsp;
4132 struct lock_struct lock;
4133 int saved_errno = 0;
4135 START_PROFILE(SMBwriteunlock);
4137 if (req->wct < 5) {
4138 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4139 END_PROFILE(SMBwriteunlock);
4140 return;
4143 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4145 if (!check_fsp(conn, req, fsp)) {
4146 END_PROFILE(SMBwriteunlock);
4147 return;
4150 if (!CHECK_WRITE(fsp)) {
4151 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4152 END_PROFILE(SMBwriteunlock);
4153 return;
4156 numtowrite = SVAL(req->vwv+1, 0);
4157 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4158 data = (const char *)req->buf + 3;
4160 if (!fsp->print_file && numtowrite > 0) {
4161 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4162 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4163 &lock);
4165 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4166 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4167 END_PROFILE(SMBwriteunlock);
4168 return;
4172 /* The special X/Open SMB protocol handling of
4173 zero length writes is *NOT* done for
4174 this call */
4175 if(numtowrite == 0) {
4176 nwritten = 0;
4177 } else {
4178 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4179 saved_errno = errno;
4182 status = sync_file(conn, fsp, False /* write through */);
4183 if (!NT_STATUS_IS_OK(status)) {
4184 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4185 fsp_str_dbg(fsp), nt_errstr(status)));
4186 reply_nterror(req, status);
4187 goto strict_unlock;
4190 if(nwritten < 0) {
4191 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4192 goto strict_unlock;
4195 if((nwritten < numtowrite) && (numtowrite != 0)) {
4196 reply_nterror(req, NT_STATUS_DISK_FULL);
4197 goto strict_unlock;
4200 if (numtowrite && !fsp->print_file) {
4201 status = do_unlock(req->sconn->msg_ctx,
4202 fsp,
4203 (uint64_t)req->smbpid,
4204 (uint64_t)numtowrite,
4205 (uint64_t)startpos,
4206 WINDOWS_LOCK);
4208 if (NT_STATUS_V(status)) {
4209 reply_nterror(req, status);
4210 goto strict_unlock;
4214 reply_outbuf(req, 1, 0);
4216 SSVAL(req->outbuf,smb_vwv0,nwritten);
4218 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4219 fsp->fnum, (int)numtowrite, (int)nwritten));
4221 strict_unlock:
4222 if (numtowrite && !fsp->print_file) {
4223 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4226 END_PROFILE(SMBwriteunlock);
4227 return;
4230 #undef DBGC_CLASS
4231 #define DBGC_CLASS DBGC_ALL
4233 /****************************************************************************
4234 Reply to a write.
4235 ****************************************************************************/
4237 void reply_write(struct smb_request *req)
4239 connection_struct *conn = req->conn;
4240 size_t numtowrite;
4241 ssize_t nwritten = -1;
4242 SMB_OFF_T startpos;
4243 const char *data;
4244 files_struct *fsp;
4245 struct lock_struct lock;
4246 NTSTATUS status;
4247 int saved_errno = 0;
4249 START_PROFILE(SMBwrite);
4251 if (req->wct < 5) {
4252 END_PROFILE(SMBwrite);
4253 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4254 return;
4257 /* If it's an IPC, pass off the pipe handler. */
4258 if (IS_IPC(conn)) {
4259 reply_pipe_write(req);
4260 END_PROFILE(SMBwrite);
4261 return;
4264 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4266 if (!check_fsp(conn, req, fsp)) {
4267 END_PROFILE(SMBwrite);
4268 return;
4271 if (!CHECK_WRITE(fsp)) {
4272 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4273 END_PROFILE(SMBwrite);
4274 return;
4277 numtowrite = SVAL(req->vwv+1, 0);
4278 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4279 data = (const char *)req->buf + 3;
4281 if (!fsp->print_file) {
4282 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4283 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4284 &lock);
4286 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4287 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4288 END_PROFILE(SMBwrite);
4289 return;
4294 * X/Open SMB protocol says that if smb_vwv1 is
4295 * zero then the file size should be extended or
4296 * truncated to the size given in smb_vwv[2-3].
4299 if(numtowrite == 0) {
4301 * This is actually an allocate call, and set EOF. JRA.
4303 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4304 if (nwritten < 0) {
4305 reply_nterror(req, NT_STATUS_DISK_FULL);
4306 goto strict_unlock;
4308 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4309 if (nwritten < 0) {
4310 reply_nterror(req, NT_STATUS_DISK_FULL);
4311 goto strict_unlock;
4313 trigger_write_time_update_immediate(fsp);
4314 } else {
4315 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4318 status = sync_file(conn, fsp, False);
4319 if (!NT_STATUS_IS_OK(status)) {
4320 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4321 fsp_str_dbg(fsp), nt_errstr(status)));
4322 reply_nterror(req, status);
4323 goto strict_unlock;
4326 if(nwritten < 0) {
4327 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4328 goto strict_unlock;
4331 if((nwritten == 0) && (numtowrite != 0)) {
4332 reply_nterror(req, NT_STATUS_DISK_FULL);
4333 goto strict_unlock;
4336 reply_outbuf(req, 1, 0);
4338 SSVAL(req->outbuf,smb_vwv0,nwritten);
4340 if (nwritten < (ssize_t)numtowrite) {
4341 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4342 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4345 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4347 strict_unlock:
4348 if (!fsp->print_file) {
4349 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4352 END_PROFILE(SMBwrite);
4353 return;
4356 /****************************************************************************
4357 Ensure a buffer is a valid writeX for recvfile purposes.
4358 ****************************************************************************/
4360 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4361 (2*14) + /* word count (including bcc) */ \
4362 1 /* pad byte */)
4364 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4365 const uint8_t *inbuf)
4367 size_t numtowrite;
4368 connection_struct *conn = NULL;
4369 unsigned int doff = 0;
4370 size_t len = smb_len_large(inbuf);
4372 if (is_encrypted_packet(inbuf)) {
4373 /* Can't do this on encrypted
4374 * connections. */
4375 return false;
4378 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4379 return false;
4382 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4383 CVAL(inbuf,smb_wct) != 14) {
4384 DEBUG(10,("is_valid_writeX_buffer: chained or "
4385 "invalid word length.\n"));
4386 return false;
4389 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4390 if (conn == NULL) {
4391 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4392 return false;
4394 if (IS_IPC(conn)) {
4395 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4396 return false;
4398 if (IS_PRINT(conn)) {
4399 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4400 return false;
4402 doff = SVAL(inbuf,smb_vwv11);
4404 numtowrite = SVAL(inbuf,smb_vwv10);
4406 if (len > doff && len - doff > 0xFFFF) {
4407 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4410 if (numtowrite == 0) {
4411 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4412 return false;
4415 /* Ensure the sizes match up. */
4416 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4417 /* no pad byte...old smbclient :-( */
4418 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4419 (unsigned int)doff,
4420 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4421 return false;
4424 if (len - doff != numtowrite) {
4425 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4426 "len = %u, doff = %u, numtowrite = %u\n",
4427 (unsigned int)len,
4428 (unsigned int)doff,
4429 (unsigned int)numtowrite ));
4430 return false;
4433 DEBUG(10,("is_valid_writeX_buffer: true "
4434 "len = %u, doff = %u, numtowrite = %u\n",
4435 (unsigned int)len,
4436 (unsigned int)doff,
4437 (unsigned int)numtowrite ));
4439 return true;
4442 /****************************************************************************
4443 Reply to a write and X.
4444 ****************************************************************************/
4446 void reply_write_and_X(struct smb_request *req)
4448 connection_struct *conn = req->conn;
4449 files_struct *fsp;
4450 struct lock_struct lock;
4451 SMB_OFF_T startpos;
4452 size_t numtowrite;
4453 bool write_through;
4454 ssize_t nwritten;
4455 unsigned int smb_doff;
4456 unsigned int smblen;
4457 char *data;
4458 NTSTATUS status;
4459 int saved_errno = 0;
4461 START_PROFILE(SMBwriteX);
4463 if ((req->wct != 12) && (req->wct != 14)) {
4464 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4465 END_PROFILE(SMBwriteX);
4466 return;
4469 numtowrite = SVAL(req->vwv+10, 0);
4470 smb_doff = SVAL(req->vwv+11, 0);
4471 smblen = smb_len(req->inbuf);
4473 if (req->unread_bytes > 0xFFFF ||
4474 (smblen > smb_doff &&
4475 smblen - smb_doff > 0xFFFF)) {
4476 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4479 if (req->unread_bytes) {
4480 /* Can't do a recvfile write on IPC$ */
4481 if (IS_IPC(conn)) {
4482 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4483 END_PROFILE(SMBwriteX);
4484 return;
4486 if (numtowrite != req->unread_bytes) {
4487 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4488 END_PROFILE(SMBwriteX);
4489 return;
4491 } else {
4492 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4493 smb_doff + numtowrite > smblen) {
4494 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4495 END_PROFILE(SMBwriteX);
4496 return;
4500 /* If it's an IPC, pass off the pipe handler. */
4501 if (IS_IPC(conn)) {
4502 if (req->unread_bytes) {
4503 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4504 END_PROFILE(SMBwriteX);
4505 return;
4507 reply_pipe_write_and_X(req);
4508 END_PROFILE(SMBwriteX);
4509 return;
4512 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4513 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4514 write_through = BITSETW(req->vwv+7,0);
4516 if (!check_fsp(conn, req, fsp)) {
4517 END_PROFILE(SMBwriteX);
4518 return;
4521 if (!CHECK_WRITE(fsp)) {
4522 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4523 END_PROFILE(SMBwriteX);
4524 return;
4527 data = smb_base(req->inbuf) + smb_doff;
4529 if(req->wct == 14) {
4530 #ifdef LARGE_SMB_OFF_T
4532 * This is a large offset (64 bit) write.
4534 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4536 #else /* !LARGE_SMB_OFF_T */
4539 * Ensure we haven't been sent a >32 bit offset.
4542 if(IVAL(req->vwv+12, 0) != 0) {
4543 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4544 "used and we don't support 64 bit offsets.\n",
4545 (unsigned int)IVAL(req->vwv+12, 0) ));
4546 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4547 END_PROFILE(SMBwriteX);
4548 return;
4551 #endif /* LARGE_SMB_OFF_T */
4554 /* X/Open SMB protocol says that, unlike SMBwrite
4555 if the length is zero then NO truncation is
4556 done, just a write of zero. To truncate a file,
4557 use SMBwrite. */
4559 if(numtowrite == 0) {
4560 nwritten = 0;
4561 } else {
4562 if (req->unread_bytes == 0) {
4563 status = schedule_aio_write_and_X(conn,
4564 req,
4565 fsp,
4566 data,
4567 startpos,
4568 numtowrite);
4570 if (NT_STATUS_IS_OK(status)) {
4571 /* write scheduled - we're done. */
4572 goto out;
4574 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4575 /* Real error - report to client. */
4576 reply_nterror(req, status);
4577 goto out;
4579 /* NT_STATUS_RETRY - fall through to sync write. */
4582 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4583 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4584 &lock);
4586 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4587 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4588 goto out;
4591 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4592 saved_errno = errno;
4594 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4597 if(nwritten < 0) {
4598 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4599 goto out;
4602 if((nwritten == 0) && (numtowrite != 0)) {
4603 reply_nterror(req, NT_STATUS_DISK_FULL);
4604 goto out;
4607 reply_outbuf(req, 6, 0);
4608 SSVAL(req->outbuf,smb_vwv2,nwritten);
4609 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4611 if (nwritten < (ssize_t)numtowrite) {
4612 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4613 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4616 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4617 fsp->fnum, (int)numtowrite, (int)nwritten));
4619 status = sync_file(conn, fsp, write_through);
4620 if (!NT_STATUS_IS_OK(status)) {
4621 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4622 fsp_str_dbg(fsp), nt_errstr(status)));
4623 reply_nterror(req, status);
4624 goto out;
4627 END_PROFILE(SMBwriteX);
4628 chain_reply(req);
4629 return;
4631 out:
4632 END_PROFILE(SMBwriteX);
4633 return;
4636 /****************************************************************************
4637 Reply to a lseek.
4638 ****************************************************************************/
4640 void reply_lseek(struct smb_request *req)
4642 connection_struct *conn = req->conn;
4643 SMB_OFF_T startpos;
4644 SMB_OFF_T res= -1;
4645 int mode,umode;
4646 files_struct *fsp;
4648 START_PROFILE(SMBlseek);
4650 if (req->wct < 4) {
4651 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4652 END_PROFILE(SMBlseek);
4653 return;
4656 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4658 if (!check_fsp(conn, req, fsp)) {
4659 return;
4662 flush_write_cache(fsp, SEEK_FLUSH);
4664 mode = SVAL(req->vwv+1, 0) & 3;
4665 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4666 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4668 switch (mode) {
4669 case 0:
4670 umode = SEEK_SET;
4671 res = startpos;
4672 break;
4673 case 1:
4674 umode = SEEK_CUR;
4675 res = fsp->fh->pos + startpos;
4676 break;
4677 case 2:
4678 umode = SEEK_END;
4679 break;
4680 default:
4681 umode = SEEK_SET;
4682 res = startpos;
4683 break;
4686 if (umode == SEEK_END) {
4687 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4688 if(errno == EINVAL) {
4689 SMB_OFF_T current_pos = startpos;
4691 if(fsp_stat(fsp) == -1) {
4692 reply_nterror(req,
4693 map_nt_error_from_unix(errno));
4694 END_PROFILE(SMBlseek);
4695 return;
4698 current_pos += fsp->fsp_name->st.st_ex_size;
4699 if(current_pos < 0)
4700 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4704 if(res == -1) {
4705 reply_nterror(req, map_nt_error_from_unix(errno));
4706 END_PROFILE(SMBlseek);
4707 return;
4711 fsp->fh->pos = res;
4713 reply_outbuf(req, 2, 0);
4714 SIVAL(req->outbuf,smb_vwv0,res);
4716 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4717 fsp->fnum, (double)startpos, (double)res, mode));
4719 END_PROFILE(SMBlseek);
4720 return;
4723 /****************************************************************************
4724 Reply to a flush.
4725 ****************************************************************************/
4727 void reply_flush(struct smb_request *req)
4729 connection_struct *conn = req->conn;
4730 uint16 fnum;
4731 files_struct *fsp;
4733 START_PROFILE(SMBflush);
4735 if (req->wct < 1) {
4736 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4737 return;
4740 fnum = SVAL(req->vwv+0, 0);
4741 fsp = file_fsp(req, fnum);
4743 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4744 return;
4747 if (!fsp) {
4748 file_sync_all(conn);
4749 } else {
4750 NTSTATUS status = sync_file(conn, fsp, True);
4751 if (!NT_STATUS_IS_OK(status)) {
4752 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4753 fsp_str_dbg(fsp), nt_errstr(status)));
4754 reply_nterror(req, status);
4755 END_PROFILE(SMBflush);
4756 return;
4760 reply_outbuf(req, 0, 0);
4762 DEBUG(3,("flush\n"));
4763 END_PROFILE(SMBflush);
4764 return;
4767 /****************************************************************************
4768 Reply to a exit.
4769 conn POINTER CAN BE NULL HERE !
4770 ****************************************************************************/
4772 void reply_exit(struct smb_request *req)
4774 START_PROFILE(SMBexit);
4776 file_close_pid(req->sconn, req->smbpid, req->vuid);
4778 reply_outbuf(req, 0, 0);
4780 DEBUG(3,("exit\n"));
4782 END_PROFILE(SMBexit);
4783 return;
4786 /****************************************************************************
4787 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4788 ****************************************************************************/
4790 void reply_close(struct smb_request *req)
4792 connection_struct *conn = req->conn;
4793 NTSTATUS status = NT_STATUS_OK;
4794 files_struct *fsp = NULL;
4795 START_PROFILE(SMBclose);
4797 if (req->wct < 3) {
4798 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4799 END_PROFILE(SMBclose);
4800 return;
4803 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4806 * We can only use check_fsp if we know it's not a directory.
4809 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4810 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4811 END_PROFILE(SMBclose);
4812 return;
4815 if(fsp->is_directory) {
4817 * Special case - close NT SMB directory handle.
4819 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4820 status = close_file(req, fsp, NORMAL_CLOSE);
4821 } else {
4822 time_t t;
4824 * Close ordinary file.
4827 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4828 fsp->fh->fd, fsp->fnum,
4829 conn->num_files_open));
4832 * Take care of any time sent in the close.
4835 t = srv_make_unix_date3(req->vwv+1);
4836 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4839 * close_file() returns the unix errno if an error
4840 * was detected on close - normally this is due to
4841 * a disk full error. If not then it was probably an I/O error.
4844 status = close_file(req, fsp, NORMAL_CLOSE);
4847 if (!NT_STATUS_IS_OK(status)) {
4848 reply_nterror(req, status);
4849 END_PROFILE(SMBclose);
4850 return;
4853 reply_outbuf(req, 0, 0);
4854 END_PROFILE(SMBclose);
4855 return;
4858 /****************************************************************************
4859 Reply to a writeclose (Core+ protocol).
4860 ****************************************************************************/
4862 void reply_writeclose(struct smb_request *req)
4864 connection_struct *conn = req->conn;
4865 size_t numtowrite;
4866 ssize_t nwritten = -1;
4867 NTSTATUS close_status = NT_STATUS_OK;
4868 SMB_OFF_T startpos;
4869 const char *data;
4870 struct timespec mtime;
4871 files_struct *fsp;
4872 struct lock_struct lock;
4874 START_PROFILE(SMBwriteclose);
4876 if (req->wct < 6) {
4877 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4878 END_PROFILE(SMBwriteclose);
4879 return;
4882 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4884 if (!check_fsp(conn, req, fsp)) {
4885 END_PROFILE(SMBwriteclose);
4886 return;
4888 if (!CHECK_WRITE(fsp)) {
4889 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4890 END_PROFILE(SMBwriteclose);
4891 return;
4894 numtowrite = SVAL(req->vwv+1, 0);
4895 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4896 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4897 data = (const char *)req->buf + 1;
4899 if (!fsp->print_file) {
4900 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4901 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4902 &lock);
4904 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4905 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4906 END_PROFILE(SMBwriteclose);
4907 return;
4911 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4913 set_close_write_time(fsp, mtime);
4916 * More insanity. W2K only closes the file if writelen > 0.
4917 * JRA.
4920 if (numtowrite) {
4921 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4922 "file %s\n", fsp_str_dbg(fsp)));
4923 close_status = close_file(req, fsp, NORMAL_CLOSE);
4926 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4927 fsp->fnum, (int)numtowrite, (int)nwritten,
4928 conn->num_files_open));
4930 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4931 reply_nterror(req, NT_STATUS_DISK_FULL);
4932 goto strict_unlock;
4935 if(!NT_STATUS_IS_OK(close_status)) {
4936 reply_nterror(req, close_status);
4937 goto strict_unlock;
4940 reply_outbuf(req, 1, 0);
4942 SSVAL(req->outbuf,smb_vwv0,nwritten);
4944 strict_unlock:
4945 if (numtowrite && !fsp->print_file) {
4946 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4949 END_PROFILE(SMBwriteclose);
4950 return;
4953 #undef DBGC_CLASS
4954 #define DBGC_CLASS DBGC_LOCKING
4956 /****************************************************************************
4957 Reply to a lock.
4958 ****************************************************************************/
4960 void reply_lock(struct smb_request *req)
4962 connection_struct *conn = req->conn;
4963 uint64_t count,offset;
4964 NTSTATUS status;
4965 files_struct *fsp;
4966 struct byte_range_lock *br_lck = NULL;
4968 START_PROFILE(SMBlock);
4970 if (req->wct < 5) {
4971 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4972 END_PROFILE(SMBlock);
4973 return;
4976 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4978 if (!check_fsp(conn, req, fsp)) {
4979 END_PROFILE(SMBlock);
4980 return;
4983 count = (uint64_t)IVAL(req->vwv+1, 0);
4984 offset = (uint64_t)IVAL(req->vwv+3, 0);
4986 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4987 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4989 br_lck = do_lock(req->sconn->msg_ctx,
4990 fsp,
4991 (uint64_t)req->smbpid,
4992 count,
4993 offset,
4994 WRITE_LOCK,
4995 WINDOWS_LOCK,
4996 False, /* Non-blocking lock. */
4997 &status,
4998 NULL,
4999 NULL);
5001 TALLOC_FREE(br_lck);
5003 if (NT_STATUS_V(status)) {
5004 reply_nterror(req, status);
5005 END_PROFILE(SMBlock);
5006 return;
5009 reply_outbuf(req, 0, 0);
5011 END_PROFILE(SMBlock);
5012 return;
5015 /****************************************************************************
5016 Reply to a unlock.
5017 ****************************************************************************/
5019 void reply_unlock(struct smb_request *req)
5021 connection_struct *conn = req->conn;
5022 uint64_t count,offset;
5023 NTSTATUS status;
5024 files_struct *fsp;
5026 START_PROFILE(SMBunlock);
5028 if (req->wct < 5) {
5029 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5030 END_PROFILE(SMBunlock);
5031 return;
5034 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5036 if (!check_fsp(conn, req, fsp)) {
5037 END_PROFILE(SMBunlock);
5038 return;
5041 count = (uint64_t)IVAL(req->vwv+1, 0);
5042 offset = (uint64_t)IVAL(req->vwv+3, 0);
5044 status = do_unlock(req->sconn->msg_ctx,
5045 fsp,
5046 (uint64_t)req->smbpid,
5047 count,
5048 offset,
5049 WINDOWS_LOCK);
5051 if (NT_STATUS_V(status)) {
5052 reply_nterror(req, status);
5053 END_PROFILE(SMBunlock);
5054 return;
5057 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5058 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
5060 reply_outbuf(req, 0, 0);
5062 END_PROFILE(SMBunlock);
5063 return;
5066 #undef DBGC_CLASS
5067 #define DBGC_CLASS DBGC_ALL
5069 /****************************************************************************
5070 Reply to a tdis.
5071 conn POINTER CAN BE NULL HERE !
5072 ****************************************************************************/
5074 void reply_tdis(struct smb_request *req)
5076 connection_struct *conn = req->conn;
5077 START_PROFILE(SMBtdis);
5079 if (!conn) {
5080 DEBUG(4,("Invalid connection in tdis\n"));
5081 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
5082 END_PROFILE(SMBtdis);
5083 return;
5086 conn->used = False;
5088 close_cnum(conn,req->vuid);
5089 req->conn = NULL;
5091 reply_outbuf(req, 0, 0);
5092 END_PROFILE(SMBtdis);
5093 return;
5096 /****************************************************************************
5097 Reply to a echo.
5098 conn POINTER CAN BE NULL HERE !
5099 ****************************************************************************/
5101 void reply_echo(struct smb_request *req)
5103 connection_struct *conn = req->conn;
5104 struct smb_perfcount_data local_pcd;
5105 struct smb_perfcount_data *cur_pcd;
5106 int smb_reverb;
5107 int seq_num;
5109 START_PROFILE(SMBecho);
5111 smb_init_perfcount_data(&local_pcd);
5113 if (req->wct < 1) {
5114 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5115 END_PROFILE(SMBecho);
5116 return;
5119 smb_reverb = SVAL(req->vwv+0, 0);
5121 reply_outbuf(req, 1, req->buflen);
5123 /* copy any incoming data back out */
5124 if (req->buflen > 0) {
5125 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5128 if (smb_reverb > 100) {
5129 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5130 smb_reverb = 100;
5133 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5135 /* this makes sure we catch the request pcd */
5136 if (seq_num == smb_reverb) {
5137 cur_pcd = &req->pcd;
5138 } else {
5139 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5140 cur_pcd = &local_pcd;
5143 SSVAL(req->outbuf,smb_vwv0,seq_num);
5145 show_msg((char *)req->outbuf);
5146 if (!srv_send_smb(req->sconn,
5147 (char *)req->outbuf,
5148 true, req->seqnum+1,
5149 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5150 cur_pcd))
5151 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5154 DEBUG(3,("echo %d times\n", smb_reverb));
5156 TALLOC_FREE(req->outbuf);
5158 END_PROFILE(SMBecho);
5159 return;
5162 /****************************************************************************
5163 Reply to a printopen.
5164 ****************************************************************************/
5166 void reply_printopen(struct smb_request *req)
5168 connection_struct *conn = req->conn;
5169 files_struct *fsp;
5170 NTSTATUS status;
5172 START_PROFILE(SMBsplopen);
5174 if (req->wct < 2) {
5175 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5176 END_PROFILE(SMBsplopen);
5177 return;
5180 if (!CAN_PRINT(conn)) {
5181 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5182 END_PROFILE(SMBsplopen);
5183 return;
5186 status = file_new(req, conn, &fsp);
5187 if(!NT_STATUS_IS_OK(status)) {
5188 reply_nterror(req, status);
5189 END_PROFILE(SMBsplopen);
5190 return;
5193 /* Open for exclusive use, write only. */
5194 status = print_spool_open(fsp, NULL, req->vuid);
5196 if (!NT_STATUS_IS_OK(status)) {
5197 file_free(req, fsp);
5198 reply_nterror(req, status);
5199 END_PROFILE(SMBsplopen);
5200 return;
5203 reply_outbuf(req, 1, 0);
5204 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5206 DEBUG(3,("openprint fd=%d fnum=%d\n",
5207 fsp->fh->fd, fsp->fnum));
5209 END_PROFILE(SMBsplopen);
5210 return;
5213 /****************************************************************************
5214 Reply to a printclose.
5215 ****************************************************************************/
5217 void reply_printclose(struct smb_request *req)
5219 connection_struct *conn = req->conn;
5220 files_struct *fsp;
5221 NTSTATUS status;
5223 START_PROFILE(SMBsplclose);
5225 if (req->wct < 1) {
5226 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5227 END_PROFILE(SMBsplclose);
5228 return;
5231 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5233 if (!check_fsp(conn, req, fsp)) {
5234 END_PROFILE(SMBsplclose);
5235 return;
5238 if (!CAN_PRINT(conn)) {
5239 reply_force_doserror(req, ERRSRV, ERRerror);
5240 END_PROFILE(SMBsplclose);
5241 return;
5244 DEBUG(3,("printclose fd=%d fnum=%d\n",
5245 fsp->fh->fd,fsp->fnum));
5247 status = close_file(req, fsp, NORMAL_CLOSE);
5249 if(!NT_STATUS_IS_OK(status)) {
5250 reply_nterror(req, status);
5251 END_PROFILE(SMBsplclose);
5252 return;
5255 reply_outbuf(req, 0, 0);
5257 END_PROFILE(SMBsplclose);
5258 return;
5261 /****************************************************************************
5262 Reply to a printqueue.
5263 ****************************************************************************/
5265 void reply_printqueue(struct smb_request *req)
5267 connection_struct *conn = req->conn;
5268 int max_count;
5269 int start_index;
5271 START_PROFILE(SMBsplretq);
5273 if (req->wct < 2) {
5274 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5275 END_PROFILE(SMBsplretq);
5276 return;
5279 max_count = SVAL(req->vwv+0, 0);
5280 start_index = SVAL(req->vwv+1, 0);
5282 /* we used to allow the client to get the cnum wrong, but that
5283 is really quite gross and only worked when there was only
5284 one printer - I think we should now only accept it if they
5285 get it right (tridge) */
5286 if (!CAN_PRINT(conn)) {
5287 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5288 END_PROFILE(SMBsplretq);
5289 return;
5292 reply_outbuf(req, 2, 3);
5293 SSVAL(req->outbuf,smb_vwv0,0);
5294 SSVAL(req->outbuf,smb_vwv1,0);
5295 SCVAL(smb_buf(req->outbuf),0,1);
5296 SSVAL(smb_buf(req->outbuf),1,0);
5298 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5299 start_index, max_count));
5302 TALLOC_CTX *mem_ctx = talloc_tos();
5303 NTSTATUS status;
5304 WERROR werr;
5305 const char *sharename = lp_servicename(SNUM(conn));
5306 struct rpc_pipe_client *cli = NULL;
5307 struct policy_handle handle;
5308 struct spoolss_DevmodeContainer devmode_ctr;
5309 union spoolss_JobInfo *info;
5310 uint32_t count;
5311 uint32_t num_to_get;
5312 uint32_t first;
5313 uint32_t i;
5315 ZERO_STRUCT(handle);
5317 status = rpc_pipe_open_interface(conn,
5318 &ndr_table_spoolss.syntax_id,
5319 conn->server_info,
5320 &conn->sconn->client_id,
5321 conn->sconn->msg_ctx,
5322 &cli);
5323 if (!NT_STATUS_IS_OK(status)) {
5324 DEBUG(0, ("reply_printqueue: "
5325 "could not connect to spoolss: %s\n",
5326 nt_errstr(status)));
5327 reply_nterror(req, status);
5328 goto out;
5331 ZERO_STRUCT(devmode_ctr);
5333 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
5334 sharename,
5335 NULL, devmode_ctr,
5336 SEC_FLAG_MAXIMUM_ALLOWED,
5337 &handle,
5338 &werr);
5339 if (!NT_STATUS_IS_OK(status)) {
5340 reply_nterror(req, status);
5341 goto out;
5343 if (!W_ERROR_IS_OK(werr)) {
5344 reply_nterror(req, werror_to_ntstatus(werr));
5345 goto out;
5348 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5349 &handle,
5350 0, /* firstjob */
5351 0xff, /* numjobs */
5352 2, /* level */
5353 0, /* offered */
5354 &count,
5355 &info);
5356 if (!W_ERROR_IS_OK(werr)) {
5357 reply_nterror(req, werror_to_ntstatus(werr));
5358 goto out;
5361 if (max_count > 0) {
5362 first = start_index;
5363 } else {
5364 first = start_index + max_count + 1;
5367 if (first >= count) {
5368 num_to_get = first;
5369 } else {
5370 num_to_get = first + MIN(ABS(max_count), count - first);
5373 for (i = first; i < num_to_get; i++) {
5374 char blob[28];
5375 char *p = blob;
5376 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5377 int qstatus;
5378 uint16_t qrapjobid = pjobid_to_rap(sharename,
5379 info[i].info2.job_id);
5381 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5382 qstatus = 2;
5383 } else {
5384 qstatus = 3;
5387 srv_put_dos_date2(p, 0, qtime);
5388 SCVAL(p, 4, qstatus);
5389 SSVAL(p, 5, qrapjobid);
5390 SIVAL(p, 7, info[i].info2.size);
5391 SCVAL(p, 11, 0);
5392 srvstr_push(blob, req->flags2, p+12,
5393 info[i].info2.notify_name, 16, STR_ASCII);
5395 if (message_push_blob(
5396 &req->outbuf,
5397 data_blob_const(
5398 blob, sizeof(blob))) == -1) {
5399 reply_nterror(req, NT_STATUS_NO_MEMORY);
5400 goto out;
5404 if (count > 0) {
5405 SSVAL(req->outbuf,smb_vwv0,count);
5406 SSVAL(req->outbuf,smb_vwv1,
5407 (max_count>0?first+count:first-1));
5408 SCVAL(smb_buf(req->outbuf),0,1);
5409 SSVAL(smb_buf(req->outbuf),1,28*count);
5413 DEBUG(3, ("%u entries returned in queue\n",
5414 (unsigned)count));
5416 out:
5417 if (cli && is_valid_policy_hnd(&handle)) {
5418 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
5423 END_PROFILE(SMBsplretq);
5424 return;
5427 /****************************************************************************
5428 Reply to a printwrite.
5429 ****************************************************************************/
5431 void reply_printwrite(struct smb_request *req)
5433 connection_struct *conn = req->conn;
5434 int numtowrite;
5435 const char *data;
5436 files_struct *fsp;
5438 START_PROFILE(SMBsplwr);
5440 if (req->wct < 1) {
5441 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5442 END_PROFILE(SMBsplwr);
5443 return;
5446 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5448 if (!check_fsp(conn, req, fsp)) {
5449 END_PROFILE(SMBsplwr);
5450 return;
5453 if (!fsp->print_file) {
5454 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5455 END_PROFILE(SMBsplwr);
5456 return;
5459 if (!CHECK_WRITE(fsp)) {
5460 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5461 END_PROFILE(SMBsplwr);
5462 return;
5465 numtowrite = SVAL(req->buf, 1);
5467 if (req->buflen < numtowrite + 3) {
5468 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5469 END_PROFILE(SMBsplwr);
5470 return;
5473 data = (const char *)req->buf + 3;
5475 if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5476 reply_nterror(req, map_nt_error_from_unix(errno));
5477 END_PROFILE(SMBsplwr);
5478 return;
5481 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5483 END_PROFILE(SMBsplwr);
5484 return;
5487 /****************************************************************************
5488 Reply to a mkdir.
5489 ****************************************************************************/
5491 void reply_mkdir(struct smb_request *req)
5493 connection_struct *conn = req->conn;
5494 struct smb_filename *smb_dname = NULL;
5495 char *directory = NULL;
5496 NTSTATUS status;
5497 TALLOC_CTX *ctx = talloc_tos();
5499 START_PROFILE(SMBmkdir);
5501 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5502 STR_TERMINATE, &status);
5503 if (!NT_STATUS_IS_OK(status)) {
5504 reply_nterror(req, status);
5505 goto out;
5508 status = filename_convert(ctx, conn,
5509 req->flags2 & FLAGS2_DFS_PATHNAMES,
5510 directory,
5512 NULL,
5513 &smb_dname);
5514 if (!NT_STATUS_IS_OK(status)) {
5515 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5516 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5517 ERRSRV, ERRbadpath);
5518 goto out;
5520 reply_nterror(req, status);
5521 goto out;
5524 status = create_directory(conn, req, smb_dname);
5526 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5528 if (!NT_STATUS_IS_OK(status)) {
5530 if (!use_nt_status()
5531 && NT_STATUS_EQUAL(status,
5532 NT_STATUS_OBJECT_NAME_COLLISION)) {
5534 * Yes, in the DOS error code case we get a
5535 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5536 * samba4 torture test.
5538 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5541 reply_nterror(req, status);
5542 goto out;
5545 reply_outbuf(req, 0, 0);
5547 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5548 out:
5549 TALLOC_FREE(smb_dname);
5550 END_PROFILE(SMBmkdir);
5551 return;
5554 /****************************************************************************
5555 Reply to a rmdir.
5556 ****************************************************************************/
5558 void reply_rmdir(struct smb_request *req)
5560 connection_struct *conn = req->conn;
5561 struct smb_filename *smb_dname = NULL;
5562 char *directory = NULL;
5563 NTSTATUS status;
5564 TALLOC_CTX *ctx = talloc_tos();
5565 files_struct *fsp = NULL;
5566 int info = 0;
5567 struct smbd_server_connection *sconn = req->sconn;
5569 START_PROFILE(SMBrmdir);
5571 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5572 STR_TERMINATE, &status);
5573 if (!NT_STATUS_IS_OK(status)) {
5574 reply_nterror(req, status);
5575 goto out;
5578 status = filename_convert(ctx, conn,
5579 req->flags2 & FLAGS2_DFS_PATHNAMES,
5580 directory,
5582 NULL,
5583 &smb_dname);
5584 if (!NT_STATUS_IS_OK(status)) {
5585 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5586 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5587 ERRSRV, ERRbadpath);
5588 goto out;
5590 reply_nterror(req, status);
5591 goto out;
5594 if (is_ntfs_stream_smb_fname(smb_dname)) {
5595 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5596 goto out;
5599 status = SMB_VFS_CREATE_FILE(
5600 conn, /* conn */
5601 req, /* req */
5602 0, /* root_dir_fid */
5603 smb_dname, /* fname */
5604 DELETE_ACCESS, /* access_mask */
5605 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5606 FILE_SHARE_DELETE),
5607 FILE_OPEN, /* create_disposition*/
5608 FILE_DIRECTORY_FILE, /* create_options */
5609 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5610 0, /* oplock_request */
5611 0, /* allocation_size */
5612 0, /* private_flags */
5613 NULL, /* sd */
5614 NULL, /* ea_list */
5615 &fsp, /* result */
5616 &info); /* pinfo */
5618 if (!NT_STATUS_IS_OK(status)) {
5619 if (open_was_deferred(req->mid)) {
5620 /* We have re-scheduled this call. */
5621 goto out;
5623 reply_nterror(req, status);
5624 goto out;
5627 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5628 if (!NT_STATUS_IS_OK(status)) {
5629 close_file(req, fsp, ERROR_CLOSE);
5630 reply_nterror(req, status);
5631 goto out;
5634 if (!set_delete_on_close(fsp, true, &conn->server_info->utok)) {
5635 close_file(req, fsp, ERROR_CLOSE);
5636 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5637 goto out;
5640 status = close_file(req, fsp, NORMAL_CLOSE);
5641 if (!NT_STATUS_IS_OK(status)) {
5642 reply_nterror(req, status);
5643 } else {
5644 reply_outbuf(req, 0, 0);
5647 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5649 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5650 out:
5651 TALLOC_FREE(smb_dname);
5652 END_PROFILE(SMBrmdir);
5653 return;
5656 /*******************************************************************
5657 Resolve wildcards in a filename rename.
5658 ********************************************************************/
5660 static bool resolve_wildcards(TALLOC_CTX *ctx,
5661 const char *name1,
5662 const char *name2,
5663 char **pp_newname)
5665 char *name2_copy = NULL;
5666 char *root1 = NULL;
5667 char *root2 = NULL;
5668 char *ext1 = NULL;
5669 char *ext2 = NULL;
5670 char *p,*p2, *pname1, *pname2;
5672 name2_copy = talloc_strdup(ctx, name2);
5673 if (!name2_copy) {
5674 return False;
5677 pname1 = strrchr_m(name1,'/');
5678 pname2 = strrchr_m(name2_copy,'/');
5680 if (!pname1 || !pname2) {
5681 return False;
5684 /* Truncate the copy of name2 at the last '/' */
5685 *pname2 = '\0';
5687 /* Now go past the '/' */
5688 pname1++;
5689 pname2++;
5691 root1 = talloc_strdup(ctx, pname1);
5692 root2 = talloc_strdup(ctx, pname2);
5694 if (!root1 || !root2) {
5695 return False;
5698 p = strrchr_m(root1,'.');
5699 if (p) {
5700 *p = 0;
5701 ext1 = talloc_strdup(ctx, p+1);
5702 } else {
5703 ext1 = talloc_strdup(ctx, "");
5705 p = strrchr_m(root2,'.');
5706 if (p) {
5707 *p = 0;
5708 ext2 = talloc_strdup(ctx, p+1);
5709 } else {
5710 ext2 = talloc_strdup(ctx, "");
5713 if (!ext1 || !ext2) {
5714 return False;
5717 p = root1;
5718 p2 = root2;
5719 while (*p2) {
5720 if (*p2 == '?') {
5721 /* Hmmm. Should this be mb-aware ? */
5722 *p2 = *p;
5723 p2++;
5724 } else if (*p2 == '*') {
5725 *p2 = '\0';
5726 root2 = talloc_asprintf(ctx, "%s%s",
5727 root2,
5729 if (!root2) {
5730 return False;
5732 break;
5733 } else {
5734 p2++;
5736 if (*p) {
5737 p++;
5741 p = ext1;
5742 p2 = ext2;
5743 while (*p2) {
5744 if (*p2 == '?') {
5745 /* Hmmm. Should this be mb-aware ? */
5746 *p2 = *p;
5747 p2++;
5748 } else if (*p2 == '*') {
5749 *p2 = '\0';
5750 ext2 = talloc_asprintf(ctx, "%s%s",
5751 ext2,
5753 if (!ext2) {
5754 return False;
5756 break;
5757 } else {
5758 p2++;
5760 if (*p) {
5761 p++;
5765 if (*ext2) {
5766 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5767 name2_copy,
5768 root2,
5769 ext2);
5770 } else {
5771 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5772 name2_copy,
5773 root2);
5776 if (!*pp_newname) {
5777 return False;
5780 return True;
5783 /****************************************************************************
5784 Ensure open files have their names updated. Updated to notify other smbd's
5785 asynchronously.
5786 ****************************************************************************/
5788 static void rename_open_files(connection_struct *conn,
5789 struct share_mode_lock *lck,
5790 const struct smb_filename *smb_fname_dst)
5792 files_struct *fsp;
5793 bool did_rename = False;
5794 NTSTATUS status;
5796 for(fsp = file_find_di_first(conn->sconn, lck->id); fsp;
5797 fsp = file_find_di_next(fsp)) {
5798 /* fsp_name is a relative path under the fsp. To change this for other
5799 sharepaths we need to manipulate relative paths. */
5800 /* TODO - create the absolute path and manipulate the newname
5801 relative to the sharepath. */
5802 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5803 continue;
5805 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5806 "(file_id %s) from %s -> %s\n", fsp->fnum,
5807 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5808 smb_fname_str_dbg(smb_fname_dst)));
5810 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5811 if (NT_STATUS_IS_OK(status)) {
5812 did_rename = True;
5816 if (!did_rename) {
5817 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5818 "for %s\n", file_id_string_tos(&lck->id),
5819 smb_fname_str_dbg(smb_fname_dst)));
5822 /* Send messages to all smbd's (not ourself) that the name has changed. */
5823 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5824 smb_fname_dst);
5828 /****************************************************************************
5829 We need to check if the source path is a parent directory of the destination
5830 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5831 refuse the rename with a sharing violation. Under UNIX the above call can
5832 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5833 probably need to check that the client is a Windows one before disallowing
5834 this as a UNIX client (one with UNIX extensions) can know the source is a
5835 symlink and make this decision intelligently. Found by an excellent bug
5836 report from <AndyLiebman@aol.com>.
5837 ****************************************************************************/
5839 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5840 const struct smb_filename *smb_fname_dst)
5842 const char *psrc = smb_fname_src->base_name;
5843 const char *pdst = smb_fname_dst->base_name;
5844 size_t slen;
5846 if (psrc[0] == '.' && psrc[1] == '/') {
5847 psrc += 2;
5849 if (pdst[0] == '.' && pdst[1] == '/') {
5850 pdst += 2;
5852 if ((slen = strlen(psrc)) > strlen(pdst)) {
5853 return False;
5855 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5859 * Do the notify calls from a rename
5862 static void notify_rename(connection_struct *conn, bool is_dir,
5863 const struct smb_filename *smb_fname_src,
5864 const struct smb_filename *smb_fname_dst)
5866 char *parent_dir_src = NULL;
5867 char *parent_dir_dst = NULL;
5868 uint32 mask;
5870 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5871 : FILE_NOTIFY_CHANGE_FILE_NAME;
5873 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5874 &parent_dir_src, NULL) ||
5875 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5876 &parent_dir_dst, NULL)) {
5877 goto out;
5880 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5881 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5882 smb_fname_src->base_name);
5883 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5884 smb_fname_dst->base_name);
5886 else {
5887 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5888 smb_fname_src->base_name);
5889 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5890 smb_fname_dst->base_name);
5893 /* this is a strange one. w2k3 gives an additional event for
5894 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5895 files, but not directories */
5896 if (!is_dir) {
5897 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5898 FILE_NOTIFY_CHANGE_ATTRIBUTES
5899 |FILE_NOTIFY_CHANGE_CREATION,
5900 smb_fname_dst->base_name);
5902 out:
5903 TALLOC_FREE(parent_dir_src);
5904 TALLOC_FREE(parent_dir_dst);
5907 /****************************************************************************
5908 Rename an open file - given an fsp.
5909 ****************************************************************************/
5911 NTSTATUS rename_internals_fsp(connection_struct *conn,
5912 files_struct *fsp,
5913 const struct smb_filename *smb_fname_dst_in,
5914 uint32 attrs,
5915 bool replace_if_exists)
5917 TALLOC_CTX *ctx = talloc_tos();
5918 struct smb_filename *smb_fname_dst = NULL;
5919 NTSTATUS status = NT_STATUS_OK;
5920 struct share_mode_lock *lck = NULL;
5921 bool dst_exists, old_is_stream, new_is_stream;
5923 status = check_name(conn, smb_fname_dst_in->base_name);
5924 if (!NT_STATUS_IS_OK(status)) {
5925 return status;
5928 /* Make a copy of the dst smb_fname structs */
5930 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5931 if (!NT_STATUS_IS_OK(status)) {
5932 goto out;
5935 /* Ensure the dst smb_fname contains a '/' */
5936 if(strrchr_m(smb_fname_dst->base_name,'/') == 0) {
5937 char * tmp;
5938 tmp = talloc_asprintf(smb_fname_dst, "./%s",
5939 smb_fname_dst->base_name);
5940 if (!tmp) {
5941 status = NT_STATUS_NO_MEMORY;
5942 goto out;
5944 TALLOC_FREE(smb_fname_dst->base_name);
5945 smb_fname_dst->base_name = tmp;
5949 * Check for special case with case preserving and not
5950 * case sensitive. If the old last component differs from the original
5951 * last component only by case, then we should allow
5952 * the rename (user is trying to change the case of the
5953 * filename).
5955 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5956 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5957 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
5958 char *last_slash;
5959 char *fname_dst_lcomp_base_mod = NULL;
5960 struct smb_filename *smb_fname_orig_lcomp = NULL;
5963 * Get the last component of the destination name. Note that
5964 * we guarantee that destination name contains a '/' character
5965 * above.
5967 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5968 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5969 if (!fname_dst_lcomp_base_mod) {
5970 status = NT_STATUS_NO_MEMORY;
5971 goto out;
5975 * Create an smb_filename struct using the original last
5976 * component of the destination.
5978 status = create_synthetic_smb_fname_split(ctx,
5979 smb_fname_dst->original_lcomp, NULL,
5980 &smb_fname_orig_lcomp);
5981 if (!NT_STATUS_IS_OK(status)) {
5982 TALLOC_FREE(fname_dst_lcomp_base_mod);
5983 goto out;
5986 /* If the base names only differ by case, use original. */
5987 if(!strcsequal(fname_dst_lcomp_base_mod,
5988 smb_fname_orig_lcomp->base_name)) {
5989 char *tmp;
5991 * Replace the modified last component with the
5992 * original.
5994 *last_slash = '\0'; /* Truncate at the '/' */
5995 tmp = talloc_asprintf(smb_fname_dst,
5996 "%s/%s",
5997 smb_fname_dst->base_name,
5998 smb_fname_orig_lcomp->base_name);
5999 if (tmp == NULL) {
6000 status = NT_STATUS_NO_MEMORY;
6001 TALLOC_FREE(fname_dst_lcomp_base_mod);
6002 TALLOC_FREE(smb_fname_orig_lcomp);
6003 goto out;
6005 TALLOC_FREE(smb_fname_dst->base_name);
6006 smb_fname_dst->base_name = tmp;
6009 /* If the stream_names only differ by case, use original. */
6010 if(!strcsequal(smb_fname_dst->stream_name,
6011 smb_fname_orig_lcomp->stream_name)) {
6012 char *tmp = NULL;
6013 /* Use the original stream. */
6014 tmp = talloc_strdup(smb_fname_dst,
6015 smb_fname_orig_lcomp->stream_name);
6016 if (tmp == NULL) {
6017 status = NT_STATUS_NO_MEMORY;
6018 TALLOC_FREE(fname_dst_lcomp_base_mod);
6019 TALLOC_FREE(smb_fname_orig_lcomp);
6020 goto out;
6022 TALLOC_FREE(smb_fname_dst->stream_name);
6023 smb_fname_dst->stream_name = tmp;
6025 TALLOC_FREE(fname_dst_lcomp_base_mod);
6026 TALLOC_FREE(smb_fname_orig_lcomp);
6030 * If the src and dest names are identical - including case,
6031 * don't do the rename, just return success.
6034 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6035 strcsequal(fsp->fsp_name->stream_name,
6036 smb_fname_dst->stream_name)) {
6037 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6038 "- returning success\n",
6039 smb_fname_str_dbg(smb_fname_dst)));
6040 status = NT_STATUS_OK;
6041 goto out;
6044 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6045 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6047 /* Return the correct error code if both names aren't streams. */
6048 if (!old_is_stream && new_is_stream) {
6049 status = NT_STATUS_OBJECT_NAME_INVALID;
6050 goto out;
6053 if (old_is_stream && !new_is_stream) {
6054 status = NT_STATUS_INVALID_PARAMETER;
6055 goto out;
6058 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6060 if(!replace_if_exists && dst_exists) {
6061 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6062 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6063 smb_fname_str_dbg(smb_fname_dst)));
6064 status = NT_STATUS_OBJECT_NAME_COLLISION;
6065 goto out;
6068 if (dst_exists) {
6069 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6070 &smb_fname_dst->st);
6071 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6072 fileid);
6073 /* The file can be open when renaming a stream */
6074 if (dst_fsp && !new_is_stream) {
6075 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6076 status = NT_STATUS_ACCESS_DENIED;
6077 goto out;
6081 /* Ensure we have a valid stat struct for the source. */
6082 status = vfs_stat_fsp(fsp);
6083 if (!NT_STATUS_IS_OK(status)) {
6084 goto out;
6087 status = can_rename(conn, fsp, attrs);
6089 if (!NT_STATUS_IS_OK(status)) {
6090 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6091 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6092 smb_fname_str_dbg(smb_fname_dst)));
6093 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6094 status = NT_STATUS_ACCESS_DENIED;
6095 goto out;
6098 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6099 status = NT_STATUS_ACCESS_DENIED;
6102 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6103 NULL);
6106 * We have the file open ourselves, so not being able to get the
6107 * corresponding share mode lock is a fatal error.
6110 SMB_ASSERT(lck != NULL);
6112 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6113 uint32 create_options = fsp->fh->private_options;
6115 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6116 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6117 smb_fname_str_dbg(smb_fname_dst)));
6119 if (!lp_posix_pathnames() &&
6120 (lp_map_archive(SNUM(conn)) ||
6121 lp_store_dos_attributes(SNUM(conn)))) {
6122 /* We must set the archive bit on the newly
6123 renamed file. */
6124 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6125 uint32_t old_dosmode = dos_mode(conn,
6126 smb_fname_dst);
6127 file_set_dosmode(conn,
6128 smb_fname_dst,
6129 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6130 NULL,
6131 true);
6135 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6136 smb_fname_dst);
6138 rename_open_files(conn, lck, smb_fname_dst);
6141 * A rename acts as a new file create w.r.t. allowing an initial delete
6142 * on close, probably because in Windows there is a new handle to the
6143 * new file. If initial delete on close was requested but not
6144 * originally set, we need to set it here. This is probably not 100% correct,
6145 * but will work for the CIFSFS client which in non-posix mode
6146 * depends on these semantics. JRA.
6149 if (create_options & FILE_DELETE_ON_CLOSE) {
6150 status = can_set_delete_on_close(fsp, 0);
6152 if (NT_STATUS_IS_OK(status)) {
6153 /* Note that here we set the *inital* delete on close flag,
6154 * not the regular one. The magic gets handled in close. */
6155 fsp->initial_delete_on_close = True;
6158 TALLOC_FREE(lck);
6159 status = NT_STATUS_OK;
6160 goto out;
6163 TALLOC_FREE(lck);
6165 if (errno == ENOTDIR || errno == EISDIR) {
6166 status = NT_STATUS_OBJECT_NAME_COLLISION;
6167 } else {
6168 status = map_nt_error_from_unix(errno);
6171 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6172 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6173 smb_fname_str_dbg(smb_fname_dst)));
6175 out:
6176 TALLOC_FREE(smb_fname_dst);
6178 return status;
6181 /****************************************************************************
6182 The guts of the rename command, split out so it may be called by the NT SMB
6183 code.
6184 ****************************************************************************/
6186 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6187 connection_struct *conn,
6188 struct smb_request *req,
6189 struct smb_filename *smb_fname_src,
6190 struct smb_filename *smb_fname_dst,
6191 uint32 attrs,
6192 bool replace_if_exists,
6193 bool src_has_wild,
6194 bool dest_has_wild,
6195 uint32_t access_mask)
6197 char *fname_src_dir = NULL;
6198 char *fname_src_mask = NULL;
6199 int count=0;
6200 NTSTATUS status = NT_STATUS_OK;
6201 struct smb_Dir *dir_hnd = NULL;
6202 const char *dname = NULL;
6203 char *talloced = NULL;
6204 long offset = 0;
6205 int create_options = 0;
6206 bool posix_pathnames = lp_posix_pathnames();
6209 * Split the old name into directory and last component
6210 * strings. Note that unix_convert may have stripped off a
6211 * leading ./ from both name and newname if the rename is
6212 * at the root of the share. We need to make sure either both
6213 * name and newname contain a / character or neither of them do
6214 * as this is checked in resolve_wildcards().
6217 /* Split up the directory from the filename/mask. */
6218 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6219 &fname_src_dir, &fname_src_mask);
6220 if (!NT_STATUS_IS_OK(status)) {
6221 status = NT_STATUS_NO_MEMORY;
6222 goto out;
6226 * We should only check the mangled cache
6227 * here if unix_convert failed. This means
6228 * that the path in 'mask' doesn't exist
6229 * on the file system and so we need to look
6230 * for a possible mangle. This patch from
6231 * Tine Smukavec <valentin.smukavec@hermes.si>.
6234 if (!VALID_STAT(smb_fname_src->st) &&
6235 mangle_is_mangled(fname_src_mask, conn->params)) {
6236 char *new_mask = NULL;
6237 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6238 conn->params);
6239 if (new_mask) {
6240 TALLOC_FREE(fname_src_mask);
6241 fname_src_mask = new_mask;
6245 if (!src_has_wild) {
6246 files_struct *fsp;
6249 * Only one file needs to be renamed. Append the mask back
6250 * onto the directory.
6252 TALLOC_FREE(smb_fname_src->base_name);
6253 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6254 "%s/%s",
6255 fname_src_dir,
6256 fname_src_mask);
6257 if (!smb_fname_src->base_name) {
6258 status = NT_STATUS_NO_MEMORY;
6259 goto out;
6262 /* Ensure dst fname contains a '/' also */
6263 if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
6264 char *tmp;
6265 tmp = talloc_asprintf(smb_fname_dst, "./%s",
6266 smb_fname_dst->base_name);
6267 if (!tmp) {
6268 status = NT_STATUS_NO_MEMORY;
6269 goto out;
6271 TALLOC_FREE(smb_fname_dst->base_name);
6272 smb_fname_dst->base_name = tmp;
6275 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6276 "case_preserve = %d, short case preserve = %d, "
6277 "directory = %s, newname = %s, "
6278 "last_component_dest = %s\n",
6279 conn->case_sensitive, conn->case_preserve,
6280 conn->short_case_preserve,
6281 smb_fname_str_dbg(smb_fname_src),
6282 smb_fname_str_dbg(smb_fname_dst),
6283 smb_fname_dst->original_lcomp));
6285 /* The dest name still may have wildcards. */
6286 if (dest_has_wild) {
6287 char *fname_dst_mod = NULL;
6288 if (!resolve_wildcards(smb_fname_dst,
6289 smb_fname_src->base_name,
6290 smb_fname_dst->base_name,
6291 &fname_dst_mod)) {
6292 DEBUG(6, ("rename_internals: resolve_wildcards "
6293 "%s %s failed\n",
6294 smb_fname_src->base_name,
6295 smb_fname_dst->base_name));
6296 status = NT_STATUS_NO_MEMORY;
6297 goto out;
6299 TALLOC_FREE(smb_fname_dst->base_name);
6300 smb_fname_dst->base_name = fname_dst_mod;
6303 ZERO_STRUCT(smb_fname_src->st);
6304 if (posix_pathnames) {
6305 SMB_VFS_LSTAT(conn, smb_fname_src);
6306 } else {
6307 SMB_VFS_STAT(conn, smb_fname_src);
6310 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6311 create_options |= FILE_DIRECTORY_FILE;
6314 status = SMB_VFS_CREATE_FILE(
6315 conn, /* conn */
6316 req, /* req */
6317 0, /* root_dir_fid */
6318 smb_fname_src, /* fname */
6319 access_mask, /* access_mask */
6320 (FILE_SHARE_READ | /* share_access */
6321 FILE_SHARE_WRITE),
6322 FILE_OPEN, /* create_disposition*/
6323 create_options, /* create_options */
6324 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6325 0, /* oplock_request */
6326 0, /* allocation_size */
6327 0, /* private_flags */
6328 NULL, /* sd */
6329 NULL, /* ea_list */
6330 &fsp, /* result */
6331 NULL); /* pinfo */
6333 if (!NT_STATUS_IS_OK(status)) {
6334 DEBUG(3, ("Could not open rename source %s: %s\n",
6335 smb_fname_str_dbg(smb_fname_src),
6336 nt_errstr(status)));
6337 goto out;
6340 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6341 attrs, replace_if_exists);
6343 close_file(req, fsp, NORMAL_CLOSE);
6345 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6346 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6347 smb_fname_str_dbg(smb_fname_dst)));
6349 goto out;
6353 * Wildcards - process each file that matches.
6355 if (strequal(fname_src_mask, "????????.???")) {
6356 TALLOC_FREE(fname_src_mask);
6357 fname_src_mask = talloc_strdup(ctx, "*");
6358 if (!fname_src_mask) {
6359 status = NT_STATUS_NO_MEMORY;
6360 goto out;
6364 status = check_name(conn, fname_src_dir);
6365 if (!NT_STATUS_IS_OK(status)) {
6366 goto out;
6369 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6370 attrs);
6371 if (dir_hnd == NULL) {
6372 status = map_nt_error_from_unix(errno);
6373 goto out;
6376 status = NT_STATUS_NO_SUCH_FILE;
6378 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6379 * - gentest fix. JRA
6382 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6383 &talloced))) {
6384 files_struct *fsp = NULL;
6385 char *destname = NULL;
6386 bool sysdir_entry = False;
6388 /* Quick check for "." and ".." */
6389 if (ISDOT(dname) || ISDOTDOT(dname)) {
6390 if (attrs & aDIR) {
6391 sysdir_entry = True;
6392 } else {
6393 TALLOC_FREE(talloced);
6394 continue;
6398 if (!is_visible_file(conn, fname_src_dir, dname,
6399 &smb_fname_src->st, false)) {
6400 TALLOC_FREE(talloced);
6401 continue;
6404 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6405 TALLOC_FREE(talloced);
6406 continue;
6409 if (sysdir_entry) {
6410 status = NT_STATUS_OBJECT_NAME_INVALID;
6411 break;
6414 TALLOC_FREE(smb_fname_src->base_name);
6415 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6416 "%s/%s",
6417 fname_src_dir,
6418 dname);
6419 if (!smb_fname_src->base_name) {
6420 status = NT_STATUS_NO_MEMORY;
6421 goto out;
6424 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6425 smb_fname_dst->base_name,
6426 &destname)) {
6427 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6428 smb_fname_src->base_name, destname));
6429 TALLOC_FREE(talloced);
6430 continue;
6432 if (!destname) {
6433 status = NT_STATUS_NO_MEMORY;
6434 goto out;
6437 TALLOC_FREE(smb_fname_dst->base_name);
6438 smb_fname_dst->base_name = destname;
6440 ZERO_STRUCT(smb_fname_src->st);
6441 if (posix_pathnames) {
6442 SMB_VFS_LSTAT(conn, smb_fname_src);
6443 } else {
6444 SMB_VFS_STAT(conn, smb_fname_src);
6447 create_options = 0;
6449 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6450 create_options |= FILE_DIRECTORY_FILE;
6453 status = SMB_VFS_CREATE_FILE(
6454 conn, /* conn */
6455 req, /* req */
6456 0, /* root_dir_fid */
6457 smb_fname_src, /* fname */
6458 access_mask, /* access_mask */
6459 (FILE_SHARE_READ | /* share_access */
6460 FILE_SHARE_WRITE),
6461 FILE_OPEN, /* create_disposition*/
6462 create_options, /* create_options */
6463 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6464 0, /* oplock_request */
6465 0, /* allocation_size */
6466 0, /* private_flags */
6467 NULL, /* sd */
6468 NULL, /* ea_list */
6469 &fsp, /* result */
6470 NULL); /* pinfo */
6472 if (!NT_STATUS_IS_OK(status)) {
6473 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6474 "returned %s rename %s -> %s\n",
6475 nt_errstr(status),
6476 smb_fname_str_dbg(smb_fname_src),
6477 smb_fname_str_dbg(smb_fname_dst)));
6478 break;
6481 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6482 dname);
6483 if (!smb_fname_dst->original_lcomp) {
6484 status = NT_STATUS_NO_MEMORY;
6485 goto out;
6488 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6489 attrs, replace_if_exists);
6491 close_file(req, fsp, NORMAL_CLOSE);
6493 if (!NT_STATUS_IS_OK(status)) {
6494 DEBUG(3, ("rename_internals_fsp returned %s for "
6495 "rename %s -> %s\n", nt_errstr(status),
6496 smb_fname_str_dbg(smb_fname_src),
6497 smb_fname_str_dbg(smb_fname_dst)));
6498 break;
6501 count++;
6503 DEBUG(3,("rename_internals: doing rename on %s -> "
6504 "%s\n", smb_fname_str_dbg(smb_fname_src),
6505 smb_fname_str_dbg(smb_fname_src)));
6506 TALLOC_FREE(talloced);
6508 TALLOC_FREE(dir_hnd);
6510 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6511 status = map_nt_error_from_unix(errno);
6514 out:
6515 TALLOC_FREE(talloced);
6516 TALLOC_FREE(fname_src_dir);
6517 TALLOC_FREE(fname_src_mask);
6518 return status;
6521 /****************************************************************************
6522 Reply to a mv.
6523 ****************************************************************************/
6525 void reply_mv(struct smb_request *req)
6527 connection_struct *conn = req->conn;
6528 char *name = NULL;
6529 char *newname = NULL;
6530 const char *p;
6531 uint32 attrs;
6532 NTSTATUS status;
6533 bool src_has_wcard = False;
6534 bool dest_has_wcard = False;
6535 TALLOC_CTX *ctx = talloc_tos();
6536 struct smb_filename *smb_fname_src = NULL;
6537 struct smb_filename *smb_fname_dst = NULL;
6539 START_PROFILE(SMBmv);
6541 if (req->wct < 1) {
6542 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6543 goto out;
6546 attrs = SVAL(req->vwv+0, 0);
6548 p = (const char *)req->buf + 1;
6549 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6550 &status, &src_has_wcard);
6551 if (!NT_STATUS_IS_OK(status)) {
6552 reply_nterror(req, status);
6553 goto out;
6555 p++;
6556 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6557 &status, &dest_has_wcard);
6558 if (!NT_STATUS_IS_OK(status)) {
6559 reply_nterror(req, status);
6560 goto out;
6563 status = filename_convert(ctx,
6564 conn,
6565 req->flags2 & FLAGS2_DFS_PATHNAMES,
6566 name,
6567 UCF_COND_ALLOW_WCARD_LCOMP,
6568 &src_has_wcard,
6569 &smb_fname_src);
6571 if (!NT_STATUS_IS_OK(status)) {
6572 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6573 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6574 ERRSRV, ERRbadpath);
6575 goto out;
6577 reply_nterror(req, status);
6578 goto out;
6581 status = filename_convert(ctx,
6582 conn,
6583 req->flags2 & FLAGS2_DFS_PATHNAMES,
6584 newname,
6585 UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6586 &dest_has_wcard,
6587 &smb_fname_dst);
6589 if (!NT_STATUS_IS_OK(status)) {
6590 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6591 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6592 ERRSRV, ERRbadpath);
6593 goto out;
6595 reply_nterror(req, status);
6596 goto out;
6599 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6600 smb_fname_str_dbg(smb_fname_dst)));
6602 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6603 attrs, False, src_has_wcard, dest_has_wcard,
6604 DELETE_ACCESS);
6605 if (!NT_STATUS_IS_OK(status)) {
6606 if (open_was_deferred(req->mid)) {
6607 /* We have re-scheduled this call. */
6608 goto out;
6610 reply_nterror(req, status);
6611 goto out;
6614 reply_outbuf(req, 0, 0);
6615 out:
6616 TALLOC_FREE(smb_fname_src);
6617 TALLOC_FREE(smb_fname_dst);
6618 END_PROFILE(SMBmv);
6619 return;
6622 /*******************************************************************
6623 Copy a file as part of a reply_copy.
6624 ******************************************************************/
6627 * TODO: check error codes on all callers
6630 NTSTATUS copy_file(TALLOC_CTX *ctx,
6631 connection_struct *conn,
6632 struct smb_filename *smb_fname_src,
6633 struct smb_filename *smb_fname_dst,
6634 int ofun,
6635 int count,
6636 bool target_is_directory)
6638 struct smb_filename *smb_fname_dst_tmp = NULL;
6639 SMB_OFF_T ret=-1;
6640 files_struct *fsp1,*fsp2;
6641 uint32 dosattrs;
6642 uint32 new_create_disposition;
6643 NTSTATUS status;
6646 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6647 if (!NT_STATUS_IS_OK(status)) {
6648 return status;
6652 * If the target is a directory, extract the last component from the
6653 * src filename and append it to the dst filename
6655 if (target_is_directory) {
6656 const char *p;
6658 /* dest/target can't be a stream if it's a directory. */
6659 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6661 p = strrchr_m(smb_fname_src->base_name,'/');
6662 if (p) {
6663 p++;
6664 } else {
6665 p = smb_fname_src->base_name;
6667 smb_fname_dst_tmp->base_name =
6668 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6670 if (!smb_fname_dst_tmp->base_name) {
6671 status = NT_STATUS_NO_MEMORY;
6672 goto out;
6676 status = vfs_file_exist(conn, smb_fname_src);
6677 if (!NT_STATUS_IS_OK(status)) {
6678 goto out;
6681 if (!target_is_directory && count) {
6682 new_create_disposition = FILE_OPEN;
6683 } else {
6684 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
6685 NULL, NULL,
6686 &new_create_disposition,
6687 NULL,
6688 NULL)) {
6689 status = NT_STATUS_INVALID_PARAMETER;
6690 goto out;
6694 /* Open the src file for reading. */
6695 status = SMB_VFS_CREATE_FILE(
6696 conn, /* conn */
6697 NULL, /* req */
6698 0, /* root_dir_fid */
6699 smb_fname_src, /* fname */
6700 FILE_GENERIC_READ, /* access_mask */
6701 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6702 FILE_OPEN, /* create_disposition*/
6703 0, /* create_options */
6704 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6705 INTERNAL_OPEN_ONLY, /* oplock_request */
6706 0, /* allocation_size */
6707 0, /* private_flags */
6708 NULL, /* sd */
6709 NULL, /* ea_list */
6710 &fsp1, /* result */
6711 NULL); /* psbuf */
6713 if (!NT_STATUS_IS_OK(status)) {
6714 goto out;
6717 dosattrs = dos_mode(conn, smb_fname_src);
6719 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6720 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6723 /* Open the dst file for writing. */
6724 status = SMB_VFS_CREATE_FILE(
6725 conn, /* conn */
6726 NULL, /* req */
6727 0, /* root_dir_fid */
6728 smb_fname_dst, /* fname */
6729 FILE_GENERIC_WRITE, /* access_mask */
6730 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6731 new_create_disposition, /* create_disposition*/
6732 0, /* create_options */
6733 dosattrs, /* file_attributes */
6734 INTERNAL_OPEN_ONLY, /* oplock_request */
6735 0, /* allocation_size */
6736 0, /* private_flags */
6737 NULL, /* sd */
6738 NULL, /* ea_list */
6739 &fsp2, /* result */
6740 NULL); /* psbuf */
6742 if (!NT_STATUS_IS_OK(status)) {
6743 close_file(NULL, fsp1, ERROR_CLOSE);
6744 goto out;
6747 if ((ofun&3) == 1) {
6748 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6749 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6751 * Stop the copy from occurring.
6753 ret = -1;
6754 smb_fname_src->st.st_ex_size = 0;
6758 /* Do the actual copy. */
6759 if (smb_fname_src->st.st_ex_size) {
6760 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6763 close_file(NULL, fsp1, NORMAL_CLOSE);
6765 /* Ensure the modtime is set correctly on the destination file. */
6766 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6769 * As we are opening fsp1 read-only we only expect
6770 * an error on close on fsp2 if we are out of space.
6771 * Thus we don't look at the error return from the
6772 * close of fsp1.
6774 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6776 if (!NT_STATUS_IS_OK(status)) {
6777 goto out;
6780 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6781 status = NT_STATUS_DISK_FULL;
6782 goto out;
6785 status = NT_STATUS_OK;
6787 out:
6788 TALLOC_FREE(smb_fname_dst_tmp);
6789 return status;
6792 /****************************************************************************
6793 Reply to a file copy.
6794 ****************************************************************************/
6796 void reply_copy(struct smb_request *req)
6798 connection_struct *conn = req->conn;
6799 struct smb_filename *smb_fname_src = NULL;
6800 struct smb_filename *smb_fname_dst = NULL;
6801 char *fname_src = NULL;
6802 char *fname_dst = NULL;
6803 char *fname_src_mask = NULL;
6804 char *fname_src_dir = NULL;
6805 const char *p;
6806 int count=0;
6807 int error = ERRnoaccess;
6808 int tid2;
6809 int ofun;
6810 int flags;
6811 bool target_is_directory=False;
6812 bool source_has_wild = False;
6813 bool dest_has_wild = False;
6814 NTSTATUS status;
6815 TALLOC_CTX *ctx = talloc_tos();
6817 START_PROFILE(SMBcopy);
6819 if (req->wct < 3) {
6820 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6821 goto out;
6824 tid2 = SVAL(req->vwv+0, 0);
6825 ofun = SVAL(req->vwv+1, 0);
6826 flags = SVAL(req->vwv+2, 0);
6828 p = (const char *)req->buf;
6829 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6830 &status, &source_has_wild);
6831 if (!NT_STATUS_IS_OK(status)) {
6832 reply_nterror(req, status);
6833 goto out;
6835 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6836 &status, &dest_has_wild);
6837 if (!NT_STATUS_IS_OK(status)) {
6838 reply_nterror(req, status);
6839 goto out;
6842 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6844 if (tid2 != conn->cnum) {
6845 /* can't currently handle inter share copies XXXX */
6846 DEBUG(3,("Rejecting inter-share copy\n"));
6847 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6848 goto out;
6851 status = filename_convert(ctx, conn,
6852 req->flags2 & FLAGS2_DFS_PATHNAMES,
6853 fname_src,
6854 UCF_COND_ALLOW_WCARD_LCOMP,
6855 &source_has_wild,
6856 &smb_fname_src);
6857 if (!NT_STATUS_IS_OK(status)) {
6858 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6859 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6860 ERRSRV, ERRbadpath);
6861 goto out;
6863 reply_nterror(req, status);
6864 goto out;
6867 status = filename_convert(ctx, conn,
6868 req->flags2 & FLAGS2_DFS_PATHNAMES,
6869 fname_dst,
6870 UCF_COND_ALLOW_WCARD_LCOMP,
6871 &dest_has_wild,
6872 &smb_fname_dst);
6873 if (!NT_STATUS_IS_OK(status)) {
6874 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6875 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6876 ERRSRV, ERRbadpath);
6877 goto out;
6879 reply_nterror(req, status);
6880 goto out;
6883 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6885 if ((flags&1) && target_is_directory) {
6886 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6887 goto out;
6890 if ((flags&2) && !target_is_directory) {
6891 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
6892 goto out;
6895 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6896 /* wants a tree copy! XXXX */
6897 DEBUG(3,("Rejecting tree copy\n"));
6898 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6899 goto out;
6902 /* Split up the directory from the filename/mask. */
6903 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6904 &fname_src_dir, &fname_src_mask);
6905 if (!NT_STATUS_IS_OK(status)) {
6906 reply_nterror(req, NT_STATUS_NO_MEMORY);
6907 goto out;
6911 * We should only check the mangled cache
6912 * here if unix_convert failed. This means
6913 * that the path in 'mask' doesn't exist
6914 * on the file system and so we need to look
6915 * for a possible mangle. This patch from
6916 * Tine Smukavec <valentin.smukavec@hermes.si>.
6918 if (!VALID_STAT(smb_fname_src->st) &&
6919 mangle_is_mangled(fname_src_mask, conn->params)) {
6920 char *new_mask = NULL;
6921 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6922 &new_mask, conn->params);
6924 /* Use demangled name if one was successfully found. */
6925 if (new_mask) {
6926 TALLOC_FREE(fname_src_mask);
6927 fname_src_mask = new_mask;
6931 if (!source_has_wild) {
6934 * Only one file needs to be copied. Append the mask back onto
6935 * the directory.
6937 TALLOC_FREE(smb_fname_src->base_name);
6938 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6939 "%s/%s",
6940 fname_src_dir,
6941 fname_src_mask);
6942 if (!smb_fname_src->base_name) {
6943 reply_nterror(req, NT_STATUS_NO_MEMORY);
6944 goto out;
6947 if (dest_has_wild) {
6948 char *fname_dst_mod = NULL;
6949 if (!resolve_wildcards(smb_fname_dst,
6950 smb_fname_src->base_name,
6951 smb_fname_dst->base_name,
6952 &fname_dst_mod)) {
6953 reply_nterror(req, NT_STATUS_NO_MEMORY);
6954 goto out;
6956 TALLOC_FREE(smb_fname_dst->base_name);
6957 smb_fname_dst->base_name = fname_dst_mod;
6960 status = check_name(conn, smb_fname_src->base_name);
6961 if (!NT_STATUS_IS_OK(status)) {
6962 reply_nterror(req, status);
6963 goto out;
6966 status = check_name(conn, smb_fname_dst->base_name);
6967 if (!NT_STATUS_IS_OK(status)) {
6968 reply_nterror(req, status);
6969 goto out;
6972 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
6973 ofun, count, target_is_directory);
6975 if(!NT_STATUS_IS_OK(status)) {
6976 reply_nterror(req, status);
6977 goto out;
6978 } else {
6979 count++;
6981 } else {
6982 struct smb_Dir *dir_hnd = NULL;
6983 const char *dname = NULL;
6984 char *talloced = NULL;
6985 long offset = 0;
6988 * There is a wildcard that requires us to actually read the
6989 * src dir and copy each file matching the mask to the dst.
6990 * Right now streams won't be copied, but this could
6991 * presumably be added with a nested loop for reach dir entry.
6993 SMB_ASSERT(!smb_fname_src->stream_name);
6994 SMB_ASSERT(!smb_fname_dst->stream_name);
6996 smb_fname_src->stream_name = NULL;
6997 smb_fname_dst->stream_name = NULL;
6999 if (strequal(fname_src_mask,"????????.???")) {
7000 TALLOC_FREE(fname_src_mask);
7001 fname_src_mask = talloc_strdup(ctx, "*");
7002 if (!fname_src_mask) {
7003 reply_nterror(req, NT_STATUS_NO_MEMORY);
7004 goto out;
7008 status = check_name(conn, fname_src_dir);
7009 if (!NT_STATUS_IS_OK(status)) {
7010 reply_nterror(req, status);
7011 goto out;
7014 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7015 if (dir_hnd == NULL) {
7016 status = map_nt_error_from_unix(errno);
7017 reply_nterror(req, status);
7018 goto out;
7021 error = ERRbadfile;
7023 /* Iterate over the src dir copying each entry to the dst. */
7024 while ((dname = ReadDirName(dir_hnd, &offset,
7025 &smb_fname_src->st, &talloced))) {
7026 char *destname = NULL;
7028 if (ISDOT(dname) || ISDOTDOT(dname)) {
7029 TALLOC_FREE(talloced);
7030 continue;
7033 if (!is_visible_file(conn, fname_src_dir, dname,
7034 &smb_fname_src->st, false)) {
7035 TALLOC_FREE(talloced);
7036 continue;
7039 if(!mask_match(dname, fname_src_mask,
7040 conn->case_sensitive)) {
7041 TALLOC_FREE(talloced);
7042 continue;
7045 error = ERRnoaccess;
7047 /* Get the src smb_fname struct setup. */
7048 TALLOC_FREE(smb_fname_src->base_name);
7049 smb_fname_src->base_name =
7050 talloc_asprintf(smb_fname_src, "%s/%s",
7051 fname_src_dir, dname);
7053 if (!smb_fname_src->base_name) {
7054 TALLOC_FREE(dir_hnd);
7055 TALLOC_FREE(talloced);
7056 reply_nterror(req, NT_STATUS_NO_MEMORY);
7057 goto out;
7060 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7061 smb_fname_dst->base_name,
7062 &destname)) {
7063 TALLOC_FREE(talloced);
7064 continue;
7066 if (!destname) {
7067 TALLOC_FREE(dir_hnd);
7068 TALLOC_FREE(talloced);
7069 reply_nterror(req, NT_STATUS_NO_MEMORY);
7070 goto out;
7073 TALLOC_FREE(smb_fname_dst->base_name);
7074 smb_fname_dst->base_name = destname;
7076 status = check_name(conn, smb_fname_src->base_name);
7077 if (!NT_STATUS_IS_OK(status)) {
7078 TALLOC_FREE(dir_hnd);
7079 TALLOC_FREE(talloced);
7080 reply_nterror(req, status);
7081 goto out;
7084 status = check_name(conn, smb_fname_dst->base_name);
7085 if (!NT_STATUS_IS_OK(status)) {
7086 TALLOC_FREE(dir_hnd);
7087 TALLOC_FREE(talloced);
7088 reply_nterror(req, status);
7089 goto out;
7092 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7093 smb_fname_src->base_name,
7094 smb_fname_dst->base_name));
7096 status = copy_file(ctx, conn, smb_fname_src,
7097 smb_fname_dst, ofun, count,
7098 target_is_directory);
7099 if (NT_STATUS_IS_OK(status)) {
7100 count++;
7103 TALLOC_FREE(talloced);
7105 TALLOC_FREE(dir_hnd);
7108 if (count == 0) {
7109 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7110 goto out;
7113 reply_outbuf(req, 1, 0);
7114 SSVAL(req->outbuf,smb_vwv0,count);
7115 out:
7116 TALLOC_FREE(smb_fname_src);
7117 TALLOC_FREE(smb_fname_dst);
7118 TALLOC_FREE(fname_src);
7119 TALLOC_FREE(fname_dst);
7120 TALLOC_FREE(fname_src_mask);
7121 TALLOC_FREE(fname_src_dir);
7123 END_PROFILE(SMBcopy);
7124 return;
7127 #undef DBGC_CLASS
7128 #define DBGC_CLASS DBGC_LOCKING
7130 /****************************************************************************
7131 Get a lock pid, dealing with large count requests.
7132 ****************************************************************************/
7134 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7135 bool large_file_format)
7137 if(!large_file_format)
7138 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7139 else
7140 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7143 /****************************************************************************
7144 Get a lock count, dealing with large count requests.
7145 ****************************************************************************/
7147 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7148 bool large_file_format)
7150 uint64_t count = 0;
7152 if(!large_file_format) {
7153 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7154 } else {
7156 #if defined(HAVE_LONGLONG)
7157 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7158 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7159 #else /* HAVE_LONGLONG */
7162 * NT4.x seems to be broken in that it sends large file (64 bit)
7163 * lockingX calls even if the CAP_LARGE_FILES was *not*
7164 * negotiated. For boxes without large unsigned ints truncate the
7165 * lock count by dropping the top 32 bits.
7168 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7169 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7170 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7171 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7172 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7175 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7176 #endif /* HAVE_LONGLONG */
7179 return count;
7182 #if !defined(HAVE_LONGLONG)
7183 /****************************************************************************
7184 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7185 ****************************************************************************/
7187 static uint32 map_lock_offset(uint32 high, uint32 low)
7189 unsigned int i;
7190 uint32 mask = 0;
7191 uint32 highcopy = high;
7194 * Try and find out how many significant bits there are in high.
7197 for(i = 0; highcopy; i++)
7198 highcopy >>= 1;
7201 * We use 31 bits not 32 here as POSIX
7202 * lock offsets may not be negative.
7205 mask = (~0) << (31 - i);
7207 if(low & mask)
7208 return 0; /* Fail. */
7210 high <<= (31 - i);
7212 return (high|low);
7214 #endif /* !defined(HAVE_LONGLONG) */
7216 /****************************************************************************
7217 Get a lock offset, dealing with large offset requests.
7218 ****************************************************************************/
7220 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7221 bool large_file_format, bool *err)
7223 uint64_t offset = 0;
7225 *err = False;
7227 if(!large_file_format) {
7228 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7229 } else {
7231 #if defined(HAVE_LONGLONG)
7232 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7233 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7234 #else /* HAVE_LONGLONG */
7237 * NT4.x seems to be broken in that it sends large file (64 bit)
7238 * lockingX calls even if the CAP_LARGE_FILES was *not*
7239 * negotiated. For boxes without large unsigned ints mangle the
7240 * lock offset by mapping the top 32 bits onto the lower 32.
7243 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7244 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7245 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7246 uint32 new_low = 0;
7248 if((new_low = map_lock_offset(high, low)) == 0) {
7249 *err = True;
7250 return (uint64_t)-1;
7253 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7254 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7255 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7256 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7259 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7260 #endif /* HAVE_LONGLONG */
7263 return offset;
7266 NTSTATUS smbd_do_locking(struct smb_request *req,
7267 files_struct *fsp,
7268 uint8_t type,
7269 int32_t timeout,
7270 uint16_t num_ulocks,
7271 struct smbd_lock_element *ulocks,
7272 uint16_t num_locks,
7273 struct smbd_lock_element *locks,
7274 bool *async)
7276 connection_struct *conn = req->conn;
7277 int i;
7278 NTSTATUS status = NT_STATUS_OK;
7280 *async = false;
7282 /* Data now points at the beginning of the list
7283 of smb_unlkrng structs */
7284 for(i = 0; i < (int)num_ulocks; i++) {
7285 struct smbd_lock_element *e = &ulocks[i];
7287 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7288 "pid %u, file %s\n",
7289 (double)e->offset,
7290 (double)e->count,
7291 (unsigned int)e->smblctx,
7292 fsp_str_dbg(fsp)));
7294 if (e->brltype != UNLOCK_LOCK) {
7295 /* this can only happen with SMB2 */
7296 return NT_STATUS_INVALID_PARAMETER;
7299 status = do_unlock(req->sconn->msg_ctx,
7300 fsp,
7301 e->smblctx,
7302 e->count,
7303 e->offset,
7304 WINDOWS_LOCK);
7306 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7307 nt_errstr(status)));
7309 if (!NT_STATUS_IS_OK(status)) {
7310 return status;
7314 /* Setup the timeout in seconds. */
7316 if (!lp_blocking_locks(SNUM(conn))) {
7317 timeout = 0;
7320 /* Data now points at the beginning of the list
7321 of smb_lkrng structs */
7323 for(i = 0; i < (int)num_locks; i++) {
7324 struct smbd_lock_element *e = &locks[i];
7326 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7327 "%llu, file %s timeout = %d\n",
7328 (double)e->offset,
7329 (double)e->count,
7330 (unsigned long long)e->smblctx,
7331 fsp_str_dbg(fsp),
7332 (int)timeout));
7334 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7335 struct blocking_lock_record *blr = NULL;
7337 if (num_locks > 1) {
7339 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7340 * if the lock vector contains one entry. When given mutliple cancel
7341 * requests in a single PDU we expect the server to return an
7342 * error. Windows servers seem to accept the request but only
7343 * cancel the first lock.
7344 * JRA - Do what Windows does (tm) :-).
7347 #if 0
7348 /* MS-CIFS (2.2.4.32.1) behavior. */
7349 return NT_STATUS_DOS(ERRDOS,
7350 ERRcancelviolation);
7351 #else
7352 /* Windows behavior. */
7353 if (i != 0) {
7354 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7355 "cancel request\n"));
7356 continue;
7358 #endif
7361 if (lp_blocking_locks(SNUM(conn))) {
7363 /* Schedule a message to ourselves to
7364 remove the blocking lock record and
7365 return the right error. */
7367 blr = blocking_lock_cancel_smb1(fsp,
7368 e->smblctx,
7369 e->offset,
7370 e->count,
7371 WINDOWS_LOCK,
7372 type,
7373 NT_STATUS_FILE_LOCK_CONFLICT);
7374 if (blr == NULL) {
7375 return NT_STATUS_DOS(
7376 ERRDOS,
7377 ERRcancelviolation);
7380 /* Remove a matching pending lock. */
7381 status = do_lock_cancel(fsp,
7382 e->smblctx,
7383 e->count,
7384 e->offset,
7385 WINDOWS_LOCK,
7386 blr);
7387 } else {
7388 bool blocking_lock = timeout ? true : false;
7389 bool defer_lock = false;
7390 struct byte_range_lock *br_lck;
7391 uint64_t block_smblctx;
7393 br_lck = do_lock(req->sconn->msg_ctx,
7394 fsp,
7395 e->smblctx,
7396 e->count,
7397 e->offset,
7398 e->brltype,
7399 WINDOWS_LOCK,
7400 blocking_lock,
7401 &status,
7402 &block_smblctx,
7403 NULL);
7405 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7406 /* Windows internal resolution for blocking locks seems
7407 to be about 200ms... Don't wait for less than that. JRA. */
7408 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7409 timeout = lp_lock_spin_time();
7411 defer_lock = true;
7414 /* If a lock sent with timeout of zero would fail, and
7415 * this lock has been requested multiple times,
7416 * according to brl_lock_failed() we convert this
7417 * request to a blocking lock with a timeout of between
7418 * 150 - 300 milliseconds.
7420 * If lp_lock_spin_time() has been set to 0, we skip
7421 * this blocking retry and fail immediately.
7423 * Replacement for do_lock_spin(). JRA. */
7425 if (!req->sconn->using_smb2 &&
7426 br_lck && lp_blocking_locks(SNUM(conn)) &&
7427 lp_lock_spin_time() && !blocking_lock &&
7428 NT_STATUS_EQUAL((status),
7429 NT_STATUS_FILE_LOCK_CONFLICT))
7431 defer_lock = true;
7432 timeout = lp_lock_spin_time();
7435 if (br_lck && defer_lock) {
7437 * A blocking lock was requested. Package up
7438 * this smb into a queued request and push it
7439 * onto the blocking lock queue.
7441 if(push_blocking_lock_request(br_lck,
7442 req,
7443 fsp,
7444 timeout,
7446 e->smblctx,
7447 e->brltype,
7448 WINDOWS_LOCK,
7449 e->offset,
7450 e->count,
7451 block_smblctx)) {
7452 TALLOC_FREE(br_lck);
7453 *async = true;
7454 return NT_STATUS_OK;
7458 TALLOC_FREE(br_lck);
7461 if (!NT_STATUS_IS_OK(status)) {
7462 break;
7466 /* If any of the above locks failed, then we must unlock
7467 all of the previous locks (X/Open spec). */
7469 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7471 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7472 i = -1; /* we want to skip the for loop */
7476 * Ensure we don't do a remove on the lock that just failed,
7477 * as under POSIX rules, if we have a lock already there, we
7478 * will delete it (and we shouldn't) .....
7480 for(i--; i >= 0; i--) {
7481 struct smbd_lock_element *e = &locks[i];
7483 do_unlock(req->sconn->msg_ctx,
7484 fsp,
7485 e->smblctx,
7486 e->count,
7487 e->offset,
7488 WINDOWS_LOCK);
7490 return status;
7493 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7494 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7496 return NT_STATUS_OK;
7499 /****************************************************************************
7500 Reply to a lockingX request.
7501 ****************************************************************************/
7503 void reply_lockingX(struct smb_request *req)
7505 connection_struct *conn = req->conn;
7506 files_struct *fsp;
7507 unsigned char locktype;
7508 unsigned char oplocklevel;
7509 uint16 num_ulocks;
7510 uint16 num_locks;
7511 int32 lock_timeout;
7512 int i;
7513 const uint8_t *data;
7514 bool large_file_format;
7515 bool err;
7516 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7517 struct smbd_lock_element *ulocks;
7518 struct smbd_lock_element *locks;
7519 bool async = false;
7521 START_PROFILE(SMBlockingX);
7523 if (req->wct < 8) {
7524 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7525 END_PROFILE(SMBlockingX);
7526 return;
7529 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7530 locktype = CVAL(req->vwv+3, 0);
7531 oplocklevel = CVAL(req->vwv+3, 1);
7532 num_ulocks = SVAL(req->vwv+6, 0);
7533 num_locks = SVAL(req->vwv+7, 0);
7534 lock_timeout = IVAL(req->vwv+4, 0);
7535 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7537 if (!check_fsp(conn, req, fsp)) {
7538 END_PROFILE(SMBlockingX);
7539 return;
7542 data = req->buf;
7544 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7545 /* we don't support these - and CANCEL_LOCK makes w2k
7546 and XP reboot so I don't really want to be
7547 compatible! (tridge) */
7548 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7549 END_PROFILE(SMBlockingX);
7550 return;
7553 /* Check if this is an oplock break on a file
7554 we have granted an oplock on.
7556 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7557 /* Client can insist on breaking to none. */
7558 bool break_to_none = (oplocklevel == 0);
7559 bool result;
7561 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7562 "for fnum = %d\n", (unsigned int)oplocklevel,
7563 fsp->fnum ));
7566 * Make sure we have granted an exclusive or batch oplock on
7567 * this file.
7570 if (fsp->oplock_type == 0) {
7572 /* The Samba4 nbench simulator doesn't understand
7573 the difference between break to level2 and break
7574 to none from level2 - it sends oplock break
7575 replies in both cases. Don't keep logging an error
7576 message here - just ignore it. JRA. */
7578 DEBUG(5,("reply_lockingX: Error : oplock break from "
7579 "client for fnum = %d (oplock=%d) and no "
7580 "oplock granted on this file (%s).\n",
7581 fsp->fnum, fsp->oplock_type,
7582 fsp_str_dbg(fsp)));
7584 /* if this is a pure oplock break request then don't
7585 * send a reply */
7586 if (num_locks == 0 && num_ulocks == 0) {
7587 END_PROFILE(SMBlockingX);
7588 return;
7589 } else {
7590 END_PROFILE(SMBlockingX);
7591 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7592 return;
7596 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7597 (break_to_none)) {
7598 result = remove_oplock(fsp);
7599 } else {
7600 result = downgrade_oplock(fsp);
7603 if (!result) {
7604 DEBUG(0, ("reply_lockingX: error in removing "
7605 "oplock on file %s\n", fsp_str_dbg(fsp)));
7606 /* Hmmm. Is this panic justified? */
7607 smb_panic("internal tdb error");
7610 reply_to_oplock_break_requests(fsp);
7612 /* if this is a pure oplock break request then don't send a
7613 * reply */
7614 if (num_locks == 0 && num_ulocks == 0) {
7615 /* Sanity check - ensure a pure oplock break is not a
7616 chained request. */
7617 if(CVAL(req->vwv+0, 0) != 0xff)
7618 DEBUG(0,("reply_lockingX: Error : pure oplock "
7619 "break is a chained %d request !\n",
7620 (unsigned int)CVAL(req->vwv+0, 0)));
7621 END_PROFILE(SMBlockingX);
7622 return;
7626 if (req->buflen <
7627 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7628 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7629 END_PROFILE(SMBlockingX);
7630 return;
7633 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7634 if (ulocks == NULL) {
7635 reply_nterror(req, NT_STATUS_NO_MEMORY);
7636 END_PROFILE(SMBlockingX);
7637 return;
7640 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7641 if (locks == NULL) {
7642 reply_nterror(req, NT_STATUS_NO_MEMORY);
7643 END_PROFILE(SMBlockingX);
7644 return;
7647 /* Data now points at the beginning of the list
7648 of smb_unlkrng structs */
7649 for(i = 0; i < (int)num_ulocks; i++) {
7650 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7651 ulocks[i].count = get_lock_count(data, i, large_file_format);
7652 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7653 ulocks[i].brltype = UNLOCK_LOCK;
7656 * There is no error code marked "stupid client bug".... :-).
7658 if(err) {
7659 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7660 END_PROFILE(SMBlockingX);
7661 return;
7665 /* Now do any requested locks */
7666 data += ((large_file_format ? 20 : 10)*num_ulocks);
7668 /* Data now points at the beginning of the list
7669 of smb_lkrng structs */
7671 for(i = 0; i < (int)num_locks; i++) {
7672 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7673 locks[i].count = get_lock_count(data, i, large_file_format);
7674 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7676 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7677 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7678 locks[i].brltype = PENDING_READ_LOCK;
7679 } else {
7680 locks[i].brltype = READ_LOCK;
7682 } else {
7683 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7684 locks[i].brltype = PENDING_WRITE_LOCK;
7685 } else {
7686 locks[i].brltype = WRITE_LOCK;
7691 * There is no error code marked "stupid client bug".... :-).
7693 if(err) {
7694 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7695 END_PROFILE(SMBlockingX);
7696 return;
7700 status = smbd_do_locking(req, fsp,
7701 locktype, lock_timeout,
7702 num_ulocks, ulocks,
7703 num_locks, locks,
7704 &async);
7705 if (!NT_STATUS_IS_OK(status)) {
7706 END_PROFILE(SMBlockingX);
7707 reply_nterror(req, status);
7708 return;
7710 if (async) {
7711 END_PROFILE(SMBlockingX);
7712 return;
7715 reply_outbuf(req, 2, 0);
7717 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7718 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7720 END_PROFILE(SMBlockingX);
7721 chain_reply(req);
7724 #undef DBGC_CLASS
7725 #define DBGC_CLASS DBGC_ALL
7727 /****************************************************************************
7728 Reply to a SMBreadbmpx (read block multiplex) request.
7729 Always reply with an error, if someone has a platform really needs this,
7730 please contact vl@samba.org
7731 ****************************************************************************/
7733 void reply_readbmpx(struct smb_request *req)
7735 START_PROFILE(SMBreadBmpx);
7736 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7737 END_PROFILE(SMBreadBmpx);
7738 return;
7741 /****************************************************************************
7742 Reply to a SMBreadbs (read block multiplex secondary) request.
7743 Always reply with an error, if someone has a platform really needs this,
7744 please contact vl@samba.org
7745 ****************************************************************************/
7747 void reply_readbs(struct smb_request *req)
7749 START_PROFILE(SMBreadBs);
7750 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7751 END_PROFILE(SMBreadBs);
7752 return;
7755 /****************************************************************************
7756 Reply to a SMBsetattrE.
7757 ****************************************************************************/
7759 void reply_setattrE(struct smb_request *req)
7761 connection_struct *conn = req->conn;
7762 struct smb_file_time ft;
7763 files_struct *fsp;
7764 NTSTATUS status;
7766 START_PROFILE(SMBsetattrE);
7767 ZERO_STRUCT(ft);
7769 if (req->wct < 7) {
7770 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7771 goto out;
7774 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7776 if(!fsp || (fsp->conn != conn)) {
7777 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7778 goto out;
7782 * Convert the DOS times into unix times.
7785 ft.atime = convert_time_t_to_timespec(
7786 srv_make_unix_date2(req->vwv+3));
7787 ft.mtime = convert_time_t_to_timespec(
7788 srv_make_unix_date2(req->vwv+5));
7789 ft.create_time = convert_time_t_to_timespec(
7790 srv_make_unix_date2(req->vwv+1));
7792 reply_outbuf(req, 0, 0);
7795 * Patch from Ray Frush <frush@engr.colostate.edu>
7796 * Sometimes times are sent as zero - ignore them.
7799 /* Ensure we have a valid stat struct for the source. */
7800 status = vfs_stat_fsp(fsp);
7801 if (!NT_STATUS_IS_OK(status)) {
7802 reply_nterror(req, status);
7803 goto out;
7806 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7807 if (!NT_STATUS_IS_OK(status)) {
7808 reply_nterror(req, status);
7809 goto out;
7812 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7813 " createtime=%u\n",
7814 fsp->fnum,
7815 (unsigned int)ft.atime.tv_sec,
7816 (unsigned int)ft.mtime.tv_sec,
7817 (unsigned int)ft.create_time.tv_sec
7819 out:
7820 END_PROFILE(SMBsetattrE);
7821 return;
7825 /* Back from the dead for OS/2..... JRA. */
7827 /****************************************************************************
7828 Reply to a SMBwritebmpx (write block multiplex primary) request.
7829 Always reply with an error, if someone has a platform really needs this,
7830 please contact vl@samba.org
7831 ****************************************************************************/
7833 void reply_writebmpx(struct smb_request *req)
7835 START_PROFILE(SMBwriteBmpx);
7836 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7837 END_PROFILE(SMBwriteBmpx);
7838 return;
7841 /****************************************************************************
7842 Reply to a SMBwritebs (write block multiplex secondary) request.
7843 Always reply with an error, if someone has a platform really needs this,
7844 please contact vl@samba.org
7845 ****************************************************************************/
7847 void reply_writebs(struct smb_request *req)
7849 START_PROFILE(SMBwriteBs);
7850 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7851 END_PROFILE(SMBwriteBs);
7852 return;
7855 /****************************************************************************
7856 Reply to a SMBgetattrE.
7857 ****************************************************************************/
7859 void reply_getattrE(struct smb_request *req)
7861 connection_struct *conn = req->conn;
7862 int mode;
7863 files_struct *fsp;
7864 struct timespec create_ts;
7866 START_PROFILE(SMBgetattrE);
7868 if (req->wct < 1) {
7869 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7870 END_PROFILE(SMBgetattrE);
7871 return;
7874 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7876 if(!fsp || (fsp->conn != conn)) {
7877 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7878 END_PROFILE(SMBgetattrE);
7879 return;
7882 /* Do an fstat on this file */
7883 if(fsp_stat(fsp)) {
7884 reply_nterror(req, map_nt_error_from_unix(errno));
7885 END_PROFILE(SMBgetattrE);
7886 return;
7889 mode = dos_mode(conn, fsp->fsp_name);
7892 * Convert the times into dos times. Set create
7893 * date to be last modify date as UNIX doesn't save
7894 * this.
7897 reply_outbuf(req, 11, 0);
7899 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7900 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7901 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7902 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7903 /* Should we check pending modtime here ? JRA */
7904 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7905 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7907 if (mode & aDIR) {
7908 SIVAL(req->outbuf, smb_vwv6, 0);
7909 SIVAL(req->outbuf, smb_vwv8, 0);
7910 } else {
7911 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7912 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
7913 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7915 SSVAL(req->outbuf,smb_vwv10, mode);
7917 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7919 END_PROFILE(SMBgetattrE);
7920 return;