2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
29 /* look in server.c for some explanation of these variables */
30 extern enum protocol_types Protocol;
32 unsigned int smb_echo_count = 0;
33 extern uint32 global_client_caps;
35 extern struct current_user current_user;
36 extern BOOL global_encrypted_passwords_negotiated;
38 /****************************************************************************
39 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
40 path or anything including wildcards.
41 We're assuming here that '/' is not the second byte in any multibyte char
42 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
44 ****************************************************************************/
46 /* Custom version for processing POSIX paths. */
47 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
49 static NTSTATUS check_path_syntax_internal(char *path,
51 BOOL *p_last_component_contains_wcard)
55 NTSTATUS ret = NT_STATUS_OK;
56 BOOL start_of_name_component = True;
58 *p_last_component_contains_wcard = False;
61 if (IS_PATH_SEP(*s,posix_path)) {
63 * Safe to assume is not the second part of a mb char
64 * as this is handled below.
66 /* Eat multiple '/' or '\\' */
67 while (IS_PATH_SEP(*s,posix_path)) {
70 if ((d != path) && (*s != '\0')) {
71 /* We only care about non-leading or trailing '/' or '\\' */
75 start_of_name_component = True;
77 *p_last_component_contains_wcard = False;
81 if (start_of_name_component) {
82 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
83 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
86 * No mb char starts with '.' so we're safe checking the directory separator here.
89 /* If we just added a '/' - delete it */
90 if ((d > path) && (*(d-1) == '/')) {
95 /* Are we at the start ? Can't go back further if so. */
97 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
100 /* Go back one level... */
101 /* We know this is safe as '/' cannot be part of a mb sequence. */
102 /* NOTE - if this assumption is invalid we are not in good shape... */
103 /* Decrement d first as d points to the *next* char to write into. */
104 for (d--; d > path; d--) {
108 s += 2; /* Else go past the .. */
109 /* We're still at the start of a name component, just the previous one. */
112 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
125 return NT_STATUS_OBJECT_NAME_INVALID;
133 *p_last_component_contains_wcard = True;
142 /* Get the size of the next MB character. */
143 next_codepoint(s,&siz);
161 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
163 return NT_STATUS_INVALID_PARAMETER;
166 start_of_name_component = False;
173 /****************************************************************************
174 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
175 No wildcards allowed.
176 ****************************************************************************/
178 NTSTATUS check_path_syntax(char *path)
181 return check_path_syntax_internal(path, False, &ignore);
184 /****************************************************************************
185 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
186 Wildcards allowed - p_contains_wcard returns true if the last component contained
188 ****************************************************************************/
190 NTSTATUS check_path_syntax_wcard(char *path, BOOL *p_contains_wcard)
192 return check_path_syntax_internal(path, False, p_contains_wcard);
195 /****************************************************************************
196 Check the path for a POSIX client.
197 We're assuming here that '/' is not the second byte in any multibyte char
198 set (a safe assumption).
199 ****************************************************************************/
201 NTSTATUS check_path_syntax_posix(char *path)
204 return check_path_syntax_internal(path, True, &ignore);
207 /****************************************************************************
208 Pull a string and check the path allowing a wilcard - provide for error return.
209 ****************************************************************************/
211 size_t srvstr_get_path_wcard(const char *inbuf, uint16 smb_flags2, char *dest,
212 const char *src, size_t dest_len, size_t src_len,
213 int flags, NTSTATUS *err, BOOL *contains_wcard)
217 SMB_ASSERT(dest_len == sizeof(pstring));
221 ret = srvstr_pull_buf(inbuf, smb_flags2, dest, src,
224 ret = srvstr_pull(inbuf, smb_flags2, dest, src,
225 dest_len, src_len, flags);
228 *contains_wcard = False;
230 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
232 * For a DFS path the function parse_dfs_path()
233 * will do the path processing, just make a copy.
239 if (lp_posix_pathnames()) {
240 *err = check_path_syntax_posix(dest);
242 *err = check_path_syntax_wcard(dest, contains_wcard);
248 /****************************************************************************
249 Pull a string and check the path - provide for error return.
250 ****************************************************************************/
252 size_t srvstr_get_path(const char *inbuf, uint16 smb_flags2, char *dest,
253 const char *src, size_t dest_len, size_t src_len,
254 int flags, NTSTATUS *err)
258 SMB_ASSERT(dest_len == sizeof(pstring));
262 ret = srvstr_pull_buf(inbuf, smb_flags2, dest, src,
265 ret = srvstr_pull(inbuf, smb_flags2, dest, src,
266 dest_len, src_len, flags);
269 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
271 * For a DFS path the function parse_dfs_path()
272 * will do the path processing, just make a copy.
278 if (lp_posix_pathnames()) {
279 *err = check_path_syntax_posix(dest);
281 *err = check_path_syntax(dest);
287 /****************************************************************************
288 Check if we have a correct fsp pointing to a file. Replacement for the
290 ****************************************************************************/
292 BOOL check_fsp(connection_struct *conn, struct smb_request *req,
293 files_struct *fsp, struct current_user *user)
295 if (!(fsp) || !(conn)) {
296 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
299 if (((conn) != (fsp)->conn) || user->vuid != (fsp)->vuid) {
300 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
303 if ((fsp)->is_directory) {
304 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
307 if ((fsp)->fh->fd == -1) {
308 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
311 (fsp)->num_smb_operations++;
315 /****************************************************************************
316 Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
317 ****************************************************************************/
319 BOOL fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
320 files_struct *fsp, struct current_user *user)
322 if ((fsp) && (conn) && ((conn)==(fsp)->conn)
323 && (current_user.vuid==(fsp)->vuid)) {
327 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
331 /****************************************************************************
332 Reply to a (netbios-level) special message.
333 ****************************************************************************/
335 void reply_special(char *inbuf)
337 int msg_type = CVAL(inbuf,0);
338 int msg_flags = CVAL(inbuf,1);
343 * We only really use 4 bytes of the outbuf, but for the smb_setlen
344 * calculation & friends (send_smb uses that) we need the full smb
347 char outbuf[smb_size];
349 static BOOL already_got_session = False;
353 memset(outbuf, '\0', sizeof(outbuf));
355 smb_setlen(inbuf,outbuf,0);
358 case 0x81: /* session request */
360 if (already_got_session) {
361 exit_server_cleanly("multiple session request not permitted");
364 SCVAL(outbuf,0,0x82);
366 if (name_len(inbuf+4) > 50 ||
367 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
368 DEBUG(0,("Invalid name length in session request\n"));
371 name_extract(inbuf,4,name1);
372 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
373 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
376 set_local_machine_name(name1, True);
377 set_remote_machine_name(name2, True);
379 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
380 get_local_machine_name(), get_remote_machine_name(),
383 if (name_type == 'R') {
384 /* We are being asked for a pathworks session ---
386 SCVAL(outbuf, 0,0x83);
390 /* only add the client's machine name to the list
391 of possibly valid usernames if we are operating
392 in share mode security */
393 if (lp_security() == SEC_SHARE) {
394 add_session_user(get_remote_machine_name());
397 reload_services(True);
400 already_got_session = True;
403 case 0x89: /* session keepalive request
404 (some old clients produce this?) */
405 SCVAL(outbuf,0,SMBkeepalive);
409 case 0x82: /* positive session response */
410 case 0x83: /* negative session response */
411 case 0x84: /* retarget session response */
412 DEBUG(0,("Unexpected session response\n"));
415 case SMBkeepalive: /* session keepalive */
420 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
421 msg_type, msg_flags));
423 send_smb(smbd_server_fd(), outbuf);
427 /****************************************************************************
429 conn POINTER CAN BE NULL HERE !
430 ****************************************************************************/
432 void reply_tcon(connection_struct *conn, struct smb_request *req)
435 char *service_buf = NULL;
436 char *password = NULL;
441 DATA_BLOB password_blob;
443 START_PROFILE(SMBtcon);
445 /********************************************************************
446 * Warning! I'm not sure that the inbuf length check is actually
447 * correct here. -- vl
449 * Jeremy, please check and remove this comment :-)
450 ********************************************************************/
452 p = smb_buf(req->inbuf)+1;
453 p += srvstr_pull_buf_talloc(req, req->inbuf, req->flags2,
454 &service_buf, p, STR_TERMINATE) + 1;
455 pwlen = srvstr_pull_buf_talloc(req, req->inbuf, req->flags2,
456 &password, p, STR_TERMINATE) + 1;
458 p += srvstr_pull_buf_talloc(req, req->inbuf, req->flags2,
459 &dev, p, STR_TERMINATE) + 1;
461 if (service_buf == NULL || password == NULL || dev == NULL) {
462 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
463 END_PROFILE(SMBtcon);
466 p = strrchr_m(service_buf,'\\');
470 service = service_buf;
473 password_blob = data_blob(password, pwlen+1);
475 conn = make_connection(service,password_blob,dev,req->vuid,&nt_status);
477 data_blob_clear_free(&password_blob);
480 reply_nterror(req, nt_status);
481 END_PROFILE(SMBtcon);
485 reply_outbuf(req, 2, 0);
486 SSVAL(req->outbuf,smb_vwv0,max_recv);
487 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
488 SSVAL(req->outbuf,smb_tid,conn->cnum);
490 DEBUG(3,("tcon service=%s cnum=%d\n",
491 service, conn->cnum));
493 END_PROFILE(SMBtcon);
497 /****************************************************************************
498 Reply to a tcon and X.
499 conn POINTER CAN BE NULL HERE !
500 ****************************************************************************/
502 void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
504 char *service = NULL;
507 TALLOC_CTX *ctx = NULL;
508 /* what the cleint thinks the device is */
509 char *client_devicetype = NULL;
510 /* what the server tells the client the share represents */
511 const char *server_devicetype;
518 START_PROFILE(SMBtconX);
521 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
522 END_PROFILE(SMBtconX);
526 passlen = SVAL(req->inbuf,smb_vwv3);
527 tcon_flags = SVAL(req->inbuf,smb_vwv2);
529 /* we might have to close an old one */
530 if ((tcon_flags & 0x1) && conn) {
531 close_cnum(conn,req->vuid);
534 if ((passlen > MAX_PASS_LEN) || (passlen >= smb_buflen(req->inbuf))) {
535 reply_doserror(req, ERRDOS, ERRbuftoosmall);
536 END_PROFILE(SMBtconX);
540 if (global_encrypted_passwords_negotiated) {
541 password = data_blob(smb_buf(req->inbuf),passlen);
542 if (lp_security() == SEC_SHARE) {
544 * Security = share always has a pad byte
545 * after the password.
547 p = smb_buf(req->inbuf) + passlen + 1;
549 p = smb_buf(req->inbuf) + passlen;
552 password = data_blob(smb_buf(req->inbuf),passlen+1);
553 /* Ensure correct termination */
554 password.data[passlen]=0;
555 p = smb_buf(req->inbuf) + passlen + 1;
558 ctx = talloc_init("reply_tcon_and_X");
560 data_blob_clear_free(&password);
561 reply_nterror(req, NT_STATUS_NO_MEMORY);
562 END_PROFILE(SMBtconX);
565 p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2, &path, p,
569 data_blob_clear_free(&password);
571 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
572 END_PROFILE(SMBtconX);
577 * the service name can be either: \\server\share
578 * or share directly like on the DELL PowerVault 705
581 q = strchr_m(path+2,'\\');
583 data_blob_clear_free(&password);
585 reply_doserror(req, ERRDOS, ERRnosuchshare);
586 END_PROFILE(SMBtconX);
594 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
595 &client_devicetype, p,
596 MIN(6,smb_bufrem(req->inbuf, p)), STR_ASCII);
598 if (client_devicetype == NULL) {
599 data_blob_clear_free(&password);
601 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
602 END_PROFILE(SMBtconX);
606 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
608 conn = make_connection(service, password, client_devicetype,
609 req->vuid, &nt_status);
611 data_blob_clear_free(&password);
615 reply_nterror(req, nt_status);
616 END_PROFILE(SMBtconX);
621 server_devicetype = "IPC";
622 else if ( IS_PRINT(conn) )
623 server_devicetype = "LPT1:";
625 server_devicetype = "A:";
627 if (Protocol < PROTOCOL_NT1) {
628 reply_outbuf(req, 2, 0);
629 if (message_push_string(&req->outbuf, server_devicetype,
630 STR_TERMINATE|STR_ASCII) == -1) {
632 reply_nterror(req, NT_STATUS_NO_MEMORY);
633 END_PROFILE(SMBtconX);
637 /* NT sets the fstype of IPC$ to the null string */
638 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
640 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
641 /* Return permissions. */
645 reply_outbuf(req, 7, 0);
648 perm1 = FILE_ALL_ACCESS;
649 perm2 = FILE_ALL_ACCESS;
651 perm1 = CAN_WRITE(conn) ?
656 SIVAL(req->outbuf, smb_vwv3, perm1);
657 SIVAL(req->outbuf, smb_vwv5, perm2);
659 reply_outbuf(req, 3, 0);
662 if ((message_push_string(&req->outbuf, server_devicetype,
663 STR_TERMINATE|STR_ASCII) == -1)
664 || (message_push_string(&req->outbuf, fstype,
665 STR_TERMINATE) == -1)) {
667 reply_nterror(req, NT_STATUS_NO_MEMORY);
668 END_PROFILE(SMBtconX);
672 /* what does setting this bit do? It is set by NT4 and
673 may affect the ability to autorun mounted cdroms */
674 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
675 (lp_csc_policy(SNUM(conn)) << 2));
677 init_dfsroot(conn, req->inbuf, req->outbuf);
681 DEBUG(3,("tconX service=%s \n",
684 /* set the incoming and outgoing tid to the just created one */
685 SSVAL(req->inbuf,smb_tid,conn->cnum);
686 SSVAL(req->outbuf,smb_tid,conn->cnum);
689 END_PROFILE(SMBtconX);
691 chain_reply_new(req);
695 /****************************************************************************
696 Reply to an unknown type.
697 ****************************************************************************/
699 int reply_unknown(char *inbuf,char *outbuf)
702 type = CVAL(inbuf,smb_com);
704 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
705 smb_fn_name(type), type, type));
707 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
710 void reply_unknown_new(struct smb_request *req, uint8 type)
712 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
713 smb_fn_name(type), type, type));
714 reply_doserror(req, ERRSRV, ERRunknownsmb);
718 /****************************************************************************
720 conn POINTER CAN BE NULL HERE !
721 ****************************************************************************/
723 void reply_ioctl(connection_struct *conn, struct smb_request *req)
731 START_PROFILE(SMBioctl);
734 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
735 END_PROFILE(SMBioctl);
739 device = SVAL(req->inbuf,smb_vwv1);
740 function = SVAL(req->inbuf,smb_vwv2);
741 ioctl_code = (device << 16) + function;
743 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
745 switch (ioctl_code) {
746 case IOCTL_QUERY_JOB_INFO:
750 reply_doserror(req, ERRSRV, ERRnosupport);
751 END_PROFILE(SMBioctl);
755 reply_outbuf(req, 8, replysize+1);
756 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
757 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
758 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
759 p = smb_buf(req->outbuf) + 1; /* Allow for alignment */
761 switch (ioctl_code) {
762 case IOCTL_QUERY_JOB_INFO:
764 files_struct *fsp = file_fsp(SVAL(req->inbuf,
767 reply_doserror(req, ERRDOS, ERRbadfid);
768 END_PROFILE(SMBioctl);
771 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
772 srvstr_push((char *)req->outbuf, req->flags2, p+2,
774 STR_TERMINATE|STR_ASCII);
776 srvstr_push((char *)req->outbuf, req->flags2,
777 p+18, lp_servicename(SNUM(conn)),
778 13, STR_TERMINATE|STR_ASCII);
787 END_PROFILE(SMBioctl);
791 /****************************************************************************
792 Strange checkpath NTSTATUS mapping.
793 ****************************************************************************/
795 static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
797 /* Strange DOS error code semantics only for checkpath... */
798 if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
799 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
800 /* We need to map to ERRbadpath */
801 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
807 /****************************************************************************
808 Reply to a checkpath.
809 ****************************************************************************/
811 void reply_checkpath(connection_struct *conn, struct smb_request *req)
814 SMB_STRUCT_STAT sbuf;
817 START_PROFILE(SMBcheckpath);
819 srvstr_get_path((char *)req->inbuf, req->flags2, name,
820 smb_buf(req->inbuf) + 1, sizeof(name), 0,
821 STR_TERMINATE, &status);
822 if (!NT_STATUS_IS_OK(status)) {
823 status = map_checkpath_error((char *)req->inbuf, status);
824 reply_nterror(req, status);
825 END_PROFILE(SMBcheckpath);
829 status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, name);
830 if (!NT_STATUS_IS_OK(status)) {
831 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
832 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
834 END_PROFILE(SMBcheckpath);
840 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->inbuf,smb_vwv0)));
842 status = unix_convert(conn, name, False, NULL, &sbuf);
843 if (!NT_STATUS_IS_OK(status)) {
847 status = check_name(conn, name);
848 if (!NT_STATUS_IS_OK(status)) {
849 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
853 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
854 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
855 status = map_nt_error_from_unix(errno);
859 if (!S_ISDIR(sbuf.st_mode)) {
860 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
862 END_PROFILE(SMBcheckpath);
866 reply_outbuf(req, 0, 0);
868 END_PROFILE(SMBcheckpath);
873 END_PROFILE(SMBcheckpath);
875 /* We special case this - as when a Windows machine
876 is parsing a path is steps through the components
877 one at a time - if a component fails it expects
878 ERRbadpath, not ERRbadfile.
880 status = map_checkpath_error((char *)req->inbuf, status);
881 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
883 * Windows returns different error codes if
884 * the parent directory is valid but not the
885 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
886 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
887 * if the path is invalid.
889 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
894 reply_nterror(req, status);
897 /****************************************************************************
899 ****************************************************************************/
901 void reply_getatr(connection_struct *conn, struct smb_request *req)
904 SMB_STRUCT_STAT sbuf;
911 START_PROFILE(SMBgetatr);
913 p = smb_buf(req->inbuf) + 1;
914 p += srvstr_get_path((char *)req->inbuf, req->flags2, fname, p,
915 sizeof(fname), 0, STR_TERMINATE, &status);
916 if (!NT_STATUS_IS_OK(status)) {
917 reply_nterror(req, status);
918 END_PROFILE(SMBgetatr);
922 status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
924 if (!NT_STATUS_IS_OK(status)) {
925 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
926 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
928 END_PROFILE(SMBgetatr);
931 reply_nterror(req, status);
932 END_PROFILE(SMBgetatr);
936 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
937 under WfWg - weird! */
938 if (*fname == '\0') {
939 mode = aHIDDEN | aDIR;
940 if (!CAN_WRITE(conn)) {
946 status = unix_convert(conn, fname, False, NULL,&sbuf);
947 if (!NT_STATUS_IS_OK(status)) {
948 reply_nterror(req, status);
949 END_PROFILE(SMBgetatr);
952 status = check_name(conn, fname);
953 if (!NT_STATUS_IS_OK(status)) {
954 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
955 reply_nterror(req, status);
956 END_PROFILE(SMBgetatr);
959 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
960 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
961 reply_unixerror(req, ERRDOS,ERRbadfile);
962 END_PROFILE(SMBgetatr);
966 mode = dos_mode(conn,fname,&sbuf);
968 mtime = sbuf.st_mtime;
974 reply_outbuf(req, 10, 0);
976 SSVAL(req->outbuf,smb_vwv0,mode);
977 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
978 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
980 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
982 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
984 if (Protocol >= PROTOCOL_NT1) {
985 SSVAL(req->outbuf, smb_flg2,
986 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
989 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
991 END_PROFILE(SMBgetatr);
995 /****************************************************************************
997 ****************************************************************************/
999 void reply_setatr(connection_struct *conn, struct smb_request *req)
1004 SMB_STRUCT_STAT sbuf;
1008 START_PROFILE(SMBsetatr);
1011 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1015 p = smb_buf(req->inbuf) + 1;
1016 p += srvstr_get_path((char *)req->inbuf, req->flags2, fname, p,
1017 sizeof(fname), 0, STR_TERMINATE, &status);
1018 if (!NT_STATUS_IS_OK(status)) {
1019 reply_nterror(req, status);
1020 END_PROFILE(SMBsetatr);
1024 status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
1026 if (!NT_STATUS_IS_OK(status)) {
1027 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1028 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1029 ERRSRV, ERRbadpath);
1030 END_PROFILE(SMBsetatr);
1033 reply_nterror(req, status);
1034 END_PROFILE(SMBsetatr);
1038 status = unix_convert(conn, fname, False, NULL, &sbuf);
1039 if (!NT_STATUS_IS_OK(status)) {
1040 reply_nterror(req, status);
1041 END_PROFILE(SMBsetatr);
1045 status = check_name(conn, fname);
1046 if (!NT_STATUS_IS_OK(status)) {
1047 reply_nterror(req, status);
1048 END_PROFILE(SMBsetatr);
1052 if (fname[0] == '.' && fname[1] == '\0') {
1054 * Not sure here is the right place to catch this
1055 * condition. Might be moved to somewhere else later -- vl
1057 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1058 END_PROFILE(SMBsetatr);
1062 mode = SVAL(req->inbuf,smb_vwv0);
1063 mtime = srv_make_unix_date3(req->inbuf+smb_vwv1);
1065 if (mode != FILE_ATTRIBUTE_NORMAL) {
1066 if (VALID_STAT_OF_DIR(sbuf))
1071 if (file_set_dosmode(conn,fname,mode,&sbuf,False) != 0) {
1072 reply_unixerror(req, ERRDOS, ERRnoaccess);
1073 END_PROFILE(SMBsetatr);
1078 if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) {
1079 reply_unixerror(req, ERRDOS, ERRnoaccess);
1080 END_PROFILE(SMBsetatr);
1084 reply_outbuf(req, 0, 0);
1086 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1088 END_PROFILE(SMBsetatr);
1092 /****************************************************************************
1094 ****************************************************************************/
1096 void reply_dskattr(connection_struct *conn, struct smb_request *req)
1098 SMB_BIG_UINT dfree,dsize,bsize;
1099 START_PROFILE(SMBdskattr);
1101 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1102 reply_unixerror(req, ERRHRD, ERRgeneral);
1103 END_PROFILE(SMBdskattr);
1107 reply_outbuf(req, 5, 0);
1109 if (Protocol <= PROTOCOL_LANMAN2) {
1110 double total_space, free_space;
1111 /* we need to scale this to a number that DOS6 can handle. We
1112 use floating point so we can handle large drives on systems
1113 that don't have 64 bit integers
1115 we end up displaying a maximum of 2G to DOS systems
1117 total_space = dsize * (double)bsize;
1118 free_space = dfree * (double)bsize;
1120 dsize = (total_space+63*512) / (64*512);
1121 dfree = (free_space+63*512) / (64*512);
1123 if (dsize > 0xFFFF) dsize = 0xFFFF;
1124 if (dfree > 0xFFFF) dfree = 0xFFFF;
1126 SSVAL(req->outbuf,smb_vwv0,dsize);
1127 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1128 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1129 SSVAL(req->outbuf,smb_vwv3,dfree);
1131 SSVAL(req->outbuf,smb_vwv0,dsize);
1132 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1133 SSVAL(req->outbuf,smb_vwv2,512);
1134 SSVAL(req->outbuf,smb_vwv3,dfree);
1137 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1139 END_PROFILE(SMBdskattr);
1143 /****************************************************************************
1145 Can be called from SMBsearch, SMBffirst or SMBfunique.
1146 ****************************************************************************/
1148 void reply_search(connection_struct *conn, struct smb_request *req)
1157 unsigned int numentries = 0;
1158 unsigned int maxentries = 0;
1159 BOOL finished = False;
1165 BOOL check_descend = False;
1166 BOOL expect_close = False;
1168 BOOL mask_contains_wcard = False;
1169 BOOL allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1171 START_PROFILE(SMBsearch);
1174 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1175 END_PROFILE(SMBsearch);
1179 if (lp_posix_pathnames()) {
1180 reply_unknown_new(req, CVAL(req->inbuf, smb_com));
1181 END_PROFILE(SMBsearch);
1185 *mask = *directory = *fname = 0;
1187 /* If we were called as SMBffirst then we must expect close. */
1188 if(CVAL(req->inbuf,smb_com) == SMBffirst) {
1189 expect_close = True;
1192 reply_outbuf(req, 1, 3);
1193 maxentries = SVAL(req->inbuf,smb_vwv0);
1194 dirtype = SVAL(req->inbuf,smb_vwv1);
1195 p = smb_buf(req->inbuf) + 1;
1196 p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, path, p,
1197 sizeof(path), 0, STR_TERMINATE, &nt_status,
1198 &mask_contains_wcard);
1199 if (!NT_STATUS_IS_OK(nt_status)) {
1200 reply_nterror(req, nt_status);
1201 END_PROFILE(SMBsearch);
1205 nt_status = resolve_dfspath_wcard(conn,
1206 req->flags2 & FLAGS2_DFS_PATHNAMES,
1207 path, &mask_contains_wcard);
1208 if (!NT_STATUS_IS_OK(nt_status)) {
1209 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1210 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1211 ERRSRV, ERRbadpath);
1212 END_PROFILE(SMBsearch);
1215 reply_nterror(req, nt_status);
1216 END_PROFILE(SMBsearch);
1221 status_len = SVAL(p, 0);
1224 /* dirtype &= ~aDIR; */
1226 if (status_len == 0) {
1227 SMB_STRUCT_STAT sbuf;
1229 pstrcpy(directory,path);
1230 nt_status = unix_convert(conn, directory, True, NULL, &sbuf);
1231 if (!NT_STATUS_IS_OK(nt_status)) {
1232 reply_nterror(req, nt_status);
1233 END_PROFILE(SMBsearch);
1237 nt_status = check_name(conn, directory);
1238 if (!NT_STATUS_IS_OK(nt_status)) {
1239 reply_nterror(req, nt_status);
1240 END_PROFILE(SMBsearch);
1244 p = strrchr_m(directory,'/');
1246 pstrcpy(mask,directory);
1247 pstrcpy(directory,".");
1253 if (*directory == '\0') {
1254 pstrcpy(directory,".");
1256 memset((char *)status,'\0',21);
1257 SCVAL(status,0,(dirtype & 0x1F));
1261 memcpy(status,p,21);
1262 status_dirtype = CVAL(status,0) & 0x1F;
1263 if (status_dirtype != (dirtype & 0x1F)) {
1264 dirtype = status_dirtype;
1267 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1268 if (!conn->dirptr) {
1271 string_set(&conn->dirpath,dptr_path(dptr_num));
1272 pstrcpy(mask, dptr_wcard(dptr_num));
1274 * For a 'continue' search we have no string. So
1275 * check from the initial saved string.
1277 mask_contains_wcard = ms_has_wild(mask);
1280 if (status_len == 0) {
1281 nt_status = dptr_create(conn,
1287 mask_contains_wcard,
1290 if (!NT_STATUS_IS_OK(nt_status)) {
1291 reply_nterror(req, nt_status);
1292 END_PROFILE(SMBsearch);
1295 dptr_num = dptr_dnum(conn->dirptr);
1297 dirtype = dptr_attr(dptr_num);
1300 DEBUG(4,("dptr_num is %d\n",dptr_num));
1302 if ((dirtype&0x1F) == aVOLID) {
1303 char buf[DIR_STRUCT_SIZE];
1304 memcpy(buf,status,21);
1305 make_dir_struct(buf,"???????????",volume_label(SNUM(conn)),
1306 0,aVOLID,0,!allow_long_path_components);
1307 dptr_fill(buf+12,dptr_num);
1308 if (dptr_zero(buf+12) && (status_len==0)) {
1313 if (message_push_blob(&req->outbuf,
1314 data_blob_const(buf, sizeof(buf)))
1316 reply_nterror(req, NT_STATUS_NO_MEMORY);
1317 END_PROFILE(SMBsearch);
1325 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1328 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1329 conn->dirpath,lp_dontdescend(SNUM(conn))));
1330 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1331 check_descend = True;
1334 for (i=numentries;(i<maxentries) && !finished;i++) {
1335 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1337 char buf[DIR_STRUCT_SIZE];
1338 memcpy(buf,status,21);
1339 make_dir_struct(buf,mask,fname,size, mode,date,
1340 !allow_long_path_components);
1341 if (!dptr_fill(buf+12,dptr_num)) {
1344 if (message_push_blob(&req->outbuf,
1345 data_blob_const(buf, sizeof(buf)))
1347 reply_nterror(req, NT_STATUS_NO_MEMORY);
1348 END_PROFILE(SMBsearch);
1358 /* If we were called as SMBffirst with smb_search_id == NULL
1359 and no entries were found then return error and close dirptr
1362 if (numentries == 0) {
1363 dptr_close(&dptr_num);
1364 } else if(expect_close && status_len == 0) {
1365 /* Close the dptr - we know it's gone */
1366 dptr_close(&dptr_num);
1369 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1370 if(dptr_num >= 0 && CVAL(req->inbuf,smb_com) == SMBfunique) {
1371 dptr_close(&dptr_num);
1374 if ((numentries == 0) && !mask_contains_wcard) {
1375 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1376 END_PROFILE(SMBsearch);
1380 SSVAL(req->outbuf,smb_vwv0,numentries);
1381 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1382 SCVAL(smb_buf(req->outbuf),0,5);
1383 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1385 /* The replies here are never long name. */
1386 SSVAL(req->outbuf, smb_flg2,
1387 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1388 if (!allow_long_path_components) {
1389 SSVAL(req->outbuf, smb_flg2,
1390 SVAL(req->outbuf, smb_flg2)
1391 & (~FLAGS2_LONG_PATH_COMPONENTS));
1394 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1395 SSVAL(req->outbuf, smb_flg2,
1396 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1398 if ((! *directory) && dptr_path(dptr_num))
1399 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1401 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1402 smb_fn_name(CVAL(req->inbuf,smb_com)),
1403 mask, directory, dirtype, numentries, maxentries ) );
1405 END_PROFILE(SMBsearch);
1409 /****************************************************************************
1410 Reply to a fclose (stop directory search).
1411 ****************************************************************************/
1413 void reply_fclose(connection_struct *conn, struct smb_request *req)
1421 BOOL path_contains_wcard = False;
1423 START_PROFILE(SMBfclose);
1425 if (lp_posix_pathnames()) {
1426 reply_unknown_new(req, CVAL(req->inbuf, smb_com));
1427 END_PROFILE(SMBfclose);
1431 p = smb_buf(req->inbuf) + 1;
1432 p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, path, p,
1433 sizeof(path), 0, STR_TERMINATE, &err,
1434 &path_contains_wcard);
1435 if (!NT_STATUS_IS_OK(err)) {
1436 reply_nterror(req, err);
1437 END_PROFILE(SMBfclose);
1441 status_len = SVAL(p,0);
1444 if (status_len == 0) {
1445 reply_doserror(req, ERRSRV, ERRsrverror);
1446 END_PROFILE(SMBfclose);
1450 memcpy(status,p,21);
1452 if(dptr_fetch(status+12,&dptr_num)) {
1453 /* Close the dptr - we know it's gone */
1454 dptr_close(&dptr_num);
1457 reply_outbuf(req, 1, 0);
1458 SSVAL(req->outbuf,smb_vwv0,0);
1460 DEBUG(3,("search close\n"));
1462 END_PROFILE(SMBfclose);
1466 /****************************************************************************
1468 ****************************************************************************/
1470 void reply_open(connection_struct *conn, struct smb_request *req)
1477 SMB_STRUCT_STAT sbuf;
1484 uint32 create_disposition;
1485 uint32 create_options = 0;
1488 START_PROFILE(SMBopen);
1491 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1492 END_PROFILE(SMBopen);
1496 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1497 deny_mode = SVAL(req->inbuf,smb_vwv0);
1498 dos_attr = SVAL(req->inbuf,smb_vwv1);
1500 srvstr_get_path((char *)req->inbuf, req->flags2, fname,
1501 smb_buf(req->inbuf)+1, sizeof(fname), 0,
1502 STR_TERMINATE, &status);
1503 if (!NT_STATUS_IS_OK(status)) {
1504 reply_nterror(req, status);
1505 END_PROFILE(SMBopen);
1509 status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
1511 if (!NT_STATUS_IS_OK(status)) {
1512 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1513 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1514 ERRSRV, ERRbadpath);
1515 END_PROFILE(SMBopen);
1518 reply_nterror(req, status);
1519 END_PROFILE(SMBopen);
1523 status = unix_convert(conn, fname, False, NULL, &sbuf);
1524 if (!NT_STATUS_IS_OK(status)) {
1525 reply_nterror(req, status);
1526 END_PROFILE(SMBopen);
1530 status = check_name(conn, fname);
1531 if (!NT_STATUS_IS_OK(status)) {
1532 reply_nterror(req, status);
1533 END_PROFILE(SMBopen);
1537 if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
1538 &access_mask, &share_mode, &create_disposition, &create_options)) {
1539 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1540 END_PROFILE(SMBopen);
1544 status = open_file_ntcreate(conn, req, fname, &sbuf,
1553 if (!NT_STATUS_IS_OK(status)) {
1554 if (open_was_deferred(req->mid)) {
1555 /* We have re-scheduled this call. */
1556 END_PROFILE(SMBopen);
1559 reply_nterror(req, status);
1560 END_PROFILE(SMBopen);
1564 size = sbuf.st_size;
1565 fattr = dos_mode(conn,fname,&sbuf);
1566 mtime = sbuf.st_mtime;
1569 DEBUG(3,("attempt to open a directory %s\n",fname));
1570 close_file(fsp,ERROR_CLOSE);
1571 reply_doserror(req, ERRDOS,ERRnoaccess);
1572 END_PROFILE(SMBopen);
1576 reply_outbuf(req, 7, 0);
1577 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1578 SSVAL(req->outbuf,smb_vwv1,fattr);
1579 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1580 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1582 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1584 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1585 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1587 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1588 SCVAL(req->outbuf,smb_flg,
1589 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1592 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1593 SCVAL(req->outbuf,smb_flg,
1594 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1596 END_PROFILE(SMBopen);
1600 /****************************************************************************
1601 Reply to an open and X.
1602 ****************************************************************************/
1604 void reply_open_and_X(connection_struct *conn, struct smb_request *req)
1610 /* Breakout the oplock request bits so we can set the
1611 reply bits separately. */
1612 int ex_oplock_request;
1613 int core_oplock_request;
1616 int smb_sattr = SVAL(req->inbuf,smb_vwv4);
1617 uint32 smb_time = make_unix_date3(req->inbuf+smb_vwv6);
1622 SMB_STRUCT_STAT sbuf;
1626 SMB_BIG_UINT allocation_size;
1627 ssize_t retval = -1;
1630 uint32 create_disposition;
1631 uint32 create_options = 0;
1633 START_PROFILE(SMBopenX);
1635 if (req->wct < 15) {
1636 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1637 END_PROFILE(SMBopenX);
1641 open_flags = SVAL(req->inbuf,smb_vwv2);
1642 deny_mode = SVAL(req->inbuf,smb_vwv3);
1643 smb_attr = SVAL(req->inbuf,smb_vwv5);
1644 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1645 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1646 oplock_request = ex_oplock_request | core_oplock_request;
1647 smb_ofun = SVAL(req->inbuf,smb_vwv8);
1648 allocation_size = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv9);
1650 /* If it's an IPC, pass off the pipe handler. */
1652 if (lp_nt_pipe_support()) {
1653 reply_open_pipe_and_X(conn, req);
1655 reply_doserror(req, ERRSRV, ERRaccess);
1657 END_PROFILE(SMBopenX);
1661 /* XXXX we need to handle passed times, sattr and flags */
1662 srvstr_get_path((char *)req->inbuf, req->flags2, fname,
1663 smb_buf(req->inbuf), sizeof(fname), 0, STR_TERMINATE,
1665 if (!NT_STATUS_IS_OK(status)) {
1666 reply_nterror(req, status);
1667 END_PROFILE(SMBopenX);
1671 status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
1673 if (!NT_STATUS_IS_OK(status)) {
1674 END_PROFILE(SMBopenX);
1675 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1676 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1677 ERRSRV, ERRbadpath);
1680 reply_nterror(req, status);
1684 status = unix_convert(conn, fname, False, NULL, &sbuf);
1685 if (!NT_STATUS_IS_OK(status)) {
1686 reply_nterror(req, status);
1687 END_PROFILE(SMBopenX);
1691 status = check_name(conn, fname);
1692 if (!NT_STATUS_IS_OK(status)) {
1693 reply_nterror(req, status);
1694 END_PROFILE(SMBopenX);
1698 if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
1701 &create_disposition,
1703 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1704 END_PROFILE(SMBopenX);
1708 status = open_file_ntcreate(conn, req, fname, &sbuf,
1717 if (!NT_STATUS_IS_OK(status)) {
1718 END_PROFILE(SMBopenX);
1719 if (open_was_deferred(req->mid)) {
1720 /* We have re-scheduled this call. */
1721 END_PROFILE(SMBopenX);
1724 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1726 * We hit an existing file, and if we're returning DOS
1727 * error codes OBJECT_NAME_COLLISION would map to
1728 * ERRDOS/183, we need to return ERRDOS/80, see bug
1731 reply_botherror(req, NT_STATUS_OBJECT_NAME_COLLISION,
1732 ERRDOS, ERRfilexists);
1733 END_PROFILE(SMBopenX);
1736 reply_nterror(req, status);
1737 END_PROFILE(SMBopenX);
1741 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1742 if the file is truncated or created. */
1743 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1744 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1745 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1746 close_file(fsp,ERROR_CLOSE);
1747 reply_nterror(req, NT_STATUS_DISK_FULL);
1748 END_PROFILE(SMBopenX);
1751 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1753 close_file(fsp,ERROR_CLOSE);
1754 reply_nterror(req, NT_STATUS_DISK_FULL);
1755 END_PROFILE(SMBopenX);
1758 sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
1761 fattr = dos_mode(conn,fname,&sbuf);
1762 mtime = sbuf.st_mtime;
1764 close_file(fsp,ERROR_CLOSE);
1765 reply_doserror(req, ERRDOS, ERRnoaccess);
1766 END_PROFILE(SMBopenX);
1770 /* If the caller set the extended oplock request bit
1771 and we granted one (by whatever means) - set the
1772 correct bit for extended oplock reply.
1775 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1776 smb_action |= EXTENDED_OPLOCK_GRANTED;
1779 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1780 smb_action |= EXTENDED_OPLOCK_GRANTED;
1783 /* If the caller set the core oplock request bit
1784 and we granted one (by whatever means) - set the
1785 correct bit for core oplock reply.
1788 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1789 reply_outbuf(req, 19, 0);
1791 reply_outbuf(req, 15, 0);
1794 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1795 SCVAL(req->outbuf, smb_flg,
1796 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1799 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1800 SCVAL(req->outbuf, smb_flg,
1801 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1804 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1805 SSVAL(req->outbuf,smb_vwv3,fattr);
1806 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1807 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1809 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
1811 SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_size);
1812 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1813 SSVAL(req->outbuf,smb_vwv11,smb_action);
1815 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1816 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1819 END_PROFILE(SMBopenX);
1820 chain_reply_new(req);
1824 /****************************************************************************
1825 Reply to a SMBulogoffX.
1826 conn POINTER CAN BE NULL HERE !
1827 ****************************************************************************/
1829 void reply_ulogoffX(connection_struct *conn, struct smb_request *req)
1833 START_PROFILE(SMBulogoffX);
1835 vuser = get_valid_user_struct(req->vuid);
1838 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
1842 /* in user level security we are supposed to close any files
1843 open by this user */
1844 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
1845 file_close_user(req->vuid);
1848 invalidate_vuid(req->vuid);
1850 reply_outbuf(req, 2, 0);
1852 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
1854 END_PROFILE(SMBulogoffX);
1855 chain_reply_new(req);
1858 /****************************************************************************
1859 Reply to a mknew or a create.
1860 ****************************************************************************/
1862 void reply_mknew(connection_struct *conn, struct smb_request *req)
1867 struct timespec ts[2];
1869 int oplock_request = 0;
1870 SMB_STRUCT_STAT sbuf;
1872 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1873 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1874 uint32 create_disposition;
1875 uint32 create_options = 0;
1877 START_PROFILE(SMBcreate);
1880 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1881 END_PROFILE(SMBcreate);
1885 fattr = SVAL(req->inbuf,smb_vwv0);
1886 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1887 com = SVAL(req->inbuf,smb_com);
1889 ts[1] =convert_time_t_to_timespec(
1890 srv_make_unix_date3(req->inbuf + smb_vwv1));
1893 srvstr_get_path((char *)req->inbuf, req->flags2, fname,
1894 smb_buf(req->inbuf) + 1, sizeof(fname), 0,
1895 STR_TERMINATE, &status);
1896 if (!NT_STATUS_IS_OK(status)) {
1897 reply_nterror(req, status);
1898 END_PROFILE(SMBcreate);
1902 status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
1904 if (!NT_STATUS_IS_OK(status)) {
1905 END_PROFILE(SMBcreate);
1906 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1907 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1908 ERRSRV, ERRbadpath);
1911 reply_nterror(req, status);
1915 status = unix_convert(conn, fname, False, NULL, &sbuf);
1916 if (!NT_STATUS_IS_OK(status)) {
1917 reply_nterror(req, status);
1918 END_PROFILE(SMBcreate);
1922 status = check_name(conn, fname);
1923 if (!NT_STATUS_IS_OK(status)) {
1924 reply_nterror(req, status);
1925 END_PROFILE(SMBcreate);
1929 if (fattr & aVOLID) {
1930 DEBUG(0,("Attempt to create file (%s) with volid set - "
1931 "please report this\n", fname));
1934 if(com == SMBmknew) {
1935 /* We should fail if file exists. */
1936 create_disposition = FILE_CREATE;
1938 /* Create if file doesn't exist, truncate if it does. */
1939 create_disposition = FILE_OVERWRITE_IF;
1942 /* Open file using ntcreate. */
1943 status = open_file_ntcreate(conn, req, fname, &sbuf,
1952 if (!NT_STATUS_IS_OK(status)) {
1953 END_PROFILE(SMBcreate);
1954 if (open_was_deferred(req->mid)) {
1955 /* We have re-scheduled this call. */
1958 reply_nterror(req, status);
1962 ts[0] = get_atimespec(&sbuf); /* atime. */
1963 file_ntimes(conn, fname, ts);
1965 reply_outbuf(req, 1, 0);
1967 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1969 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1970 SCVAL(req->outbuf,smb_flg,
1971 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1974 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1975 SCVAL(req->outbuf,smb_flg,
1976 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1979 DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
1980 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
1981 fname, fsp->fh->fd, (unsigned int)fattr ) );
1983 END_PROFILE(SMBcreate);
1987 /****************************************************************************
1988 Reply to a create temporary file.
1989 ****************************************************************************/
1991 void reply_ctemp(connection_struct *conn, struct smb_request *req)
1998 SMB_STRUCT_STAT sbuf;
2002 START_PROFILE(SMBctemp);
2005 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2006 END_PROFILE(SMBctemp);
2010 fattr = SVAL(req->inbuf,smb_vwv0);
2011 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2013 srvstr_get_path((char *)req->inbuf, req->flags2, fname,
2014 smb_buf(req->inbuf)+1, sizeof(fname), 0, STR_TERMINATE,
2016 if (!NT_STATUS_IS_OK(status)) {
2017 reply_nterror(req, status);
2018 END_PROFILE(SMBctemp);
2022 pstrcat(fname,"/TMXXXXXX");
2024 pstrcat(fname,"TMXXXXXX");
2027 status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
2029 if (!NT_STATUS_IS_OK(status)) {
2030 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2031 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2032 ERRSRV, ERRbadpath);
2033 END_PROFILE(SMBctemp);
2036 reply_nterror(req, status);
2037 END_PROFILE(SMBctemp);
2041 status = unix_convert(conn, fname, False, NULL, &sbuf);
2042 if (!NT_STATUS_IS_OK(status)) {
2043 reply_nterror(req, status);
2044 END_PROFILE(SMBctemp);
2048 status = check_name(conn, fname);
2049 if (!NT_STATUS_IS_OK(status)) {
2050 reply_nterror(req, status);
2051 END_PROFILE(SMBctemp);
2055 tmpfd = smb_mkstemp(fname);
2057 reply_unixerror(req, ERRDOS, ERRnoaccess);
2058 END_PROFILE(SMBctemp);
2062 SMB_VFS_STAT(conn,fname,&sbuf);
2064 /* We should fail if file does not exist. */
2065 status = open_file_ntcreate(conn, req, fname, &sbuf,
2066 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
2067 FILE_SHARE_READ|FILE_SHARE_WRITE,
2074 /* close fd from smb_mkstemp() */
2077 if (!NT_STATUS_IS_OK(status)) {
2078 if (open_was_deferred(req->mid)) {
2079 /* We have re-scheduled this call. */
2080 END_PROFILE(SMBctemp);
2083 reply_nterror(req, status);
2084 END_PROFILE(SMBctemp);
2088 reply_outbuf(req, 1, 0);
2089 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2091 /* the returned filename is relative to the directory */
2092 s = strrchr_m(fname, '/');
2100 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2101 thing in the byte section. JRA */
2102 SSVALS(p, 0, -1); /* what is this? not in spec */
2104 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2106 reply_nterror(req, NT_STATUS_NO_MEMORY);
2107 END_PROFILE(SMBctemp);
2111 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2112 SCVAL(req->outbuf, smb_flg,
2113 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2116 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2117 SCVAL(req->outbuf, smb_flg,
2118 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2121 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
2122 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
2123 (unsigned int)sbuf.st_mode ) );
2125 END_PROFILE(SMBctemp);
2129 /*******************************************************************
2130 Check if a user is allowed to rename a file.
2131 ********************************************************************/
2133 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2134 uint16 dirtype, SMB_STRUCT_STAT *pst)
2138 if (!CAN_WRITE(conn)) {
2139 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2142 fmode = dos_mode(conn, fsp->fsp_name, pst);
2143 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2144 return NT_STATUS_NO_SUCH_FILE;
2147 if (S_ISDIR(pst->st_mode)) {
2148 return NT_STATUS_OK;
2151 if (fsp->access_mask & DELETE_ACCESS) {
2152 return NT_STATUS_OK;
2155 return NT_STATUS_ACCESS_DENIED;
2158 /*******************************************************************
2159 * unlink a file with all relevant access checks
2160 *******************************************************************/
2162 static NTSTATUS do_unlink(connection_struct *conn, struct smb_request *req,
2163 char *fname, uint32 dirtype)
2165 SMB_STRUCT_STAT sbuf;
2168 uint32 dirtype_orig = dirtype;
2171 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2173 if (!CAN_WRITE(conn)) {
2174 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2177 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
2178 return map_nt_error_from_unix(errno);
2181 fattr = dos_mode(conn,fname,&sbuf);
2183 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2184 dirtype = aDIR|aARCH|aRONLY;
2187 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2189 return NT_STATUS_NO_SUCH_FILE;
2192 if (!dir_check_ftype(conn, fattr, dirtype)) {
2194 return NT_STATUS_FILE_IS_A_DIRECTORY;
2196 return NT_STATUS_NO_SUCH_FILE;
2199 if (dirtype_orig & 0x8000) {
2200 /* These will never be set for POSIX. */
2201 return NT_STATUS_NO_SUCH_FILE;
2205 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2206 return NT_STATUS_FILE_IS_A_DIRECTORY;
2209 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2210 return NT_STATUS_NO_SUCH_FILE;
2213 if (dirtype & 0xFF00) {
2214 /* These will never be set for POSIX. */
2215 return NT_STATUS_NO_SUCH_FILE;
2220 return NT_STATUS_NO_SUCH_FILE;
2223 /* Can't delete a directory. */
2225 return NT_STATUS_FILE_IS_A_DIRECTORY;
2230 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2231 return NT_STATUS_OBJECT_NAME_INVALID;
2232 #endif /* JRATEST */
2234 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2236 On a Windows share, a file with read-only dosmode can be opened with
2237 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2238 fails with NT_STATUS_CANNOT_DELETE error.
2240 This semantic causes a problem that a user can not
2241 rename a file with read-only dosmode on a Samba share
2242 from a Windows command prompt (i.e. cmd.exe, but can rename
2243 from Windows Explorer).
2246 if (!lp_delete_readonly(SNUM(conn))) {
2247 if (fattr & aRONLY) {
2248 return NT_STATUS_CANNOT_DELETE;
2252 /* On open checks the open itself will check the share mode, so
2253 don't do it here as we'll get it wrong. */
2255 status = open_file_ntcreate(conn, req, fname, &sbuf,
2260 FILE_ATTRIBUTE_NORMAL,
2261 req != NULL ? 0 : INTERNAL_OPEN_ONLY,
2264 if (!NT_STATUS_IS_OK(status)) {
2265 DEBUG(10, ("open_file_ntcreate failed: %s\n",
2266 nt_errstr(status)));
2270 /* The set is across all open files on this dev/inode pair. */
2271 if (!set_delete_on_close(fsp, True, ¤t_user.ut)) {
2272 close_file(fsp, NORMAL_CLOSE);
2273 return NT_STATUS_ACCESS_DENIED;
2276 return close_file(fsp,NORMAL_CLOSE);
2279 /****************************************************************************
2280 The guts of the unlink command, split out so it may be called by the NT SMB
2282 ****************************************************************************/
2284 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2285 uint32 dirtype, char *name, BOOL has_wild)
2291 NTSTATUS status = NT_STATUS_OK;
2292 SMB_STRUCT_STAT sbuf;
2294 *directory = *mask = 0;
2296 status = unix_convert(conn, name, has_wild, NULL, &sbuf);
2297 if (!NT_STATUS_IS_OK(status)) {
2301 p = strrchr_m(name,'/');
2303 pstrcpy(directory,".");
2307 pstrcpy(directory,name);
2312 * We should only check the mangled cache
2313 * here if unix_convert failed. This means
2314 * that the path in 'mask' doesn't exist
2315 * on the file system and so we need to look
2316 * for a possible mangle. This patch from
2317 * Tine Smukavec <valentin.smukavec@hermes.si>.
2320 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params))
2321 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
2324 pstrcat(directory,"/");
2325 pstrcat(directory,mask);
2327 dirtype = FILE_ATTRIBUTE_NORMAL;
2330 status = check_name(conn, directory);
2331 if (!NT_STATUS_IS_OK(status)) {
2335 status = do_unlink(conn, req, directory, dirtype);
2336 if (!NT_STATUS_IS_OK(status)) {
2342 struct smb_Dir *dir_hnd = NULL;
2346 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2347 return NT_STATUS_OBJECT_NAME_INVALID;
2350 if (strequal(mask,"????????.???")) {
2354 status = check_name(conn, directory);
2355 if (!NT_STATUS_IS_OK(status)) {
2359 dir_hnd = OpenDir(conn, directory, mask, dirtype);
2360 if (dir_hnd == NULL) {
2361 return map_nt_error_from_unix(errno);
2364 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2365 the pattern matches against the long name, otherwise the short name
2366 We don't implement this yet XXXX
2369 status = NT_STATUS_NO_SUCH_FILE;
2371 while ((dname = ReadDirName(dir_hnd, &offset))) {
2374 pstrcpy(fname,dname);
2376 if (!is_visible_file(conn, directory, dname, &st, True)) {
2380 /* Quick check for "." and ".." */
2381 if (fname[0] == '.') {
2382 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
2387 if(!mask_match(fname, mask, conn->case_sensitive)) {
2391 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2393 status = check_name(conn, fname);
2394 if (!NT_STATUS_IS_OK(status)) {
2399 status = do_unlink(conn, req, fname, dirtype);
2400 if (!NT_STATUS_IS_OK(status)) {
2405 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",
2411 if (count == 0 && NT_STATUS_IS_OK(status)) {
2412 status = map_nt_error_from_unix(errno);
2418 /****************************************************************************
2420 ****************************************************************************/
2422 void reply_unlink(connection_struct *conn, struct smb_request *req)
2427 BOOL path_contains_wcard = False;
2429 START_PROFILE(SMBunlink);
2432 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2433 END_PROFILE(SMBunlink);
2437 dirtype = SVAL(req->inbuf,smb_vwv0);
2439 srvstr_get_path_wcard((char *)req->inbuf, req->flags2, name,
2440 smb_buf(req->inbuf) + 1, sizeof(name), 0,
2441 STR_TERMINATE, &status, &path_contains_wcard);
2442 if (!NT_STATUS_IS_OK(status)) {
2443 reply_nterror(req, status);
2444 END_PROFILE(SMBunlink);
2448 status = resolve_dfspath_wcard(conn,
2449 req->flags2 & FLAGS2_DFS_PATHNAMES,
2450 name, &path_contains_wcard);
2451 if (!NT_STATUS_IS_OK(status)) {
2452 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2453 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2454 ERRSRV, ERRbadpath);
2455 END_PROFILE(SMBunlink);
2458 reply_nterror(req, status);
2459 END_PROFILE(SMBunlink);
2463 DEBUG(3,("reply_unlink : %s\n",name));
2465 status = unlink_internals(conn, req, dirtype, name,
2466 path_contains_wcard);
2467 if (!NT_STATUS_IS_OK(status)) {
2468 if (open_was_deferred(req->mid)) {
2469 /* We have re-scheduled this call. */
2470 END_PROFILE(SMBunlink);
2473 reply_nterror(req, status);
2474 END_PROFILE(SMBunlink);
2478 reply_outbuf(req, 0, 0);
2479 END_PROFILE(SMBunlink);
2484 /****************************************************************************
2486 ****************************************************************************/
2488 static void fail_readraw(void)
2491 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2493 exit_server_cleanly(errstr);
2496 /****************************************************************************
2497 Fake (read/write) sendfile. Returns -1 on read or write fail.
2498 ****************************************************************************/
2500 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2504 size_t tosend = nread;
2511 bufsize = MIN(nread, 65536);
2513 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2517 while (tosend > 0) {
2521 if (tosend > bufsize) {
2526 ret = read_file(fsp,buf,startpos,cur_read);
2532 /* If we had a short read, fill with zeros. */
2533 if (ret < cur_read) {
2534 memset(buf, '\0', cur_read - ret);
2537 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2542 startpos += cur_read;
2546 return (ssize_t)nread;
2549 /****************************************************************************
2550 Return a readbraw error (4 bytes of zero).
2551 ****************************************************************************/
2553 static void reply_readbraw_error(void)
2557 if (write_data(smbd_server_fd(),header,4) != 4) {
2562 /****************************************************************************
2563 Use sendfile in readbraw.
2564 ****************************************************************************/
2566 void send_file_readbraw(connection_struct *conn,
2572 char *outbuf = NULL;
2575 #if defined(WITH_SENDFILE)
2577 * We can only use sendfile on a non-chained packet
2578 * but we can use on a non-oplocked file. tridge proved this
2579 * on a train in Germany :-). JRA.
2580 * reply_readbraw has already checked the length.
2583 if ( (chain_size == 0) && (nread > 0) &&
2584 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2586 DATA_BLOB header_blob;
2588 _smb_setlen(header,nread);
2589 header_blob = data_blob_const(header, 4);
2591 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd,
2592 &header_blob, startpos, nread) == -1) {
2593 /* Returning ENOSYS means no data at all was sent.
2594 * Do this as a normal read. */
2595 if (errno == ENOSYS) {
2596 goto normal_readbraw;
2600 * Special hack for broken Linux with no working sendfile. If we
2601 * return EINTR we sent the header but not the rest of the data.
2602 * Fake this up by doing read/write calls.
2604 if (errno == EINTR) {
2605 /* Ensure we don't do this again. */
2606 set_use_sendfile(SNUM(conn), False);
2607 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2609 if (fake_sendfile(fsp, startpos, nread) == -1) {
2610 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2611 fsp->fsp_name, strerror(errno) ));
2612 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2617 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2618 fsp->fsp_name, strerror(errno) ));
2619 exit_server_cleanly("send_file_readbraw sendfile failed");
2628 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2630 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2631 (unsigned)(nread+4)));
2632 reply_readbraw_error();
2637 ret = read_file(fsp,outbuf+4,startpos,nread);
2638 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2647 _smb_setlen(outbuf,ret);
2648 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2651 TALLOC_FREE(outbuf);
2654 /****************************************************************************
2655 Reply to a readbraw (core+ protocol).
2656 ****************************************************************************/
2658 void reply_readbraw(connection_struct *conn, struct smb_request *req)
2660 ssize_t maxcount,mincount;
2667 START_PROFILE(SMBreadbraw);
2669 if (srv_is_signing_active()) {
2670 exit_server_cleanly("reply_readbraw: SMB signing is active - "
2671 "raw reads/writes are disallowed.");
2675 reply_readbraw_error();
2676 END_PROFILE(SMBreadbraw);
2681 * Special check if an oplock break has been issued
2682 * and the readraw request croses on the wire, we must
2683 * return a zero length response here.
2686 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
2689 * We have to do a check_fsp by hand here, as
2690 * we must always return 4 zero bytes on error,
2694 if (!fsp || !conn || conn != fsp->conn ||
2695 current_user.vuid != fsp->vuid ||
2696 fsp->is_directory || fsp->fh->fd == -1) {
2698 * fsp could be NULL here so use the value from the packet. JRA.
2700 DEBUG(3,("reply_readbraw: fnum %d not valid "
2702 (int)SVAL(req->inbuf,smb_vwv0)));
2703 reply_readbraw_error();
2704 END_PROFILE(SMBreadbraw);
2708 /* Do a "by hand" version of CHECK_READ. */
2709 if (!(fsp->can_read ||
2710 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
2711 (fsp->access_mask & FILE_EXECUTE)))) {
2712 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
2713 (int)SVAL(req->inbuf,smb_vwv0)));
2714 reply_readbraw_error();
2715 END_PROFILE(SMBreadbraw);
2719 flush_write_cache(fsp, READRAW_FLUSH);
2721 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv1);
2722 if(req->wct == 10) {
2724 * This is a large offset (64 bit) read.
2726 #ifdef LARGE_SMB_OFF_T
2728 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv8)) << 32);
2730 #else /* !LARGE_SMB_OFF_T */
2733 * Ensure we haven't been sent a >32 bit offset.
2736 if(IVAL(req->inbuf,smb_vwv8) != 0) {
2737 DEBUG(0,("reply_readbraw: large offset "
2738 "(%x << 32) used and we don't support "
2739 "64 bit offsets.\n",
2740 (unsigned int)IVAL(req->inbuf,smb_vwv8) ));
2741 reply_readbraw_error();
2742 END_PROFILE(SMBreadbraw);
2746 #endif /* LARGE_SMB_OFF_T */
2749 DEBUG(0,("reply_readbraw: negative 64 bit "
2750 "readraw offset (%.0f) !\n",
2751 (double)startpos ));
2752 reply_readbraw_error();
2753 END_PROFILE(SMBreadbraw);
2758 maxcount = (SVAL(req->inbuf,smb_vwv3) & 0xFFFF);
2759 mincount = (SVAL(req->inbuf,smb_vwv4) & 0xFFFF);
2761 /* ensure we don't overrun the packet size */
2762 maxcount = MIN(65535,maxcount);
2764 if (is_locked(fsp,(uint32)req->smbpid,
2765 (SMB_BIG_UINT)maxcount,
2766 (SMB_BIG_UINT)startpos,
2768 reply_readbraw_error();
2769 END_PROFILE(SMBreadbraw);
2773 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2777 if (startpos >= size) {
2780 nread = MIN(maxcount,(size - startpos));
2783 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2784 if (nread < mincount)
2788 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
2789 "min=%lu nread=%lu\n",
2790 fsp->fnum, (double)startpos,
2791 (unsigned long)maxcount,
2792 (unsigned long)mincount,
2793 (unsigned long)nread ) );
2795 send_file_readbraw(conn, fsp, startpos, nread, mincount);
2797 DEBUG(5,("reply_readbraw finished\n"));
2798 END_PROFILE(SMBreadbraw);
2802 #define DBGC_CLASS DBGC_LOCKING
2804 /****************************************************************************
2805 Reply to a lockread (core+ protocol).
2806 ****************************************************************************/
2808 void reply_lockread(connection_struct *conn, struct smb_request *req)
2816 struct byte_range_lock *br_lck = NULL;
2818 START_PROFILE(SMBlockread);
2821 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2822 END_PROFILE(SMBlockread);
2826 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
2828 if (!check_fsp(conn, req, fsp, ¤t_user)) {
2829 END_PROFILE(SMBlockread);
2833 if (!CHECK_READ(fsp,req->inbuf)) {
2834 reply_doserror(req, ERRDOS, ERRbadaccess);
2835 END_PROFILE(SMBlockread);
2839 release_level_2_oplocks_on_change(fsp);
2841 numtoread = SVAL(req->inbuf,smb_vwv1);
2842 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
2844 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
2846 reply_outbuf(req, 5, numtoread + 3);
2848 data = smb_buf(req->outbuf) + 3;
2851 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2852 * protocol request that predates the read/write lock concept.
2853 * Thus instead of asking for a read lock here we need to ask
2854 * for a write lock. JRA.
2855 * Note that the requested lock size is unaffected by max_recv.
2858 br_lck = do_lock(smbd_messaging_context(),
2861 (SMB_BIG_UINT)numtoread,
2862 (SMB_BIG_UINT)startpos,
2865 False, /* Non-blocking lock. */
2868 TALLOC_FREE(br_lck);
2870 if (NT_STATUS_V(status)) {
2871 reply_nterror(req, status);
2872 END_PROFILE(SMBlockread);
2877 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2880 if (numtoread > max_recv) {
2881 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2882 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2883 (unsigned int)numtoread, (unsigned int)max_recv ));
2884 numtoread = MIN(numtoread,max_recv);
2886 nread = read_file(fsp,data,startpos,numtoread);
2889 reply_unixerror(req, ERRDOS, ERRnoaccess);
2890 END_PROFILE(SMBlockread);
2894 set_message(NULL, (char *)req->outbuf, 5, nread+3, False);
2896 SSVAL(req->outbuf,smb_vwv0,nread);
2897 SSVAL(req->outbuf,smb_vwv5,nread+3);
2898 SSVAL(smb_buf(req->outbuf),1,nread);
2900 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2901 fsp->fnum, (int)numtoread, (int)nread));
2903 END_PROFILE(SMBlockread);
2908 #define DBGC_CLASS DBGC_ALL
2910 /****************************************************************************
2912 ****************************************************************************/
2914 void reply_read(connection_struct *conn, struct smb_request *req)
2923 START_PROFILE(SMBread);
2926 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2927 END_PROFILE(SMBread);
2931 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
2933 if (!check_fsp(conn, req, fsp, ¤t_user)) {
2934 END_PROFILE(SMBread);
2938 if (!CHECK_READ(fsp,req->inbuf)) {
2939 reply_doserror(req, ERRDOS, ERRbadaccess);
2940 END_PROFILE(SMBread);
2944 numtoread = SVAL(req->inbuf,smb_vwv1);
2945 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
2947 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2950 * The requested read size cannot be greater than max_recv. JRA.
2952 if (numtoread > max_recv) {
2953 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2954 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2955 (unsigned int)numtoread, (unsigned int)max_recv ));
2956 numtoread = MIN(numtoread,max_recv);
2959 reply_outbuf(req, 5, numtoread+3);
2961 data = smb_buf(req->outbuf) + 3;
2963 if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtoread,
2964 (SMB_BIG_UINT)startpos, READ_LOCK)) {
2965 reply_doserror(req, ERRDOS,ERRlock);
2966 END_PROFILE(SMBread);
2971 nread = read_file(fsp,data,startpos,numtoread);
2974 reply_unixerror(req, ERRDOS,ERRnoaccess);
2975 END_PROFILE(SMBread);
2979 set_message(NULL, (char *)req->outbuf, 5, nread+3, False);
2981 SSVAL(req->outbuf,smb_vwv0,nread);
2982 SSVAL(req->outbuf,smb_vwv5,nread+3);
2983 SCVAL(smb_buf(req->outbuf),0,1);
2984 SSVAL(smb_buf(req->outbuf),1,nread);
2986 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2987 fsp->fnum, (int)numtoread, (int)nread ) );
2989 END_PROFILE(SMBread);
2993 /****************************************************************************
2995 ****************************************************************************/
2997 static int setup_readX_header(const uint8 *inbuf, uint8 *outbuf,
3003 outsize = set_message((char *)inbuf, (char *)outbuf,12,smb_maxcnt,
3005 data = smb_buf(outbuf);
3007 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3008 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3009 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
3010 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3011 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
3012 SCVAL(outbuf,smb_vwv0,0xFF);
3013 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3014 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3018 /****************************************************************************
3019 Reply to a read and X - possibly using sendfile.
3020 ****************************************************************************/
3022 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3023 files_struct *fsp, SMB_OFF_T startpos,
3026 SMB_STRUCT_STAT sbuf;
3029 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3030 reply_unixerror(req, ERRDOS, ERRnoaccess);
3034 if (startpos > sbuf.st_size) {
3036 } else if (smb_maxcnt > (sbuf.st_size - startpos)) {
3037 smb_maxcnt = (sbuf.st_size - startpos);
3040 if (smb_maxcnt == 0) {
3044 #if defined(WITH_SENDFILE)
3046 * We can only use sendfile on a non-chained packet
3047 * but we can use on a non-oplocked file. tridge proved this
3048 * on a train in Germany :-). JRA.
3051 if ((chain_size == 0) && (CVAL(req->inbuf,smb_vwv0) == 0xFF) &&
3052 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
3053 uint8 headerbuf[smb_size + 12 * 2];
3057 * Set up the packet header before send. We
3058 * assume here the sendfile will work (get the
3059 * correct amount of data).
3062 header = data_blob_const(headerbuf, sizeof(headerbuf));
3064 construct_reply_common((char *)req->inbuf, (char *)headerbuf);
3065 setup_readX_header(req->inbuf, headerbuf, smb_maxcnt);
3067 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
3068 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
3069 if (errno == ENOSYS) {
3074 * Special hack for broken Linux with no working sendfile. If we
3075 * return EINTR we sent the header but not the rest of the data.
3076 * Fake this up by doing read/write calls.
3079 if (errno == EINTR) {
3080 /* Ensure we don't do this again. */
3081 set_use_sendfile(SNUM(conn), False);
3082 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3083 nread = fake_sendfile(fsp, startpos,
3086 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3087 fsp->fsp_name, strerror(errno) ));
3088 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3090 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3091 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3092 /* No outbuf here means successful sendfile. */
3093 TALLOC_FREE(req->outbuf);
3097 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3098 fsp->fsp_name, strerror(errno) ));
3099 exit_server_cleanly("send_file_readX sendfile failed");
3102 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3103 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3104 /* No outbuf here means successful sendfile. */
3105 TALLOC_FREE(req->outbuf);
3113 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3114 uint8 headerbuf[smb_size + 2*12];
3116 construct_reply_common((char *)req->inbuf, (char *)headerbuf);
3117 setup_readX_header(req->inbuf, headerbuf, smb_maxcnt);
3119 /* Send out the header. */
3120 if (write_data(smbd_server_fd(), (char *)headerbuf,
3121 sizeof(headerbuf)) != sizeof(headerbuf)) {
3122 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3123 fsp->fsp_name, strerror(errno) ));
3124 exit_server_cleanly("send_file_readX sendfile failed");
3126 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3128 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3129 fsp->fsp_name, strerror(errno) ));
3130 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3132 TALLOC_FREE(req->outbuf);
3135 reply_outbuf(req, 12, smb_maxcnt);
3137 nread = read_file(fsp, smb_buf(req->outbuf), startpos,
3140 reply_unixerror(req, ERRDOS, ERRnoaccess);
3144 setup_readX_header(req->inbuf, req->outbuf, nread);
3146 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3147 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3149 chain_reply_new(req);
3155 /****************************************************************************
3156 Reply to a read and X.
3157 ****************************************************************************/
3159 void reply_read_and_X(connection_struct *conn, struct smb_request *req)
3164 BOOL big_readX = False;
3166 size_t smb_mincnt = SVAL(req->inbuf,smb_vwv6);
3169 START_PROFILE(SMBreadX);
3171 if ((req->wct != 10) && (req->wct != 12)) {
3172 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3176 fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
3177 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
3178 smb_maxcnt = SVAL(req->inbuf,smb_vwv5);
3180 /* If it's an IPC, pass off the pipe handler. */
3182 reply_pipe_read_and_X(req);
3183 END_PROFILE(SMBreadX);
3187 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3188 END_PROFILE(SMBreadX);
3192 if (!CHECK_READ(fsp,req->inbuf)) {
3193 reply_doserror(req, ERRDOS,ERRbadaccess);
3194 END_PROFILE(SMBreadX);
3198 if (global_client_caps & CAP_LARGE_READX) {
3199 size_t upper_size = SVAL(req->inbuf,smb_vwv7);
3200 smb_maxcnt |= (upper_size<<16);
3201 if (upper_size > 1) {
3202 /* Can't do this on a chained packet. */
3203 if ((CVAL(req->inbuf,smb_vwv0) != 0xFF)) {
3204 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3205 END_PROFILE(SMBreadX);
3208 /* We currently don't do this on signed or sealed data. */
3209 if (srv_is_signing_active() || srv_encryption_on()) {
3210 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3211 END_PROFILE(SMBreadX);
3214 /* Is there room in the reply for this data ? */
3215 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3217 NT_STATUS_INVALID_PARAMETER);
3218 END_PROFILE(SMBreadX);
3225 if (req->wct == 12) {
3226 #ifdef LARGE_SMB_OFF_T
3228 * This is a large offset (64 bit) read.
3230 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv10)) << 32);
3232 #else /* !LARGE_SMB_OFF_T */
3235 * Ensure we haven't been sent a >32 bit offset.
3238 if(IVAL(req->inbuf,smb_vwv10) != 0) {
3239 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3240 "used and we don't support 64 bit offsets.\n",
3241 (unsigned int)IVAL(req->inbuf,smb_vwv10) ));
3242 END_PROFILE(SMBreadX);
3243 reply_doserror(req, ERRDOS, ERRbadaccess);
3247 #endif /* LARGE_SMB_OFF_T */
3251 if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)smb_maxcnt,
3252 (SMB_BIG_UINT)startpos, READ_LOCK)) {
3253 END_PROFILE(SMBreadX);
3254 reply_doserror(req, ERRDOS, ERRlock);
3259 && schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3260 END_PROFILE(SMBreadX);
3261 reply_post_legacy(req, -1);
3265 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3267 END_PROFILE(SMBreadX);
3271 /****************************************************************************
3272 Error replies to writebraw must have smb_wct == 1. Fix this up.
3273 ****************************************************************************/
3275 void error_to_writebrawerr(struct smb_request *req)
3277 uint8 *old_outbuf = req->outbuf;
3279 reply_outbuf(req, 1, 0);
3281 memcpy(req->outbuf, old_outbuf, smb_size);
3282 TALLOC_FREE(old_outbuf);
3285 /****************************************************************************
3286 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3287 ****************************************************************************/
3289 void reply_writebraw(connection_struct *conn, struct smb_request *req)
3294 ssize_t total_written=0;
3295 size_t numtowrite=0;
3303 START_PROFILE(SMBwritebraw);
3306 * If we ever reply with an error, it must have the SMB command
3307 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3310 SCVAL(req->inbuf,smb_com,SMBwritec);
3312 if (srv_is_signing_active()) {
3313 END_PROFILE(SMBwritebraw);
3314 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3315 "raw reads/writes are disallowed.");
3318 if (req->wct < 12) {
3319 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3320 error_to_writebrawerr(req);
3321 END_PROFILE(SMBwritebraw);
3325 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3326 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3327 error_to_writebrawerr(req);
3328 END_PROFILE(SMBwritebraw);
3332 if (!CHECK_WRITE(fsp)) {
3333 reply_doserror(req, ERRDOS, ERRbadaccess);
3334 error_to_writebrawerr(req);
3335 END_PROFILE(SMBwritebraw);
3339 tcount = IVAL(req->inbuf,smb_vwv1);
3340 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
3341 write_through = BITSETW(req->inbuf+smb_vwv7,0);
3343 /* We have to deal with slightly different formats depending
3344 on whether we are using the core+ or lanman1.0 protocol */
3346 if(Protocol <= PROTOCOL_COREPLUS) {
3347 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3348 data = smb_buf(req->inbuf);
3350 numtowrite = SVAL(req->inbuf,smb_vwv10);
3351 data = smb_base(req->inbuf) + SVAL(req->inbuf, smb_vwv11);
3354 /* Ensure we don't write bytes past the end of this packet. */
3355 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3356 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3357 error_to_writebrawerr(req);
3358 END_PROFILE(SMBwritebraw);
3362 if (is_locked(fsp,(uint32)req->smbpid,(SMB_BIG_UINT)tcount,
3363 (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3364 reply_doserror(req, ERRDOS, ERRlock);
3365 error_to_writebrawerr(req);
3366 END_PROFILE(SMBwritebraw);
3371 nwritten = write_file(fsp,data,startpos,numtowrite);
3374 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3375 "wrote=%d sync=%d\n",
3376 fsp->fnum, (double)startpos, (int)numtowrite,
3377 (int)nwritten, (int)write_through));
3379 if (nwritten < (ssize_t)numtowrite) {
3380 reply_unixerror(req, ERRHRD, ERRdiskfull);
3381 error_to_writebrawerr(req);
3382 END_PROFILE(SMBwritebraw);
3386 total_written = nwritten;
3388 /* Allocate a buffer of 64k + length. */
3389 buf = TALLOC_ARRAY(NULL, char, 65540);
3391 reply_doserror(req, ERRDOS, ERRnomem);
3392 error_to_writebrawerr(req);
3393 END_PROFILE(SMBwritebraw);
3397 /* Return a SMBwritebraw message to the redirector to tell
3398 * it to send more bytes */
3400 memcpy(buf, req->inbuf, smb_size);
3401 outsize = set_message(NULL,buf,
3402 Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3403 SCVAL(buf,smb_com,SMBwritebraw);
3404 SSVALS(buf,smb_vwv0,0xFFFF);
3406 if (!send_smb(smbd_server_fd(),buf)) {
3407 exit_server_cleanly("reply_writebraw: send_smb "
3411 /* Now read the raw data into the buffer and write it */
3412 if (read_smb_length(smbd_server_fd(),buf,SMB_SECONDARY_WAIT) == -1) {
3413 exit_server_cleanly("secondary writebraw failed");
3417 * Even though this is not an smb message,
3418 * smb_len returns the generic length of a packet.
3421 numtowrite = smb_len(buf);
3423 /* Set up outbuf to return the correct size */
3424 reply_outbuf(req, 1, 0);
3426 if (numtowrite != 0) {
3428 if (numtowrite > 0xFFFF) {
3429 DEBUG(0,("reply_writebraw: Oversize secondary write "
3430 "raw requested (%u). Terminating\n",
3431 (unsigned int)numtowrite ));
3432 exit_server_cleanly("secondary writebraw failed");
3435 if (tcount > nwritten+numtowrite) {
3436 DEBUG(3,("reply_writebraw: Client overestimated the "
3438 (int)tcount,(int)nwritten,(int)numtowrite));
3441 if (read_data(smbd_server_fd(), buf+4, numtowrite)
3443 DEBUG(0,("reply_writebraw: Oversize secondary write "
3444 "raw read failed (%s). Terminating\n",
3446 exit_server_cleanly("secondary writebraw failed");
3449 nwritten = write_file(fsp,buf+4,startpos+nwritten,numtowrite);
3450 if (nwritten == -1) {
3452 reply_unixerror(req, ERRHRD, ERRdiskfull);
3453 error_to_writebrawerr(req);
3454 END_PROFILE(SMBwritebraw);
3458 if (nwritten < (ssize_t)numtowrite) {
3459 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3460 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3464 total_written += nwritten;
3469 SSVAL(req->outbuf,smb_vwv0,total_written);
3471 status = sync_file(conn, fsp, write_through);
3472 if (!NT_STATUS_IS_OK(status)) {
3473 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3474 fsp->fsp_name, nt_errstr(status) ));
3475 reply_nterror(req, status);
3476 error_to_writebrawerr(req);
3477 END_PROFILE(SMBwritebraw);
3481 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3483 fsp->fnum, (double)startpos, (int)numtowrite,
3484 (int)total_written));
3486 /* We won't return a status if write through is not selected - this
3487 * follows what WfWg does */
3488 END_PROFILE(SMBwritebraw);
3490 if (!write_through && total_written==tcount) {
3492 #if RABBIT_PELLET_FIX
3494 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3495 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3498 if (!send_keepalive(smbd_server_fd())) {
3499 exit_server_cleanly("reply_writebraw: send of "
3500 "keepalive failed");
3503 TALLOC_FREE(req->outbuf);
3509 #define DBGC_CLASS DBGC_LOCKING
3511 /****************************************************************************
3512 Reply to a writeunlock (core+).
3513 ****************************************************************************/
3515 void reply_writeunlock(connection_struct *conn, struct smb_request *req)
3517 ssize_t nwritten = -1;
3521 NTSTATUS status = NT_STATUS_OK;
3524 START_PROFILE(SMBwriteunlock);
3527 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3528 END_PROFILE(SMBwriteunlock);
3532 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3534 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3535 END_PROFILE(SMBwriteunlock);
3539 if (!CHECK_WRITE(fsp)) {
3540 reply_doserror(req, ERRDOS,ERRbadaccess);
3541 END_PROFILE(SMBwriteunlock);
3545 numtowrite = SVAL(req->inbuf,smb_vwv1);
3546 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
3547 data = smb_buf(req->inbuf) + 3;
3550 && is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
3551 (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3552 reply_doserror(req, ERRDOS, ERRlock);
3553 END_PROFILE(SMBwriteunlock);
3557 /* The special X/Open SMB protocol handling of
3558 zero length writes is *NOT* done for
3560 if(numtowrite == 0) {
3563 nwritten = write_file(fsp,data,startpos,numtowrite);
3566 status = sync_file(conn, fsp, False /* write through */);
3567 if (!NT_STATUS_IS_OK(status)) {
3568 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3569 fsp->fsp_name, nt_errstr(status) ));
3570 reply_nterror(req, status);
3571 END_PROFILE(SMBwriteunlock);
3575 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3576 reply_unixerror(req, ERRHRD, ERRdiskfull);
3577 END_PROFILE(SMBwriteunlock);
3582 status = do_unlock(smbd_messaging_context(),
3585 (SMB_BIG_UINT)numtowrite,
3586 (SMB_BIG_UINT)startpos,
3589 if (NT_STATUS_V(status)) {
3590 reply_nterror(req, status);
3591 END_PROFILE(SMBwriteunlock);
3596 reply_outbuf(req, 1, 0);
3598 SSVAL(req->outbuf,smb_vwv0,nwritten);
3600 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3601 fsp->fnum, (int)numtowrite, (int)nwritten));
3603 END_PROFILE(SMBwriteunlock);
3608 #define DBGC_CLASS DBGC_ALL
3610 /****************************************************************************
3612 ****************************************************************************/
3614 void reply_write(connection_struct *conn, struct smb_request *req)
3617 ssize_t nwritten = -1;
3623 START_PROFILE(SMBwrite);
3626 END_PROFILE(SMBwrite);
3627 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3631 /* If it's an IPC, pass off the pipe handler. */
3633 reply_pipe_write(req);
3634 END_PROFILE(SMBwrite);
3638 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3640 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3641 END_PROFILE(SMBwrite);
3645 if (!CHECK_WRITE(fsp)) {
3646 reply_doserror(req, ERRDOS, ERRbadaccess);
3647 END_PROFILE(SMBwrite);
3651 numtowrite = SVAL(req->inbuf,smb_vwv1);
3652 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
3653 data = smb_buf(req->inbuf) + 3;
3655 if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
3656 (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3657 reply_doserror(req, ERRDOS, ERRlock);
3658 END_PROFILE(SMBwrite);
3663 * X/Open SMB protocol says that if smb_vwv1 is
3664 * zero then the file size should be extended or
3665 * truncated to the size given in smb_vwv[2-3].
3668 if(numtowrite == 0) {
3670 * This is actually an allocate call, and set EOF. JRA.
3672 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3674 reply_nterror(req, NT_STATUS_DISK_FULL);
3675 END_PROFILE(SMBwrite);
3678 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3680 reply_nterror(req, NT_STATUS_DISK_FULL);
3681 END_PROFILE(SMBwrite);
3685 nwritten = write_file(fsp,data,startpos,numtowrite);
3687 status = sync_file(conn, fsp, False);
3688 if (!NT_STATUS_IS_OK(status)) {
3689 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3690 fsp->fsp_name, nt_errstr(status) ));
3691 reply_nterror(req, status);
3692 END_PROFILE(SMBwrite);
3696 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3697 reply_unixerror(req, ERRHRD, ERRdiskfull);
3698 END_PROFILE(SMBwrite);
3702 reply_outbuf(req, 1, 0);
3704 SSVAL(req->outbuf,smb_vwv0,nwritten);
3706 if (nwritten < (ssize_t)numtowrite) {
3707 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3708 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3711 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3713 END_PROFILE(SMBwrite);
3717 /****************************************************************************
3718 Reply to a write and X.
3719 ****************************************************************************/
3721 void reply_write_and_X(connection_struct *conn, struct smb_request *req)
3728 unsigned int smb_doff;
3729 unsigned int smblen;
3734 START_PROFILE(SMBwriteX);
3736 if ((req->wct != 12) && (req->wct != 14)) {
3737 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3738 END_PROFILE(SMBwriteX);
3742 numtowrite = SVAL(req->inbuf,smb_vwv10);
3743 smb_doff = SVAL(req->inbuf,smb_vwv11);
3744 smblen = smb_len(req->inbuf);
3745 large_writeX = ((req->wct == 14) && (smblen > 0xFFFF));
3747 /* Deal with possible LARGE_WRITEX */
3749 numtowrite |= ((((size_t)SVAL(req->inbuf,smb_vwv9)) & 1 )<<16);
3752 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
3753 reply_doserror(req, ERRDOS, ERRbadmem);
3754 END_PROFILE(SMBwriteX);
3758 /* If it's an IPC, pass off the pipe handler. */
3760 reply_pipe_write_and_X(req);
3761 END_PROFILE(SMBwriteX);
3765 fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
3766 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
3767 write_through = BITSETW(req->inbuf+smb_vwv7,0);
3769 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3770 END_PROFILE(SMBwriteX);
3774 if (!CHECK_WRITE(fsp)) {
3775 reply_doserror(req, ERRDOS, ERRbadaccess);
3776 END_PROFILE(SMBwriteX);
3780 data = smb_base(req->inbuf) + smb_doff;
3782 if(req->wct == 14) {
3783 #ifdef LARGE_SMB_OFF_T
3785 * This is a large offset (64 bit) write.
3787 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv12)) << 32);
3789 #else /* !LARGE_SMB_OFF_T */
3792 * Ensure we haven't been sent a >32 bit offset.
3795 if(IVAL(req->inbuf,smb_vwv12) != 0) {
3796 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
3797 "used and we don't support 64 bit offsets.\n",
3798 (unsigned int)IVAL(inbuf,smb_vwv12) ));
3799 reply_doserror(req, ERRDOS, ERRbadaccess);
3800 END_PROFILE(SMBwriteX);
3804 #endif /* LARGE_SMB_OFF_T */
3807 if (is_locked(fsp,(uint32)req->smbpid,
3808 (SMB_BIG_UINT)numtowrite,
3809 (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3810 reply_doserror(req, ERRDOS, ERRlock);
3811 END_PROFILE(SMBwriteX);
3815 /* X/Open SMB protocol says that, unlike SMBwrite
3816 if the length is zero then NO truncation is
3817 done, just a write of zero. To truncate a file,
3820 if(numtowrite == 0) {
3824 if (schedule_aio_write_and_X(conn, req, fsp, data, startpos,
3826 END_PROFILE(SMBwriteX);
3830 nwritten = write_file(fsp,data,startpos,numtowrite);
3833 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3834 reply_unixerror(req, ERRHRD, ERRdiskfull);
3835 END_PROFILE(SMBwriteX);
3839 reply_outbuf(req, 6, 0);
3840 SSVAL(req->outbuf,smb_vwv2,nwritten);
3842 SSVAL(req->outbuf,smb_vwv4,(nwritten>>16)&1);
3844 if (nwritten < (ssize_t)numtowrite) {
3845 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3846 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3849 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
3850 fsp->fnum, (int)numtowrite, (int)nwritten));
3852 status = sync_file(conn, fsp, write_through);
3853 if (!NT_STATUS_IS_OK(status)) {
3854 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
3855 fsp->fsp_name, nt_errstr(status) ));
3856 reply_nterror(req, status);
3857 END_PROFILE(SMBwriteX);
3861 END_PROFILE(SMBwriteX);
3862 chain_reply_new(req);
3866 /****************************************************************************
3868 ****************************************************************************/
3870 void reply_lseek(connection_struct *conn, struct smb_request *req)
3877 START_PROFILE(SMBlseek);
3880 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3881 END_PROFILE(SMBlseek);
3885 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3887 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3891 flush_write_cache(fsp, SEEK_FLUSH);
3893 mode = SVAL(req->inbuf,smb_vwv1) & 3;
3894 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3895 startpos = (SMB_OFF_T)IVALS(req->inbuf,smb_vwv2);
3904 res = fsp->fh->pos + startpos;
3915 if (umode == SEEK_END) {
3916 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
3917 if(errno == EINVAL) {
3918 SMB_OFF_T current_pos = startpos;
3919 SMB_STRUCT_STAT sbuf;
3921 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3922 reply_unixerror(req, ERRDOS,
3924 END_PROFILE(SMBlseek);
3928 current_pos += sbuf.st_size;
3930 res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
3935 reply_unixerror(req, ERRDOS, ERRnoaccess);
3936 END_PROFILE(SMBlseek);
3943 reply_outbuf(req, 2, 0);
3944 SIVAL(req->outbuf,smb_vwv0,res);
3946 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3947 fsp->fnum, (double)startpos, (double)res, mode));
3949 END_PROFILE(SMBlseek);
3953 /****************************************************************************
3955 ****************************************************************************/
3957 void reply_flush(connection_struct *conn, struct smb_request *req)
3962 START_PROFILE(SMBflush);
3965 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3969 fnum = SVAL(req->inbuf,smb_vwv0);
3970 fsp = file_fsp(fnum);
3972 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp, ¤t_user)) {
3977 file_sync_all(conn);
3979 NTSTATUS status = sync_file(conn, fsp, True);
3980 if (!NT_STATUS_IS_OK(status)) {
3981 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
3982 fsp->fsp_name, nt_errstr(status) ));
3983 reply_nterror(req, status);
3984 END_PROFILE(SMBflush);
3989 reply_outbuf(req, 0, 0);
3991 DEBUG(3,("flush\n"));
3992 END_PROFILE(SMBflush);
3996 /****************************************************************************
3998 conn POINTER CAN BE NULL HERE !
3999 ****************************************************************************/
4001 void reply_exit(connection_struct *conn, struct smb_request *req)
4003 START_PROFILE(SMBexit);
4005 file_close_pid(req->smbpid, req->vuid);
4007 reply_outbuf(req, 0, 0);
4009 DEBUG(3,("exit\n"));
4011 END_PROFILE(SMBexit);
4015 /****************************************************************************
4016 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4017 ****************************************************************************/
4019 void reply_close(connection_struct *conn, struct smb_request *req)
4021 NTSTATUS status = NT_STATUS_OK;
4022 files_struct *fsp = NULL;
4023 START_PROFILE(SMBclose);
4026 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4027 END_PROFILE(SMBclose);
4031 /* If it's an IPC, pass off to the pipe handler. */
4033 reply_pipe_close(conn, req);
4034 END_PROFILE(SMBclose);
4038 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4041 * We can only use CHECK_FSP if we know it's not a directory.
4044 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
4045 reply_doserror(req, ERRDOS, ERRbadfid);
4046 END_PROFILE(SMBclose);
4050 if(fsp->is_directory) {
4052 * Special case - close NT SMB directory handle.
4054 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4055 status = close_file(fsp,NORMAL_CLOSE);
4058 * Close ordinary file.
4061 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4062 fsp->fh->fd, fsp->fnum,
4063 conn->num_files_open));
4066 * Take care of any time sent in the close.
4069 fsp_set_pending_modtime(fsp, convert_time_t_to_timespec(
4070 srv_make_unix_date3(
4071 req->inbuf+smb_vwv1)));
4074 * close_file() returns the unix errno if an error
4075 * was detected on close - normally this is due to
4076 * a disk full error. If not then it was probably an I/O error.
4079 status = close_file(fsp,NORMAL_CLOSE);
4082 if (!NT_STATUS_IS_OK(status)) {
4083 reply_nterror(req, status);
4084 END_PROFILE(SMBclose);
4088 reply_outbuf(req, 0, 0);
4089 END_PROFILE(SMBclose);
4093 /****************************************************************************
4094 Reply to a writeclose (Core+ protocol).
4095 ****************************************************************************/
4097 void reply_writeclose(connection_struct *conn, struct smb_request *req)
4100 ssize_t nwritten = -1;
4101 NTSTATUS close_status = NT_STATUS_OK;
4104 struct timespec mtime;
4107 START_PROFILE(SMBwriteclose);
4110 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4111 END_PROFILE(SMBwriteclose);
4115 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4117 if (!check_fsp(conn, req, fsp, ¤t_user)) {
4118 END_PROFILE(SMBwriteclose);
4121 if (!CHECK_WRITE(fsp)) {
4122 reply_doserror(req, ERRDOS,ERRbadaccess);
4123 END_PROFILE(SMBwriteclose);
4127 numtowrite = SVAL(req->inbuf,smb_vwv1);
4128 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
4129 mtime = convert_time_t_to_timespec(srv_make_unix_date3(
4130 req->inbuf+smb_vwv4));
4131 data = smb_buf(req->inbuf) + 1;
4134 && is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
4135 (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
4136 reply_doserror(req, ERRDOS,ERRlock);
4137 END_PROFILE(SMBwriteclose);
4141 nwritten = write_file(fsp,data,startpos,numtowrite);
4143 set_filetime(conn, fsp->fsp_name, mtime);
4146 * More insanity. W2K only closes the file if writelen > 0.
4151 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4153 close_status = close_file(fsp,NORMAL_CLOSE);
4156 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4157 fsp->fnum, (int)numtowrite, (int)nwritten,
4158 conn->num_files_open));
4160 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4161 reply_doserror(req, ERRHRD, ERRdiskfull);
4162 END_PROFILE(SMBwriteclose);
4166 if(!NT_STATUS_IS_OK(close_status)) {
4167 reply_nterror(req, close_status);
4168 END_PROFILE(SMBwriteclose);
4172 reply_outbuf(req, 1, 0);
4174 SSVAL(req->outbuf,smb_vwv0,nwritten);
4175 END_PROFILE(SMBwriteclose);
4180 #define DBGC_CLASS DBGC_LOCKING
4182 /****************************************************************************
4184 ****************************************************************************/
4186 void reply_lock(connection_struct *conn, struct smb_request *req)
4188 SMB_BIG_UINT count,offset;
4191 struct byte_range_lock *br_lck = NULL;
4193 START_PROFILE(SMBlock);
4196 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4197 END_PROFILE(SMBlock);
4201 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4203 if (!check_fsp(conn, req, fsp, ¤t_user)) {
4204 END_PROFILE(SMBlock);
4208 release_level_2_oplocks_on_change(fsp);
4210 count = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv1);
4211 offset = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv3);
4213 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4214 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4216 br_lck = do_lock(smbd_messaging_context(),
4223 False, /* Non-blocking lock. */
4227 TALLOC_FREE(br_lck);
4229 if (NT_STATUS_V(status)) {
4230 reply_nterror(req, status);
4231 END_PROFILE(SMBlock);
4235 reply_outbuf(req, 0, 0);
4237 END_PROFILE(SMBlock);
4241 /****************************************************************************
4243 ****************************************************************************/
4245 void reply_unlock(connection_struct *conn, struct smb_request *req)
4247 SMB_BIG_UINT count,offset;
4251 START_PROFILE(SMBunlock);
4254 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4255 END_PROFILE(SMBunlock);
4259 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4261 if (!check_fsp(conn, req, fsp, ¤t_user)) {
4262 END_PROFILE(SMBunlock);
4266 count = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv1);
4267 offset = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv3);
4269 status = do_unlock(smbd_messaging_context(),
4276 if (NT_STATUS_V(status)) {
4277 reply_nterror(req, status);
4278 END_PROFILE(SMBunlock);
4282 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4283 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4285 reply_outbuf(req, 0, 0);
4287 END_PROFILE(SMBunlock);
4292 #define DBGC_CLASS DBGC_ALL
4294 /****************************************************************************
4296 conn POINTER CAN BE NULL HERE !
4297 ****************************************************************************/
4299 void reply_tdis(connection_struct *conn, struct smb_request *req)
4301 START_PROFILE(SMBtdis);
4304 DEBUG(4,("Invalid connection in tdis\n"));
4305 reply_doserror(req, ERRSRV, ERRinvnid);
4306 END_PROFILE(SMBtdis);
4312 close_cnum(conn,req->vuid);
4314 reply_outbuf(req, 0, 0);
4315 END_PROFILE(SMBtdis);
4319 /****************************************************************************
4321 conn POINTER CAN BE NULL HERE !
4322 ****************************************************************************/
4324 void reply_echo(connection_struct *conn, struct smb_request *req)
4328 unsigned int data_len = smb_buflen(req->inbuf);
4330 START_PROFILE(SMBecho);
4333 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4334 END_PROFILE(SMBecho);
4338 if (data_len > BUFFER_SIZE) {
4339 DEBUG(0,("reply_echo: data_len too large.\n"));
4340 reply_nterror(req, NT_STATUS_INSUFFICIENT_RESOURCES);
4341 END_PROFILE(SMBecho);
4345 smb_reverb = SVAL(req->inbuf,smb_vwv0);
4347 reply_outbuf(req, 1, data_len);
4349 /* copy any incoming data back out */
4351 memcpy(smb_buf(req->outbuf),smb_buf(req->inbuf),data_len);
4354 if (smb_reverb > 100) {
4355 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4359 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
4360 SSVAL(req->outbuf,smb_vwv0,seq_num);
4362 show_msg((char *)req->outbuf);
4363 if (!send_smb(smbd_server_fd(),(char *)req->outbuf))
4364 exit_server_cleanly("reply_echo: send_smb failed.");
4367 DEBUG(3,("echo %d times\n", smb_reverb));
4369 TALLOC_FREE(req->outbuf);
4373 END_PROFILE(SMBecho);
4377 /****************************************************************************
4378 Reply to a printopen.
4379 ****************************************************************************/
4381 void reply_printopen(connection_struct *conn, struct smb_request *req)
4386 START_PROFILE(SMBsplopen);
4389 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4390 END_PROFILE(SMBsplopen);
4394 if (!CAN_PRINT(conn)) {
4395 reply_doserror(req, ERRDOS, ERRnoaccess);
4396 END_PROFILE(SMBsplopen);
4400 /* Open for exclusive use, write only. */
4401 status = print_fsp_open(conn, NULL, &fsp);
4403 if (!NT_STATUS_IS_OK(status)) {
4404 reply_nterror(req, status);
4405 END_PROFILE(SMBsplopen);
4409 reply_outbuf(req, 1, 0);
4410 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4412 DEBUG(3,("openprint fd=%d fnum=%d\n",
4413 fsp->fh->fd, fsp->fnum));
4415 END_PROFILE(SMBsplopen);
4419 /****************************************************************************
4420 Reply to a printclose.
4421 ****************************************************************************/
4423 void reply_printclose(connection_struct *conn, struct smb_request *req)
4428 START_PROFILE(SMBsplclose);
4431 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4432 END_PROFILE(SMBsplclose);
4436 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4438 if (!check_fsp(conn, req, fsp, ¤t_user)) {
4439 END_PROFILE(SMBsplclose);
4443 if (!CAN_PRINT(conn)) {
4444 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
4445 END_PROFILE(SMBsplclose);
4449 DEBUG(3,("printclose fd=%d fnum=%d\n",
4450 fsp->fh->fd,fsp->fnum));
4452 status = close_file(fsp,NORMAL_CLOSE);
4454 if(!NT_STATUS_IS_OK(status)) {
4455 reply_nterror(req, status);
4456 END_PROFILE(SMBsplclose);
4460 END_PROFILE(SMBsplclose);
4464 /****************************************************************************
4465 Reply to a printqueue.
4466 ****************************************************************************/
4468 void reply_printqueue(connection_struct *conn, struct smb_request *req)
4473 START_PROFILE(SMBsplretq);
4476 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4477 END_PROFILE(SMBsplretq);
4481 max_count = SVAL(req->inbuf,smb_vwv0);
4482 start_index = SVAL(req->inbuf,smb_vwv1);
4484 /* we used to allow the client to get the cnum wrong, but that
4485 is really quite gross and only worked when there was only
4486 one printer - I think we should now only accept it if they
4487 get it right (tridge) */
4488 if (!CAN_PRINT(conn)) {
4489 reply_doserror(req, ERRDOS, ERRnoaccess);
4490 END_PROFILE(SMBsplretq);
4494 reply_outbuf(req, 2, 3);
4495 SSVAL(req->outbuf,smb_vwv0,0);
4496 SSVAL(req->outbuf,smb_vwv1,0);
4497 SCVAL(smb_buf(req->outbuf),0,1);
4498 SSVAL(smb_buf(req->outbuf),1,0);
4500 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
4501 start_index, max_count));
4504 print_queue_struct *queue = NULL;
4505 print_status_struct status;
4506 int count = print_queue_status(SNUM(conn), &queue, &status);
4507 int num_to_get = ABS(max_count);
4508 int first = (max_count>0?start_index:start_index+max_count+1);
4514 num_to_get = MIN(num_to_get,count-first);
4517 for (i=first;i<first+num_to_get;i++) {
4521 srv_put_dos_date2(p,0,queue[i].time);
4522 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
4523 SSVAL(p,5, queue[i].job);
4524 SIVAL(p,7,queue[i].size);
4526 srvstr_push(blob, req->flags2, p+12,
4527 queue[i].fs_user, 16, STR_ASCII);
4529 if (message_push_blob(
4532 blob, sizeof(blob))) == -1) {
4533 reply_nterror(req, NT_STATUS_NO_MEMORY);
4534 END_PROFILE(SMBsplretq);
4540 SSVAL(req->outbuf,smb_vwv0,count);
4541 SSVAL(req->outbuf,smb_vwv1,
4542 (max_count>0?first+count:first-1));
4543 SCVAL(smb_buf(req->outbuf),0,1);
4544 SSVAL(smb_buf(req->outbuf),1,28*count);
4549 DEBUG(3,("%d entries returned in queue\n",count));
4552 END_PROFILE(SMBsplretq);
4556 /****************************************************************************
4557 Reply to a printwrite.
4558 ****************************************************************************/
4560 void reply_printwrite(connection_struct *conn, struct smb_request *req)
4566 START_PROFILE(SMBsplwr);
4569 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4570 END_PROFILE(SMBsplwr);
4574 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4576 if (!check_fsp(conn, req, fsp, ¤t_user)) {
4577 END_PROFILE(SMBsplwr);
4581 if (!CAN_PRINT(conn)) {
4582 reply_doserror(req, ERRDOS, ERRnoaccess);
4583 END_PROFILE(SMBsplwr);
4587 if (!CHECK_WRITE(fsp)) {
4588 reply_doserror(req, ERRDOS, ERRbadaccess);
4589 END_PROFILE(SMBsplwr);
4593 numtowrite = SVAL(smb_buf(req->inbuf),1);
4595 if (smb_buflen(req->inbuf) < numtowrite + 3) {
4596 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4597 END_PROFILE(SMBsplwr);
4601 data = smb_buf(req->inbuf) + 3;
4603 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
4604 reply_unixerror(req, ERRHRD, ERRdiskfull);
4605 END_PROFILE(SMBsplwr);
4609 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
4611 END_PROFILE(SMBsplwr);
4615 /****************************************************************************
4617 ****************************************************************************/
4619 void reply_mkdir(connection_struct *conn, struct smb_request *req)
4623 SMB_STRUCT_STAT sbuf;
4625 START_PROFILE(SMBmkdir);
4627 srvstr_get_path((char *)req->inbuf, req->flags2, directory,
4628 smb_buf(req->inbuf) + 1, sizeof(directory), 0,
4629 STR_TERMINATE, &status);
4630 if (!NT_STATUS_IS_OK(status)) {
4631 reply_nterror(req, status);
4632 END_PROFILE(SMBmkdir);
4636 status = resolve_dfspath(conn,
4637 req->flags2 & FLAGS2_DFS_PATHNAMES,
4639 if (!NT_STATUS_IS_OK(status)) {
4640 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4641 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
4642 ERRSRV, ERRbadpath);
4643 END_PROFILE(SMBmkdir);
4646 reply_nterror(req, status);
4647 END_PROFILE(SMBmkdir);
4651 status = unix_convert(conn, directory, False, NULL, &sbuf);
4652 if (!NT_STATUS_IS_OK(status)) {
4653 reply_nterror(req, status);
4654 END_PROFILE(SMBmkdir);
4658 status = check_name(conn, directory);
4659 if (!NT_STATUS_IS_OK(status)) {
4660 reply_nterror(req, status);
4661 END_PROFILE(SMBmkdir);
4665 status = create_directory(conn, directory);
4667 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
4669 if (!NT_STATUS_IS_OK(status)) {
4671 if (!use_nt_status()
4672 && NT_STATUS_EQUAL(status,
4673 NT_STATUS_OBJECT_NAME_COLLISION)) {
4675 * Yes, in the DOS error code case we get a
4676 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
4677 * samba4 torture test.
4679 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
4682 reply_nterror(req, status);
4683 END_PROFILE(SMBmkdir);
4687 reply_outbuf(req, 0, 0);
4689 DEBUG( 3, ( "mkdir %s\n", directory ) );
4691 END_PROFILE(SMBmkdir);
4695 /****************************************************************************
4696 Static function used by reply_rmdir to delete an entire directory
4697 tree recursively. Return True on ok, False on fail.
4698 ****************************************************************************/
4700 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
4702 const char *dname = NULL;
4705 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
4710 while((dname = ReadDirName(dir_hnd, &offset))) {
4714 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4717 if (!is_visible_file(conn, directory, dname, &st, False))
4720 /* Construct the full name. */
4721 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
4727 pstrcpy(fullname, directory);
4728 pstrcat(fullname, "/");
4729 pstrcat(fullname, dname);
4731 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
4736 if(st.st_mode & S_IFDIR) {
4737 if(!recursive_rmdir(conn, fullname)) {
4741 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
4745 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
4754 /****************************************************************************
4755 The internals of the rmdir code - called elsewhere.
4756 ****************************************************************************/
4758 NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
4763 /* Might be a symlink. */
4764 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
4765 return map_nt_error_from_unix(errno);
4768 if (S_ISLNK(st.st_mode)) {
4769 /* Is what it points to a directory ? */
4770 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
4771 return map_nt_error_from_unix(errno);
4773 if (!(S_ISDIR(st.st_mode))) {
4774 return NT_STATUS_NOT_A_DIRECTORY;
4776 ret = SMB_VFS_UNLINK(conn,directory);
4778 ret = SMB_VFS_RMDIR(conn,directory);
4781 notify_fname(conn, NOTIFY_ACTION_REMOVED,
4782 FILE_NOTIFY_CHANGE_DIR_NAME,
4784 return NT_STATUS_OK;
4787 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
4789 * Check to see if the only thing in this directory are
4790 * vetoed files/directories. If so then delete them and
4791 * retry. If we fail to delete any of them (and we *don't*
4792 * do a recursive delete) then fail the rmdir.
4796 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
4798 if(dir_hnd == NULL) {
4803 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4804 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4806 if (!is_visible_file(conn, directory, dname, &st, False))
4808 if(!IS_VETO_PATH(conn, dname)) {
4815 /* We only have veto files/directories. Recursive delete. */
4817 RewindDir(dir_hnd,&dirpos);
4818 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4821 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4823 if (!is_visible_file(conn, directory, dname, &st, False))
4826 /* Construct the full name. */
4827 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
4832 pstrcpy(fullname, directory);
4833 pstrcat(fullname, "/");
4834 pstrcat(fullname, dname);
4836 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
4838 if(st.st_mode & S_IFDIR) {
4839 if(lp_recursive_veto_delete(SNUM(conn))) {
4840 if(!recursive_rmdir(conn, fullname))
4843 if(SMB_VFS_RMDIR(conn,fullname) != 0)
4845 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
4849 /* Retry the rmdir */
4850 ret = SMB_VFS_RMDIR(conn,directory);
4856 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
4857 "%s\n", directory,strerror(errno)));
4858 return map_nt_error_from_unix(errno);
4861 notify_fname(conn, NOTIFY_ACTION_REMOVED,
4862 FILE_NOTIFY_CHANGE_DIR_NAME,
4865 return NT_STATUS_OK;
4868 /****************************************************************************
4870 ****************************************************************************/
4872 void reply_rmdir(connection_struct *conn, struct smb_request *req)
4875 SMB_STRUCT_STAT sbuf;
4877 START_PROFILE(SMBrmdir);
4879 srvstr_get_path((char *)req->inbuf, req->flags2, directory,
4880 smb_buf(req->inbuf) + 1, sizeof(directory), 0,
4881 STR_TERMINATE, &status);
4882 if (!NT_STATUS_IS_OK(status)) {
4883 reply_nterror(req, status);
4884 END_PROFILE(SMBrmdir);
4888 status = resolve_dfspath(conn,
4889 req->flags2 & FLAGS2_DFS_PATHNAMES,
4891 if (!NT_STATUS_IS_OK(status)) {
4892 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4893 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
4894 ERRSRV, ERRbadpath);
4895 END_PROFILE(SMBrmdir);
4898 reply_nterror(req, status);
4899 END_PROFILE(SMBrmdir);
4903 status = unix_convert(conn, directory, False, NULL, &sbuf);
4904 if (!NT_STATUS_IS_OK(status)) {
4905 reply_nterror(req, status);
4906 END_PROFILE(SMBrmdir);
4910 status = check_name(conn, directory);
4911 if (!NT_STATUS_IS_OK(status)) {
4912 reply_nterror(req, status);
4913 END_PROFILE(SMBrmdir);
4917 dptr_closepath(directory, req->smbpid);
4918 status = rmdir_internals(conn, directory);
4919 if (!NT_STATUS_IS_OK(status)) {
4920 reply_nterror(req, status);
4921 END_PROFILE(SMBrmdir);
4925 reply_outbuf(req, 0, 0);
4927 DEBUG( 3, ( "rmdir %s\n", directory ) );
4929 END_PROFILE(SMBrmdir);
4933 /*******************************************************************
4934 Resolve wildcards in a filename rename.
4935 Note that name is in UNIX charset and thus potentially can be more
4936 than fstring buffer (255 bytes) especially in default UTF-8 case.
4937 Therefore, we use pstring inside and all calls should ensure that
4938 name2 is at least pstring-long (they do already)
4939 ********************************************************************/
4941 static BOOL resolve_wildcards(const char *name1, char *name2)
4943 pstring root1,root2;
4945 char *p,*p2, *pname1, *pname2;
4946 int available_space, actual_space;
4948 pname1 = strrchr_m(name1,'/');
4949 pname2 = strrchr_m(name2,'/');
4951 if (!pname1 || !pname2)
4954 pstrcpy(root1,pname1);
4955 pstrcpy(root2,pname2);
4956 p = strrchr_m(root1,'.');
4963 p = strrchr_m(root2,'.');
4977 } else if (*p2 == '*') {
4993 } else if (*p2 == '*') {
5003 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
5006 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
5007 if (actual_space >= available_space - 1) {
5008 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
5009 actual_space - available_space));
5012 pstrcpy_base(pname2, root2, name2);
5018 /****************************************************************************
5019 Ensure open files have their names updated. Updated to notify other smbd's
5021 ****************************************************************************/
5023 static void rename_open_files(connection_struct *conn,
5024 struct share_mode_lock *lck,
5025 const char *newname)
5028 BOOL did_rename = False;
5030 for(fsp = file_find_di_first(lck->id); fsp;
5031 fsp = file_find_di_next(fsp)) {
5032 /* fsp_name is a relative path under the fsp. To change this for other
5033 sharepaths we need to manipulate relative paths. */
5034 /* TODO - create the absolute path and manipulate the newname
5035 relative to the sharepath. */
5036 if (fsp->conn != conn) {
5039 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5040 fsp->fnum, file_id_static_string(&fsp->file_id),
5041 fsp->fsp_name, newname ));
5042 string_set(&fsp->fsp_name, newname);
5047 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5048 file_id_static_string(&lck->id), newname ));
5051 /* Send messages to all smbd's (not ourself) that the name has changed. */
5052 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5056 /****************************************************************************
5057 We need to check if the source path is a parent directory of the destination
5058 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5059 refuse the rename with a sharing violation. Under UNIX the above call can
5060 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5061 probably need to check that the client is a Windows one before disallowing
5062 this as a UNIX client (one with UNIX extensions) can know the source is a
5063 symlink and make this decision intelligently. Found by an excellent bug
5064 report from <AndyLiebman@aol.com>.
5065 ****************************************************************************/
5067 static BOOL rename_path_prefix_equal(const char *src, const char *dest)
5069 const char *psrc = src;
5070 const char *pdst = dest;
5073 if (psrc[0] == '.' && psrc[1] == '/') {
5076 if (pdst[0] == '.' && pdst[1] == '/') {
5079 if ((slen = strlen(psrc)) > strlen(pdst)) {
5082 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5086 * Do the notify calls from a rename
5089 static void notify_rename(connection_struct *conn, BOOL is_dir,
5090 const char *oldpath, const char *newpath)
5092 char *olddir, *newdir;
5093 const char *oldname, *newname;
5096 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5097 : FILE_NOTIFY_CHANGE_FILE_NAME;
5099 if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
5100 || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
5101 TALLOC_FREE(olddir);
5105 if (strcmp(olddir, newdir) == 0) {
5106 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
5107 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
5110 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
5111 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
5113 TALLOC_FREE(olddir);
5114 TALLOC_FREE(newdir);
5116 /* this is a strange one. w2k3 gives an additional event for
5117 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5118 files, but not directories */
5120 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5121 FILE_NOTIFY_CHANGE_ATTRIBUTES
5122 |FILE_NOTIFY_CHANGE_CREATION,
5127 /****************************************************************************
5128 Rename an open file - given an fsp.
5129 ****************************************************************************/
5131 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstring newname, uint32 attrs, BOOL replace_if_exists)
5133 SMB_STRUCT_STAT sbuf, sbuf1;
5134 pstring newname_last_component;
5135 NTSTATUS status = NT_STATUS_OK;
5136 struct share_mode_lock *lck = NULL;
5141 status = unix_convert(conn, newname, False, newname_last_component, &sbuf);
5143 /* If an error we expect this to be NT_STATUS_OBJECT_PATH_NOT_FOUND */
5145 if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND, status)) {
5149 status = check_name(conn, newname);
5150 if (!NT_STATUS_IS_OK(status)) {
5154 /* Ensure newname contains a '/' */
5155 if(strrchr_m(newname,'/') == 0) {
5158 pstrcpy(tmpstr, "./");
5159 pstrcat(tmpstr, newname);
5160 pstrcpy(newname, tmpstr);
5164 * Check for special case with case preserving and not
5165 * case sensitive. If the old last component differs from the original
5166 * last component only by case, then we should allow
5167 * the rename (user is trying to change the case of the
5171 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5172 strequal(newname, fsp->fsp_name)) {
5174 pstring newname_modified_last_component;
5177 * Get the last component of the modified name.
5178 * Note that we guarantee that newname contains a '/'
5181 p = strrchr_m(newname,'/');
5182 pstrcpy(newname_modified_last_component,p+1);
5184 if(strcsequal(newname_modified_last_component,
5185 newname_last_component) == False) {
5187 * Replace the modified last component with
5190 pstrcpy(p+1, newname_last_component);
5195 * If the src and dest names are identical - including case,
5196 * don't do the rename, just return success.
5199 if (strcsequal(fsp->fsp_name, newname)) {
5200 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5202 return NT_STATUS_OK;
5206 * Have vfs_object_exist also fill sbuf1
5208 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
5210 if(!replace_if_exists && dst_exists) {
5211 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5212 fsp->fsp_name,newname));
5213 return NT_STATUS_OBJECT_NAME_COLLISION;
5217 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5218 files_struct *dst_fsp = file_find_di_first(fileid);
5220 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5221 return NT_STATUS_ACCESS_DENIED;
5225 /* Ensure we have a valid stat struct for the source. */
5226 if (fsp->fh->fd != -1) {
5227 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) == -1) {
5228 return map_nt_error_from_unix(errno);
5231 if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
5232 return map_nt_error_from_unix(errno);
5236 status = can_rename(conn, fsp, attrs, &sbuf);
5238 if (!NT_STATUS_IS_OK(status)) {
5239 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5240 nt_errstr(status), fsp->fsp_name,newname));
5241 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5242 status = NT_STATUS_ACCESS_DENIED;
5246 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5247 return NT_STATUS_ACCESS_DENIED;
5250 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
5253 * We have the file open ourselves, so not being able to get the
5254 * corresponding share mode lock is a fatal error.
5257 SMB_ASSERT(lck != NULL);
5259 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5260 uint32 create_options = fsp->fh->private_options;
5262 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5263 fsp->fsp_name,newname));
5265 rename_open_files(conn, lck, newname);
5267 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5270 * A rename acts as a new file create w.r.t. allowing an initial delete
5271 * on close, probably because in Windows there is a new handle to the
5272 * new file. If initial delete on close was requested but not
5273 * originally set, we need to set it here. This is probably not 100% correct,
5274 * but will work for the CIFSFS client which in non-posix mode
5275 * depends on these semantics. JRA.
5278 set_allow_initial_delete_on_close(lck, fsp, True);
5280 if (create_options & FILE_DELETE_ON_CLOSE) {
5281 status = can_set_delete_on_close(fsp, True, 0);
5283 if (NT_STATUS_IS_OK(status)) {
5284 /* Note that here we set the *inital* delete on close flag,
5285 * not the regular one. The magic gets handled in close. */
5286 fsp->initial_delete_on_close = True;
5290 return NT_STATUS_OK;
5295 if (errno == ENOTDIR || errno == EISDIR) {
5296 status = NT_STATUS_OBJECT_NAME_COLLISION;
5298 status = map_nt_error_from_unix(errno);
5301 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5302 nt_errstr(status), fsp->fsp_name,newname));
5307 /****************************************************************************
5308 The guts of the rename command, split out so it may be called by the NT SMB
5310 ****************************************************************************/
5312 NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
5316 BOOL replace_if_exists,
5322 pstring last_component_src;
5323 pstring last_component_dest;
5326 NTSTATUS status = NT_STATUS_OK;
5327 SMB_STRUCT_STAT sbuf1, sbuf2;
5328 struct smb_Dir *dir_hnd = NULL;
5333 *directory = *mask = 0;
5338 status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1);
5339 if (!NT_STATUS_IS_OK(status)) {
5343 status = unix_convert(conn, newname, dest_has_wild, last_component_dest, &sbuf2);
5344 if (!NT_STATUS_IS_OK(status)) {
5349 * Split the old name into directory and last component
5350 * strings. Note that unix_convert may have stripped off a
5351 * leading ./ from both name and newname if the rename is
5352 * at the root of the share. We need to make sure either both
5353 * name and newname contain a / character or neither of them do
5354 * as this is checked in resolve_wildcards().
5357 p = strrchr_m(name,'/');
5359 pstrcpy(directory,".");
5363 pstrcpy(directory,name);
5365 *p = '/'; /* Replace needed for exceptional test below. */
5369 * We should only check the mangled cache
5370 * here if unix_convert failed. This means
5371 * that the path in 'mask' doesn't exist
5372 * on the file system and so we need to look
5373 * for a possible mangle. This patch from
5374 * Tine Smukavec <valentin.smukavec@hermes.si>.
5377 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5378 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
5381 if (!src_has_wild) {
5385 * No wildcards - just process the one file.
5387 BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
5389 /* Add a terminating '/' to the directory name. */
5390 pstrcat(directory,"/");
5391 pstrcat(directory,mask);
5393 /* Ensure newname contains a '/' also */
5394 if(strrchr_m(newname,'/') == 0) {
5397 pstrcpy(tmpstr, "./");
5398 pstrcat(tmpstr, newname);
5399 pstrcpy(newname, tmpstr);
5402 DEBUG(3, ("rename_internals: case_sensitive = %d, "
5403 "case_preserve = %d, short case preserve = %d, "
5404 "directory = %s, newname = %s, "
5405 "last_component_dest = %s, is_8_3 = %d\n",
5406 conn->case_sensitive, conn->case_preserve,
5407 conn->short_case_preserve, directory,
5408 newname, last_component_dest, is_short_name));
5410 /* The dest name still may have wildcards. */
5411 if (dest_has_wild) {
5412 if (!resolve_wildcards(directory,newname)) {
5413 DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n",
5414 directory,newname));
5415 return NT_STATUS_NO_MEMORY;
5420 SMB_VFS_STAT(conn, directory, &sbuf1);
5422 status = S_ISDIR(sbuf1.st_mode) ?
5423 open_directory(conn, req, directory, &sbuf1,
5425 FILE_SHARE_READ|FILE_SHARE_WRITE,
5426 FILE_OPEN, 0, 0, NULL,
5428 : open_file_ntcreate(conn, req, directory, &sbuf1,
5430 FILE_SHARE_READ|FILE_SHARE_WRITE,
5431 FILE_OPEN, 0, 0, 0, NULL,
5434 if (!NT_STATUS_IS_OK(status)) {
5435 DEBUG(3, ("Could not open rename source %s: %s\n",
5436 directory, nt_errstr(status)));
5440 status = rename_internals_fsp(conn, fsp, newname, attrs,
5443 close_file(fsp, NORMAL_CLOSE);
5445 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
5446 nt_errstr(status), directory,newname));
5452 * Wildcards - process each file that matches.
5454 if (strequal(mask,"????????.???")) {
5458 status = check_name(conn, directory);
5459 if (!NT_STATUS_IS_OK(status)) {
5463 dir_hnd = OpenDir(conn, directory, mask, attrs);
5464 if (dir_hnd == NULL) {
5465 return map_nt_error_from_unix(errno);
5468 status = NT_STATUS_NO_SUCH_FILE;
5470 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
5471 * - gentest fix. JRA
5474 while ((dname = ReadDirName(dir_hnd, &offset))) {
5477 BOOL sysdir_entry = False;
5479 pstrcpy(fname,dname);
5481 /* Quick check for "." and ".." */
5482 if (fname[0] == '.') {
5483 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
5485 sysdir_entry = True;
5492 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5496 if(!mask_match(fname, mask, conn->case_sensitive)) {
5501 status = NT_STATUS_OBJECT_NAME_INVALID;
5505 slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname);
5507 pstrcpy(destname,newname);
5509 if (!resolve_wildcards(fname,destname)) {
5510 DEBUG(6, ("resolve_wildcards %s %s failed\n",
5516 SMB_VFS_STAT(conn, fname, &sbuf1);
5518 status = S_ISDIR(sbuf1.st_mode) ?
5519 open_directory(conn, req, fname, &sbuf1,
5521 FILE_SHARE_READ|FILE_SHARE_WRITE,
5522 FILE_OPEN, 0, 0, NULL,
5524 : open_file_ntcreate(conn, req, fname, &sbuf1,
5526 FILE_SHARE_READ|FILE_SHARE_WRITE,
5527 FILE_OPEN, 0, 0, 0, NULL,
5530 if (!NT_STATUS_IS_OK(status)) {
5531 DEBUG(3,("rename_internals: open_file_ntcreate "
5532 "returned %s rename %s -> %s\n",
5533 nt_errstr(status), directory, newname));
5537 status = rename_internals_fsp(conn, fsp, destname, attrs,
5540 close_file(fsp, NORMAL_CLOSE);
5542 if (!NT_STATUS_IS_OK(status)) {
5543 DEBUG(3, ("rename_internals_fsp returned %s for "
5544 "rename %s -> %s\n", nt_errstr(status),
5545 directory, newname));
5551 DEBUG(3,("rename_internals: doing rename on %s -> "
5552 "%s\n",fname,destname));
5556 if (count == 0 && NT_STATUS_IS_OK(status)) {
5557 status = map_nt_error_from_unix(errno);
5563 /****************************************************************************
5565 ****************************************************************************/
5567 void reply_mv(connection_struct *conn, struct smb_request *req)
5574 BOOL src_has_wcard = False;
5575 BOOL dest_has_wcard = False;
5577 START_PROFILE(SMBmv);
5580 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5585 attrs = SVAL(req->inbuf,smb_vwv0);
5587 p = smb_buf(req->inbuf) + 1;
5588 p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, name, p,
5589 sizeof(name), 0, STR_TERMINATE, &status,
5591 if (!NT_STATUS_IS_OK(status)) {
5592 reply_nterror(req, status);
5597 p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, newname, p,
5598 sizeof(newname), 0, STR_TERMINATE, &status,
5600 if (!NT_STATUS_IS_OK(status)) {
5601 reply_nterror(req, status);
5606 status = resolve_dfspath_wcard(conn,
5607 req->flags2 & FLAGS2_DFS_PATHNAMES,
5608 name, &src_has_wcard);
5609 if (!NT_STATUS_IS_OK(status)) {
5610 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5611 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5612 ERRSRV, ERRbadpath);
5616 reply_nterror(req, status);
5621 status = resolve_dfspath_wcard(conn,
5622 req->flags2 & FLAGS2_DFS_PATHNAMES,
5623 newname, &dest_has_wcard);
5624 if (!NT_STATUS_IS_OK(status)) {
5625 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5626 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5627 ERRSRV, ERRbadpath);
5631 reply_nterror(req, status);
5636 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
5638 status = rename_internals(conn, req, name, newname, attrs, False,
5639 src_has_wcard, dest_has_wcard);
5640 if (!NT_STATUS_IS_OK(status)) {
5641 if (open_was_deferred(req->mid)) {
5642 /* We have re-scheduled this call. */
5646 reply_nterror(req, status);
5651 reply_outbuf(req, 0, 0);
5657 /*******************************************************************
5658 Copy a file as part of a reply_copy.
5659 ******************************************************************/
5662 * TODO: check error codes on all callers
5665 NTSTATUS copy_file(connection_struct *conn,
5670 BOOL target_is_directory)
5672 SMB_STRUCT_STAT src_sbuf, sbuf2;
5674 files_struct *fsp1,*fsp2;
5677 uint32 new_create_disposition;
5680 pstrcpy(dest,dest1);
5681 if (target_is_directory) {
5682 char *p = strrchr_m(src,'/');
5692 if (!vfs_file_exist(conn,src,&src_sbuf)) {
5693 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5696 if (!target_is_directory && count) {
5697 new_create_disposition = FILE_OPEN;
5699 if (!map_open_params_to_ntcreate(dest1,0,ofun,
5700 NULL, NULL, &new_create_disposition, NULL)) {
5701 return NT_STATUS_INVALID_PARAMETER;
5705 status = open_file_ntcreate(conn, NULL, src, &src_sbuf,
5707 FILE_SHARE_READ|FILE_SHARE_WRITE,
5710 FILE_ATTRIBUTE_NORMAL,
5714 if (!NT_STATUS_IS_OK(status)) {
5718 dosattrs = dos_mode(conn, src, &src_sbuf);
5719 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
5720 ZERO_STRUCTP(&sbuf2);
5723 status = open_file_ntcreate(conn, NULL, dest, &sbuf2,
5725 FILE_SHARE_READ|FILE_SHARE_WRITE,
5726 new_create_disposition,
5732 if (!NT_STATUS_IS_OK(status)) {
5733 close_file(fsp1,ERROR_CLOSE);
5737 if ((ofun&3) == 1) {
5738 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
5739 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
5741 * Stop the copy from occurring.
5744 src_sbuf.st_size = 0;
5748 if (src_sbuf.st_size) {
5749 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
5752 close_file(fsp1,NORMAL_CLOSE);
5754 /* Ensure the modtime is set correctly on the destination file. */
5755 fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
5758 * As we are opening fsp1 read-only we only expect
5759 * an error on close on fsp2 if we are out of space.
5760 * Thus we don't look at the error return from the
5763 status = close_file(fsp2,NORMAL_CLOSE);
5765 if (!NT_STATUS_IS_OK(status)) {
5769 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
5770 return NT_STATUS_DISK_FULL;
5773 return NT_STATUS_OK;
5776 /****************************************************************************
5777 Reply to a file copy.
5778 ****************************************************************************/
5780 void reply_copy(connection_struct *conn, struct smb_request *req)
5784 pstring mask,newname;
5787 int error = ERRnoaccess;
5792 BOOL target_is_directory=False;
5793 BOOL source_has_wild = False;
5794 BOOL dest_has_wild = False;
5795 SMB_STRUCT_STAT sbuf1, sbuf2;
5798 START_PROFILE(SMBcopy);
5801 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5802 END_PROFILE(SMBcopy);
5806 tid2 = SVAL(req->inbuf,smb_vwv0);
5807 ofun = SVAL(req->inbuf,smb_vwv1);
5808 flags = SVAL(req->inbuf,smb_vwv2);
5810 *directory = *mask = 0;
5812 p = smb_buf(req->inbuf);
5813 p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, name, p,
5814 sizeof(name), 0, STR_TERMINATE, &status,
5816 if (!NT_STATUS_IS_OK(status)) {
5817 reply_nterror(req, status);
5818 END_PROFILE(SMBcopy);
5821 p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, newname, p,
5822 sizeof(newname), 0, STR_TERMINATE, &status,
5824 if (!NT_STATUS_IS_OK(status)) {
5825 reply_nterror(req, status);
5826 END_PROFILE(SMBcopy);
5830 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
5832 if (tid2 != conn->cnum) {
5833 /* can't currently handle inter share copies XXXX */
5834 DEBUG(3,("Rejecting inter-share copy\n"));
5835 reply_doserror(req, ERRSRV, ERRinvdevice);
5836 END_PROFILE(SMBcopy);
5840 status = resolve_dfspath_wcard(conn,
5841 req->flags2 & FLAGS2_DFS_PATHNAMES,
5842 name, &source_has_wild);
5843 if (!NT_STATUS_IS_OK(status)) {
5844 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5845 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5846 ERRSRV, ERRbadpath);
5847 END_PROFILE(SMBcopy);
5850 reply_nterror(req, status);
5851 END_PROFILE(SMBcopy);
5855 status = resolve_dfspath_wcard(conn,
5856 req->flags2 & FLAGS2_DFS_PATHNAMES,
5857 newname, &dest_has_wild);
5858 if (!NT_STATUS_IS_OK(status)) {
5859 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5860 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5861 ERRSRV, ERRbadpath);
5862 END_PROFILE(SMBcopy);
5865 reply_nterror(req, status);
5866 END_PROFILE(SMBcopy);
5870 status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1);
5871 if (!NT_STATUS_IS_OK(status)) {
5872 reply_nterror(req, status);
5873 END_PROFILE(SMBcopy);
5877 status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2);
5878 if (!NT_STATUS_IS_OK(status)) {
5879 reply_nterror(req, status);
5880 END_PROFILE(SMBcopy);
5884 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
5886 if ((flags&1) && target_is_directory) {
5887 reply_doserror(req, ERRDOS, ERRbadfile);
5888 END_PROFILE(SMBcopy);
5892 if ((flags&2) && !target_is_directory) {
5893 reply_doserror(req, ERRDOS, ERRbadpath);
5894 END_PROFILE(SMBcopy);
5898 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
5899 /* wants a tree copy! XXXX */
5900 DEBUG(3,("Rejecting tree copy\n"));
5901 reply_doserror(req, ERRSRV, ERRerror);
5902 END_PROFILE(SMBcopy);
5906 p = strrchr_m(name,'/');
5908 pstrcpy(directory,"./");
5912 pstrcpy(directory,name);
5917 * We should only check the mangled cache
5918 * here if unix_convert failed. This means
5919 * that the path in 'mask' doesn't exist
5920 * on the file system and so we need to look
5921 * for a possible mangle. This patch from
5922 * Tine Smukavec <valentin.smukavec@hermes.si>.
5925 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5926 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
5929 if (!source_has_wild) {
5930 pstrcat(directory,"/");
5931 pstrcat(directory,mask);
5932 if (dest_has_wild) {
5933 if (!resolve_wildcards(directory,newname)) {
5934 reply_nterror(req, NT_STATUS_NO_MEMORY);
5935 END_PROFILE(SMBcopy);
5940 status = check_name(conn, directory);
5941 if (!NT_STATUS_IS_OK(status)) {
5942 reply_nterror(req, status);
5943 END_PROFILE(SMBcopy);
5947 status = check_name(conn, newname);
5948 if (!NT_STATUS_IS_OK(status)) {
5949 reply_nterror(req, status);
5950 END_PROFILE(SMBcopy);
5954 status = copy_file(conn,directory,newname,ofun,
5955 count,target_is_directory);
5957 if(!NT_STATUS_IS_OK(status)) {
5958 reply_nterror(req, status);
5959 END_PROFILE(SMBcopy);
5965 struct smb_Dir *dir_hnd = NULL;
5970 if (strequal(mask,"????????.???"))
5973 status = check_name(conn, directory);
5974 if (!NT_STATUS_IS_OK(status)) {
5975 reply_nterror(req, status);
5976 END_PROFILE(SMBcopy);
5980 dir_hnd = OpenDir(conn, directory, mask, 0);
5981 if (dir_hnd == NULL) {
5982 status = map_nt_error_from_unix(errno);
5983 reply_nterror(req, status);
5984 END_PROFILE(SMBcopy);
5990 while ((dname = ReadDirName(dir_hnd, &offset))) {
5992 pstrcpy(fname,dname);
5994 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5998 if(!mask_match(fname, mask, conn->case_sensitive)) {
6002 error = ERRnoaccess;
6003 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
6004 pstrcpy(destname,newname);
6005 if (!resolve_wildcards(fname,destname)) {
6009 status = check_name(conn, fname);
6010 if (!NT_STATUS_IS_OK(status)) {
6011 reply_nterror(req, status);
6012 END_PROFILE(SMBcopy);
6016 status = check_name(conn, destname);
6017 if (!NT_STATUS_IS_OK(status)) {
6018 reply_nterror(req, status);
6019 END_PROFILE(SMBcopy);
6023 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
6025 status = copy_file(conn,fname,destname,ofun,
6026 count,target_is_directory);
6027 if (NT_STATUS_IS_OK(status)) {
6036 /* Error on close... */
6038 reply_unixerror(req, ERRHRD, ERRgeneral);
6039 END_PROFILE(SMBcopy);
6043 reply_doserror(req, ERRDOS, error);
6044 END_PROFILE(SMBcopy);
6048 reply_outbuf(req, 1, 0);
6049 SSVAL(req->outbuf,smb_vwv0,count);
6051 END_PROFILE(SMBcopy);
6056 #define DBGC_CLASS DBGC_LOCKING
6058 /****************************************************************************
6059 Get a lock pid, dealing with large count requests.
6060 ****************************************************************************/
6062 uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
6064 if(!large_file_format)
6065 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
6067 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6070 /****************************************************************************
6071 Get a lock count, dealing with large count requests.
6072 ****************************************************************************/
6074 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
6076 SMB_BIG_UINT count = 0;
6078 if(!large_file_format) {
6079 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6082 #if defined(HAVE_LONGLONG)
6083 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6084 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6085 #else /* HAVE_LONGLONG */
6088 * NT4.x seems to be broken in that it sends large file (64 bit)
6089 * lockingX calls even if the CAP_LARGE_FILES was *not*
6090 * negotiated. For boxes without large unsigned ints truncate the
6091 * lock count by dropping the top 32 bits.
6094 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6095 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6096 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6097 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6098 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6101 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6102 #endif /* HAVE_LONGLONG */
6108 #if !defined(HAVE_LONGLONG)
6109 /****************************************************************************
6110 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6111 ****************************************************************************/
6113 static uint32 map_lock_offset(uint32 high, uint32 low)
6117 uint32 highcopy = high;
6120 * Try and find out how many significant bits there are in high.
6123 for(i = 0; highcopy; i++)
6127 * We use 31 bits not 32 here as POSIX
6128 * lock offsets may not be negative.
6131 mask = (~0) << (31 - i);
6134 return 0; /* Fail. */
6140 #endif /* !defined(HAVE_LONGLONG) */
6142 /****************************************************************************
6143 Get a lock offset, dealing with large offset requests.
6144 ****************************************************************************/
6146 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
6148 SMB_BIG_UINT offset = 0;
6152 if(!large_file_format) {
6153 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
6156 #if defined(HAVE_LONGLONG)
6157 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
6158 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
6159 #else /* HAVE_LONGLONG */
6162 * NT4.x seems to be broken in that it sends large file (64 bit)
6163 * lockingX calls even if the CAP_LARGE_FILES was *not*
6164 * negotiated. For boxes without large unsigned ints mangle the
6165 * lock offset by mapping the top 32 bits onto the lower 32.
6168 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
6169 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6170 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
6173 if((new_low = map_lock_offset(high, low)) == 0) {
6175 return (SMB_BIG_UINT)-1;
6178 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
6179 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
6180 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
6181 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
6184 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6185 #endif /* HAVE_LONGLONG */
6191 /****************************************************************************
6192 Reply to a lockingX request.
6193 ****************************************************************************/
6195 void reply_lockingX(connection_struct *conn, struct smb_request *req)
6198 unsigned char locktype;
6199 unsigned char oplocklevel;
6202 SMB_BIG_UINT count = 0, offset = 0;
6207 BOOL large_file_format;
6209 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
6211 START_PROFILE(SMBlockingX);
6214 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6215 END_PROFILE(SMBlockingX);
6219 fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
6220 locktype = CVAL(req->inbuf,smb_vwv3);
6221 oplocklevel = CVAL(req->inbuf,smb_vwv3+1);
6222 num_ulocks = SVAL(req->inbuf,smb_vwv6);
6223 num_locks = SVAL(req->inbuf,smb_vwv7);
6224 lock_timeout = IVAL(req->inbuf,smb_vwv4);
6225 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
6227 if (!check_fsp(conn, req, fsp, ¤t_user)) {
6228 END_PROFILE(SMBlockingX);
6232 data = smb_buf(req->inbuf);
6234 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
6235 /* we don't support these - and CANCEL_LOCK makes w2k
6236 and XP reboot so I don't really want to be
6237 compatible! (tridge) */
6238 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
6239 END_PROFILE(SMBlockingX);
6243 /* Check if this is an oplock break on a file
6244 we have granted an oplock on.
6246 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
6247 /* Client can insist on breaking to none. */
6248 BOOL break_to_none = (oplocklevel == 0);
6251 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6252 "for fnum = %d\n", (unsigned int)oplocklevel,
6256 * Make sure we have granted an exclusive or batch oplock on
6260 if (fsp->oplock_type == 0) {
6262 /* The Samba4 nbench simulator doesn't understand
6263 the difference between break to level2 and break
6264 to none from level2 - it sends oplock break
6265 replies in both cases. Don't keep logging an error
6266 message here - just ignore it. JRA. */
6268 DEBUG(5,("reply_lockingX: Error : oplock break from "
6269 "client for fnum = %d (oplock=%d) and no "
6270 "oplock granted on this file (%s).\n",
6271 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
6273 /* if this is a pure oplock break request then don't
6275 if (num_locks == 0 && num_ulocks == 0) {
6276 END_PROFILE(SMBlockingX);
6277 reply_post_legacy(req, -1);
6280 END_PROFILE(SMBlockingX);
6281 reply_doserror(req, ERRDOS, ERRlock);
6286 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
6288 result = remove_oplock(fsp);
6290 result = downgrade_oplock(fsp);
6294 DEBUG(0, ("reply_lockingX: error in removing "
6295 "oplock on file %s\n", fsp->fsp_name));
6296 /* Hmmm. Is this panic justified? */
6297 smb_panic("internal tdb error");
6300 reply_to_oplock_break_requests(fsp);
6302 /* if this is a pure oplock break request then don't send a
6304 if (num_locks == 0 && num_ulocks == 0) {
6305 /* Sanity check - ensure a pure oplock break is not a
6307 if(CVAL(req->inbuf,smb_vwv0) != 0xff)
6308 DEBUG(0,("reply_lockingX: Error : pure oplock "
6309 "break is a chained %d request !\n",
6310 (unsigned int)CVAL(req->inbuf,
6312 END_PROFILE(SMBlockingX);
6318 * We do this check *after* we have checked this is not a oplock break
6319 * response message. JRA.
6322 release_level_2_oplocks_on_change(fsp);
6324 if (smb_buflen(req->inbuf) <
6325 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
6326 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6327 END_PROFILE(SMBlockingX);
6331 /* Data now points at the beginning of the list
6332 of smb_unlkrng structs */
6333 for(i = 0; i < (int)num_ulocks; i++) {
6334 lock_pid = get_lock_pid( data, i, large_file_format);
6335 count = get_lock_count( data, i, large_file_format);
6336 offset = get_lock_offset( data, i, large_file_format, &err);
6339 * There is no error code marked "stupid client bug".... :-).
6342 END_PROFILE(SMBlockingX);
6343 reply_doserror(req, ERRDOS, ERRnoaccess);
6347 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
6348 "pid %u, file %s\n", (double)offset, (double)count,
6349 (unsigned int)lock_pid, fsp->fsp_name ));
6351 status = do_unlock(smbd_messaging_context(),
6358 if (NT_STATUS_V(status)) {
6359 END_PROFILE(SMBlockingX);
6360 reply_nterror(req, status);
6365 /* Setup the timeout in seconds. */
6367 if (!lp_blocking_locks(SNUM(conn))) {
6371 /* Now do any requested locks */
6372 data += ((large_file_format ? 20 : 10)*num_ulocks);
6374 /* Data now points at the beginning of the list
6375 of smb_lkrng structs */
6377 for(i = 0; i < (int)num_locks; i++) {
6378 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
6379 READ_LOCK:WRITE_LOCK);
6380 lock_pid = get_lock_pid( data, i, large_file_format);
6381 count = get_lock_count( data, i, large_file_format);
6382 offset = get_lock_offset( data, i, large_file_format, &err);
6385 * There is no error code marked "stupid client bug".... :-).
6388 END_PROFILE(SMBlockingX);
6389 reply_doserror(req, ERRDOS, ERRnoaccess);
6393 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
6394 "%u, file %s timeout = %d\n", (double)offset,
6395 (double)count, (unsigned int)lock_pid,
6396 fsp->fsp_name, (int)lock_timeout ));
6398 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
6399 if (lp_blocking_locks(SNUM(conn))) {
6401 /* Schedule a message to ourselves to
6402 remove the blocking lock record and
6403 return the right error. */
6405 if (!blocking_lock_cancel(fsp,
6411 NT_STATUS_FILE_LOCK_CONFLICT)) {
6412 END_PROFILE(SMBlockingX);
6417 ERRcancelviolation));
6421 /* Remove a matching pending lock. */
6422 status = do_lock_cancel(fsp,
6428 BOOL blocking_lock = lock_timeout ? True : False;
6429 BOOL defer_lock = False;
6430 struct byte_range_lock *br_lck;
6431 uint32 block_smbpid;
6433 br_lck = do_lock(smbd_messaging_context(),
6444 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6445 /* Windows internal resolution for blocking locks seems
6446 to be about 200ms... Don't wait for less than that. JRA. */
6447 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
6448 lock_timeout = lp_lock_spin_time();
6453 /* This heuristic seems to match W2K3 very well. If a
6454 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
6455 it pretends we asked for a timeout of between 150 - 300 milliseconds as
6456 far as I can tell. Replacement for do_lock_spin(). JRA. */
6458 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
6459 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
6461 lock_timeout = lp_lock_spin_time();
6464 if (br_lck && defer_lock) {
6466 * A blocking lock was requested. Package up
6467 * this smb into a queued request and push it
6468 * onto the blocking lock queue.
6470 if(push_blocking_lock_request(br_lck,
6472 smb_len(req->inbuf)+4,
6482 TALLOC_FREE(br_lck);
6483 END_PROFILE(SMBlockingX);
6484 reply_post_legacy(req, -1);
6489 TALLOC_FREE(br_lck);
6492 if (NT_STATUS_V(status)) {
6493 END_PROFILE(SMBlockingX);
6494 reply_nterror(req, status);
6499 /* If any of the above locks failed, then we must unlock
6500 all of the previous locks (X/Open spec). */
6502 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
6506 * Ensure we don't do a remove on the lock that just failed,
6507 * as under POSIX rules, if we have a lock already there, we
6508 * will delete it (and we shouldn't) .....
6510 for(i--; i >= 0; i--) {
6511 lock_pid = get_lock_pid( data, i, large_file_format);
6512 count = get_lock_count( data, i, large_file_format);
6513 offset = get_lock_offset( data, i, large_file_format,
6517 * There is no error code marked "stupid client
6521 END_PROFILE(SMBlockingX);
6522 reply_doserror(req, ERRDOS, ERRnoaccess);
6526 do_unlock(smbd_messaging_context(),
6533 END_PROFILE(SMBlockingX);
6534 reply_nterror(req, status);
6538 reply_outbuf(req, 2, 0);
6540 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
6541 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
6543 END_PROFILE(SMBlockingX);
6544 chain_reply_new(req);
6548 #define DBGC_CLASS DBGC_ALL
6550 /****************************************************************************
6551 Reply to a SMBreadbmpx (read block multiplex) request.
6552 Always reply with an error, if someone has a platform really needs this,
6553 please contact vl@samba.org
6554 ****************************************************************************/
6556 void reply_readbmpx(connection_struct *conn, struct smb_request *req)
6558 START_PROFILE(SMBreadBmpx);
6559 reply_doserror(req, ERRSRV, ERRuseSTD);
6560 END_PROFILE(SMBreadBmpx);
6564 /****************************************************************************
6565 Reply to a SMBreadbs (read block multiplex secondary) request.
6566 Always reply with an error, if someone has a platform really needs this,
6567 please contact vl@samba.org
6568 ****************************************************************************/
6570 void reply_readbs(connection_struct *conn, struct smb_request *req)
6572 START_PROFILE(SMBreadBs);
6573 reply_doserror(req, ERRSRV, ERRuseSTD);
6574 END_PROFILE(SMBreadBs);
6578 /****************************************************************************
6579 Reply to a SMBsetattrE.
6580 ****************************************************************************/
6582 void reply_setattrE(connection_struct *conn, struct smb_request *req)
6584 struct timespec ts[2];
6587 START_PROFILE(SMBsetattrE);
6590 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6591 END_PROFILE(SMBsetattrE);
6595 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
6597 if(!fsp || (fsp->conn != conn)) {
6598 reply_doserror(req, ERRDOS, ERRbadfid);
6599 END_PROFILE(SMBsetattrE);
6605 * Convert the DOS times into unix times. Ignore create
6606 * time as UNIX can't set this.
6609 ts[0] = convert_time_t_to_timespec(
6610 srv_make_unix_date2(req->inbuf+smb_vwv3)); /* atime. */
6611 ts[1] = convert_time_t_to_timespec(
6612 srv_make_unix_date2(req->inbuf+smb_vwv5)); /* mtime. */
6614 reply_outbuf(req, 0, 0);
6617 * Patch from Ray Frush <frush@engr.colostate.edu>
6618 * Sometimes times are sent as zero - ignore them.
6621 if (null_timespec(ts[0]) && null_timespec(ts[1])) {
6622 /* Ignore request */
6623 if( DEBUGLVL( 3 ) ) {
6624 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
6625 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
6627 END_PROFILE(SMBsetattrE);
6629 } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
6630 /* set modify time = to access time if modify time was unset */
6634 /* Set the date on this file */
6635 /* Should we set pending modtime here ? JRA */
6636 if(file_ntimes(conn, fsp->fsp_name, ts)) {
6637 reply_doserror(req, ERRDOS, ERRnoaccess);
6638 END_PROFILE(SMBsetattrE);
6642 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
6644 (unsigned int)ts[0].tv_sec,
6645 (unsigned int)ts[1].tv_sec));
6647 END_PROFILE(SMBsetattrE);
6652 /* Back from the dead for OS/2..... JRA. */
6654 /****************************************************************************
6655 Reply to a SMBwritebmpx (write block multiplex primary) request.
6656 Always reply with an error, if someone has a platform really needs this,
6657 please contact vl@samba.org
6658 ****************************************************************************/
6660 void reply_writebmpx(connection_struct *conn, struct smb_request *req)
6662 START_PROFILE(SMBwriteBmpx);
6663 reply_doserror(req, ERRSRV, ERRuseSTD);
6664 END_PROFILE(SMBwriteBmpx);
6668 /****************************************************************************
6669 Reply to a SMBwritebs (write block multiplex secondary) request.
6670 Always reply with an error, if someone has a platform really needs this,
6671 please contact vl@samba.org
6672 ****************************************************************************/
6674 void reply_writebs(connection_struct *conn, struct smb_request *req)
6676 START_PROFILE(SMBwriteBs);
6677 reply_doserror(req, ERRSRV, ERRuseSTD);
6678 END_PROFILE(SMBwriteBs);
6682 /****************************************************************************
6683 Reply to a SMBgetattrE.
6684 ****************************************************************************/
6686 void reply_getattrE(connection_struct *conn, struct smb_request *req)
6688 SMB_STRUCT_STAT sbuf;
6692 START_PROFILE(SMBgetattrE);
6695 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6696 END_PROFILE(SMBgetattrE);
6700 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
6702 if(!fsp || (fsp->conn != conn)) {
6703 reply_doserror(req, ERRDOS, ERRbadfid);
6704 END_PROFILE(SMBgetattrE);
6708 /* Do an fstat on this file */
6709 if(fsp_stat(fsp, &sbuf)) {
6710 reply_unixerror(req, ERRDOS, ERRnoaccess);
6711 END_PROFILE(SMBgetattrE);
6715 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
6718 * Convert the times into dos times. Set create
6719 * date to be last modify date as UNIX doesn't save
6723 reply_outbuf(req, 11, 0);
6725 srv_put_dos_date2((char *)req->outbuf, smb_vwv0,
6726 get_create_time(&sbuf,
6727 lp_fake_dir_create_times(SNUM(conn))));
6728 srv_put_dos_date2((char *)req->outbuf, smb_vwv2, sbuf.st_atime);
6729 /* Should we check pending modtime here ? JRA */
6730 srv_put_dos_date2((char *)req->outbuf, smb_vwv4, sbuf.st_mtime);
6733 SIVAL(req->outbuf, smb_vwv6, 0);
6734 SIVAL(req->outbuf, smb_vwv8, 0);
6736 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
6737 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_size);
6738 SIVAL(req->outbuf, smb_vwv8, allocation_size);
6740 SSVAL(req->outbuf,smb_vwv10, mode);
6742 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
6744 END_PROFILE(SMBgetattrE);