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-2004.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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;
33 extern int global_oplock_break;
34 unsigned int smb_echo_count = 0;
35 extern uint32 global_client_caps;
37 extern struct current_user current_user;
38 extern BOOL global_encrypted_passwords_negotiated;
40 /****************************************************************************
41 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
42 We're assuming here that '/' is not the second byte in any multibyte char
43 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
45 ****************************************************************************/
47 NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
50 const char *s = srcname;
51 NTSTATUS ret = NT_STATUS_OK;
52 BOOL start_of_name_component = True;
53 unsigned int num_bad_components = 0;
56 if (IS_DIRECTORY_SEP(*s)) {
58 * Safe to assume is not the second part of a mb char as this is handled below.
60 /* Eat multiple '/' or '\\' */
61 while (IS_DIRECTORY_SEP(*s)) {
64 if ((d != destname) && (*s != '\0')) {
65 /* We only care about non-leading or trailing '/' or '\\' */
69 start_of_name_component = True;
73 if (start_of_name_component) {
74 if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
75 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
78 * No mb char starts with '.' so we're safe checking the directory separator here.
81 /* If we just added a '/' - delete it */
82 if ((d > destname) && (*(d-1) == '/')) {
87 /* Are we at the start ? Can't go back further if so. */
89 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
92 /* Go back one level... */
93 /* We know this is safe as '/' cannot be part of a mb sequence. */
94 /* NOTE - if this assumption is invalid we are not in good shape... */
95 /* Decrement d first as d points to the *next* char to write into. */
96 for (d--; d > destname; d--) {
100 s += 2; /* Else go past the .. */
101 /* We're still at the start of a name component, just the previous one. */
103 if (num_bad_components) {
104 /* Hmmm. Should we only decrement the bad_components if
105 we're removing a bad component ? Need to check this. JRA. */
106 num_bad_components--;
111 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
112 /* Component of pathname can't be "." only. */
113 ret = NT_STATUS_OBJECT_NAME_INVALID;
114 num_bad_components++;
122 return NT_STATUS_OBJECT_NAME_INVALID;
130 return NT_STATUS_OBJECT_NAME_INVALID;
136 switch(next_mb_char_size(s)) {
147 DEBUG(0,("check_path_syntax: character length assumptions invalid !\n"));
149 return NT_STATUS_INVALID_PARAMETER;
152 if (start_of_name_component && num_bad_components) {
153 num_bad_components++;
155 start_of_name_component = False;
158 if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
159 if (num_bad_components > 1) {
160 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
168 /****************************************************************************
169 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
170 path or anything including wildcards.
171 We're assuming here that '/' is not the second byte in any multibyte char
172 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
174 ****************************************************************************/
176 NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname)
179 const char *s = srcname;
180 NTSTATUS ret = NT_STATUS_OK;
181 BOOL start_of_name_component = True;
182 unsigned int num_bad_components = 0;
185 if (IS_DIRECTORY_SEP(*s)) {
187 * Safe to assume is not the second part of a mb char as this is handled below.
189 /* Eat multiple '/' or '\\' */
190 while (IS_DIRECTORY_SEP(*s)) {
193 if ((d != destname) && (*s != '\0')) {
194 /* We only care about non-leading or trailing '/' or '\\' */
198 start_of_name_component = True;
202 if (start_of_name_component) {
203 if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
204 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
207 * No mb char starts with '.' so we're safe checking the directory separator here.
210 /* If we just added a '/' - delete it */
211 if ((d > destname) && (*(d-1) == '/')) {
216 /* Are we at the start ? Can't go back further if so. */
218 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
221 /* Go back one level... */
222 /* We know this is safe as '/' cannot be part of a mb sequence. */
223 /* NOTE - if this assumption is invalid we are not in good shape... */
224 /* Decrement d first as d points to the *next* char to write into. */
225 for (d--; d > destname; d--) {
229 s += 2; /* Else go past the .. */
230 /* We're still at the start of a name component, just the previous one. */
232 if (num_bad_components) {
233 /* Hmmm. Should we only decrement the bad_components if
234 we're removing a bad component ? Need to check this. JRA. */
235 num_bad_components--;
240 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
241 /* Component of pathname can't be "." only. */
242 ret = NT_STATUS_OBJECT_NAME_INVALID;
243 num_bad_components++;
251 return NT_STATUS_OBJECT_NAME_INVALID;
255 switch(next_mb_char_size(s)) {
266 DEBUG(0,("check_path_syntax_wcard: character length assumptions invalid !\n"));
268 return NT_STATUS_INVALID_PARAMETER;
271 if (start_of_name_component && num_bad_components) {
272 num_bad_components++;
274 start_of_name_component = False;
277 if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
278 /* For some strange reason being called from findfirst changes
279 the num_components number to cause the error return to change. JRA. */
280 if (num_bad_components > 2) {
281 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
289 /****************************************************************************
290 Check the path for a POSIX client.
291 We're assuming here that '/' is not the second byte in any multibyte char
292 set (a safe assumption).
293 ****************************************************************************/
295 NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname)
298 const char *s = srcname;
299 NTSTATUS ret = NT_STATUS_OK;
300 BOOL start_of_name_component = True;
305 * Safe to assume is not the second part of a mb char as this is handled below.
307 /* Eat multiple '/' or '\\' */
311 if ((d != destname) && (*s != '\0')) {
312 /* We only care about non-leading or trailing '/' */
316 start_of_name_component = True;
320 if (start_of_name_component) {
321 if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
322 /* Uh oh - "/../" or "/..\0" ! */
325 * No mb char starts with '.' so we're safe checking the directory separator here.
328 /* If we just added a '/' - delete it */
329 if ((d > destname) && (*(d-1) == '/')) {
334 /* Are we at the start ? Can't go back further if so. */
336 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
339 /* Go back one level... */
340 /* We know this is safe as '/' cannot be part of a mb sequence. */
341 /* NOTE - if this assumption is invalid we are not in good shape... */
342 /* Decrement d first as d points to the *next* char to write into. */
343 for (d--; d > destname; d--) {
347 s += 2; /* Else go past the .. */
350 } else if ((s[0] == '.') && ((s[1] == '\0') || (s[1] == '/'))) {
360 switch(next_mb_char_size(s)) {
371 DEBUG(0,("check_path_syntax_posix: character length assumptions invalid !\n"));
373 return NT_STATUS_INVALID_PARAMETER;
376 start_of_name_component = False;
383 /****************************************************************************
384 Pull a string and check the path - provide for error return.
385 ****************************************************************************/
387 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err, BOOL allow_wcard_names)
390 char *tmppath_ptr = tmppath;
393 SMB_ASSERT(dest_len == sizeof(pstring));
397 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
399 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
401 if (lp_posix_pathnames()) {
402 *err = check_path_syntax_posix(dest, tmppath);
403 } else if (allow_wcard_names) {
404 *err = check_path_syntax_wcard(dest, tmppath);
406 *err = check_path_syntax(dest, tmppath);
411 /****************************************************************************
412 Reply to a special message.
413 ****************************************************************************/
415 int reply_special(char *inbuf,char *outbuf)
418 int msg_type = CVAL(inbuf,0);
419 int msg_flags = CVAL(inbuf,1);
423 static BOOL already_got_session = False;
427 memset(outbuf,'\0',smb_size);
429 smb_setlen(outbuf,0);
432 case 0x81: /* session request */
434 if (already_got_session) {
435 exit_server("multiple session request not permitted");
438 SCVAL(outbuf,0,0x82);
440 if (name_len(inbuf+4) > 50 ||
441 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
442 DEBUG(0,("Invalid name length in session request\n"));
445 name_extract(inbuf,4,name1);
446 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
447 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
450 set_local_machine_name(name1, True);
451 set_remote_machine_name(name2, True);
453 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
454 get_local_machine_name(), get_remote_machine_name(),
457 if (name_type == 'R') {
458 /* We are being asked for a pathworks session ---
460 SCVAL(outbuf, 0,0x83);
464 /* only add the client's machine name to the list
465 of possibly valid usernames if we are operating
466 in share mode security */
467 if (lp_security() == SEC_SHARE) {
468 add_session_user(get_remote_machine_name());
471 reload_services(True);
474 already_got_session = True;
477 case 0x89: /* session keepalive request
478 (some old clients produce this?) */
479 SCVAL(outbuf,0,SMBkeepalive);
483 case 0x82: /* positive session response */
484 case 0x83: /* negative session response */
485 case 0x84: /* retarget session response */
486 DEBUG(0,("Unexpected session response\n"));
489 case SMBkeepalive: /* session keepalive */
494 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
495 msg_type, msg_flags));
500 /****************************************************************************
502 ****************************************************************************/
504 int reply_tcon(connection_struct *conn,
505 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
512 uint16 vuid = SVAL(inbuf,smb_uid);
516 DATA_BLOB password_blob;
518 START_PROFILE(SMBtcon);
520 *service_buf = *password = *dev = 0;
522 p = smb_buf(inbuf)+1;
523 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
524 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
526 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
528 p = strrchr_m(service_buf,'\\');
532 service = service_buf;
535 password_blob = data_blob(password, pwlen+1);
537 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
539 data_blob_clear_free(&password_blob);
542 END_PROFILE(SMBtcon);
543 return ERROR_NT(nt_status);
546 outsize = set_message(outbuf,2,0,True);
547 SSVAL(outbuf,smb_vwv0,max_recv);
548 SSVAL(outbuf,smb_vwv1,conn->cnum);
549 SSVAL(outbuf,smb_tid,conn->cnum);
551 DEBUG(3,("tcon service=%s cnum=%d\n",
552 service, conn->cnum));
554 END_PROFILE(SMBtcon);
558 /****************************************************************************
559 Reply to a tcon and X.
560 ****************************************************************************/
562 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
567 /* what the cleint thinks the device is */
568 fstring client_devicetype;
569 /* what the server tells the client the share represents */
570 const char *server_devicetype;
572 uint16 vuid = SVAL(inbuf,smb_uid);
573 int passlen = SVAL(inbuf,smb_vwv3);
577 START_PROFILE(SMBtconX);
579 *service = *client_devicetype = 0;
581 /* we might have to close an old one */
582 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
583 close_cnum(conn,vuid);
586 if (passlen > MAX_PASS_LEN) {
587 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
590 if (global_encrypted_passwords_negotiated) {
591 password = data_blob(smb_buf(inbuf),passlen);
593 password = data_blob(smb_buf(inbuf),passlen+1);
594 /* Ensure correct termination */
595 password.data[passlen]=0;
598 p = smb_buf(inbuf) + passlen;
599 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
602 * the service name can be either: \\server\share
603 * or share directly like on the DELL PowerVault 705
606 q = strchr_m(path+2,'\\');
608 END_PROFILE(SMBtconX);
609 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
611 fstrcpy(service,q+1);
614 fstrcpy(service,path);
616 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
618 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
620 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
622 data_blob_clear_free(&password);
625 END_PROFILE(SMBtconX);
626 return ERROR_NT(nt_status);
630 server_devicetype = "IPC";
631 else if ( IS_PRINT(conn) )
632 server_devicetype = "LPT1:";
634 server_devicetype = "A:";
636 if (Protocol < PROTOCOL_NT1) {
637 set_message(outbuf,2,0,True);
639 p += srvstr_push(outbuf, p, server_devicetype, -1,
640 STR_TERMINATE|STR_ASCII);
641 set_message_end(outbuf,p);
643 /* NT sets the fstype of IPC$ to the null string */
644 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
646 set_message(outbuf,3,0,True);
649 p += srvstr_push(outbuf, p, server_devicetype, -1,
650 STR_TERMINATE|STR_ASCII);
651 p += srvstr_push(outbuf, p, fstype, -1,
654 set_message_end(outbuf,p);
656 /* what does setting this bit do? It is set by NT4 and
657 may affect the ability to autorun mounted cdroms */
658 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
659 (lp_csc_policy(SNUM(conn)) << 2));
661 init_dfsroot(conn, inbuf, outbuf);
665 DEBUG(3,("tconX service=%s \n",
668 /* set the incoming and outgoing tid to the just created one */
669 SSVAL(inbuf,smb_tid,conn->cnum);
670 SSVAL(outbuf,smb_tid,conn->cnum);
672 END_PROFILE(SMBtconX);
673 return chain_reply(inbuf,outbuf,length,bufsize);
676 /****************************************************************************
677 Reply to an unknown type.
678 ****************************************************************************/
680 int reply_unknown(char *inbuf,char *outbuf)
683 type = CVAL(inbuf,smb_com);
685 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
686 smb_fn_name(type), type, type));
688 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
691 /****************************************************************************
693 ****************************************************************************/
695 int reply_ioctl(connection_struct *conn,
696 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
698 uint16 device = SVAL(inbuf,smb_vwv1);
699 uint16 function = SVAL(inbuf,smb_vwv2);
700 uint32 ioctl_code = (device << 16) + function;
701 int replysize, outsize;
703 START_PROFILE(SMBioctl);
705 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
707 switch (ioctl_code) {
708 case IOCTL_QUERY_JOB_INFO:
712 END_PROFILE(SMBioctl);
713 return(ERROR_DOS(ERRSRV,ERRnosupport));
716 outsize = set_message(outbuf,8,replysize+1,True);
717 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
718 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
719 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
720 p = smb_buf(outbuf) + 1; /* Allow for alignment */
722 switch (ioctl_code) {
723 case IOCTL_QUERY_JOB_INFO:
725 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
727 END_PROFILE(SMBioctl);
728 return(UNIXERROR(ERRDOS,ERRbadfid));
730 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
731 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
733 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
739 END_PROFILE(SMBioctl);
743 /****************************************************************************
745 ****************************************************************************/
747 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
752 BOOL bad_path = False;
753 SMB_STRUCT_STAT sbuf;
756 START_PROFILE(SMBchkpth);
758 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, False);
759 if (!NT_STATUS_IS_OK(status)) {
760 END_PROFILE(SMBchkpth);
761 return ERROR_NT(status);
764 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
766 unix_convert(name,conn,0,&bad_path,&sbuf);
768 END_PROFILE(SMBchkpth);
769 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
772 if (check_name(name,conn)) {
773 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
774 if (!(ok = S_ISDIR(sbuf.st_mode))) {
775 END_PROFILE(SMBchkpth);
776 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
781 /* We special case this - as when a Windows machine
782 is parsing a path is steps through the components
783 one at a time - if a component fails it expects
784 ERRbadpath, not ERRbadfile.
786 if(errno == ENOENT) {
788 * Windows returns different error codes if
789 * the parent directory is valid but not the
790 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
791 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
792 * if the path is invalid. This is different from set_bad_path_error()
793 * in the non-NT error case.
795 END_PROFILE(SMBchkpth);
796 return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
799 END_PROFILE(SMBchkpth);
800 return(UNIXERROR(ERRDOS,ERRbadpath));
803 outsize = set_message(outbuf,0,0,True);
804 DEBUG(3,("chkpth %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
806 END_PROFILE(SMBchkpth);
810 /****************************************************************************
812 ****************************************************************************/
814 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
818 SMB_STRUCT_STAT sbuf;
823 BOOL bad_path = False;
827 START_PROFILE(SMBgetatr);
829 p = smb_buf(inbuf) + 1;
830 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
831 if (!NT_STATUS_IS_OK(status)) {
832 END_PROFILE(SMBgetatr);
833 return ERROR_NT(status);
836 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
838 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
839 under WfWg - weird! */
841 mode = aHIDDEN | aDIR;
842 if (!CAN_WRITE(conn))
848 unix_convert(fname,conn,0,&bad_path,&sbuf);
850 END_PROFILE(SMBgetatr);
851 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
853 if (check_name(fname,conn)) {
854 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
855 mode = dos_mode(conn,fname,&sbuf);
857 mtime = sbuf.st_mtime;
862 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
868 END_PROFILE(SMBgetatr);
869 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
872 outsize = set_message(outbuf,10,0,True);
874 SSVAL(outbuf,smb_vwv0,mode);
875 if(lp_dos_filetime_resolution(SNUM(conn)) )
876 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
878 put_dos_date3(outbuf,smb_vwv1,mtime);
879 SIVAL(outbuf,smb_vwv3,(uint32)size);
881 if (Protocol >= PROTOCOL_NT1)
882 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
884 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
886 END_PROFILE(SMBgetatr);
890 /****************************************************************************
892 ****************************************************************************/
894 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
901 SMB_STRUCT_STAT sbuf;
902 BOOL bad_path = False;
906 START_PROFILE(SMBsetatr);
908 p = smb_buf(inbuf) + 1;
909 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
910 if (!NT_STATUS_IS_OK(status)) {
911 END_PROFILE(SMBsetatr);
912 return ERROR_NT(status);
915 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
917 unix_convert(fname,conn,0,&bad_path,&sbuf);
919 END_PROFILE(SMBsetatr);
920 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
923 mode = SVAL(inbuf,smb_vwv0);
924 mtime = make_unix_date3(inbuf+smb_vwv1);
926 if (mode != FILE_ATTRIBUTE_NORMAL) {
927 if (VALID_STAT_OF_DIR(sbuf))
932 if (check_name(fname,conn)) {
933 ok = (file_set_dosmode(conn,fname,mode,&sbuf,False) == 0);
940 ok = set_filetime(conn,fname,mtime);
943 END_PROFILE(SMBsetatr);
944 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
947 outsize = set_message(outbuf,0,0,True);
949 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
951 END_PROFILE(SMBsetatr);
955 /****************************************************************************
957 ****************************************************************************/
959 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
962 SMB_BIG_UINT dfree,dsize,bsize;
963 START_PROFILE(SMBdskattr);
965 if (SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
966 END_PROFILE(SMBdskattr);
967 return(UNIXERROR(ERRHRD,ERRgeneral));
970 outsize = set_message(outbuf,5,0,True);
972 if (Protocol <= PROTOCOL_LANMAN2) {
973 double total_space, free_space;
974 /* we need to scale this to a number that DOS6 can handle. We
975 use floating point so we can handle large drives on systems
976 that don't have 64 bit integers
978 we end up displaying a maximum of 2G to DOS systems
980 total_space = dsize * (double)bsize;
981 free_space = dfree * (double)bsize;
983 dsize = (total_space+63*512) / (64*512);
984 dfree = (free_space+63*512) / (64*512);
986 if (dsize > 0xFFFF) dsize = 0xFFFF;
987 if (dfree > 0xFFFF) dfree = 0xFFFF;
989 SSVAL(outbuf,smb_vwv0,dsize);
990 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
991 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
992 SSVAL(outbuf,smb_vwv3,dfree);
994 SSVAL(outbuf,smb_vwv0,dsize);
995 SSVAL(outbuf,smb_vwv1,bsize/512);
996 SSVAL(outbuf,smb_vwv2,512);
997 SSVAL(outbuf,smb_vwv3,dfree);
1000 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1002 END_PROFILE(SMBdskattr);
1006 /****************************************************************************
1008 Can be called from SMBsearch, SMBffirst or SMBfunique.
1009 ****************************************************************************/
1011 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1021 unsigned int numentries = 0;
1022 unsigned int maxentries = 0;
1023 BOOL finished = False;
1030 BOOL check_descend = False;
1031 BOOL expect_close = False;
1032 BOOL can_open = True;
1033 BOOL bad_path = False;
1035 BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1037 if (lp_posix_pathnames()) {
1038 return reply_unknown(inbuf, outbuf);
1041 START_PROFILE(SMBsearch);
1043 *mask = *directory = *fname = 0;
1045 /* If we were called as SMBffirst then we must expect close. */
1046 if(CVAL(inbuf,smb_com) == SMBffirst)
1047 expect_close = True;
1049 outsize = set_message(outbuf,1,3,True);
1050 maxentries = SVAL(inbuf,smb_vwv0);
1051 dirtype = SVAL(inbuf,smb_vwv1);
1052 p = smb_buf(inbuf) + 1;
1053 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, True);
1054 if (!NT_STATUS_IS_OK(nt_status)) {
1055 END_PROFILE(SMBsearch);
1056 return ERROR_NT(nt_status);
1059 RESOLVE_DFSPATH_WCARD(path, conn, inbuf, outbuf);
1062 status_len = SVAL(p, 0);
1065 /* dirtype &= ~aDIR; */
1067 if (status_len == 0) {
1068 SMB_STRUCT_STAT sbuf;
1071 pstrcpy(directory,path);
1073 unix_convert(directory,conn,0,&bad_path,&sbuf);
1076 if (!check_name(directory,conn))
1079 p = strrchr_m(dir2,'/');
1088 p = strrchr_m(directory,'/');
1094 if (strlen(directory) == 0)
1095 pstrcpy(directory,".");
1096 memset((char *)status,'\0',21);
1097 SCVAL(status,0,(dirtype & 0x1F));
1101 memcpy(status,p,21);
1102 status_dirtype = CVAL(status,0) & 0x1F;
1103 if (status_dirtype != (dirtype & 0x1F))
1104 dirtype = status_dirtype;
1106 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1109 string_set(&conn->dirpath,dptr_path(dptr_num));
1110 pstrcpy(mask, dptr_wcard(dptr_num));
1114 p = smb_buf(outbuf) + 3;
1117 if (status_len == 0) {
1118 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid), mask, dirtype);
1120 if(dptr_num == -2) {
1121 END_PROFILE(SMBsearch);
1122 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
1124 END_PROFILE(SMBsearch);
1125 return ERROR_DOS(ERRDOS,ERRnofids);
1128 dirtype = dptr_attr(dptr_num);
1131 DEBUG(4,("dptr_num is %d\n",dptr_num));
1134 if ((dirtype&0x1F) == aVOLID) {
1135 memcpy(p,status,21);
1136 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
1137 0,aVOLID,0,!allow_long_path_components);
1138 dptr_fill(p+12,dptr_num);
1139 if (dptr_zero(p+12) && (status_len==0))
1143 p += DIR_STRUCT_SIZE;
1146 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
1148 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1149 conn->dirpath,lp_dontdescend(SNUM(conn))));
1150 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1151 check_descend = True;
1153 for (i=numentries;(i<maxentries) && !finished;i++) {
1154 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1156 memcpy(p,status,21);
1157 make_dir_struct(p,mask,fname,size, mode,date,
1158 !allow_long_path_components);
1159 dptr_fill(p+12,dptr_num);
1161 p += DIR_STRUCT_SIZE;
1171 /* If we were called as SMBffirst with smb_search_id == NULL
1172 and no entries were found then return error and close dirptr
1175 if (numentries == 0 || !ok) {
1176 dptr_close(&dptr_num);
1177 } else if(ok && expect_close && status_len == 0) {
1178 /* Close the dptr - we know it's gone */
1179 dptr_close(&dptr_num);
1182 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1183 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1184 dptr_close(&dptr_num);
1187 if ((numentries == 0) && !ms_has_wild(mask)) {
1188 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1191 SSVAL(outbuf,smb_vwv0,numentries);
1192 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1193 SCVAL(smb_buf(outbuf),0,5);
1194 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1196 /* The replies here are never long name. */
1197 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1198 if (!allow_long_path_components) {
1199 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
1202 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1203 SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1205 outsize += DIR_STRUCT_SIZE*numentries;
1206 smb_setlen(outbuf,outsize - 4);
1208 if ((! *directory) && dptr_path(dptr_num))
1209 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1211 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1212 smb_fn_name(CVAL(inbuf,smb_com)),
1213 mask, directory, dirtype, numentries, maxentries ) );
1215 END_PROFILE(SMBsearch);
1219 /****************************************************************************
1220 Reply to a fclose (stop directory search).
1221 ****************************************************************************/
1223 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1233 if (lp_posix_pathnames()) {
1234 return reply_unknown(inbuf, outbuf);
1237 START_PROFILE(SMBfclose);
1239 outsize = set_message(outbuf,1,0,True);
1240 p = smb_buf(inbuf) + 1;
1241 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, True);
1242 if (!NT_STATUS_IS_OK(err)) {
1243 END_PROFILE(SMBfclose);
1244 return ERROR_NT(err);
1247 status_len = SVAL(p,0);
1250 if (status_len == 0) {
1251 END_PROFILE(SMBfclose);
1252 return ERROR_DOS(ERRSRV,ERRsrverror);
1255 memcpy(status,p,21);
1257 if(dptr_fetch(status+12,&dptr_num)) {
1258 /* Close the dptr - we know it's gone */
1259 dptr_close(&dptr_num);
1262 SSVAL(outbuf,smb_vwv0,0);
1264 DEBUG(3,("search close\n"));
1266 END_PROFILE(SMBfclose);
1270 /****************************************************************************
1272 ****************************************************************************/
1274 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1283 SMB_STRUCT_STAT sbuf;
1284 BOOL bad_path = False;
1286 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1287 uint16 dos_attr = SVAL(inbuf,smb_vwv1);
1289 START_PROFILE(SMBopen);
1291 share_mode = SVAL(inbuf,smb_vwv0);
1293 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1294 if (!NT_STATUS_IS_OK(status)) {
1295 END_PROFILE(SMBopen);
1296 return ERROR_NT(status);
1299 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1301 unix_convert(fname,conn,0,&bad_path,&sbuf);
1303 END_PROFILE(SMBopen);
1304 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1307 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1308 (uint32)dos_attr, oplock_request,&rmode,NULL);
1311 END_PROFILE(SMBopen);
1312 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1313 /* We have re-scheduled this call. */
1316 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1319 size = sbuf.st_size;
1320 fmode = dos_mode(conn,fname,&sbuf);
1321 mtime = sbuf.st_mtime;
1324 DEBUG(3,("attempt to open a directory %s\n",fname));
1325 close_file(fsp,False);
1326 END_PROFILE(SMBopen);
1327 return ERROR_DOS(ERRDOS,ERRnoaccess);
1330 outsize = set_message(outbuf,7,0,True);
1331 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1332 SSVAL(outbuf,smb_vwv1,fmode);
1333 if(lp_dos_filetime_resolution(SNUM(conn)) )
1334 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1336 put_dos_date3(outbuf,smb_vwv2,mtime);
1337 SIVAL(outbuf,smb_vwv4,(uint32)size);
1338 SSVAL(outbuf,smb_vwv6,rmode);
1340 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1341 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1343 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1344 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1345 END_PROFILE(SMBopen);
1349 /****************************************************************************
1350 Reply to an open and X.
1351 ****************************************************************************/
1353 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1356 int smb_mode = SVAL(inbuf,smb_vwv3);
1357 int smb_attr = SVAL(inbuf,smb_vwv5);
1358 /* Breakout the oplock request bits so we can set the
1359 reply bits separately. */
1360 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1361 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1362 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1364 int open_flags = SVAL(inbuf,smb_vwv2);
1365 int smb_sattr = SVAL(inbuf,smb_vwv4);
1366 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1368 int smb_ofun = SVAL(inbuf,smb_vwv8);
1370 int fmode=0,mtime=0,rmode=0;
1371 SMB_STRUCT_STAT sbuf;
1373 BOOL bad_path = False;
1376 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
1377 ssize_t retval = -1;
1379 START_PROFILE(SMBopenX);
1381 /* If it's an IPC, pass off the pipe handler. */
1383 if (lp_nt_pipe_support()) {
1384 END_PROFILE(SMBopenX);
1385 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1387 END_PROFILE(SMBopenX);
1388 return ERROR_DOS(ERRSRV,ERRaccess);
1392 /* XXXX we need to handle passed times, sattr and flags */
1393 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status, False);
1394 if (!NT_STATUS_IS_OK(status)) {
1395 END_PROFILE(SMBopenX);
1396 return ERROR_NT(status);
1399 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1401 unix_convert(fname,conn,0,&bad_path,&sbuf);
1403 END_PROFILE(SMBopenX);
1404 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1407 /* Strange open mode mapping. */
1408 if (smb_ofun == 0) {
1409 if (GET_OPEN_MODE(smb_mode) == DOS_OPEN_EXEC) {
1410 smb_ofun = FILE_EXISTS_FAIL | FILE_CREATE_IF_NOT_EXIST;
1412 END_PROFILE(SMBopenX);
1413 return ERROR_FORCE_DOS(ERRDOS, ERRbadaccess);
1417 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr,
1418 oplock_request, &rmode,&smb_action);
1421 END_PROFILE(SMBopenX);
1422 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1423 /* We have re-scheduled this call. */
1426 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1429 size = sbuf.st_size;
1431 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1432 if the file is truncated or created. */
1433 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1434 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1435 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1436 close_file(fsp,False);
1437 END_PROFILE(SMBntcreateX);
1438 return ERROR_NT(NT_STATUS_DISK_FULL);
1440 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1442 close_file(fsp,False);
1443 END_PROFILE(SMBwrite);
1444 return ERROR_NT(NT_STATUS_DISK_FULL);
1446 size = get_allocation_size(conn,fsp,&sbuf);
1449 fmode = dos_mode(conn,fname,&sbuf);
1450 mtime = sbuf.st_mtime;
1452 close_file(fsp,False);
1453 END_PROFILE(SMBopenX);
1454 return ERROR_DOS(ERRDOS,ERRnoaccess);
1457 /* If the caller set the extended oplock request bit
1458 and we granted one (by whatever means) - set the
1459 correct bit for extended oplock reply.
1462 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1463 smb_action |= EXTENDED_OPLOCK_GRANTED;
1465 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1466 smb_action |= EXTENDED_OPLOCK_GRANTED;
1468 /* If the caller set the core oplock request bit
1469 and we granted one (by whatever means) - set the
1470 correct bit for core oplock reply.
1473 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1474 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1476 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1477 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1479 set_message(outbuf,15,0,True);
1480 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1481 SSVAL(outbuf,smb_vwv3,fmode);
1482 if(lp_dos_filetime_resolution(SNUM(conn)) )
1483 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1485 put_dos_date3(outbuf,smb_vwv4,mtime);
1486 SIVAL(outbuf,smb_vwv6,(uint32)size);
1487 SSVAL(outbuf,smb_vwv8,rmode);
1488 SSVAL(outbuf,smb_vwv11,smb_action);
1490 END_PROFILE(SMBopenX);
1491 return chain_reply(inbuf,outbuf,length,bufsize);
1494 /****************************************************************************
1495 Reply to a SMBulogoffX.
1496 ****************************************************************************/
1498 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1500 uint16 vuid = SVAL(inbuf,smb_uid);
1501 user_struct *vuser = get_valid_user_struct(vuid);
1502 START_PROFILE(SMBulogoffX);
1505 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1507 /* in user level security we are supposed to close any files
1508 open by this user */
1509 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1510 file_close_user(vuid);
1512 invalidate_vuid(vuid);
1514 set_message(outbuf,2,0,True);
1516 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1518 END_PROFILE(SMBulogoffX);
1519 return chain_reply(inbuf,outbuf,length,bufsize);
1522 /****************************************************************************
1523 Reply to a mknew or a create.
1524 ****************************************************************************/
1526 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1533 BOOL bad_path = False;
1535 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1536 SMB_STRUCT_STAT sbuf;
1538 START_PROFILE(SMBcreate);
1540 com = SVAL(inbuf,smb_com);
1542 createmode = SVAL(inbuf,smb_vwv0);
1543 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1544 if (!NT_STATUS_IS_OK(status)) {
1545 END_PROFILE(SMBcreate);
1546 return ERROR_NT(status);
1549 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1551 unix_convert(fname,conn,0,&bad_path,&sbuf);
1553 END_PROFILE(SMBcreate);
1554 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1557 if (createmode & aVOLID)
1558 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1560 if(com == SMBmknew) {
1561 /* We should fail if file exists. */
1562 ofun = FILE_CREATE_IF_NOT_EXIST;
1564 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1565 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1568 /* Open file in dos compatibility share mode. */
1569 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1570 ofun, (uint32)createmode, oplock_request, NULL, NULL);
1573 END_PROFILE(SMBcreate);
1574 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1575 /* We have re-scheduled this call. */
1578 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1581 outsize = set_message(outbuf,1,0,True);
1582 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1584 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1585 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1587 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1588 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1590 DEBUG( 2, ( "new file %s\n", fname ) );
1591 DEBUG( 3, ( "mknew %s fd=%d dmode=%d\n", fname, fsp->fd, createmode ) );
1593 END_PROFILE(SMBcreate);
1597 /****************************************************************************
1598 Reply to a create temporary file.
1599 ****************************************************************************/
1601 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1606 BOOL bad_path = False;
1608 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1610 SMB_STRUCT_STAT sbuf;
1613 unsigned int namelen;
1615 START_PROFILE(SMBctemp);
1617 createattr = SVAL(inbuf,smb_vwv0);
1618 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1619 if (!NT_STATUS_IS_OK(status)) {
1620 END_PROFILE(SMBctemp);
1621 return ERROR_NT(status);
1624 pstrcat(fname,"/TMXXXXXX");
1626 pstrcat(fname,"TMXXXXXX");
1629 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1631 unix_convert(fname,conn,0,&bad_path,&sbuf);
1633 END_PROFILE(SMBctemp);
1634 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1637 tmpfd = smb_mkstemp(fname);
1639 END_PROFILE(SMBctemp);
1640 return(UNIXERROR(ERRDOS,ERRnoaccess));
1643 SMB_VFS_STAT(conn,fname,&sbuf);
1645 /* Open file in dos compatibility share mode. */
1646 /* We should fail if file does not exist. */
1647 fsp = open_file_shared(conn,fname,&sbuf,
1648 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1649 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1650 (uint32)createattr, oplock_request, NULL, NULL);
1652 /* close fd from smb_mkstemp() */
1656 END_PROFILE(SMBctemp);
1657 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1658 /* We have re-scheduled this call. */
1661 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1664 outsize = set_message(outbuf,1,0,True);
1665 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1667 /* the returned filename is relative to the directory */
1668 s = strrchr_m(fname, '/');
1674 p = smb_buf(outbuf);
1676 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1677 thing in the byte section. JRA */
1678 SSVALS(p, 0, -1); /* what is this? not in spec */
1680 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1682 outsize = set_message_end(outbuf, p);
1684 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1685 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1687 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1688 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1690 DEBUG( 2, ( "created temp file %s\n", fname ) );
1691 DEBUG( 3, ( "ctemp %s fd=%d umode=%o\n",
1692 fname, fsp->fd, sbuf.st_mode ) );
1694 END_PROFILE(SMBctemp);
1698 /*******************************************************************
1699 Check if a user is allowed to rename a file.
1700 ********************************************************************/
1702 static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
1709 if (!CAN_WRITE(conn))
1710 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1712 fmode = dos_mode(conn,fname,pst);
1713 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1714 return NT_STATUS_NO_SUCH_FILE;
1716 if (S_ISDIR(pst->st_mode))
1717 return NT_STATUS_OK;
1719 /* We need a better way to return NT status codes from open... */
1720 set_saved_error_triple(0, 0, NT_STATUS_OK);
1722 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1723 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1727 if (get_saved_error_triple(NULL, NULL, &ret)) {
1728 set_saved_error_triple(0, 0, NT_STATUS_OK);
1731 set_saved_error_triple(0, 0, NT_STATUS_OK);
1732 return NT_STATUS_ACCESS_DENIED;
1734 close_file(fsp,False);
1735 return NT_STATUS_OK;
1738 /*******************************************************************
1739 Check if a user is allowed to delete a file.
1740 ********************************************************************/
1742 NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL bad_path, BOOL check_is_at_open)
1744 SMB_STRUCT_STAT sbuf;
1750 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1753 if (!CAN_WRITE(conn))
1754 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1756 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1757 if(errno == ENOENT) {
1759 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1761 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1763 return map_nt_error_from_unix(errno);
1766 fmode = dos_mode(conn,fname,&sbuf);
1768 /* Can't delete a directory. */
1770 return NT_STATUS_FILE_IS_A_DIRECTORY;
1772 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1773 return NT_STATUS_OBJECT_NAME_INVALID;
1774 #endif /* JRATEST */
1776 if (!lp_delete_readonly(SNUM(conn))) {
1778 return NT_STATUS_CANNOT_DELETE;
1780 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1781 return NT_STATUS_NO_SUCH_FILE;
1783 if (check_is_at_open) {
1784 if (!can_delete_file_in_directory(conn, fname)) {
1785 return NT_STATUS_ACCESS_DENIED;
1788 /* On open checks the open itself will check the share mode, so
1789 don't do it here as we'll get it wrong. */
1791 /* We need a better way to return NT status codes from open... */
1792 set_saved_error_triple(0, 0, NT_STATUS_OK);
1794 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1795 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1799 if (get_saved_error_triple(NULL, NULL, &ret)) {
1800 set_saved_error_triple(0, 0, NT_STATUS_OK);
1803 set_saved_error_triple(0, 0, NT_STATUS_OK);
1804 return NT_STATUS_ACCESS_DENIED;
1806 close_file(fsp,False);
1808 return NT_STATUS_OK;
1811 /****************************************************************************
1812 The guts of the unlink command, split out so it may be called by the NT SMB
1814 ****************************************************************************/
1816 NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name)
1822 NTSTATUS error = NT_STATUS_OK;
1824 BOOL bad_path = False;
1826 SMB_STRUCT_STAT sbuf;
1828 *directory = *mask = 0;
1830 /* We must check for wildcards in the name given
1831 * directly by the client - before any unmangling.
1832 * This prevents an unmangling of a UNIX name containing
1833 * a DOS wildcard like '*' or '?' from unmangling into
1834 * a wildcard delete which was not intended.
1835 * FIX for #226. JRA.
1838 has_wild = ms_has_wild(name);
1840 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1842 p = strrchr_m(name,'/');
1844 pstrcpy(directory,".");
1848 pstrcpy(directory,name);
1853 * We should only check the mangled cache
1854 * here if unix_convert failed. This means
1855 * that the path in 'mask' doesn't exist
1856 * on the file system and so we need to look
1857 * for a possible mangle. This patch from
1858 * Tine Smukavec <valentin.smukavec@hermes.si>.
1861 if (!rc && mangle_is_mangled(mask,SNUM(conn)))
1862 mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
1865 pstrcat(directory,"/");
1866 pstrcat(directory,mask);
1867 error = can_delete(conn,directory,dirtype,bad_path,False);
1868 if (!NT_STATUS_IS_OK(error))
1871 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1875 struct smb_Dir *dir_hnd = NULL;
1878 if (strequal(mask,"????????.???"))
1881 if (check_name(directory,conn))
1882 dir_hnd = OpenDir(conn, directory, mask, dirtype);
1884 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1885 the pattern matches against the long name, otherwise the short name
1886 We don't implement this yet XXXX
1891 error = NT_STATUS_NO_SUCH_FILE;
1893 while ((dname = ReadDirName(dir_hnd, &offset))) {
1896 BOOL sys_direntry = False;
1897 pstrcpy(fname,dname);
1899 if (!is_visible_file(conn, directory, dname, &st, True)) {
1903 /* Quick check for "." and ".." */
1904 if (fname[0] == '.') {
1905 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1906 if ((dirtype & FILE_ATTRIBUTE_DIRECTORY) && (dirtype & FILE_ATTRIBUTE_SYSTEM)) {
1907 sys_direntry = True;
1914 if(!mask_match(fname, mask, conn->case_sensitive))
1918 error = NT_STATUS_OBJECT_NAME_INVALID;
1919 DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n",
1924 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1925 error = can_delete(conn,fname,dirtype,bad_path,False);
1926 if (!NT_STATUS_IS_OK(error)) {
1929 if (SMB_VFS_UNLINK(conn,fname) == 0)
1931 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1937 if (count == 0 && NT_STATUS_IS_OK(error)) {
1938 error = map_nt_error_from_unix(errno);
1944 /****************************************************************************
1946 ****************************************************************************/
1948 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1955 START_PROFILE(SMBunlink);
1957 dirtype = SVAL(inbuf,smb_vwv0);
1959 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, True);
1960 if (!NT_STATUS_IS_OK(status)) {
1961 END_PROFILE(SMBunlink);
1962 return ERROR_NT(status);
1965 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
1967 DEBUG(3,("reply_unlink : %s\n",name));
1969 status = unlink_internals(conn, dirtype, name);
1970 if (!NT_STATUS_IS_OK(status)) {
1971 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1972 /* We have re-scheduled this call. */
1975 return ERROR_NT(status);
1979 * Win2k needs a changenotify request response before it will
1980 * update after a rename..
1982 process_pending_change_notify_queue((time_t)0);
1984 outsize = set_message(outbuf,0,0,True);
1986 END_PROFILE(SMBunlink);
1990 /****************************************************************************
1992 ****************************************************************************/
1994 static void fail_readraw(void)
1997 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1999 exit_server(errstr);
2002 #if defined(WITH_SENDFILE)
2003 /****************************************************************************
2004 Fake (read/write) sendfile. Returns -1 on read or write fail.
2005 ****************************************************************************/
2007 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
2011 /* Paranioa check... */
2012 if (nread > bufsize) {
2017 ret = read_file(fsp,buf,startpos,nread);
2023 /* If we had a short read, fill with zeros. */
2025 memset(buf, '\0', nread - ret);
2028 if (write_data(smbd_server_fd(),buf,nread) != nread) {
2032 return (ssize_t)nread;
2036 /****************************************************************************
2037 Use sendfile in readbraw.
2038 ****************************************************************************/
2040 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
2041 ssize_t mincount, char *outbuf, int out_buffsize)
2045 #if defined(WITH_SENDFILE)
2047 * We can only use sendfile on a non-chained packet
2048 * but we can use on a non-oplocked file. tridge proved this
2049 * on a train in Germany :-). JRA.
2050 * reply_readbraw has already checked the length.
2053 if (chain_size ==0 && (nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) && lp_use_sendfile(SNUM(conn)) ) {
2056 _smb_setlen(outbuf,nread);
2057 header.data = outbuf;
2061 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
2062 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2063 if (errno == ENOSYS) {
2064 goto normal_readbraw;
2068 * Special hack for broken Linux with no working sendfile. If we
2069 * return EINTR we sent the header but not the rest of the data.
2070 * Fake this up by doing read/write calls.
2072 if (errno == EINTR) {
2073 /* Ensure we don't do this again. */
2074 set_use_sendfile(SNUM(conn), False);
2075 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2077 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
2078 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2079 fsp->fsp_name, strerror(errno) ));
2080 exit_server("send_file_readbraw fake_sendfile failed");
2085 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2086 fsp->fsp_name, strerror(errno) ));
2087 exit_server("send_file_readbraw sendfile failed");
2097 ret = read_file(fsp,outbuf+4,startpos,nread);
2098 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2107 _smb_setlen(outbuf,ret);
2108 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2112 /****************************************************************************
2113 Reply to a readbraw (core+ protocol).
2114 ****************************************************************************/
2116 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2118 ssize_t maxcount,mincount;
2121 char *header = outbuf;
2123 START_PROFILE(SMBreadbraw);
2125 if (srv_is_signing_active()) {
2126 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2130 * Special check if an oplock break has been issued
2131 * and the readraw request croses on the wire, we must
2132 * return a zero length response here.
2135 if(global_oplock_break) {
2136 _smb_setlen(header,0);
2137 if (write_data(smbd_server_fd(),header,4) != 4)
2139 DEBUG(5,("readbraw - oplock break finished\n"));
2140 END_PROFILE(SMBreadbraw);
2144 fsp = file_fsp(inbuf,smb_vwv0);
2146 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2148 * fsp could be NULL here so use the value from the packet. JRA.
2150 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2151 _smb_setlen(header,0);
2152 if (write_data(smbd_server_fd(),header,4) != 4)
2154 END_PROFILE(SMBreadbraw);
2158 CHECK_FSP(fsp,conn);
2160 flush_write_cache(fsp, READRAW_FLUSH);
2162 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2163 if(CVAL(inbuf,smb_wct) == 10) {
2165 * This is a large offset (64 bit) read.
2167 #ifdef LARGE_SMB_OFF_T
2169 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2171 #else /* !LARGE_SMB_OFF_T */
2174 * Ensure we haven't been sent a >32 bit offset.
2177 if(IVAL(inbuf,smb_vwv8) != 0) {
2178 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2179 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2180 _smb_setlen(header,0);
2181 if (write_data(smbd_server_fd(),header,4) != 4)
2183 END_PROFILE(SMBreadbraw);
2187 #endif /* LARGE_SMB_OFF_T */
2190 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2191 _smb_setlen(header,0);
2192 if (write_data(smbd_server_fd(),header,4) != 4)
2194 END_PROFILE(SMBreadbraw);
2198 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2199 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2201 /* ensure we don't overrun the packet size */
2202 maxcount = MIN(65535,maxcount);
2204 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2208 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0) {
2212 if (startpos >= size) {
2215 nread = MIN(maxcount,(size - startpos));
2219 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2220 if (nread < mincount)
2224 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
2225 (int)maxcount, (int)mincount, (int)nread ) );
2227 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2229 DEBUG(5,("readbraw finished\n"));
2230 END_PROFILE(SMBreadbraw);
2235 #define DBGC_CLASS DBGC_LOCKING
2237 /****************************************************************************
2238 Reply to a lockread (core+ protocol).
2239 ****************************************************************************/
2241 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2249 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2250 BOOL my_lock_ctx = False;
2251 START_PROFILE(SMBlockread);
2253 CHECK_FSP(fsp,conn);
2256 release_level_2_oplocks_on_change(fsp);
2258 numtoread = SVAL(inbuf,smb_vwv1);
2259 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2261 outsize = set_message(outbuf,5,3,True);
2262 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2263 data = smb_buf(outbuf) + 3;
2266 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2267 * protocol request that predates the read/write lock concept.
2268 * Thus instead of asking for a read lock here we need to ask
2269 * for a write lock. JRA.
2270 * Note that the requested lock size is unaffected by max_recv.
2273 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
2274 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
2276 if (NT_STATUS_V(status)) {
2279 * We used to make lockread a blocking lock. It turns out
2280 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
2284 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2286 * A blocking lock was requested. Package up
2287 * this smb into a queued request and push it
2288 * onto the blocking lock queue.
2290 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
2291 (SMB_BIG_UINT)numtoread)) {
2292 END_PROFILE(SMBlockread);
2297 END_PROFILE(SMBlockread);
2298 return ERROR_NT(status);
2302 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2305 if (numtoread > max_recv) {
2306 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2307 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2308 (unsigned int)numtoread, (unsigned int)max_recv ));
2309 numtoread = MIN(numtoread,max_recv);
2311 nread = read_file(fsp,data,startpos,numtoread);
2314 END_PROFILE(SMBlockread);
2315 return(UNIXERROR(ERRDOS,ERRnoaccess));
2319 SSVAL(outbuf,smb_vwv0,nread);
2320 SSVAL(outbuf,smb_vwv5,nread+3);
2321 SSVAL(smb_buf(outbuf),1,nread);
2323 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2324 fsp->fnum, (int)numtoread, (int)nread));
2326 END_PROFILE(SMBlockread);
2331 #define DBGC_CLASS DBGC_ALL
2333 /****************************************************************************
2335 ****************************************************************************/
2337 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2344 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2345 START_PROFILE(SMBread);
2347 CHECK_FSP(fsp,conn);
2350 numtoread = SVAL(inbuf,smb_vwv1);
2351 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2353 outsize = set_message(outbuf,5,3,True);
2354 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2356 * The requested read size cannot be greater than max_recv. JRA.
2358 if (numtoread > max_recv) {
2359 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2360 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2361 (unsigned int)numtoread, (unsigned int)max_recv ));
2362 numtoread = MIN(numtoread,max_recv);
2365 data = smb_buf(outbuf) + 3;
2367 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2368 END_PROFILE(SMBread);
2369 return ERROR_DOS(ERRDOS,ERRlock);
2373 nread = read_file(fsp,data,startpos,numtoread);
2376 END_PROFILE(SMBread);
2377 return(UNIXERROR(ERRDOS,ERRnoaccess));
2381 SSVAL(outbuf,smb_vwv0,nread);
2382 SSVAL(outbuf,smb_vwv5,nread+3);
2383 SCVAL(smb_buf(outbuf),0,1);
2384 SSVAL(smb_buf(outbuf),1,nread);
2386 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2387 fsp->fnum, (int)numtoread, (int)nread ) );
2389 END_PROFILE(SMBread);
2393 /****************************************************************************
2394 Reply to a read and X - possibly using sendfile.
2395 ****************************************************************************/
2397 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2398 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2402 char *data = smb_buf(outbuf);
2404 #if defined(WITH_SENDFILE)
2406 * We can only use sendfile on a non-chained packet
2407 * but we can use on a non-oplocked file. tridge proved this
2408 * on a train in Germany :-). JRA.
2411 if (chain_size ==0 && (CVAL(inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) &&
2412 (lp_write_cache_size(SNUM(conn)) == 0) ) {
2413 SMB_STRUCT_STAT sbuf;
2416 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
2417 return(UNIXERROR(ERRDOS,ERRnoaccess));
2419 if (startpos > sbuf.st_size)
2422 if (smb_maxcnt > (sbuf.st_size - startpos))
2423 smb_maxcnt = (sbuf.st_size - startpos);
2425 if (smb_maxcnt == 0)
2429 * Set up the packet header before send. We
2430 * assume here the sendfile will work (get the
2431 * correct amount of data).
2434 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2435 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2436 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2437 SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
2438 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2439 SCVAL(outbuf,smb_vwv0,0xFF);
2440 set_message(outbuf,12,smb_maxcnt,False);
2441 header.data = outbuf;
2442 header.length = data - outbuf;
2445 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt)) == -1) {
2446 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2447 if (errno == ENOSYS) {
2452 * Special hack for broken Linux with no working sendfile. If we
2453 * return EINTR we sent the header but not the rest of the data.
2454 * Fake this up by doing read/write calls.
2457 if (errno == EINTR) {
2458 /* Ensure we don't do this again. */
2459 set_use_sendfile(SNUM(conn), False);
2460 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2462 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2463 len_outbuf - (data-outbuf))) == -1) {
2464 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2465 fsp->fsp_name, strerror(errno) ));
2466 exit_server("send_file_readX: fake_sendfile failed");
2468 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2469 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2470 /* Returning -1 here means successful sendfile. */
2474 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2475 fsp->fsp_name, strerror(errno) ));
2476 exit_server("send_file_readX sendfile failed");
2479 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2480 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2481 /* Returning -1 here means successful sendfile. */
2489 nread = read_file(fsp,data,startpos,smb_maxcnt);
2492 END_PROFILE(SMBreadX);
2493 return(UNIXERROR(ERRDOS,ERRnoaccess));
2496 outsize = set_message(outbuf,12,nread,False);
2497 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2498 SSVAL(outbuf,smb_vwv5,nread);
2499 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2500 SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
2501 SSVAL(smb_buf(outbuf),-2,nread);
2503 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2504 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2506 /* Returning the number of bytes we want to send back - including header. */
2510 /****************************************************************************
2511 Reply to a read and X.
2512 ****************************************************************************/
2514 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2516 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2517 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2519 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2521 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2524 START_PROFILE(SMBreadX);
2526 /* If it's an IPC, pass off the pipe handler. */
2528 END_PROFILE(SMBreadX);
2529 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2532 CHECK_FSP(fsp,conn);
2535 set_message(outbuf,12,0,True);
2537 if (global_client_caps & CAP_LARGE_READX) {
2538 if (SVAL(inbuf,smb_vwv7) == 1) {
2539 smb_maxcnt |= (1<<16);
2541 if (smb_maxcnt > BUFFER_SIZE) {
2542 DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2543 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
2544 END_PROFILE(SMBreadX);
2545 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2549 if(CVAL(inbuf,smb_wct) == 12) {
2550 #ifdef LARGE_SMB_OFF_T
2552 * This is a large offset (64 bit) read.
2554 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2556 #else /* !LARGE_SMB_OFF_T */
2559 * Ensure we haven't been sent a >32 bit offset.
2562 if(IVAL(inbuf,smb_vwv10) != 0) {
2563 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2564 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2565 END_PROFILE(SMBreadX);
2566 return ERROR_DOS(ERRDOS,ERRbadaccess);
2569 #endif /* LARGE_SMB_OFF_T */
2573 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2574 END_PROFILE(SMBreadX);
2575 return ERROR_DOS(ERRDOS,ERRlock);
2578 if (schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
2579 END_PROFILE(SMBreadX);
2583 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2585 nread = chain_reply(inbuf,outbuf,length,bufsize);
2587 END_PROFILE(SMBreadX);
2591 /****************************************************************************
2592 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2593 ****************************************************************************/
2595 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2598 ssize_t total_written=0;
2599 size_t numtowrite=0;
2604 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2606 START_PROFILE(SMBwritebraw);
2608 if (srv_is_signing_active()) {
2609 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2612 CHECK_FSP(fsp,conn);
2615 tcount = IVAL(inbuf,smb_vwv1);
2616 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2617 write_through = BITSETW(inbuf+smb_vwv7,0);
2619 /* We have to deal with slightly different formats depending
2620 on whether we are using the core+ or lanman1.0 protocol */
2622 if(Protocol <= PROTOCOL_COREPLUS) {
2623 numtowrite = SVAL(smb_buf(inbuf),-2);
2624 data = smb_buf(inbuf);
2626 numtowrite = SVAL(inbuf,smb_vwv10);
2627 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2630 /* force the error type */
2631 SCVAL(inbuf,smb_com,SMBwritec);
2632 SCVAL(outbuf,smb_com,SMBwritec);
2634 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2635 END_PROFILE(SMBwritebraw);
2636 return(ERROR_DOS(ERRDOS,ERRlock));
2640 nwritten = write_file(fsp,data,startpos,numtowrite);
2642 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2643 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2645 if (nwritten < (ssize_t)numtowrite) {
2646 END_PROFILE(SMBwritebraw);
2647 return(UNIXERROR(ERRHRD,ERRdiskfull));
2650 total_written = nwritten;
2652 /* Return a message to the redirector to tell it to send more bytes */
2653 SCVAL(outbuf,smb_com,SMBwritebraw);
2654 SSVALS(outbuf,smb_vwv0,-1);
2655 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2657 if (!send_smb(smbd_server_fd(),outbuf))
2658 exit_server("reply_writebraw: send_smb failed.");
2660 /* Now read the raw data into the buffer and write it */
2661 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2662 exit_server("secondary writebraw failed");
2665 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2666 numtowrite = smb_len(inbuf);
2668 /* Set up outbuf to return the correct return */
2669 outsize = set_message(outbuf,1,0,True);
2670 SCVAL(outbuf,smb_com,SMBwritec);
2671 SSVAL(outbuf,smb_vwv0,total_written);
2673 if (numtowrite != 0) {
2675 if (numtowrite > BUFFER_SIZE) {
2676 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2677 (unsigned int)numtowrite ));
2678 exit_server("secondary writebraw failed");
2681 if (tcount > nwritten+numtowrite) {
2682 DEBUG(3,("Client overestimated the write %d %d %d\n",
2683 (int)tcount,(int)nwritten,(int)numtowrite));
2686 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2687 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2689 exit_server("secondary writebraw failed");
2692 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2694 if (nwritten < (ssize_t)numtowrite) {
2695 SCVAL(outbuf,smb_rcls,ERRHRD);
2696 SSVAL(outbuf,smb_err,ERRdiskfull);
2700 total_written += nwritten;
2703 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2704 sync_file(conn,fsp);
2706 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2707 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2709 /* we won't return a status if write through is not selected - this follows what WfWg does */
2710 END_PROFILE(SMBwritebraw);
2711 if (!write_through && total_written==tcount) {
2713 #if RABBIT_PELLET_FIX
2715 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2716 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2718 if (!send_keepalive(smbd_server_fd()))
2719 exit_server("reply_writebraw: send of keepalive failed");
2728 #define DBGC_CLASS DBGC_LOCKING
2730 /****************************************************************************
2731 Reply to a writeunlock (core+).
2732 ****************************************************************************/
2734 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2735 int size, int dum_buffsize)
2737 ssize_t nwritten = -1;
2741 NTSTATUS status = NT_STATUS_OK;
2742 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2744 START_PROFILE(SMBwriteunlock);
2746 CHECK_FSP(fsp,conn);
2749 numtowrite = SVAL(inbuf,smb_vwv1);
2750 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2751 data = smb_buf(inbuf) + 3;
2753 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2754 END_PROFILE(SMBwriteunlock);
2755 return ERROR_DOS(ERRDOS,ERRlock);
2758 /* The special X/Open SMB protocol handling of
2759 zero length writes is *NOT* done for
2764 nwritten = write_file(fsp,data,startpos,numtowrite);
2766 if (lp_syncalways(SNUM(conn)))
2767 sync_file(conn,fsp);
2769 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2770 END_PROFILE(SMBwriteunlock);
2771 return(UNIXERROR(ERRHRD,ERRdiskfull));
2775 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2776 (SMB_BIG_UINT)startpos);
2777 if (NT_STATUS_V(status)) {
2778 END_PROFILE(SMBwriteunlock);
2779 return ERROR_NT(status);
2783 outsize = set_message(outbuf,1,0,True);
2785 SSVAL(outbuf,smb_vwv0,nwritten);
2787 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2788 fsp->fnum, (int)numtowrite, (int)nwritten));
2790 END_PROFILE(SMBwriteunlock);
2795 #define DBGC_CLASS DBGC_ALL
2797 /****************************************************************************
2799 ****************************************************************************/
2801 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2804 ssize_t nwritten = -1;
2807 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2809 START_PROFILE(SMBwrite);
2811 /* If it's an IPC, pass off the pipe handler. */
2813 END_PROFILE(SMBwrite);
2814 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2817 CHECK_FSP(fsp,conn);
2820 numtowrite = SVAL(inbuf,smb_vwv1);
2821 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2822 data = smb_buf(inbuf) + 3;
2824 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2825 END_PROFILE(SMBwrite);
2826 return ERROR_DOS(ERRDOS,ERRlock);
2830 * X/Open SMB protocol says that if smb_vwv1 is
2831 * zero then the file size should be extended or
2832 * truncated to the size given in smb_vwv[2-3].
2835 if(numtowrite == 0) {
2837 * This is actually an allocate call, and set EOF. JRA.
2839 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2841 END_PROFILE(SMBwrite);
2842 return ERROR_NT(NT_STATUS_DISK_FULL);
2844 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2846 END_PROFILE(SMBwrite);
2847 return ERROR_NT(NT_STATUS_DISK_FULL);
2850 nwritten = write_file(fsp,data,startpos,numtowrite);
2852 if (lp_syncalways(SNUM(conn)))
2853 sync_file(conn,fsp);
2855 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2856 END_PROFILE(SMBwrite);
2857 return(UNIXERROR(ERRHRD,ERRdiskfull));
2860 outsize = set_message(outbuf,1,0,True);
2862 SSVAL(outbuf,smb_vwv0,nwritten);
2864 if (nwritten < (ssize_t)numtowrite) {
2865 SCVAL(outbuf,smb_rcls,ERRHRD);
2866 SSVAL(outbuf,smb_err,ERRdiskfull);
2869 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2871 END_PROFILE(SMBwrite);
2875 /****************************************************************************
2876 Reply to a write and X.
2877 ****************************************************************************/
2879 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2881 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2882 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2883 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2884 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2885 ssize_t nwritten = -1;
2886 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2887 unsigned int smblen = smb_len(inbuf);
2889 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2890 START_PROFILE(SMBwriteX);
2892 /* If it's an IPC, pass off the pipe handler. */
2894 END_PROFILE(SMBwriteX);
2895 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2898 CHECK_FSP(fsp,conn);
2901 set_message(outbuf,6,0,True);
2903 /* Deal with possible LARGE_WRITEX */
2905 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2908 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2909 END_PROFILE(SMBwriteX);
2910 return ERROR_DOS(ERRDOS,ERRbadmem);
2913 data = smb_base(inbuf) + smb_doff;
2915 if(CVAL(inbuf,smb_wct) == 14) {
2916 #ifdef LARGE_SMB_OFF_T
2918 * This is a large offset (64 bit) write.
2920 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2922 #else /* !LARGE_SMB_OFF_T */
2925 * Ensure we haven't been sent a >32 bit offset.
2928 if(IVAL(inbuf,smb_vwv12) != 0) {
2929 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2930 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2931 END_PROFILE(SMBwriteX);
2932 return ERROR_DOS(ERRDOS,ERRbadaccess);
2935 #endif /* LARGE_SMB_OFF_T */
2938 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2939 END_PROFILE(SMBwriteX);
2940 return ERROR_DOS(ERRDOS,ERRlock);
2943 /* X/Open SMB protocol says that, unlike SMBwrite
2944 if the length is zero then NO truncation is
2945 done, just a write of zero. To truncate a file,
2948 if(numtowrite == 0) {
2952 if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize,
2953 fsp,data,startpos,numtowrite)) {
2954 END_PROFILE(SMBwriteX);
2958 nwritten = write_file(fsp,data,startpos,numtowrite);
2961 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2962 END_PROFILE(SMBwriteX);
2963 return(UNIXERROR(ERRHRD,ERRdiskfull));
2966 SSVAL(outbuf,smb_vwv2,nwritten);
2968 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2970 if (nwritten < (ssize_t)numtowrite) {
2971 SCVAL(outbuf,smb_rcls,ERRHRD);
2972 SSVAL(outbuf,smb_err,ERRdiskfull);
2975 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2976 fsp->fnum, (int)numtowrite, (int)nwritten));
2978 if (lp_syncalways(SNUM(conn)) || write_through)
2979 sync_file(conn,fsp);
2981 END_PROFILE(SMBwriteX);
2982 return chain_reply(inbuf,outbuf,length,bufsize);
2985 /****************************************************************************
2987 ****************************************************************************/
2989 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2995 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2996 START_PROFILE(SMBlseek);
2998 CHECK_FSP(fsp,conn);
3000 flush_write_cache(fsp, SEEK_FLUSH);
3002 mode = SVAL(inbuf,smb_vwv1) & 3;
3003 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3004 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
3013 res = fsp->pos + startpos;
3024 if (umode == SEEK_END) {
3025 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
3026 if(errno == EINVAL) {
3027 SMB_OFF_T current_pos = startpos;
3028 SMB_STRUCT_STAT sbuf;
3030 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
3031 END_PROFILE(SMBlseek);
3032 return(UNIXERROR(ERRDOS,ERRnoaccess));
3035 current_pos += sbuf.st_size;
3037 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
3042 END_PROFILE(SMBlseek);
3043 return(UNIXERROR(ERRDOS,ERRnoaccess));
3049 outsize = set_message(outbuf,2,0,True);
3050 SIVAL(outbuf,smb_vwv0,res);
3052 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3053 fsp->fnum, (double)startpos, (double)res, mode));
3055 END_PROFILE(SMBlseek);
3059 /****************************************************************************
3061 ****************************************************************************/
3063 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3065 int outsize = set_message(outbuf,0,0,True);
3066 uint16 fnum = SVAL(inbuf,smb_vwv0);
3067 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3068 START_PROFILE(SMBflush);
3071 CHECK_FSP(fsp,conn);
3074 file_sync_all(conn);
3076 sync_file(conn,fsp);
3079 DEBUG(3,("flush\n"));
3080 END_PROFILE(SMBflush);
3084 /****************************************************************************
3086 ****************************************************************************/
3088 int reply_exit(connection_struct *conn,
3089 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3092 START_PROFILE(SMBexit);
3094 file_close_pid(SVAL(inbuf,smb_pid));
3096 outsize = set_message(outbuf,0,0,True);
3098 DEBUG(3,("exit\n"));
3100 END_PROFILE(SMBexit);
3104 /****************************************************************************
3105 Reply to a close - has to deal with closing a directory opened by NT SMB's.
3106 ****************************************************************************/
3108 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
3113 int32 eclass = 0, err = 0;
3114 files_struct *fsp = NULL;
3115 START_PROFILE(SMBclose);
3117 outsize = set_message(outbuf,0,0,True);
3119 /* If it's an IPC, pass off to the pipe handler. */
3121 END_PROFILE(SMBclose);
3122 return reply_pipe_close(conn, inbuf,outbuf);
3125 fsp = file_fsp(inbuf,smb_vwv0);
3128 * We can only use CHECK_FSP if we know it's not a directory.
3131 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3132 END_PROFILE(SMBclose);
3133 return ERROR_DOS(ERRDOS,ERRbadfid);
3136 if(fsp->is_directory) {
3138 * Special case - close NT SMB directory handle.
3140 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
3141 close_file(fsp,True);
3144 * Close ordinary file.
3149 /* Save the name for time set in close. */
3150 pstrcpy( file_name, fsp->fsp_name);
3152 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3154 conn->num_files_open));
3157 * Take care of any time sent in the close.
3160 mtime = make_unix_date3(inbuf+smb_vwv1);
3161 fsp_set_pending_modtime(fsp, mtime);
3164 * close_file() returns the unix errno if an error
3165 * was detected on close - normally this is due to
3166 * a disk full error. If not then it was probably an I/O error.
3169 if((close_err = close_file(fsp,True)) != 0) {
3171 END_PROFILE(SMBclose);
3172 return (UNIXERROR(ERRHRD,ERRgeneral));
3176 /* We have a cached error */
3178 END_PROFILE(SMBclose);
3179 return ERROR_DOS(eclass,err);
3182 END_PROFILE(SMBclose);
3186 /****************************************************************************
3187 Reply to a writeclose (Core+ protocol).
3188 ****************************************************************************/
3190 int reply_writeclose(connection_struct *conn,
3191 char *inbuf,char *outbuf, int size, int dum_buffsize)
3194 ssize_t nwritten = -1;
3200 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3201 START_PROFILE(SMBwriteclose);
3203 CHECK_FSP(fsp,conn);
3206 numtowrite = SVAL(inbuf,smb_vwv1);
3207 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3208 mtime = make_unix_date3(inbuf+smb_vwv4);
3209 data = smb_buf(inbuf) + 1;
3211 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3212 END_PROFILE(SMBwriteclose);
3213 return ERROR_DOS(ERRDOS,ERRlock);
3216 nwritten = write_file(fsp,data,startpos,numtowrite);
3218 set_filetime(conn, fsp->fsp_name,mtime);
3221 * More insanity. W2K only closes the file if writelen > 0.
3226 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3228 close_err = close_file(fsp,True);
3231 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3232 fsp->fnum, (int)numtowrite, (int)nwritten,
3233 conn->num_files_open));
3235 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3236 END_PROFILE(SMBwriteclose);
3237 return(UNIXERROR(ERRHRD,ERRdiskfull));
3240 if(close_err != 0) {
3242 END_PROFILE(SMBwriteclose);
3243 return(UNIXERROR(ERRHRD,ERRgeneral));
3246 outsize = set_message(outbuf,1,0,True);
3248 SSVAL(outbuf,smb_vwv0,nwritten);
3249 END_PROFILE(SMBwriteclose);
3254 #define DBGC_CLASS DBGC_LOCKING
3256 /****************************************************************************
3258 ****************************************************************************/
3260 int reply_lock(connection_struct *conn,
3261 char *inbuf,char *outbuf, int length, int dum_buffsize)
3263 int outsize = set_message(outbuf,0,0,True);
3264 SMB_BIG_UINT count,offset;
3266 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3267 BOOL my_lock_ctx = False;
3269 START_PROFILE(SMBlock);
3271 CHECK_FSP(fsp,conn);
3273 release_level_2_oplocks_on_change(fsp);
3275 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3276 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3278 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3279 fsp->fd, fsp->fnum, (double)offset, (double)count));
3281 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
3282 if (NT_STATUS_V(status)) {
3284 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
3285 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
3287 * A blocking lock was requested. Package up
3288 * this smb into a queued request and push it
3289 * onto the blocking lock queue.
3291 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
3292 END_PROFILE(SMBlock);
3297 END_PROFILE(SMBlock);
3298 return ERROR_NT(status);
3301 END_PROFILE(SMBlock);
3305 /****************************************************************************
3307 ****************************************************************************/
3309 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3312 int outsize = set_message(outbuf,0,0,True);
3313 SMB_BIG_UINT count,offset;
3315 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3316 START_PROFILE(SMBunlock);
3318 CHECK_FSP(fsp,conn);
3320 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3321 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3323 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
3324 if (NT_STATUS_V(status)) {
3325 END_PROFILE(SMBunlock);
3326 return ERROR_NT(status);
3329 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3330 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
3332 END_PROFILE(SMBunlock);
3337 #define DBGC_CLASS DBGC_ALL
3339 /****************************************************************************
3341 ****************************************************************************/
3343 int reply_tdis(connection_struct *conn,
3344 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3346 int outsize = set_message(outbuf,0,0,True);
3348 START_PROFILE(SMBtdis);
3350 vuid = SVAL(inbuf,smb_uid);
3353 DEBUG(4,("Invalid connection in tdis\n"));
3354 END_PROFILE(SMBtdis);
3355 return ERROR_DOS(ERRSRV,ERRinvnid);
3360 close_cnum(conn,vuid);
3362 END_PROFILE(SMBtdis);
3366 /****************************************************************************
3368 ****************************************************************************/
3370 int reply_echo(connection_struct *conn,
3371 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3373 int smb_reverb = SVAL(inbuf,smb_vwv0);
3375 unsigned int data_len = smb_buflen(inbuf);
3376 int outsize = set_message(outbuf,1,data_len,True);
3377 START_PROFILE(SMBecho);
3379 if (data_len > BUFFER_SIZE) {
3380 DEBUG(0,("reply_echo: data_len too large.\n"));
3381 END_PROFILE(SMBecho);
3385 /* copy any incoming data back out */
3387 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3389 if (smb_reverb > 100) {
3390 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3394 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3395 SSVAL(outbuf,smb_vwv0,seq_num);
3397 smb_setlen(outbuf,outsize - 4);
3400 if (!send_smb(smbd_server_fd(),outbuf))
3401 exit_server("reply_echo: send_smb failed.");
3404 DEBUG(3,("echo %d times\n", smb_reverb));
3408 END_PROFILE(SMBecho);
3412 /****************************************************************************
3413 Reply to a printopen.
3414 ****************************************************************************/
3416 int reply_printopen(connection_struct *conn,
3417 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3421 START_PROFILE(SMBsplopen);
3423 if (!CAN_PRINT(conn)) {
3424 END_PROFILE(SMBsplopen);
3425 return ERROR_DOS(ERRDOS,ERRnoaccess);
3428 /* Open for exclusive use, write only. */
3429 fsp = print_fsp_open(conn, NULL);
3432 END_PROFILE(SMBsplopen);
3433 return(UNIXERROR(ERRDOS,ERRnoaccess));
3436 outsize = set_message(outbuf,1,0,True);
3437 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3439 DEBUG(3,("openprint fd=%d fnum=%d\n",
3440 fsp->fd, fsp->fnum));
3442 END_PROFILE(SMBsplopen);
3446 /****************************************************************************
3447 Reply to a printclose.
3448 ****************************************************************************/
3450 int reply_printclose(connection_struct *conn,
3451 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3453 int outsize = set_message(outbuf,0,0,True);
3454 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3456 START_PROFILE(SMBsplclose);
3458 CHECK_FSP(fsp,conn);
3460 if (!CAN_PRINT(conn)) {
3461 END_PROFILE(SMBsplclose);
3462 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
3465 DEBUG(3,("printclose fd=%d fnum=%d\n",
3466 fsp->fd,fsp->fnum));
3468 close_err = close_file(fsp,True);
3470 if(close_err != 0) {
3472 END_PROFILE(SMBsplclose);
3473 return(UNIXERROR(ERRHRD,ERRgeneral));
3476 END_PROFILE(SMBsplclose);
3480 /****************************************************************************
3481 Reply to a printqueue.
3482 ****************************************************************************/
3484 int reply_printqueue(connection_struct *conn,
3485 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3487 int outsize = set_message(outbuf,2,3,True);
3488 int max_count = SVAL(inbuf,smb_vwv0);
3489 int start_index = SVAL(inbuf,smb_vwv1);
3490 START_PROFILE(SMBsplretq);
3492 /* we used to allow the client to get the cnum wrong, but that
3493 is really quite gross and only worked when there was only
3494 one printer - I think we should now only accept it if they
3495 get it right (tridge) */
3496 if (!CAN_PRINT(conn)) {
3497 END_PROFILE(SMBsplretq);
3498 return ERROR_DOS(ERRDOS,ERRnoaccess);
3501 SSVAL(outbuf,smb_vwv0,0);
3502 SSVAL(outbuf,smb_vwv1,0);
3503 SCVAL(smb_buf(outbuf),0,1);
3504 SSVAL(smb_buf(outbuf),1,0);
3506 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3507 start_index, max_count));
3510 print_queue_struct *queue = NULL;
3511 print_status_struct status;
3512 char *p = smb_buf(outbuf) + 3;
3513 int count = print_queue_status(SNUM(conn), &queue, &status);
3514 int num_to_get = ABS(max_count);
3515 int first = (max_count>0?start_index:start_index+max_count+1);
3521 num_to_get = MIN(num_to_get,count-first);
3524 for (i=first;i<first+num_to_get;i++) {
3525 put_dos_date2(p,0,queue[i].time);
3526 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3527 SSVAL(p,5, queue[i].job);
3528 SIVAL(p,7,queue[i].size);
3530 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3535 outsize = set_message(outbuf,2,28*count+3,False);
3536 SSVAL(outbuf,smb_vwv0,count);
3537 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3538 SCVAL(smb_buf(outbuf),0,1);
3539 SSVAL(smb_buf(outbuf),1,28*count);
3544 DEBUG(3,("%d entries returned in queue\n",count));
3547 END_PROFILE(SMBsplretq);
3551 /****************************************************************************
3552 Reply to a printwrite.
3553 ****************************************************************************/
3555 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3558 int outsize = set_message(outbuf,0,0,True);
3560 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3562 START_PROFILE(SMBsplwr);
3564 if (!CAN_PRINT(conn)) {
3565 END_PROFILE(SMBsplwr);
3566 return ERROR_DOS(ERRDOS,ERRnoaccess);
3569 CHECK_FSP(fsp,conn);
3572 numtowrite = SVAL(smb_buf(inbuf),1);
3573 data = smb_buf(inbuf) + 3;
3575 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3576 END_PROFILE(SMBsplwr);
3577 return(UNIXERROR(ERRHRD,ERRdiskfull));
3580 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3582 END_PROFILE(SMBsplwr);
3586 /****************************************************************************
3587 The guts of the mkdir command, split out so it may be called by the NT SMB
3589 ****************************************************************************/
3591 NTSTATUS mkdir_internal(connection_struct *conn, const pstring directory, BOOL bad_path)
3595 if(!CAN_WRITE(conn)) {
3596 DEBUG(5,("mkdir_internal: failing create on read-only share %s\n", lp_servicename(SNUM(conn))));
3598 return map_nt_error_from_unix(errno);
3602 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3605 if (!check_name(directory, conn)) {
3606 if(errno == ENOENT) {
3608 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3610 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3613 return map_nt_error_from_unix(errno);
3616 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
3618 if(errno == ENOENT) {
3619 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3621 return map_nt_error_from_unix(errno);
3624 return NT_STATUS_OK;
3627 /****************************************************************************
3629 ****************************************************************************/
3631 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3636 BOOL bad_path = False;
3637 SMB_STRUCT_STAT sbuf;
3639 START_PROFILE(SMBmkdir);
3641 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3642 if (!NT_STATUS_IS_OK(status)) {
3643 END_PROFILE(SMBmkdir);
3644 return ERROR_NT(status);
3647 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3649 unix_convert(directory,conn,0,&bad_path,&sbuf);
3651 if( is_ntfs_stream_name(directory)) {
3652 DEBUG(5,("reply_mkdir: failing create on filename %s with colon in name\n", directory));
3653 END_PROFILE(SMBmkdir);
3654 return ERROR_FORCE_DOS(ERRDOS, ERRinvalidname);
3657 status = mkdir_internal(conn, directory,bad_path);
3658 if (!NT_STATUS_IS_OK(status)) {
3659 END_PROFILE(SMBmkdir);
3660 return ERROR_NT(status);
3663 if (lp_inherit_owner(SNUM(conn))) {
3664 /* Ensure we're checking for a symlink here.... */
3665 /* We don't want to get caught by a symlink racer. */
3667 if(SMB_VFS_LSTAT(conn,directory, &sbuf) != 0) {
3668 END_PROFILE(SMBmkdir);
3669 return(UNIXERROR(ERRDOS,ERRnoaccess));
3672 if(!S_ISDIR(sbuf.st_mode)) {
3673 DEBUG(0,("reply_mkdir: %s is not a directory !\n", directory ));
3674 END_PROFILE(SMBmkdir);
3675 return(UNIXERROR(ERRDOS,ERRnoaccess));
3678 change_owner_to_parent(conn, NULL, directory, &sbuf);
3681 outsize = set_message(outbuf,0,0,True);
3683 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3685 END_PROFILE(SMBmkdir);
3689 /****************************************************************************
3690 Static function used by reply_rmdir to delete an entire directory
3691 tree recursively. Return False on ok, True on fail.
3692 ****************************************************************************/
3694 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3696 const char *dname = NULL;
3699 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3704 while((dname = ReadDirName(dir_hnd, &offset))) {
3708 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3711 if (!is_visible_file(conn, directory, dname, &st, False))
3714 /* Construct the full name. */
3715 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3721 pstrcpy(fullname, directory);
3722 pstrcat(fullname, "/");
3723 pstrcat(fullname, dname);
3725 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3730 if(st.st_mode & S_IFDIR) {
3731 if(recursive_rmdir(conn, fullname)!=0) {
3735 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3739 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3748 /****************************************************************************
3749 The internals of the rmdir code - called elsewhere.
3750 ****************************************************************************/
3752 BOOL rmdir_internals(connection_struct *conn, char *directory)
3757 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3758 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3760 * Check to see if the only thing in this directory are
3761 * vetoed files/directories. If so then delete them and
3762 * retry. If we fail to delete any of them (and we *don't*
3763 * do a recursive delete) then fail the rmdir.
3765 BOOL all_veto_files = True;
3767 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3769 if(dir_hnd != NULL) {
3771 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3772 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3774 if (!is_visible_file(conn, directory, dname, &st, False))
3776 if(!IS_VETO_PATH(conn, dname)) {
3777 all_veto_files = False;
3782 if(all_veto_files) {
3783 RewindDir(dir_hnd,&dirpos);
3784 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3787 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3789 if (!is_visible_file(conn, directory, dname, &st, False))
3792 /* Construct the full name. */
3793 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3798 pstrcpy(fullname, directory);
3799 pstrcat(fullname, "/");
3800 pstrcat(fullname, dname);
3802 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3804 if(st.st_mode & S_IFDIR) {
3805 if(lp_recursive_veto_delete(SNUM(conn))) {
3806 if(recursive_rmdir(conn, fullname) != 0)
3809 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3811 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3815 /* Retry the rmdir */
3816 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3826 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3831 /****************************************************************************
3833 ****************************************************************************/
3835 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3840 BOOL bad_path = False;
3841 SMB_STRUCT_STAT sbuf;
3843 START_PROFILE(SMBrmdir);
3845 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3846 if (!NT_STATUS_IS_OK(status)) {
3847 END_PROFILE(SMBrmdir);
3848 return ERROR_NT(status);
3851 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3853 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3855 END_PROFILE(SMBrmdir);
3856 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3859 if (check_name(directory,conn)) {
3860 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3861 ok = rmdir_internals(conn, directory);
3865 END_PROFILE(SMBrmdir);
3866 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3869 outsize = set_message(outbuf,0,0,True);
3871 DEBUG( 3, ( "rmdir %s\n", directory ) );
3873 END_PROFILE(SMBrmdir);
3877 /*******************************************************************
3878 Resolve wildcards in a filename rename.
3879 Note that name is in UNIX charset and thus potentially can be more
3880 than fstring buffer (255 bytes) especially in default UTF-8 case.
3881 Therefore, we use pstring inside and all calls should ensure that
3882 name2 is at least pstring-long (they do already)
3883 ********************************************************************/
3885 static BOOL resolve_wildcards(const char *name1, char *name2)
3887 pstring root1,root2;
3889 char *p,*p2, *pname1, *pname2;
3890 int available_space, actual_space;
3893 pname1 = strrchr_m(name1,'/');
3894 pname2 = strrchr_m(name2,'/');
3896 if (!pname1 || !pname2)
3899 pstrcpy(root1,pname1);
3900 pstrcpy(root2,pname2);
3901 p = strrchr_m(root1,'.');
3908 p = strrchr_m(root2,'.');
3922 } else if (*p2 == '*') {
3938 } else if (*p2 == '*') {
3948 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3951 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3952 if (actual_space >= available_space - 1) {
3953 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3954 actual_space - available_space));
3957 pstrcpy_base(pname2, root2, name2);
3963 /****************************************************************************
3964 Ensure open files have their names updates.
3965 ****************************************************************************/
3967 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3970 BOOL did_rename = False;
3972 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3973 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3974 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3975 fsp->fsp_name, newname ));
3976 string_set(&fsp->fsp_name, newname);
3981 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3982 (unsigned int)dev, (double)inode, newname ));
3985 /****************************************************************************
3986 Rename an open file - given an fsp.
3987 ****************************************************************************/
3989 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint32 attrs, BOOL replace_if_exists)
3991 SMB_STRUCT_STAT sbuf;
3992 BOOL bad_path = False;
3993 pstring newname_last_component;
3994 NTSTATUS error = NT_STATUS_OK;
3999 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
4001 /* Quick check for "." and ".." */
4002 if (!bad_path && newname_last_component[0] == '.') {
4003 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
4004 return NT_STATUS_ACCESS_DENIED;
4007 if (!rcdest && bad_path) {
4008 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4011 /* Ensure newname contains a '/' */
4012 if(strrchr_m(newname,'/') == 0) {
4015 pstrcpy(tmpstr, "./");
4016 pstrcat(tmpstr, newname);
4017 pstrcpy(newname, tmpstr);
4021 * Check for special case with case preserving and not
4022 * case sensitive. If the old last component differs from the original
4023 * last component only by case, then we should allow
4024 * the rename (user is trying to change the case of the
4028 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
4029 strequal(newname, fsp->fsp_name)) {
4031 pstring newname_modified_last_component;
4034 * Get the last component of the modified name.
4035 * Note that we guarantee that newname contains a '/'
4038 p = strrchr_m(newname,'/');
4039 pstrcpy(newname_modified_last_component,p+1);
4041 if(strcsequal(newname_modified_last_component,
4042 newname_last_component) == False) {
4044 * Replace the modified last component with
4047 pstrcpy(p+1, newname_last_component);
4052 * If the src and dest names are identical - including case,
4053 * don't do the rename, just return success.
4056 if (strcsequal(fsp->fsp_name, newname)) {
4057 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4059 return NT_STATUS_OK;
4062 dest_exists = vfs_object_exist(conn,newname,NULL);
4064 if(!replace_if_exists && dest_exists) {
4065 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4066 fsp->fsp_name,newname));
4067 return NT_STATUS_OBJECT_NAME_COLLISION;
4070 error = can_rename(conn,newname,attrs,&sbuf);
4072 if (dest_exists && !NT_STATUS_IS_OK(error)) {
4073 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4074 nt_errstr(error), fsp->fsp_name,newname));
4075 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
4076 error = NT_STATUS_ACCESS_DENIED;
4080 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
4081 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4082 fsp->fsp_name,newname));
4083 rename_open_files(conn, fsp->dev, fsp->inode, newname);
4084 return NT_STATUS_OK;
4087 if (errno == ENOTDIR || errno == EISDIR)
4088 error = NT_STATUS_OBJECT_NAME_COLLISION;
4090 error = map_nt_error_from_unix(errno);
4092 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4093 nt_errstr(error), fsp->fsp_name,newname));
4098 /****************************************************************************
4099 The guts of the rename command, split out so it may be called by the NT SMB
4101 ****************************************************************************/
4103 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint32 attrs, BOOL replace_if_exists)
4107 pstring last_component_src;
4108 pstring last_component_dest;
4111 BOOL bad_path_src = False;
4112 BOOL bad_path_dest = False;
4114 NTSTATUS error = NT_STATUS_OK;
4117 SMB_STRUCT_STAT sbuf1, sbuf2;
4119 *directory = *mask = 0;
4124 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
4125 if (!rc && bad_path_src) {
4126 if (ms_has_wild(last_component_src))
4127 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4128 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4131 /* Quick check for "." and ".." */
4132 if (last_component_src[0] == '.') {
4133 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
4134 return NT_STATUS_OBJECT_NAME_INVALID;
4138 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
4140 /* Quick check for "." and ".." */
4141 if (last_component_dest[0] == '.') {
4142 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
4143 return NT_STATUS_OBJECT_NAME_INVALID;
4148 * Split the old name into directory and last component
4149 * strings. Note that unix_convert may have stripped off a
4150 * leading ./ from both name and newname if the rename is
4151 * at the root of the share. We need to make sure either both
4152 * name and newname contain a / character or neither of them do
4153 * as this is checked in resolve_wildcards().
4156 p = strrchr_m(name,'/');
4158 pstrcpy(directory,".");
4162 pstrcpy(directory,name);
4164 *p = '/'; /* Replace needed for exceptional test below. */
4168 * We should only check the mangled cache
4169 * here if unix_convert failed. This means
4170 * that the path in 'mask' doesn't exist
4171 * on the file system and so we need to look
4172 * for a possible mangle. This patch from
4173 * Tine Smukavec <valentin.smukavec@hermes.si>.
4176 if (!rc && mangle_is_mangled(mask,SNUM(conn)))
4177 mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
4179 has_wild = ms_has_wild(mask);
4183 * No wildcards - just process the one file.
4185 BOOL is_short_name = mangle_is_8_3(name, True, SNUM(conn));
4187 /* Add a terminating '/' to the directory name. */
4188 pstrcat(directory,"/");
4189 pstrcat(directory,mask);
4191 /* Ensure newname contains a '/' also */
4192 if(strrchr_m(newname,'/') == 0) {
4195 pstrcpy(tmpstr, "./");
4196 pstrcat(tmpstr, newname);
4197 pstrcpy(newname, tmpstr);
4200 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
4201 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
4202 conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory,
4203 newname, last_component_dest, is_short_name));
4206 * Check for special case with case preserving and not
4207 * case sensitive, if directory and newname are identical,
4208 * and the old last component differs from the original
4209 * last component only by case, then we should allow
4210 * the rename (user is trying to change the case of the
4213 if((conn->case_sensitive == False) &&
4214 (((conn->case_preserve == True) &&
4215 (is_short_name == False)) ||
4216 ((conn->short_case_preserve == True) &&
4217 (is_short_name == True))) &&
4218 strcsequal(directory, newname)) {
4219 pstring modified_last_component;
4222 * Get the last component of the modified name.
4223 * Note that we guarantee that newname contains a '/'
4226 p = strrchr_m(newname,'/');
4227 pstrcpy(modified_last_component,p+1);
4229 if(strcsequal(modified_last_component,
4230 last_component_dest) == False) {
4232 * Replace the modified last component with
4235 pstrcpy(p+1, last_component_dest);
4239 resolve_wildcards(directory,newname);
4242 * The source object must exist.
4245 if (!vfs_object_exist(conn, directory, &sbuf1)) {
4246 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
4247 directory,newname));
4249 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
4251 * Must return different errors depending on whether the parent
4252 * directory existed or not.
4255 p = strrchr_m(directory, '/');
4257 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4259 if (vfs_object_exist(conn, directory, NULL))
4260 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4261 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4263 error = map_nt_error_from_unix(errno);
4264 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4265 nt_errstr(error), directory,newname));
4270 if (!rcdest && bad_path_dest) {
4271 if (ms_has_wild(last_component_dest))
4272 return NT_STATUS_OBJECT_NAME_INVALID;
4273 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4276 error = can_rename(conn,directory,attrs,&sbuf1);
4278 if (!NT_STATUS_IS_OK(error)) {
4279 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4280 nt_errstr(error), directory,newname));
4285 * If the src and dest names are identical - including case,
4286 * don't do the rename, just return success.
4289 if (strcsequal(directory, newname)) {
4290 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4291 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
4292 return NT_STATUS_OK;
4295 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
4296 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
4297 directory,newname));
4298 return NT_STATUS_OBJECT_NAME_COLLISION;
4301 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
4302 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
4303 directory,newname));
4304 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4305 return NT_STATUS_OK;
4308 if (errno == ENOTDIR || errno == EISDIR)
4309 error = NT_STATUS_OBJECT_NAME_COLLISION;
4311 error = map_nt_error_from_unix(errno);
4313 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4314 nt_errstr(error), directory,newname));
4319 * Wildcards - process each file that matches.
4321 struct smb_Dir *dir_hnd = NULL;
4325 if (strequal(mask,"????????.???"))
4328 if (check_name(directory,conn))
4329 dir_hnd = OpenDir(conn, directory, mask, attrs);
4333 error = NT_STATUS_NO_SUCH_FILE;
4334 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
4336 while ((dname = ReadDirName(dir_hnd, &offset))) {
4338 BOOL sysdir_entry = False;
4340 pstrcpy(fname,dname);
4342 /* Quick check for "." and ".." */
4343 if (fname[0] == '.') {
4344 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4346 sysdir_entry = True;
4353 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4356 if(!mask_match(fname, mask, conn->case_sensitive))
4360 error = NT_STATUS_OBJECT_NAME_INVALID;
4364 error = NT_STATUS_ACCESS_DENIED;
4365 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
4366 if (!vfs_object_exist(conn, fname, &sbuf1)) {
4367 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4368 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
4371 error = can_rename(conn,fname,attrs,&sbuf1);
4372 if (!NT_STATUS_IS_OK(error)) {
4373 DEBUG(6,("rename %s refused\n", fname));
4376 pstrcpy(destname,newname);
4378 if (!resolve_wildcards(fname,destname)) {
4379 DEBUG(6,("resolve_wildcards %s %s failed\n",
4384 if (strcsequal(fname,destname)) {
4385 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4386 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
4388 error = NT_STATUS_OK;
4392 if (!replace_if_exists &&
4393 vfs_file_exist(conn,destname, NULL)) {
4394 DEBUG(6,("file_exist %s\n", destname));
4395 error = NT_STATUS_OBJECT_NAME_COLLISION;
4399 if (!SMB_VFS_RENAME(conn,fname,destname)) {
4400 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4402 error = NT_STATUS_OK;
4404 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
4409 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
4410 if (!rcdest && bad_path_dest) {
4411 if (ms_has_wild(last_component_dest))
4412 return NT_STATUS_OBJECT_NAME_INVALID;
4413 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4418 if (count == 0 && NT_STATUS_IS_OK(error)) {
4419 error = map_nt_error_from_unix(errno);
4425 /****************************************************************************
4427 ****************************************************************************/
4429 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4436 uint32 attrs = SVAL(inbuf,smb_vwv0);
4439 START_PROFILE(SMBmv);
4441 p = smb_buf(inbuf) + 1;
4442 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4443 if (!NT_STATUS_IS_OK(status)) {
4445 return ERROR_NT(status);
4448 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4449 if (!NT_STATUS_IS_OK(status)) {
4451 return ERROR_NT(status);
4454 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4455 RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4457 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4459 status = rename_internals(conn, name, newname, attrs, False);
4460 if (!NT_STATUS_IS_OK(status)) {
4462 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4463 /* We have re-scheduled this call. */
4466 return ERROR_NT(status);
4470 * Win2k needs a changenotify request response before it will
4471 * update after a rename..
4473 process_pending_change_notify_queue((time_t)0);
4474 outsize = set_message(outbuf,0,0,True);
4480 /*******************************************************************
4481 Copy a file as part of a reply_copy.
4482 ******************************************************************/
4484 BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4485 int count,BOOL target_is_directory, int *err_ret)
4488 SMB_STRUCT_STAT src_sbuf, sbuf2;
4490 files_struct *fsp1,*fsp2;
4496 pstrcpy(dest,dest1);
4497 if (target_is_directory) {
4498 char *p = strrchr_m(src,'/');
4507 if (!vfs_file_exist(conn,src,&src_sbuf))
4510 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
4511 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,INTERNAL_OPEN_ONLY,
4517 if (!target_is_directory && count)
4518 ofun = FILE_EXISTS_OPEN;
4520 dosattrs = dos_mode(conn, src, &src_sbuf);
4521 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
4522 ZERO_STRUCTP(&sbuf2);
4524 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4525 ofun,dosattrs,INTERNAL_OPEN_ONLY,&Access,&action);
4528 close_file(fsp1,False);
4532 if ((ofun&3) == 1) {
4533 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4534 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4536 * Stop the copy from occurring.
4539 src_sbuf.st_size = 0;
4543 if (src_sbuf.st_size)
4544 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4546 close_file(fsp1,False);
4548 /* Ensure the modtime is set correctly on the destination file. */
4549 fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime);
4552 * As we are opening fsp1 read-only we only expect
4553 * an error on close on fsp2 if we are out of space.
4554 * Thus we don't look at the error return from the
4557 *err_ret = close_file(fsp2,False);
4559 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4562 /****************************************************************************
4563 Reply to a file copy.
4564 ****************************************************************************/
4566 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4571 pstring mask,newname;
4574 int error = ERRnoaccess;
4578 int tid2 = SVAL(inbuf,smb_vwv0);
4579 int ofun = SVAL(inbuf,smb_vwv1);
4580 int flags = SVAL(inbuf,smb_vwv2);
4581 BOOL target_is_directory=False;
4582 BOOL bad_path1 = False;
4583 BOOL bad_path2 = False;
4585 SMB_STRUCT_STAT sbuf1, sbuf2;
4588 START_PROFILE(SMBcopy);
4590 *directory = *mask = 0;
4593 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4594 if (!NT_STATUS_IS_OK(status)) {
4595 END_PROFILE(SMBcopy);
4596 return ERROR_NT(status);
4598 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4599 if (!NT_STATUS_IS_OK(status)) {
4600 END_PROFILE(SMBcopy);
4601 return ERROR_NT(status);
4604 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4606 if (tid2 != conn->cnum) {
4607 /* can't currently handle inter share copies XXXX */
4608 DEBUG(3,("Rejecting inter-share copy\n"));
4609 END_PROFILE(SMBcopy);
4610 return ERROR_DOS(ERRSRV,ERRinvdevice);
4613 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4614 RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4616 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4617 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4619 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4621 if ((flags&1) && target_is_directory) {
4622 END_PROFILE(SMBcopy);
4623 return ERROR_DOS(ERRDOS,ERRbadfile);
4626 if ((flags&2) && !target_is_directory) {
4627 END_PROFILE(SMBcopy);
4628 return ERROR_DOS(ERRDOS,ERRbadpath);
4631 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4632 /* wants a tree copy! XXXX */
4633 DEBUG(3,("Rejecting tree copy\n"));
4634 END_PROFILE(SMBcopy);
4635 return ERROR_DOS(ERRSRV,ERRerror);
4638 p = strrchr_m(name,'/');
4640 pstrcpy(directory,"./");
4644 pstrcpy(directory,name);
4649 * We should only check the mangled cache
4650 * here if unix_convert failed. This means
4651 * that the path in 'mask' doesn't exist
4652 * on the file system and so we need to look
4653 * for a possible mangle. This patch from
4654 * Tine Smukavec <valentin.smukavec@hermes.si>.
4657 if (!rc && mangle_is_mangled(mask, SNUM(conn)))
4658 mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
4660 has_wild = ms_has_wild(mask);
4663 pstrcat(directory,"/");
4664 pstrcat(directory,mask);
4665 if (resolve_wildcards(directory,newname) &&
4666 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4670 END_PROFILE(SMBcopy);
4671 return(UNIXERROR(ERRHRD,ERRgeneral));
4674 exists = vfs_file_exist(conn,directory,NULL);
4677 struct smb_Dir *dir_hnd = NULL;
4681 if (strequal(mask,"????????.???"))
4684 if (check_name(directory,conn))
4685 dir_hnd = OpenDir(conn, directory, mask, 0);
4691 while ((dname = ReadDirName(dir_hnd, &offset))) {
4693 pstrcpy(fname,dname);
4695 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4698 if(!mask_match(fname, mask, conn->case_sensitive))
4701 error = ERRnoaccess;
4702 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4703 pstrcpy(destname,newname);
4704 if (resolve_wildcards(fname,destname) &&
4705 copy_file(fname,destname,conn,ofun,
4706 count,target_is_directory,&err))
4708 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4716 /* Error on close... */
4718 END_PROFILE(SMBcopy);
4719 return(UNIXERROR(ERRHRD,ERRgeneral));
4723 END_PROFILE(SMBcopy);
4724 return ERROR_DOS(ERRDOS,error);
4726 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4727 set_saved_error_triple(ERRDOS, ERRbadpath, NT_STATUS_OK);
4729 END_PROFILE(SMBcopy);
4730 return(UNIXERROR(ERRDOS,error));
4734 outsize = set_message(outbuf,1,0,True);
4735 SSVAL(outbuf,smb_vwv0,count);
4737 END_PROFILE(SMBcopy);
4741 /****************************************************************************
4743 ****************************************************************************/
4745 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4753 START_PROFILE(pathworks_setdir);
4756 if (!CAN_SETDIR(snum)) {
4757 END_PROFILE(pathworks_setdir);
4758 return ERROR_DOS(ERRDOS,ERRnoaccess);
4761 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False);
4762 if (!NT_STATUS_IS_OK(status)) {
4763 END_PROFILE(pathworks_setdir);
4764 return ERROR_NT(status);
4767 RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf);
4769 if (strlen(newdir) == 0) {
4772 ok = vfs_directory_exist(conn,newdir,NULL);
4774 string_set(&conn->connectpath,newdir);
4778 END_PROFILE(pathworks_setdir);
4779 return ERROR_DOS(ERRDOS,ERRbadpath);
4782 outsize = set_message(outbuf,0,0,True);
4783 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4785 DEBUG(3,("setdir %s\n", newdir));
4787 END_PROFILE(pathworks_setdir);
4792 #define DBGC_CLASS DBGC_LOCKING
4794 /****************************************************************************
4795 Get a lock pid, dealing with large count requests.
4796 ****************************************************************************/
4798 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4800 if(!large_file_format)
4801 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4803 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4806 /****************************************************************************
4807 Get a lock count, dealing with large count requests.
4808 ****************************************************************************/
4810 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4812 SMB_BIG_UINT count = 0;
4814 if(!large_file_format) {
4815 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4818 #if defined(HAVE_LONGLONG)
4819 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4820 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4821 #else /* HAVE_LONGLONG */
4824 * NT4.x seems to be broken in that it sends large file (64 bit)
4825 * lockingX calls even if the CAP_LARGE_FILES was *not*
4826 * negotiated. For boxes without large unsigned ints truncate the
4827 * lock count by dropping the top 32 bits.
4830 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4831 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4832 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4833 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4834 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4837 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4838 #endif /* HAVE_LONGLONG */
4844 #if !defined(HAVE_LONGLONG)
4845 /****************************************************************************
4846 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4847 ****************************************************************************/
4849 static uint32 map_lock_offset(uint32 high, uint32 low)
4853 uint32 highcopy = high;
4856 * Try and find out how many significant bits there are in high.
4859 for(i = 0; highcopy; i++)
4863 * We use 31 bits not 32 here as POSIX
4864 * lock offsets may not be negative.
4867 mask = (~0) << (31 - i);
4870 return 0; /* Fail. */
4876 #endif /* !defined(HAVE_LONGLONG) */
4878 /****************************************************************************
4879 Get a lock offset, dealing with large offset requests.
4880 ****************************************************************************/
4882 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4884 SMB_BIG_UINT offset = 0;
4888 if(!large_file_format) {
4889 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4892 #if defined(HAVE_LONGLONG)
4893 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4894 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4895 #else /* HAVE_LONGLONG */
4898 * NT4.x seems to be broken in that it sends large file (64 bit)
4899 * lockingX calls even if the CAP_LARGE_FILES was *not*
4900 * negotiated. For boxes without large unsigned ints mangle the
4901 * lock offset by mapping the top 32 bits onto the lower 32.
4904 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4905 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4906 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4909 if((new_low = map_lock_offset(high, low)) == 0) {
4911 return (SMB_BIG_UINT)-1;
4914 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4915 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4916 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4917 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4920 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4921 #endif /* HAVE_LONGLONG */
4927 /****************************************************************************
4928 Reply to a lockingX request.
4929 ****************************************************************************/
4931 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4933 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4934 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4935 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4936 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4937 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4938 SMB_BIG_UINT count = 0, offset = 0;
4940 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4943 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4945 BOOL my_lock_ctx = False;
4948 START_PROFILE(SMBlockingX);
4950 CHECK_FSP(fsp,conn);
4952 data = smb_buf(inbuf);
4954 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
4955 /* we don't support these - and CANCEL_LOCK makes w2k
4956 and XP reboot so I don't really want to be
4957 compatible! (tridge) */
4958 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4961 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
4962 /* Need to make this like a cancel.... JRA. */
4963 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4966 /* Check if this is an oplock break on a file
4967 we have granted an oplock on.
4969 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4970 /* Client can insist on breaking to none. */
4971 BOOL break_to_none = (oplocklevel == 0);
4973 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4974 (unsigned int)oplocklevel, fsp->fnum ));
4977 * Make sure we have granted an exclusive or batch oplock on this file.
4980 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4981 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4982 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4984 /* if this is a pure oplock break request then don't send a reply */
4985 if (num_locks == 0 && num_ulocks == 0) {
4986 END_PROFILE(SMBlockingX);
4989 END_PROFILE(SMBlockingX);
4990 return ERROR_DOS(ERRDOS,ERRlock);
4994 if (remove_oplock(fsp, break_to_none) == False) {
4995 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4999 /* if this is a pure oplock break request then don't send a reply */
5000 if (num_locks == 0 && num_ulocks == 0) {
5001 /* Sanity check - ensure a pure oplock break is not a
5003 if(CVAL(inbuf,smb_vwv0) != 0xff)
5004 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
5005 (unsigned int)CVAL(inbuf,smb_vwv0) ));
5006 END_PROFILE(SMBlockingX);
5012 * We do this check *after* we have checked this is not a oplock break
5013 * response message. JRA.
5016 release_level_2_oplocks_on_change(fsp);
5018 /* Data now points at the beginning of the list
5019 of smb_unlkrng structs */
5020 for(i = 0; i < (int)num_ulocks; i++) {
5021 lock_pid = get_lock_pid( data, i, large_file_format);
5022 count = get_lock_count( data, i, large_file_format);
5023 offset = get_lock_offset( data, i, large_file_format, &err);
5026 * There is no error code marked "stupid client bug".... :-).
5029 END_PROFILE(SMBlockingX);
5030 return ERROR_DOS(ERRDOS,ERRnoaccess);
5033 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
5034 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
5036 status = do_unlock(fsp,conn,lock_pid,count,offset);
5037 if (NT_STATUS_V(status)) {
5038 END_PROFILE(SMBlockingX);
5039 return ERROR_NT(status);
5043 /* Setup the timeout in seconds. */
5045 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
5047 /* Now do any requested locks */
5048 data += ((large_file_format ? 20 : 10)*num_ulocks);
5050 /* Data now points at the beginning of the list
5051 of smb_lkrng structs */
5053 for(i = 0; i < (int)num_locks; i++) {
5054 lock_pid = get_lock_pid( data, i, large_file_format);
5055 count = get_lock_count( data, i, large_file_format);
5056 offset = get_lock_offset( data, i, large_file_format, &err);
5059 * There is no error code marked "stupid client bug".... :-).
5062 END_PROFILE(SMBlockingX);
5063 return ERROR_DOS(ERRDOS,ERRnoaccess);
5066 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
5067 (double)offset, (double)count, (unsigned int)lock_pid,
5068 fsp->fsp_name, (int)lock_timeout ));
5070 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
5071 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
5072 if (NT_STATUS_V(status)) {
5074 * Interesting fact found by IFSTEST /t LockOverlappedTest...
5075 * Even if it's our own lock context, we need to wait here as
5076 * there may be an unlock on the way.
5077 * So I removed a "&& !my_lock_ctx" from the following
5078 * if statement. JRA.
5080 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
5082 * A blocking lock was requested. Package up
5083 * this smb into a queued request and push it
5084 * onto the blocking lock queue.
5086 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
5087 END_PROFILE(SMBlockingX);
5095 /* If any of the above locks failed, then we must unlock
5096 all of the previous locks (X/Open spec). */
5097 if (i != num_locks && num_locks != 0) {
5099 * Ensure we don't do a remove on the lock that just failed,
5100 * as under POSIX rules, if we have a lock already there, we
5101 * will delete it (and we shouldn't) .....
5103 for(i--; i >= 0; i--) {
5104 lock_pid = get_lock_pid( data, i, large_file_format);
5105 count = get_lock_count( data, i, large_file_format);
5106 offset = get_lock_offset( data, i, large_file_format, &err);
5109 * There is no error code marked "stupid client bug".... :-).
5112 END_PROFILE(SMBlockingX);
5113 return ERROR_DOS(ERRDOS,ERRnoaccess);
5116 do_unlock(fsp,conn,lock_pid,count,offset);
5118 END_PROFILE(SMBlockingX);
5119 return ERROR_NT(status);
5122 set_message(outbuf,2,0,True);
5124 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5125 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
5127 END_PROFILE(SMBlockingX);
5128 return chain_reply(inbuf,outbuf,length,bufsize);
5132 #define DBGC_CLASS DBGC_ALL
5134 /****************************************************************************
5135 Reply to a SMBreadbmpx (read block multiplex) request.
5136 ****************************************************************************/
5138 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5149 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5150 START_PROFILE(SMBreadBmpx);
5152 /* this function doesn't seem to work - disable by default */
5153 if (!lp_readbmpx()) {
5154 END_PROFILE(SMBreadBmpx);
5155 return ERROR_DOS(ERRSRV,ERRuseSTD);
5158 outsize = set_message(outbuf,8,0,True);
5160 CHECK_FSP(fsp,conn);
5163 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5164 maxcount = SVAL(inbuf,smb_vwv3);
5166 data = smb_buf(outbuf);
5167 pad = ((long)data)%4;
5172 max_per_packet = bufsize-(outsize+pad);
5176 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5177 END_PROFILE(SMBreadBmpx);
5178 return ERROR_DOS(ERRDOS,ERRlock);
5182 size_t N = MIN(max_per_packet,tcount-total_read);
5184 nread = read_file(fsp,data,startpos,N);
5189 if (nread < (ssize_t)N)
5190 tcount = total_read + nread;
5192 set_message(outbuf,8,nread,False);
5193 SIVAL(outbuf,smb_vwv0,startpos);
5194 SSVAL(outbuf,smb_vwv2,tcount);
5195 SSVAL(outbuf,smb_vwv6,nread);
5196 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5199 if (!send_smb(smbd_server_fd(),outbuf))
5200 exit_server("reply_readbmpx: send_smb failed.");
5202 total_read += nread;
5204 } while (total_read < (ssize_t)tcount);
5206 END_PROFILE(SMBreadBmpx);
5210 /****************************************************************************
5211 Reply to a SMBsetattrE.
5212 ****************************************************************************/
5214 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5216 struct utimbuf unix_times;
5218 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5219 START_PROFILE(SMBsetattrE);
5221 outsize = set_message(outbuf,0,0,True);
5223 if(!fsp || (fsp->conn != conn)) {
5224 END_PROFILE(SMBgetattrE);
5225 return ERROR_DOS(ERRDOS,ERRbadfid);
5229 * Convert the DOS times into unix times. Ignore create
5230 * time as UNIX can't set this.
5233 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
5234 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
5237 * Patch from Ray Frush <frush@engr.colostate.edu>
5238 * Sometimes times are sent as zero - ignore them.
5241 if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5242 /* Ignore request */
5243 if( DEBUGLVL( 3 ) ) {
5244 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5245 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5247 END_PROFILE(SMBsetattrE);
5249 } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5250 /* set modify time = to access time if modify time was unset */
5251 unix_times.modtime = unix_times.actime;
5254 /* Set the date on this file */
5255 /* Should we set pending modtime here ? JRA */
5256 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
5257 END_PROFILE(SMBsetattrE);
5258 return ERROR_DOS(ERRDOS,ERRnoaccess);
5261 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
5262 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
5264 END_PROFILE(SMBsetattrE);
5269 /* Back from the dead for OS/2..... JRA. */
5271 /****************************************************************************
5272 Reply to a SMBwritebmpx (write block multiplex primary) request.
5273 ****************************************************************************/
5275 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5278 ssize_t nwritten = -1;
5285 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5286 START_PROFILE(SMBwriteBmpx);
5288 CHECK_FSP(fsp,conn);
5290 if (HAS_CACHED_ERROR(fsp)) {
5291 return(CACHED_ERROR(fsp));
5294 tcount = SVAL(inbuf,smb_vwv1);
5295 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
5296 write_through = BITSETW(inbuf+smb_vwv7,0);
5297 numtowrite = SVAL(inbuf,smb_vwv10);
5298 smb_doff = SVAL(inbuf,smb_vwv11);
5300 data = smb_base(inbuf) + smb_doff;
5302 /* If this fails we need to send an SMBwriteC response,
5303 not an SMBwritebmpx - set this up now so we don't forget */
5304 SCVAL(outbuf,smb_com,SMBwritec);
5306 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
5307 END_PROFILE(SMBwriteBmpx);
5308 return(ERROR_DOS(ERRDOS,ERRlock));
5311 nwritten = write_file(fsp,data,startpos,numtowrite);
5313 if(lp_syncalways(SNUM(conn)) || write_through)
5314 sync_file(conn,fsp);
5316 if(nwritten < (ssize_t)numtowrite) {
5317 END_PROFILE(SMBwriteBmpx);
5318 return(UNIXERROR(ERRHRD,ERRdiskfull));
5321 /* If the maximum to be written to this file
5322 is greater than what we just wrote then set
5323 up a secondary struct to be attached to this
5324 fd, we will use this to cache error messages etc. */
5326 if((ssize_t)tcount > nwritten) {
5327 write_bmpx_struct *wbms;
5328 if(fsp->wbmpx_ptr != NULL)
5329 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5331 wbms = SMB_MALLOC_P(write_bmpx_struct);
5333 DEBUG(0,("Out of memory in reply_readmpx\n"));
5334 END_PROFILE(SMBwriteBmpx);
5335 return(ERROR_DOS(ERRSRV,ERRnoresource));
5337 wbms->wr_mode = write_through;
5338 wbms->wr_discard = False; /* No errors yet */
5339 wbms->wr_total_written = nwritten;
5340 wbms->wr_errclass = 0;
5342 fsp->wbmpx_ptr = wbms;
5345 /* We are returning successfully, set the message type back to
5347 SCVAL(outbuf,smb_com,SMBwriteBmpx);
5349 outsize = set_message(outbuf,1,0,True);
5351 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5353 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5354 fsp->fnum, (int)numtowrite, (int)nwritten ) );
5356 if (write_through && tcount==nwritten) {
5357 /* We need to send both a primary and a secondary response */
5358 smb_setlen(outbuf,outsize - 4);
5360 if (!send_smb(smbd_server_fd(),outbuf))
5361 exit_server("reply_writebmpx: send_smb failed.");
5363 /* Now the secondary */
5364 outsize = set_message(outbuf,1,0,True);
5365 SCVAL(outbuf,smb_com,SMBwritec);
5366 SSVAL(outbuf,smb_vwv0,nwritten);
5369 END_PROFILE(SMBwriteBmpx);
5373 /****************************************************************************
5374 Reply to a SMBwritebs (write block multiplex secondary) request.
5375 ****************************************************************************/
5377 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5380 ssize_t nwritten = -1;
5387 write_bmpx_struct *wbms;
5388 BOOL send_response = False;
5389 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5390 START_PROFILE(SMBwriteBs);
5392 CHECK_FSP(fsp,conn);
5395 tcount = SVAL(inbuf,smb_vwv1);
5396 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5397 numtowrite = SVAL(inbuf,smb_vwv6);
5398 smb_doff = SVAL(inbuf,smb_vwv7);
5400 data = smb_base(inbuf) + smb_doff;
5402 /* We need to send an SMBwriteC response, not an SMBwritebs */
5403 SCVAL(outbuf,smb_com,SMBwritec);
5405 /* This fd should have an auxiliary struct attached,
5406 check that it does */
5407 wbms = fsp->wbmpx_ptr;
5409 END_PROFILE(SMBwriteBs);
5413 /* If write through is set we can return errors, else we must cache them */
5414 write_through = wbms->wr_mode;
5416 /* Check for an earlier error */
5417 if(wbms->wr_discard) {
5418 END_PROFILE(SMBwriteBs);
5419 return -1; /* Just discard the packet */
5422 nwritten = write_file(fsp,data,startpos,numtowrite);
5424 if(lp_syncalways(SNUM(conn)) || write_through)
5425 sync_file(conn,fsp);
5427 if (nwritten < (ssize_t)numtowrite) {
5429 /* We are returning an error - we can delete the aux struct */
5432 fsp->wbmpx_ptr = NULL;
5433 END_PROFILE(SMBwriteBs);
5434 return(ERROR_DOS(ERRHRD,ERRdiskfull));
5436 wbms->wr_errclass = ERRHRD;
5437 wbms->wr_error = ERRdiskfull;
5438 wbms->wr_status = NT_STATUS_DISK_FULL;
5439 wbms->wr_discard = True;
5440 END_PROFILE(SMBwriteBs);
5444 /* Increment the total written, if this matches tcount
5445 we can discard the auxiliary struct (hurrah !) and return a writeC */
5446 wbms->wr_total_written += nwritten;
5447 if(wbms->wr_total_written >= tcount) {
5448 if (write_through) {
5449 outsize = set_message(outbuf,1,0,True);
5450 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
5451 send_response = True;
5455 fsp->wbmpx_ptr = NULL;
5459 END_PROFILE(SMBwriteBs);
5463 END_PROFILE(SMBwriteBs);
5467 /****************************************************************************
5468 Reply to a SMBgetattrE.
5469 ****************************************************************************/
5471 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5473 SMB_STRUCT_STAT sbuf;
5476 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5477 START_PROFILE(SMBgetattrE);
5479 outsize = set_message(outbuf,11,0,True);
5481 if(!fsp || (fsp->conn != conn)) {
5482 END_PROFILE(SMBgetattrE);
5483 return ERROR_DOS(ERRDOS,ERRbadfid);
5486 /* Do an fstat on this file */
5487 if(fsp_stat(fsp, &sbuf)) {
5488 END_PROFILE(SMBgetattrE);
5489 return(UNIXERROR(ERRDOS,ERRnoaccess));
5492 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5495 * Convert the times into dos times. Set create
5496 * date to be last modify date as UNIX doesn't save
5500 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5501 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5502 /* Should we check pending modtime here ? JRA */
5503 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5506 SIVAL(outbuf,smb_vwv6,0);
5507 SIVAL(outbuf,smb_vwv8,0);
5509 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
5510 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5511 SIVAL(outbuf,smb_vwv8,allocation_size);
5513 SSVAL(outbuf,smb_vwv10, mode);
5515 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5517 END_PROFILE(SMBgetattrE);