s3: Remove smbd_server_fd() from reply_echo
[Samba/ita.git] / source3 / smbd / reply.c
blob97451e629c93196fcd6c2f898a1719e622c95b8b
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 "../librpc/gen_ndr/cli_spoolss.h"
31 #include "rpc_client/cli_spoolss.h"
32 #include "rpc_client/init_spoolss.h"
34 /****************************************************************************
35 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
36 path or anything including wildcards.
37 We're assuming here that '/' is not the second byte in any multibyte char
38 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
39 set.
40 ****************************************************************************/
42 /* Custom version for processing POSIX paths. */
43 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
45 static NTSTATUS check_path_syntax_internal(char *path,
46 bool posix_path,
47 bool *p_last_component_contains_wcard)
49 char *d = path;
50 const char *s = path;
51 NTSTATUS ret = NT_STATUS_OK;
52 bool start_of_name_component = True;
53 bool stream_started = false;
55 *p_last_component_contains_wcard = False;
57 while (*s) {
58 if (stream_started) {
59 switch (*s) {
60 case '/':
61 case '\\':
62 return NT_STATUS_OBJECT_NAME_INVALID;
63 case ':':
64 if (s[1] == '\0') {
65 return NT_STATUS_OBJECT_NAME_INVALID;
67 if (strchr_m(&s[1], ':')) {
68 return NT_STATUS_OBJECT_NAME_INVALID;
70 break;
74 if ((*s == ':') && !posix_path && !stream_started) {
75 if (*p_last_component_contains_wcard) {
76 return NT_STATUS_OBJECT_NAME_INVALID;
78 /* Stream names allow more characters than file names.
79 We're overloading posix_path here to allow a wider
80 range of characters. If stream_started is true this
81 is still a Windows path even if posix_path is true.
82 JRA.
84 stream_started = true;
85 start_of_name_component = false;
86 posix_path = true;
88 if (s[1] == '\0') {
89 return NT_STATUS_OBJECT_NAME_INVALID;
93 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
95 * Safe to assume is not the second part of a mb char
96 * as this is handled below.
98 /* Eat multiple '/' or '\\' */
99 while (IS_PATH_SEP(*s,posix_path)) {
100 s++;
102 if ((d != path) && (*s != '\0')) {
103 /* We only care about non-leading or trailing '/' or '\\' */
104 *d++ = '/';
107 start_of_name_component = True;
108 /* New component. */
109 *p_last_component_contains_wcard = False;
110 continue;
113 if (start_of_name_component) {
114 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
115 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
118 * No mb char starts with '.' so we're safe checking the directory separator here.
121 /* If we just added a '/' - delete it */
122 if ((d > path) && (*(d-1) == '/')) {
123 *(d-1) = '\0';
124 d--;
127 /* Are we at the start ? Can't go back further if so. */
128 if (d <= path) {
129 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
130 break;
132 /* Go back one level... */
133 /* We know this is safe as '/' cannot be part of a mb sequence. */
134 /* NOTE - if this assumption is invalid we are not in good shape... */
135 /* Decrement d first as d points to the *next* char to write into. */
136 for (d--; d > path; d--) {
137 if (*d == '/')
138 break;
140 s += 2; /* Else go past the .. */
141 /* We're still at the start of a name component, just the previous one. */
142 continue;
144 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
145 if (posix_path) {
146 /* Eat the '.' */
147 s++;
148 continue;
154 if (!(*s & 0x80)) {
155 if (!posix_path) {
156 if (*s <= 0x1f || *s == '|') {
157 return NT_STATUS_OBJECT_NAME_INVALID;
159 switch (*s) {
160 case '*':
161 case '?':
162 case '<':
163 case '>':
164 case '"':
165 *p_last_component_contains_wcard = True;
166 break;
167 default:
168 break;
171 *d++ = *s++;
172 } else {
173 size_t siz;
174 /* Get the size of the next MB character. */
175 next_codepoint(s,&siz);
176 switch(siz) {
177 case 5:
178 *d++ = *s++;
179 /*fall through*/
180 case 4:
181 *d++ = *s++;
182 /*fall through*/
183 case 3:
184 *d++ = *s++;
185 /*fall through*/
186 case 2:
187 *d++ = *s++;
188 /*fall through*/
189 case 1:
190 *d++ = *s++;
191 break;
192 default:
193 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
194 *d = '\0';
195 return NT_STATUS_INVALID_PARAMETER;
198 start_of_name_component = False;
201 *d = '\0';
203 return ret;
206 /****************************************************************************
207 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
208 No wildcards allowed.
209 ****************************************************************************/
211 NTSTATUS check_path_syntax(char *path)
213 bool ignore;
214 return check_path_syntax_internal(path, False, &ignore);
217 /****************************************************************************
218 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
219 Wildcards allowed - p_contains_wcard returns true if the last component contained
220 a wildcard.
221 ****************************************************************************/
223 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
225 return check_path_syntax_internal(path, False, p_contains_wcard);
228 /****************************************************************************
229 Check the path for a POSIX client.
230 We're assuming here that '/' is not the second byte in any multibyte char
231 set (a safe assumption).
232 ****************************************************************************/
234 NTSTATUS check_path_syntax_posix(char *path)
236 bool ignore;
237 return check_path_syntax_internal(path, True, &ignore);
240 /****************************************************************************
241 Pull a string and check the path allowing a wilcard - provide for error return.
242 ****************************************************************************/
244 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
245 const char *base_ptr,
246 uint16 smb_flags2,
247 char **pp_dest,
248 const char *src,
249 size_t src_len,
250 int flags,
251 NTSTATUS *err,
252 bool *contains_wcard)
254 size_t ret;
256 *pp_dest = NULL;
258 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
259 src_len, flags);
261 if (!*pp_dest) {
262 *err = NT_STATUS_INVALID_PARAMETER;
263 return ret;
266 *contains_wcard = False;
268 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
270 * For a DFS path the function parse_dfs_path()
271 * will do the path processing, just make a copy.
273 *err = NT_STATUS_OK;
274 return ret;
277 if (lp_posix_pathnames()) {
278 *err = check_path_syntax_posix(*pp_dest);
279 } else {
280 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
283 return ret;
286 /****************************************************************************
287 Pull a string and check the path - provide for error return.
288 ****************************************************************************/
290 size_t srvstr_get_path(TALLOC_CTX *ctx,
291 const char *base_ptr,
292 uint16 smb_flags2,
293 char **pp_dest,
294 const char *src,
295 size_t src_len,
296 int flags,
297 NTSTATUS *err)
299 bool ignore;
300 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
301 src_len, flags, err, &ignore);
304 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
305 char **pp_dest, const char *src, int flags,
306 NTSTATUS *err, bool *contains_wcard)
308 return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
309 pp_dest, src, smbreq_bufrem(req, src),
310 flags, err, contains_wcard);
313 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
314 char **pp_dest, const char *src, int flags,
315 NTSTATUS *err)
317 bool ignore;
318 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
319 flags, err, &ignore);
322 /****************************************************************************
323 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
324 ****************************************************************************/
326 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
327 files_struct *fsp)
329 if ((fsp == NULL) || (conn == NULL)) {
330 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
331 return False;
333 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
334 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
335 return False;
337 return True;
340 /****************************************************************************
341 Check if we have a correct fsp pointing to a file.
342 ****************************************************************************/
344 bool check_fsp(connection_struct *conn, struct smb_request *req,
345 files_struct *fsp)
347 if (!check_fsp_open(conn, req, fsp)) {
348 return False;
350 if (fsp->is_directory) {
351 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
352 return False;
354 if (fsp->fh->fd == -1) {
355 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
356 return False;
358 fsp->num_smb_operations++;
359 return True;
362 /****************************************************************************
363 Check if we have a correct fsp pointing to a quota fake file. Replacement for
364 the CHECK_NTQUOTA_HANDLE_OK macro.
365 ****************************************************************************/
367 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
368 files_struct *fsp)
370 if (!check_fsp_open(conn, req, fsp)) {
371 return false;
374 if (fsp->is_directory) {
375 return false;
378 if (fsp->fake_file_handle == NULL) {
379 return false;
382 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
383 return false;
386 if (fsp->fake_file_handle->private_data == NULL) {
387 return false;
390 return true;
393 static bool netbios_session_retarget(struct smbd_server_connection *sconn,
394 const char *name, int name_type)
396 char *trim_name;
397 char *trim_name_type;
398 const char *retarget_parm;
399 char *retarget;
400 char *p;
401 int retarget_type = 0x20;
402 int retarget_port = 139;
403 struct sockaddr_storage retarget_addr;
404 struct sockaddr_in *in_addr;
405 bool ret = false;
406 uint8_t outbuf[10];
408 if (get_socket_port(sconn->sock) != 139) {
409 return false;
412 trim_name = talloc_strdup(talloc_tos(), name);
413 if (trim_name == NULL) {
414 goto fail;
416 trim_char(trim_name, ' ', ' ');
418 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
419 name_type);
420 if (trim_name_type == NULL) {
421 goto fail;
424 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
425 trim_name_type, NULL);
426 if (retarget_parm == NULL) {
427 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
428 trim_name, NULL);
430 if (retarget_parm == NULL) {
431 goto fail;
434 retarget = talloc_strdup(trim_name, retarget_parm);
435 if (retarget == NULL) {
436 goto fail;
439 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
441 p = strchr(retarget, ':');
442 if (p != NULL) {
443 *p++ = '\0';
444 retarget_port = atoi(p);
447 p = strchr_m(retarget, '#');
448 if (p != NULL) {
449 *p++ = '\0';
450 sscanf(p, "%x", &retarget_type);
453 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
454 if (!ret) {
455 DEBUG(10, ("could not resolve %s\n", retarget));
456 goto fail;
459 if (retarget_addr.ss_family != AF_INET) {
460 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
461 goto fail;
464 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
466 _smb_setlen(outbuf, 6);
467 SCVAL(outbuf, 0, 0x84);
468 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
469 *(uint16_t *)(outbuf+8) = htons(retarget_port);
471 if (!srv_send_smb(sconn->sock, (char *)outbuf, false, 0, false,
472 NULL)) {
473 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
474 "failed.");
477 ret = true;
478 fail:
479 TALLOC_FREE(trim_name);
480 return ret;
483 /****************************************************************************
484 Reply to a (netbios-level) special message.
485 ****************************************************************************/
487 void reply_special(struct smbd_server_connection *sconn, char *inbuf)
489 int msg_type = CVAL(inbuf,0);
490 int msg_flags = CVAL(inbuf,1);
491 fstring name1,name2;
492 char name_type1, name_type2;
495 * We only really use 4 bytes of the outbuf, but for the smb_setlen
496 * calculation & friends (srv_send_smb uses that) we need the full smb
497 * header.
499 char outbuf[smb_size];
501 *name1 = *name2 = 0;
503 memset(outbuf, '\0', sizeof(outbuf));
505 smb_setlen(outbuf,0);
507 switch (msg_type) {
508 case 0x81: /* session request */
510 if (sconn->nbt.got_session) {
511 exit_server_cleanly("multiple session request not permitted");
514 SCVAL(outbuf,0,0x82);
515 SCVAL(outbuf,3,0);
516 if (name_len(inbuf+4) > 50 ||
517 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
518 DEBUG(0,("Invalid name length in session request\n"));
519 return;
521 name_type1 = name_extract(inbuf,4,name1);
522 name_type2 = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
523 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
524 name1, name_type1, name2, name_type2));
526 if (netbios_session_retarget(sconn, name1, name_type1)) {
527 exit_server_cleanly("retargeted client");
530 set_local_machine_name(name1, True);
531 set_remote_machine_name(name2, True);
533 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
534 get_local_machine_name(), get_remote_machine_name(),
535 name_type2));
537 if (name_type2 == 'R') {
538 /* We are being asked for a pathworks session ---
539 no thanks! */
540 SCVAL(outbuf, 0,0x83);
541 break;
544 /* only add the client's machine name to the list
545 of possibly valid usernames if we are operating
546 in share mode security */
547 if (lp_security() == SEC_SHARE) {
548 add_session_user(sconn, get_remote_machine_name());
551 reload_services(sconn->msg_ctx, True);
552 reopen_logs();
554 sconn->nbt.got_session = true;
555 break;
557 case 0x89: /* session keepalive request
558 (some old clients produce this?) */
559 SCVAL(outbuf,0,SMBkeepalive);
560 SCVAL(outbuf,3,0);
561 break;
563 case 0x82: /* positive session response */
564 case 0x83: /* negative session response */
565 case 0x84: /* retarget session response */
566 DEBUG(0,("Unexpected session response\n"));
567 break;
569 case SMBkeepalive: /* session keepalive */
570 default:
571 return;
574 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
575 msg_type, msg_flags));
577 srv_send_smb(sconn->sock, outbuf, false, 0, false, NULL);
578 return;
581 /****************************************************************************
582 Reply to a tcon.
583 conn POINTER CAN BE NULL HERE !
584 ****************************************************************************/
586 void reply_tcon(struct smb_request *req)
588 connection_struct *conn = req->conn;
589 const char *service;
590 char *service_buf = NULL;
591 char *password = NULL;
592 char *dev = NULL;
593 int pwlen=0;
594 NTSTATUS nt_status;
595 const char *p;
596 DATA_BLOB password_blob;
597 TALLOC_CTX *ctx = talloc_tos();
598 struct smbd_server_connection *sconn = req->sconn;
600 START_PROFILE(SMBtcon);
602 if (req->buflen < 4) {
603 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
604 END_PROFILE(SMBtcon);
605 return;
608 p = (const char *)req->buf + 1;
609 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
610 p += 1;
611 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
612 p += pwlen+1;
613 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
614 p += 1;
616 if (service_buf == NULL || password == NULL || dev == NULL) {
617 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
618 END_PROFILE(SMBtcon);
619 return;
621 p = strrchr_m(service_buf,'\\');
622 if (p) {
623 service = p+1;
624 } else {
625 service = service_buf;
628 password_blob = data_blob(password, pwlen+1);
630 conn = make_connection(sconn,service,password_blob,dev,
631 req->vuid,&nt_status);
632 req->conn = conn;
634 data_blob_clear_free(&password_blob);
636 if (!conn) {
637 reply_nterror(req, nt_status);
638 END_PROFILE(SMBtcon);
639 return;
642 reply_outbuf(req, 2, 0);
643 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
644 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
645 SSVAL(req->outbuf,smb_tid,conn->cnum);
647 DEBUG(3,("tcon service=%s cnum=%d\n",
648 service, conn->cnum));
650 END_PROFILE(SMBtcon);
651 return;
654 /****************************************************************************
655 Reply to a tcon and X.
656 conn POINTER CAN BE NULL HERE !
657 ****************************************************************************/
659 void reply_tcon_and_X(struct smb_request *req)
661 connection_struct *conn = req->conn;
662 const char *service = NULL;
663 DATA_BLOB password;
664 TALLOC_CTX *ctx = talloc_tos();
665 /* what the cleint thinks the device is */
666 char *client_devicetype = NULL;
667 /* what the server tells the client the share represents */
668 const char *server_devicetype;
669 NTSTATUS nt_status;
670 int passlen;
671 char *path = NULL;
672 const char *p, *q;
673 uint16 tcon_flags;
674 struct smbd_server_connection *sconn = req->sconn;
676 START_PROFILE(SMBtconX);
678 if (req->wct < 4) {
679 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
680 END_PROFILE(SMBtconX);
681 return;
684 passlen = SVAL(req->vwv+3, 0);
685 tcon_flags = SVAL(req->vwv+2, 0);
687 /* we might have to close an old one */
688 if ((tcon_flags & 0x1) && conn) {
689 close_cnum(conn,req->vuid);
690 req->conn = NULL;
691 conn = NULL;
694 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
695 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
696 END_PROFILE(SMBtconX);
697 return;
700 if (sconn->smb1.negprot.encrypted_passwords) {
701 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
702 if (lp_security() == SEC_SHARE) {
704 * Security = share always has a pad byte
705 * after the password.
707 p = (const char *)req->buf + passlen + 1;
708 } else {
709 p = (const char *)req->buf + passlen;
711 } else {
712 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
713 /* Ensure correct termination */
714 password.data[passlen]=0;
715 p = (const char *)req->buf + passlen + 1;
718 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
720 if (path == NULL) {
721 data_blob_clear_free(&password);
722 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
723 END_PROFILE(SMBtconX);
724 return;
728 * the service name can be either: \\server\share
729 * or share directly like on the DELL PowerVault 705
731 if (*path=='\\') {
732 q = strchr_m(path+2,'\\');
733 if (!q) {
734 data_blob_clear_free(&password);
735 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
736 END_PROFILE(SMBtconX);
737 return;
739 service = q+1;
740 } else {
741 service = path;
744 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
745 &client_devicetype, p,
746 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
748 if (client_devicetype == NULL) {
749 data_blob_clear_free(&password);
750 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
751 END_PROFILE(SMBtconX);
752 return;
755 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
757 conn = make_connection(sconn, service, password, client_devicetype,
758 req->vuid, &nt_status);
759 req->conn =conn;
761 data_blob_clear_free(&password);
763 if (!conn) {
764 reply_nterror(req, nt_status);
765 END_PROFILE(SMBtconX);
766 return;
769 if ( IS_IPC(conn) )
770 server_devicetype = "IPC";
771 else if ( IS_PRINT(conn) )
772 server_devicetype = "LPT1:";
773 else
774 server_devicetype = "A:";
776 if (get_Protocol() < PROTOCOL_NT1) {
777 reply_outbuf(req, 2, 0);
778 if (message_push_string(&req->outbuf, server_devicetype,
779 STR_TERMINATE|STR_ASCII) == -1) {
780 reply_nterror(req, NT_STATUS_NO_MEMORY);
781 END_PROFILE(SMBtconX);
782 return;
784 } else {
785 /* NT sets the fstype of IPC$ to the null string */
786 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
788 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
789 /* Return permissions. */
790 uint32 perm1 = 0;
791 uint32 perm2 = 0;
793 reply_outbuf(req, 7, 0);
795 if (IS_IPC(conn)) {
796 perm1 = FILE_ALL_ACCESS;
797 perm2 = FILE_ALL_ACCESS;
798 } else {
799 perm1 = CAN_WRITE(conn) ?
800 SHARE_ALL_ACCESS :
801 SHARE_READ_ONLY;
804 SIVAL(req->outbuf, smb_vwv3, perm1);
805 SIVAL(req->outbuf, smb_vwv5, perm2);
806 } else {
807 reply_outbuf(req, 3, 0);
810 if ((message_push_string(&req->outbuf, server_devicetype,
811 STR_TERMINATE|STR_ASCII) == -1)
812 || (message_push_string(&req->outbuf, fstype,
813 STR_TERMINATE) == -1)) {
814 reply_nterror(req, NT_STATUS_NO_MEMORY);
815 END_PROFILE(SMBtconX);
816 return;
819 /* what does setting this bit do? It is set by NT4 and
820 may affect the ability to autorun mounted cdroms */
821 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
822 (lp_csc_policy(SNUM(conn)) << 2));
824 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
825 DEBUG(2,("Serving %s as a Dfs root\n",
826 lp_servicename(SNUM(conn)) ));
827 SSVAL(req->outbuf, smb_vwv2,
828 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
833 DEBUG(3,("tconX service=%s \n",
834 service));
836 /* set the incoming and outgoing tid to the just created one */
837 SSVAL(req->inbuf,smb_tid,conn->cnum);
838 SSVAL(req->outbuf,smb_tid,conn->cnum);
840 END_PROFILE(SMBtconX);
842 req->tid = conn->cnum;
843 chain_reply(req);
844 return;
847 /****************************************************************************
848 Reply to an unknown type.
849 ****************************************************************************/
851 void reply_unknown_new(struct smb_request *req, uint8 type)
853 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
854 smb_fn_name(type), type, type));
855 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
856 return;
859 /****************************************************************************
860 Reply to an ioctl.
861 conn POINTER CAN BE NULL HERE !
862 ****************************************************************************/
864 void reply_ioctl(struct smb_request *req)
866 connection_struct *conn = req->conn;
867 uint16 device;
868 uint16 function;
869 uint32 ioctl_code;
870 int replysize;
871 char *p;
873 START_PROFILE(SMBioctl);
875 if (req->wct < 3) {
876 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
877 END_PROFILE(SMBioctl);
878 return;
881 device = SVAL(req->vwv+1, 0);
882 function = SVAL(req->vwv+2, 0);
883 ioctl_code = (device << 16) + function;
885 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
887 switch (ioctl_code) {
888 case IOCTL_QUERY_JOB_INFO:
889 replysize = 32;
890 break;
891 default:
892 reply_force_doserror(req, ERRSRV, ERRnosupport);
893 END_PROFILE(SMBioctl);
894 return;
897 reply_outbuf(req, 8, replysize+1);
898 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
899 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
900 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
901 p = smb_buf(req->outbuf);
902 memset(p, '\0', replysize+1); /* valgrind-safe. */
903 p += 1; /* Allow for alignment */
905 switch (ioctl_code) {
906 case IOCTL_QUERY_JOB_INFO:
908 files_struct *fsp = file_fsp(
909 req, SVAL(req->vwv+0, 0));
910 if (!fsp) {
911 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
912 END_PROFILE(SMBioctl);
913 return;
915 /* Job number */
916 if (fsp->print_file) {
917 SSVAL(p, 0, fsp->print_file->rap_jobid);
918 } else {
919 SSVAL(p, 0, 0);
921 srvstr_push((char *)req->outbuf, req->flags2, p+2,
922 global_myname(), 15,
923 STR_TERMINATE|STR_ASCII);
924 if (conn) {
925 srvstr_push((char *)req->outbuf, req->flags2,
926 p+18, lp_servicename(SNUM(conn)),
927 13, STR_TERMINATE|STR_ASCII);
928 } else {
929 memset(p+18, 0, 13);
931 break;
935 END_PROFILE(SMBioctl);
936 return;
939 /****************************************************************************
940 Strange checkpath NTSTATUS mapping.
941 ****************************************************************************/
943 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
945 /* Strange DOS error code semantics only for checkpath... */
946 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
947 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
948 /* We need to map to ERRbadpath */
949 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
952 return status;
955 /****************************************************************************
956 Reply to a checkpath.
957 ****************************************************************************/
959 void reply_checkpath(struct smb_request *req)
961 connection_struct *conn = req->conn;
962 struct smb_filename *smb_fname = NULL;
963 char *name = NULL;
964 NTSTATUS status;
965 TALLOC_CTX *ctx = talloc_tos();
967 START_PROFILE(SMBcheckpath);
969 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
970 STR_TERMINATE, &status);
972 if (!NT_STATUS_IS_OK(status)) {
973 status = map_checkpath_error(req->flags2, status);
974 reply_nterror(req, status);
975 END_PROFILE(SMBcheckpath);
976 return;
979 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
981 status = filename_convert(ctx,
982 conn,
983 req->flags2 & FLAGS2_DFS_PATHNAMES,
984 name,
986 NULL,
987 &smb_fname);
989 if (!NT_STATUS_IS_OK(status)) {
990 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
991 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
992 ERRSRV, ERRbadpath);
993 END_PROFILE(SMBcheckpath);
994 return;
996 goto path_err;
999 if (!VALID_STAT(smb_fname->st) &&
1000 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1001 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1002 smb_fname_str_dbg(smb_fname), strerror(errno)));
1003 status = map_nt_error_from_unix(errno);
1004 goto path_err;
1007 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1008 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1009 ERRDOS, ERRbadpath);
1010 goto out;
1013 reply_outbuf(req, 0, 0);
1015 path_err:
1016 /* We special case this - as when a Windows machine
1017 is parsing a path is steps through the components
1018 one at a time - if a component fails it expects
1019 ERRbadpath, not ERRbadfile.
1021 status = map_checkpath_error(req->flags2, status);
1022 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1024 * Windows returns different error codes if
1025 * the parent directory is valid but not the
1026 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1027 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1028 * if the path is invalid.
1030 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1031 ERRDOS, ERRbadpath);
1032 goto out;
1035 reply_nterror(req, status);
1037 out:
1038 TALLOC_FREE(smb_fname);
1039 END_PROFILE(SMBcheckpath);
1040 return;
1043 /****************************************************************************
1044 Reply to a getatr.
1045 ****************************************************************************/
1047 void reply_getatr(struct smb_request *req)
1049 connection_struct *conn = req->conn;
1050 struct smb_filename *smb_fname = NULL;
1051 char *fname = NULL;
1052 int mode=0;
1053 SMB_OFF_T size=0;
1054 time_t mtime=0;
1055 const char *p;
1056 NTSTATUS status;
1057 TALLOC_CTX *ctx = talloc_tos();
1058 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1060 START_PROFILE(SMBgetatr);
1062 p = (const char *)req->buf + 1;
1063 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1064 if (!NT_STATUS_IS_OK(status)) {
1065 reply_nterror(req, status);
1066 goto out;
1069 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1070 under WfWg - weird! */
1071 if (*fname == '\0') {
1072 mode = aHIDDEN | aDIR;
1073 if (!CAN_WRITE(conn)) {
1074 mode |= aRONLY;
1076 size = 0;
1077 mtime = 0;
1078 } else {
1079 status = filename_convert(ctx,
1080 conn,
1081 req->flags2 & FLAGS2_DFS_PATHNAMES,
1082 fname,
1084 NULL,
1085 &smb_fname);
1086 if (!NT_STATUS_IS_OK(status)) {
1087 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1088 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1089 ERRSRV, ERRbadpath);
1090 goto out;
1092 reply_nterror(req, status);
1093 goto out;
1095 if (!VALID_STAT(smb_fname->st) &&
1096 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1097 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1098 smb_fname_str_dbg(smb_fname),
1099 strerror(errno)));
1100 reply_nterror(req, map_nt_error_from_unix(errno));
1101 goto out;
1104 mode = dos_mode(conn, smb_fname);
1105 size = smb_fname->st.st_ex_size;
1107 if (ask_sharemode) {
1108 struct timespec write_time_ts;
1109 struct file_id fileid;
1111 ZERO_STRUCT(write_time_ts);
1112 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1113 get_file_infos(fileid, NULL, &write_time_ts);
1114 if (!null_timespec(write_time_ts)) {
1115 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1119 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1120 if (mode & aDIR) {
1121 size = 0;
1125 reply_outbuf(req, 10, 0);
1127 SSVAL(req->outbuf,smb_vwv0,mode);
1128 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1129 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1130 } else {
1131 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1133 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1135 if (get_Protocol() >= PROTOCOL_NT1) {
1136 SSVAL(req->outbuf, smb_flg2,
1137 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1140 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1141 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1143 out:
1144 TALLOC_FREE(smb_fname);
1145 TALLOC_FREE(fname);
1146 END_PROFILE(SMBgetatr);
1147 return;
1150 /****************************************************************************
1151 Reply to a setatr.
1152 ****************************************************************************/
1154 void reply_setatr(struct smb_request *req)
1156 struct smb_file_time ft;
1157 connection_struct *conn = req->conn;
1158 struct smb_filename *smb_fname = NULL;
1159 char *fname = NULL;
1160 int mode;
1161 time_t mtime;
1162 const char *p;
1163 NTSTATUS status;
1164 TALLOC_CTX *ctx = talloc_tos();
1166 START_PROFILE(SMBsetatr);
1168 ZERO_STRUCT(ft);
1170 if (req->wct < 2) {
1171 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1172 goto out;
1175 p = (const char *)req->buf + 1;
1176 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1177 if (!NT_STATUS_IS_OK(status)) {
1178 reply_nterror(req, status);
1179 goto out;
1182 status = filename_convert(ctx,
1183 conn,
1184 req->flags2 & FLAGS2_DFS_PATHNAMES,
1185 fname,
1187 NULL,
1188 &smb_fname);
1189 if (!NT_STATUS_IS_OK(status)) {
1190 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1191 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1192 ERRSRV, ERRbadpath);
1193 goto out;
1195 reply_nterror(req, status);
1196 goto out;
1199 if (smb_fname->base_name[0] == '.' &&
1200 smb_fname->base_name[1] == '\0') {
1202 * Not sure here is the right place to catch this
1203 * condition. Might be moved to somewhere else later -- vl
1205 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1206 goto out;
1209 mode = SVAL(req->vwv+0, 0);
1210 mtime = srv_make_unix_date3(req->vwv+1);
1212 ft.mtime = convert_time_t_to_timespec(mtime);
1213 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1214 if (!NT_STATUS_IS_OK(status)) {
1215 reply_nterror(req, status);
1216 goto out;
1219 if (mode != FILE_ATTRIBUTE_NORMAL) {
1220 if (VALID_STAT_OF_DIR(smb_fname->st))
1221 mode |= aDIR;
1222 else
1223 mode &= ~aDIR;
1225 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1226 false) != 0) {
1227 reply_nterror(req, map_nt_error_from_unix(errno));
1228 goto out;
1232 reply_outbuf(req, 0, 0);
1234 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1235 mode));
1236 out:
1237 TALLOC_FREE(smb_fname);
1238 END_PROFILE(SMBsetatr);
1239 return;
1242 /****************************************************************************
1243 Reply to a dskattr.
1244 ****************************************************************************/
1246 void reply_dskattr(struct smb_request *req)
1248 connection_struct *conn = req->conn;
1249 uint64_t dfree,dsize,bsize;
1250 START_PROFILE(SMBdskattr);
1252 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1253 reply_nterror(req, map_nt_error_from_unix(errno));
1254 END_PROFILE(SMBdskattr);
1255 return;
1258 reply_outbuf(req, 5, 0);
1260 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1261 double total_space, free_space;
1262 /* we need to scale this to a number that DOS6 can handle. We
1263 use floating point so we can handle large drives on systems
1264 that don't have 64 bit integers
1266 we end up displaying a maximum of 2G to DOS systems
1268 total_space = dsize * (double)bsize;
1269 free_space = dfree * (double)bsize;
1271 dsize = (uint64_t)((total_space+63*512) / (64*512));
1272 dfree = (uint64_t)((free_space+63*512) / (64*512));
1274 if (dsize > 0xFFFF) dsize = 0xFFFF;
1275 if (dfree > 0xFFFF) dfree = 0xFFFF;
1277 SSVAL(req->outbuf,smb_vwv0,dsize);
1278 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1279 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1280 SSVAL(req->outbuf,smb_vwv3,dfree);
1281 } else {
1282 SSVAL(req->outbuf,smb_vwv0,dsize);
1283 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1284 SSVAL(req->outbuf,smb_vwv2,512);
1285 SSVAL(req->outbuf,smb_vwv3,dfree);
1288 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1290 END_PROFILE(SMBdskattr);
1291 return;
1295 * Utility function to split the filename from the directory.
1297 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1298 char **fname_dir_out,
1299 char **fname_mask_out)
1301 const char *p = NULL;
1302 char *fname_dir = NULL;
1303 char *fname_mask = NULL;
1305 p = strrchr_m(fname_in, '/');
1306 if (!p) {
1307 fname_dir = talloc_strdup(ctx, ".");
1308 fname_mask = talloc_strdup(ctx, fname_in);
1309 } else {
1310 fname_dir = talloc_strndup(ctx, fname_in,
1311 PTR_DIFF(p, fname_in));
1312 fname_mask = talloc_strdup(ctx, p+1);
1315 if (!fname_dir || !fname_mask) {
1316 TALLOC_FREE(fname_dir);
1317 TALLOC_FREE(fname_mask);
1318 return NT_STATUS_NO_MEMORY;
1321 *fname_dir_out = fname_dir;
1322 *fname_mask_out = fname_mask;
1323 return NT_STATUS_OK;
1326 /****************************************************************************
1327 Reply to a search.
1328 Can be called from SMBsearch, SMBffirst or SMBfunique.
1329 ****************************************************************************/
1331 void reply_search(struct smb_request *req)
1333 connection_struct *conn = req->conn;
1334 char *path = NULL;
1335 const char *mask = NULL;
1336 char *directory = NULL;
1337 struct smb_filename *smb_fname = NULL;
1338 char *fname = NULL;
1339 SMB_OFF_T size;
1340 uint32 mode;
1341 struct timespec date;
1342 uint32 dirtype;
1343 unsigned int numentries = 0;
1344 unsigned int maxentries = 0;
1345 bool finished = False;
1346 const char *p;
1347 int status_len;
1348 char status[21];
1349 int dptr_num= -1;
1350 bool check_descend = False;
1351 bool expect_close = False;
1352 NTSTATUS nt_status;
1353 bool mask_contains_wcard = False;
1354 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1355 TALLOC_CTX *ctx = talloc_tos();
1356 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1357 struct dptr_struct *dirptr = NULL;
1358 struct smbd_server_connection *sconn = req->sconn;
1360 START_PROFILE(SMBsearch);
1362 if (req->wct < 2) {
1363 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1364 goto out;
1367 if (lp_posix_pathnames()) {
1368 reply_unknown_new(req, req->cmd);
1369 goto out;
1372 /* If we were called as SMBffirst then we must expect close. */
1373 if(req->cmd == SMBffirst) {
1374 expect_close = True;
1377 reply_outbuf(req, 1, 3);
1378 maxentries = SVAL(req->vwv+0, 0);
1379 dirtype = SVAL(req->vwv+1, 0);
1380 p = (const char *)req->buf + 1;
1381 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1382 &nt_status, &mask_contains_wcard);
1383 if (!NT_STATUS_IS_OK(nt_status)) {
1384 reply_nterror(req, nt_status);
1385 goto out;
1388 p++;
1389 status_len = SVAL(p, 0);
1390 p += 2;
1392 /* dirtype &= ~aDIR; */
1394 if (status_len == 0) {
1395 nt_status = filename_convert(ctx, conn,
1396 req->flags2 & FLAGS2_DFS_PATHNAMES,
1397 path,
1398 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1399 &mask_contains_wcard,
1400 &smb_fname);
1401 if (!NT_STATUS_IS_OK(nt_status)) {
1402 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1403 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1404 ERRSRV, ERRbadpath);
1405 goto out;
1407 reply_nterror(req, nt_status);
1408 goto out;
1411 directory = smb_fname->base_name;
1413 p = strrchr_m(directory,'/');
1414 if ((p != NULL) && (*directory != '/')) {
1415 mask = p + 1;
1416 directory = talloc_strndup(ctx, directory,
1417 PTR_DIFF(p, directory));
1418 } else {
1419 mask = directory;
1420 directory = talloc_strdup(ctx,".");
1423 if (!directory) {
1424 reply_nterror(req, NT_STATUS_NO_MEMORY);
1425 goto out;
1428 memset((char *)status,'\0',21);
1429 SCVAL(status,0,(dirtype & 0x1F));
1431 nt_status = dptr_create(conn,
1432 directory,
1433 True,
1434 expect_close,
1435 req->smbpid,
1436 mask,
1437 mask_contains_wcard,
1438 dirtype,
1439 &dirptr);
1440 if (!NT_STATUS_IS_OK(nt_status)) {
1441 reply_nterror(req, nt_status);
1442 goto out;
1444 dptr_num = dptr_dnum(dirptr);
1445 } else {
1446 int status_dirtype;
1447 const char *dirpath;
1449 memcpy(status,p,21);
1450 status_dirtype = CVAL(status,0) & 0x1F;
1451 if (status_dirtype != (dirtype & 0x1F)) {
1452 dirtype = status_dirtype;
1455 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1456 if (!dirptr) {
1457 goto SearchEmpty;
1459 dirpath = dptr_path(sconn, dptr_num);
1460 directory = talloc_strdup(ctx, dirpath);
1461 if (!directory) {
1462 reply_nterror(req, NT_STATUS_NO_MEMORY);
1463 goto out;
1466 mask = dptr_wcard(sconn, dptr_num);
1467 if (!mask) {
1468 goto SearchEmpty;
1471 * For a 'continue' search we have no string. So
1472 * check from the initial saved string.
1474 mask_contains_wcard = ms_has_wild(mask);
1475 dirtype = dptr_attr(sconn, dptr_num);
1478 DEBUG(4,("dptr_num is %d\n",dptr_num));
1480 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1481 dptr_init_search_op(dirptr);
1483 if ((dirtype&0x1F) == aVOLID) {
1484 char buf[DIR_STRUCT_SIZE];
1485 memcpy(buf,status,21);
1486 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1487 0,aVOLID,0,!allow_long_path_components)) {
1488 reply_nterror(req, NT_STATUS_NO_MEMORY);
1489 goto out;
1491 dptr_fill(sconn, buf+12,dptr_num);
1492 if (dptr_zero(buf+12) && (status_len==0)) {
1493 numentries = 1;
1494 } else {
1495 numentries = 0;
1497 if (message_push_blob(&req->outbuf,
1498 data_blob_const(buf, sizeof(buf)))
1499 == -1) {
1500 reply_nterror(req, NT_STATUS_NO_MEMORY);
1501 goto out;
1503 } else {
1504 unsigned int i;
1505 maxentries = MIN(
1506 maxentries,
1507 ((BUFFER_SIZE -
1508 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1509 /DIR_STRUCT_SIZE));
1511 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1512 directory,lp_dontdescend(SNUM(conn))));
1513 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1514 check_descend = True;
1517 for (i=numentries;(i<maxentries) && !finished;i++) {
1518 finished = !get_dir_entry(ctx,
1519 dirptr,
1520 mask,
1521 dirtype,
1522 &fname,
1523 &size,
1524 &mode,
1525 &date,
1526 check_descend,
1527 ask_sharemode);
1528 if (!finished) {
1529 char buf[DIR_STRUCT_SIZE];
1530 memcpy(buf,status,21);
1531 if (!make_dir_struct(ctx,
1532 buf,
1533 mask,
1534 fname,
1535 size,
1536 mode,
1537 convert_timespec_to_time_t(date),
1538 !allow_long_path_components)) {
1539 reply_nterror(req, NT_STATUS_NO_MEMORY);
1540 goto out;
1542 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1543 break;
1545 if (message_push_blob(&req->outbuf,
1546 data_blob_const(buf, sizeof(buf)))
1547 == -1) {
1548 reply_nterror(req, NT_STATUS_NO_MEMORY);
1549 goto out;
1551 numentries++;
1556 SearchEmpty:
1558 /* If we were called as SMBffirst with smb_search_id == NULL
1559 and no entries were found then return error and close dirptr
1560 (X/Open spec) */
1562 if (numentries == 0) {
1563 dptr_close(sconn, &dptr_num);
1564 } else if(expect_close && status_len == 0) {
1565 /* Close the dptr - we know it's gone */
1566 dptr_close(sconn, &dptr_num);
1569 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1570 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1571 dptr_close(sconn, &dptr_num);
1574 if ((numentries == 0) && !mask_contains_wcard) {
1575 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1576 goto out;
1579 SSVAL(req->outbuf,smb_vwv0,numentries);
1580 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1581 SCVAL(smb_buf(req->outbuf),0,5);
1582 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1584 /* The replies here are never long name. */
1585 SSVAL(req->outbuf, smb_flg2,
1586 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1587 if (!allow_long_path_components) {
1588 SSVAL(req->outbuf, smb_flg2,
1589 SVAL(req->outbuf, smb_flg2)
1590 & (~FLAGS2_LONG_PATH_COMPONENTS));
1593 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1594 SSVAL(req->outbuf, smb_flg2,
1595 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1597 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1598 smb_fn_name(req->cmd),
1599 mask,
1600 directory,
1601 dirtype,
1602 numentries,
1603 maxentries ));
1604 out:
1605 TALLOC_FREE(directory);
1606 TALLOC_FREE(smb_fname);
1607 END_PROFILE(SMBsearch);
1608 return;
1611 /****************************************************************************
1612 Reply to a fclose (stop directory search).
1613 ****************************************************************************/
1615 void reply_fclose(struct smb_request *req)
1617 int status_len;
1618 char status[21];
1619 int dptr_num= -2;
1620 const char *p;
1621 char *path = NULL;
1622 NTSTATUS err;
1623 bool path_contains_wcard = False;
1624 TALLOC_CTX *ctx = talloc_tos();
1625 struct smbd_server_connection *sconn = req->sconn;
1627 START_PROFILE(SMBfclose);
1629 if (lp_posix_pathnames()) {
1630 reply_unknown_new(req, req->cmd);
1631 END_PROFILE(SMBfclose);
1632 return;
1635 p = (const char *)req->buf + 1;
1636 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1637 &err, &path_contains_wcard);
1638 if (!NT_STATUS_IS_OK(err)) {
1639 reply_nterror(req, err);
1640 END_PROFILE(SMBfclose);
1641 return;
1643 p++;
1644 status_len = SVAL(p,0);
1645 p += 2;
1647 if (status_len == 0) {
1648 reply_force_doserror(req, ERRSRV, ERRsrverror);
1649 END_PROFILE(SMBfclose);
1650 return;
1653 memcpy(status,p,21);
1655 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1656 /* Close the dptr - we know it's gone */
1657 dptr_close(sconn, &dptr_num);
1660 reply_outbuf(req, 1, 0);
1661 SSVAL(req->outbuf,smb_vwv0,0);
1663 DEBUG(3,("search close\n"));
1665 END_PROFILE(SMBfclose);
1666 return;
1669 /****************************************************************************
1670 Reply to an open.
1671 ****************************************************************************/
1673 void reply_open(struct smb_request *req)
1675 connection_struct *conn = req->conn;
1676 struct smb_filename *smb_fname = NULL;
1677 char *fname = NULL;
1678 uint32 fattr=0;
1679 SMB_OFF_T size = 0;
1680 time_t mtime=0;
1681 int info;
1682 files_struct *fsp;
1683 int oplock_request;
1684 int deny_mode;
1685 uint32 dos_attr;
1686 uint32 access_mask;
1687 uint32 share_mode;
1688 uint32 create_disposition;
1689 uint32 create_options = 0;
1690 uint32_t private_flags = 0;
1691 NTSTATUS status;
1692 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1693 TALLOC_CTX *ctx = talloc_tos();
1695 START_PROFILE(SMBopen);
1697 if (req->wct < 2) {
1698 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1699 goto out;
1702 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1703 deny_mode = SVAL(req->vwv+0, 0);
1704 dos_attr = SVAL(req->vwv+1, 0);
1706 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1707 STR_TERMINATE, &status);
1708 if (!NT_STATUS_IS_OK(status)) {
1709 reply_nterror(req, status);
1710 goto out;
1713 status = filename_convert(ctx,
1714 conn,
1715 req->flags2 & FLAGS2_DFS_PATHNAMES,
1716 fname,
1718 NULL,
1719 &smb_fname);
1720 if (!NT_STATUS_IS_OK(status)) {
1721 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1722 reply_botherror(req,
1723 NT_STATUS_PATH_NOT_COVERED,
1724 ERRSRV, ERRbadpath);
1725 goto out;
1727 reply_nterror(req, status);
1728 goto out;
1731 if (!map_open_params_to_ntcreate(smb_fname, deny_mode,
1732 OPENX_FILE_EXISTS_OPEN, &access_mask,
1733 &share_mode, &create_disposition,
1734 &create_options, &private_flags)) {
1735 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1736 goto out;
1739 status = SMB_VFS_CREATE_FILE(
1740 conn, /* conn */
1741 req, /* req */
1742 0, /* root_dir_fid */
1743 smb_fname, /* fname */
1744 access_mask, /* access_mask */
1745 share_mode, /* share_access */
1746 create_disposition, /* create_disposition*/
1747 create_options, /* create_options */
1748 dos_attr, /* file_attributes */
1749 oplock_request, /* oplock_request */
1750 0, /* allocation_size */
1751 private_flags,
1752 NULL, /* sd */
1753 NULL, /* ea_list */
1754 &fsp, /* result */
1755 &info); /* pinfo */
1757 if (!NT_STATUS_IS_OK(status)) {
1758 if (open_was_deferred(req->mid)) {
1759 /* We have re-scheduled this call. */
1760 goto out;
1762 reply_openerror(req, status);
1763 goto out;
1766 size = smb_fname->st.st_ex_size;
1767 fattr = dos_mode(conn, smb_fname);
1769 /* Deal with other possible opens having a modified
1770 write time. JRA. */
1771 if (ask_sharemode) {
1772 struct timespec write_time_ts;
1774 ZERO_STRUCT(write_time_ts);
1775 get_file_infos(fsp->file_id, NULL, &write_time_ts);
1776 if (!null_timespec(write_time_ts)) {
1777 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1781 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1783 if (fattr & aDIR) {
1784 DEBUG(3,("attempt to open a directory %s\n",
1785 fsp_str_dbg(fsp)));
1786 close_file(req, fsp, ERROR_CLOSE);
1787 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1788 ERRDOS, ERRnoaccess);
1789 goto out;
1792 reply_outbuf(req, 7, 0);
1793 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1794 SSVAL(req->outbuf,smb_vwv1,fattr);
1795 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1796 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1797 } else {
1798 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1800 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1801 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1803 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1804 SCVAL(req->outbuf,smb_flg,
1805 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1808 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1809 SCVAL(req->outbuf,smb_flg,
1810 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1812 out:
1813 TALLOC_FREE(smb_fname);
1814 END_PROFILE(SMBopen);
1815 return;
1818 /****************************************************************************
1819 Reply to an open and X.
1820 ****************************************************************************/
1822 void reply_open_and_X(struct smb_request *req)
1824 connection_struct *conn = req->conn;
1825 struct smb_filename *smb_fname = NULL;
1826 char *fname = NULL;
1827 uint16 open_flags;
1828 int deny_mode;
1829 uint32 smb_attr;
1830 /* Breakout the oplock request bits so we can set the
1831 reply bits separately. */
1832 int ex_oplock_request;
1833 int core_oplock_request;
1834 int oplock_request;
1835 #if 0
1836 int smb_sattr = SVAL(req->vwv+4, 0);
1837 uint32 smb_time = make_unix_date3(req->vwv+6);
1838 #endif
1839 int smb_ofun;
1840 uint32 fattr=0;
1841 int mtime=0;
1842 int smb_action = 0;
1843 files_struct *fsp;
1844 NTSTATUS status;
1845 uint64_t allocation_size;
1846 ssize_t retval = -1;
1847 uint32 access_mask;
1848 uint32 share_mode;
1849 uint32 create_disposition;
1850 uint32 create_options = 0;
1851 uint32_t private_flags = 0;
1852 TALLOC_CTX *ctx = talloc_tos();
1854 START_PROFILE(SMBopenX);
1856 if (req->wct < 15) {
1857 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1858 goto out;
1861 open_flags = SVAL(req->vwv+2, 0);
1862 deny_mode = SVAL(req->vwv+3, 0);
1863 smb_attr = SVAL(req->vwv+5, 0);
1864 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1865 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1866 oplock_request = ex_oplock_request | core_oplock_request;
1867 smb_ofun = SVAL(req->vwv+8, 0);
1868 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1870 /* If it's an IPC, pass off the pipe handler. */
1871 if (IS_IPC(conn)) {
1872 if (lp_nt_pipe_support()) {
1873 reply_open_pipe_and_X(conn, req);
1874 } else {
1875 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1877 goto out;
1880 /* XXXX we need to handle passed times, sattr and flags */
1881 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1882 STR_TERMINATE, &status);
1883 if (!NT_STATUS_IS_OK(status)) {
1884 reply_nterror(req, status);
1885 goto out;
1888 status = filename_convert(ctx,
1889 conn,
1890 req->flags2 & FLAGS2_DFS_PATHNAMES,
1891 fname,
1893 NULL,
1894 &smb_fname);
1895 if (!NT_STATUS_IS_OK(status)) {
1896 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1897 reply_botherror(req,
1898 NT_STATUS_PATH_NOT_COVERED,
1899 ERRSRV, ERRbadpath);
1900 goto out;
1902 reply_nterror(req, status);
1903 goto out;
1906 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, smb_ofun,
1907 &access_mask, &share_mode,
1908 &create_disposition,
1909 &create_options,
1910 &private_flags)) {
1911 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1912 goto out;
1915 status = SMB_VFS_CREATE_FILE(
1916 conn, /* conn */
1917 req, /* req */
1918 0, /* root_dir_fid */
1919 smb_fname, /* fname */
1920 access_mask, /* access_mask */
1921 share_mode, /* share_access */
1922 create_disposition, /* create_disposition*/
1923 create_options, /* create_options */
1924 smb_attr, /* file_attributes */
1925 oplock_request, /* oplock_request */
1926 0, /* allocation_size */
1927 private_flags,
1928 NULL, /* sd */
1929 NULL, /* ea_list */
1930 &fsp, /* result */
1931 &smb_action); /* pinfo */
1933 if (!NT_STATUS_IS_OK(status)) {
1934 if (open_was_deferred(req->mid)) {
1935 /* We have re-scheduled this call. */
1936 goto out;
1938 reply_openerror(req, status);
1939 goto out;
1942 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1943 if the file is truncated or created. */
1944 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1945 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1946 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1947 close_file(req, fsp, ERROR_CLOSE);
1948 reply_nterror(req, NT_STATUS_DISK_FULL);
1949 goto out;
1951 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1952 if (retval < 0) {
1953 close_file(req, fsp, ERROR_CLOSE);
1954 reply_nterror(req, NT_STATUS_DISK_FULL);
1955 goto out;
1957 smb_fname->st.st_ex_size =
1958 SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
1961 fattr = dos_mode(conn, smb_fname);
1962 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1963 if (fattr & aDIR) {
1964 close_file(req, fsp, ERROR_CLOSE);
1965 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1966 goto out;
1969 /* If the caller set the extended oplock request bit
1970 and we granted one (by whatever means) - set the
1971 correct bit for extended oplock reply.
1974 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1975 smb_action |= EXTENDED_OPLOCK_GRANTED;
1978 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1979 smb_action |= EXTENDED_OPLOCK_GRANTED;
1982 /* If the caller set the core oplock request bit
1983 and we granted one (by whatever means) - set the
1984 correct bit for core oplock reply.
1987 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1988 reply_outbuf(req, 19, 0);
1989 } else {
1990 reply_outbuf(req, 15, 0);
1993 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1994 SCVAL(req->outbuf, smb_flg,
1995 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1998 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1999 SCVAL(req->outbuf, smb_flg,
2000 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2003 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2004 SSVAL(req->outbuf,smb_vwv3,fattr);
2005 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2006 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2007 } else {
2008 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2010 SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size);
2011 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2012 SSVAL(req->outbuf,smb_vwv11,smb_action);
2014 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2015 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2018 chain_reply(req);
2019 out:
2020 TALLOC_FREE(smb_fname);
2021 END_PROFILE(SMBopenX);
2022 return;
2025 /****************************************************************************
2026 Reply to a SMBulogoffX.
2027 ****************************************************************************/
2029 void reply_ulogoffX(struct smb_request *req)
2031 struct smbd_server_connection *sconn = req->sconn;
2032 user_struct *vuser;
2034 START_PROFILE(SMBulogoffX);
2036 vuser = get_valid_user_struct(sconn, req->vuid);
2038 if(vuser == NULL) {
2039 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2040 req->vuid));
2043 /* in user level security we are supposed to close any files
2044 open by this user */
2045 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2046 file_close_user(req->vuid);
2049 invalidate_vuid(sconn, req->vuid);
2051 reply_outbuf(req, 2, 0);
2053 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2055 END_PROFILE(SMBulogoffX);
2056 req->vuid = UID_FIELD_INVALID;
2057 chain_reply(req);
2060 /****************************************************************************
2061 Reply to a mknew or a create.
2062 ****************************************************************************/
2064 void reply_mknew(struct smb_request *req)
2066 connection_struct *conn = req->conn;
2067 struct smb_filename *smb_fname = NULL;
2068 char *fname = NULL;
2069 uint32 fattr = 0;
2070 struct smb_file_time ft;
2071 files_struct *fsp;
2072 int oplock_request = 0;
2073 NTSTATUS status;
2074 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2075 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2076 uint32 create_disposition;
2077 uint32 create_options = 0;
2078 TALLOC_CTX *ctx = talloc_tos();
2080 START_PROFILE(SMBcreate);
2081 ZERO_STRUCT(ft);
2083 if (req->wct < 3) {
2084 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2085 goto out;
2088 fattr = SVAL(req->vwv+0, 0);
2089 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2091 /* mtime. */
2092 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2094 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2095 STR_TERMINATE, &status);
2096 if (!NT_STATUS_IS_OK(status)) {
2097 reply_nterror(req, status);
2098 goto out;
2101 status = filename_convert(ctx,
2102 conn,
2103 req->flags2 & FLAGS2_DFS_PATHNAMES,
2104 fname,
2106 NULL,
2107 &smb_fname);
2108 if (!NT_STATUS_IS_OK(status)) {
2109 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2110 reply_botherror(req,
2111 NT_STATUS_PATH_NOT_COVERED,
2112 ERRSRV, ERRbadpath);
2113 goto out;
2115 reply_nterror(req, status);
2116 goto out;
2119 if (fattr & aVOLID) {
2120 DEBUG(0,("Attempt to create file (%s) with volid set - "
2121 "please report this\n",
2122 smb_fname_str_dbg(smb_fname)));
2125 if(req->cmd == SMBmknew) {
2126 /* We should fail if file exists. */
2127 create_disposition = FILE_CREATE;
2128 } else {
2129 /* Create if file doesn't exist, truncate if it does. */
2130 create_disposition = FILE_OVERWRITE_IF;
2133 status = SMB_VFS_CREATE_FILE(
2134 conn, /* conn */
2135 req, /* req */
2136 0, /* root_dir_fid */
2137 smb_fname, /* fname */
2138 access_mask, /* access_mask */
2139 share_mode, /* share_access */
2140 create_disposition, /* create_disposition*/
2141 create_options, /* create_options */
2142 fattr, /* file_attributes */
2143 oplock_request, /* oplock_request */
2144 0, /* allocation_size */
2145 0, /* private_flags */
2146 NULL, /* sd */
2147 NULL, /* ea_list */
2148 &fsp, /* result */
2149 NULL); /* pinfo */
2151 if (!NT_STATUS_IS_OK(status)) {
2152 if (open_was_deferred(req->mid)) {
2153 /* We have re-scheduled this call. */
2154 goto out;
2156 reply_openerror(req, status);
2157 goto out;
2160 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2161 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2162 if (!NT_STATUS_IS_OK(status)) {
2163 END_PROFILE(SMBcreate);
2164 goto out;
2167 reply_outbuf(req, 1, 0);
2168 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2170 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2171 SCVAL(req->outbuf,smb_flg,
2172 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2175 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2176 SCVAL(req->outbuf,smb_flg,
2177 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2180 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2181 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2182 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2183 (unsigned int)fattr));
2185 out:
2186 TALLOC_FREE(smb_fname);
2187 END_PROFILE(SMBcreate);
2188 return;
2191 /****************************************************************************
2192 Reply to a create temporary file.
2193 ****************************************************************************/
2195 void reply_ctemp(struct smb_request *req)
2197 connection_struct *conn = req->conn;
2198 struct smb_filename *smb_fname = NULL;
2199 char *fname = NULL;
2200 uint32 fattr;
2201 files_struct *fsp;
2202 int oplock_request;
2203 int tmpfd;
2204 char *s;
2205 NTSTATUS status;
2206 TALLOC_CTX *ctx = talloc_tos();
2208 START_PROFILE(SMBctemp);
2210 if (req->wct < 3) {
2211 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2212 goto out;
2215 fattr = SVAL(req->vwv+0, 0);
2216 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2218 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2219 STR_TERMINATE, &status);
2220 if (!NT_STATUS_IS_OK(status)) {
2221 reply_nterror(req, status);
2222 goto out;
2224 if (*fname) {
2225 fname = talloc_asprintf(ctx,
2226 "%s/TMXXXXXX",
2227 fname);
2228 } else {
2229 fname = talloc_strdup(ctx, "TMXXXXXX");
2232 if (!fname) {
2233 reply_nterror(req, NT_STATUS_NO_MEMORY);
2234 goto out;
2237 status = filename_convert(ctx, conn,
2238 req->flags2 & FLAGS2_DFS_PATHNAMES,
2239 fname,
2241 NULL,
2242 &smb_fname);
2243 if (!NT_STATUS_IS_OK(status)) {
2244 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2245 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2246 ERRSRV, ERRbadpath);
2247 goto out;
2249 reply_nterror(req, status);
2250 goto out;
2253 tmpfd = mkstemp(smb_fname->base_name);
2254 if (tmpfd == -1) {
2255 reply_nterror(req, map_nt_error_from_unix(errno));
2256 goto out;
2259 SMB_VFS_STAT(conn, smb_fname);
2261 /* We should fail if file does not exist. */
2262 status = SMB_VFS_CREATE_FILE(
2263 conn, /* conn */
2264 req, /* req */
2265 0, /* root_dir_fid */
2266 smb_fname, /* fname */
2267 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2268 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2269 FILE_OPEN, /* create_disposition*/
2270 0, /* create_options */
2271 fattr, /* file_attributes */
2272 oplock_request, /* oplock_request */
2273 0, /* allocation_size */
2274 0, /* private_flags */
2275 NULL, /* sd */
2276 NULL, /* ea_list */
2277 &fsp, /* result */
2278 NULL); /* pinfo */
2280 /* close fd from mkstemp() */
2281 close(tmpfd);
2283 if (!NT_STATUS_IS_OK(status)) {
2284 if (open_was_deferred(req->mid)) {
2285 /* We have re-scheduled this call. */
2286 goto out;
2288 reply_openerror(req, status);
2289 goto out;
2292 reply_outbuf(req, 1, 0);
2293 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2295 /* the returned filename is relative to the directory */
2296 s = strrchr_m(fsp->fsp_name->base_name, '/');
2297 if (!s) {
2298 s = fsp->fsp_name->base_name;
2299 } else {
2300 s++;
2303 #if 0
2304 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2305 thing in the byte section. JRA */
2306 SSVALS(p, 0, -1); /* what is this? not in spec */
2307 #endif
2308 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2309 == -1) {
2310 reply_nterror(req, NT_STATUS_NO_MEMORY);
2311 goto out;
2314 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2315 SCVAL(req->outbuf, smb_flg,
2316 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2319 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2320 SCVAL(req->outbuf, smb_flg,
2321 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2324 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2325 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2326 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2327 out:
2328 TALLOC_FREE(smb_fname);
2329 END_PROFILE(SMBctemp);
2330 return;
2333 /*******************************************************************
2334 Check if a user is allowed to rename a file.
2335 ********************************************************************/
2337 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2338 uint16 dirtype)
2340 uint32 fmode;
2342 if (!CAN_WRITE(conn)) {
2343 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2346 fmode = dos_mode(conn, fsp->fsp_name);
2347 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2348 return NT_STATUS_NO_SUCH_FILE;
2351 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2352 if (fsp->posix_open) {
2353 return NT_STATUS_OK;
2356 /* If no pathnames are open below this
2357 directory, allow the rename. */
2359 if (file_find_subpath(fsp)) {
2360 return NT_STATUS_ACCESS_DENIED;
2362 return NT_STATUS_OK;
2365 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2366 return NT_STATUS_OK;
2369 return NT_STATUS_ACCESS_DENIED;
2372 /*******************************************************************
2373 * unlink a file with all relevant access checks
2374 *******************************************************************/
2376 static NTSTATUS do_unlink(connection_struct *conn,
2377 struct smb_request *req,
2378 struct smb_filename *smb_fname,
2379 uint32 dirtype)
2381 uint32 fattr;
2382 files_struct *fsp;
2383 uint32 dirtype_orig = dirtype;
2384 NTSTATUS status;
2385 int ret;
2386 bool posix_paths = lp_posix_pathnames();
2388 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2389 smb_fname_str_dbg(smb_fname),
2390 dirtype));
2392 if (!CAN_WRITE(conn)) {
2393 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2396 if (posix_paths) {
2397 ret = SMB_VFS_LSTAT(conn, smb_fname);
2398 } else {
2399 ret = SMB_VFS_STAT(conn, smb_fname);
2401 if (ret != 0) {
2402 return map_nt_error_from_unix(errno);
2405 fattr = dos_mode(conn, smb_fname);
2407 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2408 dirtype = aDIR|aARCH|aRONLY;
2411 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2412 if (!dirtype) {
2413 return NT_STATUS_NO_SUCH_FILE;
2416 if (!dir_check_ftype(conn, fattr, dirtype)) {
2417 if (fattr & aDIR) {
2418 return NT_STATUS_FILE_IS_A_DIRECTORY;
2420 return NT_STATUS_NO_SUCH_FILE;
2423 if (dirtype_orig & 0x8000) {
2424 /* These will never be set for POSIX. */
2425 return NT_STATUS_NO_SUCH_FILE;
2428 #if 0
2429 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2430 return NT_STATUS_FILE_IS_A_DIRECTORY;
2433 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2434 return NT_STATUS_NO_SUCH_FILE;
2437 if (dirtype & 0xFF00) {
2438 /* These will never be set for POSIX. */
2439 return NT_STATUS_NO_SUCH_FILE;
2442 dirtype &= 0xFF;
2443 if (!dirtype) {
2444 return NT_STATUS_NO_SUCH_FILE;
2447 /* Can't delete a directory. */
2448 if (fattr & aDIR) {
2449 return NT_STATUS_FILE_IS_A_DIRECTORY;
2451 #endif
2453 #if 0 /* JRATEST */
2454 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2455 return NT_STATUS_OBJECT_NAME_INVALID;
2456 #endif /* JRATEST */
2458 /* On open checks the open itself will check the share mode, so
2459 don't do it here as we'll get it wrong. */
2461 status = SMB_VFS_CREATE_FILE
2462 (conn, /* conn */
2463 req, /* req */
2464 0, /* root_dir_fid */
2465 smb_fname, /* fname */
2466 DELETE_ACCESS, /* access_mask */
2467 FILE_SHARE_NONE, /* share_access */
2468 FILE_OPEN, /* create_disposition*/
2469 FILE_NON_DIRECTORY_FILE, /* create_options */
2470 /* file_attributes */
2471 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2472 FILE_ATTRIBUTE_NORMAL,
2473 0, /* oplock_request */
2474 0, /* allocation_size */
2475 0, /* private_flags */
2476 NULL, /* sd */
2477 NULL, /* ea_list */
2478 &fsp, /* result */
2479 NULL); /* pinfo */
2481 if (!NT_STATUS_IS_OK(status)) {
2482 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2483 nt_errstr(status)));
2484 return status;
2487 status = can_set_delete_on_close(fsp, fattr);
2488 if (!NT_STATUS_IS_OK(status)) {
2489 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2490 "(%s)\n",
2491 smb_fname_str_dbg(smb_fname),
2492 nt_errstr(status)));
2493 close_file(req, fsp, NORMAL_CLOSE);
2494 return status;
2497 /* The set is across all open files on this dev/inode pair. */
2498 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2499 close_file(req, fsp, NORMAL_CLOSE);
2500 return NT_STATUS_ACCESS_DENIED;
2503 return close_file(req, fsp, NORMAL_CLOSE);
2506 /****************************************************************************
2507 The guts of the unlink command, split out so it may be called by the NT SMB
2508 code.
2509 ****************************************************************************/
2511 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2512 uint32 dirtype, struct smb_filename *smb_fname,
2513 bool has_wild)
2515 char *fname_dir = NULL;
2516 char *fname_mask = NULL;
2517 int count=0;
2518 NTSTATUS status = NT_STATUS_OK;
2519 TALLOC_CTX *ctx = talloc_tos();
2521 /* Split up the directory from the filename/mask. */
2522 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2523 &fname_dir, &fname_mask);
2524 if (!NT_STATUS_IS_OK(status)) {
2525 goto out;
2529 * We should only check the mangled cache
2530 * here if unix_convert failed. This means
2531 * that the path in 'mask' doesn't exist
2532 * on the file system and so we need to look
2533 * for a possible mangle. This patch from
2534 * Tine Smukavec <valentin.smukavec@hermes.si>.
2537 if (!VALID_STAT(smb_fname->st) &&
2538 mangle_is_mangled(fname_mask, conn->params)) {
2539 char *new_mask = NULL;
2540 mangle_lookup_name_from_8_3(ctx, fname_mask,
2541 &new_mask, conn->params);
2542 if (new_mask) {
2543 TALLOC_FREE(fname_mask);
2544 fname_mask = new_mask;
2548 if (!has_wild) {
2551 * Only one file needs to be unlinked. Append the mask back
2552 * onto the directory.
2554 TALLOC_FREE(smb_fname->base_name);
2555 smb_fname->base_name = talloc_asprintf(smb_fname,
2556 "%s/%s",
2557 fname_dir,
2558 fname_mask);
2559 if (!smb_fname->base_name) {
2560 status = NT_STATUS_NO_MEMORY;
2561 goto out;
2563 if (dirtype == 0) {
2564 dirtype = FILE_ATTRIBUTE_NORMAL;
2567 status = check_name(conn, smb_fname->base_name);
2568 if (!NT_STATUS_IS_OK(status)) {
2569 goto out;
2572 status = do_unlink(conn, req, smb_fname, dirtype);
2573 if (!NT_STATUS_IS_OK(status)) {
2574 goto out;
2577 count++;
2578 } else {
2579 struct smb_Dir *dir_hnd = NULL;
2580 long offset = 0;
2581 const char *dname = NULL;
2582 char *talloced = NULL;
2584 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2585 status = NT_STATUS_OBJECT_NAME_INVALID;
2586 goto out;
2589 if (strequal(fname_mask,"????????.???")) {
2590 TALLOC_FREE(fname_mask);
2591 fname_mask = talloc_strdup(ctx, "*");
2592 if (!fname_mask) {
2593 status = NT_STATUS_NO_MEMORY;
2594 goto out;
2598 status = check_name(conn, fname_dir);
2599 if (!NT_STATUS_IS_OK(status)) {
2600 goto out;
2603 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2604 dirtype);
2605 if (dir_hnd == NULL) {
2606 status = map_nt_error_from_unix(errno);
2607 goto out;
2610 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2611 the pattern matches against the long name, otherwise the short name
2612 We don't implement this yet XXXX
2615 status = NT_STATUS_NO_SUCH_FILE;
2617 while ((dname = ReadDirName(dir_hnd, &offset,
2618 &smb_fname->st, &talloced))) {
2619 TALLOC_CTX *frame = talloc_stackframe();
2621 if (!is_visible_file(conn, fname_dir, dname,
2622 &smb_fname->st, true)) {
2623 TALLOC_FREE(frame);
2624 TALLOC_FREE(talloced);
2625 continue;
2628 /* Quick check for "." and ".." */
2629 if (ISDOT(dname) || ISDOTDOT(dname)) {
2630 TALLOC_FREE(frame);
2631 TALLOC_FREE(talloced);
2632 continue;
2635 if(!mask_match(dname, fname_mask,
2636 conn->case_sensitive)) {
2637 TALLOC_FREE(frame);
2638 TALLOC_FREE(talloced);
2639 continue;
2642 TALLOC_FREE(smb_fname->base_name);
2643 smb_fname->base_name =
2644 talloc_asprintf(smb_fname, "%s/%s",
2645 fname_dir, dname);
2647 if (!smb_fname->base_name) {
2648 TALLOC_FREE(dir_hnd);
2649 status = NT_STATUS_NO_MEMORY;
2650 TALLOC_FREE(frame);
2651 TALLOC_FREE(talloced);
2652 goto out;
2655 status = check_name(conn, smb_fname->base_name);
2656 if (!NT_STATUS_IS_OK(status)) {
2657 TALLOC_FREE(dir_hnd);
2658 TALLOC_FREE(frame);
2659 TALLOC_FREE(talloced);
2660 goto out;
2663 status = do_unlink(conn, req, smb_fname, dirtype);
2664 if (!NT_STATUS_IS_OK(status)) {
2665 TALLOC_FREE(frame);
2666 TALLOC_FREE(talloced);
2667 continue;
2670 count++;
2671 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2672 smb_fname->base_name));
2674 TALLOC_FREE(frame);
2675 TALLOC_FREE(talloced);
2677 TALLOC_FREE(dir_hnd);
2680 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2681 status = map_nt_error_from_unix(errno);
2684 out:
2685 TALLOC_FREE(fname_dir);
2686 TALLOC_FREE(fname_mask);
2687 return status;
2690 /****************************************************************************
2691 Reply to a unlink
2692 ****************************************************************************/
2694 void reply_unlink(struct smb_request *req)
2696 connection_struct *conn = req->conn;
2697 char *name = NULL;
2698 struct smb_filename *smb_fname = NULL;
2699 uint32 dirtype;
2700 NTSTATUS status;
2701 bool path_contains_wcard = False;
2702 TALLOC_CTX *ctx = talloc_tos();
2704 START_PROFILE(SMBunlink);
2706 if (req->wct < 1) {
2707 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2708 goto out;
2711 dirtype = SVAL(req->vwv+0, 0);
2713 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2714 STR_TERMINATE, &status,
2715 &path_contains_wcard);
2716 if (!NT_STATUS_IS_OK(status)) {
2717 reply_nterror(req, status);
2718 goto out;
2721 status = filename_convert(ctx, conn,
2722 req->flags2 & FLAGS2_DFS_PATHNAMES,
2723 name,
2724 UCF_COND_ALLOW_WCARD_LCOMP,
2725 &path_contains_wcard,
2726 &smb_fname);
2727 if (!NT_STATUS_IS_OK(status)) {
2728 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2729 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2730 ERRSRV, ERRbadpath);
2731 goto out;
2733 reply_nterror(req, status);
2734 goto out;
2737 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2739 status = unlink_internals(conn, req, dirtype, smb_fname,
2740 path_contains_wcard);
2741 if (!NT_STATUS_IS_OK(status)) {
2742 if (open_was_deferred(req->mid)) {
2743 /* We have re-scheduled this call. */
2744 goto out;
2746 reply_nterror(req, status);
2747 goto out;
2750 reply_outbuf(req, 0, 0);
2751 out:
2752 TALLOC_FREE(smb_fname);
2753 END_PROFILE(SMBunlink);
2754 return;
2757 /****************************************************************************
2758 Fail for readbraw.
2759 ****************************************************************************/
2761 static void fail_readraw(void)
2763 const char *errstr = talloc_asprintf(talloc_tos(),
2764 "FAIL ! reply_readbraw: socket write fail (%s)",
2765 strerror(errno));
2766 if (!errstr) {
2767 errstr = "";
2769 exit_server_cleanly(errstr);
2772 /****************************************************************************
2773 Fake (read/write) sendfile. Returns -1 on read or write fail.
2774 ****************************************************************************/
2776 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2777 size_t nread)
2779 size_t bufsize;
2780 size_t tosend = nread;
2781 char *buf;
2783 if (nread == 0) {
2784 return 0;
2787 bufsize = MIN(nread, 65536);
2789 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2790 return -1;
2793 while (tosend > 0) {
2794 ssize_t ret;
2795 size_t cur_read;
2797 if (tosend > bufsize) {
2798 cur_read = bufsize;
2799 } else {
2800 cur_read = tosend;
2802 ret = read_file(fsp,buf,startpos,cur_read);
2803 if (ret == -1) {
2804 SAFE_FREE(buf);
2805 return -1;
2808 /* If we had a short read, fill with zeros. */
2809 if (ret < cur_read) {
2810 memset(buf + ret, '\0', cur_read - ret);
2813 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
2814 != cur_read) {
2815 SAFE_FREE(buf);
2816 return -1;
2818 tosend -= cur_read;
2819 startpos += cur_read;
2822 SAFE_FREE(buf);
2823 return (ssize_t)nread;
2826 #if defined(WITH_SENDFILE)
2827 /****************************************************************************
2828 Deal with the case of sendfile reading less bytes from the file than
2829 requested. Fill with zeros (all we can do).
2830 ****************************************************************************/
2832 static void sendfile_short_send(files_struct *fsp,
2833 ssize_t nread,
2834 size_t headersize,
2835 size_t smb_maxcnt)
2837 #define SHORT_SEND_BUFSIZE 1024
2838 if (nread < headersize) {
2839 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2840 "header for file %s (%s). Terminating\n",
2841 fsp_str_dbg(fsp), strerror(errno)));
2842 exit_server_cleanly("sendfile_short_send failed");
2845 nread -= headersize;
2847 if (nread < smb_maxcnt) {
2848 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2849 if (!buf) {
2850 exit_server_cleanly("sendfile_short_send: "
2851 "malloc failed");
2854 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2855 "with zeros !\n", fsp_str_dbg(fsp)));
2857 while (nread < smb_maxcnt) {
2859 * We asked for the real file size and told sendfile
2860 * to not go beyond the end of the file. But it can
2861 * happen that in between our fstat call and the
2862 * sendfile call the file was truncated. This is very
2863 * bad because we have already announced the larger
2864 * number of bytes to the client.
2866 * The best we can do now is to send 0-bytes, just as
2867 * a read from a hole in a sparse file would do.
2869 * This should happen rarely enough that I don't care
2870 * about efficiency here :-)
2872 size_t to_write;
2874 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2875 if (write_data(fsp->conn->sconn->sock, buf, to_write)
2876 != to_write) {
2877 exit_server_cleanly("sendfile_short_send: "
2878 "write_data failed");
2880 nread += to_write;
2882 SAFE_FREE(buf);
2885 #endif /* defined WITH_SENDFILE */
2887 /****************************************************************************
2888 Return a readbraw error (4 bytes of zero).
2889 ****************************************************************************/
2891 static void reply_readbraw_error(struct smbd_server_connection *sconn)
2893 char header[4];
2895 SIVAL(header,0,0);
2897 smbd_lock_socket(sconn);
2898 if (write_data(sconn->sock,header,4) != 4) {
2899 fail_readraw();
2901 smbd_unlock_socket(sconn);
2904 /****************************************************************************
2905 Use sendfile in readbraw.
2906 ****************************************************************************/
2908 static void send_file_readbraw(connection_struct *conn,
2909 struct smb_request *req,
2910 files_struct *fsp,
2911 SMB_OFF_T startpos,
2912 size_t nread,
2913 ssize_t mincount)
2915 struct smbd_server_connection *sconn = req->sconn;
2916 char *outbuf = NULL;
2917 ssize_t ret=0;
2919 #if defined(WITH_SENDFILE)
2921 * We can only use sendfile on a non-chained packet
2922 * but we can use on a non-oplocked file. tridge proved this
2923 * on a train in Germany :-). JRA.
2924 * reply_readbraw has already checked the length.
2927 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2928 (fsp->wcp == NULL) &&
2929 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
2930 ssize_t sendfile_read = -1;
2931 char header[4];
2932 DATA_BLOB header_blob;
2934 _smb_setlen(header,nread);
2935 header_blob = data_blob_const(header, 4);
2937 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
2938 &header_blob, startpos,
2939 nread);
2940 if (sendfile_read == -1) {
2941 /* Returning ENOSYS means no data at all was sent.
2942 * Do this as a normal read. */
2943 if (errno == ENOSYS) {
2944 goto normal_readbraw;
2948 * Special hack for broken Linux with no working sendfile. If we
2949 * return EINTR we sent the header but not the rest of the data.
2950 * Fake this up by doing read/write calls.
2952 if (errno == EINTR) {
2953 /* Ensure we don't do this again. */
2954 set_use_sendfile(SNUM(conn), False);
2955 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2957 if (fake_sendfile(fsp, startpos, nread) == -1) {
2958 DEBUG(0,("send_file_readbraw: "
2959 "fake_sendfile failed for "
2960 "file %s (%s).\n",
2961 fsp_str_dbg(fsp),
2962 strerror(errno)));
2963 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2965 return;
2968 DEBUG(0,("send_file_readbraw: sendfile failed for "
2969 "file %s (%s). Terminating\n",
2970 fsp_str_dbg(fsp), strerror(errno)));
2971 exit_server_cleanly("send_file_readbraw sendfile failed");
2972 } else if (sendfile_read == 0) {
2974 * Some sendfile implementations return 0 to indicate
2975 * that there was a short read, but nothing was
2976 * actually written to the socket. In this case,
2977 * fallback to the normal read path so the header gets
2978 * the correct byte count.
2980 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2981 "bytes falling back to the normal read: "
2982 "%s\n", fsp_str_dbg(fsp)));
2983 goto normal_readbraw;
2986 /* Deal with possible short send. */
2987 if (sendfile_read != 4+nread) {
2988 sendfile_short_send(fsp, sendfile_read, 4, nread);
2990 return;
2993 normal_readbraw:
2994 #endif
2996 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2997 if (!outbuf) {
2998 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2999 (unsigned)(nread+4)));
3000 reply_readbraw_error(sconn);
3001 return;
3004 if (nread > 0) {
3005 ret = read_file(fsp,outbuf+4,startpos,nread);
3006 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3007 if (ret < mincount)
3008 ret = 0;
3009 #else
3010 if (ret < nread)
3011 ret = 0;
3012 #endif
3015 _smb_setlen(outbuf,ret);
3016 if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret)
3017 fail_readraw();
3019 TALLOC_FREE(outbuf);
3022 /****************************************************************************
3023 Reply to a readbraw (core+ protocol).
3024 ****************************************************************************/
3026 void reply_readbraw(struct smb_request *req)
3028 connection_struct *conn = req->conn;
3029 struct smbd_server_connection *sconn = req->sconn;
3030 ssize_t maxcount,mincount;
3031 size_t nread = 0;
3032 SMB_OFF_T startpos;
3033 files_struct *fsp;
3034 struct lock_struct lock;
3035 SMB_OFF_T size = 0;
3037 START_PROFILE(SMBreadbraw);
3039 if (srv_is_signing_active(sconn) ||
3040 is_encrypted_packet(req->inbuf)) {
3041 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3042 "raw reads/writes are disallowed.");
3045 if (req->wct < 8) {
3046 reply_readbraw_error(sconn);
3047 END_PROFILE(SMBreadbraw);
3048 return;
3051 if (sconn->smb1.echo_handler.trusted_fde) {
3052 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3053 "'async smb echo handler = yes'\n"));
3054 reply_readbraw_error(sconn);
3055 END_PROFILE(SMBreadbraw);
3056 return;
3060 * Special check if an oplock break has been issued
3061 * and the readraw request croses on the wire, we must
3062 * return a zero length response here.
3065 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3068 * We have to do a check_fsp by hand here, as
3069 * we must always return 4 zero bytes on error,
3070 * not a NTSTATUS.
3073 if (!fsp || !conn || conn != fsp->conn ||
3074 req->vuid != fsp->vuid ||
3075 fsp->is_directory || fsp->fh->fd == -1) {
3077 * fsp could be NULL here so use the value from the packet. JRA.
3079 DEBUG(3,("reply_readbraw: fnum %d not valid "
3080 "- cache prime?\n",
3081 (int)SVAL(req->vwv+0, 0)));
3082 reply_readbraw_error(sconn);
3083 END_PROFILE(SMBreadbraw);
3084 return;
3087 /* Do a "by hand" version of CHECK_READ. */
3088 if (!(fsp->can_read ||
3089 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3090 (fsp->access_mask & FILE_EXECUTE)))) {
3091 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3092 (int)SVAL(req->vwv+0, 0)));
3093 reply_readbraw_error(sconn);
3094 END_PROFILE(SMBreadbraw);
3095 return;
3098 flush_write_cache(fsp, READRAW_FLUSH);
3100 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3101 if(req->wct == 10) {
3103 * This is a large offset (64 bit) read.
3105 #ifdef LARGE_SMB_OFF_T
3107 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3109 #else /* !LARGE_SMB_OFF_T */
3112 * Ensure we haven't been sent a >32 bit offset.
3115 if(IVAL(req->vwv+8, 0) != 0) {
3116 DEBUG(0,("reply_readbraw: large offset "
3117 "(%x << 32) used and we don't support "
3118 "64 bit offsets.\n",
3119 (unsigned int)IVAL(req->vwv+8, 0) ));
3120 reply_readbraw_error();
3121 END_PROFILE(SMBreadbraw);
3122 return;
3125 #endif /* LARGE_SMB_OFF_T */
3127 if(startpos < 0) {
3128 DEBUG(0,("reply_readbraw: negative 64 bit "
3129 "readraw offset (%.0f) !\n",
3130 (double)startpos ));
3131 reply_readbraw_error(sconn);
3132 END_PROFILE(SMBreadbraw);
3133 return;
3137 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3138 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3140 /* ensure we don't overrun the packet size */
3141 maxcount = MIN(65535,maxcount);
3143 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3144 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3145 &lock);
3147 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3148 reply_readbraw_error(sconn);
3149 END_PROFILE(SMBreadbraw);
3150 return;
3153 if (fsp_stat(fsp) == 0) {
3154 size = fsp->fsp_name->st.st_ex_size;
3157 if (startpos >= size) {
3158 nread = 0;
3159 } else {
3160 nread = MIN(maxcount,(size - startpos));
3163 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3164 if (nread < mincount)
3165 nread = 0;
3166 #endif
3168 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3169 "min=%lu nread=%lu\n",
3170 fsp->fnum, (double)startpos,
3171 (unsigned long)maxcount,
3172 (unsigned long)mincount,
3173 (unsigned long)nread ) );
3175 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3177 DEBUG(5,("reply_readbraw finished\n"));
3179 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3181 END_PROFILE(SMBreadbraw);
3182 return;
3185 #undef DBGC_CLASS
3186 #define DBGC_CLASS DBGC_LOCKING
3188 /****************************************************************************
3189 Reply to a lockread (core+ protocol).
3190 ****************************************************************************/
3192 void reply_lockread(struct smb_request *req)
3194 connection_struct *conn = req->conn;
3195 ssize_t nread = -1;
3196 char *data;
3197 SMB_OFF_T startpos;
3198 size_t numtoread;
3199 NTSTATUS status;
3200 files_struct *fsp;
3201 struct byte_range_lock *br_lck = NULL;
3202 char *p = NULL;
3203 struct smbd_server_connection *sconn = req->sconn;
3205 START_PROFILE(SMBlockread);
3207 if (req->wct < 5) {
3208 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3209 END_PROFILE(SMBlockread);
3210 return;
3213 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3215 if (!check_fsp(conn, req, fsp)) {
3216 END_PROFILE(SMBlockread);
3217 return;
3220 if (!CHECK_READ(fsp,req)) {
3221 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3222 END_PROFILE(SMBlockread);
3223 return;
3226 numtoread = SVAL(req->vwv+1, 0);
3227 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3229 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3231 reply_outbuf(req, 5, numtoread + 3);
3233 data = smb_buf(req->outbuf) + 3;
3236 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3237 * protocol request that predates the read/write lock concept.
3238 * Thus instead of asking for a read lock here we need to ask
3239 * for a write lock. JRA.
3240 * Note that the requested lock size is unaffected by max_recv.
3243 br_lck = do_lock(req->sconn->msg_ctx,
3244 fsp,
3245 (uint64_t)req->smbpid,
3246 (uint64_t)numtoread,
3247 (uint64_t)startpos,
3248 WRITE_LOCK,
3249 WINDOWS_LOCK,
3250 False, /* Non-blocking lock. */
3251 &status,
3252 NULL,
3253 NULL);
3254 TALLOC_FREE(br_lck);
3256 if (NT_STATUS_V(status)) {
3257 reply_nterror(req, status);
3258 END_PROFILE(SMBlockread);
3259 return;
3263 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3266 if (numtoread > sconn->smb1.negprot.max_recv) {
3267 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3268 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3269 (unsigned int)numtoread,
3270 (unsigned int)sconn->smb1.negprot.max_recv));
3271 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3273 nread = read_file(fsp,data,startpos,numtoread);
3275 if (nread < 0) {
3276 reply_nterror(req, map_nt_error_from_unix(errno));
3277 END_PROFILE(SMBlockread);
3278 return;
3281 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3283 SSVAL(req->outbuf,smb_vwv0,nread);
3284 SSVAL(req->outbuf,smb_vwv5,nread+3);
3285 p = smb_buf(req->outbuf);
3286 SCVAL(p,0,0); /* pad byte. */
3287 SSVAL(p,1,nread);
3289 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3290 fsp->fnum, (int)numtoread, (int)nread));
3292 END_PROFILE(SMBlockread);
3293 return;
3296 #undef DBGC_CLASS
3297 #define DBGC_CLASS DBGC_ALL
3299 /****************************************************************************
3300 Reply to a read.
3301 ****************************************************************************/
3303 void reply_read(struct smb_request *req)
3305 connection_struct *conn = req->conn;
3306 size_t numtoread;
3307 ssize_t nread = 0;
3308 char *data;
3309 SMB_OFF_T startpos;
3310 int outsize = 0;
3311 files_struct *fsp;
3312 struct lock_struct lock;
3313 struct smbd_server_connection *sconn = req->sconn;
3315 START_PROFILE(SMBread);
3317 if (req->wct < 3) {
3318 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3319 END_PROFILE(SMBread);
3320 return;
3323 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3325 if (!check_fsp(conn, req, fsp)) {
3326 END_PROFILE(SMBread);
3327 return;
3330 if (!CHECK_READ(fsp,req)) {
3331 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3332 END_PROFILE(SMBread);
3333 return;
3336 numtoread = SVAL(req->vwv+1, 0);
3337 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3339 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3342 * The requested read size cannot be greater than max_recv. JRA.
3344 if (numtoread > sconn->smb1.negprot.max_recv) {
3345 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3346 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3347 (unsigned int)numtoread,
3348 (unsigned int)sconn->smb1.negprot.max_recv));
3349 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3352 reply_outbuf(req, 5, numtoread+3);
3354 data = smb_buf(req->outbuf) + 3;
3356 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3357 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3358 &lock);
3360 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3361 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3362 END_PROFILE(SMBread);
3363 return;
3366 if (numtoread > 0)
3367 nread = read_file(fsp,data,startpos,numtoread);
3369 if (nread < 0) {
3370 reply_nterror(req, map_nt_error_from_unix(errno));
3371 goto strict_unlock;
3374 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3376 SSVAL(req->outbuf,smb_vwv0,nread);
3377 SSVAL(req->outbuf,smb_vwv5,nread+3);
3378 SCVAL(smb_buf(req->outbuf),0,1);
3379 SSVAL(smb_buf(req->outbuf),1,nread);
3381 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3382 fsp->fnum, (int)numtoread, (int)nread ) );
3384 strict_unlock:
3385 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3387 END_PROFILE(SMBread);
3388 return;
3391 /****************************************************************************
3392 Setup readX header.
3393 ****************************************************************************/
3395 static int setup_readX_header(struct smb_request *req, char *outbuf,
3396 size_t smb_maxcnt)
3398 int outsize;
3399 char *data;
3401 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3402 data = smb_buf(outbuf);
3404 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3406 SCVAL(outbuf,smb_vwv0,0xFF);
3407 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3408 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3409 SSVAL(outbuf,smb_vwv6,
3410 req_wct_ofs(req)
3411 + 1 /* the wct field */
3412 + 12 * sizeof(uint16_t) /* vwv */
3413 + 2); /* the buflen field */
3414 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3415 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3416 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3417 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3418 return outsize;
3421 /****************************************************************************
3422 Reply to a read and X - possibly using sendfile.
3423 ****************************************************************************/
3425 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3426 files_struct *fsp, SMB_OFF_T startpos,
3427 size_t smb_maxcnt)
3429 ssize_t nread = -1;
3430 struct lock_struct lock;
3431 int saved_errno = 0;
3433 if(fsp_stat(fsp) == -1) {
3434 reply_nterror(req, map_nt_error_from_unix(errno));
3435 return;
3438 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3439 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3440 &lock);
3442 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3443 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3444 return;
3447 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3448 (startpos > fsp->fsp_name->st.st_ex_size)
3449 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3451 * We already know that we would do a short read, so don't
3452 * try the sendfile() path.
3454 goto nosendfile_read;
3457 #if defined(WITH_SENDFILE)
3459 * We can only use sendfile on a non-chained packet
3460 * but we can use on a non-oplocked file. tridge proved this
3461 * on a train in Germany :-). JRA.
3464 if (!req_is_in_chain(req) &&
3465 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3466 (fsp->wcp == NULL) &&
3467 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3468 uint8 headerbuf[smb_size + 12 * 2];
3469 DATA_BLOB header;
3472 * Set up the packet header before send. We
3473 * assume here the sendfile will work (get the
3474 * correct amount of data).
3477 header = data_blob_const(headerbuf, sizeof(headerbuf));
3479 construct_reply_common_req(req, (char *)headerbuf);
3480 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3482 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3483 startpos, smb_maxcnt);
3484 if (nread == -1) {
3485 /* Returning ENOSYS means no data at all was sent.
3486 Do this as a normal read. */
3487 if (errno == ENOSYS) {
3488 goto normal_read;
3492 * Special hack for broken Linux with no working sendfile. If we
3493 * return EINTR we sent the header but not the rest of the data.
3494 * Fake this up by doing read/write calls.
3497 if (errno == EINTR) {
3498 /* Ensure we don't do this again. */
3499 set_use_sendfile(SNUM(conn), False);
3500 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3501 nread = fake_sendfile(fsp, startpos,
3502 smb_maxcnt);
3503 if (nread == -1) {
3504 DEBUG(0,("send_file_readX: "
3505 "fake_sendfile failed for "
3506 "file %s (%s).\n",
3507 fsp_str_dbg(fsp),
3508 strerror(errno)));
3509 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3511 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3512 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3513 /* No outbuf here means successful sendfile. */
3514 goto strict_unlock;
3517 DEBUG(0,("send_file_readX: sendfile failed for file "
3518 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3519 strerror(errno)));
3520 exit_server_cleanly("send_file_readX sendfile failed");
3521 } else if (nread == 0) {
3523 * Some sendfile implementations return 0 to indicate
3524 * that there was a short read, but nothing was
3525 * actually written to the socket. In this case,
3526 * fallback to the normal read path so the header gets
3527 * the correct byte count.
3529 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3530 "falling back to the normal read: %s\n",
3531 fsp_str_dbg(fsp)));
3532 goto normal_read;
3535 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3536 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3538 /* Deal with possible short send. */
3539 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3540 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3542 /* No outbuf here means successful sendfile. */
3543 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3544 SMB_PERFCOUNT_END(&req->pcd);
3545 goto strict_unlock;
3548 normal_read:
3550 #endif
3552 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3553 uint8 headerbuf[smb_size + 2*12];
3555 construct_reply_common_req(req, (char *)headerbuf);
3556 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3558 /* Send out the header. */
3559 if (write_data(req->sconn->sock, (char *)headerbuf,
3560 sizeof(headerbuf)) != sizeof(headerbuf)) {
3561 DEBUG(0,("send_file_readX: write_data failed for file "
3562 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3563 strerror(errno)));
3564 exit_server_cleanly("send_file_readX sendfile failed");
3566 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3567 if (nread == -1) {
3568 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3569 "file %s (%s).\n", fsp_str_dbg(fsp),
3570 strerror(errno)));
3571 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3573 goto strict_unlock;
3576 nosendfile_read:
3578 reply_outbuf(req, 12, smb_maxcnt);
3580 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3581 saved_errno = errno;
3583 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3585 if (nread < 0) {
3586 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3587 return;
3590 setup_readX_header(req, (char *)req->outbuf, nread);
3592 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3593 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3595 chain_reply(req);
3596 return;
3598 strict_unlock:
3599 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3600 TALLOC_FREE(req->outbuf);
3601 return;
3604 /****************************************************************************
3605 Reply to a read and X.
3606 ****************************************************************************/
3608 void reply_read_and_X(struct smb_request *req)
3610 connection_struct *conn = req->conn;
3611 files_struct *fsp;
3612 SMB_OFF_T startpos;
3613 size_t smb_maxcnt;
3614 bool big_readX = False;
3615 #if 0
3616 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3617 #endif
3619 START_PROFILE(SMBreadX);
3621 if ((req->wct != 10) && (req->wct != 12)) {
3622 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3623 return;
3626 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3627 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3628 smb_maxcnt = SVAL(req->vwv+5, 0);
3630 /* If it's an IPC, pass off the pipe handler. */
3631 if (IS_IPC(conn)) {
3632 reply_pipe_read_and_X(req);
3633 END_PROFILE(SMBreadX);
3634 return;
3637 if (!check_fsp(conn, req, fsp)) {
3638 END_PROFILE(SMBreadX);
3639 return;
3642 if (!CHECK_READ(fsp,req)) {
3643 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3644 END_PROFILE(SMBreadX);
3645 return;
3648 if (global_client_caps & CAP_LARGE_READX) {
3649 size_t upper_size = SVAL(req->vwv+7, 0);
3650 smb_maxcnt |= (upper_size<<16);
3651 if (upper_size > 1) {
3652 /* Can't do this on a chained packet. */
3653 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3654 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3655 END_PROFILE(SMBreadX);
3656 return;
3658 /* We currently don't do this on signed or sealed data. */
3659 if (srv_is_signing_active(req->sconn) ||
3660 is_encrypted_packet(req->inbuf)) {
3661 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3662 END_PROFILE(SMBreadX);
3663 return;
3665 /* Is there room in the reply for this data ? */
3666 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3667 reply_nterror(req,
3668 NT_STATUS_INVALID_PARAMETER);
3669 END_PROFILE(SMBreadX);
3670 return;
3672 big_readX = True;
3676 if (req->wct == 12) {
3677 #ifdef LARGE_SMB_OFF_T
3679 * This is a large offset (64 bit) read.
3681 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3683 #else /* !LARGE_SMB_OFF_T */
3686 * Ensure we haven't been sent a >32 bit offset.
3689 if(IVAL(req->vwv+10, 0) != 0) {
3690 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3691 "used and we don't support 64 bit offsets.\n",
3692 (unsigned int)IVAL(req->vwv+10, 0) ));
3693 END_PROFILE(SMBreadX);
3694 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3695 return;
3698 #endif /* LARGE_SMB_OFF_T */
3702 if (!big_readX) {
3703 NTSTATUS status = schedule_aio_read_and_X(conn,
3704 req,
3705 fsp,
3706 startpos,
3707 smb_maxcnt);
3708 if (NT_STATUS_IS_OK(status)) {
3709 /* Read scheduled - we're done. */
3710 goto out;
3712 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3713 /* Real error - report to client. */
3714 END_PROFILE(SMBreadX);
3715 reply_nterror(req, status);
3716 return;
3718 /* NT_STATUS_RETRY - fall back to sync read. */
3721 smbd_lock_socket(req->sconn);
3722 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3723 smbd_unlock_socket(req->sconn);
3725 out:
3726 END_PROFILE(SMBreadX);
3727 return;
3730 /****************************************************************************
3731 Error replies to writebraw must have smb_wct == 1. Fix this up.
3732 ****************************************************************************/
3734 void error_to_writebrawerr(struct smb_request *req)
3736 uint8 *old_outbuf = req->outbuf;
3738 reply_outbuf(req, 1, 0);
3740 memcpy(req->outbuf, old_outbuf, smb_size);
3741 TALLOC_FREE(old_outbuf);
3744 /****************************************************************************
3745 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3746 ****************************************************************************/
3748 void reply_writebraw(struct smb_request *req)
3750 connection_struct *conn = req->conn;
3751 char *buf = NULL;
3752 ssize_t nwritten=0;
3753 ssize_t total_written=0;
3754 size_t numtowrite=0;
3755 size_t tcount;
3756 SMB_OFF_T startpos;
3757 char *data=NULL;
3758 bool write_through;
3759 files_struct *fsp;
3760 struct lock_struct lock;
3761 NTSTATUS status;
3763 START_PROFILE(SMBwritebraw);
3766 * If we ever reply with an error, it must have the SMB command
3767 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3768 * we're finished.
3770 SCVAL(req->inbuf,smb_com,SMBwritec);
3772 if (srv_is_signing_active(req->sconn)) {
3773 END_PROFILE(SMBwritebraw);
3774 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3775 "raw reads/writes are disallowed.");
3778 if (req->wct < 12) {
3779 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3780 error_to_writebrawerr(req);
3781 END_PROFILE(SMBwritebraw);
3782 return;
3785 if (req->sconn->smb1.echo_handler.trusted_fde) {
3786 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3787 "'async smb echo handler = yes'\n"));
3788 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3789 error_to_writebrawerr(req);
3790 END_PROFILE(SMBwritebraw);
3791 return;
3794 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3795 if (!check_fsp(conn, req, fsp)) {
3796 error_to_writebrawerr(req);
3797 END_PROFILE(SMBwritebraw);
3798 return;
3801 if (!CHECK_WRITE(fsp)) {
3802 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3803 error_to_writebrawerr(req);
3804 END_PROFILE(SMBwritebraw);
3805 return;
3808 tcount = IVAL(req->vwv+1, 0);
3809 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3810 write_through = BITSETW(req->vwv+7,0);
3812 /* We have to deal with slightly different formats depending
3813 on whether we are using the core+ or lanman1.0 protocol */
3815 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3816 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3817 data = smb_buf(req->inbuf);
3818 } else {
3819 numtowrite = SVAL(req->vwv+10, 0);
3820 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3823 /* Ensure we don't write bytes past the end of this packet. */
3824 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3825 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3826 error_to_writebrawerr(req);
3827 END_PROFILE(SMBwritebraw);
3828 return;
3831 if (!fsp->print_file) {
3832 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3833 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3834 &lock);
3836 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3837 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3838 error_to_writebrawerr(req);
3839 END_PROFILE(SMBwritebraw);
3840 return;
3844 if (numtowrite>0) {
3845 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3848 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3849 "wrote=%d sync=%d\n",
3850 fsp->fnum, (double)startpos, (int)numtowrite,
3851 (int)nwritten, (int)write_through));
3853 if (nwritten < (ssize_t)numtowrite) {
3854 reply_nterror(req, NT_STATUS_DISK_FULL);
3855 error_to_writebrawerr(req);
3856 goto strict_unlock;
3859 total_written = nwritten;
3861 /* Allocate a buffer of 64k + length. */
3862 buf = TALLOC_ARRAY(NULL, char, 65540);
3863 if (!buf) {
3864 reply_nterror(req, NT_STATUS_NO_MEMORY);
3865 error_to_writebrawerr(req);
3866 goto strict_unlock;
3869 /* Return a SMBwritebraw message to the redirector to tell
3870 * it to send more bytes */
3872 memcpy(buf, req->inbuf, smb_size);
3873 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
3874 SCVAL(buf,smb_com,SMBwritebraw);
3875 SSVALS(buf,smb_vwv0,0xFFFF);
3876 show_msg(buf);
3877 if (!srv_send_smb(req->sconn->sock,
3878 buf,
3879 false, 0, /* no signing */
3880 IS_CONN_ENCRYPTED(conn),
3881 &req->pcd)) {
3882 exit_server_cleanly("reply_writebraw: srv_send_smb "
3883 "failed.");
3886 /* Now read the raw data into the buffer and write it */
3887 status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
3888 &numtowrite);
3889 if (!NT_STATUS_IS_OK(status)) {
3890 exit_server_cleanly("secondary writebraw failed");
3893 /* Set up outbuf to return the correct size */
3894 reply_outbuf(req, 1, 0);
3896 if (numtowrite != 0) {
3898 if (numtowrite > 0xFFFF) {
3899 DEBUG(0,("reply_writebraw: Oversize secondary write "
3900 "raw requested (%u). Terminating\n",
3901 (unsigned int)numtowrite ));
3902 exit_server_cleanly("secondary writebraw failed");
3905 if (tcount > nwritten+numtowrite) {
3906 DEBUG(3,("reply_writebraw: Client overestimated the "
3907 "write %d %d %d\n",
3908 (int)tcount,(int)nwritten,(int)numtowrite));
3911 status = read_data(req->sconn->sock, buf+4, numtowrite);
3913 if (!NT_STATUS_IS_OK(status)) {
3914 DEBUG(0,("reply_writebraw: Oversize secondary write "
3915 "raw read failed (%s). Terminating\n",
3916 nt_errstr(status)));
3917 exit_server_cleanly("secondary writebraw failed");
3920 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3921 if (nwritten == -1) {
3922 TALLOC_FREE(buf);
3923 reply_nterror(req, map_nt_error_from_unix(errno));
3924 error_to_writebrawerr(req);
3925 goto strict_unlock;
3928 if (nwritten < (ssize_t)numtowrite) {
3929 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3930 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3933 if (nwritten > 0) {
3934 total_written += nwritten;
3938 TALLOC_FREE(buf);
3939 SSVAL(req->outbuf,smb_vwv0,total_written);
3941 status = sync_file(conn, fsp, write_through);
3942 if (!NT_STATUS_IS_OK(status)) {
3943 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3944 fsp_str_dbg(fsp), nt_errstr(status)));
3945 reply_nterror(req, status);
3946 error_to_writebrawerr(req);
3947 goto strict_unlock;
3950 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3951 "wrote=%d\n",
3952 fsp->fnum, (double)startpos, (int)numtowrite,
3953 (int)total_written));
3955 if (!fsp->print_file) {
3956 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3959 /* We won't return a status if write through is not selected - this
3960 * follows what WfWg does */
3961 END_PROFILE(SMBwritebraw);
3963 if (!write_through && total_written==tcount) {
3965 #if RABBIT_PELLET_FIX
3967 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3968 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3969 * JRA.
3971 if (!send_keepalive(req->sconn->sock)) {
3972 exit_server_cleanly("reply_writebraw: send of "
3973 "keepalive failed");
3975 #endif
3976 TALLOC_FREE(req->outbuf);
3978 return;
3980 strict_unlock:
3981 if (!fsp->print_file) {
3982 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3985 END_PROFILE(SMBwritebraw);
3986 return;
3989 #undef DBGC_CLASS
3990 #define DBGC_CLASS DBGC_LOCKING
3992 /****************************************************************************
3993 Reply to a writeunlock (core+).
3994 ****************************************************************************/
3996 void reply_writeunlock(struct smb_request *req)
3998 connection_struct *conn = req->conn;
3999 ssize_t nwritten = -1;
4000 size_t numtowrite;
4001 SMB_OFF_T startpos;
4002 const char *data;
4003 NTSTATUS status = NT_STATUS_OK;
4004 files_struct *fsp;
4005 struct lock_struct lock;
4006 int saved_errno = 0;
4008 START_PROFILE(SMBwriteunlock);
4010 if (req->wct < 5) {
4011 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4012 END_PROFILE(SMBwriteunlock);
4013 return;
4016 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4018 if (!check_fsp(conn, req, fsp)) {
4019 END_PROFILE(SMBwriteunlock);
4020 return;
4023 if (!CHECK_WRITE(fsp)) {
4024 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4025 END_PROFILE(SMBwriteunlock);
4026 return;
4029 numtowrite = SVAL(req->vwv+1, 0);
4030 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4031 data = (const char *)req->buf + 3;
4033 if (!fsp->print_file && numtowrite > 0) {
4034 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4035 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4036 &lock);
4038 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4039 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4040 END_PROFILE(SMBwriteunlock);
4041 return;
4045 /* The special X/Open SMB protocol handling of
4046 zero length writes is *NOT* done for
4047 this call */
4048 if(numtowrite == 0) {
4049 nwritten = 0;
4050 } else {
4051 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4052 saved_errno = errno;
4055 status = sync_file(conn, fsp, False /* write through */);
4056 if (!NT_STATUS_IS_OK(status)) {
4057 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4058 fsp_str_dbg(fsp), nt_errstr(status)));
4059 reply_nterror(req, status);
4060 goto strict_unlock;
4063 if(nwritten < 0) {
4064 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4065 goto strict_unlock;
4068 if((nwritten < numtowrite) && (numtowrite != 0)) {
4069 reply_nterror(req, NT_STATUS_DISK_FULL);
4070 goto strict_unlock;
4073 if (numtowrite && !fsp->print_file) {
4074 status = do_unlock(req->sconn->msg_ctx,
4075 fsp,
4076 (uint64_t)req->smbpid,
4077 (uint64_t)numtowrite,
4078 (uint64_t)startpos,
4079 WINDOWS_LOCK);
4081 if (NT_STATUS_V(status)) {
4082 reply_nterror(req, status);
4083 goto strict_unlock;
4087 reply_outbuf(req, 1, 0);
4089 SSVAL(req->outbuf,smb_vwv0,nwritten);
4091 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4092 fsp->fnum, (int)numtowrite, (int)nwritten));
4094 strict_unlock:
4095 if (numtowrite && !fsp->print_file) {
4096 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4099 END_PROFILE(SMBwriteunlock);
4100 return;
4103 #undef DBGC_CLASS
4104 #define DBGC_CLASS DBGC_ALL
4106 /****************************************************************************
4107 Reply to a write.
4108 ****************************************************************************/
4110 void reply_write(struct smb_request *req)
4112 connection_struct *conn = req->conn;
4113 size_t numtowrite;
4114 ssize_t nwritten = -1;
4115 SMB_OFF_T startpos;
4116 const char *data;
4117 files_struct *fsp;
4118 struct lock_struct lock;
4119 NTSTATUS status;
4120 int saved_errno = 0;
4122 START_PROFILE(SMBwrite);
4124 if (req->wct < 5) {
4125 END_PROFILE(SMBwrite);
4126 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4127 return;
4130 /* If it's an IPC, pass off the pipe handler. */
4131 if (IS_IPC(conn)) {
4132 reply_pipe_write(req);
4133 END_PROFILE(SMBwrite);
4134 return;
4137 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4139 if (!check_fsp(conn, req, fsp)) {
4140 END_PROFILE(SMBwrite);
4141 return;
4144 if (!CHECK_WRITE(fsp)) {
4145 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4146 END_PROFILE(SMBwrite);
4147 return;
4150 numtowrite = SVAL(req->vwv+1, 0);
4151 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4152 data = (const char *)req->buf + 3;
4154 if (!fsp->print_file) {
4155 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4156 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4157 &lock);
4159 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4160 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4161 END_PROFILE(SMBwrite);
4162 return;
4167 * X/Open SMB protocol says that if smb_vwv1 is
4168 * zero then the file size should be extended or
4169 * truncated to the size given in smb_vwv[2-3].
4172 if(numtowrite == 0) {
4174 * This is actually an allocate call, and set EOF. JRA.
4176 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4177 if (nwritten < 0) {
4178 reply_nterror(req, NT_STATUS_DISK_FULL);
4179 goto strict_unlock;
4181 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4182 if (nwritten < 0) {
4183 reply_nterror(req, NT_STATUS_DISK_FULL);
4184 goto strict_unlock;
4186 trigger_write_time_update_immediate(fsp);
4187 } else {
4188 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4191 status = sync_file(conn, fsp, False);
4192 if (!NT_STATUS_IS_OK(status)) {
4193 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4194 fsp_str_dbg(fsp), nt_errstr(status)));
4195 reply_nterror(req, status);
4196 goto strict_unlock;
4199 if(nwritten < 0) {
4200 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4201 goto strict_unlock;
4204 if((nwritten == 0) && (numtowrite != 0)) {
4205 reply_nterror(req, NT_STATUS_DISK_FULL);
4206 goto strict_unlock;
4209 reply_outbuf(req, 1, 0);
4211 SSVAL(req->outbuf,smb_vwv0,nwritten);
4213 if (nwritten < (ssize_t)numtowrite) {
4214 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4215 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4218 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4220 strict_unlock:
4221 if (!fsp->print_file) {
4222 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4225 END_PROFILE(SMBwrite);
4226 return;
4229 /****************************************************************************
4230 Ensure a buffer is a valid writeX for recvfile purposes.
4231 ****************************************************************************/
4233 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4234 (2*14) + /* word count (including bcc) */ \
4235 1 /* pad byte */)
4237 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4238 const uint8_t *inbuf)
4240 size_t numtowrite;
4241 connection_struct *conn = NULL;
4242 unsigned int doff = 0;
4243 size_t len = smb_len_large(inbuf);
4245 if (is_encrypted_packet(inbuf)) {
4246 /* Can't do this on encrypted
4247 * connections. */
4248 return false;
4251 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4252 return false;
4255 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4256 CVAL(inbuf,smb_wct) != 14) {
4257 DEBUG(10,("is_valid_writeX_buffer: chained or "
4258 "invalid word length.\n"));
4259 return false;
4262 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4263 if (conn == NULL) {
4264 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4265 return false;
4267 if (IS_IPC(conn)) {
4268 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4269 return false;
4271 if (IS_PRINT(conn)) {
4272 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4273 return false;
4275 doff = SVAL(inbuf,smb_vwv11);
4277 numtowrite = SVAL(inbuf,smb_vwv10);
4279 if (len > doff && len - doff > 0xFFFF) {
4280 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4283 if (numtowrite == 0) {
4284 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4285 return false;
4288 /* Ensure the sizes match up. */
4289 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4290 /* no pad byte...old smbclient :-( */
4291 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4292 (unsigned int)doff,
4293 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4294 return false;
4297 if (len - doff != numtowrite) {
4298 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4299 "len = %u, doff = %u, numtowrite = %u\n",
4300 (unsigned int)len,
4301 (unsigned int)doff,
4302 (unsigned int)numtowrite ));
4303 return false;
4306 DEBUG(10,("is_valid_writeX_buffer: true "
4307 "len = %u, doff = %u, numtowrite = %u\n",
4308 (unsigned int)len,
4309 (unsigned int)doff,
4310 (unsigned int)numtowrite ));
4312 return true;
4315 /****************************************************************************
4316 Reply to a write and X.
4317 ****************************************************************************/
4319 void reply_write_and_X(struct smb_request *req)
4321 connection_struct *conn = req->conn;
4322 files_struct *fsp;
4323 struct lock_struct lock;
4324 SMB_OFF_T startpos;
4325 size_t numtowrite;
4326 bool write_through;
4327 ssize_t nwritten;
4328 unsigned int smb_doff;
4329 unsigned int smblen;
4330 char *data;
4331 NTSTATUS status;
4332 int saved_errno = 0;
4334 START_PROFILE(SMBwriteX);
4336 if ((req->wct != 12) && (req->wct != 14)) {
4337 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4338 END_PROFILE(SMBwriteX);
4339 return;
4342 numtowrite = SVAL(req->vwv+10, 0);
4343 smb_doff = SVAL(req->vwv+11, 0);
4344 smblen = smb_len(req->inbuf);
4346 if (req->unread_bytes > 0xFFFF ||
4347 (smblen > smb_doff &&
4348 smblen - smb_doff > 0xFFFF)) {
4349 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4352 if (req->unread_bytes) {
4353 /* Can't do a recvfile write on IPC$ */
4354 if (IS_IPC(conn)) {
4355 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4356 END_PROFILE(SMBwriteX);
4357 return;
4359 if (numtowrite != req->unread_bytes) {
4360 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4361 END_PROFILE(SMBwriteX);
4362 return;
4364 } else {
4365 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4366 smb_doff + numtowrite > smblen) {
4367 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4368 END_PROFILE(SMBwriteX);
4369 return;
4373 /* If it's an IPC, pass off the pipe handler. */
4374 if (IS_IPC(conn)) {
4375 if (req->unread_bytes) {
4376 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4377 END_PROFILE(SMBwriteX);
4378 return;
4380 reply_pipe_write_and_X(req);
4381 END_PROFILE(SMBwriteX);
4382 return;
4385 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4386 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4387 write_through = BITSETW(req->vwv+7,0);
4389 if (!check_fsp(conn, req, fsp)) {
4390 END_PROFILE(SMBwriteX);
4391 return;
4394 if (!CHECK_WRITE(fsp)) {
4395 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4396 END_PROFILE(SMBwriteX);
4397 return;
4400 data = smb_base(req->inbuf) + smb_doff;
4402 if(req->wct == 14) {
4403 #ifdef LARGE_SMB_OFF_T
4405 * This is a large offset (64 bit) write.
4407 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4409 #else /* !LARGE_SMB_OFF_T */
4412 * Ensure we haven't been sent a >32 bit offset.
4415 if(IVAL(req->vwv+12, 0) != 0) {
4416 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4417 "used and we don't support 64 bit offsets.\n",
4418 (unsigned int)IVAL(req->vwv+12, 0) ));
4419 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4420 END_PROFILE(SMBwriteX);
4421 return;
4424 #endif /* LARGE_SMB_OFF_T */
4427 /* X/Open SMB protocol says that, unlike SMBwrite
4428 if the length is zero then NO truncation is
4429 done, just a write of zero. To truncate a file,
4430 use SMBwrite. */
4432 if(numtowrite == 0) {
4433 nwritten = 0;
4434 } else {
4435 if (req->unread_bytes == 0) {
4436 status = schedule_aio_write_and_X(conn,
4437 req,
4438 fsp,
4439 data,
4440 startpos,
4441 numtowrite);
4443 if (NT_STATUS_IS_OK(status)) {
4444 /* write scheduled - we're done. */
4445 goto out;
4447 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4448 /* Real error - report to client. */
4449 reply_nterror(req, status);
4450 goto out;
4452 /* NT_STATUS_RETRY - fall through to sync write. */
4455 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4456 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4457 &lock);
4459 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4460 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4461 goto out;
4464 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4465 saved_errno = errno;
4467 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4470 if(nwritten < 0) {
4471 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4472 goto out;
4475 if((nwritten == 0) && (numtowrite != 0)) {
4476 reply_nterror(req, NT_STATUS_DISK_FULL);
4477 goto out;
4480 reply_outbuf(req, 6, 0);
4481 SSVAL(req->outbuf,smb_vwv2,nwritten);
4482 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4484 if (nwritten < (ssize_t)numtowrite) {
4485 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4486 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4489 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4490 fsp->fnum, (int)numtowrite, (int)nwritten));
4492 status = sync_file(conn, fsp, write_through);
4493 if (!NT_STATUS_IS_OK(status)) {
4494 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4495 fsp_str_dbg(fsp), nt_errstr(status)));
4496 reply_nterror(req, status);
4497 goto out;
4500 END_PROFILE(SMBwriteX);
4501 chain_reply(req);
4502 return;
4504 out:
4505 END_PROFILE(SMBwriteX);
4506 return;
4509 /****************************************************************************
4510 Reply to a lseek.
4511 ****************************************************************************/
4513 void reply_lseek(struct smb_request *req)
4515 connection_struct *conn = req->conn;
4516 SMB_OFF_T startpos;
4517 SMB_OFF_T res= -1;
4518 int mode,umode;
4519 files_struct *fsp;
4521 START_PROFILE(SMBlseek);
4523 if (req->wct < 4) {
4524 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4525 END_PROFILE(SMBlseek);
4526 return;
4529 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4531 if (!check_fsp(conn, req, fsp)) {
4532 return;
4535 flush_write_cache(fsp, SEEK_FLUSH);
4537 mode = SVAL(req->vwv+1, 0) & 3;
4538 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4539 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4541 switch (mode) {
4542 case 0:
4543 umode = SEEK_SET;
4544 res = startpos;
4545 break;
4546 case 1:
4547 umode = SEEK_CUR;
4548 res = fsp->fh->pos + startpos;
4549 break;
4550 case 2:
4551 umode = SEEK_END;
4552 break;
4553 default:
4554 umode = SEEK_SET;
4555 res = startpos;
4556 break;
4559 if (umode == SEEK_END) {
4560 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4561 if(errno == EINVAL) {
4562 SMB_OFF_T current_pos = startpos;
4564 if(fsp_stat(fsp) == -1) {
4565 reply_nterror(req,
4566 map_nt_error_from_unix(errno));
4567 END_PROFILE(SMBlseek);
4568 return;
4571 current_pos += fsp->fsp_name->st.st_ex_size;
4572 if(current_pos < 0)
4573 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4577 if(res == -1) {
4578 reply_nterror(req, map_nt_error_from_unix(errno));
4579 END_PROFILE(SMBlseek);
4580 return;
4584 fsp->fh->pos = res;
4586 reply_outbuf(req, 2, 0);
4587 SIVAL(req->outbuf,smb_vwv0,res);
4589 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4590 fsp->fnum, (double)startpos, (double)res, mode));
4592 END_PROFILE(SMBlseek);
4593 return;
4596 /****************************************************************************
4597 Reply to a flush.
4598 ****************************************************************************/
4600 void reply_flush(struct smb_request *req)
4602 connection_struct *conn = req->conn;
4603 uint16 fnum;
4604 files_struct *fsp;
4606 START_PROFILE(SMBflush);
4608 if (req->wct < 1) {
4609 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4610 return;
4613 fnum = SVAL(req->vwv+0, 0);
4614 fsp = file_fsp(req, fnum);
4616 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4617 return;
4620 if (!fsp) {
4621 file_sync_all(conn);
4622 } else {
4623 NTSTATUS status = sync_file(conn, fsp, True);
4624 if (!NT_STATUS_IS_OK(status)) {
4625 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4626 fsp_str_dbg(fsp), nt_errstr(status)));
4627 reply_nterror(req, status);
4628 END_PROFILE(SMBflush);
4629 return;
4633 reply_outbuf(req, 0, 0);
4635 DEBUG(3,("flush\n"));
4636 END_PROFILE(SMBflush);
4637 return;
4640 /****************************************************************************
4641 Reply to a exit.
4642 conn POINTER CAN BE NULL HERE !
4643 ****************************************************************************/
4645 void reply_exit(struct smb_request *req)
4647 START_PROFILE(SMBexit);
4649 file_close_pid(req->smbpid, req->vuid);
4651 reply_outbuf(req, 0, 0);
4653 DEBUG(3,("exit\n"));
4655 END_PROFILE(SMBexit);
4656 return;
4659 /****************************************************************************
4660 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4661 ****************************************************************************/
4663 void reply_close(struct smb_request *req)
4665 connection_struct *conn = req->conn;
4666 NTSTATUS status = NT_STATUS_OK;
4667 files_struct *fsp = NULL;
4668 START_PROFILE(SMBclose);
4670 if (req->wct < 3) {
4671 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4672 END_PROFILE(SMBclose);
4673 return;
4676 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4679 * We can only use check_fsp if we know it's not a directory.
4682 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4683 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4684 END_PROFILE(SMBclose);
4685 return;
4688 if(fsp->is_directory) {
4690 * Special case - close NT SMB directory handle.
4692 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4693 status = close_file(req, fsp, NORMAL_CLOSE);
4694 } else {
4695 time_t t;
4697 * Close ordinary file.
4700 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4701 fsp->fh->fd, fsp->fnum,
4702 conn->num_files_open));
4705 * Take care of any time sent in the close.
4708 t = srv_make_unix_date3(req->vwv+1);
4709 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4712 * close_file() returns the unix errno if an error
4713 * was detected on close - normally this is due to
4714 * a disk full error. If not then it was probably an I/O error.
4717 status = close_file(req, fsp, NORMAL_CLOSE);
4720 if (!NT_STATUS_IS_OK(status)) {
4721 reply_nterror(req, status);
4722 END_PROFILE(SMBclose);
4723 return;
4726 reply_outbuf(req, 0, 0);
4727 END_PROFILE(SMBclose);
4728 return;
4731 /****************************************************************************
4732 Reply to a writeclose (Core+ protocol).
4733 ****************************************************************************/
4735 void reply_writeclose(struct smb_request *req)
4737 connection_struct *conn = req->conn;
4738 size_t numtowrite;
4739 ssize_t nwritten = -1;
4740 NTSTATUS close_status = NT_STATUS_OK;
4741 SMB_OFF_T startpos;
4742 const char *data;
4743 struct timespec mtime;
4744 files_struct *fsp;
4745 struct lock_struct lock;
4747 START_PROFILE(SMBwriteclose);
4749 if (req->wct < 6) {
4750 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4751 END_PROFILE(SMBwriteclose);
4752 return;
4755 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4757 if (!check_fsp(conn, req, fsp)) {
4758 END_PROFILE(SMBwriteclose);
4759 return;
4761 if (!CHECK_WRITE(fsp)) {
4762 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4763 END_PROFILE(SMBwriteclose);
4764 return;
4767 numtowrite = SVAL(req->vwv+1, 0);
4768 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4769 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4770 data = (const char *)req->buf + 1;
4772 if (!fsp->print_file) {
4773 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4774 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4775 &lock);
4777 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4778 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4779 END_PROFILE(SMBwriteclose);
4780 return;
4784 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4786 set_close_write_time(fsp, mtime);
4789 * More insanity. W2K only closes the file if writelen > 0.
4790 * JRA.
4793 if (numtowrite) {
4794 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4795 "file %s\n", fsp_str_dbg(fsp)));
4796 close_status = close_file(req, fsp, NORMAL_CLOSE);
4799 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4800 fsp->fnum, (int)numtowrite, (int)nwritten,
4801 conn->num_files_open));
4803 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4804 reply_nterror(req, NT_STATUS_DISK_FULL);
4805 goto strict_unlock;
4808 if(!NT_STATUS_IS_OK(close_status)) {
4809 reply_nterror(req, close_status);
4810 goto strict_unlock;
4813 reply_outbuf(req, 1, 0);
4815 SSVAL(req->outbuf,smb_vwv0,nwritten);
4817 strict_unlock:
4818 if (numtowrite && !fsp->print_file) {
4819 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4822 END_PROFILE(SMBwriteclose);
4823 return;
4826 #undef DBGC_CLASS
4827 #define DBGC_CLASS DBGC_LOCKING
4829 /****************************************************************************
4830 Reply to a lock.
4831 ****************************************************************************/
4833 void reply_lock(struct smb_request *req)
4835 connection_struct *conn = req->conn;
4836 uint64_t count,offset;
4837 NTSTATUS status;
4838 files_struct *fsp;
4839 struct byte_range_lock *br_lck = NULL;
4841 START_PROFILE(SMBlock);
4843 if (req->wct < 5) {
4844 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4845 END_PROFILE(SMBlock);
4846 return;
4849 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4851 if (!check_fsp(conn, req, fsp)) {
4852 END_PROFILE(SMBlock);
4853 return;
4856 count = (uint64_t)IVAL(req->vwv+1, 0);
4857 offset = (uint64_t)IVAL(req->vwv+3, 0);
4859 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4860 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4862 br_lck = do_lock(req->sconn->msg_ctx,
4863 fsp,
4864 (uint64_t)req->smbpid,
4865 count,
4866 offset,
4867 WRITE_LOCK,
4868 WINDOWS_LOCK,
4869 False, /* Non-blocking lock. */
4870 &status,
4871 NULL,
4872 NULL);
4874 TALLOC_FREE(br_lck);
4876 if (NT_STATUS_V(status)) {
4877 reply_nterror(req, status);
4878 END_PROFILE(SMBlock);
4879 return;
4882 reply_outbuf(req, 0, 0);
4884 END_PROFILE(SMBlock);
4885 return;
4888 /****************************************************************************
4889 Reply to a unlock.
4890 ****************************************************************************/
4892 void reply_unlock(struct smb_request *req)
4894 connection_struct *conn = req->conn;
4895 uint64_t count,offset;
4896 NTSTATUS status;
4897 files_struct *fsp;
4899 START_PROFILE(SMBunlock);
4901 if (req->wct < 5) {
4902 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4903 END_PROFILE(SMBunlock);
4904 return;
4907 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4909 if (!check_fsp(conn, req, fsp)) {
4910 END_PROFILE(SMBunlock);
4911 return;
4914 count = (uint64_t)IVAL(req->vwv+1, 0);
4915 offset = (uint64_t)IVAL(req->vwv+3, 0);
4917 status = do_unlock(req->sconn->msg_ctx,
4918 fsp,
4919 (uint64_t)req->smbpid,
4920 count,
4921 offset,
4922 WINDOWS_LOCK);
4924 if (NT_STATUS_V(status)) {
4925 reply_nterror(req, status);
4926 END_PROFILE(SMBunlock);
4927 return;
4930 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4931 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4933 reply_outbuf(req, 0, 0);
4935 END_PROFILE(SMBunlock);
4936 return;
4939 #undef DBGC_CLASS
4940 #define DBGC_CLASS DBGC_ALL
4942 /****************************************************************************
4943 Reply to a tdis.
4944 conn POINTER CAN BE NULL HERE !
4945 ****************************************************************************/
4947 void reply_tdis(struct smb_request *req)
4949 connection_struct *conn = req->conn;
4950 START_PROFILE(SMBtdis);
4952 if (!conn) {
4953 DEBUG(4,("Invalid connection in tdis\n"));
4954 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
4955 END_PROFILE(SMBtdis);
4956 return;
4959 conn->used = False;
4961 close_cnum(conn,req->vuid);
4962 req->conn = NULL;
4964 reply_outbuf(req, 0, 0);
4965 END_PROFILE(SMBtdis);
4966 return;
4969 /****************************************************************************
4970 Reply to a echo.
4971 conn POINTER CAN BE NULL HERE !
4972 ****************************************************************************/
4974 void reply_echo(struct smb_request *req)
4976 connection_struct *conn = req->conn;
4977 struct smb_perfcount_data local_pcd;
4978 struct smb_perfcount_data *cur_pcd;
4979 int smb_reverb;
4980 int seq_num;
4982 START_PROFILE(SMBecho);
4984 smb_init_perfcount_data(&local_pcd);
4986 if (req->wct < 1) {
4987 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4988 END_PROFILE(SMBecho);
4989 return;
4992 smb_reverb = SVAL(req->vwv+0, 0);
4994 reply_outbuf(req, 1, req->buflen);
4996 /* copy any incoming data back out */
4997 if (req->buflen > 0) {
4998 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5001 if (smb_reverb > 100) {
5002 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5003 smb_reverb = 100;
5006 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5008 /* this makes sure we catch the request pcd */
5009 if (seq_num == smb_reverb) {
5010 cur_pcd = &req->pcd;
5011 } else {
5012 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5013 cur_pcd = &local_pcd;
5016 SSVAL(req->outbuf,smb_vwv0,seq_num);
5018 show_msg((char *)req->outbuf);
5019 if (!srv_send_smb(req->sconn->sock,
5020 (char *)req->outbuf,
5021 true, req->seqnum+1,
5022 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5023 cur_pcd))
5024 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5027 DEBUG(3,("echo %d times\n", smb_reverb));
5029 TALLOC_FREE(req->outbuf);
5031 END_PROFILE(SMBecho);
5032 return;
5035 /****************************************************************************
5036 Reply to a printopen.
5037 ****************************************************************************/
5039 void reply_printopen(struct smb_request *req)
5041 connection_struct *conn = req->conn;
5042 files_struct *fsp;
5043 NTSTATUS status;
5045 START_PROFILE(SMBsplopen);
5047 if (req->wct < 2) {
5048 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5049 END_PROFILE(SMBsplopen);
5050 return;
5053 if (!CAN_PRINT(conn)) {
5054 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5055 END_PROFILE(SMBsplopen);
5056 return;
5059 status = file_new(req, conn, &fsp);
5060 if(!NT_STATUS_IS_OK(status)) {
5061 reply_nterror(req, status);
5062 END_PROFILE(SMBsplopen);
5063 return;
5066 /* Open for exclusive use, write only. */
5067 status = print_spool_open(fsp, NULL, req->vuid);
5069 if (!NT_STATUS_IS_OK(status)) {
5070 file_free(req, fsp);
5071 reply_nterror(req, status);
5072 END_PROFILE(SMBsplopen);
5073 return;
5076 reply_outbuf(req, 1, 0);
5077 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5079 DEBUG(3,("openprint fd=%d fnum=%d\n",
5080 fsp->fh->fd, fsp->fnum));
5082 END_PROFILE(SMBsplopen);
5083 return;
5086 /****************************************************************************
5087 Reply to a printclose.
5088 ****************************************************************************/
5090 void reply_printclose(struct smb_request *req)
5092 connection_struct *conn = req->conn;
5093 files_struct *fsp;
5094 NTSTATUS status;
5096 START_PROFILE(SMBsplclose);
5098 if (req->wct < 1) {
5099 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5100 END_PROFILE(SMBsplclose);
5101 return;
5104 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5106 if (!check_fsp(conn, req, fsp)) {
5107 END_PROFILE(SMBsplclose);
5108 return;
5111 if (!CAN_PRINT(conn)) {
5112 reply_force_doserror(req, ERRSRV, ERRerror);
5113 END_PROFILE(SMBsplclose);
5114 return;
5117 DEBUG(3,("printclose fd=%d fnum=%d\n",
5118 fsp->fh->fd,fsp->fnum));
5120 status = close_file(req, fsp, NORMAL_CLOSE);
5122 if(!NT_STATUS_IS_OK(status)) {
5123 reply_nterror(req, status);
5124 END_PROFILE(SMBsplclose);
5125 return;
5128 reply_outbuf(req, 0, 0);
5130 END_PROFILE(SMBsplclose);
5131 return;
5134 /****************************************************************************
5135 Reply to a printqueue.
5136 ****************************************************************************/
5138 void reply_printqueue(struct smb_request *req)
5140 connection_struct *conn = req->conn;
5141 int max_count;
5142 int start_index;
5144 START_PROFILE(SMBsplretq);
5146 if (req->wct < 2) {
5147 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5148 END_PROFILE(SMBsplretq);
5149 return;
5152 max_count = SVAL(req->vwv+0, 0);
5153 start_index = SVAL(req->vwv+1, 0);
5155 /* we used to allow the client to get the cnum wrong, but that
5156 is really quite gross and only worked when there was only
5157 one printer - I think we should now only accept it if they
5158 get it right (tridge) */
5159 if (!CAN_PRINT(conn)) {
5160 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5161 END_PROFILE(SMBsplretq);
5162 return;
5165 reply_outbuf(req, 2, 3);
5166 SSVAL(req->outbuf,smb_vwv0,0);
5167 SSVAL(req->outbuf,smb_vwv1,0);
5168 SCVAL(smb_buf(req->outbuf),0,1);
5169 SSVAL(smb_buf(req->outbuf),1,0);
5171 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5172 start_index, max_count));
5175 TALLOC_CTX *mem_ctx = talloc_tos();
5176 NTSTATUS status;
5177 WERROR werr;
5178 const char *sharename = lp_servicename(SNUM(conn));
5179 struct rpc_pipe_client *cli = NULL;
5180 struct policy_handle handle;
5181 struct spoolss_DevmodeContainer devmode_ctr;
5182 union spoolss_JobInfo *info;
5183 uint32_t count;
5184 uint32_t num_to_get;
5185 uint32_t first;
5186 uint32_t i;
5188 ZERO_STRUCT(handle);
5190 status = rpc_connect_spoolss_pipe(conn, &cli);
5191 if (!NT_STATUS_IS_OK(status)) {
5192 DEBUG(0, ("reply_printqueue: "
5193 "could not connect to spoolss: %s\n",
5194 nt_errstr(status)));
5195 reply_nterror(req, status);
5196 goto out;
5199 ZERO_STRUCT(devmode_ctr);
5201 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
5202 sharename,
5203 NULL, devmode_ctr,
5204 SEC_FLAG_MAXIMUM_ALLOWED,
5205 &handle,
5206 &werr);
5207 if (!NT_STATUS_IS_OK(status)) {
5208 reply_nterror(req, status);
5209 goto out;
5211 if (!W_ERROR_IS_OK(werr)) {
5212 reply_nterror(req, werror_to_ntstatus(werr));
5213 goto out;
5216 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5217 &handle,
5218 0, /* firstjob */
5219 0xff, /* numjobs */
5220 2, /* level */
5221 0, /* offered */
5222 &count,
5223 &info);
5224 if (!W_ERROR_IS_OK(werr)) {
5225 reply_nterror(req, werror_to_ntstatus(werr));
5226 goto out;
5229 if (max_count > 0) {
5230 first = start_index;
5231 } else {
5232 first = start_index + max_count + 1;
5235 if (first >= count) {
5236 num_to_get = first;
5237 } else {
5238 num_to_get = first + MIN(ABS(max_count), count - first);
5241 for (i = first; i < num_to_get; i++) {
5242 char blob[28];
5243 char *p = blob;
5244 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5245 int qstatus;
5246 uint16_t qrapjobid = pjobid_to_rap(sharename,
5247 info[i].info2.job_id);
5249 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5250 qstatus = 2;
5251 } else {
5252 qstatus = 3;
5255 srv_put_dos_date2(p, 0, qtime);
5256 SCVAL(p, 4, qstatus);
5257 SSVAL(p, 5, qrapjobid);
5258 SIVAL(p, 7, info[i].info2.size);
5259 SCVAL(p, 11, 0);
5260 srvstr_push(blob, req->flags2, p+12,
5261 info[i].info2.notify_name, 16, STR_ASCII);
5263 if (message_push_blob(
5264 &req->outbuf,
5265 data_blob_const(
5266 blob, sizeof(blob))) == -1) {
5267 reply_nterror(req, NT_STATUS_NO_MEMORY);
5268 goto out;
5272 if (count > 0) {
5273 SSVAL(req->outbuf,smb_vwv0,count);
5274 SSVAL(req->outbuf,smb_vwv1,
5275 (max_count>0?first+count:first-1));
5276 SCVAL(smb_buf(req->outbuf),0,1);
5277 SSVAL(smb_buf(req->outbuf),1,28*count);
5281 DEBUG(3, ("%u entries returned in queue\n",
5282 (unsigned)count));
5284 out:
5285 if (cli && is_valid_policy_hnd(&handle)) {
5286 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
5291 END_PROFILE(SMBsplretq);
5292 return;
5295 /****************************************************************************
5296 Reply to a printwrite.
5297 ****************************************************************************/
5299 void reply_printwrite(struct smb_request *req)
5301 connection_struct *conn = req->conn;
5302 int numtowrite;
5303 const char *data;
5304 files_struct *fsp;
5306 START_PROFILE(SMBsplwr);
5308 if (req->wct < 1) {
5309 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5310 END_PROFILE(SMBsplwr);
5311 return;
5314 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5316 if (!check_fsp(conn, req, fsp)) {
5317 END_PROFILE(SMBsplwr);
5318 return;
5321 if (!fsp->print_file) {
5322 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5323 END_PROFILE(SMBsplwr);
5324 return;
5327 if (!CHECK_WRITE(fsp)) {
5328 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5329 END_PROFILE(SMBsplwr);
5330 return;
5333 numtowrite = SVAL(req->buf, 1);
5335 if (req->buflen < numtowrite + 3) {
5336 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5337 END_PROFILE(SMBsplwr);
5338 return;
5341 data = (const char *)req->buf + 3;
5343 if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5344 reply_nterror(req, map_nt_error_from_unix(errno));
5345 END_PROFILE(SMBsplwr);
5346 return;
5349 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5351 END_PROFILE(SMBsplwr);
5352 return;
5355 /****************************************************************************
5356 Reply to a mkdir.
5357 ****************************************************************************/
5359 void reply_mkdir(struct smb_request *req)
5361 connection_struct *conn = req->conn;
5362 struct smb_filename *smb_dname = NULL;
5363 char *directory = NULL;
5364 NTSTATUS status;
5365 TALLOC_CTX *ctx = talloc_tos();
5367 START_PROFILE(SMBmkdir);
5369 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5370 STR_TERMINATE, &status);
5371 if (!NT_STATUS_IS_OK(status)) {
5372 reply_nterror(req, status);
5373 goto out;
5376 status = filename_convert(ctx, conn,
5377 req->flags2 & FLAGS2_DFS_PATHNAMES,
5378 directory,
5380 NULL,
5381 &smb_dname);
5382 if (!NT_STATUS_IS_OK(status)) {
5383 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5384 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5385 ERRSRV, ERRbadpath);
5386 goto out;
5388 reply_nterror(req, status);
5389 goto out;
5392 status = create_directory(conn, req, smb_dname);
5394 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5396 if (!NT_STATUS_IS_OK(status)) {
5398 if (!use_nt_status()
5399 && NT_STATUS_EQUAL(status,
5400 NT_STATUS_OBJECT_NAME_COLLISION)) {
5402 * Yes, in the DOS error code case we get a
5403 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5404 * samba4 torture test.
5406 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5409 reply_nterror(req, status);
5410 goto out;
5413 reply_outbuf(req, 0, 0);
5415 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5416 out:
5417 TALLOC_FREE(smb_dname);
5418 END_PROFILE(SMBmkdir);
5419 return;
5422 /****************************************************************************
5423 Reply to a rmdir.
5424 ****************************************************************************/
5426 void reply_rmdir(struct smb_request *req)
5428 connection_struct *conn = req->conn;
5429 struct smb_filename *smb_dname = NULL;
5430 char *directory = NULL;
5431 NTSTATUS status;
5432 TALLOC_CTX *ctx = talloc_tos();
5433 files_struct *fsp = NULL;
5434 int info = 0;
5435 struct smbd_server_connection *sconn = req->sconn;
5437 START_PROFILE(SMBrmdir);
5439 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5440 STR_TERMINATE, &status);
5441 if (!NT_STATUS_IS_OK(status)) {
5442 reply_nterror(req, status);
5443 goto out;
5446 status = filename_convert(ctx, conn,
5447 req->flags2 & FLAGS2_DFS_PATHNAMES,
5448 directory,
5450 NULL,
5451 &smb_dname);
5452 if (!NT_STATUS_IS_OK(status)) {
5453 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5454 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5455 ERRSRV, ERRbadpath);
5456 goto out;
5458 reply_nterror(req, status);
5459 goto out;
5462 if (is_ntfs_stream_smb_fname(smb_dname)) {
5463 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5464 goto out;
5467 status = SMB_VFS_CREATE_FILE(
5468 conn, /* conn */
5469 req, /* req */
5470 0, /* root_dir_fid */
5471 smb_dname, /* fname */
5472 DELETE_ACCESS, /* access_mask */
5473 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5474 FILE_SHARE_DELETE),
5475 FILE_OPEN, /* create_disposition*/
5476 FILE_DIRECTORY_FILE, /* create_options */
5477 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5478 0, /* oplock_request */
5479 0, /* allocation_size */
5480 0, /* private_flags */
5481 NULL, /* sd */
5482 NULL, /* ea_list */
5483 &fsp, /* result */
5484 &info); /* pinfo */
5486 if (!NT_STATUS_IS_OK(status)) {
5487 if (open_was_deferred(req->mid)) {
5488 /* We have re-scheduled this call. */
5489 goto out;
5491 reply_nterror(req, status);
5492 goto out;
5495 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5496 if (!NT_STATUS_IS_OK(status)) {
5497 close_file(req, fsp, ERROR_CLOSE);
5498 reply_nterror(req, status);
5499 goto out;
5502 if (!set_delete_on_close(fsp, true, &conn->server_info->utok)) {
5503 close_file(req, fsp, ERROR_CLOSE);
5504 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5505 goto out;
5508 status = close_file(req, fsp, NORMAL_CLOSE);
5509 if (!NT_STATUS_IS_OK(status)) {
5510 reply_nterror(req, status);
5511 } else {
5512 reply_outbuf(req, 0, 0);
5515 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5517 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5518 out:
5519 TALLOC_FREE(smb_dname);
5520 END_PROFILE(SMBrmdir);
5521 return;
5524 /*******************************************************************
5525 Resolve wildcards in a filename rename.
5526 ********************************************************************/
5528 static bool resolve_wildcards(TALLOC_CTX *ctx,
5529 const char *name1,
5530 const char *name2,
5531 char **pp_newname)
5533 char *name2_copy = NULL;
5534 char *root1 = NULL;
5535 char *root2 = NULL;
5536 char *ext1 = NULL;
5537 char *ext2 = NULL;
5538 char *p,*p2, *pname1, *pname2;
5540 name2_copy = talloc_strdup(ctx, name2);
5541 if (!name2_copy) {
5542 return False;
5545 pname1 = strrchr_m(name1,'/');
5546 pname2 = strrchr_m(name2_copy,'/');
5548 if (!pname1 || !pname2) {
5549 return False;
5552 /* Truncate the copy of name2 at the last '/' */
5553 *pname2 = '\0';
5555 /* Now go past the '/' */
5556 pname1++;
5557 pname2++;
5559 root1 = talloc_strdup(ctx, pname1);
5560 root2 = talloc_strdup(ctx, pname2);
5562 if (!root1 || !root2) {
5563 return False;
5566 p = strrchr_m(root1,'.');
5567 if (p) {
5568 *p = 0;
5569 ext1 = talloc_strdup(ctx, p+1);
5570 } else {
5571 ext1 = talloc_strdup(ctx, "");
5573 p = strrchr_m(root2,'.');
5574 if (p) {
5575 *p = 0;
5576 ext2 = talloc_strdup(ctx, p+1);
5577 } else {
5578 ext2 = talloc_strdup(ctx, "");
5581 if (!ext1 || !ext2) {
5582 return False;
5585 p = root1;
5586 p2 = root2;
5587 while (*p2) {
5588 if (*p2 == '?') {
5589 /* Hmmm. Should this be mb-aware ? */
5590 *p2 = *p;
5591 p2++;
5592 } else if (*p2 == '*') {
5593 *p2 = '\0';
5594 root2 = talloc_asprintf(ctx, "%s%s",
5595 root2,
5597 if (!root2) {
5598 return False;
5600 break;
5601 } else {
5602 p2++;
5604 if (*p) {
5605 p++;
5609 p = ext1;
5610 p2 = ext2;
5611 while (*p2) {
5612 if (*p2 == '?') {
5613 /* Hmmm. Should this be mb-aware ? */
5614 *p2 = *p;
5615 p2++;
5616 } else if (*p2 == '*') {
5617 *p2 = '\0';
5618 ext2 = talloc_asprintf(ctx, "%s%s",
5619 ext2,
5621 if (!ext2) {
5622 return False;
5624 break;
5625 } else {
5626 p2++;
5628 if (*p) {
5629 p++;
5633 if (*ext2) {
5634 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5635 name2_copy,
5636 root2,
5637 ext2);
5638 } else {
5639 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5640 name2_copy,
5641 root2);
5644 if (!*pp_newname) {
5645 return False;
5648 return True;
5651 /****************************************************************************
5652 Ensure open files have their names updated. Updated to notify other smbd's
5653 asynchronously.
5654 ****************************************************************************/
5656 static void rename_open_files(connection_struct *conn,
5657 struct share_mode_lock *lck,
5658 const struct smb_filename *smb_fname_dst)
5660 files_struct *fsp;
5661 bool did_rename = False;
5662 NTSTATUS status;
5664 for(fsp = file_find_di_first(lck->id); fsp;
5665 fsp = file_find_di_next(fsp)) {
5666 /* fsp_name is a relative path under the fsp. To change this for other
5667 sharepaths we need to manipulate relative paths. */
5668 /* TODO - create the absolute path and manipulate the newname
5669 relative to the sharepath. */
5670 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5671 continue;
5673 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5674 "(file_id %s) from %s -> %s\n", fsp->fnum,
5675 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5676 smb_fname_str_dbg(smb_fname_dst)));
5678 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5679 if (NT_STATUS_IS_OK(status)) {
5680 did_rename = True;
5684 if (!did_rename) {
5685 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5686 "for %s\n", file_id_string_tos(&lck->id),
5687 smb_fname_str_dbg(smb_fname_dst)));
5690 /* Send messages to all smbd's (not ourself) that the name has changed. */
5691 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5692 smb_fname_dst);
5696 /****************************************************************************
5697 We need to check if the source path is a parent directory of the destination
5698 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5699 refuse the rename with a sharing violation. Under UNIX the above call can
5700 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5701 probably need to check that the client is a Windows one before disallowing
5702 this as a UNIX client (one with UNIX extensions) can know the source is a
5703 symlink and make this decision intelligently. Found by an excellent bug
5704 report from <AndyLiebman@aol.com>.
5705 ****************************************************************************/
5707 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5708 const struct smb_filename *smb_fname_dst)
5710 const char *psrc = smb_fname_src->base_name;
5711 const char *pdst = smb_fname_dst->base_name;
5712 size_t slen;
5714 if (psrc[0] == '.' && psrc[1] == '/') {
5715 psrc += 2;
5717 if (pdst[0] == '.' && pdst[1] == '/') {
5718 pdst += 2;
5720 if ((slen = strlen(psrc)) > strlen(pdst)) {
5721 return False;
5723 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5727 * Do the notify calls from a rename
5730 static void notify_rename(connection_struct *conn, bool is_dir,
5731 const struct smb_filename *smb_fname_src,
5732 const struct smb_filename *smb_fname_dst)
5734 char *parent_dir_src = NULL;
5735 char *parent_dir_dst = NULL;
5736 uint32 mask;
5738 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5739 : FILE_NOTIFY_CHANGE_FILE_NAME;
5741 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5742 &parent_dir_src, NULL) ||
5743 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5744 &parent_dir_dst, NULL)) {
5745 goto out;
5748 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5749 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5750 smb_fname_src->base_name);
5751 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5752 smb_fname_dst->base_name);
5754 else {
5755 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5756 smb_fname_src->base_name);
5757 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5758 smb_fname_dst->base_name);
5761 /* this is a strange one. w2k3 gives an additional event for
5762 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5763 files, but not directories */
5764 if (!is_dir) {
5765 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5766 FILE_NOTIFY_CHANGE_ATTRIBUTES
5767 |FILE_NOTIFY_CHANGE_CREATION,
5768 smb_fname_dst->base_name);
5770 out:
5771 TALLOC_FREE(parent_dir_src);
5772 TALLOC_FREE(parent_dir_dst);
5775 /****************************************************************************
5776 Rename an open file - given an fsp.
5777 ****************************************************************************/
5779 NTSTATUS rename_internals_fsp(connection_struct *conn,
5780 files_struct *fsp,
5781 const struct smb_filename *smb_fname_dst_in,
5782 uint32 attrs,
5783 bool replace_if_exists)
5785 TALLOC_CTX *ctx = talloc_tos();
5786 struct smb_filename *smb_fname_dst = NULL;
5787 NTSTATUS status = NT_STATUS_OK;
5788 struct share_mode_lock *lck = NULL;
5789 bool dst_exists, old_is_stream, new_is_stream;
5791 status = check_name(conn, smb_fname_dst_in->base_name);
5792 if (!NT_STATUS_IS_OK(status)) {
5793 return status;
5796 /* Make a copy of the dst smb_fname structs */
5798 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5799 if (!NT_STATUS_IS_OK(status)) {
5800 goto out;
5803 /* Ensure the dst smb_fname contains a '/' */
5804 if(strrchr_m(smb_fname_dst->base_name,'/') == 0) {
5805 char * tmp;
5806 tmp = talloc_asprintf(smb_fname_dst, "./%s",
5807 smb_fname_dst->base_name);
5808 if (!tmp) {
5809 status = NT_STATUS_NO_MEMORY;
5810 goto out;
5812 TALLOC_FREE(smb_fname_dst->base_name);
5813 smb_fname_dst->base_name = tmp;
5817 * Check for special case with case preserving and not
5818 * case sensitive. If the old last component differs from the original
5819 * last component only by case, then we should allow
5820 * the rename (user is trying to change the case of the
5821 * filename).
5823 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5824 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5825 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
5826 char *last_slash;
5827 char *fname_dst_lcomp_base_mod = NULL;
5828 struct smb_filename *smb_fname_orig_lcomp = NULL;
5831 * Get the last component of the destination name. Note that
5832 * we guarantee that destination name contains a '/' character
5833 * above.
5835 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5836 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5837 if (!fname_dst_lcomp_base_mod) {
5838 status = NT_STATUS_NO_MEMORY;
5839 goto out;
5843 * Create an smb_filename struct using the original last
5844 * component of the destination.
5846 status = create_synthetic_smb_fname_split(ctx,
5847 smb_fname_dst->original_lcomp, NULL,
5848 &smb_fname_orig_lcomp);
5849 if (!NT_STATUS_IS_OK(status)) {
5850 TALLOC_FREE(fname_dst_lcomp_base_mod);
5851 goto out;
5854 /* If the base names only differ by case, use original. */
5855 if(!strcsequal(fname_dst_lcomp_base_mod,
5856 smb_fname_orig_lcomp->base_name)) {
5857 char *tmp;
5859 * Replace the modified last component with the
5860 * original.
5862 *last_slash = '\0'; /* Truncate at the '/' */
5863 tmp = talloc_asprintf(smb_fname_dst,
5864 "%s/%s",
5865 smb_fname_dst->base_name,
5866 smb_fname_orig_lcomp->base_name);
5867 if (tmp == NULL) {
5868 status = NT_STATUS_NO_MEMORY;
5869 TALLOC_FREE(fname_dst_lcomp_base_mod);
5870 TALLOC_FREE(smb_fname_orig_lcomp);
5871 goto out;
5873 TALLOC_FREE(smb_fname_dst->base_name);
5874 smb_fname_dst->base_name = tmp;
5877 /* If the stream_names only differ by case, use original. */
5878 if(!strcsequal(smb_fname_dst->stream_name,
5879 smb_fname_orig_lcomp->stream_name)) {
5880 char *tmp = NULL;
5881 /* Use the original stream. */
5882 tmp = talloc_strdup(smb_fname_dst,
5883 smb_fname_orig_lcomp->stream_name);
5884 if (tmp == NULL) {
5885 status = NT_STATUS_NO_MEMORY;
5886 TALLOC_FREE(fname_dst_lcomp_base_mod);
5887 TALLOC_FREE(smb_fname_orig_lcomp);
5888 goto out;
5890 TALLOC_FREE(smb_fname_dst->stream_name);
5891 smb_fname_dst->stream_name = tmp;
5893 TALLOC_FREE(fname_dst_lcomp_base_mod);
5894 TALLOC_FREE(smb_fname_orig_lcomp);
5898 * If the src and dest names are identical - including case,
5899 * don't do the rename, just return success.
5902 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5903 strcsequal(fsp->fsp_name->stream_name,
5904 smb_fname_dst->stream_name)) {
5905 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
5906 "- returning success\n",
5907 smb_fname_str_dbg(smb_fname_dst)));
5908 status = NT_STATUS_OK;
5909 goto out;
5912 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
5913 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
5915 /* Return the correct error code if both names aren't streams. */
5916 if (!old_is_stream && new_is_stream) {
5917 status = NT_STATUS_OBJECT_NAME_INVALID;
5918 goto out;
5921 if (old_is_stream && !new_is_stream) {
5922 status = NT_STATUS_INVALID_PARAMETER;
5923 goto out;
5926 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
5928 if(!replace_if_exists && dst_exists) {
5929 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
5930 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
5931 smb_fname_str_dbg(smb_fname_dst)));
5932 status = NT_STATUS_OBJECT_NAME_COLLISION;
5933 goto out;
5936 if (dst_exists) {
5937 struct file_id fileid = vfs_file_id_from_sbuf(conn,
5938 &smb_fname_dst->st);
5939 files_struct *dst_fsp = file_find_di_first(fileid);
5940 /* The file can be open when renaming a stream */
5941 if (dst_fsp && !new_is_stream) {
5942 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5943 status = NT_STATUS_ACCESS_DENIED;
5944 goto out;
5948 /* Ensure we have a valid stat struct for the source. */
5949 status = vfs_stat_fsp(fsp);
5950 if (!NT_STATUS_IS_OK(status)) {
5951 goto out;
5954 status = can_rename(conn, fsp, attrs);
5956 if (!NT_STATUS_IS_OK(status)) {
5957 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
5958 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
5959 smb_fname_str_dbg(smb_fname_dst)));
5960 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5961 status = NT_STATUS_ACCESS_DENIED;
5962 goto out;
5965 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
5966 status = NT_STATUS_ACCESS_DENIED;
5969 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5970 NULL);
5973 * We have the file open ourselves, so not being able to get the
5974 * corresponding share mode lock is a fatal error.
5977 SMB_ASSERT(lck != NULL);
5979 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
5980 uint32 create_options = fsp->fh->private_options;
5982 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
5983 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
5984 smb_fname_str_dbg(smb_fname_dst)));
5986 if (lp_map_archive(SNUM(conn)) ||
5987 lp_store_dos_attributes(SNUM(conn))) {
5988 /* We must set the archive bit on the newly
5989 renamed file. */
5990 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
5991 uint32_t old_dosmode = dos_mode(conn,
5992 smb_fname_dst);
5993 file_set_dosmode(conn,
5994 smb_fname_dst,
5995 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
5996 NULL,
5997 true);
6001 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6002 smb_fname_dst);
6004 rename_open_files(conn, lck, smb_fname_dst);
6007 * A rename acts as a new file create w.r.t. allowing an initial delete
6008 * on close, probably because in Windows there is a new handle to the
6009 * new file. If initial delete on close was requested but not
6010 * originally set, we need to set it here. This is probably not 100% correct,
6011 * but will work for the CIFSFS client which in non-posix mode
6012 * depends on these semantics. JRA.
6015 if (create_options & FILE_DELETE_ON_CLOSE) {
6016 status = can_set_delete_on_close(fsp, 0);
6018 if (NT_STATUS_IS_OK(status)) {
6019 /* Note that here we set the *inital* delete on close flag,
6020 * not the regular one. The magic gets handled in close. */
6021 fsp->initial_delete_on_close = True;
6024 TALLOC_FREE(lck);
6025 status = NT_STATUS_OK;
6026 goto out;
6029 TALLOC_FREE(lck);
6031 if (errno == ENOTDIR || errno == EISDIR) {
6032 status = NT_STATUS_OBJECT_NAME_COLLISION;
6033 } else {
6034 status = map_nt_error_from_unix(errno);
6037 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6038 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6039 smb_fname_str_dbg(smb_fname_dst)));
6041 out:
6042 TALLOC_FREE(smb_fname_dst);
6044 return status;
6047 /****************************************************************************
6048 The guts of the rename command, split out so it may be called by the NT SMB
6049 code.
6050 ****************************************************************************/
6052 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6053 connection_struct *conn,
6054 struct smb_request *req,
6055 struct smb_filename *smb_fname_src,
6056 struct smb_filename *smb_fname_dst,
6057 uint32 attrs,
6058 bool replace_if_exists,
6059 bool src_has_wild,
6060 bool dest_has_wild,
6061 uint32_t access_mask)
6063 char *fname_src_dir = NULL;
6064 char *fname_src_mask = NULL;
6065 int count=0;
6066 NTSTATUS status = NT_STATUS_OK;
6067 struct smb_Dir *dir_hnd = NULL;
6068 const char *dname = NULL;
6069 char *talloced = NULL;
6070 long offset = 0;
6071 int create_options = 0;
6072 bool posix_pathnames = lp_posix_pathnames();
6075 * Split the old name into directory and last component
6076 * strings. Note that unix_convert may have stripped off a
6077 * leading ./ from both name and newname if the rename is
6078 * at the root of the share. We need to make sure either both
6079 * name and newname contain a / character or neither of them do
6080 * as this is checked in resolve_wildcards().
6083 /* Split up the directory from the filename/mask. */
6084 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6085 &fname_src_dir, &fname_src_mask);
6086 if (!NT_STATUS_IS_OK(status)) {
6087 status = NT_STATUS_NO_MEMORY;
6088 goto out;
6092 * We should only check the mangled cache
6093 * here if unix_convert failed. This means
6094 * that the path in 'mask' doesn't exist
6095 * on the file system and so we need to look
6096 * for a possible mangle. This patch from
6097 * Tine Smukavec <valentin.smukavec@hermes.si>.
6100 if (!VALID_STAT(smb_fname_src->st) &&
6101 mangle_is_mangled(fname_src_mask, conn->params)) {
6102 char *new_mask = NULL;
6103 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6104 conn->params);
6105 if (new_mask) {
6106 TALLOC_FREE(fname_src_mask);
6107 fname_src_mask = new_mask;
6111 if (!src_has_wild) {
6112 files_struct *fsp;
6115 * Only one file needs to be renamed. Append the mask back
6116 * onto the directory.
6118 TALLOC_FREE(smb_fname_src->base_name);
6119 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6120 "%s/%s",
6121 fname_src_dir,
6122 fname_src_mask);
6123 if (!smb_fname_src->base_name) {
6124 status = NT_STATUS_NO_MEMORY;
6125 goto out;
6128 /* Ensure dst fname contains a '/' also */
6129 if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
6130 char *tmp;
6131 tmp = talloc_asprintf(smb_fname_dst, "./%s",
6132 smb_fname_dst->base_name);
6133 if (!tmp) {
6134 status = NT_STATUS_NO_MEMORY;
6135 goto out;
6137 TALLOC_FREE(smb_fname_dst->base_name);
6138 smb_fname_dst->base_name = tmp;
6141 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6142 "case_preserve = %d, short case preserve = %d, "
6143 "directory = %s, newname = %s, "
6144 "last_component_dest = %s\n",
6145 conn->case_sensitive, conn->case_preserve,
6146 conn->short_case_preserve,
6147 smb_fname_str_dbg(smb_fname_src),
6148 smb_fname_str_dbg(smb_fname_dst),
6149 smb_fname_dst->original_lcomp));
6151 /* The dest name still may have wildcards. */
6152 if (dest_has_wild) {
6153 char *fname_dst_mod = NULL;
6154 if (!resolve_wildcards(smb_fname_dst,
6155 smb_fname_src->base_name,
6156 smb_fname_dst->base_name,
6157 &fname_dst_mod)) {
6158 DEBUG(6, ("rename_internals: resolve_wildcards "
6159 "%s %s failed\n",
6160 smb_fname_src->base_name,
6161 smb_fname_dst->base_name));
6162 status = NT_STATUS_NO_MEMORY;
6163 goto out;
6165 TALLOC_FREE(smb_fname_dst->base_name);
6166 smb_fname_dst->base_name = fname_dst_mod;
6169 ZERO_STRUCT(smb_fname_src->st);
6170 if (posix_pathnames) {
6171 SMB_VFS_LSTAT(conn, smb_fname_src);
6172 } else {
6173 SMB_VFS_STAT(conn, smb_fname_src);
6176 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6177 create_options |= FILE_DIRECTORY_FILE;
6180 status = SMB_VFS_CREATE_FILE(
6181 conn, /* conn */
6182 req, /* req */
6183 0, /* root_dir_fid */
6184 smb_fname_src, /* fname */
6185 access_mask, /* access_mask */
6186 (FILE_SHARE_READ | /* share_access */
6187 FILE_SHARE_WRITE),
6188 FILE_OPEN, /* create_disposition*/
6189 create_options, /* create_options */
6190 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6191 0, /* oplock_request */
6192 0, /* allocation_size */
6193 0, /* private_flags */
6194 NULL, /* sd */
6195 NULL, /* ea_list */
6196 &fsp, /* result */
6197 NULL); /* pinfo */
6199 if (!NT_STATUS_IS_OK(status)) {
6200 DEBUG(3, ("Could not open rename source %s: %s\n",
6201 smb_fname_str_dbg(smb_fname_src),
6202 nt_errstr(status)));
6203 goto out;
6206 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6207 attrs, replace_if_exists);
6209 close_file(req, fsp, NORMAL_CLOSE);
6211 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6212 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6213 smb_fname_str_dbg(smb_fname_dst)));
6215 goto out;
6219 * Wildcards - process each file that matches.
6221 if (strequal(fname_src_mask, "????????.???")) {
6222 TALLOC_FREE(fname_src_mask);
6223 fname_src_mask = talloc_strdup(ctx, "*");
6224 if (!fname_src_mask) {
6225 status = NT_STATUS_NO_MEMORY;
6226 goto out;
6230 status = check_name(conn, fname_src_dir);
6231 if (!NT_STATUS_IS_OK(status)) {
6232 goto out;
6235 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6236 attrs);
6237 if (dir_hnd == NULL) {
6238 status = map_nt_error_from_unix(errno);
6239 goto out;
6242 status = NT_STATUS_NO_SUCH_FILE;
6244 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6245 * - gentest fix. JRA
6248 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6249 &talloced))) {
6250 files_struct *fsp = NULL;
6251 char *destname = NULL;
6252 bool sysdir_entry = False;
6254 /* Quick check for "." and ".." */
6255 if (ISDOT(dname) || ISDOTDOT(dname)) {
6256 if (attrs & aDIR) {
6257 sysdir_entry = True;
6258 } else {
6259 TALLOC_FREE(talloced);
6260 continue;
6264 if (!is_visible_file(conn, fname_src_dir, dname,
6265 &smb_fname_src->st, false)) {
6266 TALLOC_FREE(talloced);
6267 continue;
6270 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6271 TALLOC_FREE(talloced);
6272 continue;
6275 if (sysdir_entry) {
6276 status = NT_STATUS_OBJECT_NAME_INVALID;
6277 break;
6280 TALLOC_FREE(smb_fname_src->base_name);
6281 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6282 "%s/%s",
6283 fname_src_dir,
6284 dname);
6285 if (!smb_fname_src->base_name) {
6286 status = NT_STATUS_NO_MEMORY;
6287 goto out;
6290 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6291 smb_fname_dst->base_name,
6292 &destname)) {
6293 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6294 smb_fname_src->base_name, destname));
6295 TALLOC_FREE(talloced);
6296 continue;
6298 if (!destname) {
6299 status = NT_STATUS_NO_MEMORY;
6300 goto out;
6303 TALLOC_FREE(smb_fname_dst->base_name);
6304 smb_fname_dst->base_name = destname;
6306 ZERO_STRUCT(smb_fname_src->st);
6307 if (posix_pathnames) {
6308 SMB_VFS_LSTAT(conn, smb_fname_src);
6309 } else {
6310 SMB_VFS_STAT(conn, smb_fname_src);
6313 create_options = 0;
6315 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6316 create_options |= FILE_DIRECTORY_FILE;
6319 status = SMB_VFS_CREATE_FILE(
6320 conn, /* conn */
6321 req, /* req */
6322 0, /* root_dir_fid */
6323 smb_fname_src, /* fname */
6324 access_mask, /* access_mask */
6325 (FILE_SHARE_READ | /* share_access */
6326 FILE_SHARE_WRITE),
6327 FILE_OPEN, /* create_disposition*/
6328 create_options, /* create_options */
6329 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6330 0, /* oplock_request */
6331 0, /* allocation_size */
6332 0, /* private_flags */
6333 NULL, /* sd */
6334 NULL, /* ea_list */
6335 &fsp, /* result */
6336 NULL); /* pinfo */
6338 if (!NT_STATUS_IS_OK(status)) {
6339 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6340 "returned %s rename %s -> %s\n",
6341 nt_errstr(status),
6342 smb_fname_str_dbg(smb_fname_src),
6343 smb_fname_str_dbg(smb_fname_dst)));
6344 break;
6347 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6348 dname);
6349 if (!smb_fname_dst->original_lcomp) {
6350 status = NT_STATUS_NO_MEMORY;
6351 goto out;
6354 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6355 attrs, replace_if_exists);
6357 close_file(req, fsp, NORMAL_CLOSE);
6359 if (!NT_STATUS_IS_OK(status)) {
6360 DEBUG(3, ("rename_internals_fsp returned %s for "
6361 "rename %s -> %s\n", nt_errstr(status),
6362 smb_fname_str_dbg(smb_fname_src),
6363 smb_fname_str_dbg(smb_fname_dst)));
6364 break;
6367 count++;
6369 DEBUG(3,("rename_internals: doing rename on %s -> "
6370 "%s\n", smb_fname_str_dbg(smb_fname_src),
6371 smb_fname_str_dbg(smb_fname_src)));
6372 TALLOC_FREE(talloced);
6374 TALLOC_FREE(dir_hnd);
6376 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6377 status = map_nt_error_from_unix(errno);
6380 out:
6381 TALLOC_FREE(talloced);
6382 TALLOC_FREE(fname_src_dir);
6383 TALLOC_FREE(fname_src_mask);
6384 return status;
6387 /****************************************************************************
6388 Reply to a mv.
6389 ****************************************************************************/
6391 void reply_mv(struct smb_request *req)
6393 connection_struct *conn = req->conn;
6394 char *name = NULL;
6395 char *newname = NULL;
6396 const char *p;
6397 uint32 attrs;
6398 NTSTATUS status;
6399 bool src_has_wcard = False;
6400 bool dest_has_wcard = False;
6401 TALLOC_CTX *ctx = talloc_tos();
6402 struct smb_filename *smb_fname_src = NULL;
6403 struct smb_filename *smb_fname_dst = NULL;
6405 START_PROFILE(SMBmv);
6407 if (req->wct < 1) {
6408 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6409 goto out;
6412 attrs = SVAL(req->vwv+0, 0);
6414 p = (const char *)req->buf + 1;
6415 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6416 &status, &src_has_wcard);
6417 if (!NT_STATUS_IS_OK(status)) {
6418 reply_nterror(req, status);
6419 goto out;
6421 p++;
6422 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6423 &status, &dest_has_wcard);
6424 if (!NT_STATUS_IS_OK(status)) {
6425 reply_nterror(req, status);
6426 goto out;
6429 status = filename_convert(ctx,
6430 conn,
6431 req->flags2 & FLAGS2_DFS_PATHNAMES,
6432 name,
6433 UCF_COND_ALLOW_WCARD_LCOMP,
6434 &src_has_wcard,
6435 &smb_fname_src);
6437 if (!NT_STATUS_IS_OK(status)) {
6438 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6439 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6440 ERRSRV, ERRbadpath);
6441 goto out;
6443 reply_nterror(req, status);
6444 goto out;
6447 status = filename_convert(ctx,
6448 conn,
6449 req->flags2 & FLAGS2_DFS_PATHNAMES,
6450 newname,
6451 UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6452 &dest_has_wcard,
6453 &smb_fname_dst);
6455 if (!NT_STATUS_IS_OK(status)) {
6456 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6457 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6458 ERRSRV, ERRbadpath);
6459 goto out;
6461 reply_nterror(req, status);
6462 goto out;
6465 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6466 smb_fname_str_dbg(smb_fname_dst)));
6468 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6469 attrs, False, src_has_wcard, dest_has_wcard,
6470 DELETE_ACCESS);
6471 if (!NT_STATUS_IS_OK(status)) {
6472 if (open_was_deferred(req->mid)) {
6473 /* We have re-scheduled this call. */
6474 goto out;
6476 reply_nterror(req, status);
6477 goto out;
6480 reply_outbuf(req, 0, 0);
6481 out:
6482 TALLOC_FREE(smb_fname_src);
6483 TALLOC_FREE(smb_fname_dst);
6484 END_PROFILE(SMBmv);
6485 return;
6488 /*******************************************************************
6489 Copy a file as part of a reply_copy.
6490 ******************************************************************/
6493 * TODO: check error codes on all callers
6496 NTSTATUS copy_file(TALLOC_CTX *ctx,
6497 connection_struct *conn,
6498 struct smb_filename *smb_fname_src,
6499 struct smb_filename *smb_fname_dst,
6500 int ofun,
6501 int count,
6502 bool target_is_directory)
6504 struct smb_filename *smb_fname_dst_tmp = NULL;
6505 SMB_OFF_T ret=-1;
6506 files_struct *fsp1,*fsp2;
6507 uint32 dosattrs;
6508 uint32 new_create_disposition;
6509 NTSTATUS status;
6512 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6513 if (!NT_STATUS_IS_OK(status)) {
6514 return status;
6518 * If the target is a directory, extract the last component from the
6519 * src filename and append it to the dst filename
6521 if (target_is_directory) {
6522 const char *p;
6524 /* dest/target can't be a stream if it's a directory. */
6525 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6527 p = strrchr_m(smb_fname_src->base_name,'/');
6528 if (p) {
6529 p++;
6530 } else {
6531 p = smb_fname_src->base_name;
6533 smb_fname_dst_tmp->base_name =
6534 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6536 if (!smb_fname_dst_tmp->base_name) {
6537 status = NT_STATUS_NO_MEMORY;
6538 goto out;
6542 status = vfs_file_exist(conn, smb_fname_src);
6543 if (!NT_STATUS_IS_OK(status)) {
6544 goto out;
6547 if (!target_is_directory && count) {
6548 new_create_disposition = FILE_OPEN;
6549 } else {
6550 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
6551 NULL, NULL,
6552 &new_create_disposition,
6553 NULL,
6554 NULL)) {
6555 status = NT_STATUS_INVALID_PARAMETER;
6556 goto out;
6560 /* Open the src file for reading. */
6561 status = SMB_VFS_CREATE_FILE(
6562 conn, /* conn */
6563 NULL, /* req */
6564 0, /* root_dir_fid */
6565 smb_fname_src, /* fname */
6566 FILE_GENERIC_READ, /* access_mask */
6567 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6568 FILE_OPEN, /* create_disposition*/
6569 0, /* create_options */
6570 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6571 INTERNAL_OPEN_ONLY, /* oplock_request */
6572 0, /* allocation_size */
6573 0, /* private_flags */
6574 NULL, /* sd */
6575 NULL, /* ea_list */
6576 &fsp1, /* result */
6577 NULL); /* psbuf */
6579 if (!NT_STATUS_IS_OK(status)) {
6580 goto out;
6583 dosattrs = dos_mode(conn, smb_fname_src);
6585 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6586 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6589 /* Open the dst file for writing. */
6590 status = SMB_VFS_CREATE_FILE(
6591 conn, /* conn */
6592 NULL, /* req */
6593 0, /* root_dir_fid */
6594 smb_fname_dst, /* fname */
6595 FILE_GENERIC_WRITE, /* access_mask */
6596 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6597 new_create_disposition, /* create_disposition*/
6598 0, /* create_options */
6599 dosattrs, /* file_attributes */
6600 INTERNAL_OPEN_ONLY, /* oplock_request */
6601 0, /* allocation_size */
6602 0, /* private_flags */
6603 NULL, /* sd */
6604 NULL, /* ea_list */
6605 &fsp2, /* result */
6606 NULL); /* psbuf */
6608 if (!NT_STATUS_IS_OK(status)) {
6609 close_file(NULL, fsp1, ERROR_CLOSE);
6610 goto out;
6613 if ((ofun&3) == 1) {
6614 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6615 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6617 * Stop the copy from occurring.
6619 ret = -1;
6620 smb_fname_src->st.st_ex_size = 0;
6624 /* Do the actual copy. */
6625 if (smb_fname_src->st.st_ex_size) {
6626 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6629 close_file(NULL, fsp1, NORMAL_CLOSE);
6631 /* Ensure the modtime is set correctly on the destination file. */
6632 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6635 * As we are opening fsp1 read-only we only expect
6636 * an error on close on fsp2 if we are out of space.
6637 * Thus we don't look at the error return from the
6638 * close of fsp1.
6640 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6642 if (!NT_STATUS_IS_OK(status)) {
6643 goto out;
6646 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6647 status = NT_STATUS_DISK_FULL;
6648 goto out;
6651 status = NT_STATUS_OK;
6653 out:
6654 TALLOC_FREE(smb_fname_dst_tmp);
6655 return status;
6658 /****************************************************************************
6659 Reply to a file copy.
6660 ****************************************************************************/
6662 void reply_copy(struct smb_request *req)
6664 connection_struct *conn = req->conn;
6665 struct smb_filename *smb_fname_src = NULL;
6666 struct smb_filename *smb_fname_dst = NULL;
6667 char *fname_src = NULL;
6668 char *fname_dst = NULL;
6669 char *fname_src_mask = NULL;
6670 char *fname_src_dir = NULL;
6671 const char *p;
6672 int count=0;
6673 int error = ERRnoaccess;
6674 int tid2;
6675 int ofun;
6676 int flags;
6677 bool target_is_directory=False;
6678 bool source_has_wild = False;
6679 bool dest_has_wild = False;
6680 NTSTATUS status;
6681 TALLOC_CTX *ctx = talloc_tos();
6683 START_PROFILE(SMBcopy);
6685 if (req->wct < 3) {
6686 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6687 goto out;
6690 tid2 = SVAL(req->vwv+0, 0);
6691 ofun = SVAL(req->vwv+1, 0);
6692 flags = SVAL(req->vwv+2, 0);
6694 p = (const char *)req->buf;
6695 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6696 &status, &source_has_wild);
6697 if (!NT_STATUS_IS_OK(status)) {
6698 reply_nterror(req, status);
6699 goto out;
6701 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6702 &status, &dest_has_wild);
6703 if (!NT_STATUS_IS_OK(status)) {
6704 reply_nterror(req, status);
6705 goto out;
6708 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6710 if (tid2 != conn->cnum) {
6711 /* can't currently handle inter share copies XXXX */
6712 DEBUG(3,("Rejecting inter-share copy\n"));
6713 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6714 goto out;
6717 status = filename_convert(ctx, conn,
6718 req->flags2 & FLAGS2_DFS_PATHNAMES,
6719 fname_src,
6720 UCF_COND_ALLOW_WCARD_LCOMP,
6721 &source_has_wild,
6722 &smb_fname_src);
6723 if (!NT_STATUS_IS_OK(status)) {
6724 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6725 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6726 ERRSRV, ERRbadpath);
6727 goto out;
6729 reply_nterror(req, status);
6730 goto out;
6733 status = filename_convert(ctx, conn,
6734 req->flags2 & FLAGS2_DFS_PATHNAMES,
6735 fname_dst,
6736 UCF_COND_ALLOW_WCARD_LCOMP,
6737 &dest_has_wild,
6738 &smb_fname_dst);
6739 if (!NT_STATUS_IS_OK(status)) {
6740 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6741 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6742 ERRSRV, ERRbadpath);
6743 goto out;
6745 reply_nterror(req, status);
6746 goto out;
6749 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6751 if ((flags&1) && target_is_directory) {
6752 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6753 goto out;
6756 if ((flags&2) && !target_is_directory) {
6757 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
6758 goto out;
6761 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6762 /* wants a tree copy! XXXX */
6763 DEBUG(3,("Rejecting tree copy\n"));
6764 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6765 goto out;
6768 /* Split up the directory from the filename/mask. */
6769 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6770 &fname_src_dir, &fname_src_mask);
6771 if (!NT_STATUS_IS_OK(status)) {
6772 reply_nterror(req, NT_STATUS_NO_MEMORY);
6773 goto out;
6777 * We should only check the mangled cache
6778 * here if unix_convert failed. This means
6779 * that the path in 'mask' doesn't exist
6780 * on the file system and so we need to look
6781 * for a possible mangle. This patch from
6782 * Tine Smukavec <valentin.smukavec@hermes.si>.
6784 if (!VALID_STAT(smb_fname_src->st) &&
6785 mangle_is_mangled(fname_src_mask, conn->params)) {
6786 char *new_mask = NULL;
6787 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6788 &new_mask, conn->params);
6790 /* Use demangled name if one was successfully found. */
6791 if (new_mask) {
6792 TALLOC_FREE(fname_src_mask);
6793 fname_src_mask = new_mask;
6797 if (!source_has_wild) {
6800 * Only one file needs to be copied. Append the mask back onto
6801 * the directory.
6803 TALLOC_FREE(smb_fname_src->base_name);
6804 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6805 "%s/%s",
6806 fname_src_dir,
6807 fname_src_mask);
6808 if (!smb_fname_src->base_name) {
6809 reply_nterror(req, NT_STATUS_NO_MEMORY);
6810 goto out;
6813 if (dest_has_wild) {
6814 char *fname_dst_mod = NULL;
6815 if (!resolve_wildcards(smb_fname_dst,
6816 smb_fname_src->base_name,
6817 smb_fname_dst->base_name,
6818 &fname_dst_mod)) {
6819 reply_nterror(req, NT_STATUS_NO_MEMORY);
6820 goto out;
6822 TALLOC_FREE(smb_fname_dst->base_name);
6823 smb_fname_dst->base_name = fname_dst_mod;
6826 status = check_name(conn, smb_fname_src->base_name);
6827 if (!NT_STATUS_IS_OK(status)) {
6828 reply_nterror(req, status);
6829 goto out;
6832 status = check_name(conn, smb_fname_dst->base_name);
6833 if (!NT_STATUS_IS_OK(status)) {
6834 reply_nterror(req, status);
6835 goto out;
6838 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
6839 ofun, count, target_is_directory);
6841 if(!NT_STATUS_IS_OK(status)) {
6842 reply_nterror(req, status);
6843 goto out;
6844 } else {
6845 count++;
6847 } else {
6848 struct smb_Dir *dir_hnd = NULL;
6849 const char *dname = NULL;
6850 char *talloced = NULL;
6851 long offset = 0;
6854 * There is a wildcard that requires us to actually read the
6855 * src dir and copy each file matching the mask to the dst.
6856 * Right now streams won't be copied, but this could
6857 * presumably be added with a nested loop for reach dir entry.
6859 SMB_ASSERT(!smb_fname_src->stream_name);
6860 SMB_ASSERT(!smb_fname_dst->stream_name);
6862 smb_fname_src->stream_name = NULL;
6863 smb_fname_dst->stream_name = NULL;
6865 if (strequal(fname_src_mask,"????????.???")) {
6866 TALLOC_FREE(fname_src_mask);
6867 fname_src_mask = talloc_strdup(ctx, "*");
6868 if (!fname_src_mask) {
6869 reply_nterror(req, NT_STATUS_NO_MEMORY);
6870 goto out;
6874 status = check_name(conn, fname_src_dir);
6875 if (!NT_STATUS_IS_OK(status)) {
6876 reply_nterror(req, status);
6877 goto out;
6880 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
6881 if (dir_hnd == NULL) {
6882 status = map_nt_error_from_unix(errno);
6883 reply_nterror(req, status);
6884 goto out;
6887 error = ERRbadfile;
6889 /* Iterate over the src dir copying each entry to the dst. */
6890 while ((dname = ReadDirName(dir_hnd, &offset,
6891 &smb_fname_src->st, &talloced))) {
6892 char *destname = NULL;
6894 if (ISDOT(dname) || ISDOTDOT(dname)) {
6895 TALLOC_FREE(talloced);
6896 continue;
6899 if (!is_visible_file(conn, fname_src_dir, dname,
6900 &smb_fname_src->st, false)) {
6901 TALLOC_FREE(talloced);
6902 continue;
6905 if(!mask_match(dname, fname_src_mask,
6906 conn->case_sensitive)) {
6907 TALLOC_FREE(talloced);
6908 continue;
6911 error = ERRnoaccess;
6913 /* Get the src smb_fname struct setup. */
6914 TALLOC_FREE(smb_fname_src->base_name);
6915 smb_fname_src->base_name =
6916 talloc_asprintf(smb_fname_src, "%s/%s",
6917 fname_src_dir, dname);
6919 if (!smb_fname_src->base_name) {
6920 TALLOC_FREE(dir_hnd);
6921 TALLOC_FREE(talloced);
6922 reply_nterror(req, NT_STATUS_NO_MEMORY);
6923 goto out;
6926 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6927 smb_fname_dst->base_name,
6928 &destname)) {
6929 TALLOC_FREE(talloced);
6930 continue;
6932 if (!destname) {
6933 TALLOC_FREE(dir_hnd);
6934 TALLOC_FREE(talloced);
6935 reply_nterror(req, NT_STATUS_NO_MEMORY);
6936 goto out;
6939 TALLOC_FREE(smb_fname_dst->base_name);
6940 smb_fname_dst->base_name = destname;
6942 status = check_name(conn, smb_fname_src->base_name);
6943 if (!NT_STATUS_IS_OK(status)) {
6944 TALLOC_FREE(dir_hnd);
6945 TALLOC_FREE(talloced);
6946 reply_nterror(req, status);
6947 goto out;
6950 status = check_name(conn, smb_fname_dst->base_name);
6951 if (!NT_STATUS_IS_OK(status)) {
6952 TALLOC_FREE(dir_hnd);
6953 TALLOC_FREE(talloced);
6954 reply_nterror(req, status);
6955 goto out;
6958 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
6959 smb_fname_src->base_name,
6960 smb_fname_dst->base_name));
6962 status = copy_file(ctx, conn, smb_fname_src,
6963 smb_fname_dst, ofun, count,
6964 target_is_directory);
6965 if (NT_STATUS_IS_OK(status)) {
6966 count++;
6969 TALLOC_FREE(talloced);
6971 TALLOC_FREE(dir_hnd);
6974 if (count == 0) {
6975 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
6976 goto out;
6979 reply_outbuf(req, 1, 0);
6980 SSVAL(req->outbuf,smb_vwv0,count);
6981 out:
6982 TALLOC_FREE(smb_fname_src);
6983 TALLOC_FREE(smb_fname_dst);
6984 TALLOC_FREE(fname_src);
6985 TALLOC_FREE(fname_dst);
6986 TALLOC_FREE(fname_src_mask);
6987 TALLOC_FREE(fname_src_dir);
6989 END_PROFILE(SMBcopy);
6990 return;
6993 #undef DBGC_CLASS
6994 #define DBGC_CLASS DBGC_LOCKING
6996 /****************************************************************************
6997 Get a lock pid, dealing with large count requests.
6998 ****************************************************************************/
7000 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7001 bool large_file_format)
7003 if(!large_file_format)
7004 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7005 else
7006 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7009 /****************************************************************************
7010 Get a lock count, dealing with large count requests.
7011 ****************************************************************************/
7013 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7014 bool large_file_format)
7016 uint64_t count = 0;
7018 if(!large_file_format) {
7019 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7020 } else {
7022 #if defined(HAVE_LONGLONG)
7023 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7024 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7025 #else /* HAVE_LONGLONG */
7028 * NT4.x seems to be broken in that it sends large file (64 bit)
7029 * lockingX calls even if the CAP_LARGE_FILES was *not*
7030 * negotiated. For boxes without large unsigned ints truncate the
7031 * lock count by dropping the top 32 bits.
7034 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7035 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7036 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7037 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7038 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7041 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7042 #endif /* HAVE_LONGLONG */
7045 return count;
7048 #if !defined(HAVE_LONGLONG)
7049 /****************************************************************************
7050 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7051 ****************************************************************************/
7053 static uint32 map_lock_offset(uint32 high, uint32 low)
7055 unsigned int i;
7056 uint32 mask = 0;
7057 uint32 highcopy = high;
7060 * Try and find out how many significant bits there are in high.
7063 for(i = 0; highcopy; i++)
7064 highcopy >>= 1;
7067 * We use 31 bits not 32 here as POSIX
7068 * lock offsets may not be negative.
7071 mask = (~0) << (31 - i);
7073 if(low & mask)
7074 return 0; /* Fail. */
7076 high <<= (31 - i);
7078 return (high|low);
7080 #endif /* !defined(HAVE_LONGLONG) */
7082 /****************************************************************************
7083 Get a lock offset, dealing with large offset requests.
7084 ****************************************************************************/
7086 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7087 bool large_file_format, bool *err)
7089 uint64_t offset = 0;
7091 *err = False;
7093 if(!large_file_format) {
7094 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7095 } else {
7097 #if defined(HAVE_LONGLONG)
7098 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7099 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7100 #else /* HAVE_LONGLONG */
7103 * NT4.x seems to be broken in that it sends large file (64 bit)
7104 * lockingX calls even if the CAP_LARGE_FILES was *not*
7105 * negotiated. For boxes without large unsigned ints mangle the
7106 * lock offset by mapping the top 32 bits onto the lower 32.
7109 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7110 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7111 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7112 uint32 new_low = 0;
7114 if((new_low = map_lock_offset(high, low)) == 0) {
7115 *err = True;
7116 return (uint64_t)-1;
7119 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7120 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7121 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7122 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7125 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7126 #endif /* HAVE_LONGLONG */
7129 return offset;
7132 NTSTATUS smbd_do_locking(struct smb_request *req,
7133 files_struct *fsp,
7134 uint8_t type,
7135 int32_t timeout,
7136 uint16_t num_ulocks,
7137 struct smbd_lock_element *ulocks,
7138 uint16_t num_locks,
7139 struct smbd_lock_element *locks,
7140 bool *async)
7142 connection_struct *conn = req->conn;
7143 int i;
7144 NTSTATUS status = NT_STATUS_OK;
7146 *async = false;
7148 /* Data now points at the beginning of the list
7149 of smb_unlkrng structs */
7150 for(i = 0; i < (int)num_ulocks; i++) {
7151 struct smbd_lock_element *e = &ulocks[i];
7153 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7154 "pid %u, file %s\n",
7155 (double)e->offset,
7156 (double)e->count,
7157 (unsigned int)e->smblctx,
7158 fsp_str_dbg(fsp)));
7160 if (e->brltype != UNLOCK_LOCK) {
7161 /* this can only happen with SMB2 */
7162 return NT_STATUS_INVALID_PARAMETER;
7165 status = do_unlock(req->sconn->msg_ctx,
7166 fsp,
7167 e->smblctx,
7168 e->count,
7169 e->offset,
7170 WINDOWS_LOCK);
7172 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7173 nt_errstr(status)));
7175 if (!NT_STATUS_IS_OK(status)) {
7176 return status;
7180 /* Setup the timeout in seconds. */
7182 if (!lp_blocking_locks(SNUM(conn))) {
7183 timeout = 0;
7186 /* Data now points at the beginning of the list
7187 of smb_lkrng structs */
7189 for(i = 0; i < (int)num_locks; i++) {
7190 struct smbd_lock_element *e = &locks[i];
7192 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7193 "%llu, file %s timeout = %d\n",
7194 (double)e->offset,
7195 (double)e->count,
7196 (unsigned long long)e->smblctx,
7197 fsp_str_dbg(fsp),
7198 (int)timeout));
7200 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7201 struct blocking_lock_record *blr = NULL;
7203 if (num_locks > 1) {
7205 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7206 * if the lock vector contains one entry. When given mutliple cancel
7207 * requests in a single PDU we expect the server to return an
7208 * error. Windows servers seem to accept the request but only
7209 * cancel the first lock.
7210 * JRA - Do what Windows does (tm) :-).
7213 #if 0
7214 /* MS-CIFS (2.2.4.32.1) behavior. */
7215 return NT_STATUS_DOS(ERRDOS,
7216 ERRcancelviolation);
7217 #else
7218 /* Windows behavior. */
7219 if (i != 0) {
7220 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7221 "cancel request\n"));
7222 continue;
7224 #endif
7227 if (lp_blocking_locks(SNUM(conn))) {
7229 /* Schedule a message to ourselves to
7230 remove the blocking lock record and
7231 return the right error. */
7233 blr = blocking_lock_cancel_smb1(fsp,
7234 e->smblctx,
7235 e->offset,
7236 e->count,
7237 WINDOWS_LOCK,
7238 type,
7239 NT_STATUS_FILE_LOCK_CONFLICT);
7240 if (blr == NULL) {
7241 return NT_STATUS_DOS(
7242 ERRDOS,
7243 ERRcancelviolation);
7246 /* Remove a matching pending lock. */
7247 status = do_lock_cancel(fsp,
7248 e->smblctx,
7249 e->count,
7250 e->offset,
7251 WINDOWS_LOCK,
7252 blr);
7253 } else {
7254 bool blocking_lock = timeout ? true : false;
7255 bool defer_lock = false;
7256 struct byte_range_lock *br_lck;
7257 uint64_t block_smblctx;
7259 br_lck = do_lock(req->sconn->msg_ctx,
7260 fsp,
7261 e->smblctx,
7262 e->count,
7263 e->offset,
7264 e->brltype,
7265 WINDOWS_LOCK,
7266 blocking_lock,
7267 &status,
7268 &block_smblctx,
7269 NULL);
7271 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7272 /* Windows internal resolution for blocking locks seems
7273 to be about 200ms... Don't wait for less than that. JRA. */
7274 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7275 timeout = lp_lock_spin_time();
7277 defer_lock = true;
7280 /* If a lock sent with timeout of zero would fail, and
7281 * this lock has been requested multiple times,
7282 * according to brl_lock_failed() we convert this
7283 * request to a blocking lock with a timeout of between
7284 * 150 - 300 milliseconds.
7286 * If lp_lock_spin_time() has been set to 0, we skip
7287 * this blocking retry and fail immediately.
7289 * Replacement for do_lock_spin(). JRA. */
7291 if (!req->sconn->using_smb2 &&
7292 br_lck && lp_blocking_locks(SNUM(conn)) &&
7293 lp_lock_spin_time() && !blocking_lock &&
7294 NT_STATUS_EQUAL((status),
7295 NT_STATUS_FILE_LOCK_CONFLICT))
7297 defer_lock = true;
7298 timeout = lp_lock_spin_time();
7301 if (br_lck && defer_lock) {
7303 * A blocking lock was requested. Package up
7304 * this smb into a queued request and push it
7305 * onto the blocking lock queue.
7307 if(push_blocking_lock_request(br_lck,
7308 req,
7309 fsp,
7310 timeout,
7312 e->smblctx,
7313 e->brltype,
7314 WINDOWS_LOCK,
7315 e->offset,
7316 e->count,
7317 block_smblctx)) {
7318 TALLOC_FREE(br_lck);
7319 *async = true;
7320 return NT_STATUS_OK;
7324 TALLOC_FREE(br_lck);
7327 if (!NT_STATUS_IS_OK(status)) {
7328 break;
7332 /* If any of the above locks failed, then we must unlock
7333 all of the previous locks (X/Open spec). */
7335 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7337 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7338 i = -1; /* we want to skip the for loop */
7342 * Ensure we don't do a remove on the lock that just failed,
7343 * as under POSIX rules, if we have a lock already there, we
7344 * will delete it (and we shouldn't) .....
7346 for(i--; i >= 0; i--) {
7347 struct smbd_lock_element *e = &locks[i];
7349 do_unlock(req->sconn->msg_ctx,
7350 fsp,
7351 e->smblctx,
7352 e->count,
7353 e->offset,
7354 WINDOWS_LOCK);
7356 return status;
7359 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7360 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7362 return NT_STATUS_OK;
7365 /****************************************************************************
7366 Reply to a lockingX request.
7367 ****************************************************************************/
7369 void reply_lockingX(struct smb_request *req)
7371 connection_struct *conn = req->conn;
7372 files_struct *fsp;
7373 unsigned char locktype;
7374 unsigned char oplocklevel;
7375 uint16 num_ulocks;
7376 uint16 num_locks;
7377 int32 lock_timeout;
7378 int i;
7379 const uint8_t *data;
7380 bool large_file_format;
7381 bool err;
7382 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7383 struct smbd_lock_element *ulocks;
7384 struct smbd_lock_element *locks;
7385 bool async = false;
7387 START_PROFILE(SMBlockingX);
7389 if (req->wct < 8) {
7390 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7391 END_PROFILE(SMBlockingX);
7392 return;
7395 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7396 locktype = CVAL(req->vwv+3, 0);
7397 oplocklevel = CVAL(req->vwv+3, 1);
7398 num_ulocks = SVAL(req->vwv+6, 0);
7399 num_locks = SVAL(req->vwv+7, 0);
7400 lock_timeout = IVAL(req->vwv+4, 0);
7401 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7403 if (!check_fsp(conn, req, fsp)) {
7404 END_PROFILE(SMBlockingX);
7405 return;
7408 data = req->buf;
7410 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7411 /* we don't support these - and CANCEL_LOCK makes w2k
7412 and XP reboot so I don't really want to be
7413 compatible! (tridge) */
7414 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7415 END_PROFILE(SMBlockingX);
7416 return;
7419 /* Check if this is an oplock break on a file
7420 we have granted an oplock on.
7422 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7423 /* Client can insist on breaking to none. */
7424 bool break_to_none = (oplocklevel == 0);
7425 bool result;
7427 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7428 "for fnum = %d\n", (unsigned int)oplocklevel,
7429 fsp->fnum ));
7432 * Make sure we have granted an exclusive or batch oplock on
7433 * this file.
7436 if (fsp->oplock_type == 0) {
7438 /* The Samba4 nbench simulator doesn't understand
7439 the difference between break to level2 and break
7440 to none from level2 - it sends oplock break
7441 replies in both cases. Don't keep logging an error
7442 message here - just ignore it. JRA. */
7444 DEBUG(5,("reply_lockingX: Error : oplock break from "
7445 "client for fnum = %d (oplock=%d) and no "
7446 "oplock granted on this file (%s).\n",
7447 fsp->fnum, fsp->oplock_type,
7448 fsp_str_dbg(fsp)));
7450 /* if this is a pure oplock break request then don't
7451 * send a reply */
7452 if (num_locks == 0 && num_ulocks == 0) {
7453 END_PROFILE(SMBlockingX);
7454 return;
7455 } else {
7456 END_PROFILE(SMBlockingX);
7457 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7458 return;
7462 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7463 (break_to_none)) {
7464 result = remove_oplock(fsp);
7465 } else {
7466 result = downgrade_oplock(fsp);
7469 if (!result) {
7470 DEBUG(0, ("reply_lockingX: error in removing "
7471 "oplock on file %s\n", fsp_str_dbg(fsp)));
7472 /* Hmmm. Is this panic justified? */
7473 smb_panic("internal tdb error");
7476 reply_to_oplock_break_requests(fsp);
7478 /* if this is a pure oplock break request then don't send a
7479 * reply */
7480 if (num_locks == 0 && num_ulocks == 0) {
7481 /* Sanity check - ensure a pure oplock break is not a
7482 chained request. */
7483 if(CVAL(req->vwv+0, 0) != 0xff)
7484 DEBUG(0,("reply_lockingX: Error : pure oplock "
7485 "break is a chained %d request !\n",
7486 (unsigned int)CVAL(req->vwv+0, 0)));
7487 END_PROFILE(SMBlockingX);
7488 return;
7492 if (req->buflen <
7493 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7494 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7495 END_PROFILE(SMBlockingX);
7496 return;
7499 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7500 if (ulocks == NULL) {
7501 reply_nterror(req, NT_STATUS_NO_MEMORY);
7502 END_PROFILE(SMBlockingX);
7503 return;
7506 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7507 if (locks == NULL) {
7508 reply_nterror(req, NT_STATUS_NO_MEMORY);
7509 END_PROFILE(SMBlockingX);
7510 return;
7513 /* Data now points at the beginning of the list
7514 of smb_unlkrng structs */
7515 for(i = 0; i < (int)num_ulocks; i++) {
7516 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7517 ulocks[i].count = get_lock_count(data, i, large_file_format);
7518 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7519 ulocks[i].brltype = UNLOCK_LOCK;
7522 * There is no error code marked "stupid client bug".... :-).
7524 if(err) {
7525 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7526 END_PROFILE(SMBlockingX);
7527 return;
7531 /* Now do any requested locks */
7532 data += ((large_file_format ? 20 : 10)*num_ulocks);
7534 /* Data now points at the beginning of the list
7535 of smb_lkrng structs */
7537 for(i = 0; i < (int)num_locks; i++) {
7538 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7539 locks[i].count = get_lock_count(data, i, large_file_format);
7540 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7542 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7543 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7544 locks[i].brltype = PENDING_READ_LOCK;
7545 } else {
7546 locks[i].brltype = READ_LOCK;
7548 } else {
7549 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7550 locks[i].brltype = PENDING_WRITE_LOCK;
7551 } else {
7552 locks[i].brltype = WRITE_LOCK;
7557 * There is no error code marked "stupid client bug".... :-).
7559 if(err) {
7560 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7561 END_PROFILE(SMBlockingX);
7562 return;
7566 status = smbd_do_locking(req, fsp,
7567 locktype, lock_timeout,
7568 num_ulocks, ulocks,
7569 num_locks, locks,
7570 &async);
7571 if (!NT_STATUS_IS_OK(status)) {
7572 END_PROFILE(SMBlockingX);
7573 reply_nterror(req, status);
7574 return;
7576 if (async) {
7577 END_PROFILE(SMBlockingX);
7578 return;
7581 reply_outbuf(req, 2, 0);
7583 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7584 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7586 END_PROFILE(SMBlockingX);
7587 chain_reply(req);
7590 #undef DBGC_CLASS
7591 #define DBGC_CLASS DBGC_ALL
7593 /****************************************************************************
7594 Reply to a SMBreadbmpx (read block multiplex) request.
7595 Always reply with an error, if someone has a platform really needs this,
7596 please contact vl@samba.org
7597 ****************************************************************************/
7599 void reply_readbmpx(struct smb_request *req)
7601 START_PROFILE(SMBreadBmpx);
7602 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7603 END_PROFILE(SMBreadBmpx);
7604 return;
7607 /****************************************************************************
7608 Reply to a SMBreadbs (read block multiplex secondary) request.
7609 Always reply with an error, if someone has a platform really needs this,
7610 please contact vl@samba.org
7611 ****************************************************************************/
7613 void reply_readbs(struct smb_request *req)
7615 START_PROFILE(SMBreadBs);
7616 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7617 END_PROFILE(SMBreadBs);
7618 return;
7621 /****************************************************************************
7622 Reply to a SMBsetattrE.
7623 ****************************************************************************/
7625 void reply_setattrE(struct smb_request *req)
7627 connection_struct *conn = req->conn;
7628 struct smb_file_time ft;
7629 files_struct *fsp;
7630 NTSTATUS status;
7632 START_PROFILE(SMBsetattrE);
7633 ZERO_STRUCT(ft);
7635 if (req->wct < 7) {
7636 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7637 goto out;
7640 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7642 if(!fsp || (fsp->conn != conn)) {
7643 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7644 goto out;
7648 * Convert the DOS times into unix times.
7651 ft.atime = convert_time_t_to_timespec(
7652 srv_make_unix_date2(req->vwv+3));
7653 ft.mtime = convert_time_t_to_timespec(
7654 srv_make_unix_date2(req->vwv+5));
7655 ft.create_time = convert_time_t_to_timespec(
7656 srv_make_unix_date2(req->vwv+1));
7658 reply_outbuf(req, 0, 0);
7661 * Patch from Ray Frush <frush@engr.colostate.edu>
7662 * Sometimes times are sent as zero - ignore them.
7665 /* Ensure we have a valid stat struct for the source. */
7666 status = vfs_stat_fsp(fsp);
7667 if (!NT_STATUS_IS_OK(status)) {
7668 reply_nterror(req, status);
7669 goto out;
7672 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7673 if (!NT_STATUS_IS_OK(status)) {
7674 reply_nterror(req, status);
7675 goto out;
7678 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7679 " createtime=%u\n",
7680 fsp->fnum,
7681 (unsigned int)ft.atime.tv_sec,
7682 (unsigned int)ft.mtime.tv_sec,
7683 (unsigned int)ft.create_time.tv_sec
7685 out:
7686 END_PROFILE(SMBsetattrE);
7687 return;
7691 /* Back from the dead for OS/2..... JRA. */
7693 /****************************************************************************
7694 Reply to a SMBwritebmpx (write block multiplex primary) request.
7695 Always reply with an error, if someone has a platform really needs this,
7696 please contact vl@samba.org
7697 ****************************************************************************/
7699 void reply_writebmpx(struct smb_request *req)
7701 START_PROFILE(SMBwriteBmpx);
7702 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7703 END_PROFILE(SMBwriteBmpx);
7704 return;
7707 /****************************************************************************
7708 Reply to a SMBwritebs (write block multiplex secondary) request.
7709 Always reply with an error, if someone has a platform really needs this,
7710 please contact vl@samba.org
7711 ****************************************************************************/
7713 void reply_writebs(struct smb_request *req)
7715 START_PROFILE(SMBwriteBs);
7716 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7717 END_PROFILE(SMBwriteBs);
7718 return;
7721 /****************************************************************************
7722 Reply to a SMBgetattrE.
7723 ****************************************************************************/
7725 void reply_getattrE(struct smb_request *req)
7727 connection_struct *conn = req->conn;
7728 int mode;
7729 files_struct *fsp;
7730 struct timespec create_ts;
7732 START_PROFILE(SMBgetattrE);
7734 if (req->wct < 1) {
7735 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7736 END_PROFILE(SMBgetattrE);
7737 return;
7740 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7742 if(!fsp || (fsp->conn != conn)) {
7743 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7744 END_PROFILE(SMBgetattrE);
7745 return;
7748 /* Do an fstat on this file */
7749 if(fsp_stat(fsp)) {
7750 reply_nterror(req, map_nt_error_from_unix(errno));
7751 END_PROFILE(SMBgetattrE);
7752 return;
7755 mode = dos_mode(conn, fsp->fsp_name);
7758 * Convert the times into dos times. Set create
7759 * date to be last modify date as UNIX doesn't save
7760 * this.
7763 reply_outbuf(req, 11, 0);
7765 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7766 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7767 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7768 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7769 /* Should we check pending modtime here ? JRA */
7770 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7771 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7773 if (mode & aDIR) {
7774 SIVAL(req->outbuf, smb_vwv6, 0);
7775 SIVAL(req->outbuf, smb_vwv8, 0);
7776 } else {
7777 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7778 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
7779 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7781 SSVAL(req->outbuf,smb_vwv10, mode);
7783 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7785 END_PROFILE(SMBgetattrE);
7786 return;