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 if (!dptr_fill(p+12,dptr_num)) {
1163 p += DIR_STRUCT_SIZE;
1173 /* If we were called as SMBffirst with smb_search_id == NULL
1174 and no entries were found then return error and close dirptr
1177 if (numentries == 0 || !ok) {
1178 dptr_close(&dptr_num);
1179 } else if(ok && expect_close && status_len == 0) {
1180 /* Close the dptr - we know it's gone */
1181 dptr_close(&dptr_num);
1184 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1185 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1186 dptr_close(&dptr_num);
1189 if ((numentries == 0) && !ms_has_wild(mask)) {
1190 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1193 SSVAL(outbuf,smb_vwv0,numentries);
1194 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1195 SCVAL(smb_buf(outbuf),0,5);
1196 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1198 /* The replies here are never long name. */
1199 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1200 if (!allow_long_path_components) {
1201 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
1204 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1205 SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1207 outsize += DIR_STRUCT_SIZE*numentries;
1208 smb_setlen(outbuf,outsize - 4);
1210 if ((! *directory) && dptr_path(dptr_num))
1211 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1213 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1214 smb_fn_name(CVAL(inbuf,smb_com)),
1215 mask, directory, dirtype, numentries, maxentries ) );
1217 END_PROFILE(SMBsearch);
1221 /****************************************************************************
1222 Reply to a fclose (stop directory search).
1223 ****************************************************************************/
1225 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1235 if (lp_posix_pathnames()) {
1236 return reply_unknown(inbuf, outbuf);
1239 START_PROFILE(SMBfclose);
1241 outsize = set_message(outbuf,1,0,True);
1242 p = smb_buf(inbuf) + 1;
1243 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, True);
1244 if (!NT_STATUS_IS_OK(err)) {
1245 END_PROFILE(SMBfclose);
1246 return ERROR_NT(err);
1249 status_len = SVAL(p,0);
1252 if (status_len == 0) {
1253 END_PROFILE(SMBfclose);
1254 return ERROR_DOS(ERRSRV,ERRsrverror);
1257 memcpy(status,p,21);
1259 if(dptr_fetch(status+12,&dptr_num)) {
1260 /* Close the dptr - we know it's gone */
1261 dptr_close(&dptr_num);
1264 SSVAL(outbuf,smb_vwv0,0);
1266 DEBUG(3,("search close\n"));
1268 END_PROFILE(SMBfclose);
1272 /****************************************************************************
1274 ****************************************************************************/
1276 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1284 SMB_STRUCT_STAT sbuf;
1285 BOOL bad_path = False;
1287 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1289 uint32 dos_attr = SVAL(inbuf,smb_vwv1);
1292 uint32 create_disposition;
1293 uint32 create_options = 0;
1295 START_PROFILE(SMBopen);
1297 deny_mode = SVAL(inbuf,smb_vwv0);
1299 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1300 if (!NT_STATUS_IS_OK(status)) {
1301 END_PROFILE(SMBopen);
1302 return ERROR_NT(status);
1305 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1307 unix_convert(fname,conn,0,&bad_path,&sbuf);
1309 END_PROFILE(SMBopen);
1310 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1313 if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
1314 &access_mask, &share_mode, &create_disposition, &create_options)) {
1315 END_PROFILE(SMBopen);
1316 return ERROR_DOS(ERRDOS, ERRbadaccess);
1319 fsp = open_file_ntcreate(conn,fname,&sbuf,
1329 END_PROFILE(SMBopen);
1330 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1331 /* We have re-scheduled this call. */
1334 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1337 size = sbuf.st_size;
1338 fattr = dos_mode(conn,fname,&sbuf);
1339 mtime = sbuf.st_mtime;
1342 DEBUG(3,("attempt to open a directory %s\n",fname));
1343 close_file(fsp,False);
1344 END_PROFILE(SMBopen);
1345 return ERROR_DOS(ERRDOS,ERRnoaccess);
1348 outsize = set_message(outbuf,7,0,True);
1349 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1350 SSVAL(outbuf,smb_vwv1,fattr);
1351 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1352 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1354 put_dos_date3(outbuf,smb_vwv2,mtime);
1356 SIVAL(outbuf,smb_vwv4,(uint32)size);
1357 SSVAL(outbuf,smb_vwv6,GET_OPENX_MODE(deny_mode));
1359 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1360 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1363 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1364 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1366 END_PROFILE(SMBopen);
1370 /****************************************************************************
1371 Reply to an open and X.
1372 ****************************************************************************/
1374 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1377 uint16 open_flags = SVAL(inbuf,smb_vwv2);
1378 int deny_mode = SVAL(inbuf,smb_vwv3);
1379 uint32 smb_attr = SVAL(inbuf,smb_vwv5);
1380 /* Breakout the oplock request bits so we can set the
1381 reply bits separately. */
1382 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1383 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1384 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1386 int smb_sattr = SVAL(inbuf,smb_vwv4);
1387 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1389 int smb_ofun = SVAL(inbuf,smb_vwv8);
1393 SMB_STRUCT_STAT sbuf;
1395 BOOL bad_path = False;
1398 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
1399 ssize_t retval = -1;
1402 uint32 create_disposition;
1403 uint32 create_options = 0;
1405 START_PROFILE(SMBopenX);
1407 /* If it's an IPC, pass off the pipe handler. */
1409 if (lp_nt_pipe_support()) {
1410 END_PROFILE(SMBopenX);
1411 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1413 END_PROFILE(SMBopenX);
1414 return ERROR_DOS(ERRSRV,ERRaccess);
1418 /* XXXX we need to handle passed times, sattr and flags */
1419 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status, False);
1420 if (!NT_STATUS_IS_OK(status)) {
1421 END_PROFILE(SMBopenX);
1422 return ERROR_NT(status);
1425 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1427 unix_convert(fname,conn,0,&bad_path,&sbuf);
1429 END_PROFILE(SMBopenX);
1430 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1433 if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
1436 &create_disposition,
1438 END_PROFILE(SMBopenX);
1439 return ERROR_DOS(ERRDOS, ERRbadaccess);
1442 fsp = open_file_ntcreate(conn,fname,&sbuf,
1452 END_PROFILE(SMBopenX);
1453 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1454 /* We have re-scheduled this call. */
1457 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1460 size = sbuf.st_size;
1462 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1463 if the file is truncated or created. */
1464 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1465 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1466 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1467 close_file(fsp,False);
1468 END_PROFILE(SMBntcreateX);
1469 return ERROR_NT(NT_STATUS_DISK_FULL);
1471 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1473 close_file(fsp,False);
1474 END_PROFILE(SMBwrite);
1475 return ERROR_NT(NT_STATUS_DISK_FULL);
1477 size = get_allocation_size(conn,fsp,&sbuf);
1480 fattr = dos_mode(conn,fname,&sbuf);
1481 mtime = sbuf.st_mtime;
1483 close_file(fsp,False);
1484 END_PROFILE(SMBopenX);
1485 return ERROR_DOS(ERRDOS,ERRnoaccess);
1488 /* If the caller set the extended oplock request bit
1489 and we granted one (by whatever means) - set the
1490 correct bit for extended oplock reply.
1493 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1494 smb_action |= EXTENDED_OPLOCK_GRANTED;
1497 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1498 smb_action |= EXTENDED_OPLOCK_GRANTED;
1501 /* If the caller set the core oplock request bit
1502 and we granted one (by whatever means) - set the
1503 correct bit for core oplock reply.
1506 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1507 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1510 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1511 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1514 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1515 set_message(outbuf,19,0,True);
1517 set_message(outbuf,15,0,True);
1519 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1520 SSVAL(outbuf,smb_vwv3,fattr);
1521 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1522 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1524 put_dos_date3(outbuf,smb_vwv4,mtime);
1526 SIVAL(outbuf,smb_vwv6,(uint32)size);
1527 SSVAL(outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1528 SSVAL(outbuf,smb_vwv11,smb_action);
1530 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1531 SIVAL(outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1534 END_PROFILE(SMBopenX);
1535 return chain_reply(inbuf,outbuf,length,bufsize);
1538 /****************************************************************************
1539 Reply to a SMBulogoffX.
1540 ****************************************************************************/
1542 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1544 uint16 vuid = SVAL(inbuf,smb_uid);
1545 user_struct *vuser = get_valid_user_struct(vuid);
1546 START_PROFILE(SMBulogoffX);
1549 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1551 /* in user level security we are supposed to close any files
1552 open by this user */
1553 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1554 file_close_user(vuid);
1556 invalidate_vuid(vuid);
1558 set_message(outbuf,2,0,True);
1560 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1562 END_PROFILE(SMBulogoffX);
1563 return chain_reply(inbuf,outbuf,length,bufsize);
1566 /****************************************************************************
1567 Reply to a mknew or a create.
1568 ****************************************************************************/
1570 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1575 uint32 fattr = SVAL(inbuf,smb_vwv0);
1576 BOOL bad_path = False;
1578 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1579 SMB_STRUCT_STAT sbuf;
1581 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1582 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1583 uint32 create_disposition;
1584 uint32 create_options = 0;
1586 START_PROFILE(SMBcreate);
1588 com = SVAL(inbuf,smb_com);
1590 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1591 if (!NT_STATUS_IS_OK(status)) {
1592 END_PROFILE(SMBcreate);
1593 return ERROR_NT(status);
1596 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1598 unix_convert(fname,conn,0,&bad_path,&sbuf);
1600 END_PROFILE(SMBcreate);
1601 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1604 if (fattr & aVOLID) {
1605 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1608 if(com == SMBmknew) {
1609 /* We should fail if file exists. */
1610 create_disposition = FILE_CREATE;
1612 /* Create if file doesn't exist, truncate if it does. */
1613 create_disposition = FILE_OVERWRITE_IF;
1616 /* Open file using ntcreate. */
1617 fsp = open_file_ntcreate(conn,fname,&sbuf,
1627 END_PROFILE(SMBcreate);
1628 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1629 /* We have re-scheduled this call. */
1632 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1635 outsize = set_message(outbuf,1,0,True);
1636 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1638 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1639 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1642 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1643 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1646 DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
1647 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) );
1649 END_PROFILE(SMBcreate);
1653 /****************************************************************************
1654 Reply to a create temporary file.
1655 ****************************************************************************/
1657 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1661 uint32 fattr = SVAL(inbuf,smb_vwv0);
1662 BOOL bad_path = False;
1664 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1666 SMB_STRUCT_STAT sbuf;
1669 unsigned int namelen;
1671 START_PROFILE(SMBctemp);
1673 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1674 if (!NT_STATUS_IS_OK(status)) {
1675 END_PROFILE(SMBctemp);
1676 return ERROR_NT(status);
1679 pstrcat(fname,"/TMXXXXXX");
1681 pstrcat(fname,"TMXXXXXX");
1684 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1686 unix_convert(fname,conn,0,&bad_path,&sbuf);
1688 END_PROFILE(SMBctemp);
1689 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1692 tmpfd = smb_mkstemp(fname);
1694 END_PROFILE(SMBctemp);
1695 return(UNIXERROR(ERRDOS,ERRnoaccess));
1698 SMB_VFS_STAT(conn,fname,&sbuf);
1700 /* We should fail if file does not exist. */
1701 fsp = open_file_ntcreate(conn,fname,&sbuf,
1702 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
1703 FILE_SHARE_READ|FILE_SHARE_WRITE,
1710 /* close fd from smb_mkstemp() */
1714 END_PROFILE(SMBctemp);
1715 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1716 /* We have re-scheduled this call. */
1719 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1722 outsize = set_message(outbuf,1,0,True);
1723 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1725 /* the returned filename is relative to the directory */
1726 s = strrchr_m(fname, '/');
1733 p = smb_buf(outbuf);
1735 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1736 thing in the byte section. JRA */
1737 SSVALS(p, 0, -1); /* what is this? not in spec */
1739 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1741 outsize = set_message_end(outbuf, p);
1743 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1744 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1747 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1748 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1751 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
1752 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
1753 (unsigned int)sbuf.st_mode ) );
1755 END_PROFILE(SMBctemp);
1759 /*******************************************************************
1760 Check if a user is allowed to rename a file.
1761 ********************************************************************/
1763 static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
1768 if (!CAN_WRITE(conn)) {
1769 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1772 fmode = dos_mode(conn,fname,pst);
1773 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1774 return NT_STATUS_NO_SUCH_FILE;
1777 if (S_ISDIR(pst->st_mode)) {
1778 return NT_STATUS_OK;
1781 /* We need a better way to return NT status codes from open... */
1782 set_saved_error_triple(0, 0, NT_STATUS_OK);
1784 fsp = open_file_ntcreate(conn, fname, pst,
1786 FILE_SHARE_READ|FILE_SHARE_WRITE,
1789 FILE_ATTRIBUTE_NORMAL,
1795 if (get_saved_error_triple(NULL, NULL, &ret)) {
1796 set_saved_error_triple(0, 0, NT_STATUS_OK);
1799 set_saved_error_triple(0, 0, NT_STATUS_OK);
1800 return NT_STATUS_ACCESS_DENIED;
1802 close_file(fsp,False);
1803 return NT_STATUS_OK;
1806 /*******************************************************************
1807 Check if a user is allowed to delete a file.
1808 ********************************************************************/
1810 NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL bad_path, BOOL check_is_at_open)
1812 SMB_STRUCT_STAT sbuf;
1816 DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype ));
1818 if (!CAN_WRITE(conn)) {
1819 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1822 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1823 if(errno == ENOENT) {
1825 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1827 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1830 return map_nt_error_from_unix(errno);
1833 fattr = dos_mode(conn,fname,&sbuf);
1835 /* Can't delete a directory. */
1837 return NT_STATUS_FILE_IS_A_DIRECTORY;
1841 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1842 return NT_STATUS_OBJECT_NAME_INVALID;
1843 #endif /* JRATEST */
1845 if (!lp_delete_readonly(SNUM(conn))) {
1846 if (fattr & aRONLY) {
1847 return NT_STATUS_CANNOT_DELETE;
1850 if ((fattr & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1851 return NT_STATUS_NO_SUCH_FILE;
1854 if (check_is_at_open) {
1855 if (!can_delete_file_in_directory(conn, fname)) {
1856 return NT_STATUS_ACCESS_DENIED;
1859 /* On open checks the open itself will check the share mode, so
1860 don't do it here as we'll get it wrong. */
1862 /* We need a better way to return NT status codes from open... */
1863 set_saved_error_triple(0, 0, NT_STATUS_OK);
1865 fsp = open_file_ntcreate(conn, fname, &sbuf,
1870 FILE_ATTRIBUTE_NORMAL,
1876 if (get_saved_error_triple(NULL, NULL, &ret)) {
1877 set_saved_error_triple(0, 0, NT_STATUS_OK);
1880 set_saved_error_triple(0, 0, NT_STATUS_OK);
1881 return NT_STATUS_ACCESS_DENIED;
1883 close_file(fsp,False);
1885 return NT_STATUS_OK;
1888 /****************************************************************************
1889 The guts of the unlink command, split out so it may be called by the NT SMB
1891 ****************************************************************************/
1893 NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name)
1899 NTSTATUS error = NT_STATUS_OK;
1901 BOOL bad_path = False;
1903 SMB_STRUCT_STAT sbuf;
1905 *directory = *mask = 0;
1907 /* We must check for wildcards in the name given
1908 * directly by the client - before any unmangling.
1909 * This prevents an unmangling of a UNIX name containing
1910 * a DOS wildcard like '*' or '?' from unmangling into
1911 * a wildcard delete which was not intended.
1912 * FIX for #226. JRA.
1915 has_wild = ms_has_wild(name);
1917 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1919 p = strrchr_m(name,'/');
1921 pstrcpy(directory,".");
1925 pstrcpy(directory,name);
1930 * We should only check the mangled cache
1931 * here if unix_convert failed. This means
1932 * that the path in 'mask' doesn't exist
1933 * on the file system and so we need to look
1934 * for a possible mangle. This patch from
1935 * Tine Smukavec <valentin.smukavec@hermes.si>.
1938 if (!rc && mangle_is_mangled(mask,SNUM(conn)))
1939 mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
1942 pstrcat(directory,"/");
1943 pstrcat(directory,mask);
1944 error = can_delete(conn,directory,dirtype,bad_path,False);
1945 if (!NT_STATUS_IS_OK(error))
1948 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1952 struct smb_Dir *dir_hnd = NULL;
1955 if (strequal(mask,"????????.???"))
1958 if (check_name(directory,conn))
1959 dir_hnd = OpenDir(conn, directory, mask, dirtype);
1961 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1962 the pattern matches against the long name, otherwise the short name
1963 We don't implement this yet XXXX
1968 error = NT_STATUS_NO_SUCH_FILE;
1970 while ((dname = ReadDirName(dir_hnd, &offset))) {
1973 BOOL sys_direntry = False;
1974 pstrcpy(fname,dname);
1976 if (!is_visible_file(conn, directory, dname, &st, True)) {
1980 /* Quick check for "." and ".." */
1981 if (fname[0] == '.') {
1982 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1983 if ((dirtype & FILE_ATTRIBUTE_DIRECTORY) && (dirtype & FILE_ATTRIBUTE_SYSTEM)) {
1984 sys_direntry = True;
1991 if(!mask_match(fname, mask, conn->case_sensitive))
1995 error = NT_STATUS_OBJECT_NAME_INVALID;
1996 DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n",
2001 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2002 error = can_delete(conn,fname,dirtype,bad_path,False);
2003 if (!NT_STATUS_IS_OK(error)) {
2006 if (SMB_VFS_UNLINK(conn,fname) == 0)
2008 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
2014 if (count == 0 && NT_STATUS_IS_OK(error)) {
2015 error = map_nt_error_from_unix(errno);
2021 /****************************************************************************
2023 ****************************************************************************/
2025 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
2032 START_PROFILE(SMBunlink);
2034 dirtype = SVAL(inbuf,smb_vwv0);
2036 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, True);
2037 if (!NT_STATUS_IS_OK(status)) {
2038 END_PROFILE(SMBunlink);
2039 return ERROR_NT(status);
2042 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
2044 DEBUG(3,("reply_unlink : %s\n",name));
2046 status = unlink_internals(conn, dirtype, name);
2047 if (!NT_STATUS_IS_OK(status)) {
2048 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
2049 /* We have re-scheduled this call. */
2052 return ERROR_NT(status);
2056 * Win2k needs a changenotify request response before it will
2057 * update after a rename..
2059 process_pending_change_notify_queue((time_t)0);
2061 outsize = set_message(outbuf,0,0,True);
2063 END_PROFILE(SMBunlink);
2067 /****************************************************************************
2069 ****************************************************************************/
2071 static void fail_readraw(void)
2074 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2076 exit_server(errstr);
2079 #if defined(WITH_SENDFILE)
2080 /****************************************************************************
2081 Fake (read/write) sendfile. Returns -1 on read or write fail.
2082 ****************************************************************************/
2084 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
2088 /* Paranioa check... */
2089 if (nread > bufsize) {
2094 ret = read_file(fsp,buf,startpos,nread);
2100 /* If we had a short read, fill with zeros. */
2102 memset(buf, '\0', nread - ret);
2105 if (write_data(smbd_server_fd(),buf,nread) != nread) {
2109 return (ssize_t)nread;
2113 /****************************************************************************
2114 Use sendfile in readbraw.
2115 ****************************************************************************/
2117 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
2118 ssize_t mincount, char *outbuf, int out_buffsize)
2122 #if defined(WITH_SENDFILE)
2124 * We can only use sendfile on a non-chained packet
2125 * but we can use on a non-oplocked file. tridge proved this
2126 * on a train in Germany :-). JRA.
2127 * reply_readbraw has already checked the length.
2130 if (chain_size ==0 && (nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) && lp_use_sendfile(SNUM(conn)) ) {
2133 _smb_setlen(outbuf,nread);
2134 header.data = outbuf;
2138 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) {
2139 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2140 if (errno == ENOSYS) {
2141 goto normal_readbraw;
2145 * Special hack for broken Linux with no working sendfile. If we
2146 * return EINTR we sent the header but not the rest of the data.
2147 * Fake this up by doing read/write calls.
2149 if (errno == EINTR) {
2150 /* Ensure we don't do this again. */
2151 set_use_sendfile(SNUM(conn), False);
2152 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2154 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
2155 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2156 fsp->fsp_name, strerror(errno) ));
2157 exit_server("send_file_readbraw fake_sendfile failed");
2162 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2163 fsp->fsp_name, strerror(errno) ));
2164 exit_server("send_file_readbraw sendfile failed");
2174 ret = read_file(fsp,outbuf+4,startpos,nread);
2175 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2184 _smb_setlen(outbuf,ret);
2185 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2189 /****************************************************************************
2190 Reply to a readbraw (core+ protocol).
2191 ****************************************************************************/
2193 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2195 ssize_t maxcount,mincount;
2198 char *header = outbuf;
2200 START_PROFILE(SMBreadbraw);
2202 if (srv_is_signing_active()) {
2203 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2207 * Special check if an oplock break has been issued
2208 * and the readraw request croses on the wire, we must
2209 * return a zero length response here.
2212 if(global_oplock_break) {
2213 _smb_setlen(header,0);
2214 if (write_data(smbd_server_fd(),header,4) != 4)
2216 DEBUG(5,("readbraw - oplock break finished\n"));
2217 END_PROFILE(SMBreadbraw);
2221 fsp = file_fsp(inbuf,smb_vwv0);
2223 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2225 * fsp could be NULL here so use the value from the packet. JRA.
2227 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2228 _smb_setlen(header,0);
2229 if (write_data(smbd_server_fd(),header,4) != 4)
2231 END_PROFILE(SMBreadbraw);
2235 CHECK_FSP(fsp,conn);
2237 flush_write_cache(fsp, READRAW_FLUSH);
2239 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2240 if(CVAL(inbuf,smb_wct) == 10) {
2242 * This is a large offset (64 bit) read.
2244 #ifdef LARGE_SMB_OFF_T
2246 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2248 #else /* !LARGE_SMB_OFF_T */
2251 * Ensure we haven't been sent a >32 bit offset.
2254 if(IVAL(inbuf,smb_vwv8) != 0) {
2255 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2256 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2257 _smb_setlen(header,0);
2258 if (write_data(smbd_server_fd(),header,4) != 4)
2260 END_PROFILE(SMBreadbraw);
2264 #endif /* LARGE_SMB_OFF_T */
2267 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2268 _smb_setlen(header,0);
2269 if (write_data(smbd_server_fd(),header,4) != 4)
2271 END_PROFILE(SMBreadbraw);
2275 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2276 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2278 /* ensure we don't overrun the packet size */
2279 maxcount = MIN(65535,maxcount);
2281 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2285 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2289 if (startpos >= size) {
2292 nread = MIN(maxcount,(size - startpos));
2296 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2297 if (nread < mincount)
2301 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
2302 (int)maxcount, (int)mincount, (int)nread ) );
2304 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2306 DEBUG(5,("readbraw finished\n"));
2307 END_PROFILE(SMBreadbraw);
2312 #define DBGC_CLASS DBGC_LOCKING
2314 /****************************************************************************
2315 Reply to a lockread (core+ protocol).
2316 ****************************************************************************/
2318 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2326 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2327 BOOL my_lock_ctx = False;
2328 START_PROFILE(SMBlockread);
2330 CHECK_FSP(fsp,conn);
2331 if (!CHECK_READ(fsp,inbuf)) {
2332 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2335 release_level_2_oplocks_on_change(fsp);
2337 numtoread = SVAL(inbuf,smb_vwv1);
2338 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2340 outsize = set_message(outbuf,5,3,True);
2341 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2342 data = smb_buf(outbuf) + 3;
2345 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2346 * protocol request that predates the read/write lock concept.
2347 * Thus instead of asking for a read lock here we need to ask
2348 * for a write lock. JRA.
2349 * Note that the requested lock size is unaffected by max_recv.
2352 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
2353 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
2355 if (NT_STATUS_V(status)) {
2358 * We used to make lockread a blocking lock. It turns out
2359 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
2363 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2365 * A blocking lock was requested. Package up
2366 * this smb into a queued request and push it
2367 * onto the blocking lock queue.
2369 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
2370 (SMB_BIG_UINT)numtoread)) {
2371 END_PROFILE(SMBlockread);
2376 END_PROFILE(SMBlockread);
2377 return ERROR_NT(status);
2381 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2384 if (numtoread > max_recv) {
2385 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2386 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2387 (unsigned int)numtoread, (unsigned int)max_recv ));
2388 numtoread = MIN(numtoread,max_recv);
2390 nread = read_file(fsp,data,startpos,numtoread);
2393 END_PROFILE(SMBlockread);
2394 return(UNIXERROR(ERRDOS,ERRnoaccess));
2398 SSVAL(outbuf,smb_vwv0,nread);
2399 SSVAL(outbuf,smb_vwv5,nread+3);
2400 SSVAL(smb_buf(outbuf),1,nread);
2402 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2403 fsp->fnum, (int)numtoread, (int)nread));
2405 END_PROFILE(SMBlockread);
2410 #define DBGC_CLASS DBGC_ALL
2412 /****************************************************************************
2414 ****************************************************************************/
2416 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2423 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2424 START_PROFILE(SMBread);
2426 CHECK_FSP(fsp,conn);
2427 if (!CHECK_READ(fsp,inbuf)) {
2428 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2431 numtoread = SVAL(inbuf,smb_vwv1);
2432 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2434 outsize = set_message(outbuf,5,3,True);
2435 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2437 * The requested read size cannot be greater than max_recv. JRA.
2439 if (numtoread > max_recv) {
2440 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2441 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2442 (unsigned int)numtoread, (unsigned int)max_recv ));
2443 numtoread = MIN(numtoread,max_recv);
2446 data = smb_buf(outbuf) + 3;
2448 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2449 END_PROFILE(SMBread);
2450 return ERROR_DOS(ERRDOS,ERRlock);
2454 nread = read_file(fsp,data,startpos,numtoread);
2457 END_PROFILE(SMBread);
2458 return(UNIXERROR(ERRDOS,ERRnoaccess));
2462 SSVAL(outbuf,smb_vwv0,nread);
2463 SSVAL(outbuf,smb_vwv5,nread+3);
2464 SCVAL(smb_buf(outbuf),0,1);
2465 SSVAL(smb_buf(outbuf),1,nread);
2467 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2468 fsp->fnum, (int)numtoread, (int)nread ) );
2470 END_PROFILE(SMBread);
2474 /****************************************************************************
2475 Reply to a read and X - possibly using sendfile.
2476 ****************************************************************************/
2478 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2479 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2483 char *data = smb_buf(outbuf);
2485 #if defined(WITH_SENDFILE)
2487 * We can only use sendfile on a non-chained packet
2488 * but we can use on a non-oplocked file. tridge proved this
2489 * on a train in Germany :-). JRA.
2492 if (chain_size ==0 && (CVAL(inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) &&
2493 (lp_write_cache_size(SNUM(conn)) == 0) ) {
2494 SMB_STRUCT_STAT sbuf;
2497 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1)
2498 return(UNIXERROR(ERRDOS,ERRnoaccess));
2500 if (startpos > sbuf.st_size)
2503 if (smb_maxcnt > (sbuf.st_size - startpos))
2504 smb_maxcnt = (sbuf.st_size - startpos);
2506 if (smb_maxcnt == 0)
2510 * Set up the packet header before send. We
2511 * assume here the sendfile will work (get the
2512 * correct amount of data).
2515 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2516 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2517 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2518 SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
2519 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2520 SCVAL(outbuf,smb_vwv0,0xFF);
2521 set_message(outbuf,12,smb_maxcnt,False);
2522 header.data = outbuf;
2523 header.length = data - outbuf;
2526 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
2527 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2528 if (errno == ENOSYS) {
2533 * Special hack for broken Linux with no working sendfile. If we
2534 * return EINTR we sent the header but not the rest of the data.
2535 * Fake this up by doing read/write calls.
2538 if (errno == EINTR) {
2539 /* Ensure we don't do this again. */
2540 set_use_sendfile(SNUM(conn), False);
2541 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2543 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2544 len_outbuf - (data-outbuf))) == -1) {
2545 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2546 fsp->fsp_name, strerror(errno) ));
2547 exit_server("send_file_readX: fake_sendfile failed");
2549 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2550 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2551 /* Returning -1 here means successful sendfile. */
2555 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2556 fsp->fsp_name, strerror(errno) ));
2557 exit_server("send_file_readX sendfile failed");
2560 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2561 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2562 /* Returning -1 here means successful sendfile. */
2570 nread = read_file(fsp,data,startpos,smb_maxcnt);
2573 END_PROFILE(SMBreadX);
2574 return(UNIXERROR(ERRDOS,ERRnoaccess));
2577 outsize = set_message(outbuf,12,nread,False);
2578 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2579 SSVAL(outbuf,smb_vwv5,nread);
2580 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2581 SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
2582 SSVAL(smb_buf(outbuf),-2,nread);
2584 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2585 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2587 /* Returning the number of bytes we want to send back - including header. */
2591 /****************************************************************************
2592 Reply to a read and X.
2593 ****************************************************************************/
2595 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2597 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2598 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2600 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2602 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2605 START_PROFILE(SMBreadX);
2607 /* If it's an IPC, pass off the pipe handler. */
2609 END_PROFILE(SMBreadX);
2610 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2613 CHECK_FSP(fsp,conn);
2614 if (!CHECK_READ(fsp,inbuf)) {
2615 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2618 set_message(outbuf,12,0,True);
2620 if (global_client_caps & CAP_LARGE_READX) {
2621 if (SVAL(inbuf,smb_vwv7) == 1) {
2622 smb_maxcnt |= (1<<16);
2624 if (smb_maxcnt > BUFFER_SIZE) {
2625 DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2626 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
2627 END_PROFILE(SMBreadX);
2628 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2632 if(CVAL(inbuf,smb_wct) == 12) {
2633 #ifdef LARGE_SMB_OFF_T
2635 * This is a large offset (64 bit) read.
2637 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2639 #else /* !LARGE_SMB_OFF_T */
2642 * Ensure we haven't been sent a >32 bit offset.
2645 if(IVAL(inbuf,smb_vwv10) != 0) {
2646 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2647 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2648 END_PROFILE(SMBreadX);
2649 return ERROR_DOS(ERRDOS,ERRbadaccess);
2652 #endif /* LARGE_SMB_OFF_T */
2656 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2657 END_PROFILE(SMBreadX);
2658 return ERROR_DOS(ERRDOS,ERRlock);
2661 if (schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
2662 END_PROFILE(SMBreadX);
2666 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2668 nread = chain_reply(inbuf,outbuf,length,bufsize);
2670 END_PROFILE(SMBreadX);
2674 /****************************************************************************
2675 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2676 ****************************************************************************/
2678 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2681 ssize_t total_written=0;
2682 size_t numtowrite=0;
2687 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2689 START_PROFILE(SMBwritebraw);
2691 if (srv_is_signing_active()) {
2692 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2695 CHECK_FSP(fsp,conn);
2696 if (!CHECK_WRITE(fsp)) {
2697 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2700 tcount = IVAL(inbuf,smb_vwv1);
2701 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2702 write_through = BITSETW(inbuf+smb_vwv7,0);
2704 /* We have to deal with slightly different formats depending
2705 on whether we are using the core+ or lanman1.0 protocol */
2707 if(Protocol <= PROTOCOL_COREPLUS) {
2708 numtowrite = SVAL(smb_buf(inbuf),-2);
2709 data = smb_buf(inbuf);
2711 numtowrite = SVAL(inbuf,smb_vwv10);
2712 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2715 /* force the error type */
2716 SCVAL(inbuf,smb_com,SMBwritec);
2717 SCVAL(outbuf,smb_com,SMBwritec);
2719 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2720 END_PROFILE(SMBwritebraw);
2721 return(ERROR_DOS(ERRDOS,ERRlock));
2725 nwritten = write_file(fsp,data,startpos,numtowrite);
2727 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2728 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2730 if (nwritten < (ssize_t)numtowrite) {
2731 END_PROFILE(SMBwritebraw);
2732 return(UNIXERROR(ERRHRD,ERRdiskfull));
2735 total_written = nwritten;
2737 /* Return a message to the redirector to tell it to send more bytes */
2738 SCVAL(outbuf,smb_com,SMBwritebraw);
2739 SSVALS(outbuf,smb_vwv0,-1);
2740 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2742 if (!send_smb(smbd_server_fd(),outbuf))
2743 exit_server("reply_writebraw: send_smb failed.");
2745 /* Now read the raw data into the buffer and write it */
2746 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2747 exit_server("secondary writebraw failed");
2750 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2751 numtowrite = smb_len(inbuf);
2753 /* Set up outbuf to return the correct return */
2754 outsize = set_message(outbuf,1,0,True);
2755 SCVAL(outbuf,smb_com,SMBwritec);
2757 if (numtowrite != 0) {
2759 if (numtowrite > BUFFER_SIZE) {
2760 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2761 (unsigned int)numtowrite ));
2762 exit_server("secondary writebraw failed");
2765 if (tcount > nwritten+numtowrite) {
2766 DEBUG(3,("Client overestimated the write %d %d %d\n",
2767 (int)tcount,(int)nwritten,(int)numtowrite));
2770 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2771 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2773 exit_server("secondary writebraw failed");
2776 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2778 if (nwritten < (ssize_t)numtowrite) {
2779 SCVAL(outbuf,smb_rcls,ERRHRD);
2780 SSVAL(outbuf,smb_err,ERRdiskfull);
2784 total_written += nwritten;
2787 SSVAL(outbuf,smb_vwv0,total_written);
2789 sync_file(conn, fsp, write_through);
2791 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2792 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2794 /* we won't return a status if write through is not selected - this follows what WfWg does */
2795 END_PROFILE(SMBwritebraw);
2796 if (!write_through && total_written==tcount) {
2798 #if RABBIT_PELLET_FIX
2800 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2801 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2803 if (!send_keepalive(smbd_server_fd()))
2804 exit_server("reply_writebraw: send of keepalive failed");
2813 #define DBGC_CLASS DBGC_LOCKING
2815 /****************************************************************************
2816 Reply to a writeunlock (core+).
2817 ****************************************************************************/
2819 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2820 int size, int dum_buffsize)
2822 ssize_t nwritten = -1;
2826 NTSTATUS status = NT_STATUS_OK;
2827 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2829 START_PROFILE(SMBwriteunlock);
2831 CHECK_FSP(fsp,conn);
2832 if (!CHECK_WRITE(fsp)) {
2833 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2836 numtowrite = SVAL(inbuf,smb_vwv1);
2837 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2838 data = smb_buf(inbuf) + 3;
2840 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2841 END_PROFILE(SMBwriteunlock);
2842 return ERROR_DOS(ERRDOS,ERRlock);
2845 /* The special X/Open SMB protocol handling of
2846 zero length writes is *NOT* done for
2848 if(numtowrite == 0) {
2851 nwritten = write_file(fsp,data,startpos,numtowrite);
2854 sync_file(conn, fsp, False /* write through */);
2856 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2857 END_PROFILE(SMBwriteunlock);
2858 return(UNIXERROR(ERRHRD,ERRdiskfull));
2862 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2863 (SMB_BIG_UINT)startpos);
2864 if (NT_STATUS_V(status)) {
2865 END_PROFILE(SMBwriteunlock);
2866 return ERROR_NT(status);
2870 outsize = set_message(outbuf,1,0,True);
2872 SSVAL(outbuf,smb_vwv0,nwritten);
2874 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2875 fsp->fnum, (int)numtowrite, (int)nwritten));
2877 END_PROFILE(SMBwriteunlock);
2882 #define DBGC_CLASS DBGC_ALL
2884 /****************************************************************************
2886 ****************************************************************************/
2888 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2891 ssize_t nwritten = -1;
2894 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2896 START_PROFILE(SMBwrite);
2898 /* If it's an IPC, pass off the pipe handler. */
2900 END_PROFILE(SMBwrite);
2901 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2904 CHECK_FSP(fsp,conn);
2905 if (!CHECK_WRITE(fsp)) {
2906 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2909 numtowrite = SVAL(inbuf,smb_vwv1);
2910 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2911 data = smb_buf(inbuf) + 3;
2913 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2914 END_PROFILE(SMBwrite);
2915 return ERROR_DOS(ERRDOS,ERRlock);
2919 * X/Open SMB protocol says that if smb_vwv1 is
2920 * zero then the file size should be extended or
2921 * truncated to the size given in smb_vwv[2-3].
2924 if(numtowrite == 0) {
2926 * This is actually an allocate call, and set EOF. JRA.
2928 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2930 END_PROFILE(SMBwrite);
2931 return ERROR_NT(NT_STATUS_DISK_FULL);
2933 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2935 END_PROFILE(SMBwrite);
2936 return ERROR_NT(NT_STATUS_DISK_FULL);
2939 nwritten = write_file(fsp,data,startpos,numtowrite);
2941 sync_file(conn, fsp, False);
2943 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2944 END_PROFILE(SMBwrite);
2945 return(UNIXERROR(ERRHRD,ERRdiskfull));
2948 outsize = set_message(outbuf,1,0,True);
2950 SSVAL(outbuf,smb_vwv0,nwritten);
2952 if (nwritten < (ssize_t)numtowrite) {
2953 SCVAL(outbuf,smb_rcls,ERRHRD);
2954 SSVAL(outbuf,smb_err,ERRdiskfull);
2957 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2959 END_PROFILE(SMBwrite);
2963 /****************************************************************************
2964 Reply to a write and X.
2965 ****************************************************************************/
2967 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2969 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2970 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2971 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2972 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2973 ssize_t nwritten = -1;
2974 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2975 unsigned int smblen = smb_len(inbuf);
2977 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2978 START_PROFILE(SMBwriteX);
2980 /* If it's an IPC, pass off the pipe handler. */
2982 END_PROFILE(SMBwriteX);
2983 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2986 CHECK_FSP(fsp,conn);
2987 if (!CHECK_WRITE(fsp)) {
2988 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2991 set_message(outbuf,6,0,True);
2993 /* Deal with possible LARGE_WRITEX */
2995 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2998 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2999 END_PROFILE(SMBwriteX);
3000 return ERROR_DOS(ERRDOS,ERRbadmem);
3003 data = smb_base(inbuf) + smb_doff;
3005 if(CVAL(inbuf,smb_wct) == 14) {
3006 #ifdef LARGE_SMB_OFF_T
3008 * This is a large offset (64 bit) write.
3010 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
3012 #else /* !LARGE_SMB_OFF_T */
3015 * Ensure we haven't been sent a >32 bit offset.
3018 if(IVAL(inbuf,smb_vwv12) != 0) {
3019 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
3020 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
3021 END_PROFILE(SMBwriteX);
3022 return ERROR_DOS(ERRDOS,ERRbadaccess);
3025 #endif /* LARGE_SMB_OFF_T */
3028 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3029 END_PROFILE(SMBwriteX);
3030 return ERROR_DOS(ERRDOS,ERRlock);
3033 /* X/Open SMB protocol says that, unlike SMBwrite
3034 if the length is zero then NO truncation is
3035 done, just a write of zero. To truncate a file,
3038 if(numtowrite == 0) {
3042 if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize,
3043 fsp,data,startpos,numtowrite)) {
3044 END_PROFILE(SMBwriteX);
3048 nwritten = write_file(fsp,data,startpos,numtowrite);
3051 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3052 END_PROFILE(SMBwriteX);
3053 return(UNIXERROR(ERRHRD,ERRdiskfull));
3056 SSVAL(outbuf,smb_vwv2,nwritten);
3058 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
3060 if (nwritten < (ssize_t)numtowrite) {
3061 SCVAL(outbuf,smb_rcls,ERRHRD);
3062 SSVAL(outbuf,smb_err,ERRdiskfull);
3065 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
3066 fsp->fnum, (int)numtowrite, (int)nwritten));
3068 sync_file(conn, fsp, write_through);
3070 END_PROFILE(SMBwriteX);
3071 return chain_reply(inbuf,outbuf,length,bufsize);
3074 /****************************************************************************
3076 ****************************************************************************/
3078 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3084 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3085 START_PROFILE(SMBlseek);
3087 CHECK_FSP(fsp,conn);
3089 flush_write_cache(fsp, SEEK_FLUSH);
3091 mode = SVAL(inbuf,smb_vwv1) & 3;
3092 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3093 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
3102 res = fsp->fh->pos + startpos;
3113 if (umode == SEEK_END) {
3114 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
3115 if(errno == EINVAL) {
3116 SMB_OFF_T current_pos = startpos;
3117 SMB_STRUCT_STAT sbuf;
3119 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3120 END_PROFILE(SMBlseek);
3121 return(UNIXERROR(ERRDOS,ERRnoaccess));
3124 current_pos += sbuf.st_size;
3126 res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
3131 END_PROFILE(SMBlseek);
3132 return(UNIXERROR(ERRDOS,ERRnoaccess));
3138 outsize = set_message(outbuf,2,0,True);
3139 SIVAL(outbuf,smb_vwv0,res);
3141 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3142 fsp->fnum, (double)startpos, (double)res, mode));
3144 END_PROFILE(SMBlseek);
3148 /****************************************************************************
3150 ****************************************************************************/
3152 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3154 int outsize = set_message(outbuf,0,0,True);
3155 uint16 fnum = SVAL(inbuf,smb_vwv0);
3156 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3157 START_PROFILE(SMBflush);
3160 CHECK_FSP(fsp,conn);
3163 file_sync_all(conn);
3165 sync_file(conn,fsp, True);
3168 DEBUG(3,("flush\n"));
3169 END_PROFILE(SMBflush);
3173 /****************************************************************************
3175 ****************************************************************************/
3177 int reply_exit(connection_struct *conn,
3178 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3181 START_PROFILE(SMBexit);
3183 file_close_pid(SVAL(inbuf,smb_pid));
3185 outsize = set_message(outbuf,0,0,True);
3187 DEBUG(3,("exit\n"));
3189 END_PROFILE(SMBexit);
3193 /****************************************************************************
3194 Reply to a close - has to deal with closing a directory opened by NT SMB's.
3195 ****************************************************************************/
3197 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
3202 int32 eclass = 0, err = 0;
3203 files_struct *fsp = NULL;
3204 START_PROFILE(SMBclose);
3206 outsize = set_message(outbuf,0,0,True);
3208 /* If it's an IPC, pass off to the pipe handler. */
3210 END_PROFILE(SMBclose);
3211 return reply_pipe_close(conn, inbuf,outbuf);
3214 fsp = file_fsp(inbuf,smb_vwv0);
3217 * We can only use CHECK_FSP if we know it's not a directory.
3220 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3221 END_PROFILE(SMBclose);
3222 return ERROR_DOS(ERRDOS,ERRbadfid);
3225 if(fsp->is_directory) {
3227 * Special case - close NT SMB directory handle.
3229 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
3230 close_file(fsp,True);
3233 * Close ordinary file.
3238 /* Save the name for time set in close. */
3239 pstrcpy( file_name, fsp->fsp_name);
3241 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3242 fsp->fh->fd, fsp->fnum,
3243 conn->num_files_open));
3246 * Take care of any time sent in the close.
3249 mtime = make_unix_date3(inbuf+smb_vwv1);
3250 fsp_set_pending_modtime(fsp, mtime);
3253 * close_file() returns the unix errno if an error
3254 * was detected on close - normally this is due to
3255 * a disk full error. If not then it was probably an I/O error.
3258 if((close_err = close_file(fsp,True)) != 0) {
3260 END_PROFILE(SMBclose);
3261 return (UNIXERROR(ERRHRD,ERRgeneral));
3265 /* We have a cached error */
3267 END_PROFILE(SMBclose);
3268 return ERROR_DOS(eclass,err);
3271 END_PROFILE(SMBclose);
3275 /****************************************************************************
3276 Reply to a writeclose (Core+ protocol).
3277 ****************************************************************************/
3279 int reply_writeclose(connection_struct *conn,
3280 char *inbuf,char *outbuf, int size, int dum_buffsize)
3283 ssize_t nwritten = -1;
3289 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3290 START_PROFILE(SMBwriteclose);
3292 CHECK_FSP(fsp,conn);
3293 if (!CHECK_WRITE(fsp)) {
3294 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3297 numtowrite = SVAL(inbuf,smb_vwv1);
3298 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3299 mtime = make_unix_date3(inbuf+smb_vwv4);
3300 data = smb_buf(inbuf) + 1;
3302 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3303 END_PROFILE(SMBwriteclose);
3304 return ERROR_DOS(ERRDOS,ERRlock);
3307 nwritten = write_file(fsp,data,startpos,numtowrite);
3309 set_filetime(conn, fsp->fsp_name,mtime);
3312 * More insanity. W2K only closes the file if writelen > 0.
3317 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3319 close_err = close_file(fsp,True);
3322 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3323 fsp->fnum, (int)numtowrite, (int)nwritten,
3324 conn->num_files_open));
3326 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3327 END_PROFILE(SMBwriteclose);
3328 return(UNIXERROR(ERRHRD,ERRdiskfull));
3331 if(close_err != 0) {
3333 END_PROFILE(SMBwriteclose);
3334 return(UNIXERROR(ERRHRD,ERRgeneral));
3337 outsize = set_message(outbuf,1,0,True);
3339 SSVAL(outbuf,smb_vwv0,nwritten);
3340 END_PROFILE(SMBwriteclose);
3345 #define DBGC_CLASS DBGC_LOCKING
3347 /****************************************************************************
3349 ****************************************************************************/
3351 int reply_lock(connection_struct *conn,
3352 char *inbuf,char *outbuf, int length, int dum_buffsize)
3354 int outsize = set_message(outbuf,0,0,True);
3355 SMB_BIG_UINT count,offset;
3357 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3358 BOOL my_lock_ctx = False;
3360 START_PROFILE(SMBlock);
3362 CHECK_FSP(fsp,conn);
3364 release_level_2_oplocks_on_change(fsp);
3366 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3367 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3369 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3370 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
3372 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
3373 if (NT_STATUS_V(status)) {
3375 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
3376 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
3378 * A blocking lock was requested. Package up
3379 * this smb into a queued request and push it
3380 * onto the blocking lock queue.
3382 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
3383 END_PROFILE(SMBlock);
3388 END_PROFILE(SMBlock);
3389 return ERROR_NT(status);
3392 END_PROFILE(SMBlock);
3396 /****************************************************************************
3398 ****************************************************************************/
3400 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3403 int outsize = set_message(outbuf,0,0,True);
3404 SMB_BIG_UINT count,offset;
3406 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3407 START_PROFILE(SMBunlock);
3409 CHECK_FSP(fsp,conn);
3411 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3412 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3414 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
3415 if (NT_STATUS_V(status)) {
3416 END_PROFILE(SMBunlock);
3417 return ERROR_NT(status);
3420 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3421 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
3423 END_PROFILE(SMBunlock);
3428 #define DBGC_CLASS DBGC_ALL
3430 /****************************************************************************
3432 ****************************************************************************/
3434 int reply_tdis(connection_struct *conn,
3435 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3437 int outsize = set_message(outbuf,0,0,True);
3439 START_PROFILE(SMBtdis);
3441 vuid = SVAL(inbuf,smb_uid);
3444 DEBUG(4,("Invalid connection in tdis\n"));
3445 END_PROFILE(SMBtdis);
3446 return ERROR_DOS(ERRSRV,ERRinvnid);
3451 close_cnum(conn,vuid);
3453 END_PROFILE(SMBtdis);
3457 /****************************************************************************
3459 ****************************************************************************/
3461 int reply_echo(connection_struct *conn,
3462 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3464 int smb_reverb = SVAL(inbuf,smb_vwv0);
3466 unsigned int data_len = smb_buflen(inbuf);
3467 int outsize = set_message(outbuf,1,data_len,True);
3468 START_PROFILE(SMBecho);
3470 if (data_len > BUFFER_SIZE) {
3471 DEBUG(0,("reply_echo: data_len too large.\n"));
3472 END_PROFILE(SMBecho);
3476 /* copy any incoming data back out */
3478 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3480 if (smb_reverb > 100) {
3481 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3485 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3486 SSVAL(outbuf,smb_vwv0,seq_num);
3488 smb_setlen(outbuf,outsize - 4);
3491 if (!send_smb(smbd_server_fd(),outbuf))
3492 exit_server("reply_echo: send_smb failed.");
3495 DEBUG(3,("echo %d times\n", smb_reverb));
3499 END_PROFILE(SMBecho);
3503 /****************************************************************************
3504 Reply to a printopen.
3505 ****************************************************************************/
3507 int reply_printopen(connection_struct *conn,
3508 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3512 START_PROFILE(SMBsplopen);
3514 if (!CAN_PRINT(conn)) {
3515 END_PROFILE(SMBsplopen);
3516 return ERROR_DOS(ERRDOS,ERRnoaccess);
3519 /* Open for exclusive use, write only. */
3520 fsp = print_fsp_open(conn, NULL);
3523 END_PROFILE(SMBsplopen);
3524 return(UNIXERROR(ERRDOS,ERRnoaccess));
3527 outsize = set_message(outbuf,1,0,True);
3528 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3530 DEBUG(3,("openprint fd=%d fnum=%d\n",
3531 fsp->fh->fd, fsp->fnum));
3533 END_PROFILE(SMBsplopen);
3537 /****************************************************************************
3538 Reply to a printclose.
3539 ****************************************************************************/
3541 int reply_printclose(connection_struct *conn,
3542 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3544 int outsize = set_message(outbuf,0,0,True);
3545 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3547 START_PROFILE(SMBsplclose);
3549 CHECK_FSP(fsp,conn);
3551 if (!CAN_PRINT(conn)) {
3552 END_PROFILE(SMBsplclose);
3553 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
3556 DEBUG(3,("printclose fd=%d fnum=%d\n",
3557 fsp->fh->fd,fsp->fnum));
3559 close_err = close_file(fsp,True);
3561 if(close_err != 0) {
3563 END_PROFILE(SMBsplclose);
3564 return(UNIXERROR(ERRHRD,ERRgeneral));
3567 END_PROFILE(SMBsplclose);
3571 /****************************************************************************
3572 Reply to a printqueue.
3573 ****************************************************************************/
3575 int reply_printqueue(connection_struct *conn,
3576 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3578 int outsize = set_message(outbuf,2,3,True);
3579 int max_count = SVAL(inbuf,smb_vwv0);
3580 int start_index = SVAL(inbuf,smb_vwv1);
3581 START_PROFILE(SMBsplretq);
3583 /* we used to allow the client to get the cnum wrong, but that
3584 is really quite gross and only worked when there was only
3585 one printer - I think we should now only accept it if they
3586 get it right (tridge) */
3587 if (!CAN_PRINT(conn)) {
3588 END_PROFILE(SMBsplretq);
3589 return ERROR_DOS(ERRDOS,ERRnoaccess);
3592 SSVAL(outbuf,smb_vwv0,0);
3593 SSVAL(outbuf,smb_vwv1,0);
3594 SCVAL(smb_buf(outbuf),0,1);
3595 SSVAL(smb_buf(outbuf),1,0);
3597 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3598 start_index, max_count));
3601 print_queue_struct *queue = NULL;
3602 print_status_struct status;
3603 char *p = smb_buf(outbuf) + 3;
3604 int count = print_queue_status(SNUM(conn), &queue, &status);
3605 int num_to_get = ABS(max_count);
3606 int first = (max_count>0?start_index:start_index+max_count+1);
3612 num_to_get = MIN(num_to_get,count-first);
3615 for (i=first;i<first+num_to_get;i++) {
3616 put_dos_date2(p,0,queue[i].time);
3617 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3618 SSVAL(p,5, queue[i].job);
3619 SIVAL(p,7,queue[i].size);
3621 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3626 outsize = set_message(outbuf,2,28*count+3,False);
3627 SSVAL(outbuf,smb_vwv0,count);
3628 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3629 SCVAL(smb_buf(outbuf),0,1);
3630 SSVAL(smb_buf(outbuf),1,28*count);
3635 DEBUG(3,("%d entries returned in queue\n",count));
3638 END_PROFILE(SMBsplretq);
3642 /****************************************************************************
3643 Reply to a printwrite.
3644 ****************************************************************************/
3646 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3649 int outsize = set_message(outbuf,0,0,True);
3651 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3653 START_PROFILE(SMBsplwr);
3655 if (!CAN_PRINT(conn)) {
3656 END_PROFILE(SMBsplwr);
3657 return ERROR_DOS(ERRDOS,ERRnoaccess);
3660 CHECK_FSP(fsp,conn);
3661 if (!CHECK_WRITE(fsp)) {
3662 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3665 numtowrite = SVAL(smb_buf(inbuf),1);
3666 data = smb_buf(inbuf) + 3;
3668 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3669 END_PROFILE(SMBsplwr);
3670 return(UNIXERROR(ERRHRD,ERRdiskfull));
3673 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3675 END_PROFILE(SMBsplwr);
3679 /****************************************************************************
3680 The guts of the mkdir command, split out so it may be called by the NT SMB
3682 ****************************************************************************/
3684 NTSTATUS mkdir_internal(connection_struct *conn, const pstring directory, BOOL bad_path)
3688 if(!CAN_WRITE(conn)) {
3689 DEBUG(5,("mkdir_internal: failing create on read-only share %s\n", lp_servicename(SNUM(conn))));
3691 return map_nt_error_from_unix(errno);
3695 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3698 if (!check_name(directory, conn)) {
3699 if(errno == ENOENT) {
3701 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3703 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3706 return map_nt_error_from_unix(errno);
3709 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
3711 if(errno == ENOENT) {
3712 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3714 return map_nt_error_from_unix(errno);
3717 return NT_STATUS_OK;
3720 /****************************************************************************
3722 ****************************************************************************/
3724 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3729 BOOL bad_path = False;
3730 SMB_STRUCT_STAT sbuf;
3732 START_PROFILE(SMBmkdir);
3734 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3735 if (!NT_STATUS_IS_OK(status)) {
3736 END_PROFILE(SMBmkdir);
3737 return ERROR_NT(status);
3740 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3742 unix_convert(directory,conn,0,&bad_path,&sbuf);
3744 if( is_ntfs_stream_name(directory)) {
3745 DEBUG(5,("reply_mkdir: failing create on filename %s with colon in name\n", directory));
3746 END_PROFILE(SMBmkdir);
3747 return ERROR_FORCE_DOS(ERRDOS, ERRinvalidname);
3750 status = mkdir_internal(conn, directory,bad_path);
3751 if (!NT_STATUS_IS_OK(status)) {
3752 END_PROFILE(SMBmkdir);
3753 return ERROR_NT(status);
3756 if (lp_inherit_owner(SNUM(conn))) {
3757 /* Ensure we're checking for a symlink here.... */
3758 /* We don't want to get caught by a symlink racer. */
3760 if(SMB_VFS_LSTAT(conn,directory, &sbuf) != 0) {
3761 END_PROFILE(SMBmkdir);
3762 return(UNIXERROR(ERRDOS,ERRnoaccess));
3765 if(!S_ISDIR(sbuf.st_mode)) {
3766 DEBUG(0,("reply_mkdir: %s is not a directory !\n", directory ));
3767 END_PROFILE(SMBmkdir);
3768 return(UNIXERROR(ERRDOS,ERRnoaccess));
3771 change_owner_to_parent(conn, NULL, directory, &sbuf);
3774 outsize = set_message(outbuf,0,0,True);
3776 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3778 END_PROFILE(SMBmkdir);
3782 /****************************************************************************
3783 Static function used by reply_rmdir to delete an entire directory
3784 tree recursively. Return False on ok, True on fail.
3785 ****************************************************************************/
3787 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3789 const char *dname = NULL;
3792 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3797 while((dname = ReadDirName(dir_hnd, &offset))) {
3801 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3804 if (!is_visible_file(conn, directory, dname, &st, False))
3807 /* Construct the full name. */
3808 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3814 pstrcpy(fullname, directory);
3815 pstrcat(fullname, "/");
3816 pstrcat(fullname, dname);
3818 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3823 if(st.st_mode & S_IFDIR) {
3824 if(recursive_rmdir(conn, fullname)!=0) {
3828 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3832 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3841 /****************************************************************************
3842 The internals of the rmdir code - called elsewhere.
3843 ****************************************************************************/
3845 BOOL rmdir_internals(connection_struct *conn, char *directory)
3850 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3851 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3853 * Check to see if the only thing in this directory are
3854 * vetoed files/directories. If so then delete them and
3855 * retry. If we fail to delete any of them (and we *don't*
3856 * do a recursive delete) then fail the rmdir.
3858 BOOL all_veto_files = True;
3860 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3862 if(dir_hnd != NULL) {
3864 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3865 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3867 if (!is_visible_file(conn, directory, dname, &st, False))
3869 if(!IS_VETO_PATH(conn, dname)) {
3870 all_veto_files = False;
3875 if(all_veto_files) {
3876 RewindDir(dir_hnd,&dirpos);
3877 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3880 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3882 if (!is_visible_file(conn, directory, dname, &st, False))
3885 /* Construct the full name. */
3886 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3891 pstrcpy(fullname, directory);
3892 pstrcat(fullname, "/");
3893 pstrcat(fullname, dname);
3895 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3897 if(st.st_mode & S_IFDIR) {
3898 if(lp_recursive_veto_delete(SNUM(conn))) {
3899 if(recursive_rmdir(conn, fullname) != 0)
3902 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3904 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3908 /* Retry the rmdir */
3909 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3919 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3924 /****************************************************************************
3926 ****************************************************************************/
3928 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3933 BOOL bad_path = False;
3934 SMB_STRUCT_STAT sbuf;
3936 START_PROFILE(SMBrmdir);
3938 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3939 if (!NT_STATUS_IS_OK(status)) {
3940 END_PROFILE(SMBrmdir);
3941 return ERROR_NT(status);
3944 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3946 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3948 END_PROFILE(SMBrmdir);
3949 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3952 if (check_name(directory,conn)) {
3953 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3954 ok = rmdir_internals(conn, directory);
3958 END_PROFILE(SMBrmdir);
3959 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3962 outsize = set_message(outbuf,0,0,True);
3964 DEBUG( 3, ( "rmdir %s\n", directory ) );
3966 END_PROFILE(SMBrmdir);
3970 /*******************************************************************
3971 Resolve wildcards in a filename rename.
3972 Note that name is in UNIX charset and thus potentially can be more
3973 than fstring buffer (255 bytes) especially in default UTF-8 case.
3974 Therefore, we use pstring inside and all calls should ensure that
3975 name2 is at least pstring-long (they do already)
3976 ********************************************************************/
3978 static BOOL resolve_wildcards(const char *name1, char *name2)
3980 pstring root1,root2;
3982 char *p,*p2, *pname1, *pname2;
3983 int available_space, actual_space;
3986 pname1 = strrchr_m(name1,'/');
3987 pname2 = strrchr_m(name2,'/');
3989 if (!pname1 || !pname2)
3992 pstrcpy(root1,pname1);
3993 pstrcpy(root2,pname2);
3994 p = strrchr_m(root1,'.');
4001 p = strrchr_m(root2,'.');
4015 } else if (*p2 == '*') {
4031 } else if (*p2 == '*') {
4041 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
4044 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
4045 if (actual_space >= available_space - 1) {
4046 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
4047 actual_space - available_space));
4050 pstrcpy_base(pname2, root2, name2);
4056 /****************************************************************************
4057 Ensure open files have their names updates.
4058 ****************************************************************************/
4060 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
4063 BOOL did_rename = False;
4065 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
4066 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
4067 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
4068 fsp->fsp_name, newname ));
4069 string_set(&fsp->fsp_name, newname);
4074 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
4075 (unsigned int)dev, (double)inode, newname ));
4078 /****************************************************************************
4079 We need to check if the source path is a parent directory of the destination
4080 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
4081 refuse the rename with a sharing violation. Under UNIX the above call can
4082 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
4083 probably need to check that the client is a Windows one before disallowing
4084 this as a UNIX client (one with UNIX extensions) can know the source is a
4085 symlink and make this decision intelligently. Found by an excellent bug
4086 report from <AndyLiebman@aol.com>.
4087 ****************************************************************************/
4089 static BOOL rename_path_prefix_equal(const char *src, const char *dest)
4091 const char *psrc = src;
4092 const char *pdst = dest;
4095 if (psrc[0] == '.' && psrc[1] == '/') {
4098 if (pdst[0] == '.' && pdst[1] == '/') {
4101 if ((slen = strlen(psrc)) > strlen(pdst)) {
4104 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
4107 /****************************************************************************
4108 Rename an open file - given an fsp.
4109 ****************************************************************************/
4111 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint32 attrs, BOOL replace_if_exists)
4113 SMB_STRUCT_STAT sbuf;
4114 BOOL bad_path = False;
4115 pstring newname_last_component;
4116 NTSTATUS error = NT_STATUS_OK;
4121 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
4123 /* Quick check for "." and ".." */
4124 if (!bad_path && newname_last_component[0] == '.') {
4125 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
4126 return NT_STATUS_ACCESS_DENIED;
4129 if (!rcdest && bad_path) {
4130 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4133 /* Ensure newname contains a '/' */
4134 if(strrchr_m(newname,'/') == 0) {
4137 pstrcpy(tmpstr, "./");
4138 pstrcat(tmpstr, newname);
4139 pstrcpy(newname, tmpstr);
4143 * Check for special case with case preserving and not
4144 * case sensitive. If the old last component differs from the original
4145 * last component only by case, then we should allow
4146 * the rename (user is trying to change the case of the
4150 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
4151 strequal(newname, fsp->fsp_name)) {
4153 pstring newname_modified_last_component;
4156 * Get the last component of the modified name.
4157 * Note that we guarantee that newname contains a '/'
4160 p = strrchr_m(newname,'/');
4161 pstrcpy(newname_modified_last_component,p+1);
4163 if(strcsequal(newname_modified_last_component,
4164 newname_last_component) == False) {
4166 * Replace the modified last component with
4169 pstrcpy(p+1, newname_last_component);
4174 * If the src and dest names are identical - including case,
4175 * don't do the rename, just return success.
4178 if (strcsequal(fsp->fsp_name, newname)) {
4179 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4181 return NT_STATUS_OK;
4184 dest_exists = vfs_object_exist(conn,newname,NULL);
4186 if(!replace_if_exists && dest_exists) {
4187 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4188 fsp->fsp_name,newname));
4189 return NT_STATUS_OBJECT_NAME_COLLISION;
4192 error = can_rename(conn,newname,attrs,&sbuf);
4194 if (dest_exists && !NT_STATUS_IS_OK(error)) {
4195 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4196 nt_errstr(error), fsp->fsp_name,newname));
4197 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
4198 error = NT_STATUS_ACCESS_DENIED;
4202 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
4203 return NT_STATUS_ACCESS_DENIED;
4206 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
4207 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4208 fsp->fsp_name,newname));
4209 rename_open_files(conn, fsp->dev, fsp->inode, newname);
4210 return NT_STATUS_OK;
4213 if (errno == ENOTDIR || errno == EISDIR)
4214 error = NT_STATUS_OBJECT_NAME_COLLISION;
4216 error = map_nt_error_from_unix(errno);
4218 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4219 nt_errstr(error), fsp->fsp_name,newname));
4224 /****************************************************************************
4225 The guts of the rename command, split out so it may be called by the NT SMB
4227 ****************************************************************************/
4229 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint32 attrs, BOOL replace_if_exists)
4233 pstring last_component_src;
4234 pstring last_component_dest;
4237 BOOL bad_path_src = False;
4238 BOOL bad_path_dest = False;
4240 NTSTATUS error = NT_STATUS_OK;
4243 SMB_STRUCT_STAT sbuf1, sbuf2;
4245 *directory = *mask = 0;
4250 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
4251 if (!rc && bad_path_src) {
4252 if (ms_has_wild(last_component_src))
4253 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4254 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4257 /* Quick check for "." and ".." */
4258 if (last_component_src[0] == '.') {
4259 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
4260 return NT_STATUS_OBJECT_NAME_INVALID;
4264 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
4266 /* Quick check for "." and ".." */
4267 if (last_component_dest[0] == '.') {
4268 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
4269 return NT_STATUS_OBJECT_NAME_INVALID;
4274 * Split the old name into directory and last component
4275 * strings. Note that unix_convert may have stripped off a
4276 * leading ./ from both name and newname if the rename is
4277 * at the root of the share. We need to make sure either both
4278 * name and newname contain a / character or neither of them do
4279 * as this is checked in resolve_wildcards().
4282 p = strrchr_m(name,'/');
4284 pstrcpy(directory,".");
4288 pstrcpy(directory,name);
4290 *p = '/'; /* Replace needed for exceptional test below. */
4294 * We should only check the mangled cache
4295 * here if unix_convert failed. This means
4296 * that the path in 'mask' doesn't exist
4297 * on the file system and so we need to look
4298 * for a possible mangle. This patch from
4299 * Tine Smukavec <valentin.smukavec@hermes.si>.
4302 if (!rc && mangle_is_mangled(mask,SNUM(conn)))
4303 mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
4305 has_wild = ms_has_wild(mask);
4309 * No wildcards - just process the one file.
4311 BOOL is_short_name = mangle_is_8_3(name, True, SNUM(conn));
4313 /* Add a terminating '/' to the directory name. */
4314 pstrcat(directory,"/");
4315 pstrcat(directory,mask);
4317 /* Ensure newname contains a '/' also */
4318 if(strrchr_m(newname,'/') == 0) {
4321 pstrcpy(tmpstr, "./");
4322 pstrcat(tmpstr, newname);
4323 pstrcpy(newname, tmpstr);
4326 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
4327 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
4328 conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory,
4329 newname, last_component_dest, is_short_name));
4332 * Check for special case with case preserving and not
4333 * case sensitive, if directory and newname are identical,
4334 * and the old last component differs from the original
4335 * last component only by case, then we should allow
4336 * the rename (user is trying to change the case of the
4339 if((conn->case_sensitive == False) &&
4340 (((conn->case_preserve == True) &&
4341 (is_short_name == False)) ||
4342 ((conn->short_case_preserve == True) &&
4343 (is_short_name == True))) &&
4344 strcsequal(directory, newname)) {
4345 pstring modified_last_component;
4348 * Get the last component of the modified name.
4349 * Note that we guarantee that newname contains a '/'
4352 p = strrchr_m(newname,'/');
4353 pstrcpy(modified_last_component,p+1);
4355 if(strcsequal(modified_last_component,
4356 last_component_dest) == False) {
4358 * Replace the modified last component with
4361 pstrcpy(p+1, last_component_dest);
4365 resolve_wildcards(directory,newname);
4368 * The source object must exist.
4371 if (!vfs_object_exist(conn, directory, &sbuf1)) {
4372 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
4373 directory,newname));
4375 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
4377 * Must return different errors depending on whether the parent
4378 * directory existed or not.
4381 p = strrchr_m(directory, '/');
4383 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4385 if (vfs_object_exist(conn, directory, NULL))
4386 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4387 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4389 error = map_nt_error_from_unix(errno);
4390 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4391 nt_errstr(error), directory,newname));
4396 if (!rcdest && bad_path_dest) {
4397 if (ms_has_wild(last_component_dest))
4398 return NT_STATUS_OBJECT_NAME_INVALID;
4399 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4402 error = can_rename(conn,directory,attrs,&sbuf1);
4404 if (!NT_STATUS_IS_OK(error)) {
4405 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4406 nt_errstr(error), directory,newname));
4411 * If the src and dest names are identical - including case,
4412 * don't do the rename, just return success.
4415 if (strcsequal(directory, newname)) {
4416 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4417 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
4418 return NT_STATUS_OK;
4421 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
4422 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
4423 directory,newname));
4424 return NT_STATUS_OBJECT_NAME_COLLISION;
4427 if (rename_path_prefix_equal(directory, newname)) {
4428 return NT_STATUS_SHARING_VIOLATION;
4431 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
4432 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
4433 directory,newname));
4434 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4435 return NT_STATUS_OK;
4438 if (errno == ENOTDIR || errno == EISDIR)
4439 error = NT_STATUS_OBJECT_NAME_COLLISION;
4441 error = map_nt_error_from_unix(errno);
4443 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4444 nt_errstr(error), directory,newname));
4449 * Wildcards - process each file that matches.
4451 struct smb_Dir *dir_hnd = NULL;
4455 if (strequal(mask,"????????.???"))
4458 if (check_name(directory,conn))
4459 dir_hnd = OpenDir(conn, directory, mask, attrs);
4463 error = NT_STATUS_NO_SUCH_FILE;
4464 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
4466 while ((dname = ReadDirName(dir_hnd, &offset))) {
4468 BOOL sysdir_entry = False;
4470 pstrcpy(fname,dname);
4472 /* Quick check for "." and ".." */
4473 if (fname[0] == '.') {
4474 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4476 sysdir_entry = True;
4483 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4486 if(!mask_match(fname, mask, conn->case_sensitive))
4490 error = NT_STATUS_OBJECT_NAME_INVALID;
4494 error = NT_STATUS_ACCESS_DENIED;
4495 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
4496 if (!vfs_object_exist(conn, fname, &sbuf1)) {
4497 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4498 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
4501 error = can_rename(conn,fname,attrs,&sbuf1);
4502 if (!NT_STATUS_IS_OK(error)) {
4503 DEBUG(6,("rename %s refused\n", fname));
4506 pstrcpy(destname,newname);
4508 if (!resolve_wildcards(fname,destname)) {
4509 DEBUG(6,("resolve_wildcards %s %s failed\n",
4514 if (strcsequal(fname,destname)) {
4515 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4516 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
4518 error = NT_STATUS_OK;
4522 if (!replace_if_exists &&
4523 vfs_file_exist(conn,destname, NULL)) {
4524 DEBUG(6,("file_exist %s\n", destname));
4525 error = NT_STATUS_OBJECT_NAME_COLLISION;
4529 if (rename_path_prefix_equal(fname, destname)) {
4530 return NT_STATUS_SHARING_VIOLATION;
4533 if (!SMB_VFS_RENAME(conn,fname,destname)) {
4534 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4536 error = NT_STATUS_OK;
4538 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
4543 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
4544 if (!rcdest && bad_path_dest) {
4545 if (ms_has_wild(last_component_dest))
4546 return NT_STATUS_OBJECT_NAME_INVALID;
4547 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4552 if (count == 0 && NT_STATUS_IS_OK(error)) {
4553 error = map_nt_error_from_unix(errno);
4559 /****************************************************************************
4561 ****************************************************************************/
4563 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4570 uint32 attrs = SVAL(inbuf,smb_vwv0);
4573 START_PROFILE(SMBmv);
4575 p = smb_buf(inbuf) + 1;
4576 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4577 if (!NT_STATUS_IS_OK(status)) {
4579 return ERROR_NT(status);
4582 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4583 if (!NT_STATUS_IS_OK(status)) {
4585 return ERROR_NT(status);
4588 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4589 RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4591 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4593 status = rename_internals(conn, name, newname, attrs, False);
4594 if (!NT_STATUS_IS_OK(status)) {
4596 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4597 /* We have re-scheduled this call. */
4600 return ERROR_NT(status);
4604 * Win2k needs a changenotify request response before it will
4605 * update after a rename..
4607 process_pending_change_notify_queue((time_t)0);
4608 outsize = set_message(outbuf,0,0,True);
4614 /*******************************************************************
4615 Copy a file as part of a reply_copy.
4616 ******************************************************************/
4618 BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4619 int count,BOOL target_is_directory, int *err_ret)
4621 SMB_STRUCT_STAT src_sbuf, sbuf2;
4623 files_struct *fsp1,*fsp2;
4626 uint32 new_create_disposition;
4630 pstrcpy(dest,dest1);
4631 if (target_is_directory) {
4632 char *p = strrchr_m(src,'/');
4642 if (!vfs_file_exist(conn,src,&src_sbuf)) {
4646 if (!target_is_directory && count) {
4647 new_create_disposition = FILE_OPEN;
4649 if (!map_open_params_to_ntcreate(dest1,0,ofun,
4650 NULL, NULL, &new_create_disposition, NULL)) {
4655 fsp1 = open_file_ntcreate(conn,src,&src_sbuf,
4657 FILE_SHARE_READ|FILE_SHARE_WRITE,
4660 FILE_ATTRIBUTE_NORMAL,
4668 dosattrs = dos_mode(conn, src, &src_sbuf);
4669 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
4670 ZERO_STRUCTP(&sbuf2);
4673 fsp2 = open_file_ntcreate(conn,dest,&sbuf2,
4675 FILE_SHARE_READ|FILE_SHARE_WRITE,
4676 new_create_disposition,
4683 close_file(fsp1,False);
4687 if ((ofun&3) == 1) {
4688 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
4689 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4691 * Stop the copy from occurring.
4694 src_sbuf.st_size = 0;
4698 if (src_sbuf.st_size) {
4699 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4702 close_file(fsp1,False);
4704 /* Ensure the modtime is set correctly on the destination file. */
4705 fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime);
4708 * As we are opening fsp1 read-only we only expect
4709 * an error on close on fsp2 if we are out of space.
4710 * Thus we don't look at the error return from the
4713 *err_ret = close_file(fsp2,False);
4715 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4718 /****************************************************************************
4719 Reply to a file copy.
4720 ****************************************************************************/
4722 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4727 pstring mask,newname;
4730 int error = ERRnoaccess;
4734 int tid2 = SVAL(inbuf,smb_vwv0);
4735 int ofun = SVAL(inbuf,smb_vwv1);
4736 int flags = SVAL(inbuf,smb_vwv2);
4737 BOOL target_is_directory=False;
4738 BOOL bad_path1 = False;
4739 BOOL bad_path2 = False;
4741 SMB_STRUCT_STAT sbuf1, sbuf2;
4744 START_PROFILE(SMBcopy);
4746 *directory = *mask = 0;
4749 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4750 if (!NT_STATUS_IS_OK(status)) {
4751 END_PROFILE(SMBcopy);
4752 return ERROR_NT(status);
4754 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4755 if (!NT_STATUS_IS_OK(status)) {
4756 END_PROFILE(SMBcopy);
4757 return ERROR_NT(status);
4760 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4762 if (tid2 != conn->cnum) {
4763 /* can't currently handle inter share copies XXXX */
4764 DEBUG(3,("Rejecting inter-share copy\n"));
4765 END_PROFILE(SMBcopy);
4766 return ERROR_DOS(ERRSRV,ERRinvdevice);
4769 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4770 RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4772 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4773 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4775 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4777 if ((flags&1) && target_is_directory) {
4778 END_PROFILE(SMBcopy);
4779 return ERROR_DOS(ERRDOS,ERRbadfile);
4782 if ((flags&2) && !target_is_directory) {
4783 END_PROFILE(SMBcopy);
4784 return ERROR_DOS(ERRDOS,ERRbadpath);
4787 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4788 /* wants a tree copy! XXXX */
4789 DEBUG(3,("Rejecting tree copy\n"));
4790 END_PROFILE(SMBcopy);
4791 return ERROR_DOS(ERRSRV,ERRerror);
4794 p = strrchr_m(name,'/');
4796 pstrcpy(directory,"./");
4800 pstrcpy(directory,name);
4805 * We should only check the mangled cache
4806 * here if unix_convert failed. This means
4807 * that the path in 'mask' doesn't exist
4808 * on the file system and so we need to look
4809 * for a possible mangle. This patch from
4810 * Tine Smukavec <valentin.smukavec@hermes.si>.
4813 if (!rc && mangle_is_mangled(mask, SNUM(conn)))
4814 mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
4816 has_wild = ms_has_wild(mask);
4819 pstrcat(directory,"/");
4820 pstrcat(directory,mask);
4821 if (resolve_wildcards(directory,newname) &&
4822 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4826 END_PROFILE(SMBcopy);
4827 return(UNIXERROR(ERRHRD,ERRgeneral));
4830 exists = vfs_file_exist(conn,directory,NULL);
4833 struct smb_Dir *dir_hnd = NULL;
4837 if (strequal(mask,"????????.???"))
4840 if (check_name(directory,conn))
4841 dir_hnd = OpenDir(conn, directory, mask, 0);
4847 while ((dname = ReadDirName(dir_hnd, &offset))) {
4849 pstrcpy(fname,dname);
4851 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4854 if(!mask_match(fname, mask, conn->case_sensitive))
4857 error = ERRnoaccess;
4858 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4859 pstrcpy(destname,newname);
4860 if (resolve_wildcards(fname,destname) &&
4861 copy_file(fname,destname,conn,ofun,
4862 count,target_is_directory,&err))
4864 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4872 /* Error on close... */
4874 END_PROFILE(SMBcopy);
4875 return(UNIXERROR(ERRHRD,ERRgeneral));
4879 END_PROFILE(SMBcopy);
4880 return ERROR_DOS(ERRDOS,error);
4882 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4883 set_saved_error_triple(ERRDOS, ERRbadpath, NT_STATUS_OK);
4885 END_PROFILE(SMBcopy);
4886 return(UNIXERROR(ERRDOS,error));
4890 outsize = set_message(outbuf,1,0,True);
4891 SSVAL(outbuf,smb_vwv0,count);
4893 END_PROFILE(SMBcopy);
4897 /****************************************************************************
4899 ****************************************************************************/
4901 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4909 START_PROFILE(pathworks_setdir);
4912 if (!CAN_SETDIR(snum)) {
4913 END_PROFILE(pathworks_setdir);
4914 return ERROR_DOS(ERRDOS,ERRnoaccess);
4917 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False);
4918 if (!NT_STATUS_IS_OK(status)) {
4919 END_PROFILE(pathworks_setdir);
4920 return ERROR_NT(status);
4923 RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf);
4925 if (strlen(newdir) == 0) {
4928 ok = vfs_directory_exist(conn,newdir,NULL);
4930 string_set(&conn->connectpath,newdir);
4934 END_PROFILE(pathworks_setdir);
4935 return ERROR_DOS(ERRDOS,ERRbadpath);
4938 outsize = set_message(outbuf,0,0,True);
4939 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4941 DEBUG(3,("setdir %s\n", newdir));
4943 END_PROFILE(pathworks_setdir);
4948 #define DBGC_CLASS DBGC_LOCKING
4950 /****************************************************************************
4951 Get a lock pid, dealing with large count requests.
4952 ****************************************************************************/
4954 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4956 if(!large_file_format)
4957 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4959 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4962 /****************************************************************************
4963 Get a lock count, dealing with large count requests.
4964 ****************************************************************************/
4966 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4968 SMB_BIG_UINT count = 0;
4970 if(!large_file_format) {
4971 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4974 #if defined(HAVE_LONGLONG)
4975 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4976 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4977 #else /* HAVE_LONGLONG */
4980 * NT4.x seems to be broken in that it sends large file (64 bit)
4981 * lockingX calls even if the CAP_LARGE_FILES was *not*
4982 * negotiated. For boxes without large unsigned ints truncate the
4983 * lock count by dropping the top 32 bits.
4986 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4987 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4988 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4989 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4990 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4993 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4994 #endif /* HAVE_LONGLONG */
5000 #if !defined(HAVE_LONGLONG)
5001 /****************************************************************************
5002 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
5003 ****************************************************************************/
5005 static uint32 map_lock_offset(uint32 high, uint32 low)
5009 uint32 highcopy = high;
5012 * Try and find out how many significant bits there are in high.
5015 for(i = 0; highcopy; i++)
5019 * We use 31 bits not 32 here as POSIX
5020 * lock offsets may not be negative.
5023 mask = (~0) << (31 - i);
5026 return 0; /* Fail. */
5032 #endif /* !defined(HAVE_LONGLONG) */
5034 /****************************************************************************
5035 Get a lock offset, dealing with large offset requests.
5036 ****************************************************************************/
5038 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
5040 SMB_BIG_UINT offset = 0;
5044 if(!large_file_format) {
5045 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
5048 #if defined(HAVE_LONGLONG)
5049 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
5050 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
5051 #else /* HAVE_LONGLONG */
5054 * NT4.x seems to be broken in that it sends large file (64 bit)
5055 * lockingX calls even if the CAP_LARGE_FILES was *not*
5056 * negotiated. For boxes without large unsigned ints mangle the
5057 * lock offset by mapping the top 32 bits onto the lower 32.
5060 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
5061 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5062 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
5065 if((new_low = map_lock_offset(high, low)) == 0) {
5067 return (SMB_BIG_UINT)-1;
5070 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
5071 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
5072 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
5073 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
5076 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5077 #endif /* HAVE_LONGLONG */
5083 /****************************************************************************
5084 Reply to a lockingX request.
5085 ****************************************************************************/
5087 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5089 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
5090 unsigned char locktype = CVAL(inbuf,smb_vwv3);
5091 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
5092 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
5093 uint16 num_locks = SVAL(inbuf,smb_vwv7);
5094 SMB_BIG_UINT count = 0, offset = 0;
5096 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
5099 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
5101 BOOL my_lock_ctx = False;
5104 START_PROFILE(SMBlockingX);
5106 CHECK_FSP(fsp,conn);
5108 data = smb_buf(inbuf);
5110 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
5111 /* we don't support these - and CANCEL_LOCK makes w2k
5112 and XP reboot so I don't really want to be
5113 compatible! (tridge) */
5114 return ERROR_DOS(ERRDOS, ERRnoatomiclocks);
5117 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
5118 /* Need to make this like a cancel.... JRA. */
5119 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
5122 /* Check if this is an oplock break on a file
5123 we have granted an oplock on.
5125 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
5126 /* Client can insist on breaking to none. */
5127 BOOL break_to_none = (oplocklevel == 0);
5129 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
5130 (unsigned int)oplocklevel, fsp->fnum ));
5133 * Make sure we have granted an exclusive or batch oplock on this file.
5136 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5137 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
5138 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
5140 /* if this is a pure oplock break request then don't send a reply */
5141 if (num_locks == 0 && num_ulocks == 0) {
5142 END_PROFILE(SMBlockingX);
5145 END_PROFILE(SMBlockingX);
5146 return ERROR_DOS(ERRDOS,ERRlock);
5150 if (remove_oplock(fsp, break_to_none) == False) {
5151 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
5155 /* if this is a pure oplock break request then don't send a reply */
5156 if (num_locks == 0 && num_ulocks == 0) {
5157 /* Sanity check - ensure a pure oplock break is not a
5159 if(CVAL(inbuf,smb_vwv0) != 0xff)
5160 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
5161 (unsigned int)CVAL(inbuf,smb_vwv0) ));
5162 END_PROFILE(SMBlockingX);
5168 * We do this check *after* we have checked this is not a oplock break
5169 * response message. JRA.
5172 release_level_2_oplocks_on_change(fsp);
5174 /* Data now points at the beginning of the list
5175 of smb_unlkrng structs */
5176 for(i = 0; i < (int)num_ulocks; i++) {
5177 lock_pid = get_lock_pid( data, i, large_file_format);
5178 count = get_lock_count( data, i, large_file_format);
5179 offset = get_lock_offset( data, i, large_file_format, &err);
5182 * There is no error code marked "stupid client bug".... :-).
5185 END_PROFILE(SMBlockingX);
5186 return ERROR_DOS(ERRDOS,ERRnoaccess);
5189 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
5190 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
5192 status = do_unlock(fsp,conn,lock_pid,count,offset);
5193 if (NT_STATUS_V(status)) {
5194 END_PROFILE(SMBlockingX);
5195 return ERROR_NT(status);
5199 /* Setup the timeout in seconds. */
5201 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
5203 /* Now do any requested locks */
5204 data += ((large_file_format ? 20 : 10)*num_ulocks);
5206 /* Data now points at the beginning of the list
5207 of smb_lkrng structs */
5209 for(i = 0; i < (int)num_locks; i++) {
5210 lock_pid = get_lock_pid( data, i, large_file_format);
5211 count = get_lock_count( data, i, large_file_format);
5212 offset = get_lock_offset( data, i, large_file_format, &err);
5215 * There is no error code marked "stupid client bug".... :-).
5218 END_PROFILE(SMBlockingX);
5219 return ERROR_DOS(ERRDOS,ERRnoaccess);
5222 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
5223 (double)offset, (double)count, (unsigned int)lock_pid,
5224 fsp->fsp_name, (int)lock_timeout ));
5226 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
5227 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
5228 if (NT_STATUS_V(status)) {
5230 * Interesting fact found by IFSTEST /t LockOverlappedTest...
5231 * Even if it's our own lock context, we need to wait here as
5232 * there may be an unlock on the way.
5233 * So I removed a "&& !my_lock_ctx" from the following
5234 * if statement. JRA.
5236 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
5238 * A blocking lock was requested. Package up
5239 * this smb into a queued request and push it
5240 * onto the blocking lock queue.
5242 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
5243 END_PROFILE(SMBlockingX);
5251 /* If any of the above locks failed, then we must unlock
5252 all of the previous locks (X/Open spec). */
5253 if (i != num_locks && num_locks != 0) {
5255 * Ensure we don't do a remove on the lock that just failed,
5256 * as under POSIX rules, if we have a lock already there, we
5257 * will delete it (and we shouldn't) .....
5259 for(i--; i >= 0; i--) {
5260 lock_pid = get_lock_pid( data, i, large_file_format);
5261 count = get_lock_count( data, i, large_file_format);
5262 offset = get_lock_offset( data, i, large_file_format, &err);
5265 * There is no error code marked "stupid client bug".... :-).
5268 END_PROFILE(SMBlockingX);
5269 return ERROR_DOS(ERRDOS,ERRnoaccess);
5272 do_unlock(fsp,conn,lock_pid,count,offset);
5274 END_PROFILE(SMBlockingX);
5275 return ERROR_NT(status);
5278 set_message(outbuf,2,0,True);
5280 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5281 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
5283 END_PROFILE(SMBlockingX);
5284 return chain_reply(inbuf,outbuf,length,bufsize);
5288 #define DBGC_CLASS DBGC_ALL
5290 /****************************************************************************
5291 Reply to a SMBreadbmpx (read block multiplex) request.
5292 ****************************************************************************/
5294 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5305 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5306 START_PROFILE(SMBreadBmpx);
5308 /* this function doesn't seem to work - disable by default */
5309 if (!lp_readbmpx()) {
5310 END_PROFILE(SMBreadBmpx);
5311 return ERROR_DOS(ERRSRV,ERRuseSTD);
5314 outsize = set_message(outbuf,8,0,True);
5316 CHECK_FSP(fsp,conn);
5317 if (!CHECK_READ(fsp,inbuf)) {
5318 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5321 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5322 maxcount = SVAL(inbuf,smb_vwv3);
5324 data = smb_buf(outbuf);
5325 pad = ((long)data)%4;
5330 max_per_packet = bufsize-(outsize+pad);
5334 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5335 END_PROFILE(SMBreadBmpx);
5336 return ERROR_DOS(ERRDOS,ERRlock);
5340 size_t N = MIN(max_per_packet,tcount-total_read);
5342 nread = read_file(fsp,data,startpos,N);
5347 if (nread < (ssize_t)N)
5348 tcount = total_read + nread;
5350 set_message(outbuf,8,nread+pad,False);
5351 SIVAL(outbuf,smb_vwv0,startpos);
5352 SSVAL(outbuf,smb_vwv2,tcount);
5353 SSVAL(outbuf,smb_vwv6,nread);
5354 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5357 if (!send_smb(smbd_server_fd(),outbuf))
5358 exit_server("reply_readbmpx: send_smb failed.");
5360 total_read += nread;
5362 } while (total_read < (ssize_t)tcount);
5364 END_PROFILE(SMBreadBmpx);
5368 /****************************************************************************
5369 Reply to a SMBsetattrE.
5370 ****************************************************************************/
5372 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5374 struct utimbuf unix_times;
5376 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5377 START_PROFILE(SMBsetattrE);
5379 outsize = set_message(outbuf,0,0,True);
5381 if(!fsp || (fsp->conn != conn)) {
5382 END_PROFILE(SMBgetattrE);
5383 return ERROR_DOS(ERRDOS,ERRbadfid);
5387 * Convert the DOS times into unix times. Ignore create
5388 * time as UNIX can't set this.
5391 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
5392 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
5395 * Patch from Ray Frush <frush@engr.colostate.edu>
5396 * Sometimes times are sent as zero - ignore them.
5399 if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5400 /* Ignore request */
5401 if( DEBUGLVL( 3 ) ) {
5402 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5403 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5405 END_PROFILE(SMBsetattrE);
5407 } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5408 /* set modify time = to access time if modify time was unset */
5409 unix_times.modtime = unix_times.actime;
5412 /* Set the date on this file */
5413 /* Should we set pending modtime here ? JRA */
5414 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
5415 END_PROFILE(SMBsetattrE);
5416 return ERROR_DOS(ERRDOS,ERRnoaccess);
5419 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
5420 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
5422 END_PROFILE(SMBsetattrE);
5427 /* Back from the dead for OS/2..... JRA. */
5429 /****************************************************************************
5430 Reply to a SMBwritebmpx (write block multiplex primary) request.
5431 ****************************************************************************/
5433 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5436 ssize_t nwritten = -1;
5443 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5444 START_PROFILE(SMBwriteBmpx);
5446 CHECK_FSP(fsp,conn);
5447 if (!CHECK_WRITE(fsp)) {
5448 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5450 if (HAS_CACHED_ERROR(fsp)) {
5451 return(CACHED_ERROR(fsp));
5454 tcount = SVAL(inbuf,smb_vwv1);
5455 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
5456 write_through = BITSETW(inbuf+smb_vwv7,0);
5457 numtowrite = SVAL(inbuf,smb_vwv10);
5458 smb_doff = SVAL(inbuf,smb_vwv11);
5460 data = smb_base(inbuf) + smb_doff;
5462 /* If this fails we need to send an SMBwriteC response,
5463 not an SMBwritebmpx - set this up now so we don't forget */
5464 SCVAL(outbuf,smb_com,SMBwritec);
5466 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
5467 END_PROFILE(SMBwriteBmpx);
5468 return(ERROR_DOS(ERRDOS,ERRlock));
5471 nwritten = write_file(fsp,data,startpos,numtowrite);
5473 sync_file(conn, fsp, write_through);
5475 if(nwritten < (ssize_t)numtowrite) {
5476 END_PROFILE(SMBwriteBmpx);
5477 return(UNIXERROR(ERRHRD,ERRdiskfull));
5480 /* If the maximum to be written to this file
5481 is greater than what we just wrote then set
5482 up a secondary struct to be attached to this
5483 fd, we will use this to cache error messages etc. */
5485 if((ssize_t)tcount > nwritten) {
5486 write_bmpx_struct *wbms;
5487 if(fsp->wbmpx_ptr != NULL)
5488 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5490 wbms = SMB_MALLOC_P(write_bmpx_struct);
5492 DEBUG(0,("Out of memory in reply_readmpx\n"));
5493 END_PROFILE(SMBwriteBmpx);
5494 return(ERROR_DOS(ERRSRV,ERRnoresource));
5496 wbms->wr_mode = write_through;
5497 wbms->wr_discard = False; /* No errors yet */
5498 wbms->wr_total_written = nwritten;
5499 wbms->wr_errclass = 0;
5501 fsp->wbmpx_ptr = wbms;
5504 /* We are returning successfully, set the message type back to
5506 SCVAL(outbuf,smb_com,SMBwriteBmpx);
5508 outsize = set_message(outbuf,1,0,True);
5510 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5512 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5513 fsp->fnum, (int)numtowrite, (int)nwritten ) );
5515 if (write_through && tcount==nwritten) {
5516 /* We need to send both a primary and a secondary response */
5517 smb_setlen(outbuf,outsize - 4);
5519 if (!send_smb(smbd_server_fd(),outbuf))
5520 exit_server("reply_writebmpx: send_smb failed.");
5522 /* Now the secondary */
5523 outsize = set_message(outbuf,1,0,True);
5524 SCVAL(outbuf,smb_com,SMBwritec);
5525 SSVAL(outbuf,smb_vwv0,nwritten);
5528 END_PROFILE(SMBwriteBmpx);
5532 /****************************************************************************
5533 Reply to a SMBwritebs (write block multiplex secondary) request.
5534 ****************************************************************************/
5536 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5539 ssize_t nwritten = -1;
5546 write_bmpx_struct *wbms;
5547 BOOL send_response = False;
5548 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5549 START_PROFILE(SMBwriteBs);
5551 CHECK_FSP(fsp,conn);
5552 if (!CHECK_WRITE(fsp)) {
5553 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5556 tcount = SVAL(inbuf,smb_vwv1);
5557 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5558 numtowrite = SVAL(inbuf,smb_vwv6);
5559 smb_doff = SVAL(inbuf,smb_vwv7);
5561 data = smb_base(inbuf) + smb_doff;
5563 /* We need to send an SMBwriteC response, not an SMBwritebs */
5564 SCVAL(outbuf,smb_com,SMBwritec);
5566 /* This fd should have an auxiliary struct attached,
5567 check that it does */
5568 wbms = fsp->wbmpx_ptr;
5570 END_PROFILE(SMBwriteBs);
5574 /* If write through is set we can return errors, else we must cache them */
5575 write_through = wbms->wr_mode;
5577 /* Check for an earlier error */
5578 if(wbms->wr_discard) {
5579 END_PROFILE(SMBwriteBs);
5580 return -1; /* Just discard the packet */
5583 nwritten = write_file(fsp,data,startpos,numtowrite);
5585 sync_file(conn, fsp, write_through);
5587 if (nwritten < (ssize_t)numtowrite) {
5589 /* We are returning an error - we can delete the aux struct */
5592 fsp->wbmpx_ptr = NULL;
5593 END_PROFILE(SMBwriteBs);
5594 return(ERROR_DOS(ERRHRD,ERRdiskfull));
5596 wbms->wr_errclass = ERRHRD;
5597 wbms->wr_error = ERRdiskfull;
5598 wbms->wr_status = NT_STATUS_DISK_FULL;
5599 wbms->wr_discard = True;
5600 END_PROFILE(SMBwriteBs);
5604 /* Increment the total written, if this matches tcount
5605 we can discard the auxiliary struct (hurrah !) and return a writeC */
5606 wbms->wr_total_written += nwritten;
5607 if(wbms->wr_total_written >= tcount) {
5608 if (write_through) {
5609 outsize = set_message(outbuf,1,0,True);
5610 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
5611 send_response = True;
5615 fsp->wbmpx_ptr = NULL;
5619 END_PROFILE(SMBwriteBs);
5623 END_PROFILE(SMBwriteBs);
5627 /****************************************************************************
5628 Reply to a SMBgetattrE.
5629 ****************************************************************************/
5631 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5633 SMB_STRUCT_STAT sbuf;
5636 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5637 START_PROFILE(SMBgetattrE);
5639 outsize = set_message(outbuf,11,0,True);
5641 if(!fsp || (fsp->conn != conn)) {
5642 END_PROFILE(SMBgetattrE);
5643 return ERROR_DOS(ERRDOS,ERRbadfid);
5646 /* Do an fstat on this file */
5647 if(fsp_stat(fsp, &sbuf)) {
5648 END_PROFILE(SMBgetattrE);
5649 return(UNIXERROR(ERRDOS,ERRnoaccess));
5652 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5655 * Convert the times into dos times. Set create
5656 * date to be last modify date as UNIX doesn't save
5660 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5661 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5662 /* Should we check pending modtime here ? JRA */
5663 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5666 SIVAL(outbuf,smb_vwv6,0);
5667 SIVAL(outbuf,smb_vwv8,0);
5669 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
5670 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5671 SIVAL(outbuf,smb_vwv8,allocation_size);
5673 SSVAL(outbuf,smb_vwv10, mode);
5675 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5677 END_PROFILE(SMBgetattrE);