smbd: Fix opening the quota magic file
[Samba.git] / source / smbd / reply.c
blob1141cfe0ec75376666f72476f6d833ba0d730990
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"
29 /* look in server.c for some explanation of these variables */
30 extern enum protocol_types Protocol;
31 extern int max_recv;
32 extern uint32 global_client_caps;
34 extern bool global_encrypted_passwords_negotiated;
36 /****************************************************************************
37 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
38 path or anything including wildcards.
39 We're assuming here that '/' is not the second byte in any multibyte char
40 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
41 set.
42 ****************************************************************************/
44 /* Custom version for processing POSIX paths. */
45 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
47 static NTSTATUS check_path_syntax_internal(char *path,
48 bool posix_path,
49 bool *p_last_component_contains_wcard)
51 char *d = path;
52 const char *s = path;
53 bool start_of_name_component = True;
54 bool stream_started = false;
55 bool check_quota = false;
57 *p_last_component_contains_wcard = False;
59 while (*s) {
60 if (stream_started) {
61 switch (*s) {
62 case '/':
63 case '\\':
64 return NT_STATUS_OBJECT_NAME_INVALID;
65 case ':':
66 if (s[1] == '\0') {
67 return NT_STATUS_OBJECT_NAME_INVALID;
69 if (strchr_m(&s[1], ':')) {
70 return NT_STATUS_OBJECT_NAME_INVALID;
72 if (StrCaseCmp(s, ":$DATA") != 0) {
73 check_quota = true;
75 break;
79 if (!posix_path && !stream_started && *s == ':') {
80 if (*p_last_component_contains_wcard) {
81 return NT_STATUS_OBJECT_NAME_INVALID;
83 /* Stream names allow more characters than file names.
84 We're overloading posix_path here to allow a wider
85 range of characters. If stream_started is true this
86 is still a Windows path even if posix_path is true.
87 JRA.
89 stream_started = true;
90 start_of_name_component = false;
91 posix_path = true;
93 if (s[1] == '\0') {
94 return NT_STATUS_OBJECT_NAME_INVALID;
98 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
100 * Safe to assume is not the second part of a mb char
101 * as this is handled below.
103 /* Eat multiple '/' or '\\' */
104 while (IS_PATH_SEP(*s,posix_path)) {
105 s++;
107 if ((d != path) && (*s != '\0')) {
108 /* We only care about non-leading or trailing '/' or '\\' */
109 *d++ = '/';
112 start_of_name_component = True;
113 /* New component. */
114 *p_last_component_contains_wcard = False;
115 continue;
118 if (start_of_name_component) {
119 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
120 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
123 * No mb char starts with '.' so we're safe checking the directory separator here.
126 /* If we just added a '/' - delete it */
127 if ((d > path) && (*(d-1) == '/')) {
128 *(d-1) = '\0';
129 d--;
132 /* Are we at the start ? Can't go back further if so. */
133 if (d <= path) {
134 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
136 /* Go back one level... */
137 /* We know this is safe as '/' cannot be part of a mb sequence. */
138 /* NOTE - if this assumption is invalid we are not in good shape... */
139 /* Decrement d first as d points to the *next* char to write into. */
140 for (d--; d > path; d--) {
141 if (*d == '/')
142 break;
144 s += 2; /* Else go past the .. */
145 /* We're still at the start of a name component, just the previous one. */
146 continue;
148 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
149 if (posix_path) {
150 /* Eat the '.' */
151 s++;
152 continue;
158 if (!(*s & 0x80)) {
159 if (!posix_path) {
160 if (*s <= 0x1f || *s == '|') {
161 return NT_STATUS_OBJECT_NAME_INVALID;
163 switch (*s) {
164 case '*':
165 case '?':
166 case '<':
167 case '>':
168 case '"':
169 *p_last_component_contains_wcard = True;
170 break;
171 default:
172 break;
175 *d++ = *s++;
176 } else {
177 size_t siz;
178 /* Get the size of the next MB character. */
179 next_codepoint(s,&siz);
180 switch(siz) {
181 case 5:
182 *d++ = *s++;
183 /*fall through*/
184 case 4:
185 *d++ = *s++;
186 /*fall through*/
187 case 3:
188 *d++ = *s++;
189 /*fall through*/
190 case 2:
191 *d++ = *s++;
192 /*fall through*/
193 case 1:
194 *d++ = *s++;
195 break;
196 default:
197 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
198 *d = '\0';
199 return NT_STATUS_INVALID_PARAMETER;
202 start_of_name_component = False;
205 *d = '\0';
207 if (check_quota) {
208 if (StrCaseCmp(path, FAKE_FILE_NAME_QUOTA_UNIX) != 0) {
209 return NT_STATUS_INVALID_PARAMETER;
213 return NT_STATUS_OK;
216 /****************************************************************************
217 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
218 No wildcards allowed.
219 ****************************************************************************/
221 NTSTATUS check_path_syntax(char *path)
223 bool ignore;
224 return check_path_syntax_internal(path, False, &ignore);
227 /****************************************************************************
228 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
229 Wildcards allowed - p_contains_wcard returns true if the last component contained
230 a wildcard.
231 ****************************************************************************/
233 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
235 return check_path_syntax_internal(path, False, p_contains_wcard);
238 /****************************************************************************
239 Check the path for a POSIX client.
240 We're assuming here that '/' is not the second byte in any multibyte char
241 set (a safe assumption).
242 ****************************************************************************/
244 NTSTATUS check_path_syntax_posix(char *path)
246 bool ignore;
247 return check_path_syntax_internal(path, True, &ignore);
250 /****************************************************************************
251 Pull a string and check the path allowing a wilcard - provide for error return.
252 ****************************************************************************/
254 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
255 const char *inbuf,
256 uint16 smb_flags2,
257 char **pp_dest,
258 const char *src,
259 size_t src_len,
260 int flags,
261 NTSTATUS *err,
262 bool *contains_wcard)
264 size_t ret;
266 *pp_dest = NULL;
268 if (src_len == 0) {
269 ret = srvstr_pull_buf_talloc(ctx,
270 inbuf,
271 smb_flags2,
272 pp_dest,
273 src,
274 flags);
275 } else {
276 ret = srvstr_pull_talloc(ctx,
277 inbuf,
278 smb_flags2,
279 pp_dest,
280 src,
281 src_len,
282 flags);
285 if (!*pp_dest) {
286 *err = NT_STATUS_INVALID_PARAMETER;
287 return ret;
290 *contains_wcard = False;
292 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
294 * For a DFS path the function parse_dfs_path()
295 * will do the path processing, just make a copy.
297 *err = NT_STATUS_OK;
298 return ret;
301 if (lp_posix_pathnames()) {
302 *err = check_path_syntax_posix(*pp_dest);
303 } else {
304 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
307 return ret;
310 /****************************************************************************
311 Pull a string and check the path - provide for error return.
312 ****************************************************************************/
314 size_t srvstr_get_path(TALLOC_CTX *ctx,
315 const char *inbuf,
316 uint16 smb_flags2,
317 char **pp_dest,
318 const char *src,
319 size_t src_len,
320 int flags,
321 NTSTATUS *err)
323 size_t ret;
325 *pp_dest = NULL;
327 if (src_len == 0) {
328 ret = srvstr_pull_buf_talloc(ctx,
329 inbuf,
330 smb_flags2,
331 pp_dest,
332 src,
333 flags);
334 } else {
335 ret = srvstr_pull_talloc(ctx,
336 inbuf,
337 smb_flags2,
338 pp_dest,
339 src,
340 src_len,
341 flags);
344 if (!*pp_dest) {
345 *err = NT_STATUS_INVALID_PARAMETER;
346 return ret;
349 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
351 * For a DFS path the function parse_dfs_path()
352 * will do the path processing, just make a copy.
354 *err = NT_STATUS_OK;
355 return ret;
358 if (lp_posix_pathnames()) {
359 *err = check_path_syntax_posix(*pp_dest);
360 } else {
361 *err = check_path_syntax(*pp_dest);
364 return ret;
367 /****************************************************************************
368 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
369 ****************************************************************************/
371 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
372 files_struct *fsp)
374 if (!(fsp) || !(conn)) {
375 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
376 return False;
378 if (((conn) != (fsp)->conn) || req->vuid != (fsp)->vuid) {
379 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
380 return False;
382 return True;
385 /****************************************************************************
386 Check if we have a correct fsp pointing to a file.
387 ****************************************************************************/
389 bool check_fsp(connection_struct *conn, struct smb_request *req,
390 files_struct *fsp)
392 if (!check_fsp_open(conn, req, fsp)) {
393 return False;
395 if ((fsp)->is_directory) {
396 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
397 return False;
399 if ((fsp)->fh->fd == -1) {
400 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
401 return False;
403 (fsp)->num_smb_operations++;
404 return True;
407 /****************************************************************************
408 Check if we have a correct fsp pointing to a quota fake file. Replacement for
409 the CHECK_NTQUOTA_HANDLE_OK macro.
410 ****************************************************************************/
412 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
413 files_struct *fsp)
415 if (!check_fsp_open(conn, req, fsp)) {
416 return false;
419 if (fsp->is_directory) {
420 return false;
423 if (fsp->fake_file_handle == NULL) {
424 return false;
427 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
428 return false;
431 if (fsp->fake_file_handle->private_data == NULL) {
432 return false;
435 return true;
438 /****************************************************************************
439 Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
440 ****************************************************************************/
442 bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
443 files_struct *fsp)
445 if ((fsp) && (conn) && ((conn)==(fsp)->conn)
446 && (req->vuid == (fsp)->vuid)) {
447 return True;
450 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
451 return False;
454 /****************************************************************************
455 Reply to a (netbios-level) special message.
456 ****************************************************************************/
458 void reply_special(char *inbuf)
460 int msg_type = CVAL(inbuf,0);
461 int msg_flags = CVAL(inbuf,1);
462 fstring name1,name2;
463 char name_type = 0;
466 * We only really use 4 bytes of the outbuf, but for the smb_setlen
467 * calculation & friends (srv_send_smb uses that) we need the full smb
468 * header.
470 char outbuf[smb_size];
472 static bool already_got_session = False;
474 *name1 = *name2 = 0;
476 memset(outbuf, '\0', sizeof(outbuf));
478 smb_setlen(outbuf,0);
480 switch (msg_type) {
481 case 0x81: /* session request */
483 if (already_got_session) {
484 exit_server_cleanly("multiple session request not permitted");
487 SCVAL(outbuf,0,0x82);
488 SCVAL(outbuf,3,0);
489 if (name_len(inbuf+4) > 50 ||
490 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
491 DEBUG(0,("Invalid name length in session request\n"));
492 return;
494 name_extract(inbuf,4,name1);
495 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
496 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
497 name1,name2));
499 set_local_machine_name(name1, True);
500 set_remote_machine_name(name2, True);
502 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
503 get_local_machine_name(), get_remote_machine_name(),
504 name_type));
506 if (name_type == 'R') {
507 /* We are being asked for a pathworks session ---
508 no thanks! */
509 SCVAL(outbuf, 0,0x83);
510 break;
513 /* only add the client's machine name to the list
514 of possibly valid usernames if we are operating
515 in share mode security */
516 if (lp_security() == SEC_SHARE) {
517 add_session_user(get_remote_machine_name());
520 reload_services(True);
521 reopen_logs();
523 already_got_session = True;
524 break;
526 case 0x89: /* session keepalive request
527 (some old clients produce this?) */
528 SCVAL(outbuf,0,SMBkeepalive);
529 SCVAL(outbuf,3,0);
530 break;
532 case 0x82: /* positive session response */
533 case 0x83: /* negative session response */
534 case 0x84: /* retarget session response */
535 DEBUG(0,("Unexpected session response\n"));
536 break;
538 case SMBkeepalive: /* session keepalive */
539 default:
540 return;
543 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
544 msg_type, msg_flags));
546 srv_send_smb(smbd_server_fd(), outbuf, false);
547 return;
550 /****************************************************************************
551 Reply to a tcon.
552 conn POINTER CAN BE NULL HERE !
553 ****************************************************************************/
555 void reply_tcon(struct smb_request *req)
557 connection_struct *conn = req->conn;
558 const char *service;
559 char *service_buf = NULL;
560 char *password = NULL;
561 char *dev = NULL;
562 int pwlen=0;
563 NTSTATUS nt_status;
564 char *p;
565 DATA_BLOB password_blob;
566 TALLOC_CTX *ctx = talloc_tos();
568 START_PROFILE(SMBtcon);
570 if (smb_buflen(req->inbuf) < 4) {
571 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
572 END_PROFILE(SMBtcon);
573 return;
576 p = smb_buf(req->inbuf)+1;
577 p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2,
578 &service_buf, p, STR_TERMINATE) + 1;
579 pwlen = srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2,
580 &password, p, STR_TERMINATE) + 1;
581 p += pwlen;
582 p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2,
583 &dev, p, STR_TERMINATE) + 1;
585 if (service_buf == NULL || password == NULL || dev == NULL) {
586 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
587 END_PROFILE(SMBtcon);
588 return;
590 p = strrchr_m(service_buf,'\\');
591 if (p) {
592 service = p+1;
593 } else {
594 service = service_buf;
597 password_blob = data_blob(password, pwlen+1);
599 conn = make_connection(service,password_blob,dev,req->vuid,&nt_status);
600 req->conn = conn;
602 data_blob_clear_free(&password_blob);
604 if (!conn) {
605 reply_nterror(req, nt_status);
606 END_PROFILE(SMBtcon);
607 return;
610 reply_outbuf(req, 2, 0);
611 SSVAL(req->outbuf,smb_vwv0,max_recv);
612 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
613 SSVAL(req->outbuf,smb_tid,conn->cnum);
615 DEBUG(3,("tcon service=%s cnum=%d\n",
616 service, conn->cnum));
618 END_PROFILE(SMBtcon);
619 return;
622 /****************************************************************************
623 Reply to a tcon and X.
624 conn POINTER CAN BE NULL HERE !
625 ****************************************************************************/
627 void reply_tcon_and_X(struct smb_request *req)
629 connection_struct *conn = req->conn;
630 char *service = NULL;
631 DATA_BLOB password;
632 TALLOC_CTX *ctx = talloc_tos();
633 /* what the cleint thinks the device is */
634 char *client_devicetype = NULL;
635 /* what the server tells the client the share represents */
636 const char *server_devicetype;
637 NTSTATUS nt_status;
638 int passlen;
639 char *path = NULL;
640 char *p, *q;
641 uint16 tcon_flags;
643 START_PROFILE(SMBtconX);
645 if (req->wct < 4) {
646 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
647 END_PROFILE(SMBtconX);
648 return;
651 passlen = SVAL(req->inbuf,smb_vwv3);
652 tcon_flags = SVAL(req->inbuf,smb_vwv2);
654 /* we might have to close an old one */
655 if ((tcon_flags & 0x1) && conn) {
656 close_cnum(conn,req->vuid);
657 req->conn = NULL;
658 conn = NULL;
661 if ((passlen > MAX_PASS_LEN) || (passlen >= smb_buflen(req->inbuf))) {
662 reply_doserror(req, ERRDOS, ERRbuftoosmall);
663 END_PROFILE(SMBtconX);
664 return;
667 if (global_encrypted_passwords_negotiated) {
668 password = data_blob_talloc(talloc_tos(), smb_buf(req->inbuf),
669 passlen);
670 if (lp_security() == SEC_SHARE) {
672 * Security = share always has a pad byte
673 * after the password.
675 p = smb_buf(req->inbuf) + passlen + 1;
676 } else {
677 p = smb_buf(req->inbuf) + passlen;
679 } else {
680 password = data_blob_talloc(talloc_tos(), smb_buf(req->inbuf),
681 passlen+1);
682 /* Ensure correct termination */
683 password.data[passlen]=0;
684 p = smb_buf(req->inbuf) + passlen + 1;
687 p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2, &path, p,
688 STR_TERMINATE);
690 if (path == NULL) {
691 data_blob_clear_free(&password);
692 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
693 END_PROFILE(SMBtconX);
694 return;
698 * the service name can be either: \\server\share
699 * or share directly like on the DELL PowerVault 705
701 if (*path=='\\') {
702 q = strchr_m(path+2,'\\');
703 if (!q) {
704 data_blob_clear_free(&password);
705 reply_doserror(req, ERRDOS, ERRnosuchshare);
706 END_PROFILE(SMBtconX);
707 return;
709 service = q+1;
710 } else {
711 service = path;
714 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
715 &client_devicetype, p,
716 MIN(6,smb_bufrem(req->inbuf, p)), STR_ASCII);
718 if (client_devicetype == NULL) {
719 data_blob_clear_free(&password);
720 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
721 END_PROFILE(SMBtconX);
722 return;
725 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
727 conn = make_connection(service, password, client_devicetype,
728 req->vuid, &nt_status);
729 req->conn =conn;
731 data_blob_clear_free(&password);
733 if (!conn) {
734 reply_nterror(req, nt_status);
735 END_PROFILE(SMBtconX);
736 return;
739 if ( IS_IPC(conn) )
740 server_devicetype = "IPC";
741 else if ( IS_PRINT(conn) )
742 server_devicetype = "LPT1:";
743 else
744 server_devicetype = "A:";
746 if (Protocol < PROTOCOL_NT1) {
747 reply_outbuf(req, 2, 0);
748 if (message_push_string(&req->outbuf, server_devicetype,
749 STR_TERMINATE|STR_ASCII) == -1) {
750 reply_nterror(req, NT_STATUS_NO_MEMORY);
751 END_PROFILE(SMBtconX);
752 return;
754 } else {
755 /* NT sets the fstype of IPC$ to the null string */
756 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
758 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
759 /* Return permissions. */
760 uint32 perm1 = 0;
761 uint32 perm2 = 0;
763 reply_outbuf(req, 7, 0);
765 if (IS_IPC(conn)) {
766 perm1 = FILE_ALL_ACCESS;
767 perm2 = FILE_ALL_ACCESS;
768 } else {
769 perm1 = CAN_WRITE(conn) ?
770 SHARE_ALL_ACCESS :
771 SHARE_READ_ONLY;
774 SIVAL(req->outbuf, smb_vwv3, perm1);
775 SIVAL(req->outbuf, smb_vwv5, perm2);
776 } else {
777 reply_outbuf(req, 3, 0);
780 if ((message_push_string(&req->outbuf, server_devicetype,
781 STR_TERMINATE|STR_ASCII) == -1)
782 || (message_push_string(&req->outbuf, fstype,
783 STR_TERMINATE) == -1)) {
784 reply_nterror(req, NT_STATUS_NO_MEMORY);
785 END_PROFILE(SMBtconX);
786 return;
789 /* what does setting this bit do? It is set by NT4 and
790 may affect the ability to autorun mounted cdroms */
791 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
792 (lp_csc_policy(SNUM(conn)) << 2));
794 init_dfsroot(conn, req->inbuf, req->outbuf);
798 DEBUG(3,("tconX service=%s \n",
799 service));
801 /* set the incoming and outgoing tid to the just created one */
802 SSVAL(req->inbuf,smb_tid,conn->cnum);
803 SSVAL(req->outbuf,smb_tid,conn->cnum);
805 END_PROFILE(SMBtconX);
807 chain_reply(req);
808 return;
811 /****************************************************************************
812 Reply to an unknown type.
813 ****************************************************************************/
815 void reply_unknown_new(struct smb_request *req, uint8 type)
817 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
818 smb_fn_name(type), type, type));
819 reply_doserror(req, ERRSRV, ERRunknownsmb);
820 return;
823 /****************************************************************************
824 Reply to an ioctl.
825 conn POINTER CAN BE NULL HERE !
826 ****************************************************************************/
828 void reply_ioctl(struct smb_request *req)
830 connection_struct *conn = req->conn;
831 uint16 device;
832 uint16 function;
833 uint32 ioctl_code;
834 int replysize;
835 char *p;
837 START_PROFILE(SMBioctl);
839 if (req->wct < 3) {
840 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
841 END_PROFILE(SMBioctl);
842 return;
845 device = SVAL(req->inbuf,smb_vwv1);
846 function = SVAL(req->inbuf,smb_vwv2);
847 ioctl_code = (device << 16) + function;
849 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
851 switch (ioctl_code) {
852 case IOCTL_QUERY_JOB_INFO:
853 replysize = 32;
854 break;
855 default:
856 reply_doserror(req, ERRSRV, ERRnosupport);
857 END_PROFILE(SMBioctl);
858 return;
861 reply_outbuf(req, 8, replysize+1);
862 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
863 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
864 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
865 p = smb_buf(req->outbuf);
866 memset(p, '\0', replysize+1); /* valgrind-safe. */
867 p += 1; /* Allow for alignment */
869 switch (ioctl_code) {
870 case IOCTL_QUERY_JOB_INFO:
872 files_struct *fsp = file_fsp(SVAL(req->inbuf,
873 smb_vwv0));
874 if (!fsp) {
875 reply_doserror(req, ERRDOS, ERRbadfid);
876 END_PROFILE(SMBioctl);
877 return;
879 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
880 srvstr_push((char *)req->outbuf, req->flags2, p+2,
881 global_myname(), 15,
882 STR_TERMINATE|STR_ASCII);
883 if (conn) {
884 srvstr_push((char *)req->outbuf, req->flags2,
885 p+18, lp_servicename(SNUM(conn)),
886 13, STR_TERMINATE|STR_ASCII);
887 } else {
888 memset(p+18, 0, 13);
890 break;
894 END_PROFILE(SMBioctl);
895 return;
898 /****************************************************************************
899 Strange checkpath NTSTATUS mapping.
900 ****************************************************************************/
902 static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
904 /* Strange DOS error code semantics only for checkpath... */
905 if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
906 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
907 /* We need to map to ERRbadpath */
908 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
911 return status;
914 /****************************************************************************
915 Reply to a checkpath.
916 ****************************************************************************/
918 void reply_checkpath(struct smb_request *req)
920 connection_struct *conn = req->conn;
921 char *name = NULL;
922 SMB_STRUCT_STAT sbuf;
923 NTSTATUS status;
924 TALLOC_CTX *ctx = talloc_tos();
926 START_PROFILE(SMBcheckpath);
928 srvstr_get_path(ctx,(char *)req->inbuf, req->flags2, &name,
929 smb_buf(req->inbuf) + 1, 0,
930 STR_TERMINATE, &status);
931 if (!NT_STATUS_IS_OK(status)) {
932 status = map_checkpath_error((char *)req->inbuf, status);
933 reply_nterror(req, status);
934 END_PROFILE(SMBcheckpath);
935 return;
938 status = resolve_dfspath(ctx, conn,
939 req->flags2 & FLAGS2_DFS_PATHNAMES,
940 name,
941 &name);
942 if (!NT_STATUS_IS_OK(status)) {
943 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
944 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
945 ERRSRV, ERRbadpath);
946 END_PROFILE(SMBcheckpath);
947 return;
949 goto path_err;
952 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->inbuf,smb_vwv0)));
954 status = unix_convert(ctx, conn, name, False, &name, NULL, &sbuf);
955 if (!NT_STATUS_IS_OK(status)) {
956 goto path_err;
959 status = check_name(conn, name);
960 if (!NT_STATUS_IS_OK(status)) {
961 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
962 goto path_err;
965 if (!VALID_STAT(sbuf)) {
966 int ret;
968 if (lp_posix_pathnames()) {
969 ret = SMB_VFS_LSTAT(conn,name,&sbuf);
970 } else {
971 ret = SMB_VFS_STAT(conn,name,&sbuf);
973 if (ret != 0) {
974 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
975 status = map_nt_error_from_unix(errno);
976 goto path_err;
980 if (!S_ISDIR(sbuf.st_mode)) {
981 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
982 ERRDOS, ERRbadpath);
983 END_PROFILE(SMBcheckpath);
984 return;
987 reply_outbuf(req, 0, 0);
989 END_PROFILE(SMBcheckpath);
990 return;
992 path_err:
994 END_PROFILE(SMBcheckpath);
996 /* We special case this - as when a Windows machine
997 is parsing a path is steps through the components
998 one at a time - if a component fails it expects
999 ERRbadpath, not ERRbadfile.
1001 status = map_checkpath_error((char *)req->inbuf, status);
1002 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1004 * Windows returns different error codes if
1005 * the parent directory is valid but not the
1006 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1007 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1008 * if the path is invalid.
1010 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1011 ERRDOS, ERRbadpath);
1012 return;
1015 reply_nterror(req, status);
1018 /****************************************************************************
1019 Reply to a getatr.
1020 ****************************************************************************/
1022 void reply_getatr(struct smb_request *req)
1024 connection_struct *conn = req->conn;
1025 char *fname = NULL;
1026 SMB_STRUCT_STAT sbuf;
1027 int mode=0;
1028 SMB_OFF_T size=0;
1029 time_t mtime=0;
1030 char *p;
1031 NTSTATUS status;
1032 TALLOC_CTX *ctx = talloc_tos();
1034 START_PROFILE(SMBgetatr);
1036 p = smb_buf(req->inbuf) + 1;
1037 p += srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname, p,
1038 0, STR_TERMINATE, &status);
1039 if (!NT_STATUS_IS_OK(status)) {
1040 reply_nterror(req, status);
1041 END_PROFILE(SMBgetatr);
1042 return;
1045 status = resolve_dfspath(ctx, conn,
1046 req->flags2 & FLAGS2_DFS_PATHNAMES,
1047 fname,
1048 &fname);
1049 if (!NT_STATUS_IS_OK(status)) {
1050 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1051 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1052 ERRSRV, ERRbadpath);
1053 END_PROFILE(SMBgetatr);
1054 return;
1056 reply_nterror(req, status);
1057 END_PROFILE(SMBgetatr);
1058 return;
1061 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1062 under WfWg - weird! */
1063 if (*fname == '\0') {
1064 mode = aHIDDEN | aDIR;
1065 if (!CAN_WRITE(conn)) {
1066 mode |= aRONLY;
1068 size = 0;
1069 mtime = 0;
1070 } else {
1071 status = unix_convert(ctx, conn, fname, False, &fname, NULL,&sbuf);
1072 if (!NT_STATUS_IS_OK(status)) {
1073 reply_nterror(req, status);
1074 END_PROFILE(SMBgetatr);
1075 return;
1077 status = check_name(conn, fname);
1078 if (!NT_STATUS_IS_OK(status)) {
1079 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
1080 reply_nterror(req, status);
1081 END_PROFILE(SMBgetatr);
1082 return;
1084 if (!VALID_STAT(sbuf)) {
1085 int ret;
1087 if (lp_posix_pathnames()) {
1088 ret = SMB_VFS_LSTAT(conn,fname,&sbuf);
1089 } else {
1090 ret = SMB_VFS_STAT(conn,fname,&sbuf);
1092 if (ret != 0) {
1093 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
1094 reply_unixerror(req, ERRDOS,ERRbadfile);
1095 END_PROFILE(SMBgetatr);
1096 return;
1100 mode = dos_mode(conn,fname,&sbuf);
1101 size = sbuf.st_size;
1102 mtime = sbuf.st_mtime;
1103 if (mode & aDIR) {
1104 size = 0;
1108 reply_outbuf(req, 10, 0);
1110 SSVAL(req->outbuf,smb_vwv0,mode);
1111 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1112 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1113 } else {
1114 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1116 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1118 if (Protocol >= PROTOCOL_NT1) {
1119 SSVAL(req->outbuf, smb_flg2,
1120 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1123 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
1125 END_PROFILE(SMBgetatr);
1126 return;
1129 /****************************************************************************
1130 Reply to a setatr.
1131 ****************************************************************************/
1133 void reply_setatr(struct smb_request *req)
1135 struct timespec ts[2];
1136 connection_struct *conn = req->conn;
1137 char *fname = NULL;
1138 int mode;
1139 time_t mtime;
1140 SMB_STRUCT_STAT sbuf;
1141 char *p;
1142 NTSTATUS status;
1143 TALLOC_CTX *ctx = talloc_tos();
1145 START_PROFILE(SMBsetatr);
1147 ZERO_STRUCT(ts);
1149 if (req->wct < 2) {
1150 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1151 return;
1154 p = smb_buf(req->inbuf) + 1;
1155 p += srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname, p,
1156 0, STR_TERMINATE, &status);
1157 if (!NT_STATUS_IS_OK(status)) {
1158 reply_nterror(req, status);
1159 END_PROFILE(SMBsetatr);
1160 return;
1163 status = resolve_dfspath(ctx, conn,
1164 req->flags2 & FLAGS2_DFS_PATHNAMES,
1165 fname,
1166 &fname);
1167 if (!NT_STATUS_IS_OK(status)) {
1168 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1169 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1170 ERRSRV, ERRbadpath);
1171 END_PROFILE(SMBsetatr);
1172 return;
1174 reply_nterror(req, status);
1175 END_PROFILE(SMBsetatr);
1176 return;
1179 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
1180 if (!NT_STATUS_IS_OK(status)) {
1181 reply_nterror(req, status);
1182 END_PROFILE(SMBsetatr);
1183 return;
1186 status = check_name(conn, fname);
1187 if (!NT_STATUS_IS_OK(status)) {
1188 reply_nterror(req, status);
1189 END_PROFILE(SMBsetatr);
1190 return;
1193 if (fname[0] == '.' && fname[1] == '\0') {
1195 * Not sure here is the right place to catch this
1196 * condition. Might be moved to somewhere else later -- vl
1198 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1199 END_PROFILE(SMBsetatr);
1200 return;
1203 mode = SVAL(req->inbuf,smb_vwv0);
1204 mtime = srv_make_unix_date3(req->inbuf+smb_vwv1);
1206 ts[1] = convert_time_t_to_timespec(mtime);
1207 status = smb_set_file_time(conn, NULL, fname,
1208 &sbuf, ts, true);
1209 if (!NT_STATUS_IS_OK(status)) {
1210 reply_unixerror(req, ERRDOS, ERRnoaccess);
1211 END_PROFILE(SMBsetatr);
1212 return;
1215 if (mode != FILE_ATTRIBUTE_NORMAL) {
1216 if (VALID_STAT_OF_DIR(sbuf))
1217 mode |= aDIR;
1218 else
1219 mode &= ~aDIR;
1221 if (file_set_dosmode(conn,fname,mode,&sbuf,NULL,false) != 0) {
1222 reply_unixerror(req, ERRDOS, ERRnoaccess);
1223 END_PROFILE(SMBsetatr);
1224 return;
1228 reply_outbuf(req, 0, 0);
1230 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1232 END_PROFILE(SMBsetatr);
1233 return;
1236 /****************************************************************************
1237 Reply to a dskattr.
1238 ****************************************************************************/
1240 void reply_dskattr(struct smb_request *req)
1242 connection_struct *conn = req->conn;
1243 SMB_BIG_UINT dfree,dsize,bsize;
1244 START_PROFILE(SMBdskattr);
1246 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1247 reply_unixerror(req, ERRHRD, ERRgeneral);
1248 END_PROFILE(SMBdskattr);
1249 return;
1252 reply_outbuf(req, 5, 0);
1254 if (Protocol <= PROTOCOL_LANMAN2) {
1255 double total_space, free_space;
1256 /* we need to scale this to a number that DOS6 can handle. We
1257 use floating point so we can handle large drives on systems
1258 that don't have 64 bit integers
1260 we end up displaying a maximum of 2G to DOS systems
1262 total_space = dsize * (double)bsize;
1263 free_space = dfree * (double)bsize;
1265 dsize = (SMB_BIG_UINT)((total_space+63*512) / (64*512));
1266 dfree = (SMB_BIG_UINT)((free_space+63*512) / (64*512));
1268 if (dsize > 0xFFFF) dsize = 0xFFFF;
1269 if (dfree > 0xFFFF) dfree = 0xFFFF;
1271 SSVAL(req->outbuf,smb_vwv0,dsize);
1272 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1273 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1274 SSVAL(req->outbuf,smb_vwv3,dfree);
1275 } else {
1276 SSVAL(req->outbuf,smb_vwv0,dsize);
1277 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1278 SSVAL(req->outbuf,smb_vwv2,512);
1279 SSVAL(req->outbuf,smb_vwv3,dfree);
1282 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1284 END_PROFILE(SMBdskattr);
1285 return;
1288 /****************************************************************************
1289 Reply to a search.
1290 Can be called from SMBsearch, SMBffirst or SMBfunique.
1291 ****************************************************************************/
1293 void reply_search(struct smb_request *req)
1295 connection_struct *conn = req->conn;
1296 char *mask = NULL;
1297 char *directory = NULL;
1298 char *fname = NULL;
1299 SMB_OFF_T size;
1300 uint32 mode;
1301 time_t date;
1302 uint32 dirtype;
1303 unsigned int numentries = 0;
1304 unsigned int maxentries = 0;
1305 bool finished = False;
1306 char *p;
1307 int status_len;
1308 char *path = NULL;
1309 char status[21];
1310 int dptr_num= -1;
1311 bool check_descend = False;
1312 bool expect_close = False;
1313 NTSTATUS nt_status;
1314 bool mask_contains_wcard = False;
1315 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1316 TALLOC_CTX *ctx = talloc_tos();
1317 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1319 START_PROFILE(SMBsearch);
1321 if (req->wct < 2) {
1322 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1323 END_PROFILE(SMBsearch);
1324 return;
1327 if (lp_posix_pathnames()) {
1328 reply_unknown_new(req, CVAL(req->inbuf, smb_com));
1329 END_PROFILE(SMBsearch);
1330 return;
1333 /* If we were called as SMBffirst then we must expect close. */
1334 if(CVAL(req->inbuf,smb_com) == SMBffirst) {
1335 expect_close = True;
1338 reply_outbuf(req, 1, 3);
1339 maxentries = SVAL(req->inbuf,smb_vwv0);
1340 dirtype = SVAL(req->inbuf,smb_vwv1);
1341 p = smb_buf(req->inbuf) + 1;
1342 p += srvstr_get_path_wcard(ctx,
1343 (char *)req->inbuf,
1344 req->flags2,
1345 &path,
1348 STR_TERMINATE,
1349 &nt_status,
1350 &mask_contains_wcard);
1351 if (!NT_STATUS_IS_OK(nt_status)) {
1352 reply_nterror(req, nt_status);
1353 END_PROFILE(SMBsearch);
1354 return;
1357 nt_status = resolve_dfspath_wcard(ctx, conn,
1358 req->flags2 & FLAGS2_DFS_PATHNAMES,
1359 path,
1360 &path,
1361 &mask_contains_wcard);
1362 if (!NT_STATUS_IS_OK(nt_status)) {
1363 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1364 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1365 ERRSRV, ERRbadpath);
1366 END_PROFILE(SMBsearch);
1367 return;
1369 reply_nterror(req, nt_status);
1370 END_PROFILE(SMBsearch);
1371 return;
1374 p++;
1375 status_len = SVAL(p, 0);
1376 p += 2;
1378 /* dirtype &= ~aDIR; */
1380 if (status_len == 0) {
1381 SMB_STRUCT_STAT sbuf;
1383 nt_status = unix_convert(ctx, conn, path, True,
1384 &directory, NULL, &sbuf);
1385 if (!NT_STATUS_IS_OK(nt_status)) {
1386 reply_nterror(req, nt_status);
1387 END_PROFILE(SMBsearch);
1388 return;
1391 nt_status = check_name(conn, directory);
1392 if (!NT_STATUS_IS_OK(nt_status)) {
1393 reply_nterror(req, nt_status);
1394 END_PROFILE(SMBsearch);
1395 return;
1398 p = strrchr_m(directory,'/');
1399 if (!p) {
1400 mask = directory;
1401 directory = talloc_strdup(ctx,".");
1402 if (!directory) {
1403 reply_nterror(req, NT_STATUS_NO_MEMORY);
1404 END_PROFILE(SMBsearch);
1405 return;
1407 } else {
1408 *p = 0;
1409 mask = p+1;
1412 if (*directory == '\0') {
1413 directory = talloc_strdup(ctx,".");
1414 if (!directory) {
1415 reply_nterror(req, NT_STATUS_NO_MEMORY);
1416 END_PROFILE(SMBsearch);
1417 return;
1420 memset((char *)status,'\0',21);
1421 SCVAL(status,0,(dirtype & 0x1F));
1423 nt_status = dptr_create(conn,
1424 directory,
1425 True,
1426 expect_close,
1427 req->smbpid,
1428 mask,
1429 mask_contains_wcard,
1430 dirtype,
1431 &conn->dirptr);
1432 if (!NT_STATUS_IS_OK(nt_status)) {
1433 reply_nterror(req, nt_status);
1434 END_PROFILE(SMBsearch);
1435 return;
1437 dptr_num = dptr_dnum(conn->dirptr);
1438 } else {
1439 int status_dirtype;
1441 memcpy(status,p,21);
1442 status_dirtype = CVAL(status,0) & 0x1F;
1443 if (status_dirtype != (dirtype & 0x1F)) {
1444 dirtype = status_dirtype;
1447 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1448 if (!conn->dirptr) {
1449 goto SearchEmpty;
1451 string_set(&conn->dirpath,dptr_path(dptr_num));
1452 mask = dptr_wcard(dptr_num);
1453 if (!mask) {
1454 goto SearchEmpty;
1457 * For a 'continue' search we have no string. So
1458 * check from the initial saved string.
1460 mask_contains_wcard = ms_has_wild(mask);
1461 dirtype = dptr_attr(dptr_num);
1464 DEBUG(4,("dptr_num is %d\n",dptr_num));
1466 if ((dirtype&0x1F) == aVOLID) {
1467 char buf[DIR_STRUCT_SIZE];
1468 memcpy(buf,status,21);
1469 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1470 0,aVOLID,0,!allow_long_path_components)) {
1471 reply_nterror(req, NT_STATUS_NO_MEMORY);
1472 END_PROFILE(SMBsearch);
1473 return;
1475 dptr_fill(buf+12,dptr_num);
1476 if (dptr_zero(buf+12) && (status_len==0)) {
1477 numentries = 1;
1478 } else {
1479 numentries = 0;
1481 if (message_push_blob(&req->outbuf,
1482 data_blob_const(buf, sizeof(buf)))
1483 == -1) {
1484 reply_nterror(req, NT_STATUS_NO_MEMORY);
1485 END_PROFILE(SMBsearch);
1486 return;
1488 } else {
1489 unsigned int i;
1490 maxentries = MIN(
1491 maxentries,
1492 ((BUFFER_SIZE -
1493 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1494 /DIR_STRUCT_SIZE));
1496 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1497 conn->dirpath,lp_dontdescend(SNUM(conn))));
1498 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1499 check_descend = True;
1502 for (i=numentries;(i<maxentries) && !finished;i++) {
1503 finished = !get_dir_entry(ctx,
1504 conn,
1505 mask,
1506 dirtype,
1507 &fname,
1508 &size,
1509 &mode,
1510 &date,
1511 check_descend,
1512 ask_sharemode);
1513 if (!finished) {
1514 char buf[DIR_STRUCT_SIZE];
1515 memcpy(buf,status,21);
1516 if (!make_dir_struct(ctx,
1517 buf,
1518 mask,
1519 fname,
1520 size,
1521 mode,
1522 date,
1523 !allow_long_path_components)) {
1524 reply_nterror(req, NT_STATUS_NO_MEMORY);
1525 END_PROFILE(SMBsearch);
1526 return;
1528 if (!dptr_fill(buf+12,dptr_num)) {
1529 break;
1531 if (message_push_blob(&req->outbuf,
1532 data_blob_const(buf, sizeof(buf)))
1533 == -1) {
1534 reply_nterror(req, NT_STATUS_NO_MEMORY);
1535 END_PROFILE(SMBsearch);
1536 return;
1538 numentries++;
1543 SearchEmpty:
1545 /* If we were called as SMBffirst with smb_search_id == NULL
1546 and no entries were found then return error and close dirptr
1547 (X/Open spec) */
1549 if (numentries == 0) {
1550 dptr_close(&dptr_num);
1551 } else if(expect_close && status_len == 0) {
1552 /* Close the dptr - we know it's gone */
1553 dptr_close(&dptr_num);
1556 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1557 if(dptr_num >= 0 && CVAL(req->inbuf,smb_com) == SMBfunique) {
1558 dptr_close(&dptr_num);
1561 if ((numentries == 0) && !mask_contains_wcard) {
1562 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1563 END_PROFILE(SMBsearch);
1564 return;
1567 SSVAL(req->outbuf,smb_vwv0,numentries);
1568 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1569 SCVAL(smb_buf(req->outbuf),0,5);
1570 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1572 /* The replies here are never long name. */
1573 SSVAL(req->outbuf, smb_flg2,
1574 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1575 if (!allow_long_path_components) {
1576 SSVAL(req->outbuf, smb_flg2,
1577 SVAL(req->outbuf, smb_flg2)
1578 & (~FLAGS2_LONG_PATH_COMPONENTS));
1581 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1582 SSVAL(req->outbuf, smb_flg2,
1583 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1585 if (!directory) {
1586 directory = dptr_path(dptr_num);
1589 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1590 smb_fn_name(CVAL(req->inbuf,smb_com)),
1591 mask,
1592 directory ? directory : "./",
1593 dirtype,
1594 numentries,
1595 maxentries ));
1597 END_PROFILE(SMBsearch);
1598 return;
1601 /****************************************************************************
1602 Reply to a fclose (stop directory search).
1603 ****************************************************************************/
1605 void reply_fclose(struct smb_request *req)
1607 int status_len;
1608 char status[21];
1609 int dptr_num= -2;
1610 char *p;
1611 char *path = NULL;
1612 NTSTATUS err;
1613 bool path_contains_wcard = False;
1614 TALLOC_CTX *ctx = talloc_tos();
1616 START_PROFILE(SMBfclose);
1618 if (lp_posix_pathnames()) {
1619 reply_unknown_new(req, CVAL(req->inbuf, smb_com));
1620 END_PROFILE(SMBfclose);
1621 return;
1624 p = smb_buf(req->inbuf) + 1;
1625 p += srvstr_get_path_wcard(ctx,
1626 (char *)req->inbuf,
1627 req->flags2,
1628 &path,
1631 STR_TERMINATE,
1632 &err,
1633 &path_contains_wcard);
1634 if (!NT_STATUS_IS_OK(err)) {
1635 reply_nterror(req, err);
1636 END_PROFILE(SMBfclose);
1637 return;
1639 p++;
1640 status_len = SVAL(p,0);
1641 p += 2;
1643 if (status_len == 0) {
1644 reply_doserror(req, ERRSRV, ERRsrverror);
1645 END_PROFILE(SMBfclose);
1646 return;
1649 memcpy(status,p,21);
1651 if(dptr_fetch(status+12,&dptr_num)) {
1652 /* Close the dptr - we know it's gone */
1653 dptr_close(&dptr_num);
1656 reply_outbuf(req, 1, 0);
1657 SSVAL(req->outbuf,smb_vwv0,0);
1659 DEBUG(3,("search close\n"));
1661 END_PROFILE(SMBfclose);
1662 return;
1665 /****************************************************************************
1666 Reply to an open.
1667 ****************************************************************************/
1669 void reply_open(struct smb_request *req)
1671 connection_struct *conn = req->conn;
1672 char *fname = NULL;
1673 uint32 fattr=0;
1674 SMB_OFF_T size = 0;
1675 time_t mtime=0;
1676 int info;
1677 SMB_STRUCT_STAT sbuf;
1678 files_struct *fsp;
1679 int oplock_request;
1680 int deny_mode;
1681 uint32 dos_attr;
1682 uint32 access_mask;
1683 uint32 share_mode;
1684 uint32 create_disposition;
1685 uint32 create_options = 0;
1686 NTSTATUS status;
1687 TALLOC_CTX *ctx = talloc_tos();
1689 START_PROFILE(SMBopen);
1691 if (req->wct < 2) {
1692 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1693 END_PROFILE(SMBopen);
1694 return;
1697 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1698 deny_mode = SVAL(req->inbuf,smb_vwv0);
1699 dos_attr = SVAL(req->inbuf,smb_vwv1);
1701 srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname,
1702 smb_buf(req->inbuf)+1, 0,
1703 STR_TERMINATE, &status);
1704 if (!NT_STATUS_IS_OK(status)) {
1705 reply_nterror(req, status);
1706 END_PROFILE(SMBopen);
1707 return;
1710 if (!map_open_params_to_ntcreate(
1711 fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
1712 &share_mode, &create_disposition, &create_options)) {
1713 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1714 END_PROFILE(SMBopen);
1715 return;
1718 status = create_file(conn, /* conn */
1719 req, /* req */
1720 0, /* root_dir_fid */
1721 fname, /* fname */
1722 access_mask, /* access_mask */
1723 share_mode, /* share_access */
1724 create_disposition, /* create_disposition*/
1725 create_options, /* create_options */
1726 dos_attr, /* file_attributes */
1727 oplock_request, /* oplock_request */
1728 0, /* allocation_size */
1729 NULL, /* sd */
1730 NULL, /* ea_list */
1731 &fsp, /* result */
1732 &info, /* pinfo */
1733 &sbuf); /* psbuf */
1735 if (!NT_STATUS_IS_OK(status)) {
1736 if (open_was_deferred(req->mid)) {
1737 /* We have re-scheduled this call. */
1738 END_PROFILE(SMBopen);
1739 return;
1741 reply_openerror(req, status);
1742 END_PROFILE(SMBopen);
1743 return;
1746 size = sbuf.st_size;
1747 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1748 mtime = sbuf.st_mtime;
1750 if (fattr & aDIR) {
1751 DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
1752 close_file(fsp,ERROR_CLOSE);
1753 reply_doserror(req, ERRDOS,ERRnoaccess);
1754 END_PROFILE(SMBopen);
1755 return;
1758 reply_outbuf(req, 7, 0);
1759 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1760 SSVAL(req->outbuf,smb_vwv1,fattr);
1761 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1762 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1763 } else {
1764 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1766 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1767 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1769 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1770 SCVAL(req->outbuf,smb_flg,
1771 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1774 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1775 SCVAL(req->outbuf,smb_flg,
1776 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1778 END_PROFILE(SMBopen);
1779 return;
1782 /****************************************************************************
1783 Reply to an open and X.
1784 ****************************************************************************/
1786 void reply_open_and_X(struct smb_request *req)
1788 connection_struct *conn = req->conn;
1789 char *fname = NULL;
1790 uint16 open_flags;
1791 int deny_mode;
1792 uint32 smb_attr;
1793 /* Breakout the oplock request bits so we can set the
1794 reply bits separately. */
1795 int ex_oplock_request;
1796 int core_oplock_request;
1797 int oplock_request;
1798 #if 0
1799 int smb_sattr = SVAL(req->inbuf,smb_vwv4);
1800 uint32 smb_time = make_unix_date3(req->inbuf+smb_vwv6);
1801 #endif
1802 int smb_ofun;
1803 uint32 fattr=0;
1804 int mtime=0;
1805 SMB_STRUCT_STAT sbuf;
1806 int smb_action = 0;
1807 files_struct *fsp;
1808 NTSTATUS status;
1809 SMB_BIG_UINT allocation_size;
1810 ssize_t retval = -1;
1811 uint32 access_mask;
1812 uint32 share_mode;
1813 uint32 create_disposition;
1814 uint32 create_options = 0;
1815 TALLOC_CTX *ctx = talloc_tos();
1817 START_PROFILE(SMBopenX);
1819 if (req->wct < 15) {
1820 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1821 END_PROFILE(SMBopenX);
1822 return;
1825 open_flags = SVAL(req->inbuf,smb_vwv2);
1826 deny_mode = SVAL(req->inbuf,smb_vwv3);
1827 smb_attr = SVAL(req->inbuf,smb_vwv5);
1828 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1829 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1830 oplock_request = ex_oplock_request | core_oplock_request;
1831 smb_ofun = SVAL(req->inbuf,smb_vwv8);
1832 allocation_size = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv9);
1834 /* If it's an IPC, pass off the pipe handler. */
1835 if (IS_IPC(conn)) {
1836 if (lp_nt_pipe_support()) {
1837 reply_open_pipe_and_X(conn, req);
1838 } else {
1839 reply_doserror(req, ERRSRV, ERRaccess);
1841 END_PROFILE(SMBopenX);
1842 return;
1845 /* XXXX we need to handle passed times, sattr and flags */
1846 srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname,
1847 smb_buf(req->inbuf), 0, STR_TERMINATE,
1848 &status);
1849 if (!NT_STATUS_IS_OK(status)) {
1850 reply_nterror(req, status);
1851 END_PROFILE(SMBopenX);
1852 return;
1855 if (!map_open_params_to_ntcreate(
1856 fname, deny_mode, smb_ofun, &access_mask,
1857 &share_mode, &create_disposition, &create_options)) {
1858 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1859 END_PROFILE(SMBopenX);
1860 return;
1863 status = create_file(conn, /* conn */
1864 req, /* req */
1865 0, /* root_dir_fid */
1866 fname, /* fname */
1867 access_mask, /* access_mask */
1868 share_mode, /* share_access */
1869 create_disposition, /* create_disposition*/
1870 create_options, /* create_options */
1871 smb_attr, /* file_attributes */
1872 oplock_request, /* oplock_request */
1873 0, /* allocation_size */
1874 NULL, /* sd */
1875 NULL, /* ea_list */
1876 &fsp, /* result */
1877 &smb_action, /* pinfo */
1878 &sbuf); /* psbuf */
1880 if (!NT_STATUS_IS_OK(status)) {
1881 END_PROFILE(SMBopenX);
1882 if (open_was_deferred(req->mid)) {
1883 /* We have re-scheduled this call. */
1884 return;
1886 reply_openerror(req, status);
1887 return;
1890 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1891 if the file is truncated or created. */
1892 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1893 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1894 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1895 close_file(fsp,ERROR_CLOSE);
1896 reply_nterror(req, NT_STATUS_DISK_FULL);
1897 END_PROFILE(SMBopenX);
1898 return;
1900 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1901 if (retval < 0) {
1902 close_file(fsp,ERROR_CLOSE);
1903 reply_nterror(req, NT_STATUS_DISK_FULL);
1904 END_PROFILE(SMBopenX);
1905 return;
1907 sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
1910 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1911 mtime = sbuf.st_mtime;
1912 if (fattr & aDIR) {
1913 close_file(fsp,ERROR_CLOSE);
1914 reply_doserror(req, ERRDOS, ERRnoaccess);
1915 END_PROFILE(SMBopenX);
1916 return;
1919 /* If the caller set the extended oplock request bit
1920 and we granted one (by whatever means) - set the
1921 correct bit for extended oplock reply.
1924 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1925 smb_action |= EXTENDED_OPLOCK_GRANTED;
1928 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1929 smb_action |= EXTENDED_OPLOCK_GRANTED;
1932 /* If the caller set the core oplock request bit
1933 and we granted one (by whatever means) - set the
1934 correct bit for core oplock reply.
1937 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1938 reply_outbuf(req, 19, 0);
1939 } else {
1940 reply_outbuf(req, 15, 0);
1943 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1944 SCVAL(req->outbuf, smb_flg,
1945 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1948 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1949 SCVAL(req->outbuf, smb_flg,
1950 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1953 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1954 SSVAL(req->outbuf,smb_vwv3,fattr);
1955 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1956 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1957 } else {
1958 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
1960 SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_size);
1961 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1962 SSVAL(req->outbuf,smb_vwv11,smb_action);
1964 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1965 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1968 END_PROFILE(SMBopenX);
1969 chain_reply(req);
1970 return;
1973 /****************************************************************************
1974 Reply to a SMBulogoffX.
1975 ****************************************************************************/
1977 void reply_ulogoffX(struct smb_request *req)
1979 user_struct *vuser;
1981 START_PROFILE(SMBulogoffX);
1983 vuser = get_valid_user_struct(req->vuid);
1985 if(vuser == NULL) {
1986 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
1987 req->vuid));
1990 /* in user level security we are supposed to close any files
1991 open by this user */
1992 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
1993 file_close_user(req->vuid);
1996 invalidate_vuid(req->vuid);
1998 reply_outbuf(req, 2, 0);
2000 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2002 END_PROFILE(SMBulogoffX);
2003 chain_reply(req);
2006 /****************************************************************************
2007 Reply to a mknew or a create.
2008 ****************************************************************************/
2010 void reply_mknew(struct smb_request *req)
2012 connection_struct *conn = req->conn;
2013 char *fname = NULL;
2014 int com;
2015 uint32 fattr = 0;
2016 struct timespec ts[2];
2017 files_struct *fsp;
2018 int oplock_request = 0;
2019 SMB_STRUCT_STAT sbuf;
2020 NTSTATUS status;
2021 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2022 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2023 uint32 create_disposition;
2024 uint32 create_options = 0;
2025 TALLOC_CTX *ctx = talloc_tos();
2027 START_PROFILE(SMBcreate);
2029 if (req->wct < 3) {
2030 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2031 END_PROFILE(SMBcreate);
2032 return;
2035 fattr = SVAL(req->inbuf,smb_vwv0);
2036 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2037 com = SVAL(req->inbuf,smb_com);
2039 ts[1] =convert_time_t_to_timespec(
2040 srv_make_unix_date3(req->inbuf + smb_vwv1));
2041 /* mtime. */
2043 srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname,
2044 smb_buf(req->inbuf) + 1, 0,
2045 STR_TERMINATE, &status);
2046 if (!NT_STATUS_IS_OK(status)) {
2047 reply_nterror(req, status);
2048 END_PROFILE(SMBcreate);
2049 return;
2052 if (fattr & aVOLID) {
2053 DEBUG(0,("Attempt to create file (%s) with volid set - "
2054 "please report this\n", fname));
2057 if(com == SMBmknew) {
2058 /* We should fail if file exists. */
2059 create_disposition = FILE_CREATE;
2060 } else {
2061 /* Create if file doesn't exist, truncate if it does. */
2062 create_disposition = FILE_OVERWRITE_IF;
2065 status = create_file(conn, /* conn */
2066 req, /* req */
2067 0, /* root_dir_fid */
2068 fname, /* fname */
2069 access_mask, /* access_mask */
2070 share_mode, /* share_access */
2071 create_disposition, /* create_disposition*/
2072 create_options, /* create_options */
2073 fattr, /* file_attributes */
2074 oplock_request, /* oplock_request */
2075 0, /* allocation_size */
2076 NULL, /* sd */
2077 NULL, /* ea_list */
2078 &fsp, /* result */
2079 NULL, /* pinfo */
2080 &sbuf); /* psbuf */
2082 if (!NT_STATUS_IS_OK(status)) {
2083 END_PROFILE(SMBcreate);
2084 if (open_was_deferred(req->mid)) {
2085 /* We have re-scheduled this call. */
2086 return;
2088 reply_openerror(req, status);
2089 return;
2092 ts[0] = get_atimespec(&sbuf); /* atime. */
2093 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &sbuf, ts, true);
2094 if (!NT_STATUS_IS_OK(status)) {
2095 END_PROFILE(SMBcreate);
2096 reply_openerror(req, status);
2097 return;
2100 reply_outbuf(req, 1, 0);
2101 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2103 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2104 SCVAL(req->outbuf,smb_flg,
2105 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2108 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2109 SCVAL(req->outbuf,smb_flg,
2110 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2113 DEBUG( 2, ( "reply_mknew: file %s\n", fsp->fsp_name ) );
2114 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2115 fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) );
2117 END_PROFILE(SMBcreate);
2118 return;
2121 /****************************************************************************
2122 Reply to a create temporary file.
2123 ****************************************************************************/
2125 void reply_ctemp(struct smb_request *req)
2127 connection_struct *conn = req->conn;
2128 char *fname = NULL;
2129 uint32 fattr;
2130 files_struct *fsp;
2131 int oplock_request;
2132 int tmpfd;
2133 SMB_STRUCT_STAT sbuf;
2134 char *s;
2135 NTSTATUS status;
2136 TALLOC_CTX *ctx = talloc_tos();
2138 START_PROFILE(SMBctemp);
2140 if (req->wct < 3) {
2141 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2142 END_PROFILE(SMBctemp);
2143 return;
2146 fattr = SVAL(req->inbuf,smb_vwv0);
2147 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2149 srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname,
2150 smb_buf(req->inbuf)+1, 0, STR_TERMINATE,
2151 &status);
2152 if (!NT_STATUS_IS_OK(status)) {
2153 reply_nterror(req, status);
2154 END_PROFILE(SMBctemp);
2155 return;
2157 if (*fname) {
2158 fname = talloc_asprintf(ctx,
2159 "%s/TMXXXXXX",
2160 fname);
2161 } else {
2162 fname = talloc_strdup(ctx, "TMXXXXXX");
2165 if (!fname) {
2166 reply_nterror(req, NT_STATUS_NO_MEMORY);
2167 END_PROFILE(SMBctemp);
2168 return;
2171 status = resolve_dfspath(ctx, conn,
2172 req->flags2 & FLAGS2_DFS_PATHNAMES,
2173 fname,
2174 &fname);
2175 if (!NT_STATUS_IS_OK(status)) {
2176 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2177 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2178 ERRSRV, ERRbadpath);
2179 END_PROFILE(SMBctemp);
2180 return;
2182 reply_nterror(req, status);
2183 END_PROFILE(SMBctemp);
2184 return;
2187 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
2188 if (!NT_STATUS_IS_OK(status)) {
2189 reply_nterror(req, status);
2190 END_PROFILE(SMBctemp);
2191 return;
2194 status = check_name(conn, fname);
2195 if (!NT_STATUS_IS_OK(status)) {
2196 reply_nterror(req, status);
2197 END_PROFILE(SMBctemp);
2198 return;
2201 tmpfd = smb_mkstemp(fname);
2202 if (tmpfd == -1) {
2203 reply_unixerror(req, ERRDOS, ERRnoaccess);
2204 END_PROFILE(SMBctemp);
2205 return;
2208 SMB_VFS_STAT(conn,fname,&sbuf);
2210 /* We should fail if file does not exist. */
2211 status = open_file_ntcreate(conn, req, fname, &sbuf,
2212 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
2213 FILE_SHARE_READ|FILE_SHARE_WRITE,
2214 FILE_OPEN,
2216 fattr,
2217 oplock_request,
2218 NULL, &fsp);
2220 /* close fd from smb_mkstemp() */
2221 close(tmpfd);
2223 if (!NT_STATUS_IS_OK(status)) {
2224 if (open_was_deferred(req->mid)) {
2225 /* We have re-scheduled this call. */
2226 END_PROFILE(SMBctemp);
2227 return;
2229 reply_openerror(req, status);
2230 END_PROFILE(SMBctemp);
2231 return;
2234 reply_outbuf(req, 1, 0);
2235 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2237 /* the returned filename is relative to the directory */
2238 s = strrchr_m(fsp->fsp_name, '/');
2239 if (!s) {
2240 s = fsp->fsp_name;
2241 } else {
2242 s++;
2245 #if 0
2246 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2247 thing in the byte section. JRA */
2248 SSVALS(p, 0, -1); /* what is this? not in spec */
2249 #endif
2250 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2251 == -1) {
2252 reply_nterror(req, NT_STATUS_NO_MEMORY);
2253 END_PROFILE(SMBctemp);
2254 return;
2257 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2258 SCVAL(req->outbuf, smb_flg,
2259 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2262 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2263 SCVAL(req->outbuf, smb_flg,
2264 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2267 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
2268 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
2269 fsp->fh->fd, (unsigned int)sbuf.st_mode ) );
2271 END_PROFILE(SMBctemp);
2272 return;
2275 /*******************************************************************
2276 Check if a user is allowed to rename a file.
2277 ********************************************************************/
2279 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2280 uint16 dirtype, SMB_STRUCT_STAT *pst)
2282 uint32 fmode;
2284 if (!CAN_WRITE(conn)) {
2285 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2288 fmode = dos_mode(conn, fsp->fsp_name, pst);
2289 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2290 return NT_STATUS_NO_SUCH_FILE;
2293 if (S_ISDIR(pst->st_mode)) {
2294 if (fsp->posix_open) {
2295 return NT_STATUS_OK;
2298 /* If no pathnames are open below this
2299 directory, allow the rename. */
2301 if (file_find_subpath(fsp)) {
2302 return NT_STATUS_ACCESS_DENIED;
2304 return NT_STATUS_OK;
2307 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2308 return NT_STATUS_OK;
2311 return NT_STATUS_ACCESS_DENIED;
2314 /*******************************************************************
2315 * unlink a file with all relevant access checks
2316 *******************************************************************/
2318 static NTSTATUS do_unlink(connection_struct *conn,
2319 struct smb_request *req,
2320 const char *fname,
2321 uint32 dirtype)
2323 SMB_STRUCT_STAT sbuf;
2324 uint32 fattr;
2325 files_struct *fsp;
2326 uint32 dirtype_orig = dirtype;
2327 bool posix_paths = lp_posix_pathnames();
2328 int ret;
2329 NTSTATUS status;
2331 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2333 if (!CAN_WRITE(conn)) {
2334 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2337 if (posix_paths) {
2338 ret = SMB_VFS_LSTAT(conn,fname,&sbuf);
2339 } else {
2340 ret = SMB_VFS_STAT(conn,fname,&sbuf);
2342 if (ret != 0) {
2343 return map_nt_error_from_unix(errno);
2346 fattr = dos_mode(conn,fname,&sbuf);
2348 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2349 dirtype = aDIR|aARCH|aRONLY;
2352 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2353 if (!dirtype) {
2354 return NT_STATUS_NO_SUCH_FILE;
2357 if (!dir_check_ftype(conn, fattr, dirtype)) {
2358 if (fattr & aDIR) {
2359 return NT_STATUS_FILE_IS_A_DIRECTORY;
2361 return NT_STATUS_NO_SUCH_FILE;
2364 if (dirtype_orig & 0x8000) {
2365 /* These will never be set for POSIX. */
2366 return NT_STATUS_NO_SUCH_FILE;
2369 #if 0
2370 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2371 return NT_STATUS_FILE_IS_A_DIRECTORY;
2374 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2375 return NT_STATUS_NO_SUCH_FILE;
2378 if (dirtype & 0xFF00) {
2379 /* These will never be set for POSIX. */
2380 return NT_STATUS_NO_SUCH_FILE;
2383 dirtype &= 0xFF;
2384 if (!dirtype) {
2385 return NT_STATUS_NO_SUCH_FILE;
2388 /* Can't delete a directory. */
2389 if (fattr & aDIR) {
2390 return NT_STATUS_FILE_IS_A_DIRECTORY;
2392 #endif
2394 #if 0 /* JRATEST */
2395 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2396 return NT_STATUS_OBJECT_NAME_INVALID;
2397 #endif /* JRATEST */
2399 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2401 On a Windows share, a file with read-only dosmode can be opened with
2402 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2403 fails with NT_STATUS_CANNOT_DELETE error.
2405 This semantic causes a problem that a user can not
2406 rename a file with read-only dosmode on a Samba share
2407 from a Windows command prompt (i.e. cmd.exe, but can rename
2408 from Windows Explorer).
2411 if (!lp_delete_readonly(SNUM(conn))) {
2412 if (fattr & aRONLY) {
2413 return NT_STATUS_CANNOT_DELETE;
2417 /* On open checks the open itself will check the share mode, so
2418 don't do it here as we'll get it wrong. */
2420 status = create_file_unixpath
2421 (conn, /* conn */
2422 req, /* req */
2423 fname, /* fname */
2424 DELETE_ACCESS, /* access_mask */
2425 FILE_SHARE_NONE, /* share_access */
2426 FILE_OPEN, /* create_disposition*/
2427 FILE_NON_DIRECTORY_FILE, /* create_options */
2428 /* file_attributes */
2429 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2430 FILE_ATTRIBUTE_NORMAL,
2431 0, /* oplock_request */
2432 0, /* allocation_size */
2433 NULL, /* sd */
2434 NULL, /* ea_list */
2435 &fsp, /* result */
2436 NULL, /* pinfo */
2437 &sbuf); /* psbuf */
2439 if (!NT_STATUS_IS_OK(status)) {
2440 DEBUG(10, ("create_file_unixpath failed: %s\n",
2441 nt_errstr(status)));
2442 return status;
2445 /* The set is across all open files on this dev/inode pair. */
2446 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2447 close_file(fsp, NORMAL_CLOSE);
2448 return NT_STATUS_ACCESS_DENIED;
2451 return close_file(fsp,NORMAL_CLOSE);
2454 /****************************************************************************
2455 The guts of the unlink command, split out so it may be called by the NT SMB
2456 code.
2457 ****************************************************************************/
2459 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2460 uint32 dirtype, const char *name_in, bool has_wild)
2462 const char *directory = NULL;
2463 char *mask = NULL;
2464 char *name = NULL;
2465 char *p = NULL;
2466 int count=0;
2467 NTSTATUS status = NT_STATUS_OK;
2468 SMB_STRUCT_STAT sbuf;
2469 TALLOC_CTX *ctx = talloc_tos();
2471 status = unix_convert(ctx, conn, name_in, has_wild, &name, NULL, &sbuf);
2472 if (!NT_STATUS_IS_OK(status)) {
2473 return status;
2476 p = strrchr_m(name,'/');
2477 if (!p) {
2478 directory = talloc_strdup(ctx, ".");
2479 if (!directory) {
2480 return NT_STATUS_NO_MEMORY;
2482 mask = name;
2483 } else {
2484 *p = 0;
2485 directory = name;
2486 mask = p+1;
2490 * We should only check the mangled cache
2491 * here if unix_convert failed. This means
2492 * that the path in 'mask' doesn't exist
2493 * on the file system and so we need to look
2494 * for a possible mangle. This patch from
2495 * Tine Smukavec <valentin.smukavec@hermes.si>.
2498 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params)) {
2499 char *new_mask = NULL;
2500 mangle_lookup_name_from_8_3(ctx,
2501 mask,
2502 &new_mask,
2503 conn->params );
2504 if (new_mask) {
2505 mask = new_mask;
2509 if (!has_wild) {
2510 directory = talloc_asprintf(ctx,
2511 "%s/%s",
2512 directory,
2513 mask);
2514 if (!directory) {
2515 return NT_STATUS_NO_MEMORY;
2517 if (dirtype == 0) {
2518 dirtype = FILE_ATTRIBUTE_NORMAL;
2521 status = check_name(conn, directory);
2522 if (!NT_STATUS_IS_OK(status)) {
2523 return status;
2526 status = do_unlink(conn, req, directory, dirtype);
2527 if (!NT_STATUS_IS_OK(status)) {
2528 return status;
2531 count++;
2532 } else {
2533 struct smb_Dir *dir_hnd = NULL;
2534 long offset = 0;
2535 const char *dname;
2537 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2538 return NT_STATUS_OBJECT_NAME_INVALID;
2541 if (strequal(mask,"????????.???")) {
2542 mask[0] = '*';
2543 mask[1] = '\0';
2546 status = check_name(conn, directory);
2547 if (!NT_STATUS_IS_OK(status)) {
2548 return status;
2551 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask,
2552 dirtype);
2553 if (dir_hnd == NULL) {
2554 return map_nt_error_from_unix(errno);
2557 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2558 the pattern matches against the long name, otherwise the short name
2559 We don't implement this yet XXXX
2562 status = NT_STATUS_NO_SUCH_FILE;
2564 while ((dname = ReadDirName(dir_hnd, &offset))) {
2565 SMB_STRUCT_STAT st;
2566 char *fname = NULL;
2568 if (!is_visible_file(conn, directory, dname, &st, True)) {
2569 continue;
2572 /* Quick check for "." and ".." */
2573 if (ISDOT(dname) || ISDOTDOT(dname)) {
2574 continue;
2577 if(!mask_match(dname, mask, conn->case_sensitive)) {
2578 continue;
2581 fname = talloc_asprintf(ctx, "%s/%s",
2582 directory,
2583 dname);
2584 if (!fname) {
2585 return NT_STATUS_NO_MEMORY;
2588 status = check_name(conn, fname);
2589 if (!NT_STATUS_IS_OK(status)) {
2590 TALLOC_FREE(dir_hnd);
2591 return status;
2594 status = do_unlink(conn, req, fname, dirtype);
2595 if (!NT_STATUS_IS_OK(status)) {
2596 TALLOC_FREE(fname);
2597 continue;
2600 count++;
2601 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2602 fname));
2604 TALLOC_FREE(fname);
2606 TALLOC_FREE(dir_hnd);
2609 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2610 status = map_nt_error_from_unix(errno);
2613 return status;
2616 /****************************************************************************
2617 Reply to a unlink
2618 ****************************************************************************/
2620 void reply_unlink(struct smb_request *req)
2622 connection_struct *conn = req->conn;
2623 char *name = NULL;
2624 uint32 dirtype;
2625 NTSTATUS status;
2626 bool path_contains_wcard = False;
2627 TALLOC_CTX *ctx = talloc_tos();
2629 START_PROFILE(SMBunlink);
2631 if (req->wct < 1) {
2632 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2633 END_PROFILE(SMBunlink);
2634 return;
2637 dirtype = SVAL(req->inbuf,smb_vwv0);
2639 srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name,
2640 smb_buf(req->inbuf) + 1, 0,
2641 STR_TERMINATE, &status, &path_contains_wcard);
2642 if (!NT_STATUS_IS_OK(status)) {
2643 reply_nterror(req, status);
2644 END_PROFILE(SMBunlink);
2645 return;
2648 status = resolve_dfspath_wcard(ctx, conn,
2649 req->flags2 & FLAGS2_DFS_PATHNAMES,
2650 name,
2651 &name,
2652 &path_contains_wcard);
2653 if (!NT_STATUS_IS_OK(status)) {
2654 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2655 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2656 ERRSRV, ERRbadpath);
2657 END_PROFILE(SMBunlink);
2658 return;
2660 reply_nterror(req, status);
2661 END_PROFILE(SMBunlink);
2662 return;
2665 DEBUG(3,("reply_unlink : %s\n",name));
2667 status = unlink_internals(conn, req, dirtype, name,
2668 path_contains_wcard);
2669 if (!NT_STATUS_IS_OK(status)) {
2670 if (open_was_deferred(req->mid)) {
2671 /* We have re-scheduled this call. */
2672 END_PROFILE(SMBunlink);
2673 return;
2675 reply_nterror(req, status);
2676 END_PROFILE(SMBunlink);
2677 return;
2680 reply_outbuf(req, 0, 0);
2681 END_PROFILE(SMBunlink);
2683 return;
2686 /****************************************************************************
2687 Fail for readbraw.
2688 ****************************************************************************/
2690 static void fail_readraw(void)
2692 const char *errstr = talloc_asprintf(talloc_tos(),
2693 "FAIL ! reply_readbraw: socket write fail (%s)",
2694 strerror(errno));
2695 if (!errstr) {
2696 errstr = "";
2698 exit_server_cleanly(errstr);
2701 /****************************************************************************
2702 Fake (read/write) sendfile. Returns -1 on read or write fail.
2703 ****************************************************************************/
2705 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2706 size_t nread)
2708 size_t bufsize;
2709 size_t tosend = nread;
2710 char *buf;
2712 if (nread == 0) {
2713 return 0;
2716 bufsize = MIN(nread, 65536);
2718 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2719 return -1;
2722 while (tosend > 0) {
2723 ssize_t ret;
2724 size_t cur_read;
2726 if (tosend > bufsize) {
2727 cur_read = bufsize;
2728 } else {
2729 cur_read = tosend;
2731 ret = read_file(fsp,buf,startpos,cur_read);
2732 if (ret == -1) {
2733 SAFE_FREE(buf);
2734 return -1;
2737 /* If we had a short read, fill with zeros. */
2738 if (ret < cur_read) {
2739 memset(buf, '\0', cur_read - ret);
2742 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2743 SAFE_FREE(buf);
2744 return -1;
2746 tosend -= cur_read;
2747 startpos += cur_read;
2750 SAFE_FREE(buf);
2751 return (ssize_t)nread;
2754 /****************************************************************************
2755 Return a readbraw error (4 bytes of zero).
2756 ****************************************************************************/
2758 static void reply_readbraw_error(void)
2760 char header[4];
2761 SIVAL(header,0,0);
2762 if (write_data(smbd_server_fd(),header,4) != 4) {
2763 fail_readraw();
2767 /****************************************************************************
2768 Use sendfile in readbraw.
2769 ****************************************************************************/
2771 void send_file_readbraw(connection_struct *conn,
2772 files_struct *fsp,
2773 SMB_OFF_T startpos,
2774 size_t nread,
2775 ssize_t mincount)
2777 char *outbuf = NULL;
2778 ssize_t ret=0;
2780 #if defined(WITH_SENDFILE)
2782 * We can only use sendfile on a non-chained packet
2783 * but we can use on a non-oplocked file. tridge proved this
2784 * on a train in Germany :-). JRA.
2785 * reply_readbraw has already checked the length.
2788 if ( (chain_size == 0) && (nread > 0) && (fsp->base_fsp == NULL) &&
2789 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2790 char header[4];
2791 DATA_BLOB header_blob;
2793 _smb_setlen(header,nread);
2794 header_blob = data_blob_const(header, 4);
2796 if (SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2797 &header_blob, startpos, nread) == -1) {
2798 /* Returning ENOSYS means no data at all was sent.
2799 * Do this as a normal read. */
2800 if (errno == ENOSYS) {
2801 goto normal_readbraw;
2805 * Special hack for broken Linux with no working sendfile. If we
2806 * return EINTR we sent the header but not the rest of the data.
2807 * Fake this up by doing read/write calls.
2809 if (errno == EINTR) {
2810 /* Ensure we don't do this again. */
2811 set_use_sendfile(SNUM(conn), False);
2812 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2814 if (fake_sendfile(fsp, startpos, nread) == -1) {
2815 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2816 fsp->fsp_name, strerror(errno) ));
2817 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2819 return;
2822 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2823 fsp->fsp_name, strerror(errno) ));
2824 exit_server_cleanly("send_file_readbraw sendfile failed");
2827 return;
2830 normal_readbraw:
2831 #endif
2833 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2834 if (!outbuf) {
2835 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2836 (unsigned)(nread+4)));
2837 reply_readbraw_error();
2838 return;
2841 if (nread > 0) {
2842 ret = read_file(fsp,outbuf+4,startpos,nread);
2843 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2844 if (ret < mincount)
2845 ret = 0;
2846 #else
2847 if (ret < nread)
2848 ret = 0;
2849 #endif
2852 _smb_setlen(outbuf,ret);
2853 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2854 fail_readraw();
2856 TALLOC_FREE(outbuf);
2859 /****************************************************************************
2860 Reply to a readbraw (core+ protocol).
2861 ****************************************************************************/
2863 void reply_readbraw(struct smb_request *req)
2865 connection_struct *conn = req->conn;
2866 ssize_t maxcount,mincount;
2867 size_t nread = 0;
2868 SMB_OFF_T startpos;
2869 files_struct *fsp;
2870 SMB_STRUCT_STAT st;
2871 SMB_OFF_T size = 0;
2873 START_PROFILE(SMBreadbraw);
2875 if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
2876 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
2877 "raw reads/writes are disallowed.");
2880 if (req->wct < 8) {
2881 reply_readbraw_error();
2882 END_PROFILE(SMBreadbraw);
2883 return;
2887 * Special check if an oplock break has been issued
2888 * and the readraw request croses on the wire, we must
2889 * return a zero length response here.
2892 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
2895 * We have to do a check_fsp by hand here, as
2896 * we must always return 4 zero bytes on error,
2897 * not a NTSTATUS.
2900 if (!fsp || !conn || conn != fsp->conn ||
2901 req->vuid != fsp->vuid ||
2902 fsp->is_directory || fsp->fh->fd == -1) {
2904 * fsp could be NULL here so use the value from the packet. JRA.
2906 DEBUG(3,("reply_readbraw: fnum %d not valid "
2907 "- cache prime?\n",
2908 (int)SVAL(req->inbuf,smb_vwv0)));
2909 reply_readbraw_error();
2910 END_PROFILE(SMBreadbraw);
2911 return;
2914 /* Do a "by hand" version of CHECK_READ. */
2915 if (!(fsp->can_read ||
2916 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
2917 (fsp->access_mask & FILE_EXECUTE)))) {
2918 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
2919 (int)SVAL(req->inbuf,smb_vwv0)));
2920 reply_readbraw_error();
2921 END_PROFILE(SMBreadbraw);
2922 return;
2925 flush_write_cache(fsp, READRAW_FLUSH);
2927 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv1);
2928 if(req->wct == 10) {
2930 * This is a large offset (64 bit) read.
2932 #ifdef LARGE_SMB_OFF_T
2934 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv8)) << 32);
2936 #else /* !LARGE_SMB_OFF_T */
2939 * Ensure we haven't been sent a >32 bit offset.
2942 if(IVAL(req->inbuf,smb_vwv8) != 0) {
2943 DEBUG(0,("reply_readbraw: large offset "
2944 "(%x << 32) used and we don't support "
2945 "64 bit offsets.\n",
2946 (unsigned int)IVAL(req->inbuf,smb_vwv8) ));
2947 reply_readbraw_error();
2948 END_PROFILE(SMBreadbraw);
2949 return;
2952 #endif /* LARGE_SMB_OFF_T */
2954 if(startpos < 0) {
2955 DEBUG(0,("reply_readbraw: negative 64 bit "
2956 "readraw offset (%.0f) !\n",
2957 (double)startpos ));
2958 reply_readbraw_error();
2959 END_PROFILE(SMBreadbraw);
2960 return;
2964 maxcount = (SVAL(req->inbuf,smb_vwv3) & 0xFFFF);
2965 mincount = (SVAL(req->inbuf,smb_vwv4) & 0xFFFF);
2967 /* ensure we don't overrun the packet size */
2968 maxcount = MIN(65535,maxcount);
2970 if (is_locked(fsp,(uint32)req->smbpid,
2971 (SMB_BIG_UINT)maxcount,
2972 (SMB_BIG_UINT)startpos,
2973 READ_LOCK)) {
2974 reply_readbraw_error();
2975 END_PROFILE(SMBreadbraw);
2976 return;
2979 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
2980 size = st.st_size;
2983 if (startpos >= size) {
2984 nread = 0;
2985 } else {
2986 nread = MIN(maxcount,(size - startpos));
2989 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2990 if (nread < mincount)
2991 nread = 0;
2992 #endif
2994 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
2995 "min=%lu nread=%lu\n",
2996 fsp->fnum, (double)startpos,
2997 (unsigned long)maxcount,
2998 (unsigned long)mincount,
2999 (unsigned long)nread ) );
3001 send_file_readbraw(conn, fsp, startpos, nread, mincount);
3003 DEBUG(5,("reply_readbraw finished\n"));
3004 END_PROFILE(SMBreadbraw);
3007 #undef DBGC_CLASS
3008 #define DBGC_CLASS DBGC_LOCKING
3010 /****************************************************************************
3011 Reply to a lockread (core+ protocol).
3012 ****************************************************************************/
3014 void reply_lockread(struct smb_request *req)
3016 connection_struct *conn = req->conn;
3017 ssize_t nread = -1;
3018 char *data;
3019 SMB_OFF_T startpos;
3020 size_t numtoread;
3021 NTSTATUS status;
3022 files_struct *fsp;
3023 struct byte_range_lock *br_lck = NULL;
3024 char *p = NULL;
3026 START_PROFILE(SMBlockread);
3028 if (req->wct < 5) {
3029 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3030 END_PROFILE(SMBlockread);
3031 return;
3034 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3036 if (!check_fsp(conn, req, fsp)) {
3037 END_PROFILE(SMBlockread);
3038 return;
3041 if (!CHECK_READ(fsp,req->inbuf)) {
3042 reply_doserror(req, ERRDOS, ERRbadaccess);
3043 END_PROFILE(SMBlockread);
3044 return;
3047 release_level_2_oplocks_on_change(fsp);
3049 numtoread = SVAL(req->inbuf,smb_vwv1);
3050 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
3052 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3054 reply_outbuf(req, 5, numtoread + 3);
3056 data = smb_buf(req->outbuf) + 3;
3059 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3060 * protocol request that predates the read/write lock concept.
3061 * Thus instead of asking for a read lock here we need to ask
3062 * for a write lock. JRA.
3063 * Note that the requested lock size is unaffected by max_recv.
3066 br_lck = do_lock(smbd_messaging_context(),
3067 fsp,
3068 req->smbpid,
3069 (SMB_BIG_UINT)numtoread,
3070 (SMB_BIG_UINT)startpos,
3071 WRITE_LOCK,
3072 WINDOWS_LOCK,
3073 False, /* Non-blocking lock. */
3074 &status,
3075 NULL);
3076 TALLOC_FREE(br_lck);
3078 if (NT_STATUS_V(status)) {
3079 reply_nterror(req, status);
3080 END_PROFILE(SMBlockread);
3081 return;
3085 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3088 if (numtoread > max_recv) {
3089 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3090 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3091 (unsigned int)numtoread, (unsigned int)max_recv ));
3092 numtoread = MIN(numtoread,max_recv);
3094 nread = read_file(fsp,data,startpos,numtoread);
3096 if (nread < 0) {
3097 reply_unixerror(req, ERRDOS, ERRnoaccess);
3098 END_PROFILE(SMBlockread);
3099 return;
3102 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3104 SSVAL(req->outbuf,smb_vwv0,nread);
3105 SSVAL(req->outbuf,smb_vwv5,nread+3);
3106 p = smb_buf(req->outbuf);
3107 SCVAL(p,0,0); /* pad byte. */
3108 SSVAL(p,1,nread);
3110 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3111 fsp->fnum, (int)numtoread, (int)nread));
3113 END_PROFILE(SMBlockread);
3114 return;
3117 #undef DBGC_CLASS
3118 #define DBGC_CLASS DBGC_ALL
3120 /****************************************************************************
3121 Reply to a read.
3122 ****************************************************************************/
3124 void reply_read(struct smb_request *req)
3126 connection_struct *conn = req->conn;
3127 size_t numtoread;
3128 ssize_t nread = 0;
3129 char *data;
3130 SMB_OFF_T startpos;
3131 int outsize = 0;
3132 files_struct *fsp;
3134 START_PROFILE(SMBread);
3136 if (req->wct < 3) {
3137 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3138 END_PROFILE(SMBread);
3139 return;
3142 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3144 if (!check_fsp(conn, req, fsp)) {
3145 END_PROFILE(SMBread);
3146 return;
3149 if (!CHECK_READ(fsp,req->inbuf)) {
3150 reply_doserror(req, ERRDOS, ERRbadaccess);
3151 END_PROFILE(SMBread);
3152 return;
3155 numtoread = SVAL(req->inbuf,smb_vwv1);
3156 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
3158 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3161 * The requested read size cannot be greater than max_recv. JRA.
3163 if (numtoread > max_recv) {
3164 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3165 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3166 (unsigned int)numtoread, (unsigned int)max_recv ));
3167 numtoread = MIN(numtoread,max_recv);
3170 reply_outbuf(req, 5, numtoread+3);
3172 data = smb_buf(req->outbuf) + 3;
3174 if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtoread,
3175 (SMB_BIG_UINT)startpos, READ_LOCK)) {
3176 reply_doserror(req, ERRDOS,ERRlock);
3177 END_PROFILE(SMBread);
3178 return;
3181 if (numtoread > 0)
3182 nread = read_file(fsp,data,startpos,numtoread);
3184 if (nread < 0) {
3185 reply_unixerror(req, ERRDOS,ERRnoaccess);
3186 END_PROFILE(SMBread);
3187 return;
3190 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3192 SSVAL(req->outbuf,smb_vwv0,nread);
3193 SSVAL(req->outbuf,smb_vwv5,nread+3);
3194 SCVAL(smb_buf(req->outbuf),0,1);
3195 SSVAL(smb_buf(req->outbuf),1,nread);
3197 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3198 fsp->fnum, (int)numtoread, (int)nread ) );
3200 END_PROFILE(SMBread);
3201 return;
3204 /****************************************************************************
3205 Setup readX header.
3206 ****************************************************************************/
3208 static int setup_readX_header(char *outbuf, size_t smb_maxcnt)
3210 int outsize;
3211 char *data;
3213 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3214 data = smb_buf(outbuf);
3216 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3218 SCVAL(outbuf,smb_vwv0,0xFF);
3219 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3220 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3221 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
3222 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3223 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
3224 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3225 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3226 return outsize;
3229 /****************************************************************************
3230 Reply to a read and X - possibly using sendfile.
3231 ****************************************************************************/
3233 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3234 files_struct *fsp, SMB_OFF_T startpos,
3235 size_t smb_maxcnt)
3237 SMB_STRUCT_STAT sbuf;
3238 ssize_t nread = -1;
3240 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3241 reply_unixerror(req, ERRDOS, ERRnoaccess);
3242 return;
3245 if (startpos > sbuf.st_size) {
3246 smb_maxcnt = 0;
3247 } else if (smb_maxcnt > (sbuf.st_size - startpos)) {
3248 smb_maxcnt = (sbuf.st_size - startpos);
3251 if (smb_maxcnt == 0) {
3252 goto normal_read;
3255 #if defined(WITH_SENDFILE)
3257 * We can only use sendfile on a non-chained packet
3258 * but we can use on a non-oplocked file. tridge proved this
3259 * on a train in Germany :-). JRA.
3262 if ((chain_size == 0) && (CVAL(req->inbuf,smb_vwv0) == 0xFF) &&
3263 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3264 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
3265 uint8 headerbuf[smb_size + 12 * 2];
3266 DATA_BLOB header;
3269 * Set up the packet header before send. We
3270 * assume here the sendfile will work (get the
3271 * correct amount of data).
3274 header = data_blob_const(headerbuf, sizeof(headerbuf));
3276 construct_reply_common((char *)req->inbuf, (char *)headerbuf);
3277 setup_readX_header((char *)headerbuf, smb_maxcnt);
3279 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3280 /* Returning ENOSYS means no data at all was sent.
3281 Do this as a normal read. */
3282 if (errno == ENOSYS) {
3283 goto normal_read;
3287 * Special hack for broken Linux with no working sendfile. If we
3288 * return EINTR we sent the header but not the rest of the data.
3289 * Fake this up by doing read/write calls.
3292 if (errno == EINTR) {
3293 /* Ensure we don't do this again. */
3294 set_use_sendfile(SNUM(conn), False);
3295 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3296 nread = fake_sendfile(fsp, startpos,
3297 smb_maxcnt);
3298 if (nread == -1) {
3299 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3300 fsp->fsp_name, strerror(errno) ));
3301 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3303 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3304 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3305 /* No outbuf here means successful sendfile. */
3306 TALLOC_FREE(req->outbuf);
3307 return;
3310 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3311 fsp->fsp_name, strerror(errno) ));
3312 exit_server_cleanly("send_file_readX sendfile failed");
3315 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3316 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3317 /* No outbuf here means successful sendfile. */
3318 TALLOC_FREE(req->outbuf);
3319 return;
3321 #endif
3323 normal_read:
3325 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3326 uint8 headerbuf[smb_size + 2*12];
3328 construct_reply_common((char *)req->inbuf, (char *)headerbuf);
3329 setup_readX_header((char *)headerbuf, smb_maxcnt);
3331 /* Send out the header. */
3332 if (write_data(smbd_server_fd(), (char *)headerbuf,
3333 sizeof(headerbuf)) != sizeof(headerbuf)) {
3334 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3335 fsp->fsp_name, strerror(errno) ));
3336 exit_server_cleanly("send_file_readX sendfile failed");
3338 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3339 if (nread == -1) {
3340 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3341 fsp->fsp_name, strerror(errno) ));
3342 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3344 TALLOC_FREE(req->outbuf);
3345 return;
3346 } else {
3347 reply_outbuf(req, 12, smb_maxcnt);
3349 nread = read_file(fsp, smb_buf(req->outbuf), startpos,
3350 smb_maxcnt);
3351 if (nread < 0) {
3352 reply_unixerror(req, ERRDOS, ERRnoaccess);
3353 return;
3356 setup_readX_header((char *)req->outbuf, nread);
3358 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3359 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3361 chain_reply(req);
3363 return;
3367 /****************************************************************************
3368 Reply to a read and X.
3369 ****************************************************************************/
3371 void reply_read_and_X(struct smb_request *req)
3373 connection_struct *conn = req->conn;
3374 files_struct *fsp;
3375 SMB_OFF_T startpos;
3376 size_t smb_maxcnt;
3377 bool big_readX = False;
3378 #if 0
3379 size_t smb_mincnt = SVAL(req->inbuf,smb_vwv6);
3380 #endif
3382 START_PROFILE(SMBreadX);
3384 if ((req->wct != 10) && (req->wct != 12)) {
3385 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3386 return;
3389 fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
3390 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
3391 smb_maxcnt = SVAL(req->inbuf,smb_vwv5);
3393 /* If it's an IPC, pass off the pipe handler. */
3394 if (IS_IPC(conn)) {
3395 reply_pipe_read_and_X(req);
3396 END_PROFILE(SMBreadX);
3397 return;
3400 if (!check_fsp(conn, req, fsp)) {
3401 END_PROFILE(SMBreadX);
3402 return;
3405 if (!CHECK_READ(fsp,req->inbuf)) {
3406 reply_doserror(req, ERRDOS,ERRbadaccess);
3407 END_PROFILE(SMBreadX);
3408 return;
3411 if (global_client_caps & CAP_LARGE_READX) {
3412 size_t upper_size = SVAL(req->inbuf,smb_vwv7);
3413 smb_maxcnt |= (upper_size<<16);
3414 if (upper_size > 1) {
3415 /* Can't do this on a chained packet. */
3416 if ((CVAL(req->inbuf,smb_vwv0) != 0xFF)) {
3417 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3418 END_PROFILE(SMBreadX);
3419 return;
3421 /* We currently don't do this on signed or sealed data. */
3422 if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
3423 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3424 END_PROFILE(SMBreadX);
3425 return;
3427 /* Is there room in the reply for this data ? */
3428 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3429 reply_nterror(req,
3430 NT_STATUS_INVALID_PARAMETER);
3431 END_PROFILE(SMBreadX);
3432 return;
3434 big_readX = True;
3438 if (req->wct == 12) {
3439 #ifdef LARGE_SMB_OFF_T
3441 * This is a large offset (64 bit) read.
3443 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv10)) << 32);
3445 #else /* !LARGE_SMB_OFF_T */
3448 * Ensure we haven't been sent a >32 bit offset.
3451 if(IVAL(req->inbuf,smb_vwv10) != 0) {
3452 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3453 "used and we don't support 64 bit offsets.\n",
3454 (unsigned int)IVAL(req->inbuf,smb_vwv10) ));
3455 END_PROFILE(SMBreadX);
3456 reply_doserror(req, ERRDOS, ERRbadaccess);
3457 return;
3460 #endif /* LARGE_SMB_OFF_T */
3464 if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)smb_maxcnt,
3465 (SMB_BIG_UINT)startpos, READ_LOCK)) {
3466 END_PROFILE(SMBreadX);
3467 reply_doserror(req, ERRDOS, ERRlock);
3468 return;
3471 if (!big_readX &&
3472 schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3473 END_PROFILE(SMBreadX);
3474 return;
3477 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3479 END_PROFILE(SMBreadX);
3480 return;
3483 /****************************************************************************
3484 Error replies to writebraw must have smb_wct == 1. Fix this up.
3485 ****************************************************************************/
3487 void error_to_writebrawerr(struct smb_request *req)
3489 uint8 *old_outbuf = req->outbuf;
3491 reply_outbuf(req, 1, 0);
3493 memcpy(req->outbuf, old_outbuf, smb_size);
3494 TALLOC_FREE(old_outbuf);
3497 /****************************************************************************
3498 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3499 ****************************************************************************/
3501 void reply_writebraw(struct smb_request *req)
3503 connection_struct *conn = req->conn;
3504 char *buf = NULL;
3505 ssize_t nwritten=0;
3506 ssize_t total_written=0;
3507 size_t numtowrite=0;
3508 size_t tcount;
3509 SMB_OFF_T startpos;
3510 char *data=NULL;
3511 bool write_through;
3512 files_struct *fsp;
3513 NTSTATUS status;
3515 START_PROFILE(SMBwritebraw);
3518 * If we ever reply with an error, it must have the SMB command
3519 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3520 * we're finished.
3522 SCVAL(req->inbuf,smb_com,SMBwritec);
3524 if (srv_is_signing_active()) {
3525 END_PROFILE(SMBwritebraw);
3526 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3527 "raw reads/writes are disallowed.");
3530 if (req->wct < 12) {
3531 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3532 error_to_writebrawerr(req);
3533 END_PROFILE(SMBwritebraw);
3534 return;
3537 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3538 if (!check_fsp(conn, req, fsp)) {
3539 error_to_writebrawerr(req);
3540 END_PROFILE(SMBwritebraw);
3541 return;
3544 if (!CHECK_WRITE(fsp)) {
3545 reply_doserror(req, ERRDOS, ERRbadaccess);
3546 error_to_writebrawerr(req);
3547 END_PROFILE(SMBwritebraw);
3548 return;
3551 tcount = IVAL(req->inbuf,smb_vwv1);
3552 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
3553 write_through = BITSETW(req->inbuf+smb_vwv7,0);
3555 /* We have to deal with slightly different formats depending
3556 on whether we are using the core+ or lanman1.0 protocol */
3558 if(Protocol <= PROTOCOL_COREPLUS) {
3559 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3560 data = smb_buf(req->inbuf);
3561 } else {
3562 numtowrite = SVAL(req->inbuf,smb_vwv10);
3563 data = smb_base(req->inbuf) + SVAL(req->inbuf, smb_vwv11);
3566 /* Ensure we don't write bytes past the end of this packet. */
3567 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3568 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3569 error_to_writebrawerr(req);
3570 END_PROFILE(SMBwritebraw);
3571 return;
3574 if (is_locked(fsp,(uint32)req->smbpid,(SMB_BIG_UINT)tcount,
3575 (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3576 reply_doserror(req, ERRDOS, ERRlock);
3577 error_to_writebrawerr(req);
3578 END_PROFILE(SMBwritebraw);
3579 return;
3582 if (numtowrite>0) {
3583 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3586 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3587 "wrote=%d sync=%d\n",
3588 fsp->fnum, (double)startpos, (int)numtowrite,
3589 (int)nwritten, (int)write_through));
3591 if (nwritten < (ssize_t)numtowrite) {
3592 reply_unixerror(req, ERRHRD, ERRdiskfull);
3593 error_to_writebrawerr(req);
3594 END_PROFILE(SMBwritebraw);
3595 return;
3598 total_written = nwritten;
3600 /* Allocate a buffer of 64k + length. */
3601 buf = TALLOC_ARRAY(NULL, char, 65540);
3602 if (!buf) {
3603 reply_doserror(req, ERRDOS, ERRnomem);
3604 error_to_writebrawerr(req);
3605 END_PROFILE(SMBwritebraw);
3606 return;
3609 /* Return a SMBwritebraw message to the redirector to tell
3610 * it to send more bytes */
3612 memcpy(buf, req->inbuf, smb_size);
3613 srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3614 SCVAL(buf,smb_com,SMBwritebraw);
3615 SSVALS(buf,smb_vwv0,0xFFFF);
3616 show_msg(buf);
3617 if (!srv_send_smb(smbd_server_fd(),
3618 buf,
3619 IS_CONN_ENCRYPTED(conn))) {
3620 exit_server_cleanly("reply_writebraw: srv_send_smb "
3621 "failed.");
3624 /* Now read the raw data into the buffer and write it */
3625 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3626 &numtowrite);
3627 if (!NT_STATUS_IS_OK(status)) {
3628 exit_server_cleanly("secondary writebraw failed");
3631 /* Set up outbuf to return the correct size */
3632 reply_outbuf(req, 1, 0);
3634 if (numtowrite != 0) {
3636 if (numtowrite > 0xFFFF) {
3637 DEBUG(0,("reply_writebraw: Oversize secondary write "
3638 "raw requested (%u). Terminating\n",
3639 (unsigned int)numtowrite ));
3640 exit_server_cleanly("secondary writebraw failed");
3643 if (tcount > nwritten+numtowrite) {
3644 DEBUG(3,("reply_writebraw: Client overestimated the "
3645 "write %d %d %d\n",
3646 (int)tcount,(int)nwritten,(int)numtowrite));
3649 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3651 if (!NT_STATUS_IS_OK(status)) {
3652 DEBUG(0,("reply_writebraw: Oversize secondary write "
3653 "raw read failed (%s). Terminating\n",
3654 nt_errstr(status)));
3655 exit_server_cleanly("secondary writebraw failed");
3658 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3659 if (nwritten == -1) {
3660 TALLOC_FREE(buf);
3661 reply_unixerror(req, ERRHRD, ERRdiskfull);
3662 error_to_writebrawerr(req);
3663 END_PROFILE(SMBwritebraw);
3664 return;
3667 if (nwritten < (ssize_t)numtowrite) {
3668 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3669 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3672 if (nwritten > 0) {
3673 total_written += nwritten;
3677 TALLOC_FREE(buf);
3678 SSVAL(req->outbuf,smb_vwv0,total_written);
3680 status = sync_file(conn, fsp, write_through);
3681 if (!NT_STATUS_IS_OK(status)) {
3682 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3683 fsp->fsp_name, nt_errstr(status) ));
3684 reply_nterror(req, status);
3685 error_to_writebrawerr(req);
3686 END_PROFILE(SMBwritebraw);
3687 return;
3690 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3691 "wrote=%d\n",
3692 fsp->fnum, (double)startpos, (int)numtowrite,
3693 (int)total_written));
3695 /* We won't return a status if write through is not selected - this
3696 * follows what WfWg does */
3697 END_PROFILE(SMBwritebraw);
3699 if (!write_through && total_written==tcount) {
3701 #if RABBIT_PELLET_FIX
3703 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3704 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3705 * JRA.
3707 if (!send_keepalive(smbd_server_fd())) {
3708 exit_server_cleanly("reply_writebraw: send of "
3709 "keepalive failed");
3711 #endif
3712 TALLOC_FREE(req->outbuf);
3714 return;
3717 #undef DBGC_CLASS
3718 #define DBGC_CLASS DBGC_LOCKING
3720 /****************************************************************************
3721 Reply to a writeunlock (core+).
3722 ****************************************************************************/
3724 void reply_writeunlock(struct smb_request *req)
3726 connection_struct *conn = req->conn;
3727 ssize_t nwritten = -1;
3728 size_t numtowrite;
3729 SMB_OFF_T startpos;
3730 char *data;
3731 NTSTATUS status = NT_STATUS_OK;
3732 files_struct *fsp;
3734 START_PROFILE(SMBwriteunlock);
3736 if (req->wct < 5) {
3737 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3738 END_PROFILE(SMBwriteunlock);
3739 return;
3742 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3744 if (!check_fsp(conn, req, fsp)) {
3745 END_PROFILE(SMBwriteunlock);
3746 return;
3749 if (!CHECK_WRITE(fsp)) {
3750 reply_doserror(req, ERRDOS,ERRbadaccess);
3751 END_PROFILE(SMBwriteunlock);
3752 return;
3755 numtowrite = SVAL(req->inbuf,smb_vwv1);
3756 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
3757 data = smb_buf(req->inbuf) + 3;
3759 if (numtowrite
3760 && is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
3761 (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3762 reply_doserror(req, ERRDOS, ERRlock);
3763 END_PROFILE(SMBwriteunlock);
3764 return;
3767 /* The special X/Open SMB protocol handling of
3768 zero length writes is *NOT* done for
3769 this call */
3770 if(numtowrite == 0) {
3771 nwritten = 0;
3772 } else {
3773 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3776 status = sync_file(conn, fsp, False /* write through */);
3777 if (!NT_STATUS_IS_OK(status)) {
3778 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3779 fsp->fsp_name, nt_errstr(status) ));
3780 reply_nterror(req, status);
3781 END_PROFILE(SMBwriteunlock);
3782 return;
3785 if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
3786 reply_unixerror(req, ERRHRD, ERRdiskfull);
3787 END_PROFILE(SMBwriteunlock);
3788 return;
3791 if (numtowrite) {
3792 status = do_unlock(smbd_messaging_context(),
3793 fsp,
3794 req->smbpid,
3795 (SMB_BIG_UINT)numtowrite,
3796 (SMB_BIG_UINT)startpos,
3797 WINDOWS_LOCK);
3799 if (NT_STATUS_V(status)) {
3800 reply_nterror(req, status);
3801 END_PROFILE(SMBwriteunlock);
3802 return;
3806 reply_outbuf(req, 1, 0);
3808 SSVAL(req->outbuf,smb_vwv0,nwritten);
3810 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3811 fsp->fnum, (int)numtowrite, (int)nwritten));
3813 END_PROFILE(SMBwriteunlock);
3814 return;
3817 #undef DBGC_CLASS
3818 #define DBGC_CLASS DBGC_ALL
3820 /****************************************************************************
3821 Reply to a write.
3822 ****************************************************************************/
3824 void reply_write(struct smb_request *req)
3826 connection_struct *conn = req->conn;
3827 size_t numtowrite;
3828 ssize_t nwritten = -1;
3829 SMB_OFF_T startpos;
3830 char *data;
3831 files_struct *fsp;
3832 NTSTATUS status;
3834 START_PROFILE(SMBwrite);
3836 if (req->wct < 5) {
3837 END_PROFILE(SMBwrite);
3838 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3839 return;
3842 /* If it's an IPC, pass off the pipe handler. */
3843 if (IS_IPC(conn)) {
3844 reply_pipe_write(req);
3845 END_PROFILE(SMBwrite);
3846 return;
3849 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3851 if (!check_fsp(conn, req, fsp)) {
3852 END_PROFILE(SMBwrite);
3853 return;
3856 if (!CHECK_WRITE(fsp)) {
3857 reply_doserror(req, ERRDOS, ERRbadaccess);
3858 END_PROFILE(SMBwrite);
3859 return;
3862 numtowrite = SVAL(req->inbuf,smb_vwv1);
3863 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
3864 data = smb_buf(req->inbuf) + 3;
3866 if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
3867 (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3868 reply_doserror(req, ERRDOS, ERRlock);
3869 END_PROFILE(SMBwrite);
3870 return;
3874 * X/Open SMB protocol says that if smb_vwv1 is
3875 * zero then the file size should be extended or
3876 * truncated to the size given in smb_vwv[2-3].
3879 if(numtowrite == 0) {
3881 * This is actually an allocate call, and set EOF. JRA.
3883 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3884 if (nwritten < 0) {
3885 reply_nterror(req, NT_STATUS_DISK_FULL);
3886 END_PROFILE(SMBwrite);
3887 return;
3889 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3890 if (nwritten < 0) {
3891 reply_nterror(req, NT_STATUS_DISK_FULL);
3892 END_PROFILE(SMBwrite);
3893 return;
3895 trigger_write_time_update_immediate(fsp);
3896 } else {
3897 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3900 status = sync_file(conn, fsp, False);
3901 if (!NT_STATUS_IS_OK(status)) {
3902 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3903 fsp->fsp_name, nt_errstr(status) ));
3904 reply_nterror(req, status);
3905 END_PROFILE(SMBwrite);
3906 return;
3909 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3910 reply_unixerror(req, ERRHRD, ERRdiskfull);
3911 END_PROFILE(SMBwrite);
3912 return;
3915 reply_outbuf(req, 1, 0);
3917 SSVAL(req->outbuf,smb_vwv0,nwritten);
3919 if (nwritten < (ssize_t)numtowrite) {
3920 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3921 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3924 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3926 END_PROFILE(SMBwrite);
3927 return;
3930 /****************************************************************************
3931 Ensure a buffer is a valid writeX for recvfile purposes.
3932 ****************************************************************************/
3934 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
3935 (2*14) + /* word count (including bcc) */ \
3936 1 /* pad byte */)
3938 bool is_valid_writeX_buffer(const uint8_t *inbuf)
3940 size_t numtowrite;
3941 connection_struct *conn = NULL;
3942 unsigned int doff = 0;
3943 size_t len = smb_len_large(inbuf);
3945 if (is_encrypted_packet(inbuf)) {
3946 /* Can't do this on encrypted
3947 * connections. */
3948 return false;
3951 if (CVAL(inbuf,smb_com) != SMBwriteX) {
3952 return false;
3955 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
3956 CVAL(inbuf,smb_wct) != 14) {
3957 DEBUG(10,("is_valid_writeX_buffer: chained or "
3958 "invalid word length.\n"));
3959 return false;
3962 conn = conn_find(SVAL(inbuf, smb_tid));
3963 if (conn == NULL) {
3964 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
3965 return false;
3967 if (IS_IPC(conn)) {
3968 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
3969 return false;
3971 if (IS_PRINT(conn)) {
3972 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
3973 return false;
3975 doff = SVAL(inbuf,smb_vwv11);
3977 numtowrite = SVAL(inbuf,smb_vwv10);
3979 if (len > doff && len - doff > 0xFFFF) {
3980 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
3983 if (numtowrite == 0) {
3984 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
3985 return false;
3988 /* Ensure the sizes match up. */
3989 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
3990 /* no pad byte...old smbclient :-( */
3991 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
3992 (unsigned int)doff,
3993 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
3994 return false;
3997 if (len - doff != numtowrite) {
3998 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
3999 "len = %u, doff = %u, numtowrite = %u\n",
4000 (unsigned int)len,
4001 (unsigned int)doff,
4002 (unsigned int)numtowrite ));
4003 return false;
4006 DEBUG(10,("is_valid_writeX_buffer: true "
4007 "len = %u, doff = %u, numtowrite = %u\n",
4008 (unsigned int)len,
4009 (unsigned int)doff,
4010 (unsigned int)numtowrite ));
4012 return true;
4015 /****************************************************************************
4016 Reply to a write and X.
4017 ****************************************************************************/
4019 void reply_write_and_X(struct smb_request *req)
4021 connection_struct *conn = req->conn;
4022 files_struct *fsp;
4023 SMB_OFF_T startpos;
4024 size_t numtowrite;
4025 bool write_through;
4026 ssize_t nwritten;
4027 unsigned int smb_doff;
4028 unsigned int smblen;
4029 char *data;
4030 NTSTATUS status;
4032 START_PROFILE(SMBwriteX);
4034 if ((req->wct != 12) && (req->wct != 14)) {
4035 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4036 END_PROFILE(SMBwriteX);
4037 return;
4040 numtowrite = SVAL(req->inbuf,smb_vwv10);
4041 smb_doff = SVAL(req->inbuf,smb_vwv11);
4042 smblen = smb_len(req->inbuf);
4044 if (req->unread_bytes > 0xFFFF ||
4045 (smblen > smb_doff &&
4046 smblen - smb_doff > 0xFFFF)) {
4047 numtowrite |= (((size_t)SVAL(req->inbuf,smb_vwv9))<<16);
4050 if (req->unread_bytes) {
4051 /* Can't do a recvfile write on IPC$ */
4052 if (IS_IPC(conn)) {
4053 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4054 END_PROFILE(SMBwriteX);
4055 return;
4057 if (numtowrite != req->unread_bytes) {
4058 reply_doserror(req, ERRDOS, ERRbadmem);
4059 END_PROFILE(SMBwriteX);
4060 return;
4062 } else {
4063 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4064 smb_doff + numtowrite > smblen) {
4065 reply_doserror(req, ERRDOS, ERRbadmem);
4066 END_PROFILE(SMBwriteX);
4067 return;
4071 /* If it's an IPC, pass off the pipe handler. */
4072 if (IS_IPC(conn)) {
4073 if (req->unread_bytes) {
4074 reply_doserror(req, ERRDOS, ERRbadmem);
4075 END_PROFILE(SMBwriteX);
4076 return;
4078 reply_pipe_write_and_X(req);
4079 END_PROFILE(SMBwriteX);
4080 return;
4083 fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
4084 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
4085 write_through = BITSETW(req->inbuf+smb_vwv7,0);
4087 if (!check_fsp(conn, req, fsp)) {
4088 END_PROFILE(SMBwriteX);
4089 return;
4092 if (!CHECK_WRITE(fsp)) {
4093 reply_doserror(req, ERRDOS, ERRbadaccess);
4094 END_PROFILE(SMBwriteX);
4095 return;
4098 data = smb_base(req->inbuf) + smb_doff;
4100 if(req->wct == 14) {
4101 #ifdef LARGE_SMB_OFF_T
4103 * This is a large offset (64 bit) write.
4105 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv12)) << 32);
4107 #else /* !LARGE_SMB_OFF_T */
4110 * Ensure we haven't been sent a >32 bit offset.
4113 if(IVAL(req->inbuf,smb_vwv12) != 0) {
4114 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4115 "used and we don't support 64 bit offsets.\n",
4116 (unsigned int)IVAL(req->inbuf,smb_vwv12) ));
4117 reply_doserror(req, ERRDOS, ERRbadaccess);
4118 END_PROFILE(SMBwriteX);
4119 return;
4122 #endif /* LARGE_SMB_OFF_T */
4125 if (is_locked(fsp,(uint32)req->smbpid,
4126 (SMB_BIG_UINT)numtowrite,
4127 (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
4128 reply_doserror(req, ERRDOS, ERRlock);
4129 END_PROFILE(SMBwriteX);
4130 return;
4133 /* X/Open SMB protocol says that, unlike SMBwrite
4134 if the length is zero then NO truncation is
4135 done, just a write of zero. To truncate a file,
4136 use SMBwrite. */
4138 if(numtowrite == 0) {
4139 nwritten = 0;
4140 } else {
4142 if ((req->unread_bytes == 0) &&
4143 schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4144 numtowrite)) {
4145 END_PROFILE(SMBwriteX);
4146 return;
4149 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4152 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4153 reply_unixerror(req, ERRHRD, ERRdiskfull);
4154 END_PROFILE(SMBwriteX);
4155 return;
4158 reply_outbuf(req, 6, 0);
4159 SSVAL(req->outbuf,smb_vwv2,nwritten);
4160 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4162 if (nwritten < (ssize_t)numtowrite) {
4163 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4164 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4167 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4168 fsp->fnum, (int)numtowrite, (int)nwritten));
4170 status = sync_file(conn, fsp, write_through);
4171 if (!NT_STATUS_IS_OK(status)) {
4172 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4173 fsp->fsp_name, nt_errstr(status) ));
4174 reply_nterror(req, status);
4175 END_PROFILE(SMBwriteX);
4176 return;
4179 END_PROFILE(SMBwriteX);
4180 chain_reply(req);
4181 return;
4184 /****************************************************************************
4185 Reply to a lseek.
4186 ****************************************************************************/
4188 void reply_lseek(struct smb_request *req)
4190 connection_struct *conn = req->conn;
4191 SMB_OFF_T startpos;
4192 SMB_OFF_T res= -1;
4193 int mode,umode;
4194 files_struct *fsp;
4196 START_PROFILE(SMBlseek);
4198 if (req->wct < 4) {
4199 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4200 END_PROFILE(SMBlseek);
4201 return;
4204 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4206 if (!check_fsp(conn, req, fsp)) {
4207 return;
4210 flush_write_cache(fsp, SEEK_FLUSH);
4212 mode = SVAL(req->inbuf,smb_vwv1) & 3;
4213 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4214 startpos = (SMB_OFF_T)IVALS(req->inbuf,smb_vwv2);
4216 switch (mode) {
4217 case 0:
4218 umode = SEEK_SET;
4219 res = startpos;
4220 break;
4221 case 1:
4222 umode = SEEK_CUR;
4223 res = fsp->fh->pos + startpos;
4224 break;
4225 case 2:
4226 umode = SEEK_END;
4227 break;
4228 default:
4229 umode = SEEK_SET;
4230 res = startpos;
4231 break;
4234 if (umode == SEEK_END) {
4235 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4236 if(errno == EINVAL) {
4237 SMB_OFF_T current_pos = startpos;
4238 SMB_STRUCT_STAT sbuf;
4240 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4241 reply_unixerror(req, ERRDOS,
4242 ERRnoaccess);
4243 END_PROFILE(SMBlseek);
4244 return;
4247 current_pos += sbuf.st_size;
4248 if(current_pos < 0)
4249 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4253 if(res == -1) {
4254 reply_unixerror(req, ERRDOS, ERRnoaccess);
4255 END_PROFILE(SMBlseek);
4256 return;
4260 fsp->fh->pos = res;
4262 reply_outbuf(req, 2, 0);
4263 SIVAL(req->outbuf,smb_vwv0,res);
4265 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4266 fsp->fnum, (double)startpos, (double)res, mode));
4268 END_PROFILE(SMBlseek);
4269 return;
4272 /****************************************************************************
4273 Reply to a flush.
4274 ****************************************************************************/
4276 void reply_flush(struct smb_request *req)
4278 connection_struct *conn = req->conn;
4279 uint16 fnum;
4280 files_struct *fsp;
4282 START_PROFILE(SMBflush);
4284 if (req->wct < 1) {
4285 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4286 return;
4289 fnum = SVAL(req->inbuf,smb_vwv0);
4290 fsp = file_fsp(fnum);
4292 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4293 return;
4296 if (!fsp) {
4297 file_sync_all(conn);
4298 } else {
4299 NTSTATUS status = sync_file(conn, fsp, True);
4300 if (!NT_STATUS_IS_OK(status)) {
4301 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4302 fsp->fsp_name, nt_errstr(status) ));
4303 reply_nterror(req, status);
4304 END_PROFILE(SMBflush);
4305 return;
4309 reply_outbuf(req, 0, 0);
4311 DEBUG(3,("flush\n"));
4312 END_PROFILE(SMBflush);
4313 return;
4316 /****************************************************************************
4317 Reply to a exit.
4318 conn POINTER CAN BE NULL HERE !
4319 ****************************************************************************/
4321 void reply_exit(struct smb_request *req)
4323 START_PROFILE(SMBexit);
4325 file_close_pid(req->smbpid, req->vuid);
4327 reply_outbuf(req, 0, 0);
4329 DEBUG(3,("exit\n"));
4331 END_PROFILE(SMBexit);
4332 return;
4335 /****************************************************************************
4336 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4337 ****************************************************************************/
4339 void reply_close(struct smb_request *req)
4341 connection_struct *conn = req->conn;
4342 NTSTATUS status = NT_STATUS_OK;
4343 files_struct *fsp = NULL;
4344 START_PROFILE(SMBclose);
4346 if (req->wct < 3) {
4347 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4348 END_PROFILE(SMBclose);
4349 return;
4352 /* If it's an IPC, pass off to the pipe handler. */
4353 if (IS_IPC(conn)) {
4354 reply_pipe_close(conn, req);
4355 END_PROFILE(SMBclose);
4356 return;
4359 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4362 * We can only use check_fsp if we know it's not a directory.
4365 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4366 reply_doserror(req, ERRDOS, ERRbadfid);
4367 END_PROFILE(SMBclose);
4368 return;
4371 if(fsp->is_directory) {
4373 * Special case - close NT SMB directory handle.
4375 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4376 status = close_file(fsp,NORMAL_CLOSE);
4377 } else {
4378 time_t t;
4380 * Close ordinary file.
4383 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4384 fsp->fh->fd, fsp->fnum,
4385 conn->num_files_open));
4388 * Take care of any time sent in the close.
4391 t = srv_make_unix_date3(req->inbuf+smb_vwv1);
4392 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4395 * close_file() returns the unix errno if an error
4396 * was detected on close - normally this is due to
4397 * a disk full error. If not then it was probably an I/O error.
4400 status = close_file(fsp,NORMAL_CLOSE);
4403 if (!NT_STATUS_IS_OK(status)) {
4404 reply_nterror(req, status);
4405 END_PROFILE(SMBclose);
4406 return;
4409 reply_outbuf(req, 0, 0);
4410 END_PROFILE(SMBclose);
4411 return;
4414 /****************************************************************************
4415 Reply to a writeclose (Core+ protocol).
4416 ****************************************************************************/
4418 void reply_writeclose(struct smb_request *req)
4420 connection_struct *conn = req->conn;
4421 size_t numtowrite;
4422 ssize_t nwritten = -1;
4423 NTSTATUS close_status = NT_STATUS_OK;
4424 SMB_OFF_T startpos;
4425 char *data;
4426 struct timespec mtime;
4427 files_struct *fsp;
4429 START_PROFILE(SMBwriteclose);
4431 if (req->wct < 6) {
4432 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4433 END_PROFILE(SMBwriteclose);
4434 return;
4437 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4439 if (!check_fsp(conn, req, fsp)) {
4440 END_PROFILE(SMBwriteclose);
4441 return;
4443 if (!CHECK_WRITE(fsp)) {
4444 reply_doserror(req, ERRDOS,ERRbadaccess);
4445 END_PROFILE(SMBwriteclose);
4446 return;
4449 numtowrite = SVAL(req->inbuf,smb_vwv1);
4450 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
4451 mtime = convert_time_t_to_timespec(srv_make_unix_date3(
4452 req->inbuf+smb_vwv4));
4453 data = smb_buf(req->inbuf) + 1;
4455 if (numtowrite
4456 && is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
4457 (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
4458 reply_doserror(req, ERRDOS,ERRlock);
4459 END_PROFILE(SMBwriteclose);
4460 return;
4463 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4465 set_close_write_time(fsp, mtime);
4468 * More insanity. W2K only closes the file if writelen > 0.
4469 * JRA.
4472 if (numtowrite) {
4473 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4474 fsp->fsp_name ));
4475 close_status = close_file(fsp,NORMAL_CLOSE);
4478 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4479 fsp->fnum, (int)numtowrite, (int)nwritten,
4480 conn->num_files_open));
4482 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4483 reply_doserror(req, ERRHRD, ERRdiskfull);
4484 END_PROFILE(SMBwriteclose);
4485 return;
4488 if(!NT_STATUS_IS_OK(close_status)) {
4489 reply_nterror(req, close_status);
4490 END_PROFILE(SMBwriteclose);
4491 return;
4494 reply_outbuf(req, 1, 0);
4496 SSVAL(req->outbuf,smb_vwv0,nwritten);
4497 END_PROFILE(SMBwriteclose);
4498 return;
4501 #undef DBGC_CLASS
4502 #define DBGC_CLASS DBGC_LOCKING
4504 /****************************************************************************
4505 Reply to a lock.
4506 ****************************************************************************/
4508 void reply_lock(struct smb_request *req)
4510 connection_struct *conn = req->conn;
4511 SMB_BIG_UINT count,offset;
4512 NTSTATUS status;
4513 files_struct *fsp;
4514 struct byte_range_lock *br_lck = NULL;
4516 START_PROFILE(SMBlock);
4518 if (req->wct < 5) {
4519 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4520 END_PROFILE(SMBlock);
4521 return;
4524 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4526 if (!check_fsp(conn, req, fsp)) {
4527 END_PROFILE(SMBlock);
4528 return;
4531 release_level_2_oplocks_on_change(fsp);
4533 count = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv1);
4534 offset = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv3);
4536 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4537 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4539 br_lck = do_lock(smbd_messaging_context(),
4540 fsp,
4541 req->smbpid,
4542 count,
4543 offset,
4544 WRITE_LOCK,
4545 WINDOWS_LOCK,
4546 False, /* Non-blocking lock. */
4547 &status,
4548 NULL);
4550 TALLOC_FREE(br_lck);
4552 if (NT_STATUS_V(status)) {
4553 reply_nterror(req, status);
4554 END_PROFILE(SMBlock);
4555 return;
4558 reply_outbuf(req, 0, 0);
4560 END_PROFILE(SMBlock);
4561 return;
4564 /****************************************************************************
4565 Reply to a unlock.
4566 ****************************************************************************/
4568 void reply_unlock(struct smb_request *req)
4570 connection_struct *conn = req->conn;
4571 SMB_BIG_UINT count,offset;
4572 NTSTATUS status;
4573 files_struct *fsp;
4575 START_PROFILE(SMBunlock);
4577 if (req->wct < 5) {
4578 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4579 END_PROFILE(SMBunlock);
4580 return;
4583 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4585 if (!check_fsp(conn, req, fsp)) {
4586 END_PROFILE(SMBunlock);
4587 return;
4590 count = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv1);
4591 offset = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv3);
4593 status = do_unlock(smbd_messaging_context(),
4594 fsp,
4595 req->smbpid,
4596 count,
4597 offset,
4598 WINDOWS_LOCK);
4600 if (NT_STATUS_V(status)) {
4601 reply_nterror(req, status);
4602 END_PROFILE(SMBunlock);
4603 return;
4606 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4607 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4609 reply_outbuf(req, 0, 0);
4611 END_PROFILE(SMBunlock);
4612 return;
4615 #undef DBGC_CLASS
4616 #define DBGC_CLASS DBGC_ALL
4618 /****************************************************************************
4619 Reply to a tdis.
4620 conn POINTER CAN BE NULL HERE !
4621 ****************************************************************************/
4623 void reply_tdis(struct smb_request *req)
4625 connection_struct *conn = req->conn;
4626 START_PROFILE(SMBtdis);
4628 if (!conn) {
4629 DEBUG(4,("Invalid connection in tdis\n"));
4630 reply_doserror(req, ERRSRV, ERRinvnid);
4631 END_PROFILE(SMBtdis);
4632 return;
4635 conn->used = False;
4637 close_cnum(conn,req->vuid);
4638 req->conn = NULL;
4640 reply_outbuf(req, 0, 0);
4641 END_PROFILE(SMBtdis);
4642 return;
4645 /****************************************************************************
4646 Reply to a echo.
4647 conn POINTER CAN BE NULL HERE !
4648 ****************************************************************************/
4650 void reply_echo(struct smb_request *req)
4652 connection_struct *conn = req->conn;
4653 int smb_reverb;
4654 int seq_num;
4655 unsigned int data_len = smb_buflen(req->inbuf);
4657 START_PROFILE(SMBecho);
4659 if (req->wct < 1) {
4660 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4661 END_PROFILE(SMBecho);
4662 return;
4665 if (data_len > BUFFER_SIZE) {
4666 DEBUG(0,("reply_echo: data_len too large.\n"));
4667 reply_nterror(req, NT_STATUS_INSUFFICIENT_RESOURCES);
4668 END_PROFILE(SMBecho);
4669 return;
4672 smb_reverb = SVAL(req->inbuf,smb_vwv0);
4674 reply_outbuf(req, 1, data_len);
4676 /* copy any incoming data back out */
4677 if (data_len > 0) {
4678 memcpy(smb_buf(req->outbuf),smb_buf(req->inbuf),data_len);
4681 if (smb_reverb > 100) {
4682 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4683 smb_reverb = 100;
4686 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
4687 SSVAL(req->outbuf,smb_vwv0,seq_num);
4689 show_msg((char *)req->outbuf);
4690 if (!srv_send_smb(smbd_server_fd(),
4691 (char *)req->outbuf,
4692 IS_CONN_ENCRYPTED(conn)||req->encrypted))
4693 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4696 DEBUG(3,("echo %d times\n", smb_reverb));
4698 TALLOC_FREE(req->outbuf);
4700 END_PROFILE(SMBecho);
4701 return;
4704 /****************************************************************************
4705 Reply to a printopen.
4706 ****************************************************************************/
4708 void reply_printopen(struct smb_request *req)
4710 connection_struct *conn = req->conn;
4711 files_struct *fsp;
4712 SMB_STRUCT_STAT sbuf;
4713 NTSTATUS status;
4715 START_PROFILE(SMBsplopen);
4717 if (req->wct < 2) {
4718 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4719 END_PROFILE(SMBsplopen);
4720 return;
4723 if (!CAN_PRINT(conn)) {
4724 reply_doserror(req, ERRDOS, ERRnoaccess);
4725 END_PROFILE(SMBsplopen);
4726 return;
4729 status = file_new(conn, &fsp);
4730 if(!NT_STATUS_IS_OK(status)) {
4731 reply_nterror(req, status);
4732 END_PROFILE(SMBsplopen);
4733 return;
4736 /* Open for exclusive use, write only. */
4737 status = print_fsp_open(conn, NULL, req->vuid, fsp, &sbuf);
4739 if (!NT_STATUS_IS_OK(status)) {
4740 file_free(fsp);
4741 reply_nterror(req, status);
4742 END_PROFILE(SMBsplopen);
4743 return;
4746 reply_outbuf(req, 1, 0);
4747 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4749 DEBUG(3,("openprint fd=%d fnum=%d\n",
4750 fsp->fh->fd, fsp->fnum));
4752 END_PROFILE(SMBsplopen);
4753 return;
4756 /****************************************************************************
4757 Reply to a printclose.
4758 ****************************************************************************/
4760 void reply_printclose(struct smb_request *req)
4762 connection_struct *conn = req->conn;
4763 files_struct *fsp;
4764 NTSTATUS status;
4766 START_PROFILE(SMBsplclose);
4768 if (req->wct < 1) {
4769 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4770 END_PROFILE(SMBsplclose);
4771 return;
4774 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4776 if (!check_fsp(conn, req, fsp)) {
4777 END_PROFILE(SMBsplclose);
4778 return;
4781 if (!CAN_PRINT(conn)) {
4782 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
4783 END_PROFILE(SMBsplclose);
4784 return;
4787 DEBUG(3,("printclose fd=%d fnum=%d\n",
4788 fsp->fh->fd,fsp->fnum));
4790 status = close_file(fsp,NORMAL_CLOSE);
4792 if(!NT_STATUS_IS_OK(status)) {
4793 reply_nterror(req, status);
4794 END_PROFILE(SMBsplclose);
4795 return;
4798 reply_outbuf(req, 0, 0);
4800 END_PROFILE(SMBsplclose);
4801 return;
4804 /****************************************************************************
4805 Reply to a printqueue.
4806 ****************************************************************************/
4808 void reply_printqueue(struct smb_request *req)
4810 connection_struct *conn = req->conn;
4811 int max_count;
4812 int start_index;
4814 START_PROFILE(SMBsplretq);
4816 if (req->wct < 2) {
4817 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4818 END_PROFILE(SMBsplretq);
4819 return;
4822 max_count = SVAL(req->inbuf,smb_vwv0);
4823 start_index = SVAL(req->inbuf,smb_vwv1);
4825 /* we used to allow the client to get the cnum wrong, but that
4826 is really quite gross and only worked when there was only
4827 one printer - I think we should now only accept it if they
4828 get it right (tridge) */
4829 if (!CAN_PRINT(conn)) {
4830 reply_doserror(req, ERRDOS, ERRnoaccess);
4831 END_PROFILE(SMBsplretq);
4832 return;
4835 reply_outbuf(req, 2, 3);
4836 SSVAL(req->outbuf,smb_vwv0,0);
4837 SSVAL(req->outbuf,smb_vwv1,0);
4838 SCVAL(smb_buf(req->outbuf),0,1);
4839 SSVAL(smb_buf(req->outbuf),1,0);
4841 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
4842 start_index, max_count));
4845 print_queue_struct *queue = NULL;
4846 print_status_struct status;
4847 int count = print_queue_status(SNUM(conn), &queue, &status);
4848 int num_to_get = ABS(max_count);
4849 int first = (max_count>0?start_index:start_index+max_count+1);
4850 int i;
4852 if (first >= count)
4853 num_to_get = 0;
4854 else
4855 num_to_get = MIN(num_to_get,count-first);
4858 for (i=first;i<first+num_to_get;i++) {
4859 char blob[28];
4860 char *p = blob;
4862 srv_put_dos_date2(p,0,queue[i].time);
4863 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
4864 SSVAL(p,5, queue[i].job);
4865 SIVAL(p,7,queue[i].size);
4866 SCVAL(p,11,0);
4867 srvstr_push(blob, req->flags2, p+12,
4868 queue[i].fs_user, 16, STR_ASCII);
4870 if (message_push_blob(
4871 &req->outbuf,
4872 data_blob_const(
4873 blob, sizeof(blob))) == -1) {
4874 reply_nterror(req, NT_STATUS_NO_MEMORY);
4875 END_PROFILE(SMBsplretq);
4876 return;
4880 if (count > 0) {
4881 SSVAL(req->outbuf,smb_vwv0,count);
4882 SSVAL(req->outbuf,smb_vwv1,
4883 (max_count>0?first+count:first-1));
4884 SCVAL(smb_buf(req->outbuf),0,1);
4885 SSVAL(smb_buf(req->outbuf),1,28*count);
4888 SAFE_FREE(queue);
4890 DEBUG(3,("%d entries returned in queue\n",count));
4893 END_PROFILE(SMBsplretq);
4894 return;
4897 /****************************************************************************
4898 Reply to a printwrite.
4899 ****************************************************************************/
4901 void reply_printwrite(struct smb_request *req)
4903 connection_struct *conn = req->conn;
4904 int numtowrite;
4905 char *data;
4906 files_struct *fsp;
4908 START_PROFILE(SMBsplwr);
4910 if (req->wct < 1) {
4911 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4912 END_PROFILE(SMBsplwr);
4913 return;
4916 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4918 if (!check_fsp(conn, req, fsp)) {
4919 END_PROFILE(SMBsplwr);
4920 return;
4923 if (!CAN_PRINT(conn)) {
4924 reply_doserror(req, ERRDOS, ERRnoaccess);
4925 END_PROFILE(SMBsplwr);
4926 return;
4929 if (!CHECK_WRITE(fsp)) {
4930 reply_doserror(req, ERRDOS, ERRbadaccess);
4931 END_PROFILE(SMBsplwr);
4932 return;
4935 numtowrite = SVAL(smb_buf(req->inbuf),1);
4937 if (smb_buflen(req->inbuf) < numtowrite + 3) {
4938 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4939 END_PROFILE(SMBsplwr);
4940 return;
4943 data = smb_buf(req->inbuf) + 3;
4945 if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
4946 reply_unixerror(req, ERRHRD, ERRdiskfull);
4947 END_PROFILE(SMBsplwr);
4948 return;
4951 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
4953 END_PROFILE(SMBsplwr);
4954 return;
4957 /****************************************************************************
4958 Reply to a mkdir.
4959 ****************************************************************************/
4961 void reply_mkdir(struct smb_request *req)
4963 connection_struct *conn = req->conn;
4964 char *directory = NULL;
4965 NTSTATUS status;
4966 SMB_STRUCT_STAT sbuf;
4967 TALLOC_CTX *ctx = talloc_tos();
4969 START_PROFILE(SMBmkdir);
4971 srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &directory,
4972 smb_buf(req->inbuf) + 1, 0,
4973 STR_TERMINATE, &status);
4974 if (!NT_STATUS_IS_OK(status)) {
4975 reply_nterror(req, status);
4976 END_PROFILE(SMBmkdir);
4977 return;
4980 status = resolve_dfspath(ctx, conn,
4981 req->flags2 & FLAGS2_DFS_PATHNAMES,
4982 directory,
4983 &directory);
4984 if (!NT_STATUS_IS_OK(status)) {
4985 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4986 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
4987 ERRSRV, ERRbadpath);
4988 END_PROFILE(SMBmkdir);
4989 return;
4991 reply_nterror(req, status);
4992 END_PROFILE(SMBmkdir);
4993 return;
4996 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
4997 if (!NT_STATUS_IS_OK(status)) {
4998 reply_nterror(req, status);
4999 END_PROFILE(SMBmkdir);
5000 return;
5003 status = check_name(conn, directory);
5004 if (!NT_STATUS_IS_OK(status)) {
5005 reply_nterror(req, status);
5006 END_PROFILE(SMBmkdir);
5007 return;
5010 status = create_directory(conn, req, directory);
5012 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5014 if (!NT_STATUS_IS_OK(status)) {
5016 if (!use_nt_status()
5017 && NT_STATUS_EQUAL(status,
5018 NT_STATUS_OBJECT_NAME_COLLISION)) {
5020 * Yes, in the DOS error code case we get a
5021 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5022 * samba4 torture test.
5024 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5027 reply_nterror(req, status);
5028 END_PROFILE(SMBmkdir);
5029 return;
5032 reply_outbuf(req, 0, 0);
5034 DEBUG( 3, ( "mkdir %s\n", directory ) );
5036 END_PROFILE(SMBmkdir);
5037 return;
5040 /****************************************************************************
5041 Static function used by reply_rmdir to delete an entire directory
5042 tree recursively. Return True on ok, False on fail.
5043 ****************************************************************************/
5045 static bool recursive_rmdir(TALLOC_CTX *ctx,
5046 connection_struct *conn,
5047 char *directory)
5049 const char *dname = NULL;
5050 bool ret = True;
5051 long offset = 0;
5052 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, directory,
5053 NULL, 0);
5055 if(dir_hnd == NULL)
5056 return False;
5058 while((dname = ReadDirName(dir_hnd, &offset))) {
5059 char *fullname = NULL;
5060 SMB_STRUCT_STAT st;
5062 if (ISDOT(dname) || ISDOTDOT(dname)) {
5063 continue;
5066 if (!is_visible_file(conn, directory, dname, &st, False)) {
5067 continue;
5070 /* Construct the full name. */
5071 fullname = talloc_asprintf(ctx,
5072 "%s/%s",
5073 directory,
5074 dname);
5075 if (!fullname) {
5076 errno = ENOMEM;
5077 ret = False;
5078 break;
5081 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5082 ret = False;
5083 break;
5086 if(st.st_mode & S_IFDIR) {
5087 if(!recursive_rmdir(ctx, conn, fullname)) {
5088 ret = False;
5089 break;
5091 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5092 ret = False;
5093 break;
5095 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5096 ret = False;
5097 break;
5099 TALLOC_FREE(fullname);
5101 TALLOC_FREE(dir_hnd);
5102 return ret;
5105 /****************************************************************************
5106 The internals of the rmdir code - called elsewhere.
5107 ****************************************************************************/
5109 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
5110 connection_struct *conn,
5111 const char *directory)
5113 int ret;
5114 SMB_STRUCT_STAT st;
5116 /* Might be a symlink. */
5117 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
5118 return map_nt_error_from_unix(errno);
5121 if (S_ISLNK(st.st_mode)) {
5122 /* Is what it points to a directory ? */
5123 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
5124 return map_nt_error_from_unix(errno);
5126 if (!(S_ISDIR(st.st_mode))) {
5127 return NT_STATUS_NOT_A_DIRECTORY;
5129 ret = SMB_VFS_UNLINK(conn,directory);
5130 } else {
5131 ret = SMB_VFS_RMDIR(conn,directory);
5133 if (ret == 0) {
5134 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5135 FILE_NOTIFY_CHANGE_DIR_NAME,
5136 directory);
5137 return NT_STATUS_OK;
5140 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5142 * Check to see if the only thing in this directory are
5143 * vetoed files/directories. If so then delete them and
5144 * retry. If we fail to delete any of them (and we *don't*
5145 * do a recursive delete) then fail the rmdir.
5147 const char *dname;
5148 long dirpos = 0;
5149 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5150 directory, NULL, 0);
5152 if(dir_hnd == NULL) {
5153 errno = ENOTEMPTY;
5154 goto err;
5157 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
5158 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5159 continue;
5160 if (!is_visible_file(conn, directory, dname, &st, False))
5161 continue;
5162 if(!IS_VETO_PATH(conn, dname)) {
5163 TALLOC_FREE(dir_hnd);
5164 errno = ENOTEMPTY;
5165 goto err;
5169 /* We only have veto files/directories.
5170 * Are we allowed to delete them ? */
5172 if(!lp_recursive_veto_delete(SNUM(conn))) {
5173 TALLOC_FREE(dir_hnd);
5174 errno = ENOTEMPTY;
5175 goto err;
5178 /* Do a recursive delete. */
5179 RewindDir(dir_hnd,&dirpos);
5180 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
5181 char *fullname = NULL;
5183 if (ISDOT(dname) || ISDOTDOT(dname)) {
5184 continue;
5186 if (!is_visible_file(conn, directory, dname, &st, False)) {
5187 continue;
5190 fullname = talloc_asprintf(ctx,
5191 "%s/%s",
5192 directory,
5193 dname);
5195 if(!fullname) {
5196 errno = ENOMEM;
5197 break;
5200 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5201 break;
5203 if(st.st_mode & S_IFDIR) {
5204 if(!recursive_rmdir(ctx, conn, fullname)) {
5205 break;
5207 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5208 break;
5210 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5211 break;
5213 TALLOC_FREE(fullname);
5215 TALLOC_FREE(dir_hnd);
5216 /* Retry the rmdir */
5217 ret = SMB_VFS_RMDIR(conn,directory);
5220 err:
5222 if (ret != 0) {
5223 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5224 "%s\n", directory,strerror(errno)));
5225 return map_nt_error_from_unix(errno);
5228 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5229 FILE_NOTIFY_CHANGE_DIR_NAME,
5230 directory);
5232 return NT_STATUS_OK;
5235 /****************************************************************************
5236 Reply to a rmdir.
5237 ****************************************************************************/
5239 void reply_rmdir(struct smb_request *req)
5241 connection_struct *conn = req->conn;
5242 char *directory = NULL;
5243 SMB_STRUCT_STAT sbuf;
5244 NTSTATUS status;
5245 TALLOC_CTX *ctx = talloc_tos();
5247 START_PROFILE(SMBrmdir);
5249 srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &directory,
5250 smb_buf(req->inbuf) + 1, 0,
5251 STR_TERMINATE, &status);
5252 if (!NT_STATUS_IS_OK(status)) {
5253 reply_nterror(req, status);
5254 END_PROFILE(SMBrmdir);
5255 return;
5258 status = resolve_dfspath(ctx, conn,
5259 req->flags2 & FLAGS2_DFS_PATHNAMES,
5260 directory,
5261 &directory);
5262 if (!NT_STATUS_IS_OK(status)) {
5263 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5264 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5265 ERRSRV, ERRbadpath);
5266 END_PROFILE(SMBrmdir);
5267 return;
5269 reply_nterror(req, status);
5270 END_PROFILE(SMBrmdir);
5271 return;
5274 status = unix_convert(ctx, conn, directory, False, &directory,
5275 NULL, &sbuf);
5276 if (!NT_STATUS_IS_OK(status)) {
5277 reply_nterror(req, status);
5278 END_PROFILE(SMBrmdir);
5279 return;
5282 status = check_name(conn, directory);
5283 if (!NT_STATUS_IS_OK(status)) {
5284 reply_nterror(req, status);
5285 END_PROFILE(SMBrmdir);
5286 return;
5289 dptr_closepath(directory, req->smbpid);
5290 status = rmdir_internals(ctx, conn, directory);
5291 if (!NT_STATUS_IS_OK(status)) {
5292 reply_nterror(req, status);
5293 END_PROFILE(SMBrmdir);
5294 return;
5297 reply_outbuf(req, 0, 0);
5299 DEBUG( 3, ( "rmdir %s\n", directory ) );
5301 END_PROFILE(SMBrmdir);
5302 return;
5305 /*******************************************************************
5306 Resolve wildcards in a filename rename.
5307 ********************************************************************/
5309 static bool resolve_wildcards(TALLOC_CTX *ctx,
5310 const char *name1,
5311 const char *name2,
5312 char **pp_newname)
5314 char *name2_copy = NULL;
5315 char *root1 = NULL;
5316 char *root2 = NULL;
5317 char *ext1 = NULL;
5318 char *ext2 = NULL;
5319 char *p,*p2, *pname1, *pname2;
5321 name2_copy = talloc_strdup(ctx, name2);
5322 if (!name2_copy) {
5323 return False;
5326 pname1 = strrchr_m(name1,'/');
5327 pname2 = strrchr_m(name2_copy,'/');
5329 if (!pname1 || !pname2) {
5330 return False;
5333 /* Truncate the copy of name2 at the last '/' */
5334 *pname2 = '\0';
5336 /* Now go past the '/' */
5337 pname1++;
5338 pname2++;
5340 root1 = talloc_strdup(ctx, pname1);
5341 root2 = talloc_strdup(ctx, pname2);
5343 if (!root1 || !root2) {
5344 return False;
5347 p = strrchr_m(root1,'.');
5348 if (p) {
5349 *p = 0;
5350 ext1 = talloc_strdup(ctx, p+1);
5351 } else {
5352 ext1 = talloc_strdup(ctx, "");
5354 p = strrchr_m(root2,'.');
5355 if (p) {
5356 *p = 0;
5357 ext2 = talloc_strdup(ctx, p+1);
5358 } else {
5359 ext2 = talloc_strdup(ctx, "");
5362 if (!ext1 || !ext2) {
5363 return False;
5366 p = root1;
5367 p2 = root2;
5368 while (*p2) {
5369 if (*p2 == '?') {
5370 /* Hmmm. Should this be mb-aware ? */
5371 *p2 = *p;
5372 p2++;
5373 } else if (*p2 == '*') {
5374 *p2 = '\0';
5375 root2 = talloc_asprintf(ctx, "%s%s",
5376 root2,
5378 if (!root2) {
5379 return False;
5381 break;
5382 } else {
5383 p2++;
5385 if (*p) {
5386 p++;
5390 p = ext1;
5391 p2 = ext2;
5392 while (*p2) {
5393 if (*p2 == '?') {
5394 /* Hmmm. Should this be mb-aware ? */
5395 *p2 = *p;
5396 p2++;
5397 } else if (*p2 == '*') {
5398 *p2 = '\0';
5399 ext2 = talloc_asprintf(ctx, "%s%s",
5400 ext2,
5402 if (!ext2) {
5403 return False;
5405 break;
5406 } else {
5407 p2++;
5409 if (*p) {
5410 p++;
5414 if (*ext2) {
5415 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5416 name2_copy,
5417 root2,
5418 ext2);
5419 } else {
5420 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5421 name2_copy,
5422 root2);
5425 if (!*pp_newname) {
5426 return False;
5429 return True;
5432 /****************************************************************************
5433 Ensure open files have their names updated. Updated to notify other smbd's
5434 asynchronously.
5435 ****************************************************************************/
5437 static void rename_open_files(connection_struct *conn,
5438 struct share_mode_lock *lck,
5439 const char *newname)
5441 files_struct *fsp;
5442 bool did_rename = False;
5444 for(fsp = file_find_di_first(lck->id); fsp;
5445 fsp = file_find_di_next(fsp)) {
5446 /* fsp_name is a relative path under the fsp. To change this for other
5447 sharepaths we need to manipulate relative paths. */
5448 /* TODO - create the absolute path and manipulate the newname
5449 relative to the sharepath. */
5450 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5451 continue;
5453 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5454 fsp->fnum, file_id_string_tos(&fsp->file_id),
5455 fsp->fsp_name, newname ));
5456 string_set(&fsp->fsp_name, newname);
5457 did_rename = True;
5460 if (!did_rename) {
5461 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5462 file_id_string_tos(&lck->id), newname ));
5465 /* Send messages to all smbd's (not ourself) that the name has changed. */
5466 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5467 newname);
5470 /****************************************************************************
5471 We need to check if the source path is a parent directory of the destination
5472 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5473 refuse the rename with a sharing violation. Under UNIX the above call can
5474 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5475 probably need to check that the client is a Windows one before disallowing
5476 this as a UNIX client (one with UNIX extensions) can know the source is a
5477 symlink and make this decision intelligently. Found by an excellent bug
5478 report from <AndyLiebman@aol.com>.
5479 ****************************************************************************/
5481 static bool rename_path_prefix_equal(const char *src, const char *dest)
5483 const char *psrc = src;
5484 const char *pdst = dest;
5485 size_t slen;
5487 if (psrc[0] == '.' && psrc[1] == '/') {
5488 psrc += 2;
5490 if (pdst[0] == '.' && pdst[1] == '/') {
5491 pdst += 2;
5493 if ((slen = strlen(psrc)) > strlen(pdst)) {
5494 return False;
5496 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5500 * Do the notify calls from a rename
5503 static void notify_rename(connection_struct *conn, bool is_dir,
5504 const char *oldpath, const char *newpath)
5506 char *olddir, *newdir;
5507 const char *oldname, *newname;
5508 uint32 mask;
5510 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5511 : FILE_NOTIFY_CHANGE_FILE_NAME;
5513 if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
5514 || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
5515 TALLOC_FREE(olddir);
5516 return;
5519 if (strcmp(olddir, newdir) == 0) {
5520 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
5521 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
5523 else {
5524 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
5525 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
5527 TALLOC_FREE(olddir);
5528 TALLOC_FREE(newdir);
5530 /* this is a strange one. w2k3 gives an additional event for
5531 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5532 files, but not directories */
5533 if (!is_dir) {
5534 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5535 FILE_NOTIFY_CHANGE_ATTRIBUTES
5536 |FILE_NOTIFY_CHANGE_CREATION,
5537 newpath);
5541 /****************************************************************************
5542 Rename an open file - given an fsp.
5543 ****************************************************************************/
5545 NTSTATUS rename_internals_fsp(connection_struct *conn,
5546 files_struct *fsp,
5547 char *newname,
5548 const char *newname_last_component,
5549 uint32 attrs,
5550 bool replace_if_exists)
5552 TALLOC_CTX *ctx = talloc_tos();
5553 SMB_STRUCT_STAT sbuf, sbuf1;
5554 NTSTATUS status = NT_STATUS_OK;
5555 struct share_mode_lock *lck = NULL;
5556 bool dst_exists, old_is_stream, new_is_stream;
5558 ZERO_STRUCT(sbuf);
5560 status = check_name(conn, newname);
5561 if (!NT_STATUS_IS_OK(status)) {
5562 return status;
5565 /* Ensure newname contains a '/' */
5566 if(strrchr_m(newname,'/') == 0) {
5567 newname = talloc_asprintf(ctx,
5568 "./%s",
5569 newname);
5570 if (!newname) {
5571 return NT_STATUS_NO_MEMORY;
5576 * Check for special case with case preserving and not
5577 * case sensitive. If the old last component differs from the original
5578 * last component only by case, then we should allow
5579 * the rename (user is trying to change the case of the
5580 * filename).
5583 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5584 strequal(newname, fsp->fsp_name)) {
5585 char *p;
5586 char *newname_modified_last_component = NULL;
5589 * Get the last component of the modified name.
5590 * Note that we guarantee that newname contains a '/'
5591 * character above.
5593 p = strrchr_m(newname,'/');
5594 newname_modified_last_component = talloc_strdup(ctx,
5595 p+1);
5596 if (!newname_modified_last_component) {
5597 return NT_STATUS_NO_MEMORY;
5600 if(strcsequal(newname_modified_last_component,
5601 newname_last_component) == False) {
5603 * Replace the modified last component with
5604 * the original.
5606 *p = '\0'; /* Truncate at the '/' */
5607 newname = talloc_asprintf(ctx,
5608 "%s/%s",
5609 newname,
5610 newname_last_component);
5615 * If the src and dest names are identical - including case,
5616 * don't do the rename, just return success.
5619 if (strcsequal(fsp->fsp_name, newname)) {
5620 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5621 newname));
5622 return NT_STATUS_OK;
5625 old_is_stream = is_ntfs_stream_name(fsp->fsp_name);
5626 new_is_stream = is_ntfs_stream_name(newname);
5628 /* Return the correct error code if both names aren't streams. */
5629 if (!old_is_stream && new_is_stream) {
5630 return NT_STATUS_OBJECT_NAME_INVALID;
5633 if (old_is_stream && !new_is_stream) {
5634 return NT_STATUS_INVALID_PARAMETER;
5638 * Have vfs_object_exist also fill sbuf1
5640 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
5642 if(!replace_if_exists && dst_exists) {
5643 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5644 fsp->fsp_name,newname));
5645 return NT_STATUS_OBJECT_NAME_COLLISION;
5648 if (dst_exists) {
5649 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5650 files_struct *dst_fsp = file_find_di_first(fileid);
5651 /* The file can be open when renaming a stream */
5652 if (dst_fsp && !new_is_stream) {
5653 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5654 return NT_STATUS_ACCESS_DENIED;
5658 /* Ensure we have a valid stat struct for the source. */
5659 if (fsp->fh->fd != -1) {
5660 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
5661 return map_nt_error_from_unix(errno);
5663 } else {
5664 int ret = -1;
5665 if (fsp->posix_open) {
5666 ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf);
5667 } else {
5668 ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf);
5670 if (ret == -1) {
5671 return map_nt_error_from_unix(errno);
5675 status = can_rename(conn, fsp, attrs, &sbuf);
5677 if (!NT_STATUS_IS_OK(status)) {
5678 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5679 nt_errstr(status), fsp->fsp_name,newname));
5680 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5681 status = NT_STATUS_ACCESS_DENIED;
5682 return status;
5685 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5686 return NT_STATUS_ACCESS_DENIED;
5689 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5690 NULL);
5693 * We have the file open ourselves, so not being able to get the
5694 * corresponding share mode lock is a fatal error.
5697 SMB_ASSERT(lck != NULL);
5699 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5700 uint32 create_options = fsp->fh->private_options;
5702 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5703 fsp->fsp_name,newname));
5705 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5707 rename_open_files(conn, lck, newname);
5710 * A rename acts as a new file create w.r.t. allowing an initial delete
5711 * on close, probably because in Windows there is a new handle to the
5712 * new file. If initial delete on close was requested but not
5713 * originally set, we need to set it here. This is probably not 100% correct,
5714 * but will work for the CIFSFS client which in non-posix mode
5715 * depends on these semantics. JRA.
5718 if (create_options & FILE_DELETE_ON_CLOSE) {
5719 status = can_set_delete_on_close(fsp, True, 0);
5721 if (NT_STATUS_IS_OK(status)) {
5722 /* Note that here we set the *inital* delete on close flag,
5723 * not the regular one. The magic gets handled in close. */
5724 fsp->initial_delete_on_close = True;
5727 TALLOC_FREE(lck);
5728 return NT_STATUS_OK;
5731 TALLOC_FREE(lck);
5733 if (errno == ENOTDIR || errno == EISDIR) {
5734 status = NT_STATUS_OBJECT_NAME_COLLISION;
5735 } else {
5736 status = map_nt_error_from_unix(errno);
5739 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5740 nt_errstr(status), fsp->fsp_name,newname));
5742 return status;
5745 /****************************************************************************
5746 The guts of the rename command, split out so it may be called by the NT SMB
5747 code.
5748 ****************************************************************************/
5750 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5751 connection_struct *conn,
5752 struct smb_request *req,
5753 const char *name_in,
5754 const char *newname_in,
5755 uint32 attrs,
5756 bool replace_if_exists,
5757 bool src_has_wild,
5758 bool dest_has_wild,
5759 uint32_t access_mask)
5761 char *directory = NULL;
5762 char *mask = NULL;
5763 char *last_component_src = NULL;
5764 char *last_component_dest = NULL;
5765 char *name = NULL;
5766 char *newname = NULL;
5767 char *p;
5768 int count=0;
5769 NTSTATUS status = NT_STATUS_OK;
5770 SMB_STRUCT_STAT sbuf1, sbuf2;
5771 struct smb_Dir *dir_hnd = NULL;
5772 const char *dname;
5773 long offset = 0;
5774 bool posix_pathnames = lp_posix_pathnames();
5776 ZERO_STRUCT(sbuf1);
5777 ZERO_STRUCT(sbuf2);
5779 status = unix_convert(ctx, conn, name_in, src_has_wild, &name,
5780 &last_component_src, &sbuf1);
5781 if (!NT_STATUS_IS_OK(status)) {
5782 return status;
5785 status = unix_convert(ctx, conn, newname_in, dest_has_wild, &newname,
5786 &last_component_dest, &sbuf2);
5787 if (!NT_STATUS_IS_OK(status)) {
5788 return status;
5792 * Split the old name into directory and last component
5793 * strings. Note that unix_convert may have stripped off a
5794 * leading ./ from both name and newname if the rename is
5795 * at the root of the share. We need to make sure either both
5796 * name and newname contain a / character or neither of them do
5797 * as this is checked in resolve_wildcards().
5800 p = strrchr_m(name,'/');
5801 if (!p) {
5802 directory = talloc_strdup(ctx, ".");
5803 if (!directory) {
5804 return NT_STATUS_NO_MEMORY;
5806 mask = name;
5807 } else {
5808 *p = 0;
5809 directory = talloc_strdup(ctx, name);
5810 if (!directory) {
5811 return NT_STATUS_NO_MEMORY;
5813 mask = p+1;
5814 *p = '/'; /* Replace needed for exceptional test below. */
5818 * We should only check the mangled cache
5819 * here if unix_convert failed. This means
5820 * that the path in 'mask' doesn't exist
5821 * on the file system and so we need to look
5822 * for a possible mangle. This patch from
5823 * Tine Smukavec <valentin.smukavec@hermes.si>.
5826 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5827 char *new_mask = NULL;
5828 mangle_lookup_name_from_8_3(ctx,
5829 mask,
5830 &new_mask,
5831 conn->params );
5832 if (new_mask) {
5833 mask = new_mask;
5837 if (!src_has_wild) {
5838 files_struct *fsp;
5841 * No wildcards - just process the one file.
5843 bool is_short_name = mangle_is_8_3(name, True, conn->params);
5845 /* Add a terminating '/' to the directory name. */
5846 directory = talloc_asprintf_append(directory,
5847 "/%s",
5848 mask);
5849 if (!directory) {
5850 return NT_STATUS_NO_MEMORY;
5853 /* Ensure newname contains a '/' also */
5854 if(strrchr_m(newname,'/') == 0) {
5855 newname = talloc_asprintf(ctx,
5856 "./%s",
5857 newname);
5858 if (!newname) {
5859 return NT_STATUS_NO_MEMORY;
5863 DEBUG(3, ("rename_internals: case_sensitive = %d, "
5864 "case_preserve = %d, short case preserve = %d, "
5865 "directory = %s, newname = %s, "
5866 "last_component_dest = %s, is_8_3 = %d\n",
5867 conn->case_sensitive, conn->case_preserve,
5868 conn->short_case_preserve, directory,
5869 newname, last_component_dest, is_short_name));
5871 /* The dest name still may have wildcards. */
5872 if (dest_has_wild) {
5873 char *mod_newname = NULL;
5874 if (!resolve_wildcards(ctx,
5875 directory,newname,&mod_newname)) {
5876 DEBUG(6, ("rename_internals: resolve_wildcards "
5877 "%s %s failed\n",
5878 directory,
5879 newname));
5880 return NT_STATUS_NO_MEMORY;
5882 newname = mod_newname;
5885 ZERO_STRUCT(sbuf1);
5886 if (posix_pathnames) {
5887 SMB_VFS_LSTAT(conn, directory, &sbuf1);
5888 } else {
5889 SMB_VFS_STAT(conn, directory, &sbuf1);
5892 status = S_ISDIR(sbuf1.st_mode) ?
5893 open_directory(conn, req, directory, &sbuf1,
5894 access_mask,
5895 FILE_SHARE_READ|FILE_SHARE_WRITE,
5896 FILE_OPEN,
5898 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0,
5899 NULL,
5900 &fsp)
5901 : open_file_ntcreate(conn, req, directory, &sbuf1,
5902 access_mask,
5903 FILE_SHARE_READ|FILE_SHARE_WRITE,
5904 FILE_OPEN,
5906 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0,
5908 NULL,
5909 &fsp);
5911 if (!NT_STATUS_IS_OK(status)) {
5912 DEBUG(3, ("Could not open rename source %s: %s\n",
5913 directory, nt_errstr(status)));
5914 return status;
5917 status = rename_internals_fsp(conn, fsp, newname,
5918 last_component_dest,
5919 attrs, replace_if_exists);
5921 close_file(fsp, NORMAL_CLOSE);
5923 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
5924 nt_errstr(status), directory,newname));
5926 return status;
5930 * Wildcards - process each file that matches.
5932 if (strequal(mask,"????????.???")) {
5933 mask[0] = '*';
5934 mask[1] = '\0';
5937 status = check_name(conn, directory);
5938 if (!NT_STATUS_IS_OK(status)) {
5939 return status;
5942 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, attrs);
5943 if (dir_hnd == NULL) {
5944 return map_nt_error_from_unix(errno);
5947 status = NT_STATUS_NO_SUCH_FILE;
5949 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
5950 * - gentest fix. JRA
5953 while ((dname = ReadDirName(dir_hnd, &offset))) {
5954 files_struct *fsp = NULL;
5955 char *fname = NULL;
5956 char *destname = NULL;
5957 bool sysdir_entry = False;
5959 /* Quick check for "." and ".." */
5960 if (ISDOT(dname) || ISDOTDOT(dname)) {
5961 if (attrs & aDIR) {
5962 sysdir_entry = True;
5963 } else {
5964 continue;
5968 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5969 continue;
5972 if(!mask_match(dname, mask, conn->case_sensitive)) {
5973 continue;
5976 if (sysdir_entry) {
5977 status = NT_STATUS_OBJECT_NAME_INVALID;
5978 break;
5981 fname = talloc_asprintf(ctx,
5982 "%s/%s",
5983 directory,
5984 dname);
5985 if (!fname) {
5986 return NT_STATUS_NO_MEMORY;
5989 if (!resolve_wildcards(ctx,
5990 fname,newname,&destname)) {
5991 DEBUG(6, ("resolve_wildcards %s %s failed\n",
5992 fname, destname));
5993 TALLOC_FREE(fname);
5994 continue;
5996 if (!destname) {
5997 return NT_STATUS_NO_MEMORY;
6000 ZERO_STRUCT(sbuf1);
6001 if (posix_pathnames) {
6002 SMB_VFS_LSTAT(conn, fname, &sbuf1);
6003 } else {
6004 SMB_VFS_STAT(conn, fname, &sbuf1);
6007 status = S_ISDIR(sbuf1.st_mode) ?
6008 open_directory(conn, req, fname, &sbuf1,
6009 access_mask,
6010 FILE_SHARE_READ|FILE_SHARE_WRITE,
6011 FILE_OPEN,
6013 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0,
6014 NULL,
6015 &fsp)
6016 : open_file_ntcreate(conn, req, fname, &sbuf1,
6017 access_mask,
6018 FILE_SHARE_READ|FILE_SHARE_WRITE,
6019 FILE_OPEN,
6021 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0,
6023 NULL,
6024 &fsp);
6026 if (!NT_STATUS_IS_OK(status)) {
6027 DEBUG(3,("rename_internals: open_file_ntcreate "
6028 "returned %s rename %s -> %s\n",
6029 nt_errstr(status), directory, newname));
6030 break;
6033 status = rename_internals_fsp(conn, fsp, destname, dname,
6034 attrs, replace_if_exists);
6036 close_file(fsp, NORMAL_CLOSE);
6038 if (!NT_STATUS_IS_OK(status)) {
6039 DEBUG(3, ("rename_internals_fsp returned %s for "
6040 "rename %s -> %s\n", nt_errstr(status),
6041 directory, newname));
6042 break;
6045 count++;
6047 DEBUG(3,("rename_internals: doing rename on %s -> "
6048 "%s\n",fname,destname));
6050 TALLOC_FREE(fname);
6051 TALLOC_FREE(destname);
6053 TALLOC_FREE(dir_hnd);
6055 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6056 status = map_nt_error_from_unix(errno);
6059 return status;
6062 /****************************************************************************
6063 Reply to a mv.
6064 ****************************************************************************/
6066 void reply_mv(struct smb_request *req)
6068 connection_struct *conn = req->conn;
6069 char *name = NULL;
6070 char *newname = NULL;
6071 char *p;
6072 uint32 attrs;
6073 NTSTATUS status;
6074 bool src_has_wcard = False;
6075 bool dest_has_wcard = False;
6076 TALLOC_CTX *ctx = talloc_tos();
6078 START_PROFILE(SMBmv);
6080 if (req->wct < 1) {
6081 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6082 END_PROFILE(SMBmv);
6083 return;
6086 attrs = SVAL(req->inbuf,smb_vwv0);
6088 p = smb_buf(req->inbuf) + 1;
6089 p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name, p,
6090 0, STR_TERMINATE, &status,
6091 &src_has_wcard);
6092 if (!NT_STATUS_IS_OK(status)) {
6093 reply_nterror(req, status);
6094 END_PROFILE(SMBmv);
6095 return;
6097 p++;
6098 p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &newname, p,
6099 0, STR_TERMINATE, &status,
6100 &dest_has_wcard);
6101 if (!NT_STATUS_IS_OK(status)) {
6102 reply_nterror(req, status);
6103 END_PROFILE(SMBmv);
6104 return;
6107 status = resolve_dfspath_wcard(ctx, conn,
6108 req->flags2 & FLAGS2_DFS_PATHNAMES,
6109 name,
6110 &name,
6111 &src_has_wcard);
6112 if (!NT_STATUS_IS_OK(status)) {
6113 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6114 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6115 ERRSRV, ERRbadpath);
6116 END_PROFILE(SMBmv);
6117 return;
6119 reply_nterror(req, status);
6120 END_PROFILE(SMBmv);
6121 return;
6124 status = resolve_dfspath_wcard(ctx, conn,
6125 req->flags2 & FLAGS2_DFS_PATHNAMES,
6126 newname,
6127 &newname,
6128 &dest_has_wcard);
6129 if (!NT_STATUS_IS_OK(status)) {
6130 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6131 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6132 ERRSRV, ERRbadpath);
6133 END_PROFILE(SMBmv);
6134 return;
6136 reply_nterror(req, status);
6137 END_PROFILE(SMBmv);
6138 return;
6141 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
6143 status = rename_internals(ctx, conn, req, name, newname, attrs, False,
6144 src_has_wcard, dest_has_wcard, DELETE_ACCESS);
6145 if (!NT_STATUS_IS_OK(status)) {
6146 if (open_was_deferred(req->mid)) {
6147 /* We have re-scheduled this call. */
6148 END_PROFILE(SMBmv);
6149 return;
6151 reply_nterror(req, status);
6152 END_PROFILE(SMBmv);
6153 return;
6156 reply_outbuf(req, 0, 0);
6158 END_PROFILE(SMBmv);
6159 return;
6162 /*******************************************************************
6163 Copy a file as part of a reply_copy.
6164 ******************************************************************/
6167 * TODO: check error codes on all callers
6170 NTSTATUS copy_file(TALLOC_CTX *ctx,
6171 connection_struct *conn,
6172 const char *src,
6173 const char *dest1,
6174 int ofun,
6175 int count,
6176 bool target_is_directory)
6178 SMB_STRUCT_STAT src_sbuf, sbuf2;
6179 SMB_OFF_T ret=-1;
6180 files_struct *fsp1,*fsp2;
6181 char *dest = NULL;
6182 uint32 dosattrs;
6183 uint32 new_create_disposition;
6184 NTSTATUS status;
6186 dest = talloc_strdup(ctx, dest1);
6187 if (!dest) {
6188 return NT_STATUS_NO_MEMORY;
6190 if (target_is_directory) {
6191 const char *p = strrchr_m(src,'/');
6192 if (p) {
6193 p++;
6194 } else {
6195 p = src;
6197 dest = talloc_asprintf_append(dest,
6198 "/%s",
6200 if (!dest) {
6201 return NT_STATUS_NO_MEMORY;
6205 if (!vfs_file_exist(conn,src,&src_sbuf)) {
6206 TALLOC_FREE(dest);
6207 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6210 if (!target_is_directory && count) {
6211 new_create_disposition = FILE_OPEN;
6212 } else {
6213 if (!map_open_params_to_ntcreate(dest1,0,ofun,
6214 NULL, NULL, &new_create_disposition, NULL)) {
6215 TALLOC_FREE(dest);
6216 return NT_STATUS_INVALID_PARAMETER;
6220 status = open_file_ntcreate(conn, NULL, src, &src_sbuf,
6221 FILE_GENERIC_READ,
6222 FILE_SHARE_READ|FILE_SHARE_WRITE,
6223 FILE_OPEN,
6225 FILE_ATTRIBUTE_NORMAL,
6226 INTERNAL_OPEN_ONLY,
6227 NULL, &fsp1);
6229 if (!NT_STATUS_IS_OK(status)) {
6230 TALLOC_FREE(dest);
6231 return status;
6234 dosattrs = dos_mode(conn, src, &src_sbuf);
6235 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
6236 ZERO_STRUCTP(&sbuf2);
6239 status = open_file_ntcreate(conn, NULL, dest, &sbuf2,
6240 FILE_GENERIC_WRITE,
6241 FILE_SHARE_READ|FILE_SHARE_WRITE,
6242 new_create_disposition,
6244 dosattrs,
6245 INTERNAL_OPEN_ONLY,
6246 NULL, &fsp2);
6248 TALLOC_FREE(dest);
6250 if (!NT_STATUS_IS_OK(status)) {
6251 close_file(fsp1,ERROR_CLOSE);
6252 return status;
6255 if ((ofun&3) == 1) {
6256 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6257 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6259 * Stop the copy from occurring.
6261 ret = -1;
6262 src_sbuf.st_size = 0;
6266 if (src_sbuf.st_size) {
6267 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
6270 close_file(fsp1,NORMAL_CLOSE);
6272 /* Ensure the modtime is set correctly on the destination file. */
6273 set_close_write_time(fsp2, get_mtimespec(&src_sbuf));
6276 * As we are opening fsp1 read-only we only expect
6277 * an error on close on fsp2 if we are out of space.
6278 * Thus we don't look at the error return from the
6279 * close of fsp1.
6281 status = close_file(fsp2,NORMAL_CLOSE);
6283 if (!NT_STATUS_IS_OK(status)) {
6284 return status;
6287 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
6288 return NT_STATUS_DISK_FULL;
6291 return NT_STATUS_OK;
6294 /****************************************************************************
6295 Reply to a file copy.
6296 ****************************************************************************/
6298 void reply_copy(struct smb_request *req)
6300 connection_struct *conn = req->conn;
6301 char *name = NULL;
6302 char *newname = NULL;
6303 char *directory = NULL;
6304 char *mask = NULL;
6305 char *p;
6306 int count=0;
6307 int error = ERRnoaccess;
6308 int err = 0;
6309 int tid2;
6310 int ofun;
6311 int flags;
6312 bool target_is_directory=False;
6313 bool source_has_wild = False;
6314 bool dest_has_wild = False;
6315 SMB_STRUCT_STAT sbuf1, sbuf2;
6316 NTSTATUS status;
6317 TALLOC_CTX *ctx = talloc_tos();
6319 START_PROFILE(SMBcopy);
6321 if (req->wct < 3) {
6322 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6323 END_PROFILE(SMBcopy);
6324 return;
6327 tid2 = SVAL(req->inbuf,smb_vwv0);
6328 ofun = SVAL(req->inbuf,smb_vwv1);
6329 flags = SVAL(req->inbuf,smb_vwv2);
6331 p = smb_buf(req->inbuf);
6332 p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name, p,
6333 0, STR_TERMINATE, &status,
6334 &source_has_wild);
6335 if (!NT_STATUS_IS_OK(status)) {
6336 reply_nterror(req, status);
6337 END_PROFILE(SMBcopy);
6338 return;
6340 p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &newname, p,
6341 0, STR_TERMINATE, &status,
6342 &dest_has_wild);
6343 if (!NT_STATUS_IS_OK(status)) {
6344 reply_nterror(req, status);
6345 END_PROFILE(SMBcopy);
6346 return;
6349 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
6351 if (tid2 != conn->cnum) {
6352 /* can't currently handle inter share copies XXXX */
6353 DEBUG(3,("Rejecting inter-share copy\n"));
6354 reply_doserror(req, ERRSRV, ERRinvdevice);
6355 END_PROFILE(SMBcopy);
6356 return;
6359 status = resolve_dfspath_wcard(ctx, conn,
6360 req->flags2 & FLAGS2_DFS_PATHNAMES,
6361 name,
6362 &name,
6363 &source_has_wild);
6364 if (!NT_STATUS_IS_OK(status)) {
6365 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6366 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6367 ERRSRV, ERRbadpath);
6368 END_PROFILE(SMBcopy);
6369 return;
6371 reply_nterror(req, status);
6372 END_PROFILE(SMBcopy);
6373 return;
6376 status = resolve_dfspath_wcard(ctx, conn,
6377 req->flags2 & FLAGS2_DFS_PATHNAMES,
6378 newname,
6379 &newname,
6380 &dest_has_wild);
6381 if (!NT_STATUS_IS_OK(status)) {
6382 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6383 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6384 ERRSRV, ERRbadpath);
6385 END_PROFILE(SMBcopy);
6386 return;
6388 reply_nterror(req, status);
6389 END_PROFILE(SMBcopy);
6390 return;
6393 status = unix_convert(ctx, conn, name, source_has_wild,
6394 &name, NULL, &sbuf1);
6395 if (!NT_STATUS_IS_OK(status)) {
6396 reply_nterror(req, status);
6397 END_PROFILE(SMBcopy);
6398 return;
6401 status = unix_convert(ctx, conn, newname, dest_has_wild,
6402 &newname, NULL, &sbuf2);
6403 if (!NT_STATUS_IS_OK(status)) {
6404 reply_nterror(req, status);
6405 END_PROFILE(SMBcopy);
6406 return;
6409 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
6411 if ((flags&1) && target_is_directory) {
6412 reply_doserror(req, ERRDOS, ERRbadfile);
6413 END_PROFILE(SMBcopy);
6414 return;
6417 if ((flags&2) && !target_is_directory) {
6418 reply_doserror(req, ERRDOS, ERRbadpath);
6419 END_PROFILE(SMBcopy);
6420 return;
6423 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
6424 /* wants a tree copy! XXXX */
6425 DEBUG(3,("Rejecting tree copy\n"));
6426 reply_doserror(req, ERRSRV, ERRerror);
6427 END_PROFILE(SMBcopy);
6428 return;
6431 p = strrchr_m(name,'/');
6432 if (!p) {
6433 directory = talloc_strdup(ctx, "./");
6434 if (!directory) {
6435 reply_nterror(req, NT_STATUS_NO_MEMORY);
6436 END_PROFILE(SMBcopy);
6437 return;
6439 mask = name;
6440 } else {
6441 *p = 0;
6442 directory = talloc_strdup(ctx, name);
6443 if (!directory) {
6444 reply_nterror(req, NT_STATUS_NO_MEMORY);
6445 END_PROFILE(SMBcopy);
6446 return;
6448 mask = p+1;
6452 * We should only check the mangled cache
6453 * here if unix_convert failed. This means
6454 * that the path in 'mask' doesn't exist
6455 * on the file system and so we need to look
6456 * for a possible mangle. This patch from
6457 * Tine Smukavec <valentin.smukavec@hermes.si>.
6460 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
6461 char *new_mask = NULL;
6462 mangle_lookup_name_from_8_3(ctx,
6463 mask,
6464 &new_mask,
6465 conn->params );
6466 if (new_mask) {
6467 mask = new_mask;
6471 if (!source_has_wild) {
6472 directory = talloc_asprintf_append(directory,
6473 "/%s",
6474 mask);
6475 if (dest_has_wild) {
6476 char *mod_newname = NULL;
6477 if (!resolve_wildcards(ctx,
6478 directory,newname,&mod_newname)) {
6479 reply_nterror(req, NT_STATUS_NO_MEMORY);
6480 END_PROFILE(SMBcopy);
6481 return;
6483 newname = mod_newname;
6486 status = check_name(conn, directory);
6487 if (!NT_STATUS_IS_OK(status)) {
6488 reply_nterror(req, status);
6489 END_PROFILE(SMBcopy);
6490 return;
6493 status = check_name(conn, newname);
6494 if (!NT_STATUS_IS_OK(status)) {
6495 reply_nterror(req, status);
6496 END_PROFILE(SMBcopy);
6497 return;
6500 status = copy_file(ctx,conn,directory,newname,ofun,
6501 count,target_is_directory);
6503 if(!NT_STATUS_IS_OK(status)) {
6504 reply_nterror(req, status);
6505 END_PROFILE(SMBcopy);
6506 return;
6507 } else {
6508 count++;
6510 } else {
6511 struct smb_Dir *dir_hnd = NULL;
6512 const char *dname = NULL;
6513 long offset = 0;
6515 if (strequal(mask,"????????.???")) {
6516 mask[0] = '*';
6517 mask[1] = '\0';
6520 status = check_name(conn, directory);
6521 if (!NT_STATUS_IS_OK(status)) {
6522 reply_nterror(req, status);
6523 END_PROFILE(SMBcopy);
6524 return;
6527 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, 0);
6528 if (dir_hnd == NULL) {
6529 status = map_nt_error_from_unix(errno);
6530 reply_nterror(req, status);
6531 END_PROFILE(SMBcopy);
6532 return;
6535 error = ERRbadfile;
6537 while ((dname = ReadDirName(dir_hnd, &offset))) {
6538 char *destname = NULL;
6539 char *fname = NULL;
6541 if (ISDOT(dname) || ISDOTDOT(dname)) {
6542 continue;
6545 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
6546 continue;
6549 if(!mask_match(dname, mask, conn->case_sensitive)) {
6550 continue;
6553 error = ERRnoaccess;
6554 fname = talloc_asprintf(ctx,
6555 "%s/%s",
6556 directory,
6557 dname);
6558 if (!fname) {
6559 TALLOC_FREE(dir_hnd);
6560 reply_nterror(req, NT_STATUS_NO_MEMORY);
6561 END_PROFILE(SMBcopy);
6562 return;
6565 if (!resolve_wildcards(ctx,
6566 fname,newname,&destname)) {
6567 continue;
6569 if (!destname) {
6570 TALLOC_FREE(dir_hnd);
6571 reply_nterror(req, NT_STATUS_NO_MEMORY);
6572 END_PROFILE(SMBcopy);
6573 return;
6576 status = check_name(conn, fname);
6577 if (!NT_STATUS_IS_OK(status)) {
6578 TALLOC_FREE(dir_hnd);
6579 reply_nterror(req, status);
6580 END_PROFILE(SMBcopy);
6581 return;
6584 status = check_name(conn, destname);
6585 if (!NT_STATUS_IS_OK(status)) {
6586 TALLOC_FREE(dir_hnd);
6587 reply_nterror(req, status);
6588 END_PROFILE(SMBcopy);
6589 return;
6592 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
6594 status = copy_file(ctx,conn,fname,destname,ofun,
6595 count,target_is_directory);
6596 if (NT_STATUS_IS_OK(status)) {
6597 count++;
6599 TALLOC_FREE(fname);
6600 TALLOC_FREE(destname);
6602 TALLOC_FREE(dir_hnd);
6605 if (count == 0) {
6606 if(err) {
6607 /* Error on close... */
6608 errno = err;
6609 reply_unixerror(req, ERRHRD, ERRgeneral);
6610 END_PROFILE(SMBcopy);
6611 return;
6614 reply_doserror(req, ERRDOS, error);
6615 END_PROFILE(SMBcopy);
6616 return;
6619 reply_outbuf(req, 1, 0);
6620 SSVAL(req->outbuf,smb_vwv0,count);
6622 END_PROFILE(SMBcopy);
6623 return;
6626 #undef DBGC_CLASS
6627 #define DBGC_CLASS DBGC_LOCKING
6629 /****************************************************************************
6630 Get a lock pid, dealing with large count requests.
6631 ****************************************************************************/
6633 uint32 get_lock_pid( char *data, int data_offset, bool large_file_format)
6635 if(!large_file_format)
6636 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
6637 else
6638 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6641 /****************************************************************************
6642 Get a lock count, dealing with large count requests.
6643 ****************************************************************************/
6645 SMB_BIG_UINT get_lock_count( char *data, int data_offset, bool large_file_format)
6647 SMB_BIG_UINT count = 0;
6649 if(!large_file_format) {
6650 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6651 } else {
6653 #if defined(HAVE_LONGLONG)
6654 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6655 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6656 #else /* HAVE_LONGLONG */
6659 * NT4.x seems to be broken in that it sends large file (64 bit)
6660 * lockingX calls even if the CAP_LARGE_FILES was *not*
6661 * negotiated. For boxes without large unsigned ints truncate the
6662 * lock count by dropping the top 32 bits.
6665 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6666 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6667 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6668 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6669 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6672 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6673 #endif /* HAVE_LONGLONG */
6676 return count;
6679 #if !defined(HAVE_LONGLONG)
6680 /****************************************************************************
6681 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6682 ****************************************************************************/
6684 static uint32 map_lock_offset(uint32 high, uint32 low)
6686 unsigned int i;
6687 uint32 mask = 0;
6688 uint32 highcopy = high;
6691 * Try and find out how many significant bits there are in high.
6694 for(i = 0; highcopy; i++)
6695 highcopy >>= 1;
6698 * We use 31 bits not 32 here as POSIX
6699 * lock offsets may not be negative.
6702 mask = (~0) << (31 - i);
6704 if(low & mask)
6705 return 0; /* Fail. */
6707 high <<= (31 - i);
6709 return (high|low);
6711 #endif /* !defined(HAVE_LONGLONG) */
6713 /****************************************************************************
6714 Get a lock offset, dealing with large offset requests.
6715 ****************************************************************************/
6717 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, bool large_file_format, bool *err)
6719 SMB_BIG_UINT offset = 0;
6721 *err = False;
6723 if(!large_file_format) {
6724 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
6725 } else {
6727 #if defined(HAVE_LONGLONG)
6728 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
6729 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
6730 #else /* HAVE_LONGLONG */
6733 * NT4.x seems to be broken in that it sends large file (64 bit)
6734 * lockingX calls even if the CAP_LARGE_FILES was *not*
6735 * negotiated. For boxes without large unsigned ints mangle the
6736 * lock offset by mapping the top 32 bits onto the lower 32.
6739 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
6740 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6741 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
6742 uint32 new_low = 0;
6744 if((new_low = map_lock_offset(high, low)) == 0) {
6745 *err = True;
6746 return (SMB_BIG_UINT)-1;
6749 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
6750 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
6751 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
6752 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
6755 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6756 #endif /* HAVE_LONGLONG */
6759 return offset;
6762 /****************************************************************************
6763 Reply to a lockingX request.
6764 ****************************************************************************/
6766 void reply_lockingX(struct smb_request *req)
6768 connection_struct *conn = req->conn;
6769 files_struct *fsp;
6770 unsigned char locktype;
6771 unsigned char oplocklevel;
6772 uint16 num_ulocks;
6773 uint16 num_locks;
6774 SMB_BIG_UINT count = 0, offset = 0;
6775 uint32 lock_pid;
6776 int32 lock_timeout;
6777 int i;
6778 char *data;
6779 bool large_file_format;
6780 bool err;
6781 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
6783 START_PROFILE(SMBlockingX);
6785 if (req->wct < 8) {
6786 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6787 END_PROFILE(SMBlockingX);
6788 return;
6791 fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
6792 locktype = CVAL(req->inbuf,smb_vwv3);
6793 oplocklevel = CVAL(req->inbuf,smb_vwv3+1);
6794 num_ulocks = SVAL(req->inbuf,smb_vwv6);
6795 num_locks = SVAL(req->inbuf,smb_vwv7);
6796 lock_timeout = IVAL(req->inbuf,smb_vwv4);
6797 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
6799 if (!check_fsp(conn, req, fsp)) {
6800 END_PROFILE(SMBlockingX);
6801 return;
6804 data = smb_buf(req->inbuf);
6806 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
6807 /* we don't support these - and CANCEL_LOCK makes w2k
6808 and XP reboot so I don't really want to be
6809 compatible! (tridge) */
6810 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
6811 END_PROFILE(SMBlockingX);
6812 return;
6815 /* Check if this is an oplock break on a file
6816 we have granted an oplock on.
6818 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
6819 /* Client can insist on breaking to none. */
6820 bool break_to_none = (oplocklevel == 0);
6821 bool result;
6823 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6824 "for fnum = %d\n", (unsigned int)oplocklevel,
6825 fsp->fnum ));
6828 * Make sure we have granted an exclusive or batch oplock on
6829 * this file.
6832 if (fsp->oplock_type == 0) {
6834 /* The Samba4 nbench simulator doesn't understand
6835 the difference between break to level2 and break
6836 to none from level2 - it sends oplock break
6837 replies in both cases. Don't keep logging an error
6838 message here - just ignore it. JRA. */
6840 DEBUG(5,("reply_lockingX: Error : oplock break from "
6841 "client for fnum = %d (oplock=%d) and no "
6842 "oplock granted on this file (%s).\n",
6843 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
6845 /* if this is a pure oplock break request then don't
6846 * send a reply */
6847 if (num_locks == 0 && num_ulocks == 0) {
6848 END_PROFILE(SMBlockingX);
6849 return;
6850 } else {
6851 END_PROFILE(SMBlockingX);
6852 reply_doserror(req, ERRDOS, ERRlock);
6853 return;
6857 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
6858 (break_to_none)) {
6859 result = remove_oplock(fsp);
6860 } else {
6861 result = downgrade_oplock(fsp);
6864 if (!result) {
6865 DEBUG(0, ("reply_lockingX: error in removing "
6866 "oplock on file %s\n", fsp->fsp_name));
6867 /* Hmmm. Is this panic justified? */
6868 smb_panic("internal tdb error");
6871 reply_to_oplock_break_requests(fsp);
6873 /* if this is a pure oplock break request then don't send a
6874 * reply */
6875 if (num_locks == 0 && num_ulocks == 0) {
6876 /* Sanity check - ensure a pure oplock break is not a
6877 chained request. */
6878 if(CVAL(req->inbuf,smb_vwv0) != 0xff)
6879 DEBUG(0,("reply_lockingX: Error : pure oplock "
6880 "break is a chained %d request !\n",
6881 (unsigned int)CVAL(req->inbuf,
6882 smb_vwv0) ));
6883 END_PROFILE(SMBlockingX);
6884 return;
6889 * We do this check *after* we have checked this is not a oplock break
6890 * response message. JRA.
6893 release_level_2_oplocks_on_change(fsp);
6895 if (smb_buflen(req->inbuf) <
6896 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
6897 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6898 END_PROFILE(SMBlockingX);
6899 return;
6902 /* Data now points at the beginning of the list
6903 of smb_unlkrng structs */
6904 for(i = 0; i < (int)num_ulocks; i++) {
6905 lock_pid = get_lock_pid( data, i, large_file_format);
6906 count = get_lock_count( data, i, large_file_format);
6907 offset = get_lock_offset( data, i, large_file_format, &err);
6910 * There is no error code marked "stupid client bug".... :-).
6912 if(err) {
6913 END_PROFILE(SMBlockingX);
6914 reply_doserror(req, ERRDOS, ERRnoaccess);
6915 return;
6918 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
6919 "pid %u, file %s\n", (double)offset, (double)count,
6920 (unsigned int)lock_pid, fsp->fsp_name ));
6922 status = do_unlock(smbd_messaging_context(),
6923 fsp,
6924 lock_pid,
6925 count,
6926 offset,
6927 WINDOWS_LOCK);
6929 if (NT_STATUS_V(status)) {
6930 END_PROFILE(SMBlockingX);
6931 reply_nterror(req, status);
6932 return;
6936 /* Setup the timeout in seconds. */
6938 if (!lp_blocking_locks(SNUM(conn))) {
6939 lock_timeout = 0;
6942 /* Now do any requested locks */
6943 data += ((large_file_format ? 20 : 10)*num_ulocks);
6945 /* Data now points at the beginning of the list
6946 of smb_lkrng structs */
6948 for(i = 0; i < (int)num_locks; i++) {
6949 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
6950 READ_LOCK:WRITE_LOCK);
6951 lock_pid = get_lock_pid( data, i, large_file_format);
6952 count = get_lock_count( data, i, large_file_format);
6953 offset = get_lock_offset( data, i, large_file_format, &err);
6956 * There is no error code marked "stupid client bug".... :-).
6958 if(err) {
6959 END_PROFILE(SMBlockingX);
6960 reply_doserror(req, ERRDOS, ERRnoaccess);
6961 return;
6964 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
6965 "%u, file %s timeout = %d\n", (double)offset,
6966 (double)count, (unsigned int)lock_pid,
6967 fsp->fsp_name, (int)lock_timeout ));
6969 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
6970 if (lp_blocking_locks(SNUM(conn))) {
6972 /* Schedule a message to ourselves to
6973 remove the blocking lock record and
6974 return the right error. */
6976 if (!blocking_lock_cancel(fsp,
6977 lock_pid,
6978 offset,
6979 count,
6980 WINDOWS_LOCK,
6981 locktype,
6982 NT_STATUS_FILE_LOCK_CONFLICT)) {
6983 END_PROFILE(SMBlockingX);
6984 reply_nterror(
6985 req,
6986 NT_STATUS_DOS(
6987 ERRDOS,
6988 ERRcancelviolation));
6989 return;
6992 /* Remove a matching pending lock. */
6993 status = do_lock_cancel(fsp,
6994 lock_pid,
6995 count,
6996 offset,
6997 WINDOWS_LOCK);
6998 } else {
6999 bool blocking_lock = lock_timeout ? True : False;
7000 bool defer_lock = False;
7001 struct byte_range_lock *br_lck;
7002 uint32 block_smbpid;
7004 br_lck = do_lock(smbd_messaging_context(),
7005 fsp,
7006 lock_pid,
7007 count,
7008 offset,
7009 lock_type,
7010 WINDOWS_LOCK,
7011 blocking_lock,
7012 &status,
7013 &block_smbpid);
7015 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7016 /* Windows internal resolution for blocking locks seems
7017 to be about 200ms... Don't wait for less than that. JRA. */
7018 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
7019 lock_timeout = lp_lock_spin_time();
7021 defer_lock = True;
7024 /* This heuristic seems to match W2K3 very well. If a
7025 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7026 it pretends we asked for a timeout of between 150 - 300 milliseconds as
7027 far as I can tell. Replacement for do_lock_spin(). JRA. */
7029 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
7030 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
7031 defer_lock = True;
7032 lock_timeout = lp_lock_spin_time();
7035 if (br_lck && defer_lock) {
7037 * A blocking lock was requested. Package up
7038 * this smb into a queued request and push it
7039 * onto the blocking lock queue.
7041 if(push_blocking_lock_request(br_lck,
7042 req,
7043 fsp,
7044 lock_timeout,
7046 lock_pid,
7047 lock_type,
7048 WINDOWS_LOCK,
7049 offset,
7050 count,
7051 block_smbpid)) {
7052 TALLOC_FREE(br_lck);
7053 END_PROFILE(SMBlockingX);
7054 return;
7058 TALLOC_FREE(br_lck);
7061 if (NT_STATUS_V(status)) {
7062 END_PROFILE(SMBlockingX);
7063 reply_nterror(req, status);
7064 return;
7068 /* If any of the above locks failed, then we must unlock
7069 all of the previous locks (X/Open spec). */
7071 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
7072 (i != num_locks) &&
7073 (num_locks != 0)) {
7075 * Ensure we don't do a remove on the lock that just failed,
7076 * as under POSIX rules, if we have a lock already there, we
7077 * will delete it (and we shouldn't) .....
7079 for(i--; i >= 0; i--) {
7080 lock_pid = get_lock_pid( data, i, large_file_format);
7081 count = get_lock_count( data, i, large_file_format);
7082 offset = get_lock_offset( data, i, large_file_format,
7083 &err);
7086 * There is no error code marked "stupid client
7087 * bug".... :-).
7089 if(err) {
7090 END_PROFILE(SMBlockingX);
7091 reply_doserror(req, ERRDOS, ERRnoaccess);
7092 return;
7095 do_unlock(smbd_messaging_context(),
7096 fsp,
7097 lock_pid,
7098 count,
7099 offset,
7100 WINDOWS_LOCK);
7102 END_PROFILE(SMBlockingX);
7103 reply_nterror(req, status);
7104 return;
7107 reply_outbuf(req, 2, 0);
7109 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7110 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7112 END_PROFILE(SMBlockingX);
7113 chain_reply(req);
7116 #undef DBGC_CLASS
7117 #define DBGC_CLASS DBGC_ALL
7119 /****************************************************************************
7120 Reply to a SMBreadbmpx (read block multiplex) request.
7121 Always reply with an error, if someone has a platform really needs this,
7122 please contact vl@samba.org
7123 ****************************************************************************/
7125 void reply_readbmpx(struct smb_request *req)
7127 START_PROFILE(SMBreadBmpx);
7128 reply_doserror(req, ERRSRV, ERRuseSTD);
7129 END_PROFILE(SMBreadBmpx);
7130 return;
7133 /****************************************************************************
7134 Reply to a SMBreadbs (read block multiplex secondary) request.
7135 Always reply with an error, if someone has a platform really needs this,
7136 please contact vl@samba.org
7137 ****************************************************************************/
7139 void reply_readbs(struct smb_request *req)
7141 START_PROFILE(SMBreadBs);
7142 reply_doserror(req, ERRSRV, ERRuseSTD);
7143 END_PROFILE(SMBreadBs);
7144 return;
7147 /****************************************************************************
7148 Reply to a SMBsetattrE.
7149 ****************************************************************************/
7151 void reply_setattrE(struct smb_request *req)
7153 connection_struct *conn = req->conn;
7154 struct timespec ts[2];
7155 files_struct *fsp;
7156 SMB_STRUCT_STAT sbuf;
7157 NTSTATUS status;
7159 START_PROFILE(SMBsetattrE);
7161 if (req->wct < 7) {
7162 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7163 END_PROFILE(SMBsetattrE);
7164 return;
7167 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
7169 if(!fsp || (fsp->conn != conn)) {
7170 reply_doserror(req, ERRDOS, ERRbadfid);
7171 END_PROFILE(SMBsetattrE);
7172 return;
7177 * Convert the DOS times into unix times. Ignore create
7178 * time as UNIX can't set this.
7181 ts[0] = convert_time_t_to_timespec(
7182 srv_make_unix_date2(req->inbuf+smb_vwv3)); /* atime. */
7183 ts[1] = convert_time_t_to_timespec(
7184 srv_make_unix_date2(req->inbuf+smb_vwv5)); /* mtime. */
7186 reply_outbuf(req, 0, 0);
7189 * Patch from Ray Frush <frush@engr.colostate.edu>
7190 * Sometimes times are sent as zero - ignore them.
7193 /* Ensure we have a valid stat struct for the source. */
7194 if (fsp->fh->fd != -1) {
7195 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
7196 status = map_nt_error_from_unix(errno);
7197 reply_nterror(req, status);
7198 END_PROFILE(SMBsetattrE);
7199 return;
7201 } else {
7202 int ret = -1;
7204 if (fsp->posix_open) {
7205 ret = SMB_VFS_LSTAT(conn, fsp->fsp_name, &sbuf);
7206 } else {
7207 ret = SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf);
7209 if (ret == -1) {
7210 status = map_nt_error_from_unix(errno);
7211 reply_nterror(req, status);
7212 END_PROFILE(SMBsetattrE);
7213 return;
7217 status = smb_set_file_time(conn, fsp, fsp->fsp_name,
7218 &sbuf, ts, true);
7219 if (!NT_STATUS_IS_OK(status)) {
7220 reply_doserror(req, ERRDOS, ERRnoaccess);
7221 END_PROFILE(SMBsetattrE);
7222 return;
7225 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
7226 fsp->fnum,
7227 (unsigned int)ts[0].tv_sec,
7228 (unsigned int)ts[1].tv_sec));
7230 END_PROFILE(SMBsetattrE);
7231 return;
7235 /* Back from the dead for OS/2..... JRA. */
7237 /****************************************************************************
7238 Reply to a SMBwritebmpx (write block multiplex primary) request.
7239 Always reply with an error, if someone has a platform really needs this,
7240 please contact vl@samba.org
7241 ****************************************************************************/
7243 void reply_writebmpx(struct smb_request *req)
7245 START_PROFILE(SMBwriteBmpx);
7246 reply_doserror(req, ERRSRV, ERRuseSTD);
7247 END_PROFILE(SMBwriteBmpx);
7248 return;
7251 /****************************************************************************
7252 Reply to a SMBwritebs (write block multiplex secondary) request.
7253 Always reply with an error, if someone has a platform really needs this,
7254 please contact vl@samba.org
7255 ****************************************************************************/
7257 void reply_writebs(struct smb_request *req)
7259 START_PROFILE(SMBwriteBs);
7260 reply_doserror(req, ERRSRV, ERRuseSTD);
7261 END_PROFILE(SMBwriteBs);
7262 return;
7265 /****************************************************************************
7266 Reply to a SMBgetattrE.
7267 ****************************************************************************/
7269 void reply_getattrE(struct smb_request *req)
7271 connection_struct *conn = req->conn;
7272 SMB_STRUCT_STAT sbuf;
7273 int mode;
7274 files_struct *fsp;
7275 struct timespec create_ts;
7277 START_PROFILE(SMBgetattrE);
7279 if (req->wct < 1) {
7280 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7281 END_PROFILE(SMBgetattrE);
7282 return;
7285 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
7287 if(!fsp || (fsp->conn != conn)) {
7288 reply_doserror(req, ERRDOS, ERRbadfid);
7289 END_PROFILE(SMBgetattrE);
7290 return;
7293 /* Do an fstat on this file */
7294 if(fsp_stat(fsp, &sbuf)) {
7295 reply_unixerror(req, ERRDOS, ERRnoaccess);
7296 END_PROFILE(SMBgetattrE);
7297 return;
7300 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7303 * Convert the times into dos times. Set create
7304 * date to be last modify date as UNIX doesn't save
7305 * this.
7308 reply_outbuf(req, 11, 0);
7310 create_ts = get_create_timespec(&sbuf,
7311 lp_fake_dir_create_times(SNUM(conn)));
7312 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7313 srv_put_dos_date2((char *)req->outbuf, smb_vwv2, sbuf.st_atime);
7314 /* Should we check pending modtime here ? JRA */
7315 srv_put_dos_date2((char *)req->outbuf, smb_vwv4, sbuf.st_mtime);
7317 if (mode & aDIR) {
7318 SIVAL(req->outbuf, smb_vwv6, 0);
7319 SIVAL(req->outbuf, smb_vwv8, 0);
7320 } else {
7321 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
7322 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_size);
7323 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7325 SSVAL(req->outbuf,smb_vwv10, mode);
7327 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7329 END_PROFILE(SMBgetattrE);
7330 return;